diff --git a/wiki/theme/crans-www.py b/wiki/theme/crans-www.py new file mode 100644 index 00000000..6e8e9661 --- /dev/null +++ b/wiki/theme/crans-www.py @@ -0,0 +1,500 @@ +# -*- 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 + @license: GNU GPL, see COPYING for details. +""" + +from MoinMoin.theme import ThemeBase +from MoinMoin import wikiutil, i18n +from MoinMoin.Page import Page + +class Theme(ThemeBase): + + name = "crans-www" + + # Standard set of style sheets + stylesheets = ( + # media basename + ('all', 'common'), + ('screen', 'layout'), + ('screen', 'screen'), +# ('print', 'print'), +# ('projection', 'projection'), + ) + + 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"), + ] + + + badgesPath = u'/wiki/common/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'), + ] + + +# 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. + """ + html = [ + u'', + u'', + u'
', + self.logo(), + u'
', + self.startPage(), + self.msg(d), + self.title(d), + ] + return u'\n'.join(html) + + def footer(self, d, **keywords): + """ Assemble wiki footer + """ + html = [ + # End of page + u'
', + self.endPage(), + u'
', + u'
', + self.menu(d), + u'
', + 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'
  • %s
  • ' % (lien, titre)) + html = [ + u'', + ] + return u''.join(html) + + def badges(self,d ): + badges_html = [] + for page, image, alt_text in self.support_badges: + badges_html.append(u'
  • %s
  • ' % (page, self.badgesPath, image, alt_text)) + html = [ + u'\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''' +
    +
    +
    + + +
    + + +
    +
    + ''' % d + return html + + + + def columnone(self, d): + """ assemble all the navigation aids for the page + """ + page = d['page'] + html = [ + u'
    ', + self.editbar(d), + self.username(d), + u'', + self.navibar(d), + self.searchform(d), + self.actionmenu(d), + u'
    ', + u'', + u'
    ' + ] + 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'
  • %s
  • ' % (cls, link)) + + html = [ + u'
    ', + u'', + u'
    ' + ] + 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'
    ', + u'
    Toolbox
    ', + u'
    ', + u'
      ', + u'
    • %s
    ' % '\n
  • '.join(links), + u'', + u'
  • ', + u'
    ', + ] + 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'
    ', + u'', + u'
    ' + ] + 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) + """ + 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'', + ] + return ''.join(html) + + def pageinfo(self, page): + """ Simple override from base class. + Remove

    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 = ('') + 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)s - %(sitename)s' % 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)