Attachment 'TableOfContents-1.8.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.include_id, None])
50 return res
51
52 def endContent(self):
53 res = FormatterBase.endContent(self)
54 self.collected_headings.append([0, self.request.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 if maxdepth is None:
141 maxdepth = 99
142
143 pname = macro.formatter.page.page_name
144
145 macro.request.push_unique_ids()
146
147 macro.request._tocfm_collected_headings = []
148 macro.request._tocfm_orig_formatter = macro.formatter
149
150 tocfm = TOCFormatter(macro.request)
151 p = Page(macro.request, pname, formatter=tocfm, rev=macro.request.rev)
152 output = macro.request.redirectedOutput(p.send_page,
153 content_only=True,
154 count_hit=False,
155 omit_footnotes=True)
156
157 _ = macro.request.getText
158
159 result = [
160 macro.formatter.div(1, css_class="table-of-contents", id="toc"),
161 macro.formatter.paragraph(1, css_class="table-of-contents-heading"),
162 macro.formatter.text(_('Contents')),
163 macro.formatter.paragraph(0),
164 ]
165
166 lastlvl = 0
167
168 # variables needed to provide with nice, leveled prefixes
169 levelnumbers = None
170 levelnumbers = {}
171 counter = 1
172 lowest_lvl = None
173
174 for lvl, id, txt in macro.request._tocfm_collected_headings:
175
176 if txt is None:
177 incl_id = id
178 continue
179 if lvl > maxdepth or id is None:
180 continue
181
182 # determine the lowest level available
183 if lowest_lvl is None or lowest_lvl > lvl:
184 lowest_lvl = lvl
185
186 # determine number prefix for the TOC line
187 if lvl > lastlvl:
188 levelnumbers[lastlvl] = counter
189 counter = 0
190 elif lvl < lastlvl:
191 counter = levelnumbers[lvl]
192
193 counter = counter + 1
194 levelnumbers[lvl] = counter
195
196 line_number = ""
197 for i in range(lowest_lvl, lvl):
198 line_number = line_number + str(levelnumbers[i]) + "."
199 line_number = line_number + str(counter) + "."
200
201
202 # will be reset by pop_unique_ids below
203 macro.request.include_id = incl_id
204
205 need_li = lastlvl >= lvl
206
207
208 # adjust lastlvl so that we can start lists from the lowest_lvl
209 if lastlvl < lvl and lastlvl < lowest_lvl: lastlvl = lvl - 1
210 if lastlvl > lvl and lastlvl < lowest_lvl: lastlvl = lvl + 1
211
212
213 # open and close corresponding lists
214 while lastlvl < lvl:
215 result.extend([
216 macro.formatter.bullet_list(1, type="none"),
217 macro.formatter.listitem(1),
218 ])
219 lastlvl += 1
220 while lastlvl > lvl:
221 result.extend([
222 macro.formatter.listitem(0),
223 macro.formatter.bullet_list(0),
224 ])
225 lastlvl -= 1
226 if need_li:
227 result.extend([
228 macro.formatter.listitem(0),
229 macro.formatter.listitem(1),
230 ])
231
232 result.extend([
233 '\n',
234 macro.formatter.anchorlink(1, id),
235 macro.formatter.text(line_number + " " + txt),
236 macro.formatter.anchorlink(0),
237 ])
238
239 while lastlvl > lvl:
240 result.append(macro.formatter.listitem(0))
241 result.append(macro.formatter.bullet_list(0))
242 lastlvl -= 1
243
244 macro.request.pop_unique_ids()
245
246 result.append(macro.formatter.div(0))
247 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.