buildframework/helium/external/python/lib/common/docutils-0.5-py2.5.egg/docutils/writers/html4css1/__init__.py
author wbernard
Wed, 23 Dec 2009 19:29:07 +0200
changeset 179 d8ac696cc51f
permissions -rw-r--r--
helium_7.0-r14027
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
179
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     1
# $Id: __init__.py 5314 2007-07-05 12:45:43Z wiemann $
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     2
# Author: David Goodger <goodger@python.org>
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     3
# Copyright: This module has been placed in the public domain.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     4
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     5
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     6
Simple HyperText Markup Language document tree Writer.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     7
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     8
The output conforms to the XHTML version 1.0 Transitional DTD
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
     9
(*almost* strict).  The output contains a minimum of formatting
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    10
information.  The cascading style sheet "html4css1.css" is required
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    11
for proper viewing with a modern graphical browser.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    12
"""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    13
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    14
__docformat__ = 'reStructuredText'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    15
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    16
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    17
import sys
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    18
import os
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    19
import os.path
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    20
import time
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    21
import re
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    22
from types import ListType
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    23
try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    24
    import Image                        # check for the Python Imaging Library
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    25
except ImportError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    26
    Image = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    27
import docutils
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    28
from docutils import frontend, nodes, utils, writers, languages
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    29
from docutils.transforms import writer_aux
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    30
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    31
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    32
class Writer(writers.Writer):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    33
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    34
    supported = ('html', 'html4css1', 'xhtml')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    35
    """Formats this writer supports."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    36
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    37
    default_stylesheet = 'html4css1.css'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    38
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    39
    default_stylesheet_path = utils.relative_path(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    40
        os.path.join(os.getcwd(), 'dummy'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    41
        os.path.join(os.path.dirname(__file__), default_stylesheet))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    42
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    43
    default_template = 'template.txt'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    44
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    45
    default_template_path = utils.relative_path(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    46
        os.path.join(os.getcwd(), 'dummy'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    47
        os.path.join(os.path.dirname(__file__), default_template))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    48
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    49
    settings_spec = (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    50
        'HTML-Specific Options',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    51
        None,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    52
        (('Specify the template file (UTF-8 encoded).  Default is "%s".'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    53
          % default_template_path,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    54
          ['--template'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    55
          {'default': default_template_path, 'metavar': '<file>'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    56
        ('Specify a stylesheet URL, used verbatim.  Overrides '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    57
          '--stylesheet-path.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    58
          ['--stylesheet'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    59
          {'metavar': '<URL>', 'overrides': 'stylesheet_path'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    60
         ('Specify a stylesheet file, relative to the current working '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    61
          'directory.  The path is adjusted relative to the output HTML '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    62
          'file.  Overrides --stylesheet.  Default: "%s"'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    63
          % default_stylesheet_path,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    64
          ['--stylesheet-path'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    65
          {'metavar': '<file>', 'overrides': 'stylesheet',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    66
           'default': default_stylesheet_path}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    67
         ('Embed the stylesheet in the output HTML file.  The stylesheet '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    68
          'file must be accessible during processing (--stylesheet-path is '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    69
          'recommended).  This is the default.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    70
          ['--embed-stylesheet'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    71
          {'default': 1, 'action': 'store_true',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    72
           'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    73
         ('Link to the stylesheet in the output HTML file.  Default: '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    74
          'embed the stylesheet, do not link to it.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    75
          ['--link-stylesheet'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    76
          {'dest': 'embed_stylesheet', 'action': 'store_false'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    77
         ('Specify the initial header level.  Default is 1 for "<h1>".  '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    78
          'Does not affect document title & subtitle (see --no-doc-title).',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    79
          ['--initial-header-level'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    80
          {'choices': '1 2 3 4 5 6'.split(), 'default': '1',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    81
           'metavar': '<level>'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    82
         ('Specify the maximum width (in characters) for one-column field '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    83
          'names.  Longer field names will span an entire row of the table '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    84
          'used to render the field list.  Default is 14 characters.  '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    85
          'Use 0 for "no limit".',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    86
          ['--field-name-limit'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    87
          {'default': 14, 'metavar': '<level>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    88
           'validator': frontend.validate_nonnegative_int}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    89
         ('Specify the maximum width (in characters) for options in option '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    90
          'lists.  Longer options will span an entire row of the table used '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    91
          'to render the option list.  Default is 14 characters.  '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    92
          'Use 0 for "no limit".',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    93
          ['--option-limit'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    94
          {'default': 14, 'metavar': '<level>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    95
           'validator': frontend.validate_nonnegative_int}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    96
         ('Format for footnote references: one of "superscript" or '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    97
          '"brackets".  Default is "brackets".',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    98
          ['--footnote-references'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
    99
          {'choices': ['superscript', 'brackets'], 'default': 'brackets',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   100
           'metavar': '<format>',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   101
           'overrides': 'trim_footnote_reference_space'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   102
         ('Format for block quote attributions: one of "dash" (em-dash '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   103
          'prefix), "parentheses"/"parens", or "none".  Default is "dash".',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   104
          ['--attribution'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   105
          {'choices': ['dash', 'parentheses', 'parens', 'none'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   106
           'default': 'dash', 'metavar': '<format>'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   107
         ('Remove extra vertical whitespace between items of "simple" bullet '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   108
          'lists and enumerated lists.  Default: enabled.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   109
          ['--compact-lists'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   110
          {'default': 1, 'action': 'store_true',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   111
           'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   112
         ('Disable compact simple bullet and enumerated lists.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   113
          ['--no-compact-lists'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   114
          {'dest': 'compact_lists', 'action': 'store_false'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   115
         ('Remove extra vertical whitespace between items of simple field '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   116
          'lists.  Default: enabled.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   117
          ['--compact-field-lists'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   118
          {'default': 1, 'action': 'store_true',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   119
           'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   120
         ('Disable compact simple field lists.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   121
          ['--no-compact-field-lists'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   122
          {'dest': 'compact_field_lists', 'action': 'store_false'}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   123
         ('Omit the XML declaration.  Use with caution.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   124
          ['--no-xml-declaration'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   125
          {'dest': 'xml_declaration', 'default': 1, 'action': 'store_false',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   126
           'validator': frontend.validate_boolean}),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   127
         ('Obfuscate email addresses to confuse harvesters while still '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   128
          'keeping email links usable with standards-compliant browsers.',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   129
          ['--cloak-email-addresses'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   130
          {'action': 'store_true', 'validator': frontend.validate_boolean}),))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   131
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   132
    settings_defaults = {'output_encoding_error_handler': 'xmlcharrefreplace'}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   133
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   134
    relative_path_settings = ('stylesheet_path',)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   135
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   136
    config_section = 'html4css1 writer'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   137
    config_section_dependencies = ('writers',)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   138
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   139
    visitor_attributes = (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   140
        'head_prefix', 'head', 'stylesheet', 'body_prefix',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   141
        'body_pre_docinfo', 'docinfo', 'body', 'body_suffix',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   142
        'title', 'subtitle', 'header', 'footer', 'meta', 'fragment',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   143
        'html_prolog', 'html_head', 'html_title', 'html_subtitle',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   144
        'html_body')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   145
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   146
    def get_transforms(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   147
        return writers.Writer.get_transforms(self) + [writer_aux.Admonitions]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   148
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   149
    def __init__(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   150
        writers.Writer.__init__(self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   151
        self.translator_class = HTMLTranslator
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   152
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   153
    def translate(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   154
        self.visitor = visitor = self.translator_class(self.document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   155
        self.document.walkabout(visitor)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   156
        for attr in self.visitor_attributes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   157
            setattr(self, attr, getattr(visitor, attr))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   158
        self.output = self.apply_template()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   159
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   160
    def apply_template(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   161
        template_file = open(self.document.settings.template)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   162
        template = unicode(template_file.read(), 'utf-8')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   163
        template_file.close()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   164
        subs = self.interpolation_dict()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   165
        return template % subs
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   166
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   167
    def interpolation_dict(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   168
        subs = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   169
        settings = self.document.settings
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   170
        for attr in self.visitor_attributes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   171
            subs[attr] = ''.join(getattr(self, attr)).rstrip('\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   172
        subs['encoding'] = settings.output_encoding
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   173
        subs['version'] = docutils.__version__
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   174
        return subs
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   175
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   176
    def assemble_parts(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   177
        writers.Writer.assemble_parts(self)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   178
        for part in self.visitor_attributes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   179
            self.parts[part] = ''.join(getattr(self, part))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   180
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   181
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   182
class HTMLTranslator(nodes.NodeVisitor):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   183
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   184
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   185
    This HTML writer has been optimized to produce visually compact
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   186
    lists (less vertical whitespace).  HTML's mixed content models
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   187
    allow list items to contain "<li><p>body elements</p></li>" or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   188
    "<li>just text</li>" or even "<li>text<p>and body
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   189
    elements</p>combined</li>", each with different effects.  It would
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   190
    be best to stick with strict body elements in list items, but they
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   191
    affect vertical spacing in browsers (although they really
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   192
    shouldn't).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   193
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   194
    Here is an outline of the optimization:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   195
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   196
    - Check for and omit <p> tags in "simple" lists: list items
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   197
      contain either a single paragraph, a nested simple list, or a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   198
      paragraph followed by a nested simple list.  This means that
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   199
      this list can be compact:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   200
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   201
          - Item 1.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   202
          - Item 2.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   203
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   204
      But this list cannot be compact:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   205
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   206
          - Item 1.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   207
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   208
            This second paragraph forces space between list items.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   209
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   210
          - Item 2.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   211
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   212
    - In non-list contexts, omit <p> tags on a paragraph if that
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   213
      paragraph is the only child of its parent (footnotes & citations
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   214
      are allowed a label first).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   215
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   216
    - Regardless of the above, in definitions, table cells, field bodies,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   217
      option descriptions, and list items, mark the first child with
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   218
      'class="first"' and the last child with 'class="last"'.  The stylesheet
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   219
      sets the margins (top & bottom respectively) to 0 for these elements.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   220
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   221
    The ``no_compact_lists`` setting (``--no-compact-lists`` command-line
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   222
    option) disables list whitespace optimization.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   223
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   224
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   225
    xml_declaration = '<?xml version="1.0" encoding="%s" ?>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   226
    doctype = (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   227
        '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   228
        ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   229
    head_prefix_template = ('<html xmlns="http://www.w3.org/1999/xhtml"'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   230
                            ' xml:lang="%s" lang="%s">\n<head>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   231
    content_type = ('<meta http-equiv="Content-Type"'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   232
                    ' content="text/html; charset=%s" />\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   233
    generator = ('<meta name="generator" content="Docutils %s: '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   234
                 'http://docutils.sourceforge.net/" />\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   235
    stylesheet_link = '<link rel="stylesheet" href="%s" type="text/css" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   236
    embedded_stylesheet = '<style type="text/css">\n\n%s\n</style>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   237
    words_and_spaces = re.compile(r'\S+| +|\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   238
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   239
    def __init__(self, document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   240
        nodes.NodeVisitor.__init__(self, document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   241
        self.settings = settings = document.settings
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   242
        lcode = settings.language_code
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   243
        self.language = languages.get_language(lcode)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   244
        self.meta = [self.content_type % settings.output_encoding,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   245
                     self.generator % docutils.__version__]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   246
        self.head_prefix = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   247
        self.html_prolog = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   248
        if settings.xml_declaration:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   249
            self.head_prefix.append(self.xml_declaration
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   250
                                    % settings.output_encoding)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   251
            # encoding not interpolated:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   252
            self.html_prolog.append(self.xml_declaration)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   253
        self.head_prefix.extend([self.doctype,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   254
                                 self.head_prefix_template % (lcode, lcode)])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   255
        self.html_prolog.append(self.doctype)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   256
        self.head = self.meta[:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   257
        stylesheet = utils.get_stylesheet_reference(settings)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   258
        self.stylesheet = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   259
        if stylesheet:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   260
            if settings.embed_stylesheet:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   261
                stylesheet = utils.get_stylesheet_reference(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   262
                    settings, os.path.join(os.getcwd(), 'dummy'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   263
                settings.record_dependencies.add(stylesheet)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   264
                stylesheet_text = open(stylesheet).read()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   265
                self.stylesheet = [self.embedded_stylesheet % stylesheet_text]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   266
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   267
                self.stylesheet = [self.stylesheet_link
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   268
                                   % self.encode(stylesheet)]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   269
        self.body_prefix = ['</head>\n<body>\n']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   270
        # document title, subtitle display
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   271
        self.body_pre_docinfo = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   272
        # author, date, etc.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   273
        self.docinfo = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   274
        self.body = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   275
        self.fragment = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   276
        self.body_suffix = ['</body>\n</html>\n']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   277
        self.section_level = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   278
        self.initial_header_level = int(settings.initial_header_level)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   279
        # A heterogenous stack used in conjunction with the tree traversal.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   280
        # Make sure that the pops correspond to the pushes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   281
        self.context = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   282
        self.topic_classes = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   283
        self.colspecs = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   284
        self.compact_p = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   285
        self.compact_simple = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   286
        self.compact_field_list = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   287
        self.in_docinfo = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   288
        self.in_sidebar = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   289
        self.title = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   290
        self.subtitle = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   291
        self.header = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   292
        self.footer = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   293
        self.html_head = [self.content_type] # charset not interpolated
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   294
        self.html_title = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   295
        self.html_subtitle = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   296
        self.html_body = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   297
        self.in_document_title = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   298
        self.in_mailto = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   299
        self.author_in_authors = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   300
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   301
    def astext(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   302
        return ''.join(self.head_prefix + self.head
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   303
                       + self.stylesheet + self.body_prefix
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   304
                       + self.body_pre_docinfo + self.docinfo
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   305
                       + self.body + self.body_suffix)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   306
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   307
    def encode(self, text):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   308
        """Encode special characters in `text` & return."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   309
        # @@@ A codec to do these and all other HTML entities would be nice.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   310
        text = text.replace("&", "&amp;")
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   311
        text = text.replace("<", "&lt;")
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   312
        text = text.replace('"', "&quot;")
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   313
        text = text.replace(">", "&gt;")
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   314
        text = text.replace("@", "&#64;") # may thwart some address harvesters
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   315
        # Replace the non-breaking space character with the HTML entity:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   316
        text = text.replace(u'\u00a0', "&nbsp;")
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   317
        return text
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   318
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   319
    def cloak_mailto(self, uri):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   320
        """Try to hide a mailto: URL from harvesters."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   321
        # Encode "@" using a URL octet reference (see RFC 1738).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   322
        # Further cloaking with HTML entities will be done in the
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   323
        # `attval` function.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   324
        return uri.replace('@', '%40')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   325
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   326
    def cloak_email(self, addr):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   327
        """Try to hide the link text of a email link from harversters."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   328
        # Surround at-signs and periods with <span> tags.  ("@" has
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   329
        # already been encoded to "&#64;" by the `encode` method.)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   330
        addr = addr.replace('&#64;', '<span>&#64;</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   331
        addr = addr.replace('.', '<span>&#46;</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   332
        return addr
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   333
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   334
    def attval(self, text,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   335
               whitespace=re.compile('[\n\r\t\v\f]')):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   336
        """Cleanse, HTML encode, and return attribute value text."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   337
        encoded = self.encode(whitespace.sub(' ', text))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   338
        if self.in_mailto and self.settings.cloak_email_addresses:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   339
            # Cloak at-signs ("%40") and periods with HTML entities.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   340
            encoded = encoded.replace('%40', '&#37;&#52;&#48;')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   341
            encoded = encoded.replace('.', '&#46;')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   342
        return encoded
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   343
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   344
    def starttag(self, node, tagname, suffix='\n', empty=0, **attributes):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   345
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   346
        Construct and return a start tag given a node (id & class attributes
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   347
        are extracted), tag name, and optional attributes.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   348
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   349
        tagname = tagname.lower()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   350
        prefix = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   351
        atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   352
        ids = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   353
        for (name, value) in attributes.items():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   354
            atts[name.lower()] = value
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   355
        classes = node.get('classes', [])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   356
        if atts.has_key('class'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   357
            classes.append(atts['class'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   358
        if classes:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   359
            atts['class'] = ' '.join(classes)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   360
        assert not atts.has_key('id')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   361
        ids.extend(node.get('ids', []))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   362
        if atts.has_key('ids'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   363
            ids.extend(atts['ids'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   364
            del atts['ids']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   365
        if ids:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   366
            atts['id'] = ids[0]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   367
            for id in ids[1:]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   368
                # Add empty "span" elements for additional IDs.  Note
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   369
                # that we cannot use empty "a" elements because there
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   370
                # may be targets inside of references, but nested "a"
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   371
                # elements aren't allowed in XHTML (even if they do
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   372
                # not all have a "href" attribute).
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   373
                if empty:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   374
                    # Empty tag.  Insert target right in front of element.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   375
                    prefix.append('<span id="%s"></span>' % id)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   376
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   377
                    # Non-empty tag.  Place the auxiliary <span> tag
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   378
                    # *inside* the element, as the first child.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   379
                    suffix += '<span id="%s"></span>' % id
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   380
        attlist = atts.items()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   381
        attlist.sort()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   382
        parts = [tagname]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   383
        for name, value in attlist:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   384
            # value=None was used for boolean attributes without
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   385
            # value, but this isn't supported by XHTML.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   386
            assert value is not None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   387
            if isinstance(value, ListType):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   388
                values = [unicode(v) for v in value]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   389
                parts.append('%s="%s"' % (name.lower(),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   390
                                          self.attval(' '.join(values))))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   391
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   392
                parts.append('%s="%s"' % (name.lower(),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   393
                                          self.attval(unicode(value))))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   394
        if empty:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   395
            infix = ' /'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   396
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   397
            infix = ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   398
        return ''.join(prefix) + '<%s%s>' % (' '.join(parts), infix) + suffix
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   399
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   400
    def emptytag(self, node, tagname, suffix='\n', **attributes):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   401
        """Construct and return an XML-compatible empty tag."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   402
        return self.starttag(node, tagname, suffix, empty=1, **attributes)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   403
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   404
    def set_class_on_child(self, node, class_, index=0):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   405
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   406
        Set class `class_` on the visible child no. index of `node`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   407
        Do nothing if node has fewer children than `index`.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   408
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   409
        children = [n for n in node if not isinstance(n, nodes.Invisible)]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   410
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   411
            child = children[index]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   412
        except IndexError:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   413
            return
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   414
        child['classes'].append(class_)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   415
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   416
    def set_first_last(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   417
        self.set_class_on_child(node, 'first', 0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   418
        self.set_class_on_child(node, 'last', -1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   419
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   420
    def visit_Text(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   421
        text = node.astext()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   422
        encoded = self.encode(text)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   423
        if self.in_mailto and self.settings.cloak_email_addresses:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   424
            encoded = self.cloak_email(encoded)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   425
        self.body.append(encoded)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   426
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   427
    def depart_Text(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   428
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   429
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   430
    def visit_abbreviation(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   431
        # @@@ implementation incomplete ("title" attribute)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   432
        self.body.append(self.starttag(node, 'abbr', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   433
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   434
    def depart_abbreviation(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   435
        self.body.append('</abbr>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   436
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   437
    def visit_acronym(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   438
        # @@@ implementation incomplete ("title" attribute)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   439
        self.body.append(self.starttag(node, 'acronym', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   440
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   441
    def depart_acronym(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   442
        self.body.append('</acronym>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   443
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   444
    def visit_address(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   445
        self.visit_docinfo_item(node, 'address', meta=None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   446
        self.body.append(self.starttag(node, 'pre', CLASS='address'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   447
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   448
    def depart_address(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   449
        self.body.append('\n</pre>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   450
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   451
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   452
    def visit_admonition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   453
        self.body.append(self.starttag(node, 'div'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   454
        self.set_first_last(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   455
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   456
    def depart_admonition(self, node=None):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   457
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   458
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   459
    attribution_formats = {'dash': ('&mdash;', ''),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   460
                           'parentheses': ('(', ')'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   461
                           'parens': ('(', ')'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   462
                           'none': ('', '')}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   463
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   464
    def visit_attribution(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   465
        prefix, suffix = self.attribution_formats[self.settings.attribution]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   466
        self.context.append(suffix)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   467
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   468
            self.starttag(node, 'p', prefix, CLASS='attribution'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   469
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   470
    def depart_attribution(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   471
        self.body.append(self.context.pop() + '</p>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   472
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   473
    def visit_author(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   474
        if isinstance(node.parent, nodes.authors):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   475
            if self.author_in_authors:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   476
                self.body.append('\n<br />')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   477
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   478
            self.visit_docinfo_item(node, 'author')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   479
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   480
    def depart_author(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   481
        if isinstance(node.parent, nodes.authors):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   482
            self.author_in_authors += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   483
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   484
            self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   485
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   486
    def visit_authors(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   487
        self.visit_docinfo_item(node, 'authors')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   488
        self.author_in_authors = 0      # initialize counter
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   489
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   490
    def depart_authors(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   491
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   492
        self.author_in_authors = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   493
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   494
    def visit_block_quote(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   495
        self.body.append(self.starttag(node, 'blockquote'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   496
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   497
    def depart_block_quote(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   498
        self.body.append('</blockquote>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   499
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   500
    def check_simple_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   501
        """Check for a simple list that can be rendered compactly."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   502
        visitor = SimpleListChecker(self.document)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   503
        try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   504
            node.walk(visitor)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   505
        except nodes.NodeFound:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   506
            return None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   507
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   508
            return 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   509
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   510
    def is_compactable(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   511
        return ('compact' in node['classes']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   512
                or (self.settings.compact_lists
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   513
                    and 'open' not in node['classes']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   514
                    and (self.compact_simple
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   515
                         or self.topic_classes == ['contents']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   516
                         or self.check_simple_list(node))))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   517
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   518
    def visit_bullet_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   519
        atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   520
        old_compact_simple = self.compact_simple
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   521
        self.context.append((self.compact_simple, self.compact_p))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   522
        self.compact_p = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   523
        self.compact_simple = self.is_compactable(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   524
        if self.compact_simple and not old_compact_simple:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   525
            atts['class'] = 'simple'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   526
        self.body.append(self.starttag(node, 'ul', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   527
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   528
    def depart_bullet_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   529
        self.compact_simple, self.compact_p = self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   530
        self.body.append('</ul>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   531
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   532
    def visit_caption(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   533
        self.body.append(self.starttag(node, 'p', '', CLASS='caption'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   534
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   535
    def depart_caption(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   536
        self.body.append('</p>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   537
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   538
    def visit_citation(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   539
        self.body.append(self.starttag(node, 'table',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   540
                                       CLASS='docutils citation',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   541
                                       frame="void", rules="none"))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   542
        self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   543
                         '<tbody valign="top">\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   544
                         '<tr>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   545
        self.footnote_backrefs(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   546
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   547
    def depart_citation(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   548
        self.body.append('</td></tr>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   549
                         '</tbody>\n</table>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   550
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   551
    def visit_citation_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   552
        href = '#' + node['refid']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   553
        self.body.append(self.starttag(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   554
            node, 'a', '[', CLASS='citation-reference', href=href))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   555
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   556
    def depart_citation_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   557
        self.body.append(']</a>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   558
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   559
    def visit_classifier(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   560
        self.body.append(' <span class="classifier-delimiter">:</span> ')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   561
        self.body.append(self.starttag(node, 'span', '', CLASS='classifier'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   562
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   563
    def depart_classifier(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   564
        self.body.append('</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   565
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   566
    def visit_colspec(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   567
        self.colspecs.append(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   568
        # "stubs" list is an attribute of the tgroup element:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   569
        node.parent.stubs.append(node.attributes.get('stub'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   570
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   571
    def depart_colspec(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   572
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   573
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   574
    def write_colspecs(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   575
        width = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   576
        for node in self.colspecs:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   577
            width += node['colwidth']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   578
        for node in self.colspecs:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   579
            colwidth = int(node['colwidth'] * 100.0 / width + 0.5)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   580
            self.body.append(self.emptytag(node, 'col',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   581
                                           width='%i%%' % colwidth))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   582
        self.colspecs = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   583
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   584
    def visit_comment(self, node,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   585
                      sub=re.compile('-(?=-)').sub):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   586
        """Escape double-dashes in comment text."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   587
        self.body.append('<!-- %s -->\n' % sub('- ', node.astext()))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   588
        # Content already processed:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   589
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   590
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   591
    def visit_compound(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   592
        self.body.append(self.starttag(node, 'div', CLASS='compound'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   593
        if len(node) > 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   594
            node[0]['classes'].append('compound-first')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   595
            node[-1]['classes'].append('compound-last')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   596
            for child in node[1:-1]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   597
                child['classes'].append('compound-middle')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   598
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   599
    def depart_compound(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   600
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   601
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   602
    def visit_container(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   603
        self.body.append(self.starttag(node, 'div', CLASS='container'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   604
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   605
    def depart_container(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   606
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   607
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   608
    def visit_contact(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   609
        self.visit_docinfo_item(node, 'contact', meta=None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   610
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   611
    def depart_contact(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   612
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   613
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   614
    def visit_copyright(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   615
        self.visit_docinfo_item(node, 'copyright')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   616
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   617
    def depart_copyright(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   618
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   619
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   620
    def visit_date(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   621
        self.visit_docinfo_item(node, 'date')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   622
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   623
    def depart_date(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   624
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   625
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   626
    def visit_decoration(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   627
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   628
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   629
    def depart_decoration(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   630
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   631
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   632
    def visit_definition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   633
        self.body.append('</dt>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   634
        self.body.append(self.starttag(node, 'dd', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   635
        self.set_first_last(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   636
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   637
    def depart_definition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   638
        self.body.append('</dd>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   639
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   640
    def visit_definition_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   641
        self.body.append(self.starttag(node, 'dl', CLASS='docutils'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   642
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   643
    def depart_definition_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   644
        self.body.append('</dl>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   645
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   646
    def visit_definition_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   647
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   648
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   649
    def depart_definition_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   650
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   651
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   652
    def visit_description(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   653
        self.body.append(self.starttag(node, 'td', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   654
        self.set_first_last(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   655
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   656
    def depart_description(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   657
        self.body.append('</td>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   658
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   659
    def visit_docinfo(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   660
        self.context.append(len(self.body))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   661
        self.body.append(self.starttag(node, 'table',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   662
                                       CLASS='docinfo',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   663
                                       frame="void", rules="none"))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   664
        self.body.append('<col class="docinfo-name" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   665
                         '<col class="docinfo-content" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   666
                         '<tbody valign="top">\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   667
        self.in_docinfo = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   668
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   669
    def depart_docinfo(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   670
        self.body.append('</tbody>\n</table>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   671
        self.in_docinfo = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   672
        start = self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   673
        self.docinfo = self.body[start:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   674
        self.body = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   675
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   676
    def visit_docinfo_item(self, node, name, meta=1):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   677
        if meta:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   678
            meta_tag = '<meta name="%s" content="%s" />\n' \
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   679
                       % (name, self.attval(node.astext()))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   680
            self.add_meta(meta_tag)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   681
        self.body.append(self.starttag(node, 'tr', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   682
        self.body.append('<th class="docinfo-name">%s:</th>\n<td>'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   683
                         % self.language.labels[name])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   684
        if len(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   685
            if isinstance(node[0], nodes.Element):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   686
                node[0]['classes'].append('first')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   687
            if isinstance(node[-1], nodes.Element):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   688
                node[-1]['classes'].append('last')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   689
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   690
    def depart_docinfo_item(self):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   691
        self.body.append('</td></tr>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   692
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   693
    def visit_doctest_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   694
        self.body.append(self.starttag(node, 'pre', CLASS='doctest-block'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   695
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   696
    def depart_doctest_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   697
        self.body.append('\n</pre>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   698
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   699
    def visit_document(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   700
        self.head.append('<title>%s</title>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   701
                         % self.encode(node.get('title', '')))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   702
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   703
    def depart_document(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   704
        self.fragment.extend(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   705
        self.body_prefix.append(self.starttag(node, 'div', CLASS='document'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   706
        self.body_suffix.insert(0, '</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   707
        # skip content-type meta tag with interpolated charset value:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   708
        self.html_head.extend(self.head[1:])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   709
        self.html_body.extend(self.body_prefix[1:] + self.body_pre_docinfo
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   710
                              + self.docinfo + self.body
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   711
                              + self.body_suffix[:-1])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   712
        assert not self.context, 'len(context) = %s' % len(self.context)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   713
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   714
    def visit_emphasis(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   715
        self.body.append('<em>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   716
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   717
    def depart_emphasis(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   718
        self.body.append('</em>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   719
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   720
    def visit_entry(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   721
        atts = {'class': []}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   722
        if isinstance(node.parent.parent, nodes.thead):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   723
            atts['class'].append('head')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   724
        if node.parent.parent.parent.stubs[node.parent.column]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   725
            # "stubs" list is an attribute of the tgroup element
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   726
            atts['class'].append('stub')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   727
        if atts['class']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   728
            tagname = 'th'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   729
            atts['class'] = ' '.join(atts['class'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   730
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   731
            tagname = 'td'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   732
            del atts['class']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   733
        node.parent.column += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   734
        if node.has_key('morerows'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   735
            atts['rowspan'] = node['morerows'] + 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   736
        if node.has_key('morecols'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   737
            atts['colspan'] = node['morecols'] + 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   738
            node.parent.column += node['morecols']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   739
        self.body.append(self.starttag(node, tagname, '', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   740
        self.context.append('</%s>\n' % tagname.lower())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   741
        if len(node) == 0:              # empty cell
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   742
            self.body.append('&nbsp;')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   743
        self.set_first_last(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   744
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   745
    def depart_entry(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   746
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   747
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   748
    def visit_enumerated_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   749
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   750
        The 'start' attribute does not conform to HTML 4.01's strict.dtd, but
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   751
        CSS1 doesn't help. CSS2 isn't widely enough supported yet to be
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   752
        usable.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   753
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   754
        atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   755
        if node.has_key('start'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   756
            atts['start'] = node['start']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   757
        if node.has_key('enumtype'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   758
            atts['class'] = node['enumtype']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   759
        # @@@ To do: prefix, suffix. How? Change prefix/suffix to a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   760
        # single "format" attribute? Use CSS2?
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   761
        old_compact_simple = self.compact_simple
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   762
        self.context.append((self.compact_simple, self.compact_p))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   763
        self.compact_p = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   764
        self.compact_simple = self.is_compactable(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   765
        if self.compact_simple and not old_compact_simple:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   766
            atts['class'] = (atts.get('class', '') + ' simple').strip()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   767
        self.body.append(self.starttag(node, 'ol', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   768
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   769
    def depart_enumerated_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   770
        self.compact_simple, self.compact_p = self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   771
        self.body.append('</ol>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   772
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   773
    def visit_field(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   774
        self.body.append(self.starttag(node, 'tr', '', CLASS='field'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   775
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   776
    def depart_field(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   777
        self.body.append('</tr>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   778
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   779
    def visit_field_body(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   780
        self.body.append(self.starttag(node, 'td', '', CLASS='field-body'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   781
        self.set_class_on_child(node, 'first', 0)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   782
        field = node.parent
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   783
        if (self.compact_field_list or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   784
            isinstance(field.parent, nodes.docinfo) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   785
            field.parent.index(field) == len(field.parent) - 1):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   786
            # If we are in a compact list, the docinfo, or if this is
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   787
            # the last field of the field list, do not add vertical
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   788
            # space after last element.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   789
            self.set_class_on_child(node, 'last', -1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   790
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   791
    def depart_field_body(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   792
        self.body.append('</td>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   793
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   794
    def visit_field_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   795
        self.context.append((self.compact_field_list, self.compact_p))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   796
        self.compact_p = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   797
        if 'compact' in node['classes']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   798
            self.compact_field_list = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   799
        elif (self.settings.compact_field_lists
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   800
              and 'open' not in node['classes']):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   801
            self.compact_field_list = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   802
        if self.compact_field_list:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   803
            for field in node:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   804
                field_body = field[-1]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   805
                assert isinstance(field_body, nodes.field_body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   806
                children = [n for n in field_body
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   807
                            if not isinstance(n, nodes.Invisible)]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   808
                if not (len(children) == 0 or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   809
                        len(children) == 1 and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   810
                        isinstance(children[0], nodes.paragraph)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   811
                    self.compact_field_list = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   812
                    break
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   813
        self.body.append(self.starttag(node, 'table', frame='void',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   814
                                       rules='none',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   815
                                       CLASS='docutils field-list'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   816
        self.body.append('<col class="field-name" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   817
                         '<col class="field-body" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   818
                         '<tbody valign="top">\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   819
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   820
    def depart_field_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   821
        self.body.append('</tbody>\n</table>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   822
        self.compact_field_list, self.compact_p = self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   823
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   824
    def visit_field_name(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   825
        atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   826
        if self.in_docinfo:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   827
            atts['class'] = 'docinfo-name'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   828
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   829
            atts['class'] = 'field-name'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   830
        if ( self.settings.field_name_limit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   831
             and len(node.astext()) > self.settings.field_name_limit):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   832
            atts['colspan'] = 2
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   833
            self.context.append('</tr>\n<tr><td>&nbsp;</td>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   834
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   835
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   836
        self.body.append(self.starttag(node, 'th', '', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   837
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   838
    def depart_field_name(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   839
        self.body.append(':</th>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   840
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   841
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   842
    def visit_figure(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   843
        atts = {'class': 'figure'}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   844
        if node.get('width'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   845
            atts['style'] = 'width: %spx' % node['width']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   846
        if node.get('align'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   847
            atts['align'] = node['align']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   848
        self.body.append(self.starttag(node, 'div', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   849
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   850
    def depart_figure(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   851
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   852
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   853
    def visit_footer(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   854
        self.context.append(len(self.body))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   855
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   856
    def depart_footer(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   857
        start = self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   858
        footer = [self.starttag(node, 'div', CLASS='footer'),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   859
                  '<hr class="footer" />\n']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   860
        footer.extend(self.body[start:])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   861
        footer.append('\n</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   862
        self.footer.extend(footer)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   863
        self.body_suffix[:0] = footer
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   864
        del self.body[start:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   865
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   866
    def visit_footnote(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   867
        self.body.append(self.starttag(node, 'table',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   868
                                       CLASS='docutils footnote',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   869
                                       frame="void", rules="none"))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   870
        self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   871
                         '<tbody valign="top">\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   872
                         '<tr>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   873
        self.footnote_backrefs(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   874
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   875
    def footnote_backrefs(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   876
        backlinks = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   877
        backrefs = node['backrefs']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   878
        if self.settings.footnote_backlinks and backrefs:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   879
            if len(backrefs) == 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   880
                self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   881
                self.context.append('</a>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   882
                self.context.append('<a class="fn-backref" href="#%s">'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   883
                                    % backrefs[0])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   884
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   885
                i = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   886
                for backref in backrefs:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   887
                    backlinks.append('<a class="fn-backref" href="#%s">%s</a>'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   888
                                     % (backref, i))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   889
                    i += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   890
                self.context.append('<em>(%s)</em> ' % ', '.join(backlinks))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   891
                self.context += ['', '']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   892
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   893
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   894
            self.context += ['', '']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   895
        # If the node does not only consist of a label.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   896
        if len(node) > 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   897
            # If there are preceding backlinks, we do not set class
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   898
            # 'first', because we need to retain the top-margin.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   899
            if not backlinks:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   900
                node[1]['classes'].append('first')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   901
            node[-1]['classes'].append('last')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   902
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   903
    def depart_footnote(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   904
        self.body.append('</td></tr>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   905
                         '</tbody>\n</table>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   906
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   907
    def visit_footnote_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   908
        href = '#' + node['refid']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   909
        format = self.settings.footnote_references
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   910
        if format == 'brackets':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   911
            suffix = '['
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   912
            self.context.append(']')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   913
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   914
            assert format == 'superscript'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   915
            suffix = '<sup>'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   916
            self.context.append('</sup>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   917
        self.body.append(self.starttag(node, 'a', suffix,
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   918
                                       CLASS='footnote-reference', href=href))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   919
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   920
    def depart_footnote_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   921
        self.body.append(self.context.pop() + '</a>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   922
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   923
    def visit_generated(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   924
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   925
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   926
    def depart_generated(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   927
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   928
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   929
    def visit_header(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   930
        self.context.append(len(self.body))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   931
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   932
    def depart_header(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   933
        start = self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   934
        header = [self.starttag(node, 'div', CLASS='header')]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   935
        header.extend(self.body[start:])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   936
        header.append('\n<hr class="header"/>\n</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   937
        self.body_prefix.extend(header)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   938
        self.header.extend(header)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   939
        del self.body[start:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   940
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   941
    def visit_image(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   942
        atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   943
        atts['src'] = node['uri']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   944
        if node.has_key('width'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   945
            atts['width'] = node['width']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   946
        if node.has_key('height'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   947
            atts['height'] = node['height']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   948
        if node.has_key('scale'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   949
            if Image and not (node.has_key('width')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   950
                              and node.has_key('height')):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   951
                try:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   952
                    im = Image.open(str(atts['src']))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   953
                except (IOError, # Source image can't be found or opened
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   954
                        UnicodeError):  # PIL doesn't like Unicode paths.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   955
                    pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   956
                else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   957
                    if not atts.has_key('width'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   958
                        atts['width'] = str(im.size[0])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   959
                    if not atts.has_key('height'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   960
                        atts['height'] = str(im.size[1])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   961
                    del im
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   962
            for att_name in 'width', 'height':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   963
                if atts.has_key(att_name):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   964
                    match = re.match(r'([0-9.]+)(\S*)$', atts[att_name])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   965
                    assert match
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   966
                    atts[att_name] = '%s%s' % (
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   967
                        float(match.group(1)) * (float(node['scale']) / 100),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   968
                        match.group(2))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   969
        style = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   970
        for att_name in 'width', 'height':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   971
            if atts.has_key(att_name):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   972
                if re.match(r'^[0-9.]+$', atts[att_name]):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   973
                    # Interpret unitless values as pixels.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   974
                    atts[att_name] += 'px'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   975
                style.append('%s: %s;' % (att_name, atts[att_name]))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   976
                del atts[att_name]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   977
        if style:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   978
            atts['style'] = ' '.join(style)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   979
        atts['alt'] = node.get('alt', atts['src'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   980
        if (isinstance(node.parent, nodes.TextElement) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   981
            (isinstance(node.parent, nodes.reference) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   982
             not isinstance(node.parent.parent, nodes.TextElement))):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   983
            # Inline context or surrounded by <a>...</a>.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   984
            suffix = ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   985
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   986
            suffix = '\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   987
        if node.has_key('align'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   988
            if node['align'] == 'center':
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   989
                # "align" attribute is set in surrounding "div" element.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   990
                self.body.append('<div align="center" class="align-center">')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   991
                self.context.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   992
                suffix = ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   993
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   994
                # "align" attribute is set in "img" element.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   995
                atts['align'] = node['align']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   996
                self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   997
            atts['class'] = 'align-%s' % node['align']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   998
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
   999
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1000
        self.body.append(self.emptytag(node, 'img', suffix, **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1001
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1002
    def depart_image(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1003
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1004
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1005
    def visit_inline(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1006
        self.body.append(self.starttag(node, 'span', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1007
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1008
    def depart_inline(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1009
        self.body.append('</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1010
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1011
    def visit_label(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1012
        # Context added in footnote_backrefs.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1013
        self.body.append(self.starttag(node, 'td', '%s[' % self.context.pop(),
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1014
                                       CLASS='label'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1015
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1016
    def depart_label(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1017
        # Context added in footnote_backrefs.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1018
        self.body.append(']%s</td><td>%s' % (self.context.pop(), self.context.pop()))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1019
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1020
    def visit_legend(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1021
        self.body.append(self.starttag(node, 'div', CLASS='legend'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1022
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1023
    def depart_legend(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1024
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1025
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1026
    def visit_line(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1027
        self.body.append(self.starttag(node, 'div', suffix='', CLASS='line'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1028
        if not len(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1029
            self.body.append('<br />')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1030
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1031
    def depart_line(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1032
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1033
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1034
    def visit_line_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1035
        self.body.append(self.starttag(node, 'div', CLASS='line-block'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1036
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1037
    def depart_line_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1038
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1039
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1040
    def visit_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1041
        self.body.append(self.starttag(node, 'li', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1042
        if len(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1043
            node[0]['classes'].append('first')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1044
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1045
    def depart_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1046
        self.body.append('</li>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1047
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1048
    def visit_literal(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1049
        """Process text to prevent tokens from wrapping."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1050
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1051
            self.starttag(node, 'tt', '', CLASS='docutils literal'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1052
        text = node.astext()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1053
        for token in self.words_and_spaces.findall(text):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1054
            if token.strip():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1055
                # Protect text like "--an-option" from bad line wrapping:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1056
                self.body.append('<span class="pre">%s</span>'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1057
                                 % self.encode(token))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1058
            elif token in ('\n', ' '):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1059
                # Allow breaks at whitespace:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1060
                self.body.append(token)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1061
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1062
                # Protect runs of multiple spaces; the last space can wrap:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1063
                self.body.append('&nbsp;' * (len(token) - 1) + ' ')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1064
        self.body.append('</tt>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1065
        # Content already processed:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1066
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1067
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1068
    def visit_literal_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1069
        self.body.append(self.starttag(node, 'pre', CLASS='literal-block'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1070
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1071
    def depart_literal_block(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1072
        self.body.append('\n</pre>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1073
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1074
    def visit_meta(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1075
        meta = self.emptytag(node, 'meta', **node.non_default_attributes())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1076
        self.add_meta(meta)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1077
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1078
    def depart_meta(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1079
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1080
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1081
    def add_meta(self, tag):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1082
        self.meta.append(tag)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1083
        self.head.append(tag)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1084
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1085
    def visit_option(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1086
        if self.context[-1]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1087
            self.body.append(', ')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1088
        self.body.append(self.starttag(node, 'span', '', CLASS='option'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1089
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1090
    def depart_option(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1091
        self.body.append('</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1092
        self.context[-1] += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1093
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1094
    def visit_option_argument(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1095
        self.body.append(node.get('delimiter', ' '))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1096
        self.body.append(self.starttag(node, 'var', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1097
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1098
    def depart_option_argument(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1099
        self.body.append('</var>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1100
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1101
    def visit_option_group(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1102
        atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1103
        if ( self.settings.option_limit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1104
             and len(node.astext()) > self.settings.option_limit):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1105
            atts['colspan'] = 2
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1106
            self.context.append('</tr>\n<tr><td>&nbsp;</td>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1107
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1108
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1109
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1110
            self.starttag(node, 'td', CLASS='option-group', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1111
        self.body.append('<kbd>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1112
        self.context.append(0)          # count number of options
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1113
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1114
    def depart_option_group(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1115
        self.context.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1116
        self.body.append('</kbd></td>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1117
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1118
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1119
    def visit_option_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1120
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1121
              self.starttag(node, 'table', CLASS='docutils option-list',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1122
                            frame="void", rules="none"))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1123
        self.body.append('<col class="option" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1124
                         '<col class="description" />\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1125
                         '<tbody valign="top">\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1126
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1127
    def depart_option_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1128
        self.body.append('</tbody>\n</table>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1129
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1130
    def visit_option_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1131
        self.body.append(self.starttag(node, 'tr', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1132
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1133
    def depart_option_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1134
        self.body.append('</tr>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1135
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1136
    def visit_option_string(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1137
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1138
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1139
    def depart_option_string(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1140
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1141
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1142
    def visit_organization(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1143
        self.visit_docinfo_item(node, 'organization')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1144
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1145
    def depart_organization(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1146
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1147
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1148
    def should_be_compact_paragraph(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1149
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1150
        Determine if the <p> tags around paragraph ``node`` can be omitted.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1151
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1152
        if (isinstance(node.parent, nodes.document) or
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1153
            isinstance(node.parent, nodes.compound)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1154
            # Never compact paragraphs in document or compound.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1155
            return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1156
        for key, value in node.attlist():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1157
            if (node.is_not_default(key) and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1158
                not (key == 'classes' and value in
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1159
                     ([], ['first'], ['last'], ['first', 'last']))):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1160
                # Attribute which needs to survive.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1161
                return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1162
        first = isinstance(node.parent[0], nodes.label) # skip label
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1163
        for child in node.parent.children[first:]:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1164
            # only first paragraph can be compact
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1165
            if isinstance(child, nodes.Invisible):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1166
                continue
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1167
            if child is node:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1168
                break
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1169
            return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1170
        parent_length = len([n for n in node.parent if not isinstance(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1171
            n, (nodes.Invisible, nodes.label))])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1172
        if ( self.compact_simple
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1173
             or self.compact_field_list
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1174
             or self.compact_p and parent_length == 1):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1175
            return 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1176
        return 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1177
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1178
    def visit_paragraph(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1179
        if self.should_be_compact_paragraph(node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1180
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1181
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1182
            self.body.append(self.starttag(node, 'p', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1183
            self.context.append('</p>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1184
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1185
    def depart_paragraph(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1186
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1187
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1188
    def visit_problematic(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1189
        if node.hasattr('refid'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1190
            self.body.append('<a href="#%s">' % node['refid'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1191
            self.context.append('</a>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1192
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1193
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1194
        self.body.append(self.starttag(node, 'span', '', CLASS='problematic'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1195
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1196
    def depart_problematic(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1197
        self.body.append('</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1198
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1199
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1200
    def visit_raw(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1201
        if 'html' in node.get('format', '').split():
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1202
            t = isinstance(node.parent, nodes.TextElement) and 'span' or 'div'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1203
            if node['classes']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1204
                self.body.append(self.starttag(node, t, suffix=''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1205
            self.body.append(node.astext())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1206
            if node['classes']:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1207
                self.body.append('</%s>' % t)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1208
        # Keep non-HTML raw text out of output:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1209
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1210
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1211
    def visit_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1212
        atts = {'class': 'reference'}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1213
        if node.has_key('refuri'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1214
            atts['href'] = node['refuri']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1215
            if ( self.settings.cloak_email_addresses
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1216
                 and atts['href'].startswith('mailto:')):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1217
                atts['href'] = self.cloak_mailto(atts['href'])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1218
                self.in_mailto = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1219
            atts['class'] += ' external'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1220
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1221
            assert node.has_key('refid'), \
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1222
                   'References must have "refuri" or "refid" attribute.'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1223
            atts['href'] = '#' + node['refid']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1224
            atts['class'] += ' internal'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1225
        if not isinstance(node.parent, nodes.TextElement):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1226
            assert len(node) == 1 and isinstance(node[0], nodes.image)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1227
            atts['class'] += ' image-reference'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1228
        self.body.append(self.starttag(node, 'a', '', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1229
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1230
    def depart_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1231
        self.body.append('</a>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1232
        if not isinstance(node.parent, nodes.TextElement):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1233
            self.body.append('\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1234
        self.in_mailto = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1235
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1236
    def visit_revision(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1237
        self.visit_docinfo_item(node, 'revision', meta=None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1238
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1239
    def depart_revision(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1240
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1241
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1242
    def visit_row(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1243
        self.body.append(self.starttag(node, 'tr', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1244
        node.column = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1245
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1246
    def depart_row(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1247
        self.body.append('</tr>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1248
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1249
    def visit_rubric(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1250
        self.body.append(self.starttag(node, 'p', '', CLASS='rubric'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1251
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1252
    def depart_rubric(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1253
        self.body.append('</p>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1254
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1255
    def visit_section(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1256
        self.section_level += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1257
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1258
            self.starttag(node, 'div', CLASS='section'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1259
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1260
    def depart_section(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1261
        self.section_level -= 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1262
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1263
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1264
    def visit_sidebar(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1265
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1266
            self.starttag(node, 'div', CLASS='sidebar'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1267
        self.set_first_last(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1268
        self.in_sidebar = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1269
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1270
    def depart_sidebar(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1271
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1272
        self.in_sidebar = None
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1273
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1274
    def visit_status(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1275
        self.visit_docinfo_item(node, 'status', meta=None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1276
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1277
    def depart_status(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1278
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1279
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1280
    def visit_strong(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1281
        self.body.append('<strong>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1282
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1283
    def depart_strong(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1284
        self.body.append('</strong>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1285
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1286
    def visit_subscript(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1287
        self.body.append(self.starttag(node, 'sub', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1288
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1289
    def depart_subscript(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1290
        self.body.append('</sub>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1291
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1292
    def visit_substitution_definition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1293
        """Internal only."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1294
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1295
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1296
    def visit_substitution_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1297
        self.unimplemented_visit(node)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1298
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1299
    def visit_subtitle(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1300
        if isinstance(node.parent, nodes.sidebar):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1301
            self.body.append(self.starttag(node, 'p', '',
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1302
                                           CLASS='sidebar-subtitle'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1303
            self.context.append('</p>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1304
        elif isinstance(node.parent, nodes.document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1305
            self.body.append(self.starttag(node, 'h2', '', CLASS='subtitle'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1306
            self.context.append('</h2>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1307
            self.in_document_title = len(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1308
        elif isinstance(node.parent, nodes.section):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1309
            tag = 'h%s' % (self.section_level + self.initial_header_level - 1)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1310
            self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1311
                self.starttag(node, tag, '', CLASS='section-subtitle') +
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1312
                self.starttag({}, 'span', '', CLASS='section-subtitle'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1313
            self.context.append('</span></%s>\n' % tag)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1314
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1315
    def depart_subtitle(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1316
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1317
        if self.in_document_title:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1318
            self.subtitle = self.body[self.in_document_title:-1]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1319
            self.in_document_title = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1320
            self.body_pre_docinfo.extend(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1321
            self.html_subtitle.extend(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1322
            del self.body[:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1323
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1324
    def visit_superscript(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1325
        self.body.append(self.starttag(node, 'sup', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1326
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1327
    def depart_superscript(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1328
        self.body.append('</sup>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1329
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1330
    def visit_system_message(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1331
        self.body.append(self.starttag(node, 'div', CLASS='system-message'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1332
        self.body.append('<p class="system-message-title">')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1333
        backref_text = ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1334
        if len(node['backrefs']):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1335
            backrefs = node['backrefs']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1336
            if len(backrefs) == 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1337
                backref_text = ('; <em><a href="#%s">backlink</a></em>'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1338
                                % backrefs[0])
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1339
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1340
                i = 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1341
                backlinks = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1342
                for backref in backrefs:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1343
                    backlinks.append('<a href="#%s">%s</a>' % (backref, i))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1344
                    i += 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1345
                backref_text = ('; <em>backlinks: %s</em>'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1346
                                % ', '.join(backlinks))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1347
        if node.hasattr('line'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1348
            line = ', line %s' % node['line']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1349
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1350
            line = ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1351
        self.body.append('System Message: %s/%s '
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1352
                         '(<tt class="docutils">%s</tt>%s)%s</p>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1353
                         % (node['type'], node['level'],
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1354
                            self.encode(node['source']), line, backref_text))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1355
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1356
    def depart_system_message(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1357
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1358
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1359
    def visit_table(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1360
        self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1361
            self.starttag(node, 'table', CLASS='docutils', border="1"))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1362
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1363
    def depart_table(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1364
        self.body.append('</table>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1365
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1366
    def visit_target(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1367
        if not (node.has_key('refuri') or node.has_key('refid')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1368
                or node.has_key('refname')):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1369
            self.body.append(self.starttag(node, 'span', '', CLASS='target'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1370
            self.context.append('</span>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1371
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1372
            self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1373
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1374
    def depart_target(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1375
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1376
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1377
    def visit_tbody(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1378
        self.write_colspecs()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1379
        self.body.append(self.context.pop()) # '</colgroup>\n' or ''
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1380
        self.body.append(self.starttag(node, 'tbody', valign='top'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1381
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1382
    def depart_tbody(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1383
        self.body.append('</tbody>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1384
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1385
    def visit_term(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1386
        self.body.append(self.starttag(node, 'dt', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1387
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1388
    def depart_term(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1389
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1390
        Leave the end tag to `self.visit_definition()`, in case there's a
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1391
        classifier.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1392
        """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1393
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1394
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1395
    def visit_tgroup(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1396
        # Mozilla needs <colgroup>:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1397
        self.body.append(self.starttag(node, 'colgroup'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1398
        # Appended by thead or tbody:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1399
        self.context.append('</colgroup>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1400
        node.stubs = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1401
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1402
    def depart_tgroup(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1403
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1404
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1405
    def visit_thead(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1406
        self.write_colspecs()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1407
        self.body.append(self.context.pop()) # '</colgroup>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1408
        # There may or may not be a <thead>; this is for <tbody> to use:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1409
        self.context.append('')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1410
        self.body.append(self.starttag(node, 'thead', valign='bottom'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1411
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1412
    def depart_thead(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1413
        self.body.append('</thead>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1414
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1415
    def visit_title(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1416
        """Only 6 section levels are supported by HTML."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1417
        check_id = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1418
        close_tag = '</p>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1419
        if isinstance(node.parent, nodes.topic):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1420
            self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1421
                  self.starttag(node, 'p', '', CLASS='topic-title first'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1422
        elif isinstance(node.parent, nodes.sidebar):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1423
            self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1424
                  self.starttag(node, 'p', '', CLASS='sidebar-title'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1425
        elif isinstance(node.parent, nodes.Admonition):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1426
            self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1427
                  self.starttag(node, 'p', '', CLASS='admonition-title'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1428
        elif isinstance(node.parent, nodes.table):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1429
            self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1430
                  self.starttag(node, 'caption', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1431
            close_tag = '</caption>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1432
        elif isinstance(node.parent, nodes.document):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1433
            self.body.append(self.starttag(node, 'h1', '', CLASS='title'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1434
            close_tag = '</h1>\n'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1435
            self.in_document_title = len(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1436
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1437
            assert isinstance(node.parent, nodes.section)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1438
            h_level = self.section_level + self.initial_header_level - 1
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1439
            atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1440
            if (len(node.parent) >= 2 and
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1441
                isinstance(node.parent[1], nodes.subtitle)):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1442
                atts['CLASS'] = 'with-subtitle'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1443
            self.body.append(
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1444
                  self.starttag(node, 'h%s' % h_level, '', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1445
            atts = {}
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1446
            if node.hasattr('refid'):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1447
                atts['class'] = 'toc-backref'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1448
                atts['href'] = '#' + node['refid']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1449
            if atts:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1450
                self.body.append(self.starttag({}, 'a', '', **atts))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1451
                close_tag = '</a></h%s>\n' % (h_level)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1452
            else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1453
                close_tag = '</h%s>\n' % (h_level)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1454
        self.context.append(close_tag)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1455
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1456
    def depart_title(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1457
        self.body.append(self.context.pop())
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1458
        if self.in_document_title:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1459
            self.title = self.body[self.in_document_title:-1]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1460
            self.in_document_title = 0
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1461
            self.body_pre_docinfo.extend(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1462
            self.html_title.extend(self.body)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1463
            del self.body[:]
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1464
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1465
    def visit_title_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1466
        self.body.append(self.starttag(node, 'cite', ''))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1467
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1468
    def depart_title_reference(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1469
        self.body.append('</cite>')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1470
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1471
    def visit_topic(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1472
        self.body.append(self.starttag(node, 'div', CLASS='topic'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1473
        self.topic_classes = node['classes']
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1474
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1475
    def depart_topic(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1476
        self.body.append('</div>\n')
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1477
        self.topic_classes = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1478
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1479
    def visit_transition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1480
        self.body.append(self.emptytag(node, 'hr', CLASS='docutils'))
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1481
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1482
    def depart_transition(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1483
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1484
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1485
    def visit_version(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1486
        self.visit_docinfo_item(node, 'version', meta=None)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1487
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1488
    def depart_version(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1489
        self.depart_docinfo_item()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1490
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1491
    def unimplemented_visit(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1492
        raise NotImplementedError('visiting unimplemented node type: %s'
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1493
                                  % node.__class__.__name__)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1494
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1495
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1496
class SimpleListChecker(nodes.GenericNodeVisitor):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1497
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1498
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1499
    Raise `nodes.NodeFound` if non-simple list item is encountered.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1500
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1501
    Here "simple" means a list item containing nothing other than a single
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1502
    paragraph, a simple list, or a paragraph followed by a simple list.
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1503
    """
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1504
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1505
    def default_visit(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1506
        raise nodes.NodeFound
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1507
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1508
    def visit_bullet_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1509
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1510
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1511
    def visit_enumerated_list(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1512
        pass
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1513
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1514
    def visit_list_item(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1515
        children = []
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1516
        for child in node.children:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1517
            if not isinstance(child, nodes.Invisible):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1518
                children.append(child)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1519
        if (children and isinstance(children[0], nodes.paragraph)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1520
            and (isinstance(children[-1], nodes.bullet_list)
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1521
                 or isinstance(children[-1], nodes.enumerated_list))):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1522
            children.pop()
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1523
        if len(children) <= 1:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1524
            return
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1525
        else:
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1526
            raise nodes.NodeFound
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1527
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1528
    def visit_paragraph(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1529
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1530
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1531
    def invisible_visit(self, node):
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1532
        """Invisible nodes should be ignored."""
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1533
        raise nodes.SkipNode
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1534
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1535
    visit_comment = invisible_visit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1536
    visit_substitution_definition = invisible_visit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1537
    visit_target = invisible_visit
d8ac696cc51f helium_7.0-r14027
wbernard
parents:
diff changeset
  1538
    visit_pending = invisible_visit