# -*- coding: utf-8 -*-
"""
Jinja Documenation Builder
"""
import sys
import os
import re
from docutils import nodes, utils
from docutils.core import publish_parts
from docutils.writers import html4css1
from xml.sax import saxutils
from jinja import Template, Context, StringLoader
TEMPLATE = """
{{ title }} | Jinja Documentation
Documentation
{% if toc %}
Table of Contents
{% endif %}
{{ title }}
{{ body }}
"""[1:]
class DocumentationBuilder(object):
def __init__(self, root, dest, rules):
self.root = root
self.rules = rules
self.dest = dest
def build(self):
for folder, subfolders, files in os.walk(self.root):
searchpath = []
if '.svn' in subfolders:
subfolders.remove('.svn')
for f in files:
f = os.path.join(folder, f)[len(self.root):]
for rule, params in self.rules:
m = rule.search(f)
if m is None:
continue
fid = f.rsplit('/', 1)[-1].rsplit('.')[0]
output = self.render(fid, f, params)
self.save(fid, f, output, params)
break
def render(self, fid, f, params):
writer = PageWriter()
parts = publish_parts(
file(os.path.join(self.root, f)).read(),
source_path=f,
writer=writer,
settings_overrides={'initial_header_level': 2}
)
template = Template(TEMPLATE, StringLoader())
return template.render(Context({
'title': parts['title'],
'body': parts['body'],
'toc': parts['toc'],
'root': fid == 'index',
'fid': fid
})).encode('utf-8')
def save(self, fid, f, output, params):
folder = os.path.join(self.dest, params.get('dest', ''))
filename = '%s.html' % fid
try:
os.makedirs(folder)
except OSError:
pass
fp = file(os.path.join(folder, filename), 'w')
fp.write(output)
fp.close()
class PageWriter(html4css1.Writer):
def __init__(self):
html4css1.Writer.__init__(self)
self.translator_class = PageTranslator
def translate(self):
html4css1.Writer.translate(self)
contents = self.build_contents(self.document)
contents_doc = self.document.copy()
contents_doc.children = contents
contents_visitor = self.translator_class(contents_doc)
contents_doc.walkabout(contents_visitor)
toc = []
tmp = {}
for item in contents_visitor.fragment:
if not item or item in ('', ''):
continue
elif item.startswith('':
toc.append(tmp)
tmp = {}
else:
tmp['caption'] = item
self.parts['toc'] = toc
def build_contents(self, node, level=0):
level += 1
sections = []
i = len(node) - 1
while i >= 0 and isinstance(node[i], nodes.section):
sections.append(node[i])
i -= 1
sections.reverse()
entries = []
autonum = 0
depth = 4 # XXX FIXME
for section in sections:
title = section[0]
entrytext = title
try:
reference = nodes.reference('', '', refid=section['ids'][0], *entrytext)
except IndexError:
continue
ref_id = self.document.set_id(reference)
entry = nodes.paragraph('', '', reference)
item = nodes.list_item('', entry)
if level < depth:
subsects = self.build_contents(section, level)
item += subsects
entries.append(item)
if entries:
contents = nodes.bullet_list('', *entries)
return contents
else:
return []
class PageTranslator(html4css1.HTMLTranslator):
def visit_table(self, node):
self.body.append(self.starttag(node, 'table', CLASS='docutils'))
def visit_reference(self, node):
if node.has_key('refuri'):
href = node['refuri']
if ( self.settings.cloak_email_addresses
and href.startswith('mailto:')):
href = self.cloak_mailto(href)
self.in_mailto = 1
else:
assert node.has_key('refid'), \
'References must have "refuri" or "refid" attribute.'
href = '#' + node['refid']
if not '/' in href and href.endswith('.txt'):
href = './%s.html' % (href[:-4])
atts = {'href': href, 'class': 'reference'}
if not isinstance(node.parent, nodes.TextElement):
assert len(node) == 1 and isinstance(node[0], nodes.image)
atts['class'] += ' image-reference'
self.body.append(self.starttag(node, 'a', '', **atts))
if __name__ == '__main__':
app = DocumentationBuilder(
'source/', 'build/', [
(re.compile(r'\.txt$'), {
'dest': './',
'root': './'
})
]
)
app.build()