diff options
author | gbrandl <devnull@localhost> | 2006-10-19 20:27:28 +0200 |
---|---|---|
committer | gbrandl <devnull@localhost> | 2006-10-19 20:27:28 +0200 |
commit | f4d019954468db777760d21f9243eca8b852c184 (patch) | |
tree | 328b8f8fac25338306b0e7b827686dcc7597df23 /docs/generate.py | |
download | pygments-f4d019954468db777760d21f9243eca8b852c184.tar.gz |
[svn] Name change, round 4 (rename SVN root folder).
Diffstat (limited to 'docs/generate.py')
-rw-r--r-- | docs/generate.py | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/docs/generate.py b/docs/generate.py new file mode 100644 index 00000000..59da281c --- /dev/null +++ b/docs/generate.py @@ -0,0 +1,362 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +""" + Generate Pygments Documentation + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Generates a bunch of html files containing the documentation. + + :copyright: 2006 by Armin Ronacher, Georg Brandl. + :license: GNU LGPL, see LICENSE for more details. +""" + +import os +import sys +from datetime import datetime +from cgi import escape + +from docutils import nodes +from docutils.parsers.rst import directives +from docutils.core import publish_parts +from docutils.writers import html4css1 + +from jinja import Template, Context, StringLoader + +from pygments import highlight +from pygments.lexers import get_lexer_by_name +from pygments.formatters import HtmlFormatter + + +PYGMENTS_FORMATTER = HtmlFormatter(style='friendly', cssclass='syntax') + +USAGE = '''\ +Usage: %s <mode> <destination> [<source.txt> ...] + +Generate either python or html files out of the documentation. + +Mode can either be python or html.\ +''' % sys.argv[0] + +TEMPLATE = '''\ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> +<html> +<head> + <title>{{ title }} — Pygments</title> + <meta http-equiv="content-type" content="text/html; charset=utf-8"> + <style type="text/css"> + {{ style }} + </style> +</head> +<body> + <div id="content"> + <h1 class="heading">Pygments</h1> + <h2 class="subheading">{{ title }}</h2> + {% if not file_id equals "index" %} + <a id="backlink" href="index.html">« Back To Index</a> + {% endif %} + {% if toc %} + <div class="toc"> + <h2>Contents</h2> + <ul class="contents"> + {% for item in toc %} + <li><a href="{{ item.0 }}">{{ item.1 }}</a></li> + {% endfor %} + </ul> + </div> + {% endif %} + {{ body }} + </div> +</body> +<!-- generated on: {{ generation_date }} + file id: {{ file_id }} --> +</html>\ +''' + +STYLESHEET = '''\ +body { + background-color: #f2f2f2; + margin: 0; + padding: 0; + font-family: 'Georgia', serif; + color: #111; +} + +#content { + background-color: white; + padding: 20px; + margin: 20px auto 20px auto; + max-width: 800px; + border: 4px solid #ddd; +} + +h1 { + font-weight: normal; + font-size: 40px; + color: #09839A; +} + +h2 { + font-weight: normal; + font-size: 30px; + color: #C73F00; +} + +h1.heading { + margin: 0 0 30px 0; +} + +h2.subheading { + margin: -30px 0 0 45px; +} + +h3 { + margin-top: 30px; +} + +table.docutils { + border-collapse: collapse; + border: 2px solid #aaa; + margin: 0.5em 1.5em 0.5em 1.5em; +} + +table.docutils td { + padding: 2px; + border: 1px solid #ddd; +} + +p, li, dd, dt, blockquote { + font-size: 15px; + color: #333; +} + +p { + line-height: 150%; + margin-bottom: 0; + margin-top: 10px; +} + +hr { + border-top: 1px solid #ccc; + border-bottom: 0; + border-right: 0; + border-left: 0; + margin-bottom: 10px; + margin-top: 20px; +} + +dl { + margin-left: 10px; +} + +li, dt { + margin-top: 5px; +} + +dt { + font-weight: bold; +} + +th { + text-align: left; +} + +a { + color: #990000; +} + +a:hover { + color: #c73f00; +} + +pre { + background-color: #f0f0f0; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + padding: 5px; + font-size: 13px; + font-family: Bitstream Vera Sans Mono,monospace; +} + +tt { + font-size: 13px; + font-family: Bitstream Vera Sans Mono,monospace; + color: black; + padding: 1px 2px 1px 2px; + background-color: #f0f0f0; +} + +cite { + /* abusing <cite>, it's generated by ReST for `x` */ + font-size: 13px; + font-family: Bitstream Vera Sans Mono,monospace; + font-weight: bold; + font-style: normal; +} + +#backlink { + float: right; + font-size: 11px; + color: #888; +} + +div.toc { + margin: 0 0 10px 0; +} + +div.toc h2 { + font-size: 20px; +} +''' + + +def generate_documentation(data, link_style): + writer = DocumentationWriter(link_style) + parts = publish_parts( + data, + writer=writer, + settings_overrides={ + 'initial_header_level': 3, + 'field_name_limit': 50, + } + ) + return { + 'title': parts['title'].encode('utf-8'), + 'body': parts['body'].encode('utf-8'), + 'toc': parts['toc'] + } + + +def pygments_directive(name, arguments, options, content, lineno, + content_offset, block_text, state, state_machine): + try: + lexer = get_lexer_by_name(arguments[0]) + except ValueError: + # no lexer found + lexer = get_lexer_by_name('text') + parsed = highlight(u'\n'.join(content), lexer, PYGMENTS_FORMATTER) + return [nodes.raw('', parsed, format="html")] +pygments_directive.arguments = (1, 0, 1) +pygments_directive.content = 1 +directives.register_directive('sourcecode', pygments_directive) + + +class DocumentationWriter(html4css1.Writer): + + def __init__(self, link_style): + html4css1.Writer.__init__(self) + self.translator_class = create_translator(link_style) + + def translate(self): + html4css1.Writer.translate(self) + # generate table of contents + 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) + self.parts['toc'] = self._generated_toc + + def build_contents(self, node, level=0): + sections = [] + i = len(node) - 1 + while i >= 0 and isinstance(node[i], nodes.section): + sections.append(node[i]) + i -= 1 + sections.reverse() + toc = [] + for section in sections: + try: + reference = nodes.reference('', '', refid=section['ids'][0], *section[0]) + except IndexError: + continue + ref_id = reference['refid'] + text = escape(reference.astext().encode('utf-8')) + toc.append((ref_id, text)) + + self._generated_toc = [('#%s' % href, caption) for href, caption in toc] + # no further processing + return [] + + +def create_translator(link_style): + class Translator(html4css1.HTMLTranslator): + def visit_reference(self, node): + refuri = node.get('refuri') + if refuri is not None and '/' not in refuri and refuri.endswith('.txt'): + node['refuri'] = link_style(refuri[:-4]) + html4css1.HTMLTranslator.visit_reference(self, node) + return Translator + + +def handle_python(filename, fp, dst): + now = datetime.now() + title = os.path.basename(filename)[:-4] + content = fp.read() + def urlize(href): + # create links for the pygments webpage + if href == 'index.txt': + return '/docs/' + else: + return '/docs/%s/' % href + parts = generate_documentation(content, urlize) + result = file(os.path.join(dst, title + '.py'), 'w') + result.write('# -*- coding: utf-8 -*-\n') + result.write('"""\n Pygments Documentation - %s\n' % title) + result.write(' %s\n\n' % ('~' * (24 + len(title)))) + result.write(' Generated on: %s\n"""\n\n' % now) + result.write('import datetime\n') + result.write('DATE = %r\n' % now) + result.write('TITLE = %r\n' % parts['title']) + result.write('TOC = %r\n' % parts['toc']) + result.write('BODY = %r\n' % parts['body']) + result.close() + + +def handle_html(filename, fp, dst): + now = datetime.now() + title = os.path.basename(filename)[:-4] + content = fp.read() + parts = generate_documentation(content, (lambda x: './%s.html' % x)) + result = file(os.path.join(dst, title + '.html'), 'w') + c = Context(parts) + c['style'] = STYLESHEET + PYGMENTS_FORMATTER.get_style_defs('.syntax') + c['generation_date'] = now + c['file_id'] = title + t = Template(TEMPLATE, StringLoader()) + result.write(t.render(c).encode('utf-8')) + result.close() + + +def run(handle_file, dst, sources=()): + path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'src')) + if not sources: + sources = [os.path.join(path, fn) for fn in os.listdir(path)] + for fn in sources: + if not os.path.isfile(fn): + continue + print 'Processing %s' % fn + f = open(fn) + try: + handle_file(fn, f, dst) + finally: + f.close() + + +def main(mode, dst='build/', *sources): + try: + handler = { + 'html': handle_html, + 'python': handle_python + }[mode] + except KeyError: + print 'Error: unknown mode "%s"' % mode + sys.exit(1) + run(handler, os.path.realpath(dst), sources) + + +if __name__ == '__main__': + if len(sys.argv) == 1: + print USAGE + else: + main(*sys.argv[1:]) |