source: trac/trunk/wiki-macros/TracNav.py @ 2863

Revision 2863, 4.9 KB checked in by hauma, 8 years ago (diff)
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 trac-nav">'
98    if (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
99        html += '<div class="edit"><a href="%s?edit=yes">edit</a></div>' % env.href.wiki(name)
100    (found, filtered) = filter(curpage, toc, 0)
101    if found:
102        html += display(env, curpage, filtered)
103    else:
104        html += display(env, curpage, toc)
105    html += '</div>'
106    return html
107
108
109def filter(curpage, toc, level):
110    found = 0
111    result = []
112    for name, title, sub in toc:
113        if sub == None:
114            if name == curpage:
115                found = 1
116            result.append((name, title, None))
117        else:
118            (subfound, subtoc) = filter(curpage, sub, level + 1)
119            if subfound or (name == None):
120                found = 1
121                if level == 0 and name != None:
122                    prepended = [(name, title, subtoc)]
123                    prepended.extend(result)
124                    result = prepended
125                else:
126                    result.append((name, title, subtoc))
127            else:
128                result.append((name, title, []))
129    return (found, result)
130
131
132def display(env, curpage, toc):
133    html = '<ul>'
134    for name, title, sub in toc:
135        if sub == None:
136            if name == curpage:
137                cls = ' class="active"'
138            else:
139                cls = ''
140            html += '<li%s>' % ( cls )
141            if name == None:
142                html += title
143            else:
144                html += '<a href="%s">%s</a>' % (env.href.wiki(name), title)
145            html += '</li>'
146        else:
147            html += '<li>'
148            if name == None or len(sub) > 0:
149                html += '<h4>%s</h4>' % title
150            else:
151                html += '<h4><a href="%s">%s...</a></h4>' % (env.href.wiki(name), title)
152            html += display(env, curpage, sub)
153            html += '</li>'
154    html += '</ul>'
155    return html
156
Note: See TracBrowser for help on using the repository browser.