# -*- coding: iso-8859-1 -*- """ MoinMoin nillo theme (bassed on classic theme by Thomas Waldmann) @copyright: 2004 by NiklasGidion (niklas.gidion@web.de) @license: GNU GPL, see COPYING for details. """ import urllib, re from MoinMoin import config, i18n, wikiutil, version from MoinMoin.Page import Page class Theme: """ here are the functions generating the html responsible for the look and feel of your wiki site """ name = "nillo" icons = { # key alt icon filename w h # ------------------------------------------------------------------ # navibar 'help': ("%(page_help_contents)s", "moin-help.png", 22, 22), 'find': ("%(page_find_page)s", "moin-search-big.png", 22, 22), 'diff': ("Diffs", "moin-diff.png", 25, 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", 22, 22), 'xml': ("XML", "moin-xml2.png", 36, 14), 'print': ("Print", "moin-print.png", 22, 22), 'view': ("View", "moin-show.png", 22, 22), 'home': ("Home", "moin-home.png", 22, 22), 'up': ("Up", "moin-parent.png", 22, 22), # FileAttach (is this used?) 'attach': ("%(attach_count)s", "moin-attach.png", 22, 22), # RecentChanges 'rss': ("[RSS]", "moin-rss.png", 36, 14), 'deleted': ("[DELETED]", "moin-deleted.png",22, 22), 'updated': ("[UPDATED]", "moin-updated.png",25, 22), 'new': ("[NEW]", "moin-new.png", 22, 22), 'diffrc': ("[DIFF]", "moin-diff.png", 25, 22), # General 'bottom': ("[BOTTOM]", "moin-bottom.png", 14, 10), 'top': ("[TOP]", "moin-top.png", 14, 10), 'www': ("[WWW]", "moin-www.png", 16, 16), 'mailto': ("[MAILTO]", "moin-email.png", 16, 16), '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", 15, 15), } # ??? Why do we need stylesheet_print? the standard stylesheets # provide a print version? stylesheets_print = ( # theme charset media basename (name, 'iso-8859-1', 'all', 'common'), (name, 'iso-8859-1', 'all', 'print'), ) stylesheets = ( # theme charset media basename (name, 'iso-8859-1', 'all', 'common'), (name, 'iso-8859-1', 'screen', 'screen'), (name, 'iso-8859-1', 'print', 'print'), ) def __init__(self, request): """ Initialize the theme object. @param request: the request object """ self.request = request def img_url(self, img): """ generate an img url @param img: the image filename @rtype: string @return: the image url """ return "%s/%s/img/%s" % (config.url_prefix, self.name, img) def css_url(self, basename, theme = None): """ generate the css url @param basename: the css media type (base filename w/o .css) @param theme: theme name @rtype: string @return: the css url """ if not theme: theme = self.name return "%s/%s/css/%s.css" % (config.url_prefix, theme, basename) def emit_custom_html(self, html): """ generate custom HTML code in `html` @param html: a string or a callable object, in which case it is called and its return value is used @rtype: string @return: string with html """ if html: if callable(html): html = html(self.request) return html # Header stuff ####################################################### def logo(self, d): """ Assemble the logo @param d: parameter dictionary @rtype: string @return: logo html """ html = '' # insert Header tag ####### html += '\n') return ''.join(html) def get_icon(self, icon): try: ret = self.icons[icon] except KeyError: # if called from [[Icon(file)]] we have a filename, not a key # using filenames is deprecated, but for now, we simulate old behaviour! # please use only the icon *key* in future, not the filename any more. icon = icon.replace('.gif','.png') # no gifs any more! for i in self.icons.keys(): ret = self.icons[i] if ret[1] == icon: # found the file name? break else: ret = ("", icon, "", "") return (ret[0], self.img_url(ret[1])) + ret[2:] def make_icon(self, icon, vars=None): """ This is the central routine for making tags for icons! All icons stuff except the top left logo, smileys and search field icons are handled here. @param icon: icon id (dict key) @param vars: ... @rtype: string @return: icon html (img tag) """ if vars is None: vars = {} alt, img, w, h = self.get_icon(icon) try: alt = alt % vars except KeyError, err: alt = 'KeyError: %s' % str(err) if self.request: alt = self.request.getText(alt) try: tag = self.request.formatter.image(src=img, alt=alt, width=w, height=h) except AttributeError: # XXX FIXME if we have no formatter or no request tag = '%s' % ( img, alt, w, h) import warnings warnings.warn("calling themes without correct request", DeprecationWarning) return tag def make_iconlink(self, which, d): """ Make a link with an icon @param which: icon id (dictionary key) @param d: parameter dictionary @rtype: string @return: html link tag """ page_params, title, icon = config.page_icons_table[which] d['title'] = title % d d['i18ntitle'] = self.request.getText(d['title']) img_src = self.make_icon(icon, d) return wikiutil.link_tag(self.request, page_params % d, img_src, attrs='title="%(i18ntitle)s"' % d) def iconbar(self, d): """ Assemble the iconbar @param d: parameter dictionary @rtype: string @return: iconbar html """ iconbar = [] if config.page_iconbar and self.request.user.show_toolbar and d['page_name']: # add Icons tag #################### iconbar.append('
\n') iconbar.append('\n') # close Icons tag ######## iconbar.append('
\n') return ''.join(iconbar) def msg(self, d): """ Assemble the msg display @param d: parameter dictionary @rtype: string @return: msg display html """ html = '' if d['msg']: # make sure that messages are layoutet same width as content html += '
\n' _ = self.request.getText d.update({'link_text': _('Clear message'),}) clear_msg_link = '%(link_text)s' % d d.update({'clear_msg_link': clear_msg_link,}) html += ('\n
\n' '%(msg)s
%(clear_msg_link)s
') % d #'

%(msg)s

%(clear_msg_link)s

') % d # close "content" div html += '\n' else: html += '\n' return html def trail(self, d): """ Assemble page trail @param d: parameter dictionary @rtype: string @return: trail html """ _ = self.request.getText html = [] if d['trail']: pagetrail = d['trail'] # insert lastpages tag (trailer) html.append('
\n') html.append('
\n') html.append('%s:
\n' % _("Trail")) for p in pagetrail[:-1]: html.append('%s
\n' % (Page(p).link_to(self.request),)) # close lastpages tag html.append('
\n') else: # ??? close possibly remaining "content" div ?! # ??? html.append('\n') pass splittedtrailer = ''.join(html) workinprogress = re.compile(r'">([^<]+?)([a-zäöüß])([A-ZÄÖÜ])') while workinprogress.search(splittedtrailer): splittedtrailer = workinprogress.sub(r'">\1\2 \3', splittedtrailer, 0) workinprogress = re.compile(r'([^<]+?)([a-zäöüß])([A-ZÄÖÜ])') while workinprogress.search(splittedtrailer): splittedtrailer = workinprogress.sub(r'\1\2 \3', splittedtrailer, 0) return splittedtrailer def html_stylesheet_link(self, charset, media, href): return ('\n') % (charset, media, href) def html_stylesheets(self, d): """ Assemble stylesheet links @param d: parameter dictionary @rtype: string @return: links """ html = [] if d.get('print_mode', False): stylesheets = self.stylesheets_print else: stylesheets = self.stylesheets user_css_url = self.request.user.valid and self.request.user.css_url # Create stylesheets links for theme, charset, media, name in stylesheets: href = self.css_url(name, theme) html.append(self.html_stylesheet_link(charset, media, href)) # workaround for old user settings # Dont add user css url if it matches one of ours if user_css_url and user_css_url == href: user_css_url = None # Add user css url (assuming that user css uses iso-8859-1) # ??? Maybe move to utf-8? # TODO: Document this in the Help system if user_css_url and user_css_url.lower() != "none": html.append( self.html_stylesheet_link('iso-8859-1', 'all', user_css_url)) return ''.join(html) def html_head(self, d): """ Assemble html head @param d: parameter dictionary @rtype: string @return: html head """ dict = { 'stylesheets_html': self.html_stylesheets(d), } dict.update(d) html = """ %(title)s - %(sitename)s %(stylesheets_html)s """ % dict return html def header(self, d): """ Assemble page header @param d: parameter dictionary @rtype: string @return: page header html """ dict = { 'config_header1_html': self.emit_custom_html(config.page_header1), 'config_header2_html': self.emit_custom_html(config.page_header2), 'logo_html': self.logo(d), 'title_html': self.title(d), 'username_html': self.username(d), 'navibar_html': self.navibar(d), 'iconbar_html': self.iconbar(d), 'search_form_html': self.searchform(d), 'available_actions_html': self.availableactions(d), 'msg_html': self.msg(d), 'trail_html': self.trail(d), } dict.update(d) html = """ %(config_header1_html)s %(logo_html)s %(title_html)s %(iconbar_html)s %(msg_html)s """ % dict # Next parts will use config.default_lang direction, as set in the return html # Footer stuff ####################################################### def showtext_link(self, d, **keywords): """ Assemble ShowText link (on action pages) @param d: parameter dictionary @rtype: string @return: edittext link html """ _ = self.request.getText html = '' if keywords.get('showpage', 0): #html += '
\n' html += "

%s %s

\n" % ( wikiutil.link_tag(self.request, d['q_page_name'], _("ShowText")), _('of this page'), ) #html += '
\n' return html def edittext_link(self, d, **keywords): """ Assemble EditText link (or indication that page cannot be edited) @param d: parameter dictionary @rtype: string @return: edittext link html """ _ = self.request.getText html = [] html.append('

') if keywords.get('editable', 1): editable = self.request.user.may.edit(d['page_name']) and d['page'].isWritable() if editable: html.append("%s %s" % ( wikiutil.link_tag(self.request, d['q_page_name']+'?action=edit', _('EditText')), _('of this page'), )) else: html.append("%s" % _('Immutable page')) html.append(' %(last_edit_info)s' % d) html.append('

') return ''.join(html) def footer_fragments(self, d, **keywords): """ assemble HTML code fragments added by the page formatters @param d: parameter dictionary @rtype: string @return: footer fragments html """ html = '' if d['footer_fragments']: html = ''.join(d['footer_fragments'].values()) return html def searchform(self, d): """ assemble HTML code for the search forms @param d: parameter dictionary @rtype: string @return: search form html """ _ = self.request.getText sitenav_pagename = wikiutil.getSysPage(self.request, 'SiteNavigation').page_name dict = { 'search_title': _("Search"), 'search_html': _("Title: %(titlesearch)s
Text: %(textsearch)s") % d, } dict.update(d) html = """ """ % dict return html def availableactions(self, d): """ assemble HTML code for the available actions @param d: parameter dictionary @rtype: string @return: available actions html """ _ = self.request.getText html = [] html.append('

') html.append('%s:
\n' % _("Action")) for action in d['available_actions']: html.append("%s
\n" % ( wikiutil.link_tag(self.request, '%s?action=%s' % (d['q_page_name'], action), action) )) html.append('
\n') return ''.join(html) def showversion(self, d, **keywords): """ assemble HTML code for copyright and version display @param d: parameter dictionary @rtype: string @return: copyright and version display html """ html = '' if config.show_version and not keywords.get('print_mode', 0): html = ('

' 'MoinMoin %s, Copyright \xa9 2000-2004 by Jürgen Hermann' '

' % (version.revision,)) return html def footer(self, d, **keywords): """ Assemble page footer @param d: parameter dictionary @keyword ...:... @rtype: string @return: page footer html """ dict = { 'config_page_footer1_html': self.emit_custom_html(config.page_footer1), 'config_page_footer2_html': self.emit_custom_html(config.page_footer2), 'showtext_html': self.showtext_link(d, **keywords), 'edittext_html': self.edittext_link(d, **keywords), 'search_form_html': self.searchform(d), 'credits_html': self.emit_custom_html(config.page_credits), 'version_html': self.showversion(d, **keywords), 'footer_fragments_html': self.footer_fragments(d, **keywords), } dict.update(d) html = """ """ % dict return html # RecentChanges ###################################################### def recentchanges_entry(self, d): """ Assemble a single recentchanges entry (table row) @param d: parameter dictionary @rtype: string @return: recentchanges entry html """ _ = self.request.getText html = [] html.append('\n') html.append('%(icon_html)s\n' % d) html.append('%(pagelink_html)s\n' % d) html.append('') if d['time_html']: html.append("%(time_html)s" % d) html.append('\n') html.append('%(info_html)s\n' % d) html.append('') if d['editors']: html.append('
'.join(d['editors'])) html.append('\n') html.append('') if d['comments']: if d['changecount'] > 1: notfirst = 0 for comment in d['comments']: html.append('%s#%02d %s' % ( notfirst and '
' or '' , comment[0], comment[1])) notfirst = 1 else: comment = d['comments'][0] html.append('%s' % comment[1]) html.append('\n') html.append('\n') return ''.join(html) def recentchanges_daybreak(self, d): """ Assemble a rc daybreak indication (table row) @param d: parameter dictionary @rtype: string @return: recentchanges daybreak html """ if d['bookmark_link_html']: set_bm = ' [%(bookmark_link_html)s]' % d else: set_bm = '' return ('' '%s' '%s' '\n') % (6, d['date'], set_bm) def recentchanges_header(self, d): """ Assemble the recentchanges header (intro + open table) @param d: parameter dictionary @rtype: string @return: recentchanges header html """ _ = self.request.getText html = '
\n' % self.ui_lang_attr() html += '
\n' if d['rc_rss_link']: html += '

%s

\n' % d['rc_rss_link'] html += '

' if d['rc_update_bookmark']: html += "%(rc_update_bookmark)s %(rc_curr_bookmark)s
" % d if d['rc_days']: days = [] for day in d['rc_days']: if day == d['rc_max_days']: days.append('%d' % day) else: days.append( wikiutil.link_tag(self.request, '%s?max_days=%d' % (d['q_page_name'], day), str(day))) days = ' | '.join(days) html += (_("Show all changes in the last %s days.") % (days,)) html += '

\n
\n' html += '\n' return html def recentchanges_footer(self, d): """ Assemble the recentchanges footer (close table) @param d: parameter dictionary @rtype: string @return: recentchanges footer html """ _ = self.request.getText html = '' html += '
\n' if d['rc_msg']: html += "
%(rc_msg)s\n" % d html += '
\n' return html # # Language stuff # def ui_lang_attr(self): """Generate language attributes for user interface elements User interface elements use the user language (if any), kept in request.lang. @rtype: string @return: lang and dir html attributes """ lang = self.request.lang dir = i18n.getDirection(lang) return 'lang="%(lang)s" dir="%(dir)s"' % locals() def content_lang_attr(self): """Generate language attributes for wiki page content Page content uses the wiki default language @rtype: string @return: lang and dir html attributes """ lang = config.default_lang dir = i18n.getDirection(lang) return 'lang="%(lang)s" dir="%(dir)s"' % locals() def execute(request): """ Generate and return a theme object @param request: the request object @rtype: MoinTheme @return: Theme object """ return Theme(request)