buildframework/helium/external/python/lib/2.5/docutils-0.5-py2.5.egg/docutils/transforms/parts.py
changeset 179 d8ac696cc51f
parent 1 be27ed110b50
child 180 e02a83d4c571
child 592 3215c239276a
equal deleted inserted replaced
1:be27ed110b50 179:d8ac696cc51f
     1 # $Id: parts.py 4891 2007-01-22 08:35:57Z wiemann $
       
     2 # Authors: David Goodger <goodger@python.org>; Ueli Schlaepfer; Dmitry Jemerov
       
     3 # Copyright: This module has been placed in the public domain.
       
     4 
       
     5 """
       
     6 Transforms related to document parts.
       
     7 """
       
     8 
       
     9 __docformat__ = 'reStructuredText'
       
    10 
       
    11 
       
    12 import re
       
    13 import sys
       
    14 from docutils import nodes, utils
       
    15 from docutils.transforms import TransformError, Transform
       
    16 
       
    17 
       
    18 class SectNum(Transform):
       
    19 
       
    20     """
       
    21     Automatically assigns numbers to the titles of document sections.
       
    22 
       
    23     It is possible to limit the maximum section level for which the numbers
       
    24     are added.  For those sections that are auto-numbered, the "autonum"
       
    25     attribute is set, informing the contents table generator that a different
       
    26     form of the TOC should be used.
       
    27     """
       
    28 
       
    29     default_priority = 710
       
    30     """Should be applied before `Contents`."""
       
    31 
       
    32     def apply(self):
       
    33         self.maxdepth = self.startnode.details.get('depth', sys.maxint)
       
    34         self.startvalue = self.startnode.details.get('start', 1)
       
    35         self.prefix = self.startnode.details.get('prefix', '')
       
    36         self.suffix = self.startnode.details.get('suffix', '')
       
    37         self.startnode.parent.remove(self.startnode)
       
    38         if self.document.settings.sectnum_xform:
       
    39             self.update_section_numbers(self.document)
       
    40 
       
    41     def update_section_numbers(self, node, prefix=(), depth=0):
       
    42         depth += 1
       
    43         if prefix:
       
    44             sectnum = 1
       
    45         else:
       
    46             sectnum = self.startvalue
       
    47         for child in node:
       
    48             if isinstance(child, nodes.section):
       
    49                 numbers = prefix + (str(sectnum),)
       
    50                 title = child[0]
       
    51                 # Use &nbsp; for spacing:
       
    52                 generated = nodes.generated(
       
    53                     '', (self.prefix + '.'.join(numbers) + self.suffix
       
    54                          +  u'\u00a0' * 3),
       
    55                     classes=['sectnum'])
       
    56                 title.insert(0, generated)
       
    57                 title['auto'] = 1
       
    58                 if depth < self.maxdepth:
       
    59                     self.update_section_numbers(child, numbers, depth)
       
    60                 sectnum += 1
       
    61 
       
    62 
       
    63 class Contents(Transform):
       
    64 
       
    65     """
       
    66     This transform generates a table of contents from the entire document tree
       
    67     or from a single branch.  It locates "section" elements and builds them
       
    68     into a nested bullet list, which is placed within a "topic" created by the
       
    69     contents directive.  A title is either explicitly specified, taken from
       
    70     the appropriate language module, or omitted (local table of contents).
       
    71     The depth may be specified.  Two-way references between the table of
       
    72     contents and section titles are generated (requires Writer support).
       
    73 
       
    74     This transform requires a startnode, which which contains generation
       
    75     options and provides the location for the generated table of contents (the
       
    76     startnode is replaced by the table of contents "topic").
       
    77     """
       
    78 
       
    79     default_priority = 720
       
    80 
       
    81     def apply(self):
       
    82         details = self.startnode.details
       
    83         if details.has_key('local'):
       
    84             startnode = self.startnode.parent.parent
       
    85             while not (isinstance(startnode, nodes.section)
       
    86                        or isinstance(startnode, nodes.document)):
       
    87                 # find the ToC root: a direct ancestor of startnode
       
    88                 startnode = startnode.parent
       
    89         else:
       
    90             startnode = self.document
       
    91         self.toc_id = self.startnode.parent['ids'][0]
       
    92         if details.has_key('backlinks'):
       
    93             self.backlinks = details['backlinks']
       
    94         else:
       
    95             self.backlinks = self.document.settings.toc_backlinks
       
    96         contents = self.build_contents(startnode)
       
    97         if len(contents):
       
    98             self.startnode.replace_self(contents)
       
    99         else:
       
   100             self.startnode.parent.parent.remove(self.startnode.parent)
       
   101 
       
   102     def build_contents(self, node, level=0):
       
   103         level += 1
       
   104         sections = [sect for sect in node if isinstance(sect, nodes.section)]
       
   105         entries = []
       
   106         autonum = 0
       
   107         depth = self.startnode.details.get('depth', sys.maxint)
       
   108         for section in sections:
       
   109             title = section[0]
       
   110             auto = title.get('auto')    # May be set by SectNum.
       
   111             entrytext = self.copy_and_filter(title)
       
   112             reference = nodes.reference('', '', refid=section['ids'][0],
       
   113                                         *entrytext)
       
   114             ref_id = self.document.set_id(reference)
       
   115             entry = nodes.paragraph('', '', reference)
       
   116             item = nodes.list_item('', entry)
       
   117             if ( self.backlinks in ('entry', 'top')
       
   118                  and title.next_node(nodes.reference) is None):
       
   119                 if self.backlinks == 'entry':
       
   120                     title['refid'] = ref_id
       
   121                 elif self.backlinks == 'top':
       
   122                     title['refid'] = self.toc_id
       
   123             if level < depth:
       
   124                 subsects = self.build_contents(section, level)
       
   125                 item += subsects
       
   126             entries.append(item)
       
   127         if entries:
       
   128             contents = nodes.bullet_list('', *entries)
       
   129             if auto:
       
   130                 contents['classes'].append('auto-toc')
       
   131             return contents
       
   132         else:
       
   133             return []
       
   134 
       
   135     def copy_and_filter(self, node):
       
   136         """Return a copy of a title, with references, images, etc. removed."""
       
   137         visitor = ContentsFilter(self.document)
       
   138         node.walkabout(visitor)
       
   139         return visitor.get_entry_text()
       
   140 
       
   141 
       
   142 class ContentsFilter(nodes.TreeCopyVisitor):
       
   143 
       
   144     def get_entry_text(self):
       
   145         return self.get_tree_copy().children
       
   146 
       
   147     def visit_citation_reference(self, node):
       
   148         raise nodes.SkipNode
       
   149 
       
   150     def visit_footnote_reference(self, node):
       
   151         raise nodes.SkipNode
       
   152 
       
   153     def visit_image(self, node):
       
   154         if node.hasattr('alt'):
       
   155             self.parent.append(nodes.Text(node['alt']))
       
   156         raise nodes.SkipNode
       
   157 
       
   158     def ignore_node_but_process_children(self, node):
       
   159         raise nodes.SkipDeparture
       
   160 
       
   161     visit_interpreted = ignore_node_but_process_children
       
   162     visit_problematic = ignore_node_but_process_children
       
   163     visit_reference = ignore_node_but_process_children
       
   164     visit_target = ignore_node_but_process_children