1 """MoinMoin theme "err404" by Boris Ganne.
2 Inspired by MoinMoin theme "Mandarin" by Radomir Dopieralski. (SideBar)
3 Inspired by MoinMoin theme "sinorca4moin" by David Linke.
4
5 MoinMoin theme "sinorca4moin" by David Linke.
6 See MoinMoin:DavidLinke/Sinorca4Moin for more infos.
7
8 Version 0.5b : changing css a bit (also made css2.1. compatible) and
9 updating the theme for MoinMoin Version 1.8
10 Attention: this is not an official release, more a
11 personal update (Marcel Haefner)!
12 Version 0.5 : Version adjusted for moin-1.6.x (2007-12-29)
13 Version 0.4 : Extended version adjusted for moin-1.5.x (2006-08-13)
14 Version 0.1-0.3: Initial version for moin-1.3.x (2005)
15
16 Inspired by Haran's sinorca-design published at www.oswd.org.
17
18 $Id: sinorca4moin.py 159 2007-12-29 21:43:07Z linke $
19 """
20
21 import os
22 from MoinMoin.theme import ThemeBase
23 from MoinMoin.Page import Page
24 from MoinMoin.config.multiconfig import _url_re_list, _makeConfig, _getConfigName
25 from MoinMoin import wikiutil, error
26
27 class Theme(ThemeBase):
28
29 name = "err404"
30
31 def farmWikiList(self):
32 """Generate list of links pointing to the wikis of the farm
33
34 Fore each Subwiki a link to Frontpage and RecentChanges (image) is
35 created. If interwiki_preferred is specified in the farmconfig the
36 links will be created only for these wikis else links to all wikis
37 in farmconfig.wiki will be created.
38 """
39 _ = self.request.getText
40 farmwikis = [wiki_name for wiki_name, reg in _url_re_list()]
41 if self.request.cfg.interwiki_preferred:
42 wikis = self.request.cfg.interwiki_preferred
43
44 wikis = [w for w in wikis if w in farmwikis]
45 else:
46 wikis = farmwikis
47
48 if len(wikis) < 2: return []
49
50 linkList = []
51 for wiki_name in wikis:
52 cfg = _makeConfig(wiki_name)
53 highlight = u''
54 if wiki_name == _getConfigName(self.request.url):
55 highlight = u' class="highlight"'
56 try:
57 interwiki_list = wikiutil.load_wikimap(self.request)
58 wiki_url = interwiki_list[cfg.interwikiname]
59 rc = _("RecentChanges", formatted=False)
60 linkList.append( ''.join([
61 u' <a title="%s" href="%s"%s>%s</a>' %
62 (cfg.sitename, wiki_url, highlight, cfg.interwikiname),
63 u'<a title="%s" href="%s%s">' %
64 (rc, wiki_url, wikiutil.quoteWikinameURL(rc)),
65 u'<img src="%s/sinorca4moin/img/moin-diff.png" alt="%s"' %
66 (cfg.url_prefix_static, rc),
67 u' height="11" width="15"></a>'
68 ]))
69 except KeyError:
70 msg = """
71 Missing the wiki '%s' in the interwiki list.
72
73 Please add the interwiki-name and the url of this wiki to 'intermap.txt'.
74 """%wiki_name
75
76 pass
77 return linkList
78
79 def subheader(self):
80 """Make subheader
81
82 Links to subwikis if it's a farm else uses page_header2.
83 """
84 linkList = self.farmWikiList()
85 if len(linkList) > 1:
86 subheader = ' |\n'.join(linkList)
87 else:
88 subheader = self.request.cfg.page_header2
89 return '\n'.join([
90 u'<div class="subHeader">',
91 subheader,
92 u'</div>',
93 ])
94
95 def title(self, d):
96 """ Assemble the title (not as html list as in standard method!)
97
98 Code copied from title-method in __init__.py
99 Only one line was changed.
100
101 @param d: parameter dictionary
102 @rtype: string
103 @return: title html
104 """
105 _ = self.request.getText
106 content = []
107 if d['title_text'] == d['page'].split_title():
108 curpage = ''
109 segments = d['page_name'].split('/')
110 for s in segments[:-1]:
111 curpage += s
112
113 content.append("%s / " % Page(self.request,
114 curpage).link_to(self.request, s))
115 curpage += '/'
116 link_text = segments[-1]
117 link_title = _('Click to do a full-text search for this title',
118 formatted=False)
119 link_query = {
120 'action': 'fullsearch',
121 'value': 'linkto:"%s"' % d['page_name'],
122 'context': '180',
123 }
124
125 link = d['page'].link_to(self.request, link_text,
126 querystr=link_query,
127 title=link_title, css_class='backlink',
128 rel='nofollow')
129 content.append(('<li>%s</li>') % link)
130 else:
131 content.append('<li>%s</li>' % wikiutil.escape(d['title_text']))
132
133 html = '''
134 <ul id="pagelocation">
135 %s
136 </ul>
137 ''' % "".join(content)
138 return html
139
140 def iconbar(self, d):
141 """
142 Assemble the iconbar
143
144 @param d: parameter dictionary
145 @rtype: string
146 @return: iconbar html
147 """
148 iconbar = []
149 if self.cfg.page_iconbar and self.request.user.show_toolbar and d['page_name']:
150 iconbar.append('<ul id="iconbar">\n')
151 icons = self.cfg.page_iconbar[:]
152 for icon in icons:
153 if icon == "up":
154 if d['page_parent_page']:
155 iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
156 elif icon == "subscribe" and self.cfg.mail_enabled:
157 iconbar.append('<li>%s</li>\n' % self.make_iconlink(
158 ["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d))
159 else:
160 iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
161 iconbar.append('</ul>\n')
162 return ''.join(iconbar)
163
164 def wikipanel(self, d):
165 """ Create wiki panel """
166 _ = self.request.getText
167 html = [
168 u'<div class="sidepanel">',
169 u'<h1>%s</h1>' % _("Wiki"),
170 self.navibar(d),
171 u'</div>',
172 ]
173 return u'\n'.join(html)
174
175 def pagepanel(self, d):
176 """ Create page panel """
177 _ = self.request.getText
178 if self.shouldShowEditbar(d['page']):
179 html = [
180 u'<div class="sidepanel">',
181 u'<h1>%s</h1>' % _("Page"),
182 self.editbar(d),
183 u'</div>',
184 ]
185 return u'\n'.join(html)
186 return ''
187
188 def userpanel(self, d):
189 """ Create user panel """
190 _ = self.request.getText
191
192 html = [
193 u'<div class="sidepanel">',
194 u'<h1>%s</h1>' % _("User"),
195 self.username(d),
196 u'</div>'
197 ]
198 return u'\n'.join(html)
199
200 def linkedSitename(self):
201 """Create title from sitename and link to FrontPage"""
202 frontpage = wikiutil.getFrontPage(self.request).page_name
203 html = wikiutil.link_tag(self.request,
204 wikiutil.quoteWikinameURL(frontpage),
205 self.request.cfg.sitename)
206 return html
207
208 def flexible_userhome(self, d):
209 """Determine content in superheader and sidebar based on page_header1
210 """
211 if self.cfg.page_header1:
212 superheader = self.cfg.page_header1
213 userpanel = self.userpanel(d)
214 else:
215
216 superheader = '\n'.join([
217 u' <div class="right">',
218 self.username(d),
219 u' </div>',
220 ])
221 userpanel = ''
222 return superheader, userpanel
223
224 def shortenPagename(self, name):
225 """ Shorten page names (overrides default method)
226
227 changed compared to default: for hierarchical names a part of
228 the first level is always shown.
229
230 @param name: page name, unicode
231 @rtype: unicode
232 @return: shortened version of page name
233 """
234 l1Length = 8
235 maxLength = self.maxPagenameLength()
236 if len(name) > maxLength:
237 half, left = divmod(maxLength, 2)
238 name = name.split('/')
239 parts = len(name)
240
241 if parts > 2:
242 nameStart, nameEnd = name[0], name[-1]
243 if (len(nameStart) + len(nameEnd) > maxLength-4
244 and len(nameStart) > l1Length):
245
246 if len(nameEnd) > maxLength-6-l1Length:
247 name = u'%s../../%s..' % (nameStart[:l1Length],
248 nameEnd[:maxLength-8-l1Length])
249 else:
250 lenStart = max(maxLength-len(nameEnd)-6, l1Length)
251 name = u'%s../../%s' % (nameStart[:lenStart],
252 nameEnd[:maxLength-6-lenStart])
253 elif len(nameStart) + len(nameEnd) > maxLength-4:
254
255 name = u'%s/../%s..' % (nameStart,
256 nameEnd[:maxLength-6-len(nameStart)])
257 else:
258 name = u'%s/../%s' % (nameStart, nameEnd)
259 elif parts == 2:
260 nameStart, nameEnd = name[0], name[-1]
261 if (len(nameStart) + len(nameEnd) > maxLength-1
262 and len(nameStart) > l1Length):
263
264 if len(nameEnd) > maxLength-3-l1Length:
265 name = u'%s../%s..' % (nameStart[:l1Length],
266 nameEnd[:maxLength-5-l1Length])
267 else:
268 lenStart = max(maxLength-len(nameEnd)-3, l1Length)
269 name = u'%s../%s' % (nameStart[:lenStart],
270 nameEnd[:maxLength-3-lenStart])
271 elif len(nameStart) + len(nameEnd) > maxLength-1:
272
273 name = u'%s/%s..' % (nameStart,
274 nameEnd[:maxLength-3-len(nameStart)])
275 else:
276 name = u'%s/%s' % (nameStart, nameEnd)
277 else:
278
279 half, left = divmod(maxLength-3, 2)
280 name = name[0]
281 name = u'%s...%s' % (name[:half + left], name[-half:])
282 return name
283
284 def sidebar(self, d, **keywords):
285 """ Display page called SideBar as an additional element on every page
286
287 @param d: parameter dictionary
288 @rtype: string
289 @return: sidebar html
290 """
291 request = self.request
292 _ = self.request.getText
293 sidebar = request.getPragma('sidebar') or u'SideBar';
294 page = Page(request, sidebar)
295 if not page.exists():
296 return u""
297 import StringIO
298 buff = StringIO.StringIO()
299 request.redirect(buff)
300 try:
301 try:
302 page.send_page(content_only=1, content_id="sidebar")
303 except TypeError:
304 page.send_page(request, content_only=1, content_id="sidebar")
305 finally:
306 request.redirect()
307
308 return u'<div class="sidepanel">%s</div>' % buff.getvalue()
309
310
311
312 def header(self, d):
313 """
314 Assemble page header
315
316 @param d: parameter dictionary
317 @rtype: string
318 @return: page header html
319 """
320 _ = self.request.getText
321
322 superheader, userpanel = self.flexible_userhome(d)
323
324 html = [
325
326 u'<div id="header" class="header">',
327
328
329 u' <div class="superHeader">',
330 superheader,
331 u' </div>',
332 self.searchform(d),
333
334
335 u' <div class="midHeader">',
336 u' <div id="locationline">',
337 self.logo(),
338
339 self.linkedSitename(),
340 u' </div>',
341 u' </div>',
342
343
344
345
346
347
348
349
350 self.trail(d),
351 u'</div>',
352
353
354
355 u'<div class="sidebar">',
356 self.wikipanel(d),
357 self.pagepanel(d),
358
359 self.sidebar(d),
360
361 userpanel,
362 u'</div>',
363
364 self.msg(d),
365
366
367 self.startPage(),
368
369
370 self.iconbar(d),
371
372 self.title(d),
373 ]
374 return u'\n'.join(html)
375
376 def editorheader(self, d):
377 """
378 Assemble page header for editor
379
380 @param d: parameter dictionary
381 @rtype: unicode
382 @return: page header html
383 """
384 _ = self.request.getText
385 superheader, userpanel = self.flexible_userhome(d)
386
387 html = [
388
389 u' <div id="header" class="header">',
390
391
392 u' <div class="superHeader">',
393 superheader,
394 u' </div>',
395
396
397 u' <div class="midHeader">',
398 self.searchform(d),
399 u' <div id="locationline">',
400 self.logo(),
401
402 self.linkedSitename(),
403 u' </div>',
404 u' </div>',
405
406
407
408
409 u'</div>',
410
411
412
413 u'<div class="sidebar">',
414 self.wikipanel(d),
415 self.pagepanel(d),
416
417 self.sidebar(d),
418
419 userpanel,
420 u'</div>',
421
422 self.msg(d),
423
424
425 self.startPage(),
426 ]
427 return u'\n'.join(html)
428
429 def footer(self, d, **keywords):
430 """ Assemble page footer
431
432 @param d: parameter dictionary
433 @keyword ...:...
434 @rtype: unicode
435 @return: page footer html
436 """
437 page = d['page']
438 html = [
439
440
441
442 self.pageinfo(page),
443 self.endPage(),
444
445
446
447
448
449 u'<div id="footer">',
450 self.credits(d),
451 self.showversion(d, **keywords),
452 u'</div>',
453
454
455
456 ]
457 return u'\n'.join(html)
458
459 def splitNavilink_off(self, text, localize=1):
460 """ Split navibar links into pagename, link to page
461
462 This overrides the defaut method. In contrast to default quicklinks
463 are cut down to a maximum length
464
465 @param text: the text used in config or user preferences
466 @rtype: tuple
467 @return: pagename or url, link to page or url
468 """
469 request = self.request
470
471
472 if text.startswith('[') and text.endswith(']'):
473 try:
474 pagename, title = text[1:-1].strip().split(' ', 1)
475 title = title.strip()
476 localize = 0
477 except (ValueError, TypeError):
478
479 pagename = title = text
480
481
482 else:
483
484 if localize:
485 page = wikiutil.getLocalizedPage(request, text)
486 else:
487 page = Page(request, text)
488 pagename = page.page_name
489 title = page.split_title(request)
490 title = self.shortenPagename(title)
491 link = page.link_to(request, title)
492
493
494 from MoinMoin import config
495 for scheme in self.linkSchemas:
496 if pagename.startswith(scheme):
497 title = self.shortenPagename(wikiutil.escape(title))
498 link = '<a href="%s">%s</a>' % (pagename, title)
499 return pagename, link
500
501
502 if pagename.startswith("wiki:"):
503 pagename = pagename[5:]
504
505
506 try:
507 interwiki, page = pagename.split(':', 1)
508 thiswiki = request.cfg.interwikiname
509 if interwiki == thiswiki:
510 pagename = page
511 title = self.shortenPagename(page)
512 else:
513 return (pagename,
514 self.request.formatter.interwikilink(True, interwiki, page) +
515 page +
516 self.request.formatter.interwikilink(False, interwiki, page)
517 )
518
519 except ValueError:
520 pass
521
522
523
524
525
526 pagename = request.normalizePagename(pagename)
527 link = Page(request, pagename).link_to(request, title)
528
529 return pagename, link
530
531 def execute(request):
532 """ Generate and return a theme object
533
534 @param request: the request object
535 @rtype: MoinTheme
536 @return: Theme object
537 """
538 return Theme(request)
539