7 """docutils to HTML CGI converter.
9 CGI script that automatically converts docutils files into html and serves
10 it. The script caches the HTML files and uses the timestamps to regenerate if
11 necessary. Also, the indexes are generated automatically.
16 __author__ = 'Martin Blais <blais@iro.umontreal.ca>'
17 __version__ = '$Revision$'
19 #===============================================================================
20 # EXTERNAL DECLARATIONS
21 #===============================================================================
24 assert sys.version_info[0] == 2
25 if sys.version_info[1] > 1:
26 import cgitb; cgitb.enable()
28 import os, cgi, stat, re
31 from pprint import pprint
33 from ConfigParser import ConfigParser
36 if not os.environ.has_key('NO_CONTENT_TYPE'):
37 print "Content-type: text/html"
40 #===============================================================================
42 #===============================================================================
44 configfn = join(os.getcwd(), 'rst-server.conf')
45 if not exists(configfn):
46 print 'Error: config file "%s" does not exist' % configfn
49 confparser = ConfigParser()
50 confparser.add_section('options')
51 confparser.read(configfn)
56 for o in ['source', 'cache', 'converter']:
57 if not confparser.has_option('options', o):
58 print 'Error: must configure variable', o
60 setattr(opts, o.replace('-', '_'), confparser.get('options', o))
62 for o in ['docutils-config']:
64 if confparser.has_option('options', o):
65 val = confparser.get('options', o)
66 setattr(opts, o.replace('-', '_'), val)
68 form = cgi.FieldStorage()
74 if os.environ.has_key('CONVERTER'):
75 opts.converter = os.environ['CONVERTER']
78 # if len(sys.argv) > 1:
81 #===============================================================================
83 #===============================================================================
87 rejre = map(re.compile, ['^\s*[-=]+\s*$', '^\.\.', '^\s*$', '\s*:\w+:'])
114 # prevent tag-only titles, at least we'll get an error message
115 if title[0] == '<' and title[-1] == '>':
119 valre = re.compile('(.*)\.txt')
121 def nav( fn, script ):
122 if fn and isfile(join(opts.source, fn)):
130 comps += fn.split(os.sep)
132 print '<table class="toptable">'
137 for i in comps[0:-1]:
138 cpath = join(cpath, i)
139 ccomps.append('<a href="%s?p=%s">%s</a>' % (script, cpath, i))
140 ccomps.append('%s' % comps[-1])
141 ccomps = ['<a href="%s">%s</a>' % (script, rootstr)] + ccomps
142 print ' » '.join(ccomps)
147 <?xml version="1.0" encoding="iso8859-1" ?>
148 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
151 <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
152 <meta name="GENERATOR" content="home made recipe in python">
153 <style type="text/css"><!--
157 background-color: #EEEEEE }
163 background-color: #FF8888;
175 script = os.environ['SCRIPT_NAME']
177 # make sure the cache directory exists
178 if not exists(opts.cache):
182 srcfn = join(opts.source, fn)
189 def __init__( self, fn, base ):
194 if not exists(srcfn):
195 print 'Error: this file does not exist'
198 #cachefn = join(cache, fn, 'index.html')
201 for f in os.listdir(srcfn):
202 if f.startswith('.') or f.startswith('#'):
210 files.append( Page(f, mo.group(1)) )
216 f.title = gettitle(join(srcfn, f.fn))
217 files.sort(lambda x, y: cmp(x.title, y.title))
220 print '<li><a href="%s?p=%s">%s</li>' % \
221 (script, join(fn, f.fn), f.title)
226 print '<li><a href="%s?p=%s">%s</li>' % (script, join(fn, f), f)
229 if not fn.endswith('.txt'):
230 print 'request for file not ending in .txt', fn
233 cachefn = join(opts.cache, '%s.html' % splitext(fn)[0])
235 if exists(srcfn) and exists(cachefn):
236 fnstat, cachestat = map(os.stat, [srcfn, cachefn])
237 if fnstat[stat.ST_MTIME] <= cachestat[stat.ST_MTIME]:
242 cachedir = dirname(cachefn)
243 if not exists(cachedir):
244 os.makedirs(cachedir)
247 if opts.docutils_config:
248 cmd += ' --config="%s"' % opts.docutils_config
249 cmd += ' "%s" "%s" 2>&1' % (srcfn, cachefn)
251 chin, chout, cherr = os.popen3(cmd)
256 s, out = commands.getstatusoutput(cmd)
258 print '<div class="conversion-error">'
259 print 'Error: converting document:'
266 print open(cachefn, 'r').read()