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

Revision 2864, 6.3 KB checked in by hauma, 8 years ago (diff)
  • Updated inline documentation of TracNav.
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 it is not customizable without editing its source code and
12that it does not support hierarchical ordering.
13
14
15== Installation ==
16
17To install TracNav, you must place the file {{{TracNav.py}}} somewhere
18in your {{{wiki-macros/}}} directory of your Trac
19installation. Additionally, you have to append the following lines to
20the file {{{htdocs/css/wiki.css}}} that can also be found in your Trac
21directoryhierarchy.
22
23{{{
24/* Styles for TracNav */
25.wiki-toc.trac-nav li { margin: 0; padding: 0; }
26.wiki-toc.trac-nav li li { margin: 0; padding: 0 1em; }
27.wiki-toc.trac-nav .edit { border:0; position:absolute; top:0; right:5px; }
28.wiki-toc.trac-nav .edit a { color:blue; border-color:blue; }
29}}}
30
31The lines above define the styles for displaying the navigation
32bar. These styles build upon the styles for !TracGuideToc that come
33with your Trac distribution. If you just install the macro but miss to
34extend the style file, TracNav will work but look somewhat strange.
35
36
37== Usage ==
38
39To use TracNav, you have to create an index page for your site and
40call the TracNav macro on each page, where the navigation bar should
41be displayed. The index page is a regular wiki page. The page with the
42table of contents must include an unordered list of links that should
43be displayed in the navigation bar.
44
45To display the navigation bar on a page, you must call the TracNav
46macro on that page an pass the name of your table of contents as
47argument.
48
49
50== Additional information and a life example ==
51
52Please visit: http://svn.ipd.uka.de/trac/javaparty/wiki/TracNav
53"""
54
55import re
56import sys
57
58listRule = re.compile(r"""^(?P<indent> +)\* +(?:(?P<wikilink>\[wiki:(?P<link>(&#34;([^&#34;]*)&#34;|'([^']*)')|([^ \]]+)) +(?P<label>[^\]]*)\])|(?P<text>.*))""", re.M)
59
60def getToc(env, db, name):
61    cursor = db.cursor()
62    cursor.execute('SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1', name)
63    row = cursor.fetchone()
64    if not row:
65        return None
66
67    tocText = row[0]
68
69    # env.log.debug(tocText)
70
71    stack = [(1, [])]
72    nextPos = 0
73    while 1:
74        match = listRule.search(tocText, nextPos)
75        if not match:
76            env.log.debug("No more matches")
77            break
78
79        indent = len(match.group('indent'))
80        if match.group('wikilink'):
81            link = match.group('link')
82            label = match.group('label')
83        else:
84            link = None
85            label = match.group('text')
86
87        if link == None:
88            env.log.debug(label + " ---")
89        else:
90            env.log.debug(label + ": " + link)
91
92        (lastIndent, list) = stack[len(stack) - 1]
93
94        if indent > lastIndent:
95            stack.append((indent, [(link, label, None)]))
96        elif indent == lastIndent:
97            list.append((link, label, None))
98        else:
99            while indent < lastIndent:
100                (_, list) = stack.pop()
101                (lastIndent, topList) = stack[len(stack) - 1]
102                (topLink, topLabel, _) = topList[len(topList) - 1]
103                topList[len(topList) - 1] = (topLink, topLabel, list)
104
105            (lastIndent, list) = stack[len(stack) - 1]
106            list.append((link, label, None))
107               
108        nextPos = match.end()
109
110    while len(stack) > 1:
111        (_, list) = stack.pop()
112        (_, topList) = stack[len(stack) - 1]
113        (topLink, topLabel, _) = topList[len(topList) - 1]
114        topList[len(topList) - 1] = (topLink, topLabel, list)
115
116    (_, list) = stack.pop()
117    return list
118
119
120def execute(hdf, args, env):
121    curpage =  '%s' % hdf.getValue('args.page', '')
122    name = args
123    if not name:
124        name = 'TOC'
125
126    db = env.get_db_cnx()
127    toc = getToc(env, db, name)
128    if not toc:
129        msg = ''
130        msg += '<div class="system-message"><strong>Error: Table of contents does not exist.'
131        if (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
132            msg += ' Click here to <a href="%s?edit=yes">edit</a>.' % env.href.wiki(name)
133        msg += '</strong></div>'
134        return msg
135
136    html = ''
137    html += '<div class="wiki-toc trac-nav">'
138    if (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
139        html += '<div class="edit"><a href="%s?edit=yes">edit</a></div>' % env.href.wiki(name)
140    (found, filtered) = filter(curpage, toc, 0)
141    if found:
142        html += display(env, curpage, filtered)
143    else:
144        html += display(env, curpage, toc)
145    html += '</div>'
146    return html
147
148
149def filter(curpage, toc, level):
150    found = 0
151    result = []
152    for name, title, sub in toc:
153        if sub == None:
154            if name == curpage:
155                found = 1
156            result.append((name, title, None))
157        else:
158            (subfound, subtoc) = filter(curpage, sub, level + 1)
159            if subfound or (name == None):
160                found = 1
161                if level == 0 and name != None:
162                    prepended = [(name, title, subtoc)]
163                    prepended.extend(result)
164                    result = prepended
165                else:
166                    result.append((name, title, subtoc))
167            else:
168                result.append((name, title, []))
169    return (found, result)
170
171
172def display(env, curpage, toc):
173    html = '<ul>'
174    for name, title, sub in toc:
175        if sub == None:
176            if name == curpage:
177                cls = ' class="active"'
178            else:
179                cls = ''
180            html += '<li%s>' % ( cls )
181            if name == None:
182                html += title
183            else:
184                html += '<a href="%s">%s</a>' % (env.href.wiki(name), title)
185            html += '</li>'
186        else:
187            html += '<li>'
188            if name == None or len(sub) > 0:
189                html += '<h4>%s</h4>' % title
190            else:
191                html += '<h4><a href="%s">%s...</a></h4>' % (env.href.wiki(name), title)
192            html += display(env, curpage, sub)
193            html += '</li>'
194    html += '</ul>'
195    return html
196
Note: See TracBrowser for help on using the repository browser.