diff --git a/CNAME b/CNAME new file mode 100644 index 0000000..a561a8d --- /dev/null +++ b/CNAME @@ -0,0 +1 @@ +horaceyi.com diff --git a/assets/img/DKCSL.png b/assets/img/DKCSL.png new file mode 100644 index 0000000..fdf8b29 Binary files /dev/null and b/assets/img/DKCSL.png differ diff --git a/assets/img/IAP.png b/assets/img/IAP.png new file mode 100644 index 0000000..4b342fd Binary files /dev/null and b/assets/img/IAP.png differ diff --git a/assets/img/LinkedIn.png b/assets/img/LinkedIn.png new file mode 100644 index 0000000..77c8ee4 Binary files /dev/null and b/assets/img/LinkedIn.png differ diff --git a/assets/img/Outlook.png b/assets/img/Outlook.png new file mode 100644 index 0000000..8418e54 Binary files /dev/null and b/assets/img/Outlook.png differ diff --git a/assets/img/University_of_Alberta_logo.png b/assets/img/University_of_Alberta_logo.png new file mode 100644 index 0000000..0d9f13e Binary files /dev/null and b/assets/img/University_of_Alberta_logo.png differ diff --git a/assets/img/bio.JPG b/assets/img/bio.JPG new file mode 100644 index 0000000..1e38a2e Binary files /dev/null and b/assets/img/bio.JPG differ diff --git a/assets/img/blog.jpeg b/assets/img/blog.jpeg new file mode 100644 index 0000000..006233f Binary files /dev/null and b/assets/img/blog.jpeg differ diff --git a/assets/img/coming.png b/assets/img/coming.png new file mode 100644 index 0000000..95bb0d4 Binary files /dev/null and b/assets/img/coming.png differ diff --git a/assets/img/cqu.png b/assets/img/cqu.png new file mode 100644 index 0000000..bafa1fa Binary files /dev/null and b/assets/img/cqu.png differ diff --git a/assets/img/cqu_logo.png b/assets/img/cqu_logo.png new file mode 100644 index 0000000..f6e2fc9 Binary files /dev/null and b/assets/img/cqu_logo.png differ diff --git a/assets/img/cv.jpeg b/assets/img/cv.jpeg new file mode 100644 index 0000000..be791be Binary files /dev/null and b/assets/img/cv.jpeg differ diff --git a/assets/img/github.jpeg b/assets/img/github.jpeg new file mode 100644 index 0000000..02206e1 Binary files /dev/null and b/assets/img/github.jpeg differ diff --git a/assets/img/github.png b/assets/img/github.png new file mode 100644 index 0000000..44fedef Binary files /dev/null and b/assets/img/github.png differ diff --git a/assets/img/gmail.png b/assets/img/gmail.png new file mode 100644 index 0000000..7cc9df4 Binary files /dev/null and b/assets/img/gmail.png differ diff --git a/assets/img/imr.png b/assets/img/imr.png new file mode 100644 index 0000000..daf2576 Binary files /dev/null and b/assets/img/imr.png differ diff --git a/assets/img/jhu_logo.png b/assets/img/jhu_logo.png new file mode 100644 index 0000000..7ba2a18 Binary files /dev/null and b/assets/img/jhu_logo.png differ diff --git a/assets/img/mitacs.jpeg b/assets/img/mitacs.jpeg new file mode 100644 index 0000000..a48ef58 Binary files /dev/null and b/assets/img/mitacs.jpeg differ diff --git a/assets/img/sjtu.png b/assets/img/sjtu.png new file mode 100644 index 0000000..9dfa9b0 Binary files /dev/null and b/assets/img/sjtu.png differ diff --git a/assets/img/title.ico b/assets/img/title.ico new file mode 100644 index 0000000..c831411 Binary files /dev/null and b/assets/img/title.ico differ diff --git a/assets/img/uc.png b/assets/img/uc.png new file mode 100644 index 0000000..ab56c5b Binary files /dev/null and b/assets/img/uc.png differ diff --git a/assets/img/uc_logo.png b/assets/img/uc_logo.png new file mode 100644 index 0000000..b91c388 Binary files /dev/null and b/assets/img/uc_logo.png differ diff --git a/assets/pdf/CV.pdf b/assets/pdf/CV.pdf new file mode 100644 index 0000000..7e54d13 Binary files /dev/null and b/assets/pdf/CV.pdf differ diff --git a/assets/pdf/PDF b/assets/pdf/PDF new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/assets/pdf/PDF @@ -0,0 +1 @@ + diff --git a/index.html b/index.html new file mode 100644 index 0000000..c0affa4 --- /dev/null +++ b/index.html @@ -0,0 +1,290 @@ + + + + + + + Hongrui Yi + + + + + + + + + + + + + + +
+
+
+
+

Hongrui Yi   易弘睿

+
+

I am a master student in Electrical and Computer Engineering at Johns Hopkins University. I obtained my bachelor degree at both University of Cincinnati supervised by Prof. Janet Dong at UC Center for Robotics Research, and Chongqing University supervised by Prof. Wenbin Huang at State Key Laboratory of Mechanical Transmissions (SKLMT). I was a research intern at the University of Alberta before, where I am fortunate to be advised by Prof. Hossein Rouhani. +

+ Research Interest: Medical Computer Vision
+ horaceyi [at] outlook [dot] com
+ hyi13 [at] jhu [dot] edu
+

+

+ + + GitHub (HoraceYi) +
+ + + LinkedIn +
+ + + Curriculum Vitae + +

+
+ +

News

+ +
+ +

Education

+ + + + + + + + +
+

Johns Hopkins University, Baltimore, MD, United States (Aug 2023 - Apr 2025)

+

M.S. in Electrical & Computer Engineering

+
+ +
+ + + + + + + + + +
+

University of Cincinnati, Cincinnati, OH, United States (Sep 2018 - Apr 2023)

+ B.S. in Mechanical Engineering +
    +
  • Overall GPA: 3.80/4.00
  • +
  • Magna Cum Laude
  • +
+
+ +
+ + + + + + + + + +
+

Chongqing University, Chongqing, China (Sep 2018 - Apr 2023)

+ B.E. in Mechanical Engineering +
    +
  • Overall GPA: 89/100
  • +
  • China National Scholarship
  • +
+
+ +
+ +

Research Experience

+ + + + + + + + +
+

University of Alberta, Edmonton, Canada (Jul 2022 - Oct 2022)

+ Mitacs Globalink Research Internship + +




+ + +
+ + + + + + + + +
+

Shanghai Jiao Tong University, Shanghai, China (Sep 2021 - Dec 2021)

+ Research Assitant in Institute of Medical Robotics and + School of Biomedical Engineering + +
    +
  • Supervisor: Prof. + Lixu Gu +
  • +
  • Project: Percutaneous Lung Piercing Surgery Robot
  • +
+
+ +
+ +

Work Experience

+ + + + + + + + + +
+

UC-CQU Joint Co-op Institute, Cincinnati, OH & Chongqing, China (May. 2022- Dec. 2022)

+ Teaching Assistant +
    +
  • MECH 2021: Kinematics and Kinetics of Machine
  • +
  • MECH 3080: System Dynamics and Vibrations
  • +
  • MECH 2030: Solid Mechanics
  • +
+ +
+ + + +
+ +

Publications

+ + + + + +   +   +   +
+ + + Dual-kernel driven convolutional sparse learning for bearing transient feature enhancement +
+
+ Hongrui Yi, Quanchang Li, Hao Wang, Jian Tang, Rui Liu, Wenbin Huang, Xiaoxi Ding
+ Measurement, 2023. +

+

+ [paper] +

+
+ + + + + +   +   +   +
+ + + Integrated Treatment Planning in Percutaneous Microwave Ablation of Lung Tumors +
+
+ Haoyu Wang, Hongrui Yi, Jie Liu, Lixu Gu
+ International Conference of the IEEE Engineering in Medicine and Biology Society, (EMBC), 2022. +

+

+ [paper] +

+
+ +

Miscellaneous

+

+
+ Friends (click to expand, random order) + +
+

+
+

+

+
+ +
+
+

+
+

© Hongrui Yi 2023

+
+ +
+ + + + + + diff --git a/jemdoc.css b/jemdoc.css new file mode 100644 index 0000000..eace212 --- /dev/null +++ b/jemdoc.css @@ -0,0 +1,377 @@ +/* Default css file for jemdoc. */ + +table#tlayout { + border: none; + border-collapse: separate; + background: white; +} +/* +body { + background: white; + padding-bottom: 8px; + margin: 0; +} +*/ +html { + background-color: #ffffff; +} +br { + line-height: 5px; +} + +body { + font-family: Georgia, serif; + color: #000; + background-color: #ffffff; + text-align:left; /* for IE */ + margin-top: 30px; + margin-bottom: 30px; + margin-left: auto; + margin-right: auto; + padding-left: 50px; + padding-right: 50px; + padding-top: 10px; + padding-bottom: 30px; + max-width: 960px; +} + +#layout-menu { + background: #f6f6f6; + border: 1px solid #ffffff; + padding-top: 0.5em; + padding-left: 8px; + padding-right: 8px; + font-size: 1.0em; + width: auto; + white-space: nowrap; + text-align: left; + vertical-align: top; +} + +#layout-menu td { + background: #f4f4f4; + vertical-align: top; +} + +#layout-content { + padding-top: 0.0em; + padding-left: 1.0em; + padding-right: 1.0em; + border: none; + background: white; + text-align: left; + vertical-align: top; +} + +#layout-menu a { + line-height: 1.5em; + margin-left: 0.5em; +} + +tt { + background: #ffffdd; +} + +pre, tt { + font-size: 90%; + font-family: monaco, monospace; +} + +a, a > tt { + color: #224b8d; + text-decoration: none; +} + +a:hover { + border-bottom: 1px gray dotted; +} + +#layout-menu a.current:link, #layout-menu a.current:visited { + color: #022b6d; + border-bottom: 1px gray solid; +} +#layout-menu a:link, #layout-menu a:visited, #layout-menu a:hover { + color: #527bbd; + text-decoration: none; +} +#layout-menu a:hover { + text-decoration: none; +} + +div.menu-category { + border-bottom: 1px solid gray; + margin-top: 0.8em; + padding-top: 0.2em; + padding-bottom: 0.1em; + font-weight: bold; +} + +div.menu-item { + padding-left: 16px; + text-indent: -16px; +} + +div#toptitle { + padding-bottom: 0.2em; + margin-bottom: 1.5em; + /*border-bottom: 3px double gray;*/ +} + +/* Reduce space if we begin the page with a title. */ +div#toptitle + h2, div#toptitle + h3 { + margin-top: 0em; +} + +div#subtitle { + margin-top: 0.0em; + margin-bottom: 0.0em; + padding-top: 0em; + padding-bottom: 0.1em; +} + +em { + font-style: italic; +} + +strong { + font-weight: bold; +} + + +h1, h2, h3 { + color: #527bbd; + margin-top: 0.7em; + margin-bottom: 0.5em; + padding-bottom: 0.2em; + line-height: 1.0; + padding-top: 0.5em; + border-bottom: 1px solid #aaaaaa; +} + +h1 { + font-size: 165%; + padding-bottom: 0.3em; +} + +h2 { + padding-top: 0.8em; + font-size: 125%; +} + +h2 + h3 { + padding-top: 0.2em; +} + +h3 { + font-size: 110%; + border-bottom: none; +} + +p { + margin-top: 0.0em; + margin-bottom: 0.8em; + padding: 0; + line-height: 1.3; +} + +pre { + padding: 0; + margin: 0; +} + +div#footer { + font-size: small; + border-top: 1px solid #c0c0c0; + padding-top: 0.1em; + margin-top: 4.0em; + color: #c0c0c0; +} + +div#footer a { + color: #80a0b0; +} + +div#footer-text { + float: left; + padding-bottom: 8px; +} + +ul, ol, dl { + margin-top: 0.2em; + padding-top: 0; + margin-bottom: 0.8em; +} + +dt { + margin-top: 0.5em; + margin-bottom: 0; +} + +dl { + margin-left: 20px; +} + +dd { + color: #222222; +} + +dd > *:first-child { + margin-top: 0; +} + +ul { + list-style-position: outside; + list-style-type: square; +} + +p + ul, p + ol { + margin-top: -0.5em; +} + +li { + margin-top:0.9em; +} + +ol { + list-style-position: outside; + list-style-type: decimal; +} + +li p, dd p { + margin-bottom: 0.3em; +} + + +ol ol { + list-style-type: lower-alpha; +} + +ol ol ol { + list-style-type: lower-roman; +} + +p + div.codeblock { + margin-top: -0.6em; +} + +div.codeblock, div.infoblock { + margin-right: 0%; + margin-top: 1.2em; + margin-bottom: 1.3em; +} + +div.blocktitle { + font-weight: bold; + color: #cd7b62; + margin-top: 1.2em; + margin-bottom: 0.1em; +} + +div.blockcontent { + border: 1px solid silver; + padding: 0.3em 0.5em; +} + +div.infoblock > div.blockcontent { + background: #ffffee; +} + +div.blockcontent p + ul, div.blockcontent p + ol { + margin-top: 0.4em; +} + +div.infoblock p { + margin-bottom: 0em; +} + +div.infoblock li p, div.infoblock dd p { + margin-bottom: 0.5em; +} + +div.infoblock p + p { + margin-top: 0.8em; +} + +div.codeblock > div.blockcontent { + background: #f6f6f6; +} + +span.pycommand { + color: #000070; +} + +span.statement { + color: #008800; +} +span.builtin { + color: #000088; +} +span.special { + color: #990000; +} +span.operator { + color: #880000; +} +span.error { + color: #aa0000; +} +span.comment, span.comment > *, span.string, span.string > * { + color: #606060; +} + +@media print { + #layout-menu { display: none; } +} + +#fwtitle { + margin: 2px; +} + +#fwtitle #toptitle { + padding-left: 0.5em; + margin-bottom: 0.5em; +} + +#layout-content h1:first-child, #layout-content h2:first-child, #layout-content h3:first-child { + margin-top: -0.7em; +} + +div#toptitle h1, #layout-content div#toptitle h1 { + margin-bottom: 0.0em; + padding-bottom: 0.1em; + padding-top: 0; + margin-top: 0.5em; + border-bottom: none; +} + +img.eq { + padding: 0; + padding-left: 0.1em; + padding-right: 0.1em; + margin: 0; +} + +img.eqwl { + padding-left: 2em; + padding-top: 0.6em; + padding-bottom: 0.2em; + margin: 0; +} + +table + table { + margin-top: 1em; +} + +tr.heading { + font-weight: bold; + border-bottom: 2px solid black; +} + +img { + border: none; +} + +table.imgtable, table.imgtable td { + border: none; + text-align: left; +} \ No newline at end of file diff --git a/jemdoc.py b/jemdoc.py new file mode 100644 index 0000000..d9293ee --- /dev/null +++ b/jemdoc.py @@ -0,0 +1,1608 @@ +#!/usr/bin/env python + +"""jemdoc version 0.7.3, 2012-11-27.""" + +# Copyright (C) 2007-2012 Jacob Mattingley (jacobm@stanford.edu). +# +# This file is part of jemdoc. +# +# jemdoc is free software; you can redistribute it and/or modify it under the +# terms of the GNU General Public License as published by the Free Software +# Foundation; either version 3 of the License, or (at your option) any later +# version. +# +# jemdoc is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. See the GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see . +# +# The LaTeX equation portions of this file were initially based on +# latexmath2png, by Kamil Kisiel (kamil@kamikisiel.net). +# + +import sys +import os +import re +import time +import StringIO +from subprocess import * +import tempfile + + +def info(): + print __doc__ + print 'Platform: ' + sys.platform + '.' + print 'Python: %s, located at %s.' % (sys.version[:5], sys.executable) + print 'Equation support:', + (supported, message) = testeqsupport() + if supported: + print 'yes.' + else: + print 'no.' + print message + + +def testeqsupport(): + supported = True + msg = '' + p = Popen('latex --version', shell=True, stdout=PIPE, stderr=PIPE) + rc = p.wait() + if rc != 0: + msg += ' latex: not found.\n' + supported = False + else: + msg += ' latex: ' + p.stdout.readlines()[0].rstrip() + '.\n' + p = Popen('dvipng --version', shell=True, stdout=PIPE, stderr=PIPE) + rc = p.wait() + if rc != 0: + msg += ' dvipng: not found.\n' + supported = False + else: + msg += ' dvipng: ' + p.stdout.readlines()[0].rstrip() + '.\n' + + return (supported, msg[:-1]) + + +class controlstruct(object): + def __init__(self, infile, outfile=None, conf=None, inname=None, eqs=True, + eqdir='eqs', eqdpi=130): + self.inname = inname + self.inf = infile + self.outf = outfile + self.conf = conf + self.linenum = 0 + self.otherfiles = [] + self.eqs = eqs + self.eqdir = eqdir + self.eqdpi = eqdpi + # Default to supporting equations until we know otherwise. + self.eqsupport = True + self.eqcache = True + self.eqpackages = [] + self.texlines = [] + self.analytics = None + self.eqbd = {} # equation base depth. + self.baseline = None + + def pushfile(self, newfile): + self.otherfiles.insert(0, self.inf) + self.inf = open(newfile, 'rb') + + def nextfile(self): + self.inf.close() + self.inf = self.otherfiles.pop(0) + + +def showhelp(): + a = """Usage: jemdoc [OPTIONS] [SOURCEFILE] + Produces html markup from a jemdoc SOURCEFILE. + + Most of the time you can use jemdoc without any additional flags. + For example, typing + + jemdoc index + + will produce an index.html from index.jemdoc, using a default + configuration. + + Some configuration options can be overridden by specifying a + configuration file. You can use + + jemdoc --show-config + + to print a sample configuration file (which includes all of the + default options). Any or all of the configuration [blocks] can be + overwritten by including them in a configuration file, and running, + for example, + + jemdoc -c mywebsite.conf index.jemdoc + + You can view version and installation details with + + jemdoc --version + + See http://jemdoc.jaboc.net/ for many more details.""" + b = '' + for l in a.splitlines(True): + if l.startswith(' '*4): + b += l[4:] + else: + b += l + + print b + + +def standardconf(): + a = """[firstbit] + + + + + + + [defaultcss] + + + [windowtitle] + # used in header for window title. + | + + [fwtitlestart] +
+ + [fwtitleend] +
+ + [doctitle] + # used at top of document. +
+

|

+ + [subtitle] +
|
+ + [doctitleend] +
+ + [bodystart] + + + + [analytics] + + + + [menustart] + + + + + +
+ + [menuend] + + + [menucategory] + + + [menuitem] + + + [specificcss] + + + [specificjs] + + + [currentmenuitem] + + + [nomenu] +
+ + [menulastbit] +
+ + [nomenulastbit] + + + [bodyend] + + + + [infoblock] +
+ + [codeblock] +
+ + [blocktitle] +
|
+ + [infoblockcontent] +
+ + [codeblockcontent] +
+  
+  [codeblockend]
+  
+ + [codeblockcontenttt] +
+ + [codeblockendtt] +
+ + [infoblockend] +
+ + [footerstart] + + + [lastupdated] + Page generated |, by jemdoc. + + [sourcelink] + (source) + + """ + b = '' + for l in a.splitlines(True): + if l.startswith(' '): + b += l[2:] + else: + b += l + + return b + + +class JandalError(Exception): + pass + + +class NoEqSupport(Exception): + pass + + +def raisejandal(msg, line=0): + if line == 0: + s = "%s" % msg + else: + s = "line %d: %s" % (line, msg) + raise JandalError(s) + + +def readnoncomment(f): + l = f.readline() + if l == '': + return l + elif l[0] == '#': # jem: be a little more generous with the comments we accept? + return readnoncomment(f) + else: + return l.rstrip() + '\n' # leave just one \n and no spaces etc. + + +def parseconf(cns): + syntax = {} + warn = False # jem. make configurable? + # manually add the defaults as a file handle. + fs = [StringIO.StringIO(standardconf())] + for sname in cns: + fs.append(open(sname, 'rb')) + + for f in fs: + while pc(controlstruct(f)) != '': + l = readnoncomment(f) + r = re.match(r'\[(.*)\]\n', l) + + if r: + tag = r.group(1) + + s = '' + l = readnoncomment(f) + while l not in ('\n', ''): + s += l + l = readnoncomment(f) + + syntax[tag] = s + + f.close() + + return syntax + + +def insertmenuitems(f, mname, current, prefix): + m = open(mname, 'rb') + while pc(controlstruct(m)) != '': + l = readnoncomment(m) + l = l.strip() + if l == '': + continue + + r = re.match(r'\s*(.*?)\s*\[(.*)\]', l) + + if r: # then we have a menu item. + link = r.group(2) + # Don't use prefix if we have an absolute link. + if '://' not in r.group(2): + link = prefix + allreplace(link) + + # replace spaces with nbsps. + # do do this, even though css would make it work - ie ignores. + # only replace spaces that aren't in {{ blocks. + in_quote = False + menuitem = "" + for group in re.split(r'({{|}})', r.group(1)): + if in_quote: + if group == '}}': + in_quote = False + next + else: + menuitem += group + else: + if group == '{{': + in_quote = True + next + else: + menuitem += br(re.sub(r'(?&$%\.~[\]-]""", r'\\\g<0>', s) + + +def replacequoted(b): + """Quotes {{raw html}} sections.""" + + r = re.compile(r'\{\{(.*?)\}\}', re.M + re.S) + m = r.search(b) + while m: + qb = quote(m.group(1)) + + b = b[:m.start()] + qb + b[m.end():] + + m = r.search(b, m.start()) + + return b + + +def replacepercents(b): + # replace %sections% as +{{sections}}+. Do not replace if within a link. + + r = re.compile(r'(?%s\n
}}' % ( + fullfn, eqtext) + b[m.end():] + else: + b = b[:m.start()] + \ + '{{%s}}' % ( + fullfn, eqtext, offset) + b[m.end():] + + # jem: also clean out line breaks in the alttext? + m = r.search(b, m.start()) + + return replacequoted(b) + + +def replaceimages(b): + # works with [img{width}{height}{alttext} location caption]. + r = re.compile(r'(?' % " ".join(bits) + b[m.end():] + + m = r.search(b, m.start()) + + return b + + +def replacelinks(b): + # works with [link.html new link style]. + r = re.compile(r'(?%s<\/a>' % (link, + linkname) + b[m.end():] + + m = r.search(b, m.start()) + + return b + + +def br(b, f, tableblock=False): + """Does simple text replacements on a block of text. ('block replacements')""" + + # Deal with environment variables (say, for Michael Grant). + r = re.compile(r"!\$(\w{2,})\$!", re.M + re.S) + + for m in r.findall(b): + repl = os.environ.get(m) + if repl == None: + b = re.sub("!\$%s\$!" % m, 'FAILED_MATCH_' + m, b) + else: + b = re.sub("!\$%s\$!" % m, repl, b) + + # Deal with literal backspaces. + if f.eqs and f.eqsupport: + b = replaceequations(b, f) + + b = re.sub(r'\\\\', 'jemLITerl33talBS', b) + + # Deal with {{html embedding}}. + b = replacequoted(b) + + b = allreplace(b) + + b = b.lstrip('-. \t') # remove leading spaces, tabs, dashes, dots. + b = replaceimages(b) # jem not sure if this is still used. + + # Slightly nasty hackery in this next bit. + b = replacepercents(b) + b = replacelinks(b) + b = re.sub(r'BSNOTLINKLEFT12039XX', r'[', b) + b = re.sub(r'BSNOTLINKRIGHT12039XX', r']', b) + b = replacequoted(b) + + # Deal with /italics/ first because the '/' in other tags would otherwise + # interfere. + r = re.compile(r'(?\1', b) + + # Deal with *bold*. + r = re.compile(r'(?\1', b) + + # Deal with +monospace+. + r = re.compile(r'(?\1', b) + + # Deal with "double quotes". + r = re.compile(r'(?', b) + + # Deal with paragraph break. Caution! Should only use when we're already in + # a paragraph. + r = re.compile(r"(?

', b) + + if tableblock: + # Deal with ||, meaning + r = re.compile(r"(?\n' + % f.tablerow, l) + + l2 = '' + col = 2 + r2s = r2.split(l) + for x in r2s[:-1]: + l2 += x + ('' % col) + col += 1 + l2 += r2s[-1] + + b += l2 + + # Second to last, remove any remaining quoting backslashes. + b = re.sub(r'\\(?!\\)', '', b) + + # Deal with literal backspaces. + b = re.sub('jemLITerl33talBS', r'\\', b) + + # Also fix up DOUBLEOPEN and DOUBLECLOSEBRACES. + b = re.sub('DOUBLEOPENBRACE', '{{', b) + b = re.sub('DOUBLECLOSEBRACE', '}}', b) + + return b + + +def allreplace(b): + """Replacements that should be done on everything.""" + r = re.compile(r"(?", re.M + re.S) + b = re.sub(r, r'>', b) + + r = re.compile(r"(?\1', l) + + if l.startswith('>>>'): + hb(f, '|\n', l) + else: + out(f, l + '\n') + + +def putbsbs(l): + for i in range(len(l)): + l[i] = '\\b' + l[i] + '\\b' + + return l + + +def gethl(lang): + # disable comments by default, by choosing unlikely regex. + d = {'strings': False} + if lang in ('py', 'python'): + d['statement'] = ['break', 'continue', 'del', 'except', 'exec', + 'finally', 'pass', 'print', 'raise', 'return', 'try', + 'with', 'global', 'assert', 'lambda', 'yield', 'def', + 'class', 'for', 'while', 'if', 'elif', 'else', + 'import', 'from', 'as', 'assert'] + d['builtin'] = ['True', 'False', 'set', 'open', 'frozenset', + 'enumerate', 'object', 'hasattr', 'getattr', 'filter', + 'eval', 'zip', 'vars', 'unicode', 'type', 'str', + 'repr', 'round', 'range', 'and', 'in', 'is', 'not', + 'or'] + d['special'] = ['cols', 'optvar', 'param', 'problem', 'norm2', 'norm1', + 'value', 'minimize', 'maximize', 'rows', 'rand', + 'randn', 'printval', 'matrix'] + d['error'] = ['\w*Error', ] + d['commentuntilend'] = '#' + d['strings'] = True + elif lang in ['c', 'c++', 'cpp']: + d['statement'] = ['if', 'else', 'printf', 'return', 'for'] + d['builtin'] = ['static', 'typedef', 'int', 'float', 'double', 'void', + 'clock_t', 'struct', 'long', 'extern', 'char'] + d['operator'] = ['#include.*', '#define', '@pyval{', '}@', '@pyif{', + '@py{'] + d['error'] = ['\w*Error', ] + d['commentuntilend'] = ['//', '/*', ' * ', '*/'] + elif lang in ('rb', 'ruby'): + d['statement'] = putbsbs(['while', 'until', 'unless', 'if', 'elsif', + 'when', 'then', 'else', 'end', 'begin', + 'rescue', 'class', 'def']) + d['operator'] = putbsbs(['and', 'not', 'or']) + d['builtin'] = putbsbs(['true', 'false', 'require', 'warn']) + d['special'] = putbsbs(['IO']) + d['error'] = putbsbs(['\w*Error', ]) + d['commentuntilend'] = '#' + d['strings'] = True + d['strings'] = True + if lang in ['c++', 'cpp']: + d['builtin'] += ['bool', 'virtual'] + d['statement'] += ['new', 'delete'] + d['operator'] += ['<<', '>>'] + d['special'] = ['public', 'private', 'protected', 'template', + 'ASSERT'] + elif lang == 'sh': + d['statement'] = ['cd', 'ls', 'sudo', 'cat', 'alias', 'for', 'do', + 'done', 'in', ] + d['operator'] = ['>', r'\\', r'\|', ';', '2>', 'monolith>', + 'kiwi>', 'ant>', 'kakapo>', 'client>'] + d['builtin'] = putbsbs(['gem', 'gcc', 'python', 'curl', 'wget', 'ssh', + 'latex', 'find', 'sed', 'gs', 'grep', 'tee', + 'gzip', 'killall', 'echo', 'touch', + 'ifconfig', 'git', '(?>', '~', '\.\.\.'] + d['builtin'] = putbsbs(['csolve']) + d['commentuntilend'] = '%' + d['strings'] = True + elif lang == 'commented': + d['commentuntilend'] = '#' + + # Add bsbs (whatever those are). + for x in ['statement', 'builtin', 'special', 'error']: + if x in d: + d[x] = putbsbs(d[x]) + + return d + + +def language(f, l, hl): + l = l.rstrip() + l = allreplace(l) + # handle strings. + if hl['strings']: + r = re.compile(r'(".*?")') + l = r.sub(r'\1', l) + r = re.compile(r"('.*?')") + l = r.sub(r'\1', l) + + if 'statement' in hl: + r = re.compile('(' + '|'.join(hl['statement']) + ')') + l = r.sub(r'\1', l) + + if 'operator' in hl: + r = re.compile('(' + '|'.join(hl['operator']) + ')') + l = r.sub(r'\1', l) + + if 'builtin' in hl: + r = re.compile('(' + '|'.join(hl['builtin']) + ')') + l = r.sub(r'\1', l) + + if 'special' in hl: + r = re.compile('(' + '|'.join(hl['special']) + ')') + l = r.sub(r'\1', l) + + if 'error' in hl: + r = re.compile('(' + '|'.join(hl['error']) + ')') + l = r.sub(r'\1', l) + + l = re.sub('CLCLclass', 'class', l) + + if 'commentuntilend' in hl: + cue = hl['commentuntilend'] + if isinstance(cue, (list, tuple)): + for x in cue: + if l.strip().startswith(x): + hb(f, '|\n', allreplace(l)) + return + if '//' in cue: # Handle this separately. + r = re.compile(r'\/\/.*') + l = r.sub(r'\g<0>', l) + elif cue == '#': # Handle this separately. + r = re.compile(r'#.*') + l = r.sub(r'\g<0>', l) + elif cue == '%': # Handle this separately. + r = re.compile(r'%.*') + l = r.sub(r'\g<0>', l) + elif l.strip().startswith(cue): + hb(f, '|\n', allreplace(l)) + return + + out(f, l + '\n') + + +def geneq(f, eq, dpi, wl, outname): + # First check if there is an existing file. + eqname = os.path.join(f.eqdir, outname + '.png') + + eqdepths = {} + if f.eqcache: + try: + dc = open(os.path.join(f.eqdir, '.eqdepthcache'), 'rb') + for l in dc: + a = l.split() + eqdepths[a[0]] = int(a[1]) + dc.close() + + if os.path.exists(eqname) and eqname in eqdepths: + return (eqdepths[eqname], eqname) + except IOError: + print 'eqdepthcache read failed.' + + # Open tex file. + tempdir = tempfile.gettempdir() + fd, texfile = tempfile.mkstemp('.tex', '', tempdir, True) + basefile = texfile[:-4] + g = os.fdopen(fd, 'wb') + + preamble = '\documentclass{article}\n' + for p in f.eqpackages: + preamble += '\usepackage{%s}\n' % p + for p in f.texlines: + # Replace \{ and \} in p with { and }. + # XXX hack. + preamble += re.sub(r'\\(?=[{}])', '', p + '\n') + preamble += '\pagestyle{empty}\n\\begin{document}\n' + g.write(preamble) + + # Write the equation itself. + if wl: + g.write('\\[%s\\]' % eq) + else: + g.write('$%s$' % eq) + + # Finish off the tex file. + g.write('\n\\newpage\n\end{document}') + g.close() + + exts = ['.tex', '.aux', '.dvi', '.log'] + try: + # Generate the DVI file + latexcmd = 'latex -file-line-error-style -interaction=nonstopmode ' + \ + '-output-directory %s %s' % (tempdir, texfile) + p = Popen(latexcmd, shell=True, stdout=PIPE) + rc = p.wait() + if rc != 0: + for l in p.stdout.readlines(): + print ' ' + l.rstrip() + exts.remove('.tex') + raise Exception('latex error') + + dvifile = basefile + '.dvi' + dvicmd = 'dvipng --freetype0 -Q 9 -z 3 --depth -q -T tight -D %i -bg Transparent -o %s %s' % ( + dpi, eqname, dvifile) + # discard warnings, as well. + p = Popen(dvicmd, shell=True, stdout=PIPE, stderr=PIPE) + rc = p.wait() + if rc != 0: + print p.stderr.readlines() + raise Exception('dvipng error') + depth = int(p.stdout.readlines()[-1].split('=')[-1]) + finally: + # Clean up. + for ext in exts: + g = basefile + ext + if os.path.exists(g): + os.remove(g) + + # Update the cache if we're using it. + if f.eqcache and eqname not in eqdepths: + try: + dc = open(os.path.join(f.eqdir, '.eqdepthcache'), 'ab') + dc.write(eqname + ' ' + str(depth) + '\n') + dc.close() + except IOError: + print 'eqdepthcache update failed.' + return (depth, eqname) + + +def dashlist(f, ordered=False): + level = 0 + + if ordered: + char = '.' + ul = 'ol' + else: + char = '-' + ul = 'ul' + + while pc(f) == char: + (s, newlevel) = np(f, True, False) + + # first adjust list number as appropriate. + if newlevel > level: + for i in range(newlevel - level): + if newlevel > 1: + out(f.outf, '\n') + out(f.outf, '<%s>\n

  • ' % ul) + elif newlevel < level: + out(f.outf, '\n
  • ') + for i in range(level - newlevel): + #out(f.outf, '\n\n
  • ' % ul) + # demote means place '
  • ' in the file. + out(f.outf, '\n' % ul) + #out(f.outf, '\n
  • ') + out(f.outf, '\n
  • ') + else: + # same level, make a new list item. + out(f.outf, '\n
  • \n
  • ') + + out(f.outf, '

    ' + br(s, f) + '

    ') + level = newlevel + + for i in range(level): + out(f.outf, '\n
  • \n\n' % ul) + + +def colonlist(f): + out(f.outf, '
    \n') + while pc(f) == ':': + s = np(f, eatblanks=False) + r = re.compile(r'\s*{(.*?)(?|\n', br(defpart, f)) + hb(f.outf, '

    |

    \n', br(rest, f)) + + out(f.outf, '
    \n') + + +def codeblock(f, g): + if g[1] == 'raw': + raw = True + ext_prog = None + elif g[0] == 'filter_through': + # Filter through external program. + raw = False + ext_prog = g[1] + buff = "" + else: + ext_prog = None + raw = False + out(f.outf, f.conf['codeblock']) + if g[0]: + hb(f.outf, f.conf['blocktitle'], g[0]) + if g[1] == 'jemdoc': + out(f.outf, f.conf['codeblockcontenttt']) + else: + out(f.outf, f.conf['codeblockcontent']) + + # Now we are handling code. + # Handle \~ and ~ differently. + stringmode = False + while 1: # wait for EOF. + l = nl(f, codemode=True) + if not l: + break + elif l.startswith('~'): + break + elif l.startswith('\\~'): + l = l[1:] + elif l.startswith('\\{'): + l = l[1:] + elif ext_prog: + buff += l + continue + elif stringmode: + if l.rstrip().endswith('"""'): + out(f.outf, l + '') + stringmode = False + else: + out(f.outf, l) + continue + + # jem revise pyint out of the picture. + if g[1] == 'pyint': + pyint(f.outf, l) + else: + if raw: + out(f.outf, l) + elif g[1] == 'jemdoc': + # doing this more nicely needs python 2.5. + for x in ('#', '~', '>>>', '\~', '{'): + if str(l).lstrip().startswith(x): + out(f.outf, '
    ')
    +                        out(f.outf, l + '
    ') + break + else: + for x in (':', '.', '-'): + if str(l).lstrip().startswith(x): + out(f.outf, '
    ' + prependnbsps(l)) + break + else: + if str(l).lstrip().startswith('='): + out(f.outf, prependnbsps(l) + '
    ') + else: + out(f.outf, l) + else: + if l.startswith('\\#include{') or l.startswith('\\#includeraw{'): + out(f.outf, l[1:]) + elif l.startswith('#') and doincludes(f, l[1:]): + continue + elif g[1] in ('python', 'py') and l.strip().startswith('"""'): + out(f.outf, '' + l) + stringmode = True + else: + language(f.outf, l, gethl(g[1])) + + if raw: + return + elif ext_prog: + print 'filtering through %s...' % ext_prog + + output, _ = Popen(ext_prog, shell=True, stdin=PIPE, + stdout=PIPE).communicate(buff) + out(f.outf, output) + else: + if g[1] == 'jemdoc': + out(f.outf, f.conf['codeblockendtt']) + else: + out(f.outf, f.conf['codeblockend']) + + +def prependnbsps(l): + g = re.search('(^ *)(.*)', l).groups() + return g[0].replace(' ', ' ') + g[1] + + +def inserttitle(f, t): + if t is not None: + hb(f.outf, f.conf['doctitle'], t) + + # Look for a subtitle. + if pc(f) != '\n': + hb(f.outf, f.conf['subtitle'], br(np(f), f)) + + hb(f.outf, f.conf['doctitleend'], t) + + +def procfile(f): + f.linenum = 0 + + menu = None + # convert these to a dictionary. + showfooter = True + showsourcelink = False + showlastupdated = True + showlastupdatedtime = True + nodefaultcss = False + fwtitle = False + css = [] + js = [] + title = None + while pc(f, False) == '#': + l = f.inf.readline() + f.linenum += 1 + if doincludes(f, l[1:]): + continue + if l.startswith('# jemdoc:'): + l = l[len('# jemdoc:'):] + a = l.split(',') + # jem only handle one argument for now. + for b in a: + b = b.strip() + if b.startswith('menu'): + sidemenu = True + r = re.compile(r'(? 3 or len(g) < 2: + raise SyntaxError( + 'sidemenu error on line %d' % f.linenum) + + if len(g) == 2: + menu = (f, g[0], g[1], '') + else: + menu = (f, g[0], g[1], g[2]) + + elif b.startswith('nofooter'): + showfooter = False + + elif b.startswith('nodate'): + showlastupdated = False + + elif b.startswith('notime'): + showlastupdatedtime = False + + elif b.startswith('fwtitle'): + fwtitle = True + + elif b.startswith('showsource'): + showsourcelink = True + + elif b.startswith('nodefaultcss'): + nodefaultcss = True + + elif b.startswith('addcss'): + r = re.compile(r'(?)|( ) *', ' ', t) + else: + t = None + + # if title: + hb(f.outf, f.conf['windowtitle'], title) + + out(f.outf, f.conf['bodystart']) + + if f.analytics: + hb(f.outf, f.conf['analytics'], f.analytics) + + if fwtitle: + out(f.outf, f.conf['fwtitlestart']) + inserttitle(f, t) + out(f.outf, f.conf['fwtitleend']) + + if menu: + out(f.outf, f.conf['menustart']) + insertmenuitems(*menu) + out(f.outf, f.conf['menuend']) + else: + out(f.outf, f.conf['nomenu']) + + if not fwtitle: + inserttitle(f, t) + + infoblock = False + imgblock = False + tableblock = False + while 1: # wait for EOF. + p = pc(f) + + if p == '': + break + + elif p == '\\(': + if not (f.eqs and f.eqsupport): + break + + s = nl(f) + # Quickly pull out the equation here: + # Check we don't already have the terminating character in a whole-line + # equation without linebreaks, eg \( Ax=b \): + if not s.strip().endswith('\)'): + while True: + l = nl(f, codemode=True) + if not l: + break + s += l + if l.strip() == '\)': + break + out(f.outf, br(s.strip(), f)) + + # look for lists. + elif p == '-': + dashlist(f, False) + + elif p == '.': + dashlist(f, True) + + elif p == ':': + colonlist(f) + + # look for titles. + elif p == '=': + (s, c) = nl(f, True) + # trim trailing \n. + s = s[:-1] + hb(f.outf, '|\n' % (c, c), br(s, f)) + + # look for comments. + elif p == '#': + l = nl(f) + + elif p == '\n': + nl(f) + + # look for blocks. + elif p == '~': + nl(f) + if infoblock: + out(f.outf, f.conf['infoblockend']) + infoblock = False + nl(f) + continue + elif imgblock: + out(f.outf, '\n') + imgblock = False + nl(f) + continue + elif tableblock: + out(f.outf, '\n') + tableblock = False + nl(f) + continue + else: + if pc(f) == '{': + l = allreplace(nl(f)) + r = re.compile(r'(?= 1: + g[0] = br(g[0], f) + + if len(g) in (0, 1): # info block. + out(f.outf, f.conf['infoblock']) + infoblock = True + + if len(g) == 1: # info block. + hb(f.outf, f.conf['blocktitle'], g[0]) + + out(f.outf, f.conf['infoblockcontent']) + + elif len(g) >= 2 and g[1] == 'table': + # handles + # {title}{table}{name} + # one | two || + # three | four || + name = '' + if len(g) >= 3 and g[2]: + name += ' id="%s"' % g[2] + out(f.outf, '\n' % name) + f.tablerow = 1 + f.tablecol = 1 + + tableblock = True + + elif len(g) == 2: + codeblock(f, g) + + elif len(g) >= 4 and g[1] == 'img_left': + # handles + # {}{img_left}{source}{alttext}{width}{height}{linktarget}. + g += ['']*(7 - len(g)) + + if g[4].isdigit(): + g[4] += 'px' + + if g[5].isdigit(): + g[5] += 'px' + + out(f.outf, '\n
    \n') + if g[6]: + out(f.outf, '' % g[6]) + out(f.outf, '%s') + if g[6]: + out(f.outf, '') + out(f.outf, ' ') + imgblock = True + + else: + raise JandalError("couldn't handle block", f.linenum) + + else: + s = br(np(f), f, tableblock) + if s: + if tableblock: + hb(f.outf, '|\n', s) + else: + hb(f.outf, '

    |

    \n', s) + + if showfooter and (showlastupdated or showsourcelink): + out(f.outf, f.conf['footerstart']) + if showlastupdated: + if showlastupdatedtime: + ts = '%Y-%m-%d %H:%M:%S %Z' + else: + ts = '%Y-%m-%d' + s = time.strftime(ts, time.localtime(time.time())) + hb(f.outf, f.conf['lastupdated'], s) + if showsourcelink: + hb(f.outf, f.conf['sourcelink'], f.inname) + out(f.outf, f.conf['footerend']) + + if menu: + out(f.outf, f.conf['menulastbit']) + else: + out(f.outf, f.conf['nomenulastbit']) + + out(f.outf, f.conf['bodyend']) + + if f.outf is not sys.stdout: + # jem: close file here. + # jem: XXX this is where you would intervene to do a fast open/close. + f.outf.close() + + +def main(): + if len(sys.argv) == 1 or sys.argv[1] in ('--help', '-h'): + showhelp() + raise SystemExit + if sys.argv[1] == '--show-config': + print standardconf() + raise SystemExit + if sys.argv[1] == '--version': + info() + raise SystemExit + + outoverride = False + confoverride = False + outname = None + confnames = [] + for i in range(1, len(sys.argv), 2): + if sys.argv[i] == '-o': + if outoverride: + raise RuntimeError("only one output file / directory, please") + outname = sys.argv[i+1] + outoverride = True + elif sys.argv[i] == '-c': + if confoverride: + raise RuntimeError("only one config file, please") + confnames.append(sys.argv[i+1]) + confoverride = True + elif sys.argv[i].startswith('-'): + raise RuntimeError( + 'unrecognised argument %s, try --help' % sys.argv[i]) + else: + break + + conf = parseconf(confnames) + + innames = [] + for j in range(i, len(sys.argv)): + # First, if not a file and no dot, try opening .jemdoc. Otherwise, fall back + # to just doing exactly as asked. + inname = sys.argv[j] + if not os.path.isfile(inname) and '.' not in inname: + inname += '.jemdoc' + + innames.append(inname) + + if outname is not None and not os.path.isdir(outname) and len(innames) > 1: + raise RuntimeError('cannot handle one outfile with multiple infiles') + + for inname in innames: + if outname is None: + thisout = re.sub(r'.jemdoc$', '', inname) + '.html' + elif os.path.isdir(outname): + # if directory, prepend directory to automatically generated name. + thisout = outname + re.sub(r'.jemdoc$', '', inname) + '.html' + else: + thisout = outname + + infile = open(inname, 'rUb') + outfile = open(thisout, 'w') + + f = controlstruct(infile, outfile, conf, inname) + procfile(f) + + +# +if __name__ == '__main__': + main() diff --git a/red.css b/red.css new file mode 100644 index 0000000..bff5921 --- /dev/null +++ b/red.css @@ -0,0 +1,376 @@ + +html { + text-size-adjust: none; + -webkit-text-size-adjust: none; + -moz-text-size-adjust: none; + -ms-text-size-adjust: none; + } + + + body { + background: white; + font-family: Optima, Georgia, sans-serif; + padding: 10px; + padding-top: 10px; + padding-bottom: 10px; + font-size: .96em; + margin-left: auto; + margin-right: auto; + max-width: 1000px; + } + + + #layout-menu { + background: #f4f4f4; + border: none; + border-right: 1px solid #dddddd; + border-bottom: none; + margin: 0; + padding-top: 15px; + padding-left: 8px; + padding-right: 15px; + font-size: 1.0em; + white-space: nowrap; + } + + #layout-menu a { + line-height: 1.5em; + margin-left: 0.5em; + } + + tt { + color: green; + } + + tt.tthl { + color: black; + } + + pre, tt { + font-size: 90%; + font-family: monaco, monospace; + } + + a, a > tt { + color: #224b8d; + text-decoration: none; + } + + a:hover { + border-bottom: 1px gray dotted; + } + + #layout-menu a.current:link, #layout-menu a.current:visited { + color: #022b6d; + border-bottom: 1px gray solid; + } + + #layout-menu a:link, #layout-menu a:visited, #layout-menu a:hover { + color: #527bbd; + text-decoration: none; + } + + div.menu-category { + border-bottom: 0px solid gray; + margin-top: 0.8em; + padding-top: 0.2em; + padding-bottom: 0.1em; + font-weight: bold; + } + + div.menu-item { + padding-left: 15px; + padding-right: 8px; + text-indent: -16px; + text-align: right; + } + + div#toptitle { + color: #527bbd; + padding-bottom: .5em; + margin-bottom: 1.3em; + border-bottom: 1px solid gray; + } + + /* Reduce space if we begin the page with a title. */ + div#toptitle + h2, div#toptitle + h3 { + margin-top: -0.7em; + } + + div#subtitle { + margin-top: 0.0em; + margin-bottom: 0.0em; + padding-top: 0em; + padding-bottom: 0.1em; + } + + #layout-content { + border: none; + padding-top: 10px; + padding-left: 16px; + padding-right: 16px; + padding-bottom: 0; + margin: 0; + } + + em { + font-style: italic; + } + + strong { + font-weight: bold; + } + + + h1, h2, h3 { + color: #bb0000; + margin-top: 0.7em; + margin-bottom: 0.3em; + padding-bottom: 0.2em; + line-height: 1.0; + padding-top: 0.5em; + border-bottom: 1px solid #aaaaaa; + } + + + h1 { + font-size: 165%; + } + + h2 { + padding-top: 0.8em; + font-size: 125%; + } + + h2 + h3 { + padding-top: 0.2em; + } + + h3 { + font-size: 105%; + border-bottom: none; + } + + p { + margin-top: 0.0em; + margin-bottom: 0.1em; + padding: 0; + line-height: 1.2; + } + + pre { + padding: 0; + margin: 0; + } + + div#footer { + font-size: small; + border-top: 1px solid gray; + padding-top: 0.1em; + margin-top: 4.0em; + } + + div#footer-text { + float: left; + padding-bottom: 8px; + } + + ul, ol, dl { + margin-top: 0.1em; + padding-top: 0; + margin-bottom: 0.8em; + } + + dt { + margin-top: 0.5em; + margin-bottom: 0; + } + + dl { + margin-left: 20px; + } + + dd { + color: #222222; + } + + dd > *:first-child { + margin-top: 0; + } + + ul { + list-style-position: outside; + list-style-type: square; + } + + p + ul, p + ol { + margin-top: -0.5em; + } + + li ul, li ol { + margin-top: -0.3em; + } + + ol { + list-style-position: outside; + list-style-type: decimal; + } + + li p, dd p { + margin-bottom: 0.3em; + } + + + ol ol { + list-style-type: lower-alpha; + } + + ol ol ol { + list-style-type: lower-roman; + } + + p + div.codeblock { + margin-top: -0.6em; + } + + div.codeblock, div.infoblock { + margin-right: 0%; + margin-top: 1.2em; + margin-bottom: 1.3em; + } + + div.blocktitle { + font-weight: bold; + color: #cd7b62; + margin-top: 1.2em; + margin-bottom: 0.1em; + } + + div.blockcontent { + border: 1px solid silver; + padding: 0.3em 0.5em; + } + + div.infoblock > div.blockcontent { + background: #f6f6f6; + } + + div.blockcontent p + ul, div.blockcontent p + ol { + margin-top: 0.4em; + } + + div.infoblock p { + margin-bottom: 0em; + } + + div.infoblock li p, div.infoblock dd p { + margin-bottom: 0.5em; + } + + div.infoblock p + p { + margin-top: 0.8em; + } + + div.codeblock > div.blockcontent { + background: #f6f6f6; + } + + span.pycommand { + color: #000070; + } + + span.statement { + color: #008800; + } + span.builtin { + color: #000088; + } + span.operator { + color: #880000; + } + span.error { + color: #aa0000; + } + span.comment, span.comment > *, span.string, span.string > * { + color: #606060; + } + + @media print { + #layout-menu { display: none; } + } + + #fwtitle { + margin: 0; + padding: 0; + } + + #fwtitle #toptitle { + padding-left: 0.5em; + margin-bottom: 0.5em; + } + + #fwtitle div#toptitle { + background-color: #888888; + padding: 0.5em; + padding-left: 1.2em; + padding-right: 1.2em; + margin: 0; + border: none; + } + + #layout-content h1:first-child, #layout-content h2:first-child, #layout-content h3:first-child { + margin-top: -0.7em; + } + + div#toptitle h1, #layout-content div#toptitle h1 { + margin-bottom: 0.0em; + padding-bottom: 0.1em; + padding-top: 0; + margin-top: 0.5em; + border-bottom: none; + } + + div#toptitle, div#toptitle h1, div#toptitle a, div#subtitle, div#subtitle a { + color: #666666; + text-align: left; + } + + div#toptitle a:hover { + border-bottom: none; + } + + + div#toptitle h1 { + color: #666666; + margin-top: 0.1em; + font-weight: bold; + font-size: 25px + } + + img { + border: none; + } + + img.eq { + padding: 0; + padding-left: 0.1em; + padding-right: 0.1em; + margin: 0; + } + + img.eqwl { + padding-left: 2em; + padding-top: 0.6em; + padding-bottom: 0.2em; + margin: 0; + } + + img.menu { + padding: 0; + padding-left: 0.1em; + padding-right: 0.4em; + padding-bottom: 1.2em; + margin: 0; + } + + \ No newline at end of file