
boite de recherche de firefox darcs-hash:20061213214545-f46e9-fa8ce6a5109f48d8aee162e1dcfd8e713863ab90.gz
472 lines
17 KiB
Python
472 lines
17 KiB
Python
# -*- coding: iso-8859-1 -*-
|
||
"""
|
||
MoinMoin monobook theme. Uses the css sheet from
|
||
http://wikipedia.org, adapting the moin output to fit it.
|
||
|
||
Adapted by Jim Clark <jim AT clarkster DOT co DOT uk>
|
||
Adapted for CR@NS by Nicolas Salles <salles AT crans DOT org>
|
||
@license: GNU GPL, see COPYING for details.
|
||
"""
|
||
|
||
from MoinMoin.theme import ThemeBase
|
||
from MoinMoin import wikiutil, i18n
|
||
from MoinMoin.Page import Page
|
||
|
||
class ThemeCrans(ThemeBase):
|
||
|
||
name = "crans"
|
||
|
||
# fake _ function to get gettext recognize those texts:
|
||
_ = lambda x: x
|
||
|
||
icons = {
|
||
# key alt icon filename w h
|
||
# ------------------------------------------------------------------
|
||
# navibar
|
||
'help': ("%(page_help_contents)s", "moin-help.png", 12, 11),
|
||
'find': ("%(page_find_page)s", "moin-search.png", 12, 12),
|
||
'diff': (_("Diffs"), "moin-diff.png", 22, 22),
|
||
'info': (_("Info"), "moin-info.png", 22, 22),
|
||
'edit': (_("Edit"), "moin-edit.png", 22, 22),
|
||
'unsubscribe':(_("Unsubscribe"), "moin-unsubscribe.png", 22, 22),
|
||
'subscribe': (_("Subscribe"), "moin-subscribe.png",22, 22),
|
||
'raw': (_("Raw"), "moin-raw.png", 12, 13),
|
||
'xml': (_("XML"), "moin-xml.png", 20, 13),
|
||
'print': (_("Print"), "moin-print.png", 16, 14),
|
||
'view': (_("View"), "moin-show.png", 22, 22),
|
||
'home': (_("Home"), "moin-home.png", 13, 12),
|
||
'up': (_("Up"), "moin-parent.png", 15, 13),
|
||
# FileAttach
|
||
'attach': ("%(attach_count)s", "moin-attach.png", 7, 15),
|
||
# RecentChanges
|
||
'rss': (_("[RSS]"), "moin-rss.png", 36, 14),
|
||
'deleted': (_("[DELETED]"), "moin-supprime.png",51, 12),
|
||
'updated': (_("[UPDATED]"), "moin-modifie.png",45, 12),
|
||
'new': (_("[NEW]"), "moin-nouveau.png", 51, 12),
|
||
'diffrc': (_("[DIFF]"), "moin-diff.png", 22, 22),
|
||
# General
|
||
'bottom': (_("[BOTTOM]"), "moin-bottom.png", 14, 10),
|
||
'top': (_("[TOP]"), "moin-top.png", 14, 10),
|
||
'www': ("[WWW]", "moin-www.png", 11, 11),
|
||
'mailto': ("[MAILTO]", "moin-email.png", 14, 10),
|
||
'news': ("[NEWS]", "moin-news.png", 10, 11),
|
||
'telnet': ("[TELNET]", "moin-telnet.png", 10, 11),
|
||
'ftp': ("[FTP]", "moin-ftp.png", 11, 11),
|
||
'file': ("[FILE]", "moin-ftp.png", 11, 11),
|
||
# search forms
|
||
'searchbutton': ("[?]", "moin-search.png", 12, 12),
|
||
'interwiki': ("[%(wikitag)s]", "moin-inter.png", 16, 16),
|
||
}
|
||
del _
|
||
|
||
# Standard set of style sheets
|
||
stylesheets = (
|
||
# media basename
|
||
('all', 'common'),
|
||
('screen', 'crans'),
|
||
('print', 'print'),
|
||
('projection', 'projection'),
|
||
)
|
||
|
||
|
||
# Public functions #####################################################
|
||
|
||
def header(self, d, **kw):
|
||
""" Assemble wiki header
|
||
Here we don't add any menu bars, search bars, etc - instead wait
|
||
until the footer. This keeps the HTML cleaner and more accessible,
|
||
making sure the main content arrives first.
|
||
"""
|
||
parent = d['page'].getParentPage()
|
||
html = [
|
||
u'<div id="globalWrapper">',
|
||
u'<div id="column-content">',
|
||
self.msg(d),
|
||
self.startPage(),
|
||
u'<div id="titleBarre">',
|
||
self.title(d)[:-6], # On enl<6E>ve </h1>
|
||
parent and wikiutil.link_tag(self.request,
|
||
parent.page_name,
|
||
u'<img src="/wiki/crans/img/go-up.png" alt="Haut">') or u'',
|
||
u'</h1>'
|
||
u'</div>',
|
||
]
|
||
return u'\n'.join(html)
|
||
|
||
def footer(self, d, **keywords):
|
||
""" Assemble wiki footer
|
||
"""
|
||
html = [
|
||
# End of page
|
||
u'<div class="visualClear"></div>',
|
||
self.endPage(),
|
||
u'<div class="visualclear"></div>',
|
||
u'</div>',
|
||
self.columnone(d),
|
||
u'</div>',
|
||
u"<div id=\"specialNoel\"></div>"
|
||
]
|
||
return u'\n'.join(html)
|
||
|
||
def columnone(self, d):
|
||
""" assemble all the navigation aids for the page
|
||
"""
|
||
page = d['page']
|
||
html = [
|
||
u'<div id="column-one">',
|
||
self.editbar(d),
|
||
self.username(d),
|
||
self.navibar(d),
|
||
self.searchform(d),
|
||
self.actionmenu(d),
|
||
u'<div class="visualClear"></div>',
|
||
u'<div id="footer">',
|
||
self.pageinfo(page),
|
||
self.credits(d),
|
||
u'</div>',
|
||
u'</div>'
|
||
]
|
||
return u'\n'.join(html)
|
||
|
||
def headscript(self, d):
|
||
""" Override to not output search/action menu javascript.
|
||
(perhaps not a good idea)
|
||
"""
|
||
return ''
|
||
|
||
def extendedAttrs(self, title, accesskey):
|
||
""" Helper function for assembling titled access key links
|
||
"""
|
||
return 'title="%(title)s [alt-%(accesskey)s]" accesskey=%(accesskey)s' % \
|
||
{'accesskey' : accesskey,
|
||
'title' : title}
|
||
|
||
def editbar(self, d):
|
||
""" Display a list of actions for the page. This list will be turned
|
||
into a set of tabbed views on the page by the css.
|
||
"""
|
||
page = d['page']
|
||
if not self.shouldShowEditbar(page):
|
||
return ''
|
||
|
||
# Use cached editbar if possible.
|
||
cacheKey = 'editbar'
|
||
cached = self._cache.get(cacheKey)
|
||
if cached:
|
||
return cached
|
||
|
||
request = self.request
|
||
_ = self.request.getText
|
||
link = wikiutil.link_tag
|
||
quotedname = wikiutil.quoteWikinameURL(page.page_name)
|
||
# action, title, description, accesskey
|
||
tabs = [('view', 'Article', 'View the page content', 'c'),
|
||
('edit', 'Edit', 'Edit this page', 'e'),
|
||
('diff', 'Show Changes', 'Last page modification', 'd'),
|
||
('info', 'Get Info', 'Page history and information', 'h'),
|
||
('subscribe', 'Subscribe', 'Subscribe to updates to this page', 'w')]
|
||
|
||
items = []
|
||
current = self.request.form.get('action', ['view'])[0]
|
||
for action, title, description, accesskey in tabs:
|
||
if action == current:
|
||
cls = 'selected'
|
||
else:
|
||
cls = 'none'
|
||
|
||
if action == "subscribe":
|
||
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(
|
||
["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d)))
|
||
else:
|
||
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(action, d)))
|
||
|
||
html = [
|
||
u'<div id="p-cactions" class="portlet">',
|
||
u'<ul class="editbar">',
|
||
''.join(items),
|
||
u'</ul>',
|
||
u'</div>'
|
||
]
|
||
html = ''.join(html)
|
||
# cache for next call
|
||
self._cache[cacheKey] = html
|
||
|
||
return html
|
||
|
||
|
||
def actionmenu(self, d):
|
||
""" different implementation of the actionmenu (aka toolbox)
|
||
"""
|
||
|
||
page = d['page']
|
||
|
||
# Use cached actionmenu if possible.
|
||
cacheKey = 'actionmenu'
|
||
cached = self._cache.get(cacheKey)
|
||
if cached:
|
||
return cached
|
||
|
||
request = self.request
|
||
_ = request.getText
|
||
quotedname = wikiutil.quoteWikinameURL(page.page_name)
|
||
|
||
menu = [
|
||
'raw',
|
||
'print',
|
||
u'format&mimetype=text/latex',
|
||
u'format&mimetype=text/plain',
|
||
'refresh',
|
||
'AttachFile',
|
||
'SpellCheck',
|
||
'LikePages',
|
||
'LocalSiteMap',
|
||
'RenamePage',
|
||
'DeletePage',
|
||
]
|
||
|
||
titles = {
|
||
'raw': _('Show Raw Text', formatted=False),
|
||
'print': _('Show Print View', formatted=False),
|
||
u'format&mimetype=text/latex': _('Obtenir le code latex', formatted=False),
|
||
u'format&mimetype=text/plain': _('Version texte (en test)', formatted=False),
|
||
'refresh': _('Delete Cache', formatted=False),
|
||
'AttachFile': _('Attach File', formatted=False),
|
||
'SpellCheck': _('Check Spelling', formatted=False), # rename action!
|
||
'RenamePage': _('Rename Page', formatted=False),
|
||
'DeletePage': _('Delete Page', formatted=False),
|
||
'LikePages': _('Show Like Pages', formatted=False),
|
||
'LocalSiteMap': _('Show Local Site Map', formatted=False),
|
||
}
|
||
|
||
links = [ '<a href="http://www.crans.org/%s">Voir la page web</a>' % page.page_name ]
|
||
|
||
# Format standard actions
|
||
available = request.getAvailableActions(page)
|
||
for action in menu:
|
||
# Enable delete cache only if page can use caching
|
||
if action == 'refresh':
|
||
if not page.canUseCache():
|
||
break
|
||
# Actions which are not available for this wiki, user or page
|
||
if action[0].isupper() and not action in available:
|
||
break;
|
||
|
||
link = wikiutil.link_tag(self.request, \
|
||
quotedname + '?action=' + action, titles[action])
|
||
links.append(link)
|
||
|
||
# Add custom actions not in the standard menu
|
||
more = [item for item in available if not item in titles]
|
||
more.sort()
|
||
if more:
|
||
# Add more actions (all enabled)
|
||
for action in more:
|
||
data = {'action': action, 'disabled': ''}
|
||
title = Page(request, action).split_title(request, force=1)
|
||
# Use translated version if available
|
||
title = _(title, formatted=False)
|
||
link = wikiutil.link_tag(self.request, \
|
||
quotedname + '?action=' + action, title)
|
||
links.append(link)
|
||
|
||
html = [
|
||
u'<div class="portlet" id="p-tb">',
|
||
u'<h5>Toolbox</h5>',
|
||
u'<div class="pBody">',
|
||
u'<ul>',
|
||
u'<li>%s</li>' % '</li>\n<li>'.join(links),
|
||
u'</ul>',
|
||
u'</div>',
|
||
u'</div>',
|
||
]
|
||
html = ''.join(html)
|
||
# cache for next call
|
||
self._cache[cacheKey] = html
|
||
return html
|
||
|
||
|
||
def username(self, d):
|
||
""" Assemble the username / userprefs link
|
||
Copied from the base class, modified to include hotkeys and link titles
|
||
"""
|
||
from MoinMoin.Page import Page
|
||
request = self.request
|
||
_ = request.getText
|
||
|
||
userlinks = []
|
||
# Add username/homepage link for registered users. We don't care
|
||
# if it exists, the user can create it.
|
||
if request.user.valid:
|
||
homepage = Page(request, request.user.name)
|
||
title = homepage.split_title(request)
|
||
attrs = self.extendedAttrs(_('User Page'), '.')
|
||
homelink = homepage.link_to(request, text=title, attrs=attrs)
|
||
userlinks.append(homelink)
|
||
|
||
# Set pref page to localized Preferences page
|
||
attrs = self.extendedAttrs(_('My Preferences'), 'u')
|
||
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
|
||
title = prefpage.split_title(request)
|
||
userlinks.append(prefpage.link_to(request, text=title, attrs=attrs))
|
||
|
||
# Add a logout link (not sure this is really necessary
|
||
attrs = self.extendedAttrs(_('log out'), 'o')
|
||
page = d['page']
|
||
url = wikiutil.quoteWikinameURL(page.page_name) + \
|
||
'?action=userform&logout=1'
|
||
link = wikiutil.link_tag(self.request, url, 'log out', attrs=attrs)
|
||
userlinks.append(link)
|
||
|
||
else:
|
||
# Add prefpage links with title: Login
|
||
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
|
||
attrs = self.extendedAttrs('Logging in is not required, but brings benefits', 'o')
|
||
userlinks.append(prefpage.link_to(request, text=_("Login"), attrs=attrs))
|
||
|
||
html = [
|
||
u'<div class="portlet" id="p-personal">',
|
||
u'<h5>Personnel</h5>',
|
||
u'<ul id="username">',
|
||
u'<li class="pt-userpage">%s</li>' % '</li>\n<li>'.join(userlinks),
|
||
u'</ul>',
|
||
u'</div>'
|
||
]
|
||
return ''.join(html)
|
||
|
||
def searchform(self, d):
|
||
""" assemble HTML code for the search form
|
||
Tweaks from the bass class to wrap in a 'portlet' class, move the
|
||
description to a header tag, add an access key of 'f' and
|
||
add SearchButton class for the buttons
|
||
"""
|
||
_ = self.request.getText
|
||
form = self.request.form
|
||
updates = {
|
||
'search_label' : _('Search:'),
|
||
'search_value': wikiutil.escape(form.get('value', [''])[0], 1),
|
||
'search_full_label' : _('Text', formatted=False),
|
||
'search_title_label' : _('Titles', formatted=False),
|
||
}
|
||
d.update(updates)
|
||
|
||
html = u'''
|
||
<div class="portlet" id="p-search">
|
||
<h5><label for="searchInput">%(search_label)s</label></h5>
|
||
<div class="pBody">
|
||
<form id="searchform" method="get" action="">
|
||
<div>
|
||
<input type="hidden" name="action" value="fullsearch">
|
||
<input type="hidden" name="context" value="180">
|
||
<input id="searchInput" name="value" type="text" accesskey="f"
|
||
value="%(search_value)s">
|
||
<input id="titlesearch" name="titlesearch" type="submit" class="searchButton"
|
||
value="%(search_title_label)s" alt="Search Titles">
|
||
<input id="fullsearch" name="fullsearch" type="submit" class="searchButton"
|
||
value="%(search_full_label)s" alt="Search Full Text">
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
''' % d
|
||
return html
|
||
|
||
def shouldShowEditbar(self, page):
|
||
""" Override to include the editbar on edit/preview pages.
|
||
(at the risk that the user may accidentally cancel an edit)
|
||
"""
|
||
if (page.exists(includeDeleted=1) and
|
||
self.request.user.may.read(page.page_name)):
|
||
return True
|
||
return False
|
||
|
||
|
||
def navibar(self, d):
|
||
""" Alterations from the base class to include access keys and
|
||
descriptions for FrontPage/RecentChanges
|
||
"""
|
||
request = self.request
|
||
found = {} # pages we found. prevent duplicates
|
||
links = [] # navibar items
|
||
current = d['page_name']
|
||
|
||
# Process config navi_bar
|
||
if request.cfg.navi_bar:
|
||
for text in request.cfg.navi_bar:
|
||
pagename, link = self.splitNavilink(text)
|
||
if pagename == d['page_front_page']:
|
||
attrs = self.extendedAttrs('Visit the main page', 'z')
|
||
elif pagename == 'RecentChanges':
|
||
attrs = self.extendedAttrs('List of recent changes in this wiki', 'r')
|
||
else:
|
||
attrs = ''
|
||
|
||
a = wikiutil.link_tag(request, pagename, attrs=attrs)
|
||
links.append(a)
|
||
found[pagename] = 1
|
||
|
||
# Add user links to wiki links, eliminating duplicates.
|
||
userlinks = request.user.getQuickLinks()
|
||
for text in userlinks:
|
||
# Split text without localization, user know what she wants
|
||
pagename, link = self.splitNavilink(text, localize=0)
|
||
if not pagename in found:
|
||
a = wikiutil.link_tag(request, pagename, attrs=attrs)
|
||
links.append(a)
|
||
found[pagename] = 1
|
||
|
||
html = [
|
||
u'<div class="portlet" id="p-nav">',
|
||
u'<h5>Navigation</h5>',
|
||
u'<div class="pBody">',
|
||
u'<ul id="navibar">',
|
||
u'<li>%s</li>' % '</li>\n<li>'.join(links),
|
||
u'</ul>',
|
||
u'</div>',
|
||
u'</div>',
|
||
]
|
||
return ''.join(html)
|
||
|
||
|
||
def html_head(self, d):
|
||
""" add opensearch description to html head
|
||
"""
|
||
# common prefix for static content
|
||
prefix = self.cfg.url_prefix
|
||
open_search_desc = """
|
||
<link rel="search" type="application/opensearchdescription+xml" href="%(page)s?action=opensearch&searchtype=Titres" title="%(sitename)s, Rechercher dans les titres" />
|
||
<link rel="search" type="application/opensearchdescription+xml" href="%(page)s?action=opensearch&searchtype=Texte" title="%(sitename)s, Rechercher dans le texte" />
|
||
""" % {'page':self.request.path_info, 'sitename':d['sitename']}
|
||
|
||
#d['page'].request.script_name, 'sitename':d['sitename']}
|
||
|
||
classic_head = ThemeBase.html_head(self, d)
|
||
return classic_head + open_search_desc + str(self.request.path_info)
|
||
|
||
class Theme(ThemeCrans):
|
||
|
||
name = "crans"
|
||
|
||
# Standard set of style sheets
|
||
stylesheets = (
|
||
# media basename
|
||
('all', 'common'),
|
||
('screen', 'crans'),
|
||
('print', 'print'),
|
||
('projection', 'projection'),
|
||
)
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
def execute(request):
|
||
"""
|
||
Generate and return a theme object
|
||
|
||
@param request: the request object
|
||
@rtype: MoinTheme
|
||
@return: Theme object
|
||
"""
|
||
return Theme(request)
|