Edgewall Software

MacroBazaar: TOC.2.py

File TOC.2.py, 3.9 KB (added by jouvin@…, 7 years ago)

Modified TOC version (see description)

Line 
1# vim: expandtab tabstop=4
2from StringIO import StringIO
3import re
4import string
5from trac.util import escape
6
7rules_re = re.compile(r"""(?P<heading>^\s*(?P<hdepth>=+)\s(?P<header>.*)\s(?P=hdepth)\s*$)""")
8anchor_re = re.compile('[^\w\d]+')
9
10def parse_toc(env, out, page, body, max_depth = 999, min_depth = 1):
11    current_depth = min_depth
12    in_pre = False
13    first_li = True
14    seen_anchors = []
15
16    for line in body.splitlines():
17        line = escape(line)
18
19        # Skip over wiki-escaped code, e.g. code examples (Steven N.
20        # Severinghaus <sns@severinghaus.org>)
21        if in_pre:
22            if line == '}}}':
23                in_pre = False
24            else:
25                continue
26        if line == '{{{':
27            in_pre = True
28            continue
29
30        match = rules_re.match(line)
31        if match:
32            header = match.group('header')
33            new_depth = len(match.group('hdepth'))
34            if new_depth < min_depth:
35                continue
36            elif new_depth < current_depth:
37                while new_depth < current_depth:
38                    current_depth -= 1
39                    if current_depth < max_depth:
40                        out.write("</ol>")
41                out.write("<li>")
42            elif new_depth >= current_depth:
43                i = current_depth
44                while new_depth > i or first_li  :
45                    i += 1
46                    first_li = False
47                    if current_depth <= max_depth:
48                        out.write("<ol>")
49                current_depth = new_depth
50                out.write("<li>")
51            default_anchor = anchor = anchor_re.sub("", header)
52            anchor_n = 1
53            while anchor in seen_anchors:
54                anchor = default_anchor + str(anchor_n)
55                anchor_n += 1
56            seen_anchors.append(anchor)
57            link = page + "#" + anchor
58            if current_depth <= max_depth:
59                out.write('<a href="%s">%s</a></li>\n' % (env.href.wiki(link), header))
60    while current_depth >= min_depth and not first_li:
61        if current_depth <= max_depth:
62            out.write("</ol>\n")
63        current_depth -= 1
64
65def execute(hdf, args, env):
66    db = env.get_db_cnx()
67    if not args:
68        args = ''
69    pre_pages = re.split('\s*,\s*', args)
70    # Options
71    inline = False
72    heading = 'Table of Contents'
73    pages = []
74    root = ''
75    params = { }
76    # Global options
77    for page in pre_pages:
78        if page == 'inline':
79            inline = True
80        elif page == 'noheading':
81            heading = None
82        elif page[:8] == 'heading=':
83            heading = page[8:]
84        elif page == '':
85            continue
86        elif page[:6] == 'depth=':
87            params['max_depth'] = int(page[6:])
88        elif page[:5] == 'root=':
89            root = page[5:]
90        else:
91            pages.append(page)
92    # Has the user supplied a list of pages?
93    if not pages:
94        pages.append(hdf.getValue("args.page", "WikiStart"))
95        root = ''
96        params['min_depth'] = 2     # Skip page title
97    out = StringIO()
98    if not inline:
99        out.write("<div class='wiki-toc'>\n")
100    if heading:
101        out.write("<h4>%s</h4>\n" % heading)
102    for page in pages:
103        # Override arguments
104        if page[:6] == 'depth=':
105            params['max_depth'] = int(page[6:])
106        elif page[:5] == 'root=':
107            root = page[5:]
108        else:
109            page = root + page
110            cursor = db.cursor()
111            cursor.execute("SELECT text FROM wiki WHERE name='%s' ORDER BY version desc LIMIT 1" % page)
112            row = cursor.fetchone()
113            if row:
114                parse_toc(env, out, page, row[0], **params)
115            else:
116                out.write('<div class="system-message"><strong>Error: Page %s does not exist</strong></div>' % page)
117    if not inline:
118        out.write("</div>\n")
119    return out.getvalue()