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

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

Replace db access code with calls to the wiki api.

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
72from trac.wiki.api import WikiSystem
73from trac.wiki.model import WikiPage
74
75listRule = re.compile(r"""^(?P<indent> *)\* +(?:(?P<wikilink>\[wiki:(?P<link>(&#34;([^&#34;]*)&#34;|'([^']*)')|([^ \]]+)) +(?P<label>[^\]]*)\])|(?P<text>.*))""", re.M)
76
77def getToc(hdf, env, curpage, name):
78    tocText = "* Table of contents"
79
80    preview = hdf.getValue('args.preview', "")
81    if preview and (name == curpage):
82        tocText = hdf.getValue('wiki.page_source', tocText);
83    else:
84        if WikiSystem(env).has_page(name):
85            tocText = WikiPage(env, name).text
86
87    # env.log.debug(tocText)
88    return tocText
89
90
91def parseToc(tocText):
92    stack = []
93    nextPos = 0
94    while 1:
95        match = listRule.search(tocText, nextPos)
96        if not match:
97            # env.log.debug("No more matches")
98            break
99
100        indent = len(match.group('indent'))
101        if match.group('wikilink'):
102            link = match.group('link')
103            label = match.group('label')
104        else:
105            link = None
106            label = match.group('text')
107
108        # if link == None:
109        #     env.log.debug(label + " ---")
110        # else:
111        #     env.log.debug(label + ": " + link)
112
113        if len(stack) == 0:
114            stack.append((indent, []))
115
116        (lastIndent, list) = stack[len(stack) - 1]
117
118        if indent > lastIndent:
119            stack.append((indent, [(link, label, None)]))
120        elif indent == lastIndent:
121            list.append((link, label, None))
122        else:
123            while indent < lastIndent:
124                (_, list) = stack.pop()
125                (lastIndent, topList) = stack[len(stack) - 1]
126                (topLink, topLabel, _) = topList[len(topList) - 1]
127                topList[len(topList) - 1] = (topLink, topLabel, list)
128
129            (lastIndent, list) = stack[len(stack) - 1]
130            list.append((link, label, None))
131               
132        nextPos = match.end()
133
134    while len(stack) > 1:
135        (_, list) = stack.pop()
136        (_, topList) = stack[len(stack) - 1]
137        (topLink, topLabel, _) = topList[len(topList) - 1]
138        topList[len(topList) - 1] = (topLink, topLabel, list)
139
140    (_, list) = stack.pop()
141    return list
142
143
144def execute(hdf, args, env):
145    preview = hdf.getValue('args.preview', "")
146    curpage = hdf.getValue('wiki.page_name', "")
147    name = args
148    if not name:
149        name = 'TOC'
150
151    db = env.get_db_cnx()
152    toc = parseToc(getToc(hdf, env, curpage, name))
153    if not toc:
154        msg = ''
155        msg += '<div class="system-message"><strong>Error: Table of contents does not exist.'
156        if (not preview) and (hdf.getValue('trac.acl.WIKI_MODIFY', '')):
157            msg += ' Click here to <a href="%s?edit=yes">edit</a>.' % env.href.wiki(name)
158        msg += '</strong></div>\n'
159        return msg
160
161    (found, filtered) = filter(curpage, toc, 0)
162    if found:
163        return displayAll(hdf, env, name, curpage, filtered, 0)
164    else:
165        return displayAll(hdf, env, name, curpage, toc, 0)
166
167
168def filter(curpage, toc, level):
169    found = 0
170    result = []
171    for name, title, sub in toc:
172        if sub == None:
173            if name == curpage:
174                found = 1
175            result.append((name, title, None))
176        else:
177            (subfound, subtoc) = filter(curpage, sub, level + 1)
178            if subfound:
179                found = 1
180            if subfound or (name == None):
181                if level == 0 and name != None:
182                    prepended = [(name, title, subtoc)]
183                    prepended.extend(result)
184                    result = prepended
185                else:
186                    result.append((name, title, subtoc))
187            else:
188                result.append((name, title, []))
189    return (found, result)
190
191def indentation(col):
192    return ' ' * col
193
194def displayAll(hdf, env, name, curpage, toc, col):
195    preview = hdf.getValue('args.preview', "")
196    html = ''
197    html += '%s<div class="wiki-toc trac-nav">\n' % indentation(col)
198    col += 1
199
200    html += '%s<h2><a href="http://svn.ipd.uka.de/trac/javaparty/wiki/TracNav">TracNav</a> menu</h2>' % indentation(col)
201
202    if (not preview) and hdf.getValue('trac.acl.WIKI_MODIFY', ''):
203        html += '%s<div class="edit"><a href="%s?edit=yes">edit</a></div>\n' % (indentation(col), env.href.wiki(name))
204    html += '%s<ul>\n' % indentation(col)
205    col += 1
206    html += display(env, curpage, toc, 0, col)
207    col -= 1
208    html += '%s</ul>\n' % indentation(col)
209    col -= 1
210    html += '%s</div>\n' % indentation(col)
211    return html
212
213def display(env, curpage, toc, depth, col):
214    html = ''
215    for name, title, sub in toc:
216        liStyle = ' style="padding-left: %dem;"' % (depth + 1)
217        if sub == None:
218            if name == curpage:
219                cls = ' class="active"'
220            else:
221                cls = ''
222            html += '%s<li%s%s>' % (indentation(col), liStyle, cls)
223            if name == None:
224                html += title
225            else:
226                html += '<a href="%s">%s</a>' % (env.href.wiki(name), title)
227            html += '</li>\n'
228        else:
229            html += '%s<li%s>\n' % (indentation(col), liStyle)
230            col += 1
231            if name == None or len(sub) > 0:
232                html += '%s<h4>%s</h4>\n' % (indentation(col), title)
233            else:
234                html += '%s<h4><a href="%s">%s</a>...</h4>\n' % (indentation(col), env.href.wiki(name), title)
235            col -= 1
236            html += '%s</li>\n' % indentation(col)
237            if len(sub) > 0:
238                html += display(env, curpage, sub, depth + 1, col)
239    return html
240
Note: See TracBrowser for help on using the repository browser.