From: richard Date: Thu, 21 Feb 2002 06:21:18 +0000 (+0000) Subject: Tools used to build the documentation X-Git-Url: https://git.tokkee.org/?a=commitdiff_plain;h=a243181af20ad6d502dbec8b1a6b4d11a278160a;p=roundup.git Tools used to build the documentation git-svn-id: http://svn.roundup-tracker.org/svnroot/roundup/trunk@644 57a73879-2fb5-44c3-a270-3262357dd7e2 --- diff --git a/tools/build_html b/tools/build_html new file mode 100755 index 0000000..05587ff --- /dev/null +++ b/tools/build_html @@ -0,0 +1,39 @@ +#! /usr/bin/python + +import sys +import os.path +import glob +import html +import dps.utils +try: + from restructuredtext import Parser +except ImportError: + from dps.parsers.restructuredtext import Parser + +if sys.argv[1:] == '--help': + print """ +Usage: build_html + +Converts all structured text (.stx) files to html files. +""" + sys.exit(1) + +def to_html(filename): + parser = Parser() + input = open(filename).read() + document = dps.utils.newdocument() + parser.parse(input, document) + + formatter = html.DumbHTMLFormatter() + return formatter.format_document(document) + + +for filename in glob.glob('*.stx'): + htmlfile = "%s.html" % os.path.splitext(filename)[0] + print "%s -> %s" % (filename, htmlfile) + f=open(htmlfile, 'wb') + f.write(to_html(filename)) + f.close() + + + diff --git a/tools/html.py b/tools/html.py new file mode 100644 index 0000000..26b1aa2 --- /dev/null +++ b/tools/html.py @@ -0,0 +1,685 @@ +import cStringIO, cgi, sys, urllib +import dps.utils +try: + from restructuredtext import Parser +except ImportError: + from dps.parsers.restructuredtext import Parser + +# TODO: enforce model? + +class DumbHTMLFormatter: + def __init__(self): + self.out = cStringIO.StringIO() + self.w = self.out.write + self.section = 0 + self.closers = [] + + def format(self, node): + '''Format a node + ''' + for entry in node: + self.formatOneTag(entry) + + def formatOneTag(self, tag): + if tag.tagname == '#text': + meth = self.format__text + else: + meth = getattr(self, 'format_'+tag.tagname) + meth(tag) + + # + # Root Element + # + # ((title, subtitle?)?, docinfo?, %structure.model;) + # + def format_document(self, document): + ''' ((title, subtitle?)?, docinfo?, %structure.model;) + + + ''' + self.document = document + self.w('\n') + + n = 0 + + # See if there's a title + if document[n].tagname == 'title': + title = cgi.escape(document[n][0][0].data) + self.w('%s\n'%title) + n += 1 + if document[n].tagname == 'subtitle': + title = cgi.escape(document[n][0][0].data) + self.w('

%s

'%title) + self.section += 1 + n += 1 + + # Now see if there's biblio information + + # see if there's a field_list at the start of the document + if document[n].tagname == 'docinfo': + self.format_docinfo(document[n]) + n += 1 + + self.w('\n') + + # now for the body + l = list(document) + for entry in l[n:]: + self.formatOneTag(entry) + self.w('\n') + return self.out.getvalue() + + # + # Title Elements + # + def format_title(self, node): + self.w(''%self.section) + if node.children: self.format(node) + self.w('\n'%self.section) + + def format_subtitle(self, node): + raise NotImplementedError, node + + # + # Bibliographic Elements + # + def format_docinfo(self, node): + ''' (((%bibliographic.elements;)+, abstract?) | abstract) + + bibliographic.elements: + author | authors | organization | contact | version | revision + | status | date | copyright + ''' + if node.children: self.format(node) + + def format_abstract(self, node): + content = urllib.quote(node[0].data) + self.w('\n'%content) + + def format_author(self, node): + content = urllib.quote(node[0].data) + self.w('\n'%content) + + def format_authors(self, node): + ''' ((author, organization?, contact?)+) + ''' + self.w('\n'%content) + + def format_organization(self, node): + content = urllib.quote(node[0].data) + self.w('\n'%content) + +# TODO: not in DTD +# def format_keywords(self, node): +# content = urllib.quote(node[0].data) +# self.w('\n'%content) + + def format_contact(self, node): + addr = urllib.quote(node[0].data) + self.w('\n'%content) + + def format_revision(self, node): + addr = urllib.quote(node[0].data) + self.w('\n'%content) + + def format_status(self, node): + addr = urllib.quote(node[0].data) + self.w('\n'%content) + + def format_date(self, node): + addr = urllib.quote(node[0].data) + self.w('\n'%content) + + def format_copyright(self, node): + addr = urllib.quote(node[0].data) + self.w('\n'%content) + + # + # Structural Elements + # + # section + # + # structure.model: + # ( ((%body.elements; | transition)+, (%structural.elements;)*) + # | (%structural.elements;)+ ) + # + def format_section(self, node): + self.w(''%urllib.quote(node.attributes['name'])) + self.section += 1 + if node.children: self.format(node) + self.section -= 1 + + def format_transition(self, node): + self.w('
') + + # + # Body Elements + # + # paragraph | literal_block | block_quote | doctest_block| table + # | figure | image | footnote + # | bullet_list | enumerated_list | definition_list | field_list + # | option_list + # | note | tip | hint | warning | error | caution | danger | important + # | target | substitution_definition | comment | system_message + # + # + def format_paragraph(self, node): + ''' %text.model; + ''' + # TODO: there are situations where the

are unnecessary + self.w('

') + if node.children: self.format(node) + self.w('

\n') + + # Simple lists + def format_bullet_list(self, node): + ''' (list_item+) + bullet CDATA + ''' + # TODO: handle attribute + self.w('\n') + + def format_enumerated_list(self, node): + ''' (list_item+) + enumtype (arabic | loweralpha | upperalpha | lowerroman | + upperroman) + prefix CDATA + suffix CDATA + start CDATA + ''' + # TODO: handle attributes + self.w('
    \n') + if node.children: self.format(node) + self.w('
\n') + + def format_list_item(self, node): + ''' (%body.elements;)+ + ''' + self.w('
  • ') + if node.children: self.format(node) + self.w('
  • \n') + + # Definition List + def format_definition_list(self, node): + ''' (definition_list_item+) + ''' + self.w('
    \n') + if node.children: self.format(node) + self.w('
    \n') + + def format_definition_list_item(self, node): + ''' (term, classifier?, definition) + ''' + self.w('
    ') + if node.children: self.format(node) + + def format_term(self, node): + ''' %text.model; + ''' + self.w('') + if node.children:self.format(node) + self.w('') + + def format_classifier(self, node): + ''' %text.model; + ''' + # TODO: handle the classifier better + self.w('') + if node.children: self.format(node) + self.w('') + + def format_definition(self, node): + ''' (%body.elements;)+ + ''' + self.w('
    \n
    ') + # TODO: this is way suboptimal! + first = 1 + for child in node.children: + if child.tagname == 'paragraph' and first: + # just format the contents of the para + self.format(child) + else: + # format the whole tag + self.formatOneTag(child) + first = 0 + self.w('
    \n') + + # Field List + def format_field_list(self, node): + ''' (field+) + ''' + self.w('
    ') + if node.children: self.format(node) + self.w('
    ') + + def format_field(self, node): + ''' (field_name, field_argument*, field_body) + ''' + self.w('
    ') + if node.children: self.format(node) + + def format_field_name(self, node): + ''' (#PCDATA) + ''' + self.w('') + if node.children:self.format(node) + self.w('') + + def format_field_argument(self, node): + ''' (#PCDATA) + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_field_body(self, node): + ''' (%body.elements;)+ + ''' + self.w('
    \n
    ') + if node.children: self.format(node) + self.w('
    \n') + + # Option List + def format_option_list(self, node): + ''' (option_list_item+) + ''' + self.w('\n') + self.w('\n') + if node.children: self.format(node) + self.w('
    OptionDescription
    \n') + + def format_option_list_item(self, node): + ''' (option+, description) + ''' + self.w('') + if node.children: self.format(node) + self.w('\n') + + def format_option(self, node): + ''' ((short_option | long_option | vms_option), option_argument?) + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_short_option(self, node): + ''' (#PCDATA) + ''' + for option in node.children: + self.w('-%s'%cgi.escape(option.data)) + + def format_long_option(self, node): + ''' (#PCDATA) + ''' + for option in node.children: + self.w('--%s'%cgi.escape(option.data)) + + def format_vms_option(self, node): + ''' (#PCDATA) + ''' + for option in node.children: + self.w('/%s'%cgi.escape(option.data)) + + def format_option_argument(self, node): + ''' (#PCDATA) + ''' + for option in node.children: + self.w('=%s'%cgi.escape(option.data)) + + def format_description(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('\n') + + # Literal Block + def format_literal_block(self, node): + self.w('
    ')
    +        if node.children: self.format(node)
    +        self.w('
    \n') + + # Block Quote + def format_block_quote(self, node): + # TODO: I believe this needs to be CSS'ified - blockquote is deprecated + self.w('
    ') + if node.children: self.format(node) + self.w('
    \n') + + # Doctest Block + def format_doctest_block(self, node): + self.w('
    ')
    +        if node.children: self.format(node)
    +        self.w('
    \n') + + # Note, tip, hint, warning, error, caution, danger, important + def format_note(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_tip(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_hint(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_warning(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_error(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_caution(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_danger(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_important(self, node): + ''' (%body.elements;)+ + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + # Footnote + def format_footnote(self, node): + ''' (label?, (%body.elements;)+) + %auto.att; + ''' + raise NotImplementedError, node + + def format_label(self, node): + ''' (#PCDATA) + ''' + for label in node.children: + self.w(cgi.escape(label.data)) + + # Target + def format_target(self, node): + ''' (%text.model;) + %reference.atts; + %anonymous.att; + ''' + pass + + # Substitution Definition + def format_substitution_definition(self, node): + ''' (%text.model;) + ''' + raise NotImplementedError, node + + # Comment + def format_comment(self, node): + ''' (#PCDATA) + %fixedspace.att; + ''' + # TODO: handle attrs + self.w('') + + # Figure + def format_figure(self, node): + ''' (image, ((caption, legend?) | legend) + ''' + raise NotImplementedError, node + + def format_image(self, node): + ''' EMPTY + uri CDATA #REQUIRED + alt CDATA #IMPLIED + height NMTOKEN #IMPLIED + width NMTOKEN #IMPLIED + scale NMTOKEN #IMPLIED + ''' + attrs = node.attributes + l = ['src="%(uri)s"'%attrs] + if attrs.has_key('alt'): + l.append('alt="%(alt)s"'%attrs) + if attrs.has_key('alt'): + l.append('alt="%(alt)s"'%attrs) + if attrs.has_key('height'): + l.append('height="%(height)s"'%attrs) + if attrs.has_key('width'): + l.append('width="%(width)s"'%attrs) + # TODO: scale + self.w(''%(' '.join(l))) + + def format_caption(self, node): + ''' %text.model; + ''' + raise NotImplementedError, node + + def format_legend(self, node): + ''' (%body.elements;)+ + ''' + raise NotImplementedError, node + + # System Message + def format_system_message(self, node): + ''' (%body.elements;)+ + level NMTOKEN #IMPLIED + type CDATA #IMPLIED + ''' + self.w(''%node.attributes['type']) + if node.children: self.format(node) + self.w('') + + # + # Tables: + # NOT IN DOM YET + # + def format_table(self, node): + ''' + +------------------------+------------+----------+----------+ + | Header row, column 1 | Header 2 | Header 3 | Header 4 | + | (header rows optional) | | | | + +========================+============+==========+==========+ + | body row 1, column 1 | column 2 | column 3 | column 4 | + +------------------------+------------+----------+----------+ + | body row 2 | Cells may span columns. | + +------------------------+------------+---------------------+ + | body row 3 | Cells may | - Table cells | + +------------------------+ span rows. | - contain | + | body row 4 | | - body elements. | + +------------------------+------------+---------------------+ + ''' + self.w('\n') + if node.children: self.format(node) + self.w('
    \n') + + def format_tgroup(self, node): + # we get the number of columns, if that's important + if node.children: self.format(node) + + def format_colspec(self, node): + # we get colwidth, but don't need it + pass + + def format_thead(self, node): + for row in node.children: + self.w('') + for cell in row.children: + s = '' + attrs = cell.attributes + if attrs.has_key('morecols'): + s = s + ' colspan=%d'%(attrs['morecols']+1) + if attrs.has_key('morerows'): + s = s + ' rowspan=%d'%(attrs['morerows']+1) + self.w(''%s) + if cell.children: self.format(cell) + self.w('\n') + self.w('\n') + + def format_tbody(self, node): + for row in node.children: + self.w('') + for cell in row.children: + s = '' + attrs = cell.attributes + if attrs.has_key('morecols'): + s = s + ' colspan=%d'%(attrs['morecols']+1) + if attrs.has_key('morerows'): + s = s + ' rowspan=%d'%(attrs['morerows']+1) + self.w(''%s) + if cell.children: self.format(cell) + self.w('\n') + self.w('\n') + + # + # Inline Elements + # + # Inline elements occur within the text contents of body elements. Some + # nesting of inline elements is allowed by these definitions, with the + # following caveats: + # - An inline element may not contain a nested element of the same type + # (e.g. may not contain another ). + # - Nested inline elements may or may not be supported by individual + # applications using this DTD. + # - The inline elements , , and do + # not support nesting. + # + # What that means is that all of these take (%text.model;) except: + # literal (#PCDATA) + # footnote_reference (#PCDATA) + # + # text.model: + # (#PCDATA | %inline.elements;)* + # + def format_emphasis(self, node): + ''' (%text.model;) + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_strong(self, node): + ''' (%text.model;) + ''' + self.w('') + if node.children: self.format(node) + self.w('') + + def format_interpreted(self, node): + ''' (%text.model;) + type CDATA #IMPLIED + ''' + pass #raise NotImplementedError, node + + def format_literal(self, node): + ''' (#PCDATA) + ''' + self.w('') + for literal in node.children: + self.w(cgi.escape(literal.data)) + self.w('') + + def format_reference(self, node): + ''' (%text.model;) + %reference.atts; + %anonymous.att; + ''' + attrs = node.attributes + doc = self.document + ok = 1 + print node + if attrs.has_key('refuri'): + self.w(''%attrs['refuri']) + elif doc.explicit_targets.has_key(attrs['refname']): + # an external reference has been defined + ref = doc.explicit_targets[attrs['refname']] + if ref.attributes.has_key('refuri'): + self.w(''%ref.attributes['refuri']) + else: + self.w(''%attrs['refname']) + elif doc.implicit_targets.has_key(attrs['refname']): + # internal reference + name = attrs['refname'] + self.w(''%urllib.quote(name)) + else: + ok = 0 + self.w('target "%s" ' + 'undefined'%attrs['refname']) + if node.children: self.format(node) + if ok: + self.w('') + + def format_footnote_reference(self, node): + ''' (#PCDATA) + %reference.atts; + %auto.att; + ''' + raise NotImplementedError, node + + def format_substitution_reference(self, node): + ''' (%text.model;) + %refname.att; + ''' + raise NotImplementedError, node + + def format_problematic(self, node): + ''' (%text.model;) + ''' + raise NotImplementedError, node + + # + # Finally, #text + # + def format__text(self, node): + self.w(cgi.escape(node.data)) + + +def main(filename, debug=0): + parser = Parser() + input = open(filename).read() + document = dps.utils.newdocument() + parser.parse(input, document) + if debug == 1: + print document.pformat() + else: + formatter = DumbHTMLFormatter() + print formatter.format_document(document) + +if __name__ == '__main__': + if len(sys.argv) > 2: + main(sys.argv[1], debug=1) + else: + main(sys.argv[1]) +