source: trac/trunk/wiki-macros/JPNav.py @ 2723

Revision 2723, 4.4 KB checked in by hauma, 8 years ago (diff)
  • Bugfix: Use newest version of TOC page for creating the navigation bar. This requires to sort the results from the query in reverse order.
  • Allow non-linked headlines in the TOC page. Submenus with non-linked headlines are always displayed expanded, but not displayed at the top.
Line 
1# -*- coding: iso8859-1 -*-
2"""
3= TracNav: The navigation bar for Trac =
4
5This macro implements a fully customizable navigation bar for the Trac
6wiki engine. The contents of the navigation bar is a wiki page itself
7and can be edited like any other wiki page through the web
8interface. The navigation bar supports hierarchical ordering of
9topics. The design of TracNav mimics the design of the TracGuideToc
10that was originally supplied with Trac. The drawback of TracGuideToc
11is that is is not customizable without editing its source code and
12that it does not support hierarchical ordering.
13"""
14
15import re
16import sys
17
18listRule = re.compile(r"""^(?P<indent> +)\* +(?:(?P<wikilink>\[wiki:(?P<link>(&#34;([^&#34;]*)&#34;|'([^']*)')|([^ \]]+)) +(?P<label>[^\]]*)\])|(?P<text>.*))""", re.M)
19
20def getToc(env, db, name):
21    cursor = db.cursor()
22    cursor.execute('SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1', name)
23    row = cursor.fetchone()
24    if not row:
25        return None
26
27    tocText = row[0]
28
29    # env.log.debug(tocText)
30
31    stack = [(1, [])]
32    nextPos = 0
33    while 1:
34        match = listRule.search(tocText, nextPos)
35        if not match:
36            env.log.debug("No more matches")
37            break
38
39        indent = len(match.group('indent'))
40        if match.group('wikilink'):
41            link = match.group('link')
42            label = match.group('label')
43        else:
44            link = None
45            label = match.group('text')
46
47        if link == None:
48            env.log.debug(label + " ---")
49        else:
50            env.log.debug(label + ": " + link)
51
52        (lastIndent, list) = stack[len(stack) - 1]
53
54        if indent > lastIndent:
55            stack.append((indent, [(link, label, None)]))
56        elif indent == lastIndent:
57            list.append((link, label, None))
58        else:
59            while indent < lastIndent:
60                (_, list) = stack.pop()
61                (lastIndent, topList) = stack[len(stack) - 1]
62                (topLink, topLabel, _) = topList[len(topList) - 1]
63                topList[len(topList) - 1] = (topLink, topLabel, list)
64
65            (lastIndent, list) = stack[len(stack) - 1]
66            list.append((link, label, None))
67               
68        nextPos = match.end()
69
70    while len(stack) > 1:
71        (_, list) = stack.pop()
72        (_, topList) = stack[len(stack) - 1]
73        (topLink, topLabel, _) = topList[len(topList) - 1]
74        topList[len(topList) - 1] = (topLink, topLabel, list)
75
76    (_, list) = stack.pop()
77    return list
78
79
80def execute(hdf, args, env):
81    curpage =  '%s' % hdf.getValue('args.page', '')
82    name = args
83    if not name:
84        name = 'TOC'
85
86    db = env.get_db_cnx()
87    toc = getToc(env, db, name)
88    if not toc:
89        msg = ''
90        msg += '<div class="system-message"><strong>Error: Table of contents does not exist.'
91        if (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
92            msg += ' Click here to <a href="%s?edit=yes">edit</a>.' % env.href.wiki(name)
93        msg += '</strong></div>'
94        return msg
95
96    html = ''
97    html += '<div class="wiki-toc">'
98    if (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
99        html += '<div class="wiki-tocedit"><a href="%s?edit=yes">edit</a></div>' % env.href.wiki(name)
100    (_, subhtml) = generate(env, curpage, toc, 0)
101    html += subhtml
102    html += '</div>'
103    return html;
104
105
106def generate(env, curpage, toc, level):
107    html = ''
108    found = 0
109    for name, title, sub in toc:
110        if sub == None:
111            if name == curpage:
112                cls = ' class="active"'
113                found = 1
114            else:
115                cls = ''
116            html += '<li%s>' % ( cls )
117            if name == None:
118                html += title
119            else:
120                html += '<a href="%s">%s</a>' % (env.href.wiki(name), title)
121            html += '</li>'
122        else:
123            (subfound, subhtml) = generate(env, curpage, sub, level + 1)
124            if subfound or (name == None):
125                menu = ''
126                menu += '<li>'
127                menu += '<h4>%s</h4>' % title
128                menu += subhtml
129                menu += '</li>'
130                found = 1
131                if level == 0 and name != None:
132                    html = menu + html
133                else:
134                    html += menu
135            else:
136                html += '<li>'
137                html += '<h4><a href="%s">%s...</a></h4>' % (env.href.wiki(name), title)
138                html += '</li>'
139    html = '<ul>%s</ul>' % html
140    return (found, html);
141
Note: See TracBrowser for help on using the repository browser.