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.
  • [get | view] (2009-03-27 02:31:52, 8.1 KB) [[attachment:TableOfContents-1.8.py]]
  • [get | view] (2009-03-27 02:27:46, 4.2 KB) [[attachment:TableOfContents-1.8.py.patch]]
  • [get | view] (2010-09-01 17:02:37, 9.0 KB) [[attachment:TableOfContents-1.9.3.py]]
  • [get | view] (2010-09-01 17:02:11, 3.2 KB) [[attachment:TableOfContents-1.9.3.py.patch]]
  • [get | view] (2009-03-27 02:31:20, 8.9 KB) [[attachment:TableOfContents-1.9beta2.py]]
  • [get | view] (2009-03-27 02:28:13, 2.8 KB) [[attachment:TableOfContents-1.9beta2.py.patch]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.