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

Revision 3044, 8.0 KB checked in by moschny, 8 years ago (diff)

Installation instructions updated.

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, place the file `TracNav.py` in the `wiki-macros`
18subdirectory and the accompanying `tracnav.css` file in the
19`templates` subdirectory of your Trac project. Add this line
20{{{
21@import url(<?cs var:chrome.href ?>/site/tracnav.css);
22}}}
23to the `templates/site_css.cs` file of your Trac project.
24
25The `tracnav.css` file defines the styles for displaying the
26navigation bar. These styles build upon the styles for !TracGuideToc
27that come with your Trac distribution. If you just install the macro
28but miss to install the style file, TracNav will work but look
29somewhat strange.
30
31
32== Usage ==
33
34To use TracNav, create an index page for your site and call the
35TracNav macro on each page, where the navigation bar should be
36displayed. The index page is a regular wiki page. The page with the
37table of contents must include an unordered list of links that should
38be displayed in the navigation bar.
39
40To display the navigation bar on a page, you must call the TracNav
41macro on that page an pass the name of your table of contents as
42argument.
43
44
45== Author and license ==
46
47Copyright 2005 Bernhard Haumacher (haui at haumacher.de)
48
49{{{
50This program is free software; you can redistribute it and/or modify
51it under the terms of the GNU General Public License as published by
52the Free Software Foundation; either version 2 of the License, or
53(at your option) any later version.
54
55This program is distributed in the hope that it will be useful,
56but WITHOUT ANY WARRANTY; without even the implied warranty of
57MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
58GNU General Public License for more details.
59
60You should have received a copy of the GNU General Public License
61along with this program; if not, write to the Free Software
62Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
63}}}
64
65== Additional information and a life example ==
66
67Please visit: http://svn.ipd.uka.de/trac/javaparty/wiki/TracNav
68"""
69
70import re
71import sys
72
73listRule = re.compile(r"""^(?P<indent> *)\* +(?:(?P<wikilink>\[wiki:(?P<link>(&#34;([^&#34;]*)&#34;|'([^']*)')|([^ \]]+)) +(?P<label>[^\]]*)\])|(?P<text>.*))""", re.M)
74
75def getToc(hdf, env, db, curpage, name):
76    preview = hdf.getValue('args.preview', "")
77
78    tocText = "* Table of contents"
79    if preview and (name == curpage):
80        tocText = hdf.getValue('wiki.page_source', tocText);
81    else:
82        cursor = db.cursor()
83        cursor.execute('SELECT text FROM wiki WHERE name=%s ORDER BY version DESC LIMIT 1', name)
84        row = cursor.fetchone()
85        if row:
86            tocText = row[0]
87
88    # env.log.debug(tocText)
89    return tocText
90
91
92def parseToc(tocText):
93    stack = []
94    nextPos = 0
95    while 1:
96        match = listRule.search(tocText, nextPos)
97        if not match:
98            # env.log.debug("No more matches")
99            break
100
101        indent = len(match.group('indent'))
102        if match.group('wikilink'):
103            link = match.group('link')
104            label = match.group('label')
105        else:
106            link = None
107            label = match.group('text')
108
109        # if link == None:
110        #     env.log.debug(label + " ---")
111        # else:
112        #     env.log.debug(label + ": " + link)
113
114        if len(stack) == 0:
115            stack.append((indent, []))
116
117        (lastIndent, list) = stack[len(stack) - 1]
118
119        if indent > lastIndent:
120            stack.append((indent, [(link, label, None)]))
121        elif indent == lastIndent:
122            list.append((link, label, None))
123        else:
124            while indent < lastIndent:
125                (_, list) = stack.pop()
126                (lastIndent, topList) = stack[len(stack) - 1]
127                (topLink, topLabel, _) = topList[len(topList) - 1]
128                topList[len(topList) - 1] = (topLink, topLabel, list)
129
130            (lastIndent, list) = stack[len(stack) - 1]
131            list.append((link, label, None))
132               
133        nextPos = match.end()
134
135    while len(stack) > 1:
136        (_, list) = stack.pop()
137        (_, topList) = stack[len(stack) - 1]
138        (topLink, topLabel, _) = topList[len(topList) - 1]
139        topList[len(topList) - 1] = (topLink, topLabel, list)
140
141    (_, list) = stack.pop()
142    return list
143
144
145def execute(hdf, args, env):
146    preview = hdf.getValue('args.preview', "")
147    curpage = hdf.getValue('wiki.page_name', "")
148    name = args
149    if not name:
150        name = 'TOC'
151
152    db = env.get_db_cnx()
153    toc = parseToc(getToc(hdf, env, db, curpage, name))
154    if not toc:
155        msg = ''
156        msg += '<div class="system-message"><strong>Error: Table of contents does not exist.'
157        if (not preview) and (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
158            msg += ' Click here to <a href="%s?edit=yes">edit</a>.' % env.href.wiki(name)
159        msg += '</strong></div>\n'
160        return msg
161
162    (found, filtered) = filter(curpage, toc, 0)
163    if found:
164        return displayAll(hdf, env, name, curpage, filtered, 0)
165    else:
166        return displayAll(hdf, env, name, curpage, toc, 0)
167
168
169def filter(curpage, toc, level):
170    found = 0
171    result = []
172    for name, title, sub in toc:
173        if sub == None:
174            if name == curpage:
175                found = 1
176            result.append((name, title, None))
177        else:
178            (subfound, subtoc) = filter(curpage, sub, level + 1)
179            if subfound:
180                found = 1
181            if subfound or (name == None):
182                if level == 0 and name != None:
183                    prepended = [(name, title, subtoc)]
184                    prepended.extend(result)
185                    result = prepended
186                else:
187                    result.append((name, title, subtoc))
188            else:
189                result.append((name, title, []))
190    return (found, result)
191
192def indentation(col):
193    return ' ' * col
194
195def displayAll(hdf, env, name, curpage, toc, col):
196    preview = hdf.getValue('args.preview', "")
197    html = ''
198    html += '%s<div class="wiki-toc trac-nav">\n' % indentation(col)
199    col += 1
200
201    html += '%s<h2><a href="http://svn.ipd.uka.de/trac/javaparty/wiki/TracNav">TracNav</a> menu</h2>' % indentation(col)
202
203    if (not preview) and hdf.getValue('trac.acl.WIKI_MODIFY', ''):
204        html += '%s<div class="edit"><a href="%s?edit=yes">edit</a></div>\n' % (indentation(col), env.href.wiki(name))
205    html += '%s<ul>\n' % indentation(col)
206    col += 1
207    html += display(env, curpage, toc, 0, col)
208    col -= 1
209    html += '%s</ul>\n' % indentation(col)
210    col -= 1
211    html += '%s</div>\n' % indentation(col)
212    return html
213
214def display(env, curpage, toc, depth, col):
215    html = ''
216    for name, title, sub in toc:
217        liStyle = ' style="padding-left: %dem;"' % (depth + 1)
218        if sub == None:
219            if name == curpage:
220                cls = ' class="active"'
221            else:
222                cls = ''
223            html += '%s<li%s%s>' % (indentation(col), liStyle, cls)
224            if name == None:
225                html += title
226            else:
227                html += '<a href="%s">%s</a>' % (env.href.wiki(name), title)
228            html += '</li>\n'
229        else:
230            html += '%s<li%s>\n' % (indentation(col), liStyle)
231            col += 1
232            if name == None or len(sub) > 0:
233                html += '%s<h4>%s</h4>\n' % (indentation(col), title)
234            else:
235                html += '%s<h4><a href="%s">%s</a>...</h4>\n' % (indentation(col), env.href.wiki(name), title)
236            col -= 1
237            html += '%s</li>\n' % indentation(col)
238            if len(sub) > 0:
239                html += display(env, curpage, sub, depth + 1, col)
240    return html
241
Note: See TracBrowser for help on using the repository browser.