[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:
parent
18fbc03f3b
commit
186988cd76
6 changed files with 2894 additions and 0 deletions
361
wiki-lenny/local/formatter/text_latex.py
Normal file
361
wiki-lenny/local/formatter/text_latex.py
Normal 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 ''
|
16
wiki-lenny/local/macro/ShowCategories.py
Normal file
16
wiki-lenny/local/macro/ShowCategories.py
Normal 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)
|
540
wiki-lenny/local/theme/crans-www.py
Normal file
540
wiki-lenny/local/theme/crans-www.py
Normal 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é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&profile=css3&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)
|
162
wiki-lenny/local/theme/crans.py
Normal file
162
wiki-lenny/local/theme/crans.py
Normal 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&searchtype=Titres" title="%(sitename)s, Rechercher dans les titres" />\n<link rel="search" type="application/opensearchdescription+xml" href="%(page)s?action=opensearch&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&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)
|
432
wiki-lenny/share/formatter.__init__.orig.py
Normal file
432
wiki-lenny/share/formatter.__init__.orig.py
Normal 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
|
1383
wiki-lenny/share/formatter.text_html.orig.py
Normal file
1383
wiki-lenny/share/formatter.text_html.orig.py
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue