Wiki

Beginning...

1   Wiki Script

FILENAME: /home/pytis/bin/wiki
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
#!/usr/bin/env python
"""wiki
====
Doc Here"""
import xml.sax.saxutils as saxutils
from docutils.core import publish_parts
import optparse
import tempfile
import os
import re
import sys


__curdir__ = os.path.abspath(os.path.dirname(__file__))
__author__ = 'Josh Lee'
__created__ = '01:06pm 12 Dec, 2009'
__copyright__ = 'PyTs.com'
__version__ = '1.5'

def version():
    print  __version__


def rip_scripts():
    """
    Removes anything that could be javascript to prevent malishish 
    postings.
    """
    jscript = re.compile("(<script.*?\/script\>)", re.IGNORECASE|re.DOTALL)
    def proc(contents):
        if not contents:
            return ""
        return jscript.sub(r'', contents)
    return proc

def bbc_encoder():
    uline = re.compile("\[u\](.*?)\[\/u\]", re.IGNORECASE|re.DOTALL)
    bold = re.compile("\[b\](.*?)\[\/b\]", re.IGNORECASE|re.DOTALL)
    italic = re.compile("\[i\](.*?)\[\/i\]", re.IGNORECASE|re.DOTALL)
    image = re.compile("\[img\](.*?)\[\/img\]", re.IGNORECASE|re.DOTALL)
    ccLinks = re.compile(r"\b([A-Z][a-z]+\w+[A-Z][a-z]+\w+)")
    fixcode = re.compile("\<blockquote\>(.*?)\<table class\=\'codebox\'", re.IGNORECASE|re.DOTALL)

    def proc(value):
        """
        CaSe iN-SeNsiTive
        BBC's are codes that are basically short-cut HTML.
        [u]UNDERLINED TEXT[/u]
        [i]ITALIC TEXT[/i]
        [b]BOLD TEXT[/b]
        """
        value = uline.sub(r'<u>\1</u>', value)
        value = bold.sub(r'<b>\1</b>', value)
        value = italic.sub(r'<i>\1</i>', value)
        value = image.sub(r'<img src="\1" />', value)
        value = ccLinks.sub(r'<a href="?page=\1">\1</a>', value)
        value = fixcode.sub(r"\<blockquote class='code' \><table class='codebox'",  value)

        return value
    return proc

def rest_encode():
    """
    Will be used by encoders and also by a parent encoder (that
    knows that this is is a closure).
    """
    def proc(value):
        return publish_parts(value,writer_name='html')["html_body"] 
    return proc



def wiki_encode():
    """
    The need being satisfied:
        Rest doesn't like HTML code, or BBC.  But I want both rest
        HTML.
        To get around this problem I am first adding a BBC called
        'dohtml'.  
        
    First go through the value and replace matches with tokens
    creating a list of each dohtml instance to be replaced later.

            r = str(r).replace("<td class='code syntax'><pre>\r\n","<td class='code syntax'><pre>")
            r = str(r).replace("<td class='code syntax'><pre>\n","<td class='code syntax'><pre>")
            r = str(r).replace("<td class='code syntax'><pre>","<td class='code syntax'><pre>proff")
    """

    def code_ripper(value):
        """
        pygmentize -f html -l python bin/importnanny.old
        """

        code = re.compile("\[code(.*?)\](.*?)\[\/code\]", re.IGNORECASE|re.DOTALL)
        # I WANT THIS TO MATCH [code ] or [code (python)] or [code] and always store the 
        # language if any in \1 and actual content in \2 
        ret_list = code.findall(value)
        value = code.sub(r'\2', value)
        

        i = 0
        #ret_list = [x[1] for x in ret_list]
        for a in ret_list:
            value = value.replace(a[1], "{_code_%s_}" % i)
            i+=1

        new_list = []
        for tup in ret_list:
            tmp = tempfile.NamedTemporaryFile()

            tmp.write(tup[1])
            tmp.seek(0)
            lang = tup[0]
            if 'python' in lang.lower():
                r = os.popen('pygmentize -f html -l python %s' % tmp.name).read(-1)
            elif 'php' in lang.lower():
                r = os.popen('pygmentize -f html -l php %s' % tmp.name).read(-1)
            elif 'html' in lang.lower():
                r = os.popen('pygmentize -f html -l html %s' % tmp.name).read(-1)
            elif 'bash' in lang.lower():
                r = os.popen('pygmentize -f html -l bash %s' % tmp.name).read(-1)
            else:
                r = '<pre>%s</pre>' % saxutils.escape(tup[1])
                
            tmp.close()
            new_list.append(str(r))

        ret_list = new_list

        return value, ret_list

    def html_ripper(value):
        """
        [dohtml]HTML STUFF[/dohtml]
        first of a 2 step process that allows pure html to be displayed.
        step 2 is located below in while statments using variable 
        """
        help = re.compile("\[help\](.*?)\[\/help\]", re.IGNORECASE|re.DOTALL)

        value = help.sub(r'[dohtml]<div class="help"><pre>\1</pre></div>[/dohtml]', value)


        html = re.compile("\[dohtml\](.*?)\[\/dohtml\]", re.IGNORECASE|re.DOTALL)
        ret_list = html.findall(value)
        value = html.sub(r'\1', value)
        #print ret_list
        i = 0
        for a in ret_list:
            value = value.replace(a, "{_dohtml_%s_}" % i)
            i+=1

        return value, ret_list

    def codebox(val):
        """ Wraps code in a codebox, and makes it "pretty", could
        be named code to pretty
        """
        x = [i for i in range(1, len(val.split("\n")))]
        if not val.endswith("\n"):
            x.append(len(x)+1)
        x.append('')
        x = ". <br />".join(str(i) for i in x)
        return """<div class='codebox'>
        <table width='100%%' class='codebox' cellspacing='0' cellpadding='0' >
            </tr>
                <td class='numbers' align='right'>
                    <div class='numbers' align='right'>%s</div>
                </td>
                <td width='100%%' class='code syntax'>%s</td>
            </tr>
            </table>
            </div>
        """ % (x,val.replace("<pre>\n","<pre>").replace("\n</pre>","</pre>"))



    def proc(value):
        if not value:
            return ""
        scripts = re.compile("\[script file=(.*?)\]", re.IGNORECASE|re.DOTALL)
        ret_list = scripts.findall(value)
        for script in ret_list:
            fpath = script.replace("'",'').replace('"','')
            fpath = os.path.abspath(fpath)

            if not os.path.exists(fpath) or not os.path.isfile(fpath):
                auto_code = "FILE NOT FOUND: %s" % fpath 
            else:
                body = open(fpath,'r').read(-1)
                lang = ""
                if len(body.split("\n")) > 1:
                    if 'php' in body.split("\n")[0].lower():
                        lang = " php"
                    elif 'python' in body.split("\n")[0].lower():
                        lang = " python"
                    elif 'bash' in body.split("\n")[0].lower():
                        lang = " bash"
                    elif 'html' in body.split("\n")[0].lower():
                        lang = " html"
                    # The next few lines are broken up really silly, 
                    # that is so that this can parse itself without getting
                    # too confused.
                    auto_code = "[dohtml]<div class='autoname'>FILENAME: " \
                    "%s</div>[/dohtml] [c" \
                    "ode %s]%s[/co" \
                    "de]" % (fpath, lang, body)

            a = "[script file=%s]" % script
            b = "[script file='%s']" % script
            c = '[script file="%s"]' % script

            value = value.replace(a, auto_code)
            value = value.replace(b, auto_code)
            value = value.replace(c, auto_code)

        page_content_a, page_results_a = code_ripper(value)

        page_content_b, page_results_b = html_ripper(page_content_a)
        #rest_input = saxutils.escape(page_content_b)
        rest_input = page_content_b
        rest_results = rest_encode()(rest_input)
        bbc_results = bbc_encoder()(rest_results)

        i=0
        while i < len(page_results_a):
            bbc_results = bbc_results.replace("{_code_%s_}" % i, codebox(page_results_a[i]))
            i+=1

        i=0
        while i < len(page_results_b):
            bbc_results = bbc_results.replace("{_dohtml_%s_}" % i, page_results_b[i])
            i+=1
        return bbc_results
        
    return proc



def run(opts, val):
    if not val.strip(): return ''
    #val = saxutils.escape(val)
    if opts.debug:
        print """<!-- RST generated to HTML via PyTis tool. 
        Author: Josh Lee
        Copyright: PyTis.com
        Original Text:
        %s
        -->
        """ % saxutils.escape(val)
    return wiki_encode()(rip_scripts()(val))

def main():
    """usage: wiki """
    parser = optparse.OptionParser(description=__doc__)
    parser.set_usage(main.__doc__)
    parser.formatter.format_description = lambda s:s

    parser.add_option("-D", "--debug", action="store_true",
                      default=False, 
                      help="Enable debugging")

    parser.add_option("-v", "--version", action="store_true",
                      default=False, 
                      help="Display Version")

    parser.add_option("-V", "--verbose", action="store_true",
                      default=False, 
                      help="Be more Verbose")
    (opts, args) = parser.parse_args()

    

    if opts.version:
        return version()

    input = str(sys.stdin.read(-1))
    print run(opts, input)

if __name__ == '__main__':
    main()

2   RestIT

1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
264.
265.
266.
267.
268.
269.
270.
271.
272.
273.
274.
275.
276.
277.
278.
279.
280.
281.
282.
283.
284.
285.
286.
287.
288.
289.
290.
291.
292.
293.
294.
295.
296.
297.
298.
299.
300.
301.
302.
303.
304.
305.
306.
307.
308.
309.
310.
311.
312.
313.
314.
315.
316.
317.
318.
319.
320.
321.
322.
323.
324.
325.
326.
327.
328.
329.
330.
331.
332.
333.
334.
335.
336.
337.
338.
339.
340.
341.
342.
343.
344.
345.
346.
347.
348.
349.
350.
351.
352.
353.
354.
355.
356.
357.
358.
359.
360.
361.
362.
363.
364.
365.
366.
367.
368.
369.
370.
371.
372.
373.
374.
375.
376.
377.
378.
379.
380.
381.
382.
383.
384.
385.
386.
387.
388.
389.
390.
391.
392.
393.
394.
395.
396.
397.
398.
399.
400.
401.
402.
403.
404.
405.
406.
407.
408.
409.
410.
411.
412.
413.
414.
415.
416.
417.
418.
419.
420.
421.
422.
423.
424.
425.
426.
427.
428.
429.
430.
431.
432.
433.
434.
435.
436.
437.
438.
439.
440.
441.
442.
443.
444.
445.
446.
447.
448.
449.
450.
451.
452.
453.
454.
455.
456.
457.
458.
459.
460.
461.
462.
463.
464.
465.
466.
467.
468.
469.
470.
471.
<?
/*#############################################################################
PHP ReStrucured TEXT
This tool was written by Josh Lee.
This tool it to be licneced under the GPL.

http://www.gnu.org/copyleft/gpl.html#TOC1


This script requires that you have python installed, 
and the python package "docuutils"

This script is packaged with 1 other file, rest_it.py

	Public Functions:

		make_rest
		

		rest_css
			should return the standard rest css
			
		run_test
			should return out rest in html output


Why Cache?

First Run:
    root@hedebian tools # php  restit.php
    from_file
    Processing time: 0.6830 seconds
    ------------------------------------
    make_rest
    Processing time: 0.7439 seconds
    ------------------------------------
    rst_from_file NO CACHE
    Processing time: 0.7996 seconds
    ------------------------------------
    rst_from_file WITH CACHE
    Processing time: 0.7671 seconds

With cache about the same time as other methods.

Second Run:
    root@hedebian tools # php  restit.php
    from_file
    Processing time: 0.6004 seconds
    ------------------------------------
    make_rest
    Processing time: 0.7967 seconds
    ------------------------------------
    rst_from_file NO CACHE
    Processing time: 0.8299 seconds
    ------------------------------------
    rst_from_file WITH CACHE
    Processing time: 0.0004 seconds

Now that it is cached, it is almost instant, this is why we cache.

#############################################################################*/

 
# Configuration
// Path to rest_it.py
$_rest_py_ = "/home/pytis/public_html/tools/restit.py";
$_rest_py_ = "/home/pytis/public_html/tools/wiki.py";
$cache_dir = "cache/";

$cat = "cat.exe";

function make_rest($in_str) {
	global $_rest_py_, $cat;
    if(file_exists($in_str)) {
        return from_file($in_str);
    }
	$tmpfname = tempnam("",time());
	$fname = realpath($tmpfname);
	$handle = fopen($fname, "w");
	fwrite($handle, $in_str);
	
	if(stristr(@$_SERVER['SERVER_SIGNATURE'], 'win32') !== FALSE) {
		$_rest_py_ = str_replace('/','\\',$_rest_py_);
		$cat = str_replace('/','\\',$cat);
		$cmd = "$cat $tmpfname | python $_rest_py_ ";
	} else {
		$cmd = "cat $tmpfname | $_rest_py_ -D";
	}
	$output = `$cmd`;
	fclose($handle);
	unlink($fname);
	return $output;
}

function from_file($abspath) {
    $handle = fopen($abspath, 'r');
    $contents = fread($handle, filesize($abspath));
    fclose($handle);
    return make_rest($contents);
}


function rst_from_file($abspath, $cache=False) {
    global $cache_dir;
$template = "%s
<!--
PyTis Auto-Generated HTML from the RST to HTML tool, the PyTis Wiki
PyTis wiki tool: Copyright: Josh Lee
Date: %s
File Source: %s
MD5: MD5{%s}
-->";
    $cache_md5 = "";

    if($cache) {
        #print "cacheing";
        #print '<br />';
        $real_md5 = md5_file($abspath);

        $cache_path = str_replace("//", "/", sprintf("%s/%s/%s", 
                                dirname($abspath), 
                                $cache_dir,
                                sprintf("%s.htm", str_replace('.txt','',basename($abspath)))));

        if(file_exists($cache_path)) {
            $cache_handle = fopen($cache_path, 'r');
            $cache_contents = fread($cache_handle, filesize($cache_path));
            $match = preg_match("/$real_md5/", $cache_contents, $matches);
        }
        if($match) {
            #print "returning cache";
            #print '<br />';
            return $cache_contents;
        } else {
            #print 'recahceing';
            #print '<br />';
            $cache_handle = fopen($cache_path, 'w');
            $new_contents = sprintf($template, from_file($abspath),
                                               date('Y-m-d'),
                                               $abspath,
                                               $real_md5);
            fwrite($cache_handle, $new_contents);
            fclose($cache_handle);
            return $new_contents;
        }
    } else {
        #print 'not cacheing';
        #print '<br />';
        $handle = fopen($abspath, 'r');
        $contents = fread($handle, filesize($abspath));
        fclose($handle);
        return make_rest($contents);
    }
}

function rest_css() {
	return <<< EOF
	/*
	:Author: David Goodger
	:Contact: goodger@python.org
	:Date: 2006-05-21 22:44:42 +0200 (Sun, 21 May 2006) 
	:Revision: Revision: 4564 
	:Copyright: This stylesheet has been placed in the public domain.

	Default cascading style sheet for the HTML output of Docutils.

	See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
	customize this style sheet.
	*/

	/* used to remove borders from tables and images */
	BODY {
		background-color: #FFF;
		font-family: arial;
	}
	.borderless, table.borderless td, table.borderless th {
	  border: 0 }

    div.section p {
        text-align: left;
    }
	table.borderless td, table.borderless th {
	  /* Override padding for "table.docutils td" with "! important".
		 The right padding separates the table cells. */
	  padding: 0 0.5em 0 0 ! important }

	.first {
	  /* Override more specific margin styles with "! important". */
	  margin-top: 0 ! important }

	.last, .with-subtitle {
	  margin-bottom: 0 ! important }

	.hidden {
	  display: none }

	a.toc-backref {
	  text-decoration: none ;
	  color: black }

	blockquote.epigraph {
	  margin: 2em 5em ; }

	dl.docutils dd {
	  margin-bottom: 0.5em }

	/* Uncomment (and remove this text!) to get bold-faced definition list terms
	dl.docutils dt {
	  font-weight: bold }
	*/

	div.abstract {
	  margin: 2em 5em }

	div.abstract p.topic-title {
	  font-weight: bold ;
	  text-align: center }

	div.admonition, div.attention, div.caution, div.danger, div.error,
	div.hint, div.important, div.note, div.tip, div.warning {
	  margin: 2em ;
	  border: medium outset ;
	  padding: 1em }

	div.admonition p.admonition-title, div.hint p.admonition-title,
	div.important p.admonition-title, div.note p.admonition-title,
	div.tip p.admonition-title {
	  font-weight: bold ;
	  font-family: sans-serif }

	div.attention p.admonition-title, div.caution p.admonition-title,
	div.danger p.admonition-title, div.error p.admonition-title,
	div.warning p.admonition-title {
	  color: red ;
	  font-weight: bold ;
	  font-family: sans-serif }

	/* Uncomment (and remove this text!) to get reduced vertical space in
	   compound paragraphs.
	div.compound .compound-first, div.compound .compound-middle {
	  margin-bottom: 0.5em }

	div.compound .compound-last, div.compound .compound-middle {
	  margin-top: 0.5em }
	*/

	div.dedication {
	  margin: 2em 5em ;
	  text-align: center ;
	  font-style: italic }

	div.dedication p.topic-title {
	  font-weight: bold ;
	  font-style: normal }

	div.figure {
	  margin-left: 2em ;
	  margin-right: 2em }

	div.footer, div.header {
	  clear: both;
	  font-size: smaller }

	div.line-block {
	  display: block ;
	  margin-top: 1em ;
	  margin-bottom: 1em }

	div.line-block div.line-block {
	  margin-top: 0 ;
	  margin-bottom: 0 ;
	  margin-left: 1.5em }
	
	div.section {
		background-color: #FFFFFF;
	    /* This makes the borders rounded on Mozilla, which pleases me */
	    -moz-border-radius: 8px;
        padding: 4px;
		border: 1px solid #000;
		margin: 10px;
		font-family: verdana;
		font-size: 10pt;
	}
	div.sidebar {
	  margin-left: 1em ;
	  border: medium outset ;
	  padding: 1em ;
	  background-color: #ffffee ;
	  width: 40% ;
	  float: right ;
	  clear: right }

	div.sidebar p.rubric {
	  font-family: sans-serif ;
	  font-size: medium }

	div.system-messages {
	  margin: 5em }

	div.system-messages h1 {
	  color: red }

	div.system-message {
	  border: medium outset ;
	  padding: 1em }

	div.system-message p.system-message-title {
	  color: red ;
	  font-weight: bold }

	div.topic {
	  margin: 2em }

	h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
	h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
	  margin-top: 0.4em }
	h1 {
	  padding: 2px;
	  color: #000;
	  font-weight: bold;
	  font-size: 12pt;
	  border-bottom: 1px solid #CCC;
	}
	h1.title {
	  text-align: center;
	  color: #036;
	  font-weight: bold;
	  font-size: 14pt;
	  border-bottom: 1px solid #000;
	  border: thin solid black;
	  /* This makes the borders rounded on Mozilla, which pleases me */
	  -moz-border-radius: 8px;
	  padding: 4px;
	  background-color: #CCC;
	}

	h2.subtitle {
	  text-align: center }

	hr.docutils {
	  width: 75% }

	img.align-left {
	  clear: left }

	img.align-right {
	  clear: right }

	ol.simple, ul.simple {
	  margin-bottom: 1em }

	ol.arabic {
	  list-style: decimal }

	ol.loweralpha {
	  list-style: lower-alpha }

	ol.upperalpha {
	  list-style: upper-alpha }

	ol.lowerroman {
	  list-style: lower-roman }

	ol.upperroman {
	  list-style: upper-roman }

	p.attribution {
	  text-align: right ;
	  margin-left: 50% }

	p.caption {
	  font-style: italic }

	p.credits {
	  font-style: italic ;
	  font-size: smaller }

	p.label {
	  white-space: nowrap }

	p.rubric {
	  font-weight: bold ;
	  font-size: larger ;
	  color: maroon ;
	  text-align: center }

	p.sidebar-title {
	  font-family: sans-serif ;
	  font-weight: bold ;
	  font-size: larger }

	p.sidebar-subtitle {
	  font-family: sans-serif ;
	  font-weight: bold }

	p.topic-title {
	  font-weight: bold }

	pre.address {
	  margin-bottom: 0 ;
	  margin-top: 0 ;
	  font-family: serif ;
	  font-size: 100% }

	pre.literal-block, pre.doctest-block {
	  margin-left: 2em ;
	  margin-right: 2em }

	span.classifier {
	  font-family: sans-serif ;
	  font-style: oblique }

	span.classifier-delimiter {
	  font-family: sans-serif ;
	  font-weight: bold }

	span.interpreted {
	  font-family: sans-serif }

	span.option {
	  white-space: nowrap }

	span.pre {
	  white-space: pre }

	span.problematic {
	  color: red }

	span.section-subtitle {
	  /* font-size relative to parent (h1..h6 element) */
	  background-color: #FFF;
	  font-size: 80% }

	table.citation {
	  border-left: solid 1px gray;
	  margin-left: 1px }

	table.docinfo {
	  margin: 2em 4em }

	table.docutils {
	  margin-top: 0.5em ;
	  margin-bottom: 0.5em }

	table.footnote {
	  border-left: solid 1px black;
	  margin-left: 1px }

	table.docutils td, table.docutils th,
	table.docinfo td, table.docinfo th {
	  padding-left: 0.5em ;
	  padding-right: 0.5em ;
	  vertical-align: top }

	table.docutils th.field-name, table.docinfo th.docinfo-name {
	  font-weight: bold ;
	  text-align: left ;
	  white-space: nowrap ;
	  padding-left: 0 }

	h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
	h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
	  font-size: 100% }

	ul.auto-toc {
	  list-style-type: none }
EOF;

}
?>