
Apparemment rcuprer le ThemeCrans n'est pas apprci par moinmoin, il faut donc rcuprer les lments que l'on veut l'un aprs l'autre Ajout d'un 'badge' pour avoir accs la page en mode wiki, mais il faudrait une icone associ. Grgoire pourrais-tu, si tu peux, mettre sur le wiki ta manire de les raliser ? darcs-hash:20060415211926-72cb0-f44bb41387759ad64a714eb3b050397296825ad0.gz
502 lines
18 KiB
Python
502 lines
18 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>
|
|
@license: GNU GPL, see COPYING for details.
|
|
"""
|
|
|
|
from MoinMoin.theme import ThemeBase
|
|
from MoinMoin import wikiutil, i18n
|
|
from MoinMoin.Page import Page
|
|
from crans import ThemeCrans
|
|
|
|
class Theme(ThemeBase):
|
|
icons = ThemeCrans.icons
|
|
|
|
name = "crans-www"
|
|
|
|
# Liste des feuilles de style
|
|
stylesheets = (
|
|
# media basename
|
|
('all', 'common'),
|
|
('screen', 'layout'),
|
|
('screen', 'screen'),
|
|
# ('print', 'print'),
|
|
# ('projection', 'projection'),
|
|
)
|
|
|
|
# liste des liens du menu
|
|
menu_links = [
|
|
# tire #lien
|
|
(u"Accueil", u"http://www.crans.org/"),
|
|
(u"Webmail", u"https://webmail.crans.org/"),
|
|
(u"Accès SSH", u"http://www.crans.org/VieCrans/OpenSsh"),
|
|
(u"Accès Intranet",u""),
|
|
(u"Pages persos", u"http://www.crans.org/PagesPerso"),
|
|
]
|
|
|
|
# Chemin des badges
|
|
badgesPath = u'/wiki/common/badges/'
|
|
|
|
# liste des badges
|
|
support_badges = [
|
|
# page, # image # alt text
|
|
(u'http://www.firefox.fr/', u'badges_80x15_firefox.png', u'Get firefox'),
|
|
(u'http://www.debian.org/', u'badges_80x15_debian.png', u'Debian powered'),
|
|
(u'http://www.apache.org/', u'badges_80x15_apache.png', u'Apache powered'),
|
|
(u'http://www.python.org/', u'badges_80x15_python.png', u'Python powered'),
|
|
(u'http://www.crans.org/', u'badges_80x15_crans.png', u'Cr@ns powered'),
|
|
(u'wiki', u'badges_80x15_crans.png', u'Wiki powered'),
|
|
]
|
|
|
|
# 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">',
|
|
self.logo(),
|
|
u'<div id="column-content">',
|
|
self.startPage(),
|
|
self.msg(d),
|
|
self.title(d)[:-6], # On enlève </h1>
|
|
parent and wikiutil.link_tag(self.request,
|
|
parent.page_name,
|
|
u'<img src="/wiki/crans-www/img/go-up.png" alt="Haut">') or u'',
|
|
u'</h1>'
|
|
]
|
|
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.menu(d),
|
|
u'</div>',
|
|
self.username(d),
|
|
self.badges(d),
|
|
]
|
|
return u'\n'.join(html)
|
|
|
|
def menu(self, d):
|
|
""" assemble all the navigation aids for the page
|
|
"""
|
|
liens = []
|
|
for titre, lien in self.menu_links:
|
|
liens.append(u'<li><a href="%s">%s</a></li>' % (lien, titre))
|
|
html = [
|
|
u'<div class="portlet" id="MenuNavigation">',
|
|
u'<ul>',
|
|
u'\n'.join(liens),
|
|
u'<li>%s</li>' % self.searchform(d),
|
|
u'</ul>',
|
|
u'</div>',
|
|
]
|
|
return u''.join(html)
|
|
|
|
def badges(self,d ):
|
|
badges_html = []
|
|
for page, image, alt_text in self.support_badges:
|
|
if page == u'wiki' :
|
|
page = u'http://wiki.crans.org/%s' % d['page'].page_name
|
|
badges_html.append(u'<li><a href="%s"><img src="%s%s" alt="%s"></a></li>' % (page, self.badgesPath, image, alt_text))
|
|
html = [
|
|
u'<ul class="supportBadges">',
|
|
u'\n'.join(badges_html),
|
|
u'</ul>\n\n',
|
|
]
|
|
|
|
return u''.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'''
|
|
<form id="searchform" method="get" action="">
|
|
<h5><label for="searchInput">%(search_label)s</label></h5>
|
|
<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"><br />
|
|
<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>
|
|
''' % d
|
|
return 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),
|
|
u'<div class="portlet" id="p-logo">',
|
|
self.logo(),
|
|
u'</div>',
|
|
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 = [('show', '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', ['show'])[0]
|
|
for action, title, description, accesskey in tabs:
|
|
if action == current:
|
|
cls = 'selected'
|
|
else:
|
|
cls = 'none'
|
|
|
|
if action == 'edit':
|
|
if page.isWritable() and request.user.may.write(page.page_name):
|
|
pass
|
|
else:
|
|
action = 'raw'
|
|
title = 'View Source'
|
|
description = 'This page is protected. You can view its source'
|
|
|
|
if action == 'subscribe':
|
|
user = self.request.user
|
|
if not self.cfg.mail_smarthost or not user.valid:
|
|
break
|
|
# Email enabled and user valid, get current page status
|
|
if user.isSubscribedTo([page.page_name]):
|
|
title = 'Unsubscribe'
|
|
description = 'Unsubscribe from updates to this page'
|
|
|
|
if action == 'show':
|
|
url = quotedname
|
|
else:
|
|
url = quotedname + '?action=' + action
|
|
|
|
attrs = self.extendedAttrs(_(description), accesskey)
|
|
link = wikiutil.link_tag(self.request, url, _(title), attrs=attrs)
|
|
items.append(u'<li class="%s">%s</li>' % (cls, link))
|
|
|
|
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',
|
|
'refresh',
|
|
'AttachFile',
|
|
'SpellCheck',
|
|
'LikePages',
|
|
'LocalSiteMap',
|
|
'RenamePage',
|
|
'DeletePage',
|
|
]
|
|
|
|
titles = {
|
|
'raw': _('Show Raw Text', formatted=False),
|
|
'print': _('Show Print View', 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 = []
|
|
|
|
# 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></ul>' % '</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'<ul id="username">',
|
|
u'<li class="pt-userpage">%s</li>' % '</li>\n<li>'.join(userlinks),
|
|
u'</ul>',
|
|
u'</div>'
|
|
]
|
|
return ''.join(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)
|
|
"""
|
|
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="MenuNavigation">',
|
|
u'<ul>',
|
|
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
|
|
u'</ul>',
|
|
u'</div>',
|
|
]
|
|
return ''.join(html)
|
|
|
|
def pageinfo(self, page):
|
|
""" Simple override from base class.
|
|
Remove <p> so footer isn't too big
|
|
"""
|
|
_ = self.request.getText
|
|
|
|
if self.shouldShowPageinfo(page):
|
|
info = page.lastEditInfo()
|
|
if info:
|
|
if info['editor']:
|
|
info = _("last edited %(time)s by %(editor)s") % info
|
|
else:
|
|
info = _("last modified %(time)s") % info
|
|
return info
|
|
return ''
|
|
|
|
def rtl_stylesheet(self, d):
|
|
""" monobook uses a separate css page for rtl alterations.
|
|
Add the rtl stylesheet if the user needs it
|
|
"""
|
|
link = ('<link rel="stylesheet" type="text/css" charset="%s"'
|
|
' media="%s" href="%s">')
|
|
html = []
|
|
if i18n.getDirection(self.request.lang) == 'rtl':
|
|
prefix = self.cfg.url_prefix
|
|
href = '%s/%s/css/%s.css' % (prefix, self.name, 'rtl')
|
|
html.append(link % (self.stylesheetsCharset, 'all', href))
|
|
return '\n'.join(html)
|
|
|
|
def html_head(self, d):
|
|
""" Tweak the sending of the head, to include right-to-left
|
|
alterations if necessary
|
|
"""
|
|
html = [
|
|
u'<title>%(title)s - %(sitename)s</title>' % d,
|
|
self.headscript(d), # Should move to separate .js file
|
|
self.html_stylesheets(d),
|
|
self.rtl_stylesheet(d),
|
|
self.rsslink(),
|
|
]
|
|
return '\n'.join(html)
|
|
|
|
def execute(request):
|
|
"""
|
|
Generate and return a theme object
|
|
|
|
@param request: the request object
|
|
@rtype: MoinTheme
|
|
@return: Theme object
|
|
"""
|
|
return Theme(request)
|