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