[Zope-Checkins] CVS: Zope/lib/python/docutils/writers - __init__.py:1.2.10.3.8.1 docutils_xml.py:1.2.10.3.8.1 html4css1.py:1.2.10.3.8.1 latex2e.py:1.1.2.3.8.1 pep_html.py:1.2.10.3.8.1 pseudoxml.py:1.2.10.3.8.1

Christian 'Tiran' Heimes heimes at faho.rwth-aachen.de
Wed May 12 15:58:01 EDT 2004


Update of /cvs-repository/Zope/lib/python/docutils/writers
In directory cvs.zope.org:/tmp/cvs-serv1763/lib/python/docutils/writers

Modified Files:
      Tag: tiran-restfixing-branch
	__init__.py docutils_xml.py html4css1.py latex2e.py 
	pep_html.py pseudoxml.py 
Log Message:
Installed docutils 0.3.4


=== Zope/lib/python/docutils/writers/__init__.py 1.2.10.3 => 1.2.10.3.8.1 ===
--- Zope/lib/python/docutils/writers/__init__.py:1.2.10.3	Sun Nov 30 11:05:26 2003
+++ Zope/lib/python/docutils/writers/__init__.py	Wed May 12 15:57:57 2004
@@ -26,25 +26,43 @@
     Each writer must support all standard node types listed in
     `docutils.nodes.node_class_names`.
 
-    Call `write()` to process a document.
+    The `write()` method is the main entry point.
     """
 
     component_type = 'writer'
     config_section = 'writers'
 
     document = None
-    """The document to write."""
+    """The document to write (Docutils doctree); set by `write`."""
+
+    output = None
+    """Final translated form of `document`; set by `translate`."""
 
     language = None
-    """Language module for the document."""
+    """Language module for the document; set by `write`."""
 
     destination = None
-    """`docutils.io` IO object; where to write the document."""
+    """`docutils.io` IO object; where to write the document.  Set by `write`."""
 
     def __init__(self):
-        """Initialize the Writer instance."""
+
+        # Currently only used by HTML writer for output fragments:
+        self.parts = {}
+        """Mapping of document part names to fragments of `self.output`.
+        Values are Unicode strings; encoding is up to the client.  The 'whole'
+        key should contain the entire document output.
+        """
 
     def write(self, document, destination):
+        """
+        Process a document into its final form.
+
+        Translate `document` (a Docutils document tree) into the Writer's
+        native format, and write it out to its `destination` (a
+        `docutils.io.Output` subclass object).
+
+        Normally not overridden or extended in subclasses.
+        """
         self.document = document
         self.language = languages.get_language(
             document.settings.language_code)
@@ -55,9 +73,10 @@
 
     def translate(self):
         """
-        Override to do final document tree translation.
+        Do final translation of `self.document` into `self.output`.
+        Called from `write`.  Override in subclasses.
 
-        This is usually done with a `docutils.nodes.NodeVisitor` subclass, in
+        Usually done with a `docutils.nodes.NodeVisitor` subclass, in
         combination with a call to `docutils.nodes.Node.walk()` or
         `docutils.nodes.Node.walkabout()`.  The ``NodeVisitor`` subclass must
         support all standard elements (listed in
@@ -65,6 +84,10 @@
         used by the current Reader as well.
         """
         raise NotImplementedError('subclass must override this method')
+
+    def assemble_parts(self):
+        """Assemble the `self.parts` dictionary.  Extend in subclasses."""
+        self.parts['whole'] = self.output
 
 
 _writer_aliases = {


=== Zope/lib/python/docutils/writers/docutils_xml.py 1.2.10.3 => 1.2.10.3.8.1 ===


=== Zope/lib/python/docutils/writers/html4css1.py 1.2.10.3 => 1.2.10.3.8.1 ===
--- Zope/lib/python/docutils/writers/html4css1.py:1.2.10.3	Sun Nov 30 11:05:26 2003
+++ Zope/lib/python/docutils/writers/html4css1.py	Wed May 12 15:57:57 2004
@@ -22,6 +22,10 @@
 import time
 import re
 from types import ListType
+try:
+    import Image                        # check for the Python Imaging Library
+except ImportError:
+    Image = None
 import docutils
 from docutils import frontend, nodes, utils, writers, languages
 
@@ -55,6 +59,11 @@
           'stylesheet, do not embed it.',
           ['--embed-stylesheet'],
           {'action': 'store_true', 'validator': frontend.validate_boolean}),
+         ('Specify the initial header level.  Default is 1 for "<h1>".  '
+          'Does not affect document title & subtitle (see --no-doc-title).',
+          ['--initial-header-level'],
+          {'choices': '1 2 3 4 5 6'.split(), 'default': '1',
+           'metavar': '<level>'}),
          ('Format for footnote references: one of "superscript" or '
           '"brackets".  Default is "superscript".',
           ['--footnote-references'],
@@ -85,9 +94,6 @@
     config_section = 'html4css1 writer'
     config_section_dependencies = ('writers',)
 
-    output = None
-    """Final translated form of `document`."""
-
     def __init__(self):
         writers.Writer.__init__(self)
         self.translator_class = HTMLTranslator
@@ -96,14 +102,17 @@
         visitor = self.translator_class(self.document)
         self.document.walkabout(visitor)
         self.output = visitor.astext()
-        self.head_prefix = visitor.head_prefix
-        self.stylesheet = visitor.stylesheet
-        self.head = visitor.head
-        self.body_prefix = visitor.body_prefix
-        self.body_pre_docinfo = visitor.body_pre_docinfo
-        self.docinfo = visitor.docinfo
-        self.body = visitor.body
-        self.body_suffix = visitor.body_suffix
+        self.visitor = visitor
+        for attr in ('head_prefix', 'stylesheet', 'head', 'body_prefix',
+                     'body_pre_docinfo', 'docinfo', 'body', 'fragment',
+                     'body_suffix'):
+            setattr(self, attr, getattr(visitor, attr))
+
+    def assemble_parts(self):
+        writers.Writer.assemble_parts(self)
+        for part in ('title', 'subtitle', 'docinfo', 'body', 'header',
+                     'footer', 'meta', 'stylesheet', 'fragment'):
+            self.parts[part] = ''.join(getattr(self.visitor, part))
 
 
 class HTMLTranslator(nodes.NodeVisitor):
@@ -143,14 +152,14 @@
     - Regardless of the above, in definitions, table cells, field bodies,
       option descriptions, and list items, mark the first child with
       'class="first"' and the last child with 'class="last"'.  The stylesheet
-      sets the margins (top & bottom respecively) to 0 for these elements.
+      sets the margins (top & bottom respectively) to 0 for these elements.
 
     The ``no_compact_lists`` setting (``--no-compact-lists`` command-line
     option) disables list whitespace optimization.
     """
 
     xml_declaration = '<?xml version="1.0" encoding="%s" ?>\n'
-    doctype = ('<!DOCTYPE html' 
+    doctype = ('<!DOCTYPE html'
                ' PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
                ' "http://www.w3.org/TR/xhtml1/DTD/'
                'xhtml1-transitional.dtd">\n')
@@ -171,11 +180,12 @@
         self.settings = settings = document.settings
         lcode = settings.language_code
         self.language = languages.get_language(lcode)
+        self.meta = [self.content_type % settings.output_encoding,
+                     self.generator % docutils.__version__]
         self.head_prefix = [
               self.doctype,
-              self.html_head % (lcode, lcode),
-              self.content_type % settings.output_encoding,
-              self.generator % docutils.__version__]
+              self.html_head % (lcode, lcode)]
+        self.head_prefix.extend(self.meta)
         if settings.xml_declaration:
             self.head_prefix.insert(0, self.xml_declaration
                                     % settings.output_encoding)
@@ -192,11 +202,17 @@
             else:
                 self.stylesheet = []
         self.body_prefix = ['</head>\n<body>\n']
+        # document title, subtitle display
         self.body_pre_docinfo = []
+        # author, date, etc.
         self.docinfo = []
         self.body = []
+        self.fragment = []
         self.body_suffix = ['</body>\n</html>\n']
         self.section_level = 0
+        self.initial_header_level = int(settings.initial_header_level)
+        # A heterogenous stack used in conjunction with the tree traversal.
+        # Make sure that the pops correspond to the pushes:
         self.context = []
         self.topic_class = ''
         self.colspecs = []
@@ -204,6 +220,11 @@
         self.compact_simple = None
         self.in_docinfo = None
         self.in_sidebar = None
+        self.title = []
+        self.subtitle = []
+        self.header = []
+        self.footer = []
+        self.in_document_title = 0
 
     def get_stylesheet_reference(self, relative_to=None):
         settings = self.settings
@@ -267,8 +288,11 @@
                 parts.append('%s="%s"' % (name.lower(),
                                           self.attval(' '.join(values))))
             else:
-                parts.append('%s="%s"' % (name.lower(),
-                                          self.attval(unicode(value))))
+                try:
+                    uval = unicode(value)
+                except TypeError:       # for Python 2.1 compatibility:
+                    uval = unicode(str(value))
+                parts.append('%s="%s"' % (name.lower(), self.attval(uval)))
         return '<%s%s>%s' % (' '.join(parts), infix, suffix)
 
     def emptytag(self, node, tagname, suffix='\n', **attributes):
@@ -307,7 +331,7 @@
         self.body.append(self.starttag(node, 'div',
                                         CLASS=(name or 'admonition')))
         if name:
-            self.body.append('<p class="admonition-title">'
+            self.body.append('<p class="admonition-title first">'
                              + self.language.labels[name] + '</p>\n')
 
     def depart_admonition(self, node=None):
@@ -519,14 +543,14 @@
         self.body.append('</tbody>\n</table>\n')
         self.in_docinfo = None
         start = self.context.pop()
-        self.body_pre_docinfo = self.body[:start]
         self.docinfo = self.body[start:]
         self.body = []
 
     def visit_docinfo_item(self, node, name, meta=1):
         if meta:
-            self.head.append('<meta name="%s" content="%s" />\n'
-                             % (name, self.attval(node.astext())))
+            meta_tag = '<meta name="%s" content="%s" />\n' \
+                       % (name, self.attval(node.astext()))
+            self.add_meta(meta_tag)
         self.body.append(self.starttag(node, 'tr', ''))
         self.body.append('<th class="docinfo-name">%s:</th>\n<td>'
                          % self.language.labels[name])
@@ -546,9 +570,14 @@
         self.body.append('\n</pre>\n')
 
     def visit_document(self, node):
-        self.body.append(self.starttag(node, 'div', CLASS='document'))
+        # empty or untitled document?
+        if not len(node) or not isinstance(node[0], nodes.title):
+            # for XHTML conformance, modulo IE6 appeasement:
+            self.head.insert(0, '<title></title>\n')
 
     def depart_document(self, node):
+        self.fragment.extend(self.body)
+        self.body.insert(0, self.starttag(node, 'div', CLASS='document'))
         self.body.append('</div>\n')
 
     def visit_emphasis(self, node):
@@ -671,6 +700,7 @@
         footer = (['<hr class="footer" />\n',
                    self.starttag(node, 'div', CLASS='footer')]
                   + self.body[start:] + ['</div>\n'])
+        self.footer.extend(footer)
         self.body_suffix[:0] = footer
         del self.body[start:]
 
@@ -739,9 +769,11 @@
 
     def depart_header(self, node):
         start = self.context.pop()
-        self.body_prefix.append(self.starttag(node, 'div', CLASS='header'))
-        self.body_prefix.extend(self.body[start:])
-        self.body_prefix.append('<hr />\n</div>\n')
+        header = [self.starttag(node, 'div', CLASS='header')]
+        header.extend(self.body[start:])
+        header.append('<hr />\n</div>\n')
+        self.body_prefix.extend(header)
+        self.header = header
         del self.body[start:]
 
     def visit_hint(self, node):
@@ -756,6 +788,27 @@
             del atts['class']           # prevent duplication with node attrs
         atts['src'] = atts['uri']
         del atts['uri']
+        if atts.has_key('scale'):
+            if Image and not (atts.has_key('width')
+                              and atts.has_key('height')):
+                try:
+                    im = Image.open(str(atts['src']))
+                except (IOError, # Source image can't be found or opened
+                        UnicodeError):  # PIL doesn't like Unicode paths.
+                    pass
+                else:
+                    if not atts.has_key('width'):
+                        atts['width'] = im.size[0]
+                    if not atts.has_key('height'):
+                        atts['height'] = im.size[1]
+                    del im
+            if atts.has_key('width'):
+                atts['width'] = int(round(atts['width']
+                                          * (float(atts['scale']) / 100)))
+            if atts.has_key('height'):
+                atts['height'] = int(round(atts['height']
+                                           * (float(atts['scale']) / 100)))
+            del atts['scale']
         if not atts.has_key('alt'):
             atts['alt'] = atts['src']
         if isinstance(node.parent, nodes.TextElement):
@@ -837,11 +890,16 @@
         self.body.append('\n</pre>\n')
 
     def visit_meta(self, node):
-        self.head.append(self.emptytag(node, 'meta', **node.attributes))
+        meta = self.emptytag(node, 'meta', **node.attributes)
+        self.add_meta(meta)
 
     def depart_meta(self, node):
         pass
 
+    def add_meta(self, tag):
+        self.meta.append(tag)
+        self.head.append(tag)
+
     def visit_note(self, node):
         self.visit_admonition(node, 'note')
 
@@ -941,6 +999,11 @@
         raise nodes.SkipNode
 
     def visit_reference(self, node):
+        if isinstance(node.parent, nodes.TextElement):
+            self.context.append('')
+        else:
+            self.body.append('<p>')
+            self.context.append('</p>\n')
         if node.has_key('refuri'):
             href = node['refuri']
         elif node.has_key('refid'):
@@ -952,6 +1015,7 @@
 
     def depart_reference(self, node):
         self.body.append('</a>')
+        self.body.append(self.context.pop())
 
     def visit_revision(self, node):
         self.visit_docinfo_item(node, 'revision', meta=None)
@@ -1017,12 +1081,18 @@
             self.body.append(self.starttag(node, 'p', '',
                                            CLASS='sidebar-subtitle'))
             self.context.append('</p>\n')
-        else:
+        elif isinstance(node.parent, nodes.document):
             self.body.append(self.starttag(node, 'h2', '', CLASS='subtitle'))
             self.context.append('</h2>\n')
+            self.in_document_title = len(self.body)
 
     def depart_subtitle(self, node):
         self.body.append(self.context.pop())
+        if self.in_document_title:
+            self.subtitle = self.body[self.in_document_title:-1]
+            self.in_document_title = 0
+            self.body_pre_docinfo.extend(self.body)
+            del self.body[:]
 
     def visit_superscript(self, node):
         self.body.append(self.starttag(node, 'sup', ''))
@@ -1135,27 +1205,35 @@
     def visit_title(self, node):
         """Only 6 section levels are supported by HTML."""
         check_id = 0
+        close_tag = '</p>\n'
         if isinstance(node.parent, nodes.topic):
             self.body.append(
-                  self.starttag(node, 'p', '', CLASS='topic-title'))
+                  self.starttag(node, 'p', '', CLASS='topic-title first'))
             check_id = 1
         elif isinstance(node.parent, nodes.sidebar):
             self.body.append(
-                  self.starttag(node, 'p', '', CLASS='sidebar-title'))
+                  self.starttag(node, 'p', '', CLASS='sidebar-title first'))
             check_id = 1
         elif isinstance(node.parent, nodes.admonition):
             self.body.append(
-                  self.starttag(node, 'p', '', CLASS='admonition-title'))
+                  self.starttag(node, 'p', '', CLASS='admonition-title first'))
+            check_id = 1
+        elif isinstance(node.parent, nodes.table):
+            self.body.append(
+                  self.starttag(node, 'caption', ''))
             check_id = 1
+            close_tag = '</caption>\n'
         elif self.section_level == 0:
             # document title
             self.head.append('<title>%s</title>\n'
                              % self.encode(node.astext()))
             self.body.append(self.starttag(node, 'h1', '', CLASS='title'))
             self.context.append('</h1>\n')
+            self.in_document_title = len(self.body)
         else:
+            h_level = self.section_level + self.initial_header_level - 1
             self.body.append(
-                  self.starttag(node, 'h%s' % self.section_level, ''))
+                  self.starttag(node, 'h%s' % h_level, ''))
             atts = {}
             if node.parent.hasattr('id'):
                 atts['name'] = node.parent['id']
@@ -1163,17 +1241,22 @@
                 atts['class'] = 'toc-backref'
                 atts['href'] = '#' + node['refid']
             self.body.append(self.starttag({}, 'a', '', **atts))
-            self.context.append('</a></h%s>\n' % (self.section_level))
+            self.context.append('</a></h%s>\n' % (h_level))
         if check_id:
             if node.parent.hasattr('id'):
                 self.body.append(
                     self.starttag({}, 'a', '', name=node.parent['id']))
-                self.context.append('</a></p>\n')
+                self.context.append('</a>' + close_tag)
             else:
-                self.context.append('</p>\n')
+                self.context.append(close_tag)
 
     def depart_title(self, node):
         self.body.append(self.context.pop())
+        if self.in_document_title:
+            self.title = self.body[self.in_document_title:-1]
+            self.in_document_title = 0
+            self.body_pre_docinfo.extend(self.body)
+            del self.body[:]
 
     def visit_title_reference(self, node):
         self.body.append(self.starttag(node, 'cite', ''))


=== Zope/lib/python/docutils/writers/latex2e.py 1.1.2.3 => 1.1.2.3.8.1 ===
--- Zope/lib/python/docutils/writers/latex2e.py:1.1.2.3	Sun Nov 30 11:05:26 2003
+++ Zope/lib/python/docutils/writers/latex2e.py	Wed May 12 15:57:57 2004
@@ -11,7 +11,7 @@
 __docformat__ = 'reStructuredText'
 
 # code contributions from several people included, thanks too all.
-# some named: David Abrahams, Julien Letessier, who is missing.
+# some named: David Abrahams, Julien Letessier, Lele Gaifax, and others.
 #
 # convention deactivate code by two # e.g. ##.
 
@@ -76,13 +76,43 @@
           ['--use-latex-toc'],
           {'default': 0, 'action': 'store_true',
            'validator': frontend.validate_boolean}),
-         ('Let LaTeX print author and date, donot show it in docutils document info.',
+         ('Let LaTeX print author and date, do not show it in docutils '
+          'document info.',
           ['--use-latex-docinfo'],
           {'default': 0, 'action': 'store_true',
            'validator': frontend.validate_boolean}),
          ('Color of any hyperlinks embedded in text '
           '(default: "blue", "0" to disable).',
-          ['--hyperlink-color'], {'default': 'blue'}),))
+          ['--hyperlink-color'], {'default': 'blue'}),
+         ('Enable compound enumerators for nested enumerated lists '
+          '(e.g. "1.2.a.ii").  Default: disabled.',
+          ['--compound-enumerators'],
+          {'default': None, 'action': 'store_true',
+           'validator': frontend.validate_boolean}),
+         ('Disable compound enumerators for nested enumerated lists.  This is '
+          'the default.',
+          ['--no-compound-enumerators'],
+          {'action': 'store_false', 'dest': 'compound_enumerators'}),
+         ('Enable section ("." subsection ...) prefixes for compound '
+          'enumerators.  This has no effect without --compound-enumerators.  '
+          'Default: disabled.',
+          ['--section-prefix-for-enumerators'],
+          {'default': None, 'action': 'store_true',
+           'validator': frontend.validate_boolean}),
+         ('Disable section prefixes for compound enumerators.  '
+          'This is the default.',
+          ['--no-section-prefix-for-enumerators'],
+          {'action': 'store_false', 'dest': 'section_prefix_for_enumerators'}),
+         ('Set the separator between section number and enumerator '
+          'for compound enumerated lists.  Default is "-".',
+          ['--section-enumerator-separator'],
+          {'default': '-', 'metavar': '<char>'}),
+         ('When possibile, use verbatim for literal-blocks.'
+          'Default is to always use the mbox environment.',
+          ['--use-verbatim-when-possible'],
+          {'default': 0, 'action': 'store_true',
+           'validator': frontend.validate_boolean}),
+          ))
 
     settings_defaults = {'output_encoding': 'latin-1'}
 
@@ -245,10 +275,38 @@
             '% some commands, that could be overwritten in the style file.\n'
             '\\newcommand{\\rubric}[1]'
             '{\\subsection*{~\\hfill {\\it #1} \\hfill ~}}\n'
+            '\\newcommand{\\titlereference}[1]{\\textsl{#1}}\n'
             '% end of "some commands"\n',
          ]
         }
 
+class DocumentClass:
+    """Details of a LaTeX document class."""
+
+    # BUG: LaTeX has no deeper sections (actually paragrah is no
+    # section either).
+    _class_sections = {
+        'book': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
+        'report': ( 'chapter', 'section', 'subsection', 'subsubsection' ),
+        'article': ( 'section', 'subsection', 'subsubsection' ),
+        }
+    _deepest_section = 'subsubsection'
+
+    def __init__(self, document_class):
+        self.document_class = document_class
+
+    def section(self, level):
+        """ Return the section name at the given level for the specific
+            document class.
+
+            Level is 1,2,3..., as level 0 is the title."""
+
+        sections = self._class_sections[self.document_class]
+        if level <= len(sections):
+            return sections[level-1]
+        else:
+            return self._deepest_section
+
 
 class LaTeXTranslator(nodes.NodeVisitor):
     # When options are given to the documentclass, latex will pass them
@@ -277,6 +335,16 @@
     # list environment for docinfo. else tabularx
     use_optionlist_for_docinfo = 0 # NOT YET IN USE
 
+    # Use compound enumerations (1.A.1.)
+    compound_enumerators = 0
+
+    # If using compound enumerations, include section information.
+    section_prefix_for_enumerators = 0
+
+    # This is the character that separates the section ("." subsection ...)
+    # prefix from the regular list enumerator.
+    section_enumerator_separator = '-'
+
     # default link color
     hyperlink_color = "blue"
 
@@ -287,6 +355,11 @@
         self.use_latex_docinfo = settings.use_latex_docinfo
         self.use_latex_footnotes = settings.use_latex_footnotes
         self.hyperlink_color = settings.hyperlink_color
+        self.compound_enumerators = settings.compound_enumerators
+        self.section_prefix_for_enumerators = (
+            settings.section_prefix_for_enumerators)
+        self.section_enumerator_separator = (
+            settings.section_enumerator_separator.replace('_', '\\_'))
         if self.hyperlink_color == '0':
             self.hyperlink_color = 'black'
             self.colorlinks = 'false'
@@ -302,6 +375,9 @@
         if self.babel.get_language():
             self.d_options += ',%s' % \
                     self.babel.get_language()
+
+        self.d_class = DocumentClass(settings.documentclass)
+
         self.head_prefix = [
               self.latex_head % (self.d_options,self.settings.documentclass),
               '\\usepackage{babel}\n',     # language is in documents settings.
@@ -333,7 +409,7 @@
               '\\newlength{\\docinfowidth}\n',
               '\\setlength{\\docinfowidth}{0.9\\textwidth}\n'
               # linewidth of current environment, so tables are not wider
-              # than the sidebar: using locallinewidth seams to defer evaluation
+              # than the sidebar: using locallinewidth seems to defer evaluation
               # of linewidth, this is fixing it.
               '\\newlength{\\locallinewidth}\n',
               # will be set later.
@@ -368,6 +444,7 @@
         self.topic_class = ''
         # column specification for tables
         self.colspecs = []
+        self.table_caption = None
         # do we have one or more authors
         self.author_stack = None
         # Flags to encode
@@ -383,11 +460,24 @@
 
         # enumeration is done by list environment.
         self._enum_cnt = 0
+
+        # Stack of section counters so that we don't have to use_latex_toc.
+        # This will grow and shrink as processing occurs.
+        # Initialized for potential first-level sections.
+        self._section_number = [0]
+
+        # The current stack of enumerations so that we can expand
+        # them into a compound enumeration
+        self._enumeration_counters = []
+
         # docinfo.
         self.docinfo = None
         # inside literal block: no quote mangling.
         self.literal_block = 0
+        self.literal_block_stack = []
         self.literal = 0
+        # true when encoding in math mode
+        self.mathmode = 0
 
     def get_stylesheet_reference(self):
         if self.settings.stylesheet_path:
@@ -465,7 +555,7 @@
 
         # then dollar
         text = text.replace("$", '{\\$}')
-        if not ( self.literal_block or self.literal ):
+        if not ( self.literal_block or self.literal or self.mathmode ):
             # the vertical bar: in mathmode |,\vert or \mid
             #   in textmode \textbar
             text = text.replace("|", '{\\textbar}')
@@ -492,7 +582,13 @@
             # ! LaTeX Error: There's no line here to end.
             text = text.replace("\n", '~\\\\\n')
         elif self.mbox_newline:
-            text = text.replace("\n", '}\\\\\n\\mbox{')
+            if self.literal_block:
+                closings = "}" * len(self.literal_block_stack)
+                openings = "".join(self.literal_block_stack)
+            else:
+                closings = ""
+                openings = ""
+            text = text.replace("\n", "%s}\\\\\n\\mbox{%s" % (closings,openings))
         if self.insert_none_breaking_blanks:
             text = text.replace(' ', '~')
         # unicode !!!
@@ -528,14 +624,15 @@
     def depart_address(self, node):
         self.depart_docinfo_item(node)
 
-    def visit_admonition(self, node, name):
+    def visit_admonition(self, node, name=''):
         self.body.append('\\begin{center}\\begin{sffamily}\n')
         self.body.append('\\fbox{\\parbox{\\admonitionwidth}{\n')
-        self.body.append('\\textbf{\\large '+ self.language.labels[name] + '}\n');
+        if name:
+            self.body.append('\\textbf{\\large '+ self.language.labels[name] + '}\n');
         self.body.append('\\vspace{2mm}\n')
 
 
-    def depart_admonition(self):
+    def depart_admonition(self, node=None):
         self.body.append('}}\n') # end parbox fbox
         self.body.append('\\end{sffamily}\n\\end{center}\n');
 
@@ -582,6 +679,24 @@
         else:
             self.body.append( '\\end{itemize}\n' )
 
+    # Imperfect superscript/subscript handling: mathmode italicizes
+    # all letters by default.
+    def visit_superscript(self, node):
+        self.body.append('$^{')
+        self.mathmode = 1
+
+    def depart_superscript(self, node):
+        self.body.append('}$')
+        self.mathmode = 0
+
+    def visit_subscript(self, node):
+        self.body.append('$_{')
+        self.mathmode = 1
+
+    def depart_subscript(self, node):
+        self.body.append('}$')
+        self.mathmode = 0
+
     def visit_caption(self, node):
         self.body.append( '\\caption{' )
 
@@ -601,11 +716,10 @@
         self.depart_footnote(node)
 
     def visit_title_reference(self, node):
-        # BUG title-references are what?
-        pass
+        self.body.append( '\\titlereference{' )
 
     def depart_title_reference(self, node):
-        pass
+        self.body.append( '}' )
 
     def visit_citation_reference(self, node):
         href = ''
@@ -767,9 +881,11 @@
 
     def visit_emphasis(self, node):
         self.body.append('\\emph{')
+        self.literal_block_stack.append('\\emph{')
 
     def depart_emphasis(self, node):
         self.body.append('}')
+        self.literal_block_stack.pop()
 
     def visit_entry(self, node):
         # cell separation
@@ -781,13 +897,15 @@
 
         # multi{row,column}
         if node.has_key('morerows') and node.has_key('morecols'):
-            raise NotImplementedError('LaTeX can\'t handle cells that'
+            raise NotImplementedError('LaTeX can\'t handle cells that '
             'span multiple rows *and* columns, sorry.')
         atts = {}
         if node.has_key('morerows'):
+            raise NotImplementedError('multiple rows are not working (yet), sorry.')
             count = node['morerows'] + 1
             self.body.append('\\multirow{%d}*{' % count)
             self.context.append('}')
+            # BUG following rows must have empty cells.
         elif node.has_key('morecols'):
             # the vertical bar before column is missing if it is the first column.
             # the one after always.
@@ -830,13 +948,22 @@
         enum_prefix = ""
         if node.has_key('prefix'):
             enum_prefix = node['prefix']
-
+        if self.compound_enumerators:
+            pref = ""
+            if self.section_prefix_for_enumerators and self.section_level:
+                for i in range(self.section_level):
+                    pref += '%d.' % self._section_number[i]
+                pref = pref[:-1] + self.section_enumerator_separator
+                enum_prefix += pref
+            for counter in self._enumeration_counters:
+                enum_prefix += counter + '.'
         enum_type = "arabic"
         if node.has_key('enumtype'):
             enum_type = node['enumtype']
         if enum_style.has_key(enum_type):
             enum_type = enum_style[enum_type]
         counter_name = "listcnt%d" % self._enum_cnt;
+        self._enumeration_counters.append("\\%s{%s}" % (enum_type,counter_name))
         self.body.append('\\newcounter{%s}\n' % counter_name)
         self.body.append('\\begin{list}{%s\\%s{%s}%s}\n' % \
             (enum_prefix,enum_type,counter_name,enum_suffix))
@@ -852,6 +979,7 @@
 
     def depart_enumerated_list(self, node):
         self.body.append('\\end{list}\n')
+        self._enumeration_counters.pop()
 
     def visit_error(self, node):
         self.visit_admonition(node, 'error')
@@ -964,6 +1092,7 @@
             return
         self.body.append('}%s' % self.context.pop())
 
+    # elements generated by the framework e.g. section numbers.
     def visit_generated(self, node):
         pass
 
@@ -987,17 +1116,15 @@
         self.depart_admonition()
 
     def visit_image(self, node):
-        attrs = node.attributes.copy()
+        attrs = node.attributes
         pre = []                        # in reverse order
         post = ['\\includegraphics{%s}' % attrs['uri']]
-        def prepost(pre_append, post_append):
-            pre.append(pre_append)
-            post.append(post_append)
         inline = isinstance(node.parent, nodes.TextElement)
         if 'scale' in attrs:
             # Could also be done with ``scale`` option to
             # ``\includegraphics``; doing it this way for consistency.
-            prepost('\\scalebox{%f}{' % (attrs['scale'] / 100.0,), '}')
+            pre.append('\\scalebox{%f}{' % (attrs['scale'] / 100.0,))
+            post.append('}')
         if 'align' in attrs:
             align_prepost = {
                 # By default latex aligns the top of an image.
@@ -1011,11 +1138,13 @@
                 (0, 'left'): ('{', '\\hfill}'),
                 (0, 'right'): ('{\\hfill', '}'),}
             try:
-                prepost(*align_prepost[inline, attrs['align']])
+                pre.append(align_prepost[inline, attrs['align']][0])
+                post.append(align_prepost[inline, attrs['align']][1])
             except KeyError:
-                pass                    # complain here?
+                pass                    # XXX complain here?
         if not inline:
-            prepost('\n', '\n')
+            pre.append('\n')
+            post.append('\n')
         pre.reverse()
         self.body.extend(pre + post)
 
@@ -1054,6 +1183,8 @@
         * whitespace (including linebreaks) is significant
         * inline markup is supported.
         * serif typeface
+
+        mbox would stop LaTeX from wrapping long lines.
         """
         self.body.append('\\begin{flushleft}\n')
         self.insert_none_breaking_blanks = 1
@@ -1074,7 +1205,9 @@
         self.body.append('\n\\end{flushleft}\n')
 
     def visit_list_item(self, node):
-        self.body.append('\\item ')
+        # HACK append "{}" in case the next character is "[", which would break
+        # LaTeX's list environment (no numbering and the "[" is not printed).
+        self.body.append('\\item {} ')
 
     def depart_list_item(self, node):
         self.body.append('\n')
@@ -1089,31 +1222,51 @@
 
     def visit_literal_block(self, node):
         """
-        .. parsed-literal::
+        Render a literal-block.
+
+        Literal blocks are used for "::"-prefixed literal-indented
+        blocks of text, where the inline markup is not recognized,
+        but are also the product of the parsed-literal directive,
+        where the markup is respected.
+        
+        mbox stops LaTeX from wrapping long lines.
         """
-        # typically in a typewriter/monospaced typeface.
-        # care must be taken with the text, because inline markup is recognized.
+        # In both cases, we want to use a typewriter/monospaced typeface.
+        # For "real" literal-blocks, we can use \verbatim, while for all
+        # the others we must use \mbox.
         #
-        # possibilities:
-        # * verbatim: is no possibility, as inline markup does not work.
-        # * obey..: is from julien and never worked for me (grubert).
-        self.use_for_literal_block = "mbox"
-        self.literal_block = 1
-        if (self.use_for_literal_block == "mbox"):
-            self.mbox_newline = 1
-            self.insert_none_breaking_blanks = 1
-            self.body.append('\\begin{ttfamily}\\begin{flushleft}\n\\mbox{')
+        # We can distinguish between the two kinds by the number of
+        # siblings the compose this node: if it is composed by a
+        # single element, it's surely is either a real one, otherwise
+        # it's a parsed-literal that does not contain any markup.
+        # 
+        if (self.settings.use_verbatim_when_possible and (len(node) == 1)
+              # in case of a parsed-literal containing just a "**bold**" word:
+              and isinstance(node[0], nodes.Text)):
+            self.verbatim = 1
+            self.body.append('\\begin{verbatim}\n')
         else:
-            self.body.append('{\\obeylines\\obeyspaces\\ttfamily\n')
+            self.literal_block = 1
+            self.insert_none_breaking_blanks = 1
+            self.body.append('\\begin{ttfamily}\\begin{flushleft}\n')
+            self.mbox_newline = 1
+            if self.mbox_newline:
+                self.body.append('\\mbox{')
+            # * obey..: is from julien and never worked for me (grubert).
+            #   self.body.append('{\\obeylines\\obeyspaces\\ttfamily\n')
 
     def depart_literal_block(self, node):
-        if (self.use_for_literal_block == "mbox"):
-            self.body.append('}\n\\end{flushleft}\\end{ttfamily}\n')
+        if self.verbatim:
+            self.body.append('\n\\end{verbatim}\n')
+            self.verbatim = 0
+        else:
+            if self.mbox_newline:
+                self.body.append('}')
+            self.body.append('\n\\end{flushleft}\\end{ttfamily}\n')
             self.insert_none_breaking_blanks = 0
             self.mbox_newline = 0
-        else:
-            self.body.append('}\n')
-        self.literal_block = 0
+            # obey end: self.body.append('}\n')
+            self.literal_block = 0
 
     def visit_meta(self, node):
         self.body.append('[visit_meta]\n')
@@ -1226,13 +1379,14 @@
         # BUG: hash_char "#" is trouble some in LaTeX.
         # mbox and other environment do not like the '#'.
         hash_char = '\\#'
-
         if node.has_key('refuri'):
-            href = node['refuri']
+            href = node['refuri'].replace('#',hash_char)
         elif node.has_key('refid'):
             href = hash_char + node['refid']
         elif node.has_key('refname'):
             href = hash_char + self.document.nameids[node['refname']]
+        else:
+            raise AssertionError('Unknown reference.')
         self.body.append('\\href{%s}{' % href)
 
     def depart_reference(self, node):
@@ -1250,11 +1404,18 @@
     def depart_row(self, node):
         self.context.pop()  # remove cell counter
         self.body.append(' \\\\ \\hline\n')
+        # BUG if multirow cells \cline{x-y}
 
     def visit_section(self, node):
         self.section_level += 1
+        # Initialize counter for potential subsections:
+        self._section_number.append(0)
+        # Counter for this section's level (initialized by parent section):
+        self._section_number[self.section_level - 1] += 1
 
     def depart_section(self, node):
+        # Remove counter for potential subsections:
+        self._section_number.pop()
         self.section_level -= 1
 
     def visit_sidebar(self, node):
@@ -1292,9 +1453,11 @@
 
     def visit_strong(self, node):
         self.body.append('\\textbf{')
+        self.literal_block_stack.append('\\textbf{')
 
     def depart_strong(self, node):
         self.body.append('}')
+        self.literal_block_stack.pop()
 
     def visit_substitution_definition(self, node):
         raise nodes.SkipNode
@@ -1328,13 +1491,20 @@
         Return column specification for longtable.
 
         Assumes reST line length being 80 characters.
+        Table width is hairy.
+
+        === ===
+        ABC DEF
+        === ===
+
+        usually gets to narrow, therefore we add 1 (fiddlefactor).
         """
         width = 80
 
         total_width = 0.0
         # first see if we get too wide.
         for node in self.colspecs:
-            colwidth = float(node['colwidth']) / width
+            colwidth = float(node['colwidth']+1) / width
             total_width += colwidth
         # donot make it full linewidth
         factor = 0.93
@@ -1343,8 +1513,8 @@
 
         latex_table_spec = ""
         for node in self.colspecs:
-            colwidth = factor * float(node['colwidth']) / width
-            latex_table_spec += "|p{%.2f\\locallinewidth}" % colwidth
+            colwidth = factor * float(node['colwidth']+1) / width
+            latex_table_spec += "|p{%.2f\\locallinewidth}" % (colwidth+0.005)
         self.colspecs = []
         return latex_table_spec+"|"
 
@@ -1369,6 +1539,9 @@
     def table_preamble(self):
         if self.use_longtable:
             self.body.append('{%s}\n' % self.get_colspecs())
+            if self.table_caption:
+                self.body.append('\\caption{%s}\\\\\n' % self.table_caption)
+                self.table_caption = None
         else:
             if self.context[-1] != 'table_sentinel':
                 self.body.append('{%s}' % ('|X' * self.context.pop() + '|'))
@@ -1476,6 +1649,10 @@
         elif isinstance(node.parent, nodes.sidebar):
             self.body.append('\\textbf{\\large ')
             self.context.append('}\n\\smallskip\n')
+        elif isinstance(node.parent, nodes.table):
+            # caption must be written after column spec
+            self.table_caption = node.astext()
+            raise nodes.SkipNode
         elif self.section_level == 0:
             # document title
             self.title = self.encode(node.astext())
@@ -1487,21 +1664,15 @@
             self.body.append('%' + '_' * 75)
             self.body.append('\n\n')
             self.bookmark(node)
-            # section_level 0 is title and handled above.
-            # BUG: latex has no deeper sections (actually paragrah is no section either).
+
             if self.use_latex_toc:
                 section_star = ""
             else:
                 section_star = "*"
-            if (self.section_level<=3):  # 1,2,3
-                self.body.append('\\%ssection%s{' % ('sub'*(self.section_level-1),section_star))
-            elif (self.section_level==4):
-                #self.body.append('\\paragraph*{')
-                self.body.append('\\subsubsection%s{' % (section_star))
-            else:
-                #self.body.append('\\subparagraph*{')
-                self.body.append('\\subsubsection%s{' % (section_star))
-            # BUG: self.body.append( '\\label{%s}\n' % name)
+
+            section_name = self.d_class.section(self.section_level)
+            self.body.append('\\%s%s{' % (section_name, section_star))
+
             self.context.append('}\n')
 
     def depart_title(self, node):


=== Zope/lib/python/docutils/writers/pep_html.py 1.2.10.3 => 1.2.10.3.8.1 ===
--- Zope/lib/python/docutils/writers/pep_html.py:1.2.10.3	Sun Nov 30 11:05:26 2003
+++ Zope/lib/python/docutils/writers/pep_html.py	Wed May 12 15:57:57 2004
@@ -88,15 +88,6 @@
 
 class HTMLTranslator(html4css1.HTMLTranslator):
 
-    def get_stylesheet_reference(self, relative_to=None):
-        settings = self.settings
-        if relative_to == None:
-            relative_to = settings._destination
-        if settings.stylesheet_path:
-            return utils.relative_path(relative_to, settings.stylesheet_path)
-        else:
-            return settings.stylesheet
-
     def depart_field_list(self, node):
         html4css1.HTMLTranslator.depart_field_list(self, node)
         if node.get('class') == 'rfc2822':


=== Zope/lib/python/docutils/writers/pseudoxml.py 1.2.10.3 => 1.2.10.3.8.1 ===




More information about the Zope-Checkins mailing list