[wiki-lenny] ajout de plein de fichiers

* text_latex.py --- un formatter latex qui marche
                     (appelé avec ?mimetype=text/latex)
 * ShowCategories.py --- une macro qui affiche les liens et les catégories
                         de la page courante.
 * theme/crans{,-www}.py --- Les deux thèmes officiels et supportés
 * formatter.*.orig.py --- Ajout des fichiers originaux

darcs-hash:20081212044713-bd074-f8123fa455b4e2b0f082159d492274a8b4aa4ec5.gz
This commit is contained in:
Antoine Durand-Gasselin 2008-12-12 05:47:13 +01:00
parent 18fbc03f3b
commit 186988cd76
6 changed files with 2894 additions and 0 deletions

View file

@ -0,0 +1,361 @@
# -*- coding: utf-8 -*-
"""
MoinMoin - "text/latex" Formatter
Copyright 2005 Johannes Berg <johannes@sipsolutions.net>
Copyright (c) 2003 by João Neves <moin@silvaneves.org>
Copyright (c) 2000, 2001, 2002 by Jürgen Hermann <jh@web.de>
All rights reserved, see COPYING for details.
"""
# Imports
import sys, re
from MoinMoin.formatter import FormatterBase
from MoinMoin.Page import Page
#############################################################################
### LaTeX Formatter
#############################################################################
class Formatter(FormatterBase):
"""
Send text data.
"""
hardspace = ' '
def __init__(self, request, **kw):
apply(FormatterBase.__init__, (self, request), kw)
self.verbatim = False
self.itemized = False
def text2latex(self, text):
"Escape special characters if not in verbatim mode"
if self.verbatim: return text
text = text.replace('\\', '$\\backslash$ ');
text = text.replace('$', r'\$');
text = text.replace(r'\$\backslash\$', r'$\backslash$')
text = text.replace('#', r'\#');
text = text.replace('%', r'\%');
text = text.replace('^', r'\^{}');
text = text.replace('&', r'\&');
text = text.replace('_', r'\_');
text = text.replace('{', r'\{');
text = text.replace('}', r'\}');
text = text.replace('~', r'\~{}');
text = text.replace('"', r'\"{}');
text = text.replace(u'ä', r'"a');
text = text.replace(u'ü', r'"u');
text = text.replace(u'ö', r'"o');
text = text.replace(u'Ä', r'"A');
text = text.replace(u'Ü', r'"U');
text = text.replace(u'Ö', r'"O');
text = text.replace(u'ß', r'\ss{}');
return text
def write_text(self, text):
if self.item is None:
return text
else:
self.item = (self.item[0], self.item[1]+text)
return ''
def startDocument(self, pagename):
extra_preamble = ''
preamble_page = self.request.pragma.get('latex_preamble', None)
if preamble_page is not None:
extra_preamble = Page(self.request, preamble_page).get_raw_body()
extra_preamble = re.sub(re.compile('^#'), '%', extra_preamble)
return """
\\documentclass[a4paper,12pt]{article}
\\usepackage[utf8]{inputenc}
\\usepackage{helvet}
\\usepackage{graphicx}
\\usepackage{multicol}
\\usepackage{fullpage}
\\usepackage{fancyhdr}
\\usepackage{multirow}
\\makeatletter
\\DeclareRobustCommand*\\textsubscript[1]{%%
\\@textsubscript{\\selectfont#1}}
\\def\\@textsubscript#1{%%
{\\m@th\\ensuremath{_{\\mbox{\\fontsize\\sf@size\\z@#1}}}}}
\\makeatother
%% begin extra preamble inclusion %%
%s
%% end extra preamble inclusion %%
\\title{%s}
\\author{ }
\\date{ }
\\renewcommand{\\theenumi}{\\arabic{enumi}}
\\renewcommand{\\theenumii}{\\arabic{enumi}.\\arabic{enumii}}
\\renewcommand{\\theenumiii}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}}
\\renewcommand{\\theenumiv}{\\arabic{enumi}.\\arabic{enumii}.\\arabic{enumiii}.\\arabic{enumiv}}
\\begin{document}
""" % (extra_preamble, pagename)
def endDocument(self):
return '\\end{document}\n'
def sysmsg(self, text, **kw):
return self.write_text('')
def pagelink(self, on, pagename, text=None, **kw):
return self.write_text('')
def url(self, on, url=None, css=None, **kw):
if not on:
return self.write_text('}')
if url[-4:] == '.pdf':
nid = self.next_img_data
self.next_img_data = ''
return '\\includegraphics%s{' % nid
url = url.replace('&', '\\&')
return self.write_text('\\href{%s}{' % self.text2latex(url))
def text(self, text):
return self.write_text(self.text2latex(text))
def rule(self, size=0):
size = min(size, 10)
ch = "---~=*+#####"[size]
return self.write_text('\n\n\\hrulefill{}\n\n')
def strong(self, on):
return self.write_text(['{\\bf ', '}'][not on])
def emphasis(self, on):
return self.write_text(['{\\em ', '}'][not on])
def highlight(self, on):
return self.write_text(['{\\tt ', '}'][not on])
def number_list(self, on, type=None, start=None):
self.itemized = on
if on:
text = "\\begin{enumerate}"
else:
text = '\\end{enumerate}\n'
return self.write_text(text)
def bullet_list(self, on):
self.itemized = on
return self.write_text(['\\begin{itemize}\n', '\n\\end{itemize}\n'][not on])
def listitem(self, on, **kw):
if not self.itemized: return ''
self._in_li = on != 0
if on:
return self.write_text('\\item ')
else:
return ''
def sup(self, on):
return self.write_text(['\\textsuperscript{', '}'][not on])
def sub(self, on):
return self.write_text(['\\textsubscript{', '}'][not on])
def code(self, on, **kw):
return self.write_text(['{\\tt ', '}'][not on])
def code_area(self, on, code_id, code_type='code', show=0, start=-1, step=-1):
res = self.preformatted(on)
self.verbatim = False
return self.write_text(res)
def code_token(self, on, tok_type):
return self.write_text('')
def code_line(self, on):
return self.write_text('\n')
def preformatted(self, on):
FormatterBase.preformatted(self, on)
self.verbatim = on
return self.write_text(['\\begin{verbatim}\n', '\\end{verbatim}\n'][not on])
def smiley(self, text):
return self.write_text(self.text2latex(text))
def paragraph(self, on, **kw):
FormatterBase.paragraph(self, on)
return self.write_text(['', '\n\n'][not on])
def linebreak(self, preformatted=1):
if preformatted==1:
return self.write_text('\n')
else:
return self.write_text('\\newline')
def heading(self, on, depth, **kw):
if depth == 1:
rv = (r'\section{','}\n')
elif depth == 2:
rv = ('\\subsection{','}\n')
elif depth == 3:
rv = ('\\subsubsection{','}\n')
else:
rv = (r'\paragraph{','}\n',)
return self.write_text(rv[not on])
rows = []
row = []
item = None
def table(self, on, attrs={}):
def count_cols(row):
cols = 0
for cell in row:
if cell[0].has_key('colspan'):
cols += int(cell[0]['colspan'][1:-1])
else:
cols += 1
return cols
if on:
self.rows = []
self.item = None
self.row = []
return ''
# not on:
if self.rows == []: return ''
cols = count_cols(self.rows[0])
rows = len(self.rows)
_table = [[0 for i in xrange(0,cols)] for j in xrange(0,rows)]
_rownum = -1
for _row in self.rows:
_rownum += 1
_cellnum = -1
for _cell in _row:
_cellnum += 1
while _table[_rownum][_cellnum] is None or type(_table[_rownum][_cellnum]) == type(()):
_cellnum += 1
if _cell[0].get('rowspan') == '"1"':
del _cell[0]['rowspan']
if _cell[0].get('colspan') == '"1"':
del _cell[0]['colspan']
_rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1])
_colspan = int(_cell[0].get('colspan', '"1"')[1:-1])
for j in xrange(0,_rowspan):
for i in xrange(0,_colspan):
_table[_rownum+j][_cellnum+i] = None
_table[_rownum+j][_cellnum] = ({'colspan':'"%d"'%_colspan},None)
_table[_rownum][_cellnum] = _cell
table = '\\begin{tabular}{|%s}\n' % (cols * 'l|')
for _row in _table:
row = ''
cellnum = 0
_lines = []
_do_line = True
for _cell in _row:
cellnum+=1
if _cell == 0:
return 'INVALID TABLE'
if _cell is None:
if _do_line:
_lines += [cellnum]
continue
_rowspan = int(_cell[0].get('rowspan', '"1"')[1:-1])
_colspan = int(_cell[0].get('colspan', '"1"')[1:-1])
format = '%s'
if not (_cell[1] is None):
_do_line = True
_lines += [cellnum]
else:
_do_line = False
_cell = (_cell[0], u'')
if _rowspan > 1:
format = r'\multirow{%d}*{%%s}' % _rowspan
if _colspan > 1:
format = r'\multicolumn{%d}{|l|}{ %s }' % (_colspan, format)
row += (format+' & ') % _cell[1].replace('\n',' ')
for l in _lines:
table += r'\cline{%d-%d}' % (l,l)
table += row[0:-3] + '\\\\ \n'
table += '\\hline\\end{tabular}\n\n'
return table
def table_row(self, on, attrs={}):
if not on:
self.rows += [self.row]
self.row = []
return ''
def table_cell(self, on, attrs={}):
if not on:
self.row += [self.item]
self.item = None
else:
self.item = (attrs,'')
return ''
def underline(self, on):
return self.write_text(['\\underline{', '}'][not on])
def definition_list(self, on):
return self.write_text(['\\begin{description}\n', '\\end{description}\n'][not on])
def definition_term(self, on, compact=0):
return self.write_text(['\\item[', '] '][not on])
def definition_desc(self, on):
return self.write_text('')
def attachment_image(self, fname, **kw):
return self.image(src=fname)
def image(self, **kw):
# I am using alt for caption, but how to integrate the image?
text = ''
imgname = kw['src'].split('=')[-1]
nid = self.next_img_data
self.next_img_data = ''
return '\\includegraphics%s{%s}' % (nid, imgname)
#if kw.has_key('alt'):
# text += '\\begin{picture}\n'
# text += '\\caption{%s}\n' % kw[alt]
# text += '\\end{picture}\n'
#return self.write_text(text)
def crans_portal(self, entries):
code = ''
for pic, tit, bod in entries:
code += "\\begin{minipage}{0.5\\linewidth}\n%s\\\\\n%s\n\\end{minipage}\n" % (tit, bod)
return code
def crans_box(self, tit, bod, color=None):
return '%s\n%s' % (tit, bod)
def johill_sidecall_emit_latex(self, code):
# nothing else for now
return code
next_img_data = ''
def johill_sidecall_next_image_data(self, data):
self.next_img_data = '['+data+']'
def open(self, on, **kw):
return ""
def close(self, on, **kw):
return ""
# suckers who call this. we can't do raw HTML, so we ignore it
def rawHTML(self, markup):
return ''

View file

@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
#
# SHOWCATEGORIES.PY--
#
# Copyright (C) 2008 Antoine Durand-Gasselin
# Author: Antoine Durand-Gasselin <adg@crans.org>
#
def execute (macro, text):
f = macro.formatter
code = [f.heading(1,2), "Liste des liens", f.heading(0,2)]
code += macro.request.page.getPageLinks(macro.request)
code += [f.heading(1,2), u"Liste des Catégories", f.heading(0,2)]
code += macro.request.page.getCategories(macro.request)
return "\n".join(code)

View file

@ -0,0 +1,540 @@
# -*- 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"https://intranet.crans.org/"),
(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.mozilla-europe.org/fr/products/firefox/', 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.federez.org/', u'badges_80x15_federez.png', u'Membre du r&eacute;seau federeez'),
(u'http://moinmoin.wikiwikiweb.de/', u'badges_80x15_moinmoin.png', u'Moinmoin powered'),
(u'http://jigsaw.w3.org/css-validator/check?uri=referer&amp;profile=css3&amp;warning=no', u'valid_css_80x15.png', u'Valid css3'),
# (u'http://validator.w3.org/check?uri=referer', u'valid_html401_80x15.png', u'Valid html 4.01'),
]
# 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()
title = [
'<div id="maintitle">',
self.title(d),
parent and wikiutil.link_tag(self.request,
parent.page_name,
u'<img src="/wiki/crans-www/img/go-up.png" alt="Haut">') or u'',
'</div>'
]
html = [
u'<div id="globalWrapper">',
self.logo(),
u'<div id="column-content">',
self.startPage(),
]
if d['page'].page_name != 'VieCrans' :
html += title
html += [self.msg(d)]
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),
u'<script src="http://www.crans.org/wiki/common/js/say.no.to.ie.6.js"></script>', # Campagne "Save A Developer. Upgrade Your Browser."
]
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:
badges_html.append(u'<li><a href="%(href)s" title="%(alt)s"><img src="%(path)s%(image)s" alt="%(alt)s"></a></li>' % {'href':page, 'path':self.badgesPath, 'image':image, 'alt':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))
url = u'http://wiki.crans.org/%s' % d['page'].page_name
link = u'<a href="%s">%s</a>' % ( url, 'Version Wiki')
userlinks.append(link)
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>.:: CRANS : Cachan / Réseau @ Normale Sup' ::.</title>",
self.headscript(d), # Should move to separate .js file
self.html_stylesheets(d),
self.rtl_stylesheet(d),
self.rsslink(d),
]
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)

View file

@ -0,0 +1,162 @@
# -*- 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.
"""
import datetime
from MoinMoin.theme import ThemeBase
from MoinMoin import wikiutil, i18n
from MoinMoin.Page import Page
class ThemeCrans(ThemeBase):
name = "crans"
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'crans'),
('print', 'print'),
('projection', 'projection'),
)
# Standard set of scripts
scripts = (
'crans',
)
# 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.
"""
if datetime.date.today().month == 10:
extra_style = " class=\"halloween\""
elif (datetime.date.today().month == 12) and (datetime.date.today().day <= 24):
extra_style = " class=\"noel\""
else:
extra_style = ""
parent = d['page'].getParentPage()
html = [
u'<div id="globalWrapper"%s>' % extra_style,
u'<div id="main-content">',
u'<div id="titleBarre">',
'<h1 id="title">',
self.title(d),
u'</h1>',
u'</div>',
self.msg(d),
self.startPage(),
]
return u'\n'.join(html)
editorheader = header
def footer(self, d, **keywords):
""" Assemble wiki footer
"""
html = [
# End of page
self.pageinfo(d['page']),
self.endPage(),
u'</div>', # fin du div main-content
self.rightcolumn(d),
u'</div>', # fin du div globalWrapper
u'<script src="http://www.crans.org/wiki/common/js/say.no.to.ie.6.js"></script>', # Campagne "Save A Developer. Upgrade Your Browser."
]
return u'\n'.join(html)
def rightcolumn(self, d):
""" assemble all the navigation aids for the page
"""
_ = self.request.getText
page = d['page']
html = [
u'<div id="column-one">',
u"<h5>Personnel</h5>",
self.username(d),
u"<h5>Navigation</h5>",
self.navibar(d),
# hack : c1 and V1 or v2 c'est comme le code C : c1? v1 : V2
# (si c1 est vrai alors prends la valeur V1 sinon prend la valeur c2
self.shouldShowEditbar(d['page']) and u"<h5>%s</h5>" % _("Page") or u" ",
self.editbar(d),
u"<h5>%s</h5>" % _('Search'),
self.searchform(d),
#self.actionmenu(d),
#self.pageinfo(page),
self.credits(d),
]
return u'\n'.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 = '\n<link rel="search" type="application/opensearchdescription+xml" href="%(page)s?action=opensearch&amp;searchtype=Titres" title="%(sitename)s, Rechercher dans les titres" />\n<link rel="search" type="application/opensearchdescription+xml" href="%(page)s?action=opensearch&amp;searchtype=Texte" title="%(sitename)s, Rechercher dans le texte" />' % {'page':d['page'].request.script_name, 'sitename':d['sitename']}
if (d['page'].isWritable() and
self.request.user.may.write(d['page'].page_name)):
edit_link = "/" + wikiutil.quoteWikinameURL(d['page'].page_name) + '?action=edit&amp;editor=text'
wiki_rel = '<link rel="alternate" \
type="application/x-wiki" title="Modifier" \
href="%s" />\n' % edit_link
else:
wiki_rel = ""
classic_head = ThemeBase.html_head(self, d)
return classic_head + open_search_desc + wiki_rel
def headscript(self, d):
html = []
# Check mode
if d.get('print_mode'):
link = ""
else:
# Create stylesheets links
link = '<script type="text/javascript" src="%s"></script>'
prefix = self.cfg.url_prefix
csshref = '%s/%s/js' % (prefix, self.name)
html = []
for basename in self.scripts:
href = '%s/%s.js' % (csshref, basename)
html.append(link % href )
return ThemeBase.headscript(self, d) + u"\n".join(html)
class Theme(ThemeCrans):
name = "crans"
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'layout'),
('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)

View file

@ -0,0 +1,432 @@
# -*- coding: iso-8859-1 -*-
"""
MoinMoin - Formatter Package and FormatterBase
See "base.py" for the formatter interface.
@copyright: 2000-2004 by Juergen Hermann <jh@web.de>
@license: GNU GPL, see COPYING for details.
"""
import re
from MoinMoin import log
logging = log.getLogger(__name__)
from MoinMoin.util import pysupport
from MoinMoin import wikiutil
from MoinMoin.support.python_compatibility import rsplit
modules = pysupport.getPackageModules(__file__)
class FormatterBase:
""" This defines the output interface used all over the rest of the code.
Note that no other means should be used to generate _content_ output,
while navigational elements (HTML page header/footer) and the like
can be printed directly without violating output abstraction.
"""
hardspace = ' '
def __init__(self, request, **kw):
self.request = request
self._ = request.getText
self._store_pagelinks = kw.get('store_pagelinks', 0)
self._terse = kw.get('terse', 0)
self.pagelinks = []
self.in_p = 0
self.in_pre = 0
self._highlight_re = None
self._base_depth = 0
def set_highlight_re(self, hi_re=None):
""" set the highlighting regular expression (e.g. for search terms)
@param hi_re: either a valid re as str/unicode (you may want to use
re.escape before passing generic strings!) or a compiled
re object. raises re.error for invalid re.
"""
if isinstance(hi_re, (str, unicode)):
hi_re = re.compile(hi_re, re.U + re.IGNORECASE)
self._highlight_re = hi_re
def lang(self, on, lang_name):
return ""
def setPage(self, page):
self.page = page
def sysmsg(self, on, **kw):
""" Emit a system message (embed it into the page).
Normally used to indicate disabled options, or invalid markup.
"""
return ""
# Document Level #####################################################
def startDocument(self, pagename):
return ""
def endDocument(self):
return ""
def startContent(self, content_id="content", **kw):
if self.page:
self.request.begin_include(self.page.page_name)
return ""
def endContent(self):
if self.page:
self.request.end_include()
return ""
# Links ##############################################################
def pagelink(self, on, pagename='', page=None, **kw):
""" make a link to page <pagename>. Instead of supplying a pagename,
it is also possible to give a live Page object, then page.page_name
will be used.
"""
if not self._store_pagelinks or not on or kw.get('generated'):
return ''
if not pagename and page:
pagename = page.page_name
pagename = self.request.normalizePagename(pagename)
if pagename and pagename not in self.pagelinks:
self.pagelinks.append(pagename)
def interwikilink(self, on, interwiki='', pagename='', **kw):
""" calls pagelink() for internal interwikilinks
to make sure they get counted for self.pagelinks.
IMPORTANT: on and off must be called with same parameters, see
also the text_html formatter.
"""
wikitag, wikiurl, wikitail, wikitag_bad = wikiutil.resolve_interwiki(self.request, interwiki, pagename)
if wikitag == 'Self' or wikitag == self.request.cfg.interwikiname:
if '#' in wikitail:
wikitail, kw['anchor'] = rsplit(wikitail, '#', 1)
wikitail = wikiutil.url_unquote(wikitail)
return self.pagelink(on, wikitail, **kw)
return ''
def url(self, on, url=None, css=None, **kw):
raise NotImplementedError
# Attachments ######################################################
def attachment_link(self, on, url=None, **kw):
raise NotImplementedError
def attachment_image(self, url, **kw):
raise NotImplementedError
def attachment_drawing(self, url, text, **kw):
raise NotImplementedError
def attachment_inlined(self, url, text, **kw):
from MoinMoin.action import AttachFile
import os
_ = self.request.getText
pagename, filename = AttachFile.absoluteName(url, self.page.page_name)
fname = wikiutil.taintfilename(filename)
fpath = AttachFile.getFilename(self.request, pagename, fname)
ext = os.path.splitext(filename)[1]
Parser = wikiutil.getParserForExtension(self.request.cfg, ext)
if Parser is not None:
try:
content = file(fpath, 'r').read()
# Try to decode text. It might return junk, but we don't
# have enough information with attachments.
content = wikiutil.decodeUnknownInput(content)
colorizer = Parser(content, self.request, filename=filename)
colorizer.format(self)
except IOError:
pass
return (self.attachment_link(1, url) +
self.text(text) +
self.attachment_link(0))
def anchordef(self, name):
return ""
def line_anchordef(self, lineno):
return ""
def anchorlink(self, on, name='', **kw):
return ""
def line_anchorlink(self, on, lineno=0):
return ""
def image(self, src=None, **kw):
"""An inline image.
Extra keyword arguments are according to the HTML <img> tag attributes.
In particular an 'alt' or 'title' argument should give a description
of the image.
"""
title = src
for titleattr in ('title', 'html__title', 'alt', 'html__alt'):
if titleattr in kw:
title = kw[titleattr]
break
if title:
return '[Image:%s]' % title
return '[Image]'
# generic transclude/include:
def transclusion(self, on, **kw):
raise NotImplementedError
def transclusion_param(self, **kw):
raise NotImplementedError
def smiley(self, text):
return text
def nowikiword(self, text):
return self.text(text)
# Text and Text Attributes ###########################################
def text(self, text, **kw):
if not self._highlight_re:
return self._text(text)
result = []
lastpos = 0
match = self._highlight_re.search(text)
while match and lastpos < len(text):
# add the match we found
result.append(self._text(text[lastpos:match.start()]))
result.append(self.highlight(1))
result.append(self._text(match.group(0)))
result.append(self.highlight(0))
# search for the next one
lastpos = match.end() + (match.end() == lastpos)
match = self._highlight_re.search(text, lastpos)
result.append(self._text(text[lastpos:]))
return ''.join(result)
def _text(self, text):
raise NotImplementedError
def strong(self, on, **kw):
raise NotImplementedError
def emphasis(self, on, **kw):
raise NotImplementedError
def underline(self, on, **kw):
raise NotImplementedError
def highlight(self, on, **kw):
raise NotImplementedError
def sup(self, on, **kw):
raise NotImplementedError
def sub(self, on, **kw):
raise NotImplementedError
def strike(self, on, **kw):
raise NotImplementedError
def code(self, on, **kw):
raise NotImplementedError
def preformatted(self, on, **kw):
self.in_pre = on != 0
def small(self, on, **kw):
raise NotImplementedError
def big(self, on, **kw):
raise NotImplementedError
# special markup for syntax highlighting #############################
def code_area(self, on, code_id, **kw):
raise NotImplementedError
def code_line(self, on):
raise NotImplementedError
def code_token(self, tok_text, tok_type):
raise NotImplementedError
# Paragraphs, Lines, Rules ###########################################
def linebreak(self, preformatted=1):
raise NotImplementedError
def paragraph(self, on, **kw):
self.in_p = on != 0
def rule(self, size=0, **kw):
raise NotImplementedError
def icon(self, type):
return type
# Lists ##############################################################
def number_list(self, on, type=None, start=None, **kw):
raise NotImplementedError
def bullet_list(self, on, **kw):
raise NotImplementedError
def listitem(self, on, **kw):
raise NotImplementedError
def definition_list(self, on, **kw):
raise NotImplementedError
def definition_term(self, on, compact=0, **kw):
raise NotImplementedError
def definition_desc(self, on, **kw):
raise NotImplementedError
def heading(self, on, depth, **kw):
raise NotImplementedError
# Tables #############################################################
def table(self, on, attrs={}, **kw):
raise NotImplementedError
def table_row(self, on, attrs={}, **kw):
raise NotImplementedError
def table_cell(self, on, attrs={}, **kw):
raise NotImplementedError
# Dynamic stuff / Plugins ############################################
def macro(self, macro_obj, name, args, markup=None):
# call the macro
try:
return macro_obj.execute(name, args)
except ImportError, err:
errmsg = unicode(err)
if not name in errmsg:
raise
if markup:
return (self.span(1, title=errmsg) +
self.text(markup) +
self.span(0))
else:
return self.text(errmsg)
def _get_bang_args(self, line):
if line.startswith('#!'):
try:
name, args = line[2:].split(None, 1)
except ValueError:
return ''
else:
return args
return None
def parser(self, parser_name, lines):
""" parser_name MUST be valid!
writes out the result instead of returning it!
"""
# attention: this is copied into text_python!
parser = wikiutil.searchAndImportPlugin(self.request.cfg, "parser", parser_name)
args = None
if lines:
args = self._get_bang_args(lines[0])
logging.debug("formatter.parser: parser args %r" % args)
if args is not None:
lines = lines[1:]
if lines and not lines[0]:
lines = lines[1:]
if lines and not lines[-1].strip():
lines = lines[:-1]
p = parser('\n'.join(lines), self.request, format_args=args)
p.format(self)
del p
return ''
# Other ##############################################################
def div(self, on, **kw):
""" open/close a blocklevel division """
return ""
def span(self, on, **kw):
""" open/close a inline span """
return ""
def rawHTML(self, markup):
""" This allows emitting pre-formatted HTML markup, and should be
used wisely (i.e. very seldom).
Using this event while generating content results in unwanted
effects, like loss of markup or insertion of CDATA sections
when output goes to XML formats.
"""
import formatter, htmllib
from MoinMoin.util import simpleIO
# Regenerate plain text
f = simpleIO()
h = htmllib.HTMLParser(formatter.AbstractFormatter(formatter.DumbWriter(f)))
h.feed(markup)
h.close()
return self.text(f.getvalue())
def escapedText(self, on, **kw):
""" This allows emitting text as-is, anything special will
be escaped (at least in HTML, some text output format
would possibly do nothing here)
"""
return ""
def comment(self, text, **kw):
return ""
# ID handling #################################################
def sanitize_to_id(self, text):
'''
Take 'text' and return something that is a valid ID
for this formatter.
The default returns the first non-space character of the string.
Because of the way this is used, it must be idempotent,
i.e. calling it on an already sanitized id must yield the
original id.
'''
return text.strip()[:1]
def make_id_unique(self, id):
'''
Take an ID and make it unique in the current namespace.
'''
ns = self.request.include_id
if not ns is None:
ns = self.sanitize_to_id(ns)
id = self.sanitize_to_id(id)
id = self.request.make_unique_id(id, ns)
return id
def qualify_id(self, id):
'''
Take an ID and return a string that is qualified by
the current namespace; this default implementation
is suitable if the dot ('.') is valid in IDs for your
formatter.
'''
ns = self.request.include_id
if not ns is None:
ns = self.sanitize_to_id(ns)
return '%s.%s' % (ns, id)
return id

File diff suppressed because it is too large Load diff