comparison env/lib/python3.9/site-packages/docutils/transforms/parts.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:4f3585e2f14b
1 # $Id: parts.py 8403 2019-10-11 10:09:53Z milde $
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', None)
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 if self.maxdepth is None:
40 self.maxdepth = sys.maxsize
41 self.update_section_numbers(self.document)
42 else: # store details for eventual section numbering by the writer
43 self.document.settings.sectnum_depth = self.maxdepth
44 self.document.settings.sectnum_start = self.startvalue
45 self.document.settings.sectnum_prefix = self.prefix
46 self.document.settings.sectnum_suffix = self.suffix
47
48 def update_section_numbers(self, node, prefix=(), depth=0):
49 depth += 1
50 if prefix:
51 sectnum = 1
52 else:
53 sectnum = self.startvalue
54 for child in node:
55 if isinstance(child, nodes.section):
56 numbers = prefix + (str(sectnum),)
57 title = child[0]
58 # Use &nbsp; for spacing:
59 generated = nodes.generated(
60 '', (self.prefix + '.'.join(numbers) + self.suffix
61 + u'\u00a0' * 3),
62 classes=['sectnum'])
63 title.insert(0, generated)
64 title['auto'] = 1
65 if depth < self.maxdepth:
66 self.update_section_numbers(child, numbers, depth)
67 sectnum += 1
68
69
70 class Contents(Transform):
71
72 """
73 This transform generates a table of contents from the entire document tree
74 or from a single branch. It locates "section" elements and builds them
75 into a nested bullet list, which is placed within a "topic" created by the
76 contents directive. A title is either explicitly specified, taken from
77 the appropriate language module, or omitted (local table of contents).
78 The depth may be specified. Two-way references between the table of
79 contents and section titles are generated (requires Writer support).
80
81 This transform requires a startnode, which contains generation
82 options and provides the location for the generated table of contents (the
83 startnode is replaced by the table of contents "topic").
84 """
85
86 default_priority = 720
87
88 def apply(self):
89 try: # let the writer (or output software) build the contents list?
90 toc_by_writer = self.document.settings.use_latex_toc
91 except AttributeError:
92 toc_by_writer = False
93 details = self.startnode.details
94 if 'local' in details:
95 startnode = self.startnode.parent.parent
96 while not (isinstance(startnode, nodes.section)
97 or isinstance(startnode, nodes.document)):
98 # find the ToC root: a direct ancestor of startnode
99 startnode = startnode.parent
100 else:
101 startnode = self.document
102 self.toc_id = self.startnode.parent['ids'][0]
103 if 'backlinks' in details:
104 self.backlinks = details['backlinks']
105 else:
106 self.backlinks = self.document.settings.toc_backlinks
107 if toc_by_writer:
108 # move customization settings to the parent node
109 self.startnode.parent.attributes.update(details)
110 self.startnode.parent.remove(self.startnode)
111 else:
112 contents = self.build_contents(startnode)
113 if len(contents):
114 self.startnode.replace_self(contents)
115 else:
116 self.startnode.parent.parent.remove(self.startnode.parent)
117
118 def build_contents(self, node, level=0):
119 level += 1
120 sections = [sect for sect in node if isinstance(sect, nodes.section)]
121 entries = []
122 autonum = 0
123 depth = self.startnode.details.get('depth', sys.maxsize)
124 for section in sections:
125 title = section[0]
126 auto = title.get('auto') # May be set by SectNum.
127 entrytext = self.copy_and_filter(title)
128 reference = nodes.reference('', '', refid=section['ids'][0],
129 *entrytext)
130 ref_id = self.document.set_id(reference,
131 suggested_prefix='toc-entry')
132 entry = nodes.paragraph('', '', reference)
133 item = nodes.list_item('', entry)
134 if ( self.backlinks in ('entry', 'top')
135 and title.next_node(nodes.reference) is None):
136 if self.backlinks == 'entry':
137 title['refid'] = ref_id
138 elif self.backlinks == 'top':
139 title['refid'] = self.toc_id
140 if level < depth:
141 subsects = self.build_contents(section, level)
142 item += subsects
143 entries.append(item)
144 if entries:
145 contents = nodes.bullet_list('', *entries)
146 if auto:
147 contents['classes'].append('auto-toc')
148 return contents
149 else:
150 return []
151
152 def copy_and_filter(self, node):
153 """Return a copy of a title, with references, images, etc. removed."""
154 visitor = ContentsFilter(self.document)
155 node.walkabout(visitor)
156 return visitor.get_entry_text()
157
158
159 class ContentsFilter(nodes.TreeCopyVisitor):
160
161 def get_entry_text(self):
162 return self.get_tree_copy().children
163
164 def visit_citation_reference(self, node):
165 raise nodes.SkipNode
166
167 def visit_footnote_reference(self, node):
168 raise nodes.SkipNode
169
170 def visit_image(self, node):
171 if node.hasattr('alt'):
172 self.parent.append(nodes.Text(node['alt']))
173 raise nodes.SkipNode
174
175 def ignore_node_but_process_children(self, node):
176 raise nodes.SkipDeparture
177
178 visit_problematic = ignore_node_but_process_children
179 visit_reference = ignore_node_but_process_children
180 visit_target = ignore_node_but_process_children