Attachment 'TableOfContents-1.9.3.py'
Download 1 # -*- coding: iso-8859-1 -*-
2 """
3 MoinMoin - TableOfContents Macro
4
5 The macro works as follows: First, it renders the page using
6 the TOCFormatter (below) to get access to the outline of the
7 page. During the page rendering, only macros whose
8 'generates_headings' property is set and True are rendered,
9 most macros don't generate any headings and thus need not be
10 executed speeding up the process considerably.
11
12 The generated outline is then written to the output.
13
14 However, this is not all. Consider included pages that include
15 a TOC themselves! First of all, TOCs don't generate headings
16 so we avoid recursion during the collection process. Secondly,
17 we always keep track of which content we are in and the
18 formatter's heading method is responsible for making all
19 IDs they generate unique. We use the same algorithm to make
20 the IDs unique during the TOCFormatter rendering step so that
21 in the end we can output the same IDs and the TOC is linked
22 correctly, even in the case of multiple nested inclusions.
23
24 @copyright: 2007 MoinMoin:JohannesBerg
25 @license: GNU GPL, see COPYING for details.
26 """
27
28 from MoinMoin.formatter import FormatterBase
29 from MoinMoin.Page import Page
30 from MoinMoin import wikiutil
31
32
33 # cannot be cached because of TOCs in included pages
34 Dependencies = ['time']
35
36 class TOCFormatter(FormatterBase):
37 def __init__(self, request, **kw):
38 FormatterBase.__init__(self, request, **kw)
39 self.in_heading = False
40 self.collected_headings = request._tocfm_collected_headings
41
42 def _text(self, text):
43 if self.in_heading:
44 self.collected_headings[-1][2] += text
45 return text
46
47 def startContent(self, *args, **kw):
48 res = FormatterBase.startContent(self, *args, **kw)
49 self.collected_headings.append([1, self.request.uid_generator.include_id, None])
50 return res
51
52 def endContent(self):
53 res = FormatterBase.endContent(self)
54 self.collected_headings.append([0, self.request.uid_generator.include_id, None])
55 return res
56
57 def heading(self, on, depth, **kw):
58 id = kw.get('id', None)
59 self.in_heading = on
60 if not id is None:
61 id = self.request._tocfm_orig_formatter.make_id_unique(id)
62 if on:
63 self.collected_headings.append([depth, id, u''])
64 return ''
65
66 def macro(self, macro_obj, name, args, markup=None):
67 try:
68 # plugins that are defined in the macro class itself
69 # can't generate headings this way, but that's fine
70 gen_headings = wikiutil.importPlugin(self.request.cfg, 'macro',
71 name, 'generates_headings')
72 if gen_headings:
73 return FormatterBase.macro(self, macro_obj, name, args, markup)
74 except (wikiutil.PluginMissingError, wikiutil.PluginAttributeError):
75 pass
76 return ''
77
78 def _anything_return_empty(self, *args, **kw):
79 return ''
80
81 lang = _anything_return_empty
82 sysmsg = _anything_return_empty
83 startDocument = _anything_return_empty
84 endDocument = _anything_return_empty
85 pagelink = _anything_return_empty
86 interwikilink = _anything_return_empty
87 url = _anything_return_empty
88 attachment_link = _anything_return_empty
89 attachment_image = _anything_return_empty
90 attachment_drawing = _anything_return_empty
91 attachment_inlined = _anything_return_empty
92 anchordef = _anything_return_empty
93 line_anchordef = _anything_return_empty
94 anchorlink = _anything_return_empty
95 line_anchorlink = _anything_return_empty
96 image = _anything_return_empty
97 smiley = _anything_return_empty
98 nowikiword = _anything_return_empty
99 strong = _anything_return_empty
100 emphasis = _anything_return_empty
101 underline = _anything_return_empty
102 highlight = _anything_return_empty
103 sup = _anything_return_empty
104 sub = _anything_return_empty
105 strike = _anything_return_empty
106 code = _anything_return_empty
107 preformatted = _anything_return_empty
108 small = _anything_return_empty
109 big = _anything_return_empty
110 code_area = _anything_return_empty
111 code_line = _anything_return_empty
112 code_token = _anything_return_empty
113 linebreak = _anything_return_empty
114 paragraph = _anything_return_empty
115 rule = _anything_return_empty
116 icon = _anything_return_empty
117 number_list = _anything_return_empty
118 bullet_list = _anything_return_empty
119 listitem = _anything_return_empty
120 definition_list = _anything_return_empty
121 definition_term = _anything_return_empty
122 definition_desc = _anything_return_empty
123 table = _anything_return_empty
124 table_row = _anything_return_empty
125 table_cell = _anything_return_empty
126 _get_bang_args = _anything_return_empty
127 parser = _anything_return_empty
128 div = _anything_return_empty
129 span = _anything_return_empty
130 escapedText = _anything_return_empty
131 comment = _anything_return_empty
132 transclusion = _anything_return_empty
133
134 def macro_TableOfContents(macro, maxdepth=int):
135 """
136 Prints a table of contents.
137
138 maxdepth:: maximum depth the table of contents is generated for (defaults to unlimited)
139 """
140 try:
141 mindepth = int(macro.request.getPragma('section-numbers', 1))
142 except (ValueError, TypeError):
143 mindepth = 1
144
145 if maxdepth is None:
146 maxdepth = 99
147
148 pname = macro.formatter.page.page_name
149
150 macro.request.uid_generator.push()
151
152 macro.request._tocfm_collected_headings = []
153 macro.request._tocfm_orig_formatter = macro.formatter
154
155 tocfm = TOCFormatter(macro.request)
156 p = Page(macro.request, pname, formatter=tocfm, rev=macro.request.rev)
157
158 # this is so we get a correctly updated TOC if we just preview in the editor -
159 # the new content is not stored on disk yet, but available as macro.parser.raw:
160 p.set_raw_body(macro.parser.raw, modified=1)
161
162 output = macro.request.redirectedOutput(p.send_page,
163 content_only=True,
164 count_hit=False,
165 omit_footnotes=True)
166
167 _ = macro.request.getText
168
169 result = [
170 macro.formatter.div(1, css_class="table-of-contents", id="toc"),
171 macro.formatter.paragraph(1, css_class="table-of-contents-heading"),
172 macro.formatter.text(_('Contents')),
173 macro.formatter.paragraph(0),
174 ]
175
176
177 # find smallest used level and use that as the outer-most indentation,
178 # to fix pages like HelpOnMacros that only use h2 and lower levels.
179 lastlvl = 100
180 for lvl, id, txt in macro.request._tocfm_collected_headings:
181 if txt is None:
182 incl_id = id
183 continue
184 if lvl > maxdepth or id is None:
185 continue
186 if lvl < lastlvl:
187 lastlvl = lvl
188
189 # headings are 1-based, lastlvl needs to be one less so that one is closed
190 # variables needed to provide with nice, leveled prefixes
191 # (part of the hierarhical TOC prefix code)
192 levelnumbers = None
193 levelnumbers = {}
194 counter = 1
195 lowest_lvl = None
196 lastlvl -= 1
197
198 for lvl, id, txt in macro.request._tocfm_collected_headings:
199 if txt is None:
200 incl_id = id
201 continue
202 if lvl > maxdepth or id is None:
203 continue
204
205
206 # determine the lowest level available
207 # (part of the hierarhical TOC prefix)
208 if lowest_lvl is None or lowest_lvl > lvl:
209 lowest_lvl = lvl
210
211 # determine number prefix for the TOC line
212 # (part of the hierarhical TOC prefix)
213 if lvl > lastlvl:
214 levelnumbers[lastlvl] = counter
215 counter = 0
216 elif lvl < lastlvl:
217 counter = levelnumbers[lvl]
218 counter = counter + 1
219 levelnumbers[lvl] = counter
220
221 line_number = ""
222 for i in range(lowest_lvl, lvl):
223 line_number = line_number + str(levelnumbers[i]) + "."
224 line_number = line_number + str(counter) + "."
225
226 # will be reset by pop_unique_ids below
227 macro.request.uid_generator.include_id = incl_id
228
229 need_li = lastlvl >= lvl
230 while lastlvl > lvl:
231 result.extend([
232 macro.formatter.listitem(0),
233 macro.formatter.bullet_list(0),
234 ])
235 lastlvl -= 1
236 while lastlvl < lvl:
237 result.extend([
238 macro.formatter.bullet_list(1, type="none"),
239 macro.formatter.listitem(1),
240 ])
241 lastlvl += 1
242 if need_li:
243 result.extend([
244 macro.formatter.listitem(0),
245 macro.formatter.listitem(1),
246 ])
247 result.extend([
248 '\n',
249 macro.formatter.anchorlink(1, id),
250 macro.formatter.text(line_number + " " + txt),
251 macro.formatter.anchorlink(0),
252 ])
253
254 while lastlvl > 0:
255 result.append(macro.formatter.listitem(0))
256 result.append(macro.formatter.bullet_list(0))
257 lastlvl -= 1
258
259 macro.request.uid_generator.pop()
260
261 result.append(macro.formatter.div(0))
262 return ''.join(result)
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.