Imports initiaux

darcs-hash:20060414194001-d1718-ceecbd9d441a17318a957ec7b4686f85a4aa47b5.gz
This commit is contained in:
bernat 2006-04-14 21:40:01 +02:00
parent 1c6255c1d7
commit 8f2f2247d7
18 changed files with 5116 additions and 0 deletions

110
wiki/parser/Box.py Normal file
View file

@ -0,0 +1,110 @@
# -*- coding: iso-8859-1 -*-
"""
MoinMoin - Portail parser
PURPOSE:
une boite jolie
CALLING SEQUENCE:
{{{
#!Box titre
blablabla
tables, images....
}}}
"""
from MoinMoin.parser import wiki
import os,string,re,StringIO
from MoinMoin.action import AttachFile
#####################################################################
# Fonctions #
#####################################################################
# to_wikiname : transfome la chaine text avec le parser wiki
# classique et le formateur formatter
# (je sais pas a quoi sert request, mais faut pas
# l'enlever !)
#######
def to_wikiname(request,formatter,text):
##taken from MiniPage
out=StringIO.StringIO()
request.redirect(out)
wikiizer = wiki.Parser(text,request)
wikiizer.format(formatter)
result=out.getvalue()
request.redirect()
del out
return result.strip()
#####################################################################
# BoxFormatter : creer le code html
#######
class BoxFormatter:
def __init__(self, request, formatter):
self.formatter = formatter
self.request = request
self.counter = 0
def make(self, title, body_html, color=None):
if color==None:
css_color_class=u""
else:
css_color_class = u" %s_box" % color
html = [
self.formatter.rawHTML(u'<div class="sidebox%s">' % css_color_class),
self.formatter.rawHTML(u'<div class="boxhead">'),
self.formatter.heading(1,3),
title,
self.formatter.heading(0,3),
self.formatter.rawHTML(u'</div>'),
self.formatter.rawHTML(u'<div class="boxbody1">'),
self.formatter.rawHTML(u'<div class="boxbody2">'),
body_html,
self.formatter.rawHTML(u'</div>'),
self.formatter.rawHTML(u'</div>'),
self.formatter.rawHTML(u'</div>'),
]
self.request.write(u'\n'.join(html))
#####################################################################
# Parser : classe principale, c'est elle qui parse
#######
class Parser:
def __init__(self, raw, request, **kw):
self.request = request
self.raw = raw
self.settings={'title': u'|'.join([u" ".join(kw.keys()), u" ".join(kw.values())])}
self.settings = self.parseArgs(kw["format_args"])
def parseArgs(self, argsString):
argList = argsString.split(u',')
settings = {}
for anArg in argList:
anArg = anArg.strip(u' ')
if anArg.find(u'color=')!=-1:
settings['color'] = anArg.split(u'=')[1]
else:
settings['title'] = anArg
return settings
def format(self, formatter):
quotes = self.raw
# on utilise la classe qui va fabriquer le code html
boite = BoxFormatter(self.request, formatter)
title = self.settings['title']
content = to_wikiname(self.request, formatter, quotes)
try:
color = self.settings['color']
except:
color=None
boite.make( title,content, color)
return

1193
wiki/parser/EXIF.py Normal file

File diff suppressed because it is too large Load diff

890
wiki/parser/Gallery2.py Normal file
View file

@ -0,0 +1,890 @@
# -*- coding: iso-8859-1 -*-
"""
MoinMoin - Gallery2 parser
PURPOSE:
This parser is used to visualize a couple of images as a thumbnail gallery.
Optional a description of an image could be added including WikiName.
On default the image name and it's creation date is shown.
If you click on a thumbnail you get the webnails shown. By a menue you are able to toggle between the slides.
CALLING SEQUENCE:
{{{
#!Gallery2 [columns=columns],[filter=filter],[mode=mode],
[show_text=show_text],[show_date=show_date], [show_tools=show_tools],
[sort_by_name=sort_by_name],[sort_by_date=sort_by_date], [sort_by_alias=sort_by_alias],
[reverse_sort=reverse_sort],
[only_items=only_items],[template_itemlist=template_itemlist],
[album=album],[album_name=album_name],[front_image=front_image],
[thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],
[image_for_webnail=image_for_webnail],
[border_thick=border_thick],[renew=renew],[help=help]
* [image1.jpg alias]
* [image2.jpg alias]
}}}
KEYWORD PARAMETERS:
columns: number of columns for thumbnails
filter: regex to select images
show_text: default is 1 description is shown
any other means no description
show_date: default is 1 date info from exif header if available is shown
show_tools: default is 1 icon toolbar is show any other disables this
sort_by_name: default is 1, the images are sorted by name, but not if only_items is 1
sort_by_date: default is 0, if set to 1 the images are sorted to the modification time
sort_by_alias default is 0, if set to 1 and only_items set to 1 it is used to order the images by the alias name
reverse_sort: default is 0, if set to 1 the file list is reversed
any other means no description
mode: default is 1 this means description below the image
any other number means description right of image
only_items: default is 0 if it is set to 1 only images which are described in listitem are shown
dependend on the order of the items
template_itemlist: default is 0, if set to 1 an item list is shown which could be copied into the script.
album: default is 0 if set to 1 only the first image of a series is shown but slideshow over all images
album_name: useful for album. default is 'album' use it as short name for the album.
front_image: Useful for album. default is ''. The first image is shown in front of the album and slideshow.
If set to an existing image name this is shown in front of album and slideshow.
The slide show could start by this somewhere.
border_thick: default is 1 this is the thickness in pixeln of the outer frame
renew: default is 0 if set to 1 then all selected thumbnails_* and webnails_* removed.
Afterwards they are new created.
thumbnail_width: default is 128
webnail_width: default is 640
text_width: default is 140
image_for_webnail default is 0 if set to 1 then the image is shown as preview and not the webnail
help: default is 0 if set a copy of the CALLING SEQUENCE is shown,
(there are some new ideas around to show help to an user so this will be later replaced)
OPTIONAL INPUTS:
itemlist : if it is used and only_items is 1 then only the images in this list are ahown.
The alias text is used as description of the image instead of the file name
EXAMPLE:
= GalleryTest =
== all images shown, one is decribed ==
{{{
{ { {
#!Gallery2
* [100_1185.JPG Bremen, SpaceCenter]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2
* [100_1185.JPG Bremen, SpaceCenter]
}}}
== only thumbnails and only_items ==
{{{
{ { {
#!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
* [100_1185.JPG Bremen, SpaceCenter]
* [100_1194.JPG Bremen]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 show_text=0,show_tools=0,show_date=0,columns=2,only_items=1
* [100_1185.JPG Bremen, SpaceCenter]
* [100_1194.JPG Bremen]
}}}
== only_items by two columns and text right ==
{{{
{ { {
#!Gallery2 mode=2,columns=2,only_items=1
* [100_1185.JPG Bremen, SpaceCenter]
* [100_1194.JPG Bremen]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 mode=2,columns=2,only_items=1
* [100_1185.JPG Bremen, SpaceCenter]
* [100_1194.JPG Bremen, behind SpaceCenter]
}}}
----
== only_items by two columns, date supressed ==
{{{
{ { {
#!Gallery2 columns=2,only_items=1,show_date=0
* [100_1185.JPG Bremen, SpaceCenter]
* [100_1194.JPG Bremen, behind SpaceCenter]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 columns=2,only_items=1,show_date=0
* [100_1185.JPG Bremen, SpaceCenter]
* [100_1194.JPG Bremen, behind SpaceCenter]
}}}
== filter regex used, mode 2, icons and date supressed, one column and border_thick=5 ==
{{{
{ { {
#!Gallery2 columns=1,filter=100_118[0-5],mode=2,show_date=0,show_tools=0,border_thick=5
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 columns=1,filter=100_118[0-7],mode=2,show_date=0,show_tools=0,border_thick=5
}}}
== other macro calls ==
{{{
{ { {
#!Gallery2 only_items=1,show_date=0
* [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 only_items=1,show_date=0
* [100_1189.JPG [[MiniPage(||Bremen||SpaceCenter||\n|| ||SpaceJump||)]]]
}}}
== renew means always new thumbnails and webnails of selection ==
{{{
{ { {
#!Gallery2 only_items=1,show_date=0,show_tools=0,renew=1
* [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 only_items=1,show_date=0,renew=1
* [100_1189.JPG [[MiniPage(||["Bremen"]||SpaceCenter||\n|| ||SpaceJump||)]]]
}}}
== template_itemlist ==
{{{
{ { {
#!Gallery2 template_itemlist=1
* [100_1185.JPG Bremen, SpaceCenter]
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 template_itemlist=1
* [100_1185.JPG Bremen, SpaceCenter]
}}}
== help to show Calling Sequence ==
{{{
{ { {
#!Gallery2 help=1
} } }
}}}
Result: [[BR]]
{{{
#!Gallery2 help=1
}}}
PROCEDURE:
Download some images to a page and start with the examples.
Aliasing of the filenames are done by adding an itemlist, see example.
This routine requires the PIL (Python Imaging Library).
And the EXIF routine from http://home.cfl.rr.com/genecash/digital_camera.html
At the moment I have added the EXIF routine to the parsers dir.
It's not the best place but during developing it is nice to have it there
If you put it to another place you have to change the line
from MoinMoin.parser import EXIF too.
This routine requires the Action macro gallery2Image which is used to rotate or delete a selected image.
Only users which have the rights to delete are able to execute this action macro.
The icons of these are only shown if you have enough rights.
The gallery2image macro does not take care on the EXIF header. This is lost by rotating.
If a file is deleted by this macro it is moved to a bak file.
Please remove the Version number from the code!
RESTRICTIONS:
The movie mode is not implemented at the moment. The implementation will be done in the action macro.
If you rotate an image at the moment the exif is destroyed. PIL ignores the exif header.
This is not a quite big problem normally files with an EXIF header are right rotated.
Required Images:
I have put them to wiki/modern/img/ dir. The icons were created by me. License: GPL
attachment:to_bak.png
attachment:to_left.png
attachment:to_right.png
attachment:to_slide.png
attachment:to_full.png
HISTORY:
While recognizing how to write MiniPage I got the idea to write a Gallery Parser.
We have used in our wikis in the past the Gallery macro of SimonRyan.
I have tried to modify it a bit to change it for 1.3 but my python skills weren't enough
or it was easier to write it completly new.
So this one shows now a way how a Gallery could be used by the parser and an action Macro.
Probably it is a good example for others who like to know how to do this
MODIFICATION HISTORY:
Version 1.3.3.-1
@copyright: 2005 by Reimar Bauer (R.Bauer@fz-juelich.de)
@license: GNU GPL, see COPYING for details.
2005-03-26: Version 1.3.3-2 keyword renew added
creation of thumbnails and webnails in two calls splitted
Version 1.3.3-3 bug fixed if itemlist is given to describe only some of the images
but only_items is not set to 1
Example code changed
2005-03-27: Version 1.3.3-4 Action macro added and the form to call it. User which have rights to delete
could use the functions of gallery2Image.
2005-08-03: Version 1.3.3-5 theme path for icons corrected and a platform independent path joining
os.unlink removed as suggested by CraigJohnson
sort_by_name is default if not only_items is 1
optional sort_by_date could be used
keyword template_itemlist added
keyword help added
extra frame by mode=2 removed
2005-08-06: Version 1.3.5-6 slideshow mode added
keyword image_for_webnail added
2005-08-13: Version 1.3.5-7 syntax changed from GET to POST
forms instead of links
filenames from images submitted to gallery2image too
new keyword sort_by_alias
internal code clean up
this version needs: gallery2image-1.3.5-5.py
2005-08-14: Version 1.3.5-8 (TW) cleanup
2005-08-14: Version 1.3.5-9 html code for tables changed
because of the ugly extra space of form elements
</div> tag removed so now we use the page style
slide show action goes to right webnail now
this version needs: gallery2image-1.3.5-5.py
2005-08-17: Version 1.3.5-10 html code separated in functions
structure of code changed, now you see the thumbnails after creation
bug removed if quote is given but file does not exist
2005-09-02: Version 1.3.5-11 keyword album, album_name and front_image added
image urls changed to complete server url
"""
Dependencies = []
from MoinMoin.action import AttachFile
from MoinMoin import wikiutil, config
from MoinMoin.Page import Page
import os,string,re,Image,StringIO
#from MoinMoin.parser import EXIF
import EXIF
from MoinMoin.parser import wiki
def show_tools_restricted(pagename,this_target,thumbnail_width,full,alias,target,exif_date,request):
if request.user.may.delete(pagename):
return tools_restricted_html(pagename,this_target,thumbnail_width,full,alias,target,exif_date,request)
else:
return ''
def tools_restricted_html(pagename,this_target,thumbnail_width,full,alias,target,exif_date,request):
text='''
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td>
<input type="hidden" name="action" value="gallery2image">
<input type="hidden" name="do" value="RL">
<input type="hidden" name="target" value="%(this_target)s">
<input type="image" value="submit" src="%(server)s/wiki/modern/img/to_left.png" title="rotate to left">
</td>
</form>
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td>
<input type="hidden" name="action" value="gallery2image">
<input type="hidden" name="do" value="RR">
<input type="hidden" name="target" value="%(this_target)s">
<input type="image" value="submit" src="%(server)s/wiki/modern/img/to_right.png" title="rotate to right" >
</td>
</form>
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td>
<input type="hidden" name="action" value="gallery2image">
<input type="hidden" name="do" value="RM">
<input type="hidden" name="target" value="%(this_target)s">
<input type="image" value="submit" src="%(server)s/wiki/modern/img/to_bak.png" title="move to bak" >
</td>
</form>''' % {
"server" : 'https://'+request.server_name,
'baseurl': request.getScriptname(),
"pagename":pagename,
"this_target":this_target}
return text
def tools_html(pagename,this_image,thumbnail_width,full,alias,target,exif_date,request):
text='''
<TABLE align="center" width="%(thumbnail_width)s">
<TR>
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td>
<input type="hidden" name="action" value="AttachFile">
<input type="hidden" name="do" value="get">
<input type="hidden" name="target" value="%(this_target)s">
<input type="image" value="submit" src="%(server)s/wiki/modern/img/to_full.png" title="load image">
</td>
</form>
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td>
<input type="hidden" name="action" value="gallery2image">
<input type="hidden" name="do" value="VS">
<input type="hidden" name="full" value="%(full)s">
<input type="hidden" name="alias" value="%(alias)s">
<input type="hidden" name="target" value="%(target)s">
<input type="hidden" name="exif_date" value="%(exif_date)s">
<input type="image" value="submit" src="%(server)s/wiki/modern/img/to_slide.png" title="slide_show" >
</td>
</form>
%(show_tools_restricted)s
</TR>
</TABLE>''' % {
"server" : 'https://'+request.server_name,
'baseurl': request.getScriptname(),
"pagename":pagename,
"thumbnail_width":thumbnail_width,
"full":full,
"alias":alias,
"exif_date":exif_date,
"target":target,
"this_target":this_image,
"show_tools_restricted":show_tools_restricted(pagename,this_image,thumbnail_width,full,alias,target,exif_date,request)
}
return text
def show_alias_mode2(show_alias,thumbnail_width,this_alias,text_width):
if show_alias == '1':
return '''
<td valign="top" width="%(text_width)s">
%(this_alias)s
</td>''' % {
"this_alias":this_alias,
"text_width":text_width}
else:
return ''
def show_date_mode2(show_date,this_exif_date):
if show_date == '1':
return '''
<td>
<p>%(this_exif_date)s</p>
</td>''' % {
"this_exif_date":this_exif_date }
else:
return '';
def show_tools_mode2(show_tools,pagename,this_target,thumbnail_width,full,alias,target,exif_date,request):
if show_tools == '1' :
return "<td align=""center""> %s </td>" % tools_html(pagename,this_target,thumbnail_width,full,alias,target,exif_date,request)
else:
return ''
def mode2_html(pagename,border_thick,width,thumbnail_width,text_width,full,this_image,alias,this_alias,exif_date,this_exif_date,target,this_target,submit,show_tools,show_date,show_alias,request):
text='''
<tr valign="center">
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td align="center" valign="center" width="%(thumbnail_width)s">
<input type="hidden" name="action" value="gallery2image">
<input type="hidden" name="do" value="VS">
<input type="hidden" name="full" value="%(full)s">
<input type="hidden" name="alias" value="%(alias)s">
<input type="hidden" name="exif_date" value="%(exif_date)s">
<input type="hidden" name="target" value="%(target)s">
<input type="image" value="submit" src="%(server)s%(submit)s">
</td>
</form>
%(alias_html)s
</tr>
<tr>%(tools_html)s%(date_html)s</tr>'''% {
"server" : 'https://'+request.server_name,
"baseurl": request.getScriptname(),
"pagename":pagename,
"thumbnail_width":thumbnail_width,
"full":full,
"alias":alias,
"exif_date":exif_date,
"target":target,
"submit":submit,
"tools_html":show_tools_mode2(show_tools,pagename,this_image,thumbnail_width,full,alias,target,exif_date,request),
"date_html": show_date_mode2(show_date,this_exif_date),
"alias_html": show_alias_mode2(show_alias,thumbnail_width,this_alias,text_width)
}
return text
def show_tools_mode1(show_tools,pagename,this_image,thumbnail_width,full,alias,target,exif_date,request):
if show_tools == '1' :
text="<tr><td align=""center"">%s </td></tr>" % tools_html(pagename,this_image,thumbnail_width,full,alias,target,exif_date,request)
else:
text=''
return text
def show_date_mode1(show_date,this_exif_date):
if show_date == '1':
return '''
<TR>
<td>%(this_exif_date)s</td>
</TR>''' % {
"this_exif_date":this_exif_date}
else:
return ''
def show_alias_mode1(show_alias,thumbnail_width,this_alias,text_width):
if show_alias == '1':
return '''
<TR>
<td align="left" width="%(thumbnail_width)s"> %(this_alias)s</td>
</TR>''' % {
"thumbnail_width": thumbnail_width,
"this_alias":this_alias}
else:
return ''
def mode1_html(pagename,border_thick,width,thumbnail_width,text_width,full,this_image,alias,this_alias,exif_date,this_exif_date,target,this_target,submit,
show_tools,show_date,show_alias,request):
text='''
<table width="%(thumbnail_width)s" align="center" valign="center">
<TR align="center" valign="center">
<form action="%(baseurl)s/%(pagename)s" method="POST" enctype="multipart/form-data">
<td align="center" valign="middle" width="%(thumbnail_width)s">
<input type="hidden" name="action" value="gallery2image">
<input type="hidden" name="do" value="VS">
<input type="hidden" name="full" value="%(full)s">
<input type="hidden" name="alias" value="%(alias)s">
<input type="hidden" name="exif_date" value="%(exif_date)s">
<input type="hidden" name="target" value="%(target)s">
<input type="image" value="submit" src="%(server)s%(submit)s" >
</td>
</form>
</TR>
%(alias_html)s
%(date_html)s
%(tools_html)s
</table>'''% {
"server" : 'https://'+request.server_name,
"baseurl": request.getScriptname() ,
"pagename":pagename,
"full":full,
"alias":alias,
"exif_date":exif_date,
"target":target,
"submit":submit,
"thumbnail_width":thumbnail_width,
"tools_html": show_tools_mode1(show_tools,pagename,this_image,thumbnail_width,full,alias,target,exif_date,request),
"date_html":show_date_mode1(show_date,this_exif_date),
"alias_html": show_alias_mode1(show_alias,thumbnail_width,this_alias,text_width)
}
return text
def get_files(kw,path,files,quotes,request):
web=[]
full=[]
thumb=[]
exif_date=[]
img_type=[]
description=[]
ddict={}
n=len(quotes['image'])
if n > 0 :
i = 0
for txt in quotes['image']:
ddict[txt]=quotes['alias'][i]
i += 1
for attfile in files:
# only files not thumb or webnails
if attfile.find('thumbnail_') == -1 and attfile.find('webnail_') == -1:
# only images
if wikiutil.isPicture(attfile):
description.append(ddict.get(attfile, attfile))
full.append(attfile)
if kw['image_for_webnail'] == '1':
webnail = attfile
else:
fname, ext = os.path.splitext(attfile)
if ext in ('.gif', '.png'):
img_type.append('PNG')
webnail = 'webnail_%s.png' % fname
thumbfile = 'thumbnail_%s.png' % fname
else:
img_type.append("JPEG")
webnail = 'webnail_%s.jpg' % fname
thumbfile = 'thumbnail_%s.jpg' % fname
infile = os.path.join(path, attfile)
if os.path.exists(infile):
web.append(webnail)
thumb.append(thumbfile)
f = open(infile, 'rb')
tags = EXIF.process_file(f)
if tags.has_key('EXIF DateTimeOriginal'):
date = str(tags['EXIF DateTimeOriginal'])
date = date.replace(':', '-', 2)
else:
date = '--'
exif_date.append(date)
f.close()
return thumb,web,full,exif_date,img_type,description
def to_htmltext(text):
text = text.split(' ')
text = '&nbsp;'.join(text)
return text
def to_wikiname(request,formatter,text):
##taken from MiniPage
out=StringIO.StringIO()
request.redirect(out)
wikiizer = wiki.Parser(text.strip(),request)
wikiizer.format(formatter)
result=out.getvalue()
request.redirect()
del out
return result.strip()
def get_quotes(self,formatter):
quotes = self.raw.split('\n')
quotes = [quote.strip() for quote in quotes]
quotes = [quote[2:] for quote in quotes if quote.startswith('* ')]
image=[]
text=[]
for line in quotes:
im, na=line[1:-1].split(' ',1)
text.append(na.strip())
image.append(im.strip())
return {
'alias': text,
'image': image,
}
class Parser:
def __init__(self, raw, request, **kw):
self.raw = raw
self.request = request
self.form = request.form
self._ = request.getText
self.kw = {
'sort_by_date': '0',
'sort_by_name': '1',
'sort_by_alias': '0',
'album': '0',
'album_name': 'album',
'front_image':'',
'template_itemlist': '0',
'reverse_sort': '0',
'border_thick': '1',
'columns': '4',
'filter': '.',
'mode': '1',
'help': '0',
'show_text': '1',
'show_date': '1',
'show_tools': '1',
'only_items': '0',
'image_for_webnail': '0',
'renew': '0',
'thumbnail_width': '128',
'webnail_width': '640',
'text_width': '140',
}
for arg in kw.get('format_args','').split(','):
if arg.find('=') > -1:
key, value=arg.split('=')
self.kw[key]=wikiutil.escape(value, quote=1)
self.kw['width']=str((int(self.kw['thumbnail_width'])+int(self.kw['text_width'])))
def format(self, formatter):
kw=self.kw
Dict = {}
quotes=get_quotes(self,formatter)
current_pagename=formatter.page.page_name
attachment_path = AttachFile.getAttachDir(self.request, current_pagename, create=1)
if kw['help'] == '1':
self.request.write('''
<br>
{{{<br>
#!Gallery2 [columns=columns],[filter=filter],[mode=mode],<br>
[show_text=show_text],[show_date=show_date], [show_tools=show_tools],<br>
[sort_by_name=sort_by_name],[sort_by_date=sort_by_date],[sort_by_alias=sort_by_alias]<br>
[reverse_sort=reverse_sort],<br>
[only_items=only_items],[template_itemlist=template_itemlist],<br>
[album=album],[album_name=album_name],[front_image=front_image],<br>
[thumbnail_width=thumbnail_width],[webnail_width=webnail_width],[text_width=text_width],<br>
[image_for_webnail=image_for_webnail],<br>
[border_thick=border_thick],[renew=renew],[help=help]<br>
* [image1.jpg alias]<br>
* [image2.jpg alias]<br>
}}}<br>''')
return
if kw['only_items'] == '1':
all_files=quotes['image']
result=[]
for attfile in all_files:
infile=os.path.join(attachment_path,attfile)
if os.path.exists(infile):
result.append(attfile)
all_files = result
if kw['sort_by_alias'] == '1':
new_ordered_files=[]
alias_text=quotes['alias']
i=0
for attfile in all_files:
infile=os.path.join(attachment_path,attfile)
ft_file=str(os.path.getmtime(infile))+os.tmpnam()
Dict[alias_text[i]]=attfile
i += 1
keys = Dict.keys()
keys.sort()
for txt in keys:
new_ordered_files.append(Dict[txt])
all_files=new_ordered_files
Dict.clear()
else:
all_files=os.listdir(attachment_path)
result = []
for test in all_files:
if re.match(kw['filter'], test):
result.append(test)
all_files=result
if not all_files:
self.request.write("<br><br><h1>No matching image file found!</h1>")
return
if kw['sort_by_name'] == '1' and kw['only_items'] == '0':
all_files.sort()
if kw['sort_by_date']=='1':
for attfile in all_files:
infile=os.path.join(attachment_path,attfile)
ft_file=str(os.path.getmtime(infile))+os.tmpnam()
Dict[ft_file]=attfile
keys = Dict.keys()
keys.sort()
file_mdate=[]
for txt in keys:
file_mdate.append(Dict[txt])
all_files=file_mdate
Dict.clear()
if kw['reverse_sort']=='1':
all_files.reverse()
cells=[]
cell_name=[]
img=[]
thumb, web, full, exif_date, imgtype, description = get_files(kw, attachment_path, all_files, quotes, self.request)
if kw['template_itemlist'] == '1':
self.request.write('Copy the following listitems into the script. Replace alias with the label you want. Afterwards disable template_itemlist by setting it to 0:<BR>')
for attfile in full :
self.request.write(' * [%(attfile)s %(date)s]<br>' % {
'attfile' : attfile,
'date' : 'alias'
})
i = 0
z = 1
cols = int(kw['columns'])
n = len(full)
if kw['album'] == '0' :
self.request.write("<table align='center' border='%s' >" % self.kw['border_thick'])
if kw['mode'] == '1' or cols > 1 :
self.request.write('<TR valign="bottom">')
self.request.write('<TD>')
if kw['album'] == '1' :
if kw['front_image'] == '' :
front_image = full[0]
else:
front_image = kw['front_image']
ii = 0
for tst in full :
if tst == front_image :
break
ii += 1
for attfile in full :
if kw['album'] == '1' :
if tst == front_image :
i = ii
this_description=description[i]
this_exif_date=exif_date[i]
this_webnail=web[i]
this_imgtype=imgtype[i]
this_thumbfile=thumb[i]
thumbf=os.path.join(attachment_path,this_thumbfile)
webf=os.path.join(attachment_path,this_webnail)
if kw['renew'] == '1':
if os.path.exists(thumbf):
os.unlink(thumbf)
if os.path.exists(webf):
os.unlink(webf)
if not os.path.exists(webf) or not os.path.exists(thumbf):
infile=os.path.join(attachment_path,attfile)
im = Image.open(infile)
if not os.path.exists(webf):
im.thumbnail(((int(kw['webnail_width'])),((int(kw['webnail_width'])))), Image.ANTIALIAS)
im.save(webf, this_imgtype)
if not os.path.exists(thumbf):
im.thumbnail(((int(kw['thumbnail_width'])),((int(kw['thumbnail_width'])))),
Image.ANTIALIAS)
im.save(thumbf, this_imgtype)
if kw['mode'] == '1':
text=mode1_html(current_pagename,
kw['border_thick'],
kw['width'],
kw['thumbnail_width'],
kw['text_width'],
attfile + "," + ','.join(full),
attfile,
to_htmltext(this_description + "!,!" + '!,!'.join(description)),
to_wikiname(self.request,formatter,this_description),
to_htmltext(this_exif_date + "," + ','.join(exif_date)),
this_exif_date,
this_webnail + "," + ','.join(web),
this_webnail,
AttachFile.getAttachUrl(current_pagename, this_thumbfile, self.request),
kw['show_tools'],
kw['show_date'],
kw['show_text'],
self.request
)
self.request.write(''.join(text))
if kw['mode'] == '2':
text=mode2_html(current_pagename,
kw['border_thick'],
kw['width'],
kw['thumbnail_width'],
kw['text_width'],
attfile + "," + ','.join(full),
attfile,
to_htmltext(this_description + "!,!" + '!,!'.join(description)),
to_wikiname(self.request,formatter,this_description),
to_htmltext(this_exif_date + "," + ','.join(exif_date)),
this_exif_date,
this_webnail + "," + ','.join(web),
this_webnail,
AttachFile.getAttachUrl(current_pagename, this_thumbfile, self.request),
kw['show_tools'],
kw['show_date'],
kw['show_text'],
self.request
)
if cols > 1 : self.request.write('<table valign="bottom">')
self.request.write(''.join(text))
if cols > 1 : self.request.write('</table>')
if kw['mode'] == '1' or cols > 1:
if kw['album'] == '0' :
if z < cols:
self.request.write('</TD>')
if z < n :
self.request.write('<TD>')
else:
self.request.write('</TD>')
self.request.write('</TR>')
if i < n-1 :
self.request.write('<TR valign="bottom">')
self.request.write('<TD>')
i += 1
z += 1
if z > cols :
z = 1
if kw['album'] == '1' :
self.request.write("%(n)s images (%(album_name)s)" % {"n": str(n), "album_name":kw['album_name']})
break
if kw['album'] == '0' :
if i < n :
self.request.write('</TD>')
self.request.write('</TR>')
self.request.write('</table>')
############################################
##TODO: syntax change to formatter - later #
############################################

117
wiki/parser/Portail.py Normal file
View file

@ -0,0 +1,117 @@
# -*- coding: iso-8859-1 -*-
"""
MoinMoin - Portail parser
PURPOSE:
Pour afficher un portail a la wikipedia.
CALLING SEQUENCE:
{{{
#!Portail
image1.png | title1 | description 1
image2.png | title2 | description 2
image3.png | title3 | description 3
}}}
CREDIT
Le code est derive de celui de Gallery2.
"""
from MoinMoin.parser import wiki
import os,string,re,StringIO
from MoinMoin.action import AttachFile
#####################################################################
# Fonctions #
#####################################################################
# to_wikiname : transfome la chaine text avec le parser wiki
# classique et le formateur formatter
# (je sais pas a quoi sert request, mais faut pas
# l'enlever !)
#######
def to_wikiname(request,formatter,text):
##taken from MiniPage
out=StringIO.StringIO()
request.redirect(out)
wikiizer = wiki.Parser(text.strip(),request)
wikiizer.format(formatter)
result=out.getvalue()
request.redirect()
del out
return result.strip()
#####################################################################
# PortailFormatter : creer le code html du portail a l'aide de
# de formatter et l'envoie a request
#######
class PortailFormatter:
def __init__(self, request, formatter):
self.formatter = formatter
self.request = request
self.counter = 0
def open(self):
self.request.write(self.formatter.table(1,{'style':'width:100%;padding:10px;'}))
def cell(self, title, description, image):
if self.counter==0:
self.request.write(self.formatter.table_row(1))
self.request.write(self.formatter.table_cell(1,{'style':'width:50%;border:none;padding:20px 20px 20px 50px;background:transparent url(\'' + image.replace("\'","\\\'") + '\') center left no-repeat; vertical-align:center;'}))
self.request.write(title)
self.request.write(description)
self.request.write(self.formatter.table_cell(0))
if self.counter==1:
self.request.write(self.formatter.table_row(0))
self.counter = (self.counter + 1)%2
def close(self):
if self.counter==1:
self.request.write(self.formatter.table_cell(1,{'style':'width:50%;border:none;padding:20px 20px 20px 50px;'}))
self.request.write(self.formatter.table_cell(0))
self.request.write(self.formatter.table_row(0))
self.request.write(self.formatter.table(0))
#####################################################################
# Parser : classe principale, c'est elle qui parse
#######
class Parser:
def __init__(self, raw, request, **kw):
self.request = request
self.raw = raw
return
def format(self, formatter):
# on divise le textes en lignes (1 ligne = une entree dans le portail)
quotes = self.raw.split('\n')
# on récupere le chemin des fichiers attaches pour les images
current_pagename=formatter.page.page_name
attachment_path = AttachFile.getAttachDir(self.request, current_pagename, create=1)
# on initialise la classe qui va fabriquer le code html
portail = PortailFormatter(self.request, formatter)
portail.open()
# on traite les ligne une à une
for line in quotes:
line=line.strip()
items=line.split('|',2)
if items.__len__()<3:
self.request.write('<!-- error, wrong number of parameters -->')
else:
description=items.pop().strip()
link=items.pop().strip()
image = AttachFile.getAttachUrl(current_pagename, items.pop().strip(), self.request)
link = to_wikiname(self.request, formatter, link)
description = to_wikiname(self.request, formatter, description)
portail.cell(link, description, image)
portail.close()
return

5
wiki/parser/__init__.py Normal file
View file

@ -0,0 +1,5 @@
# -*- coding: iso-8859-1 -*-
from MoinMoin.util import pysupport
modules = pysupport.getPackageModules(__file__)

214
wiki/parser/latex.py Normal file
View file

@ -0,0 +1,214 @@
#FORMAT python
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
"""
New latex formatter using dvipng and tempfile
Author: JohannesBerg <johannes@sipsolutions.net>
This parser (and the corresponding macro) was tested with Python 2.3.4 and
* Debian Linux with out-of-the-box tetex-bin and dvipng packages installed
* Windows XP (not by me)
In the parser, you can add stuff to the prologue by writing
%%end-prologue%%
somewhere in the document, before that write stuff like \\usepackage and after it put
the actual latex display code.
"""
Dependencies = []
import sha, os, tempfile, shutil, re
from MoinMoin.action import AttachFile
from MoinMoin.Page import Page
latex_template = r'''
\documentclass[12pt]{article}
\pagestyle{empty}
%(prologue)s
\begin{document}
%(raw)s
\end{document}
'''
max_pages = 10
MAX_RUN_TIME = 5 # seconds
latex = "latex" # edit full path here, e.g. reslimit = "C:\\path\\to\\latex.exe"
dvipng = "dvipng" # edit full path here (or reslimit = r'C:\path\to\latex.exe')
# last arg must have %s in it!
latex_args = ("--interaction=nonstopmode", "%s.tex")
# last arg must have %s in it!
dvipng_args = ("-bgTransparent", "-Ttight", "--noghostscript", "-l%s" % max_pages, "%s.dvi")
# this is formatted with hexdigest(texcode),
# page number and extension are appended by
# the tools
latex_name_template = "latex_%s_p"
# keep this up-to-date, also with max_pages!!
latex_attachment = re.compile((latex_name_template+'%s%s') % (r'[0-9a-fA-F]{40}', r'[0-9]{1,2}', r'\.png'))
anchor = re.compile(r'^%%anchor:[ ]*([a-zA-Z0-9_-]+)$', re.MULTILINE | re.IGNORECASE)
# the anchor re must start with a % sign to be ignored by latex as a comment!
end_prologue = '%%end-prologue%%'
def call_command_in_dir_NT(app, args, targetdir):
reslimit = "runlimit.exe" # edit full path here
os.environ['openin_any'] = 'p'
os.environ['openout_any'] = 'p'
os.environ['shell_escape'] = 'f'
stdouterr = os.popen('%s %d "%s" %s %s < NUL' % (reslimit, MAX_RUN_TIME, targetdir, app, ' '.join(args)), 'r')
output = ''.join(stdouterr.readlines())
err = stdouterr.close()
if not err is None:
return ' error! exitcode was %d, transscript follows:\n\n%s' % (err,output)
return None
def call_command_in_dir_unix(app, args, targetdir):
# this is the unix implementation
(r,w) = os.pipe()
pid = os.fork()
if pid == -1:
return 'could not fork'
if pid == 0:
# child
os.close(r)
os.dup2(os.open("/dev/null", os.O_WRONLY), 0)
os.dup2(w, 1)
os.dup2(w, 2)
os.chdir(targetdir)
os.environ['openin_any'] = 'p'
os.environ['openout_any'] = 'p'
os.environ['shell_escape'] = 'f'
import resource
resource.setrlimit(resource.RLIMIT_CPU,
(MAX_RUN_TIME * 1000, MAX_RUN_TIME * 1000)) # docs say this is seconds, but it is msecs on my system.
os.execvp(app, [app] + list(args))
print "failed to exec()",app
os._exit(2)
else:
# parent
os.close(w)
r = os.fdopen(r,"r")
output = ''.join(r.readlines())
(npid, exi) = os.waitpid(pid, 0)
r.close()
sig = exi & 0xFF
stat = exi >> 8
if stat != 0 or sig != 0:
return ' error! exitcode was %d (signal %d), transscript follows:\n\n%s' % (stat,sig,output)
return None
# notreached
if os.name == 'nt':
call_command_in_dir = call_command_in_dir_NT
else:
call_command_in_dir = call_command_in_dir_unix
class Parser:
extensions = ['.tex']
def __init__ (self, raw, request, **kw):
self.raw = raw
if len(self.raw)>0 and self.raw[0] == '#':
self.raw[0] = '%'
self.request = request
self.exclude = []
if not hasattr(request, "latex_cleanup_done"):
request.latex_cleanup_done = {}
def cleanup(self, pagename):
attachdir = AttachFile.getAttachDir(self.request, pagename, create=1)
for f in os.listdir(attachdir):
if not latex_attachment.match(f) is None:
os.remove("%s/%s" % (attachdir, f))
def _internal_format(self, formatter, text):
tmp = text.split(end_prologue, 1)
if len(tmp) == 2:
prologue,tex=tmp
else:
prologue = ''
tex = tmp[0]
if callable(getattr(formatter, 'johill_sidecall_emit_latex', None)):
return formatter.johill_sidecall_emit_latex(tex)
return self.get(formatter, tex, prologue, True)
def format(self, formatter):
self.request.write(self._internal_format(formatter, self.raw))
def get(self, formatter, inputtex, prologue, para=False):
if not self.request.latex_cleanup_done.has_key(formatter.page.page_name):
self.request.latex_cleanup_done[formatter.page.page_name] = True
self.cleanup(formatter.page.page_name)
if len(inputtex) == 0: return ''
if callable(getattr(formatter, 'johill_sidecall_emit_latex', None)):
return formatter.johill_sidecall_emit_latex(inputtex)
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)
tex = latex_template % { 'raw': inputtex, 'prologue': extra_preamble + prologue }
enctex = tex.encode('utf-8')
fn = latex_name_template % sha.new(enctex).hexdigest()
attachdir = AttachFile.getAttachDir(self.request, formatter.page.page_name, create=1)
dst = "%s/%s%%d.png" % (attachdir, fn)
if not os.access(dst % 1, os.R_OK):
tmpdir = tempfile.mkdtemp()
try:
data = open("%s/%s.tex" % (tmpdir, fn), "w")
data.write(enctex)
data.close()
args = list(latex_args)
args[-1] = args[-1] % fn
res = call_command_in_dir(latex, args, tmpdir)
if not res is None:
return formatter.preformatted(1)+formatter.text('latex'+res)+formatter.preformatted(0)
args = list(dvipng_args)
args[-1] = args[-1] % fn
res = call_command_in_dir(dvipng, args, tmpdir)
if not res is None:
return formatter.preformatted(1)+formatter.text('dvipng'+res)+formatter.preformatted(0)
page = 1
while os.access("%s/%s%d.png" % (tmpdir, fn, page), os.R_OK):
shutil.copyfile ("%s/%s%d.png" % (tmpdir, fn, page), dst % page)
page += 1
finally:
for root,dirs,files in os.walk(tmpdir, topdown=False):
for name in files:
os.remove(os.path.join(root,name))
for name in dirs:
os.rmdir(os.path.join(root,name))
os.rmdir(tmpdir)
result = ""
page = 1
loop = False
for match in anchor.finditer(inputtex):
result += formatter.anchordef(match.group(1))
for match in anchor.finditer(prologue):
result += formatter.anchordef(match.group(1))
while os.access(dst % page, os.R_OK):
url = AttachFile.getAttachUrl(formatter.page.page_name, fn+"%d.png" % page, self.request)
if loop:
result += formatter.linebreak(0)+formatter.linebreak(0)
if para:
result += formatter.paragraph(1)
result += formatter.image(src="%s" % url, alt=inputtex, title=inputtex, align="absmiddle")
if para:
result += formatter.paragraph(0)
page += 1
loop = True
return result

5
wiki/theme/__init__.py Normal file
View file

@ -0,0 +1,5 @@
# -*- coding: iso-8859-1 -*-
from MoinMoin.util import pysupport
modules = pysupport.getPackageModules(__file__)

35
wiki/theme/bde.py Normal file
View file

@ -0,0 +1,35 @@
# -*- 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.
"""
from crans import ThemeCrans
class Theme(ThemeCrans):
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'crans'),
('screen', 'bde'),
('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)

467
wiki/theme/blackliste.py Normal file
View file

@ -0,0 +1,467 @@
# -*- 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.
"""
from MoinMoin.theme import ThemeBase
from MoinMoin import wikiutil, i18n
from MoinMoin.Page import Page
class Theme(ThemeBase):
name = "blackliste"
# fake _ function to get gettext recognize those texts:
_ = lambda x: x
icons = {
# key alt icon filename w h
# ------------------------------------------------------------------
# navibar
'help': ("%(page_help_contents)s", "moin-help.png", 12, 11),
'find': ("%(page_find_page)s", "moin-search.png", 12, 12),
'diff': (_("Diffs"), "moin-diff.png", 22, 22),
'info': (_("Info"), "moin-info.png", 22, 22),
'edit': (_("Edit"), "moin-edit.png", 22, 22),
'unsubscribe':(_("Unsubscribe"), "moin-unsubscribe.png", 22, 22),
'subscribe': (_("Subscribe"), "moin-subscribe.png",22, 22),
'raw': (_("Raw"), "moin-raw.png", 12, 13),
'xml': (_("XML"), "moin-xml.png", 20, 13),
'print': (_("Print"), "moin-print.png", 16, 14),
'view': (_("View"), "moin-show.png", 22, 22),
'home': (_("Home"), "moin-home.png", 13, 12),
'up': (_("Up"), "moin-parent.png", 15, 13),
# FileAttach
'attach': ("%(attach_count)s", "moin-attach.png", 7, 15),
# RecentChanges
'rss': (_("[RSS]"), "moin-rss.png", 36, 14),
'deleted': (_("[DELETED]"), "moin-deleted.png",60, 12),
'updated': (_("[UPDATED]"), "moin-updated.png",60, 12),
'new': (_("[NEW]"), "moin-new.png", 31, 12),
'diffrc': (_("[DIFF]"), "moin-diff.png", 22, 22),
# General
'bottom': (_("[BOTTOM]"), "moin-bottom.png", 14, 10),
'top': (_("[TOP]"), "moin-top.png", 14, 10),
'www': ("[WWW]", "moin-www.png", 11, 11),
'mailto': ("[MAILTO]", "moin-email.png", 14, 10),
'news': ("[NEWS]", "moin-news.png", 10, 11),
'telnet': ("[TELNET]", "moin-telnet.png", 10, 11),
'ftp': ("[FTP]", "moin-ftp.png", 11, 11),
'file': ("[FILE]", "moin-ftp.png", 11, 11),
# search forms
'searchbutton': ("[?]", "moin-search.png", 12, 12),
'interwiki': ("[%(wikitag)s]", "moin-inter.png", 16, 16),
}
del _
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'blackliste'),
('print', 'print'),
('projection', 'projection'),
)
# Public functions #####################################################
def header(self, d, **kw):
""" Assemble wiki header
Here we don't add any menu bars, search bars, etc - instead wait
until the footer. This keeps the HTML cleaner and more accessible,
making sure the main content arrives first.
"""
html = [
u'<div id="globalWrapper">',
u'<div id="column-content">',
self.startPage(),
self.msg(d),
self.title(d),
]
return u'\n'.join(html)
def footer(self, d, **keywords):
""" Assemble wiki footer
"""
html = [
# End of page
u'<div class="visualClear"></div>',
self.endPage(),
u'</div>',
self.columnone(d),
u'</div>'
]
return u'\n'.join(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 = [('view', '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', ['view'])[0]
for action, title, description, accesskey in tabs:
if action == current:
cls = 'selected'
else:
cls = 'none'
if action == "subscribe":
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(
["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d)))
else:
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(action, d)))
html = [
u'<div id="p-cactions" class="portlet">',
u'<ul class="editbar">',
''.join(items),
u'</ul>',
u'</div>'
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def actionmenu(self, d):
""" different implementation of the actionmenu (aka toolbox)
"""
page = d['page']
# Use cached actionmenu if possible.
cacheKey = 'actionmenu'
cached = self._cache.get(cacheKey)
if cached:
return cached
request = self.request
_ = request.getText
quotedname = wikiutil.quoteWikinameURL(page.page_name)
menu = [
'raw',
'print',
'refresh',
'AttachFile',
'SpellCheck',
'LikePages',
'LocalSiteMap',
'RenamePage',
'DeletePage',
]
titles = {
'raw': _('Show Raw Text', formatted=False),
'print': _('Show Print View', formatted=False),
'refresh': _('Delete Cache', formatted=False),
'AttachFile': _('Attach File', formatted=False),
'SpellCheck': _('Check Spelling', formatted=False), # rename action!
'RenamePage': _('Rename Page', formatted=False),
'DeletePage': _('Delete Page', formatted=False),
'LikePages': _('Show Like Pages', formatted=False),
'LocalSiteMap': _('Show Local Site Map', formatted=False),
}
links = []
# Format standard actions
available = request.getAvailableActions(page)
for action in menu:
# Enable delete cache only if page can use caching
if action == 'refresh':
if not page.canUseCache():
break
# Actions which are not available for this wiki, user or page
if action[0].isupper() and not action in available:
break;
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, titles[action])
links.append(link)
# Add custom actions not in the standard menu
more = [item for item in available if not item in titles]
more.sort()
if more:
# Add more actions (all enabled)
for action in more:
data = {'action': action, 'disabled': ''}
title = Page(request, action).split_title(request, force=1)
# Use translated version if available
title = _(title, formatted=False)
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, title)
links.append(link)
html = [
u'<div class="portlet" id="p-tb">',
u'<h5>Toolbox</h5>',
u'<div class="pBody">',
u'<ul>',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def username(self, d):
""" Assemble the username / userprefs link
Copied from the base class, modified to include hotkeys and link titles
"""
from MoinMoin.Page import Page
request = self.request
_ = request.getText
userlinks = []
# Add username/homepage link for registered users. We don't care
# if it exists, the user can create it.
if request.user.valid:
homepage = Page(request, request.user.name)
title = homepage.split_title(request)
attrs = self.extendedAttrs(_('User Page'), '.')
homelink = homepage.link_to(request, text=title, attrs=attrs)
userlinks.append(homelink)
# Set pref page to localized Preferences page
attrs = self.extendedAttrs(_('My Preferences'), 'u')
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
title = prefpage.split_title(request)
userlinks.append(prefpage.link_to(request, text=title, attrs=attrs))
# Add a logout link (not sure this is really necessary
attrs = self.extendedAttrs(_('log out'), 'o')
page = d['page']
url = wikiutil.quoteWikinameURL(page.page_name) + \
'?action=userform&logout=1'
link = wikiutil.link_tag(self.request, url, 'log out', attrs=attrs)
userlinks.append(link)
else:
# Add prefpage links with title: Login
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
attrs = self.extendedAttrs('Logging in is not required, but brings benefits', 'o')
userlinks.append(prefpage.link_to(request, text=_("Login"), attrs=attrs))
html = [
u'<div class="portlet" id="p-personal">',
u'<ul id="username">',
u'<li class="pt-userpage">%s</li></ul>' % '</li>\n<li>'.join(userlinks),
u'</ul>',
u'</div>'
]
return ''.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'''
<div class="portlet" id="p-search">
<h5><label for="searchInput">%(search_label)s</label></h5>
<div class="pBody">
<form id="searchform" method="get" action="">
<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">
<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>
</div>
</div>
''' % d
return html
def shouldShowEditbar(self, page):
""" Override to include the editbar on edit/preview pages.
(at the risk that the user may accidentally cancel an edit)
"""
if (page.exists(includeDeleted=1) and
self.request.user.may.read(page.page_name)):
return True
return False
def navibar(self, d):
""" Alterations from the base class to include access keys and
descriptions for FrontPage/RecentChanges
"""
request = self.request
found = {} # pages we found. prevent duplicates
links = [] # navibar items
current = d['page_name']
# Process config navi_bar
if request.cfg.navi_bar:
for text in request.cfg.navi_bar:
pagename, link = self.splitNavilink(text)
if pagename == d['page_front_page']:
attrs = self.extendedAttrs('Visit the main page', 'z')
elif pagename == 'RecentChanges':
attrs = self.extendedAttrs('List of recent changes in this wiki', 'r')
else:
attrs = ''
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
# Add user links to wiki links, eliminating duplicates.
userlinks = request.user.getQuickLinks()
for text in userlinks:
# Split text without localization, user know what she wants
pagename, link = self.splitNavilink(text, localize=0)
if not pagename in found:
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
html = [
u'<div class="portlet" id="p-nav">',
u'<div class="pBody">',
u'<ul id="navibar">',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
return ''.join(html)
def pageinfo(self, page):
""" Simple override from base class.
Remove <p> so footer isn't too big
"""
_ = self.request.getText
if self.shouldShowPageinfo(page):
info = page.lastEditInfo()
if info:
if info['editor']:
info = _("last edited %(time)s by %(editor)s") % info
else:
info = _("last modified %(time)s") % info
return info
return ''
def rtl_stylesheet(self, d):
""" monobook uses a separate css page for rtl alterations.
Add the rtl stylesheet if the user needs it
"""
link = ('<link rel="stylesheet" type="text/css" charset="%s"'
' media="%s" href="%s">')
html = []
if i18n.getDirection(self.request.lang) == 'rtl':
prefix = self.cfg.url_prefix
href = '%s/%s/css/%s.css' % (prefix, self.name, 'rtl')
html.append(link % (self.stylesheetsCharset, 'all', href))
return '\n'.join(html)
def html_head(self, d):
""" Tweak the sending of the head, to include right-to-left
alterations if necessary
"""
html = [
u'<title>%(title)s - %(sitename)s</title>' % d,
self.headscript(d), # Should move to separate .js file
self.html_stylesheets(d),
self.rtl_stylesheet(d),
self.rsslink(),
]
return '\n'.join(html)
def execute(request):
"""
Generate and return a theme object
@param request: the request object
@rtype: MoinTheme
@return: Theme object
"""
return Theme(request)

496
wiki/theme/crans-test.py Normal file
View file

@ -0,0 +1,496 @@
# -*- 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.
"""
from MoinMoin.theme import ThemeBase
from MoinMoin import wikiutil, i18n
from MoinMoin.Page import Page
class ThemeCrans(ThemeBase):
name = "crans"
# fake _ function to get gettext recognize those texts:
_ = lambda x: x
icons = {
# key alt icon filename w h
# ------------------------------------------------------------------
# navibar
'help': ("%(page_help_contents)s", "moin-help.png", 12, 11),
'find': ("%(page_find_page)s", "moin-search.png", 12, 12),
'diff': (_("Diffs"), "moin-diff.png", 22, 22),
'info': (_("Info"), "moin-info.png", 22, 22),
'edit': (_("Edit"), "moin-edit.png", 22, 22),
'unsubscribe':(_("Unsubscribe"), "moin-unsubscribe.png", 22, 22),
'subscribe': (_("Subscribe"), "moin-subscribe.png",22, 22),
'raw': (_("Raw"), "moin-raw.png", 12, 13),
'xml': (_("XML"), "moin-xml.png", 20, 13),
'print': (_("Print"), "moin-print.png", 16, 14),
'view': (_("View"), "moin-show.png", 22, 22),
'home': (_("Home"), "moin-home.png", 13, 12),
'up': (_("Up"), "moin-parent.png", 15, 13),
# FileAttach
'attach': ("%(attach_count)s", "moin-attach.png", 7, 15),
# RecentChanges
'rss': (_("[RSS]"), "moin-rss.png", 36, 14),
'deleted': (_("[DELETED]"), "moin-deleted.png",60, 12),
'updated': (_("[UPDATED]"), "moin-updated.png",60, 12),
'new': (_("[NEW]"), "moin-new.png", 31, 12),
'diffrc': (_("[DIFF]"), "moin-diff.png", 22, 22),
# General
'bottom': (_("[BOTTOM]"), "moin-bottom.png", 14, 10),
'top': (_("[TOP]"), "moin-top.png", 14, 10),
'www': ("[WWW]", "moin-www.png", 11, 11),
'mailto': ("[MAILTO]", "moin-email.png", 14, 10),
'news': ("[NEWS]", "moin-news.png", 10, 11),
'telnet': ("[TELNET]", "moin-telnet.png", 10, 11),
'ftp': ("[FTP]", "moin-ftp.png", 11, 11),
'file': ("[FILE]", "moin-ftp.png", 11, 11),
# search forms
'searchbutton': ("[?]", "moin-search.png", 12, 12),
'interwiki': ("[%(wikitag)s]", "moin-inter.png", 16, 16),
}
del _
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'crans'),
('print', 'print'),
('projection', 'projection'),
)
# Public functions #####################################################
def header(self, d, **kw):
""" Assemble wiki header
Here we don't add any menu bars, search bars, etc - instead wait
until the footer. This keeps the HTML cleaner and more accessible,
making sure the main content arrives first.
"""
html = [
u'<div id="globalWrapper">',
u'<div id="column-content">',
self.startPage(),
self.msg(d),
self.title(d),
]
return u'\n'.join(html)
def footer(self, d, **keywords):
""" Assemble wiki footer
"""
html = [
# End of page
u'<div class="visualClear"></div>',
self.endPage(),
u'</div>',
self.columnone(d),
u'</div>'
]
return u'\n'.join(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 = [('view', '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', ['view'])[0]
for action, title, description, accesskey in tabs:
if action == current:
cls = 'selected'
else:
cls = 'none'
if action == "subscribe":
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(
["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d)))
else:
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(action, d)))
html = [
u'<div id="p-cactions" class="portlet">',
u'<ul class="editbar">',
''.join(items),
u'</ul>',
u'</div>'
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def actionmenu(self, d):
""" different implementation of the actionmenu (aka toolbox)
"""
page = d['page']
# Use cached actionmenu if possible.
cacheKey = 'actionmenu'
cached = self._cache.get(cacheKey)
if cached:
return cached
request = self.request
_ = request.getText
quotedname = wikiutil.quoteWikinameURL(page.page_name)
menu = [
'raw',
'print',
'refresh',
'AttachFile',
'SpellCheck',
'LikePages',
'LocalSiteMap',
'RenamePage',
'DeletePage',
]
titles = {
'raw': _('Show Raw Text', formatted=False),
'print': _('Show Print View', formatted=False),
'refresh': _('Delete Cache', formatted=False),
'AttachFile': _('Attach File', formatted=False),
'SpellCheck': _('Check Spelling', formatted=False), # rename action!
'RenamePage': _('Rename Page', formatted=False),
'DeletePage': _('Delete Page', formatted=False),
'LikePages': _('Show Like Pages', formatted=False),
'LocalSiteMap': _('Show Local Site Map', formatted=False),
}
links = []
# Format standard actions
available = request.getAvailableActions(page)
for action in menu:
# Enable delete cache only if page can use caching
if action == 'refresh':
if not page.canUseCache():
break
# Actions which are not available for this wiki, user or page
if action[0].isupper() and not action in available:
break;
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, titles[action])
links.append(link)
# Add custom actions not in the standard menu
more = [item for item in available if not item in titles]
more.sort()
if more:
# Add more actions (all enabled)
for action in more:
data = {'action': action, 'disabled': ''}
title = Page(request, action).split_title(request, force=1)
# Use translated version if available
title = _(title, formatted=False)
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, title)
links.append(link)
html = [
u'<div class="portlet" id="p-tb">',
u'<h5>Toolbox</h5>',
u'<div class="pBody">',
u'<ul>',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def username(self, d):
""" Assemble the username / userprefs link
Copied from the base class, modified to include hotkeys and link titles
"""
from MoinMoin.Page import Page
request = self.request
_ = request.getText
userlinks = []
# Add username/homepage link for registered users. We don't care
# if it exists, the user can create it.
if request.user.valid:
homepage = Page(request, request.user.name)
title = homepage.split_title(request)
attrs = self.extendedAttrs(_('User Page'), '.')
homelink = homepage.link_to(request, text=title, attrs=attrs)
userlinks.append(homelink)
# Set pref page to localized Preferences page
attrs = self.extendedAttrs(_('My Preferences'), 'u')
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
title = prefpage.split_title(request)
userlinks.append(prefpage.link_to(request, text=title, attrs=attrs))
# Add a logout link (not sure this is really necessary
attrs = self.extendedAttrs(_('log out'), 'o')
page = d['page']
url = wikiutil.quoteWikinameURL(page.page_name) + \
'?action=userform&logout=1'
link = wikiutil.link_tag(self.request, url, 'log out', attrs=attrs)
userlinks.append(link)
else:
# Add prefpage links with title: Login
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
attrs = self.extendedAttrs('Logging in is not required, but brings benefits', 'o')
userlinks.append(prefpage.link_to(request, text=_("Login"), attrs=attrs))
html = [
u'<div class="portlet" id="p-personal">',
u'<ul id="username">',
u'<li class="pt-userpage">%s</li></ul>' % '</li>\n<li>'.join(userlinks),
u'</ul>',
u'</div>'
]
return ''.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'''
<div class="portlet" id="p-search">
<h5><label for="searchInput">%(search_label)s</label></h5>
<div class="pBody">
<form id="searchform" method="get" action="">
<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">
<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>
</div>
</div>
''' % d
return html
def shouldShowEditbar(self, page):
""" Override to include the editbar on edit/preview pages.
(at the risk that the user may accidentally cancel an edit)
"""
if (page.exists(includeDeleted=1) and
self.request.user.may.read(page.page_name)):
return True
return False
def navibar(self, d):
""" Alterations from the base class to include access keys and
descriptions for FrontPage/RecentChanges
"""
request = self.request
found = {} # pages we found. prevent duplicates
links = [] # navibar items
current = d['page_name']
# Process config navi_bar
if request.cfg.navi_bar:
for text in request.cfg.navi_bar:
pagename, link = self.splitNavilink(text)
if pagename == d['page_front_page']:
attrs = self.extendedAttrs('Visit the main page', 'z')
elif pagename == 'RecentChanges':
attrs = self.extendedAttrs('List of recent changes in this wiki', 'r')
else:
attrs = ''
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
# Add user links to wiki links, eliminating duplicates.
userlinks = request.user.getQuickLinks()
for text in userlinks:
# Split text without localization, user know what she wants
pagename, link = self.splitNavilink(text, localize=0)
if not pagename in found:
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
html = [
u'<div class="portlet" id="p-nav">',
u'<div class="pBody">',
u'<ul id="navibar">',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
return ''.join(html)
def pageinfo(self, page):
""" Simple override from base class.
Remove <p> so footer isn't too big
"""
_ = self.request.getText
if self.shouldShowPageinfo(page):
info = page.lastEditInfo()
if info:
if info['editor']:
info = _("last edited %(time)s by %(editor)s") % info
else:
info = _("last modified %(time)s") % info
return info
return ''
def rtl_stylesheet(self, d):
""" monobook uses a separate css page for rtl alterations.
Add the rtl stylesheet if the user needs it
"""
link = ('<link rel="stylesheet" type="text/css" charset="%s"'
' media="%s" href="%s">')
html = []
if i18n.getDirection(self.request.lang) == 'rtl':
prefix = self.cfg.url_prefix
href = '%s/%s/css/%s.css' % (prefix, self.name, 'rtl')
html.append(link % (self.stylesheetsCharset, 'all', href))
return '\n'.join(html)
def html_head(self, d):
""" Tweak the sending of the head, to include right-to-left
alterations if necessary
"""
html = [
u'<title>%(title)s - %(sitename)s</title>' % d,
self.headscript(d), # Should move to separate .js file
self.html_stylesheets(d),
self.rtl_stylesheet(d),
self.rsslink(),
]
return u'\n'.join(html)
def html_stylesheets(self, d):
"""
On fixe le chemin d'acces vers les feuilles de style
"""
html = []
for media, nom in self.stylesheets:
html.append(u'<link rel="stylesheet" type="text/css" media="%s" href="/wiki/crans/css/%s.css" />' % (media, nom))
class Theme(ThemeCrans):
name = "crans"
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('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)

502
wiki/theme/crans.py Normal file
View file

@ -0,0 +1,502 @@
# -*- 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.
"""
from MoinMoin.theme import ThemeBase
from MoinMoin import wikiutil, i18n
from MoinMoin.Page import Page
class ThemeCrans(ThemeBase):
name = "crans"
# fake _ function to get gettext recognize those texts:
_ = lambda x: x
icons = {
# key alt icon filename w h
# ------------------------------------------------------------------
# navibar
'help': ("%(page_help_contents)s", "moin-help.png", 12, 11),
'find': ("%(page_find_page)s", "moin-search.png", 12, 12),
'diff': (_("Diffs"), "moin-diff.png", 22, 22),
'info': (_("Info"), "moin-info.png", 22, 22),
'edit': (_("Edit"), "moin-edit.png", 22, 22),
'unsubscribe':(_("Unsubscribe"), "moin-unsubscribe.png", 22, 22),
'subscribe': (_("Subscribe"), "moin-subscribe.png",22, 22),
'raw': (_("Raw"), "moin-raw.png", 12, 13),
'xml': (_("XML"), "moin-xml.png", 20, 13),
'print': (_("Print"), "moin-print.png", 16, 14),
'view': (_("View"), "moin-show.png", 22, 22),
'home': (_("Home"), "moin-home.png", 13, 12),
'up': (_("Up"), "moin-parent.png", 15, 13),
# format
'format': (_("[TEX]"), "moin-tex.png", 20, 22),
# FileAttach
'attach': ("%(attach_count)s", "moin-attach.png", 7, 15),
# RecentChanges
'rss': (_("[RSS]"), "moin-rss.png", 36, 14),
'deleted': (_("[DELETED]"), "moin-deleted.png",60, 12),
'updated': (_("[UPDATED]"), "moin-updated.png",60, 12),
'new': (_("[NEW]"), "moin-new.png", 31, 12),
'diffrc': (_("[DIFF]"), "moin-diff.png", 22, 22),
# General
'bottom': (_("[BOTTOM]"), "moin-bottom.png", 14, 10),
'top': (_("[TOP]"), "moin-top.png", 14, 10),
'www': ("[WWW]", "moin-www.png", 11, 11),
'mailto': ("[MAILTO]", "moin-email.png", 14, 10),
'news': ("[NEWS]", "moin-news.png", 10, 11),
'telnet': ("[TELNET]", "moin-telnet.png", 10, 11),
'ftp': ("[FTP]", "moin-ftp.png", 11, 11),
'file': ("[FILE]", "moin-ftp.png", 11, 11),
# search forms
'searchbutton': ("[?]", "moin-search.png", 12, 12),
'interwiki': ("[%(wikitag)s]", "moin-inter.png", 16, 16),
}
del _
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'crans'),
('print', 'print'),
('projection', 'projection'),
)
# Public functions #####################################################
def header(self, d, **kw):
""" Assemble wiki header
Here we don't add any menu bars, search bars, etc - instead wait
until the footer. This keeps the HTML cleaner and more accessible,
making sure the main content arrives first.
"""
html = [
u'<div id="globalWrapper">',
u'<div id="column-content">',
self.startPage(),
self.msg(d),
self.title(d),
]
return u'\n'.join(html)
def footer(self, d, **keywords):
""" Assemble wiki footer
"""
html = [
# End of page
u'<div class="visualClear"></div>',
self.endPage(),
u'<div class="visualclear"></div>',
u'</div>',
self.columnone(d),
u'</div>'
]
return u'\n'.join(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 = [('view', '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'),
#('format', 'Latex', 'Source Latex', 'l'),
('subscribe', 'Subscribe', 'Subscribe to updates to this page', 'w')]
items = []
current = self.request.form.get('action', ['view'])[0]
for action, title, description, accesskey in tabs:
if action == current:
cls = 'selected'
else:
cls = 'none'
if action == "subscribe":
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(
["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d)))
else:
items.append(u'<li class="%s" id="edit-%s">%s</li>\n' % (cls, action, self.make_iconlink(action, d)))
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',
u'format&mimetype=text/latex',
'refresh',
'AttachFile',
'SpellCheck',
'LikePages',
'LocalSiteMap',
'RenamePage',
'DeletePage',
]
titles = {
'raw': _('Show Raw Text', formatted=False),
'print': _('Show Print View', formatted=False),
u'format&mimetype=text/latex': _('Obtenir le code latex', formatted=False),
'refresh': _('Delete Cache', formatted=False),
'AttachFile': _('Attach File', formatted=False),
'SpellCheck': _('Check Spelling', formatted=False), # rename action!
'RenamePage': _('Rename Page', formatted=False),
'DeletePage': _('Delete Page', formatted=False),
'LikePages': _('Show Like Pages', formatted=False),
'LocalSiteMap': _('Show Local Site Map', formatted=False),
}
links = []
# Format standard actions
available = request.getAvailableActions(page)
for action in menu:
# Enable delete cache only if page can use caching
if action == 'refresh':
if not page.canUseCache():
break
# Actions which are not available for this wiki, user or page
if action[0].isupper() and not action in available:
break;
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, titles[action])
links.append(link)
# Add custom actions not in the standard menu
more = [item for item in available if not item in titles]
more.sort()
if more:
# Add more actions (all enabled)
for action in more:
data = {'action': action, 'disabled': ''}
title = Page(request, action).split_title(request, force=1)
# Use translated version if available
title = _(title, formatted=False)
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, title)
links.append(link)
html = [
u'<div class="portlet" id="p-tb">',
u'<h5>Toolbox</h5>',
u'<div class="pBody">',
u'<ul>',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def username(self, d):
""" Assemble the username / userprefs link
Copied from the base class, modified to include hotkeys and link titles
"""
from MoinMoin.Page import Page
request = self.request
_ = request.getText
userlinks = []
# Add username/homepage link for registered users. We don't care
# if it exists, the user can create it.
if request.user.valid:
homepage = Page(request, request.user.name)
title = homepage.split_title(request)
attrs = self.extendedAttrs(_('User Page'), '.')
homelink = homepage.link_to(request, text=title, attrs=attrs)
userlinks.append(homelink)
# Set pref page to localized Preferences page
attrs = self.extendedAttrs(_('My Preferences'), 'u')
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
title = prefpage.split_title(request)
userlinks.append(prefpage.link_to(request, text=title, attrs=attrs))
# Add a logout link (not sure this is really necessary
attrs = self.extendedAttrs(_('log out'), 'o')
page = d['page']
url = wikiutil.quoteWikinameURL(page.page_name) + \
'?action=userform&logout=1'
link = wikiutil.link_tag(self.request, url, 'log out', attrs=attrs)
userlinks.append(link)
else:
# Add prefpage links with title: Login
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
attrs = self.extendedAttrs('Logging in is not required, but brings benefits', 'o')
userlinks.append(prefpage.link_to(request, text=_("Login"), attrs=attrs))
html = [
u'<div class="portlet" id="p-personal">',
u'<ul id="username">',
u'<li class="pt-userpage">%s</li></ul>' % '</li>\n<li>'.join(userlinks),
u'</ul>',
u'</div>'
]
return ''.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'''
<div class="portlet" id="p-search">
<h5><label for="searchInput">%(search_label)s</label></h5>
<div class="pBody">
<form id="searchform" method="get" action="">
<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">
<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>
</div>
</div>
''' % d
return html
def shouldShowEditbar(self, page):
""" Override to include the editbar on edit/preview pages.
(at the risk that the user may accidentally cancel an edit)
"""
if (page.exists(includeDeleted=1) and
self.request.user.may.read(page.page_name)):
return True
return False
def navibar(self, d):
""" Alterations from the base class to include access keys and
descriptions for FrontPage/RecentChanges
"""
request = self.request
found = {} # pages we found. prevent duplicates
links = [] # navibar items
current = d['page_name']
# Process config navi_bar
if request.cfg.navi_bar:
for text in request.cfg.navi_bar:
pagename, link = self.splitNavilink(text)
if pagename == d['page_front_page']:
attrs = self.extendedAttrs('Visit the main page', 'z')
elif pagename == 'RecentChanges':
attrs = self.extendedAttrs('List of recent changes in this wiki', 'r')
else:
attrs = ''
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
# Add user links to wiki links, eliminating duplicates.
userlinks = request.user.getQuickLinks()
for text in userlinks:
# Split text without localization, user know what she wants
pagename, link = self.splitNavilink(text, localize=0)
if not pagename in found:
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
html = [
u'<div class="portlet" id="p-nav">',
u'<div class="pBody">',
u'<ul id="navibar">',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
return ''.join(html)
def pageinfo(self, page):
""" Simple override from base class.
Remove <p> so footer isn't too big
"""
_ = self.request.getText
if self.shouldShowPageinfo(page):
info = page.lastEditInfo()
if info:
if info['editor']:
info = _("last edited %(time)s by %(editor)s") % info
else:
info = _("last modified %(time)s") % info
return info
return ''
def rtl_stylesheet(self, d):
""" monobook uses a separate css page for rtl alterations.
Add the rtl stylesheet if the user needs it
"""
link = ('<link rel="stylesheet" type="text/css" charset="%s"'
' media="%s" href="%s">')
html = []
if i18n.getDirection(self.request.lang) == 'rtl':
prefix = self.cfg.url_prefix
href = '%s/%s/css/%s.css' % (prefix, self.name, 'rtl')
html.append(link % (self.stylesheetsCharset, 'all', href))
return '\n'.join(html)
def html_head(self, d):
""" Tweak the sending of the head, to include right-to-left
alterations if necessary
"""
html = [
u'<title>%(title)s - %(sitename)s</title>' % d,
self.headscript(d), # Should move to separate .js file
self.html_stylesheets(d),
self.rtl_stylesheet(d),
self.rsslink(),
]
return u' \n'.join(html)
def html_stylesheets(self, d):
"""
On fixe le chemin d'acces vers les feuilles de style
"""
html = []
for media, nom in self.stylesheets:
html.append(u'<link rel="stylesheet" type="text/css" media="%s" href="/wiki/crans/css/%s.css" />' % (media, nom))
return u'\n'.join(html)
class Theme(ThemeCrans):
name = "crans"
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('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)

24
wiki/theme/ensanime.py Normal file
View file

@ -0,0 +1,24 @@
from crans import ThemeCrans
class Theme(ThemeCrans):
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('all', 'common-reverse'),
('screen', 'crans'),
('screen', 'ensanime'),
('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)

25
wiki/theme/matrix.py Normal file
View file

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
"""
MoinMoin technical theme
@copyright: (c) 2003-2004 by Nir Soffer
@license: GNU GPL, see COPYING for details.
"""
from MoinMoin.theme import modern
class Theme(modern.Theme):
name = "matrix"
def execute(request):
""" Generate and return a theme object
@param request: the request object
@rtype: Theme instance
@return: Theme object
"""
return Theme(request)

195
wiki/theme/mentalhealth.py Normal file
View file

@ -0,0 +1,195 @@
# -*- coding: iso-8859-1 -*-
"""
Top Matter:
MentalHealth is a MoinMoin theme
by robin.escalation@ACM.org
dated this 20th of April 2005
let's call it version 0.9
and by golly this is GPLed
Description:
It may look something like the standard "rightsidebar" theme.
But in reality it is so much better. ;-)
For example:
* smaller type so more fits
* very nice colours to soothe the soul
* but main page still white background so no clashes
* nice alignment, sizes etc.
* search form integrated with right panel look
* got rid of damn ugly action pulldown menu
* no loss of functionality
Seems to look good but if you have an issue on a browser then
let me know.
Accompanying files:
No files changed in folder "img".
Only file changed in folder "css" is "screen.css".
(Though see next.)
Skinning the theme:
This theme uses four compatible colours, as mentioned in the
header "screen.css". If you like you can search'n'replace for
those more to your liking. I have a couple of alternate versions
of the stylesheet, named screen01.css, screen02.css, etc., just
to show how this works. Rename each in tun to screen.css and
check it out.
Installation:
* move mentalhealth.py to $python/Lib/site-packages/MoinMoin/theme/
* move the mentalhealth folder under $python/share/moin/htdocs/
And Finally:
"Oh we're in love with beauty,
We're in love with wealth,
We're in love with mental health."
-- Julian Cope
"""
from MoinMoin.theme import ThemeBase
from MoinMoin.wikiutil import link_tag as link
from MoinMoin.wikiutil import quoteWikinameURL as quoteURL
class Theme(ThemeBase):
name = "mentalhealth"
def editbar(self, d):
"""
Assemble the page edit bar.
This is rewritten here to get rid of fugly drop-down menu.
(Obviating the need for the actionsMenu() method).
Also I tried to reduce the number of aliases 'cause I find
that hard to follow.
@param d: parameter dictionary
@rtype: unicode
@return: iconbar html
"""
# short circuit
if not self.shouldShowEditbar(d['page']):
return ''
# initialisations & optimisation
_ = self.request.getText
page = d['page']
cacheKey = 'editbar'
quotedname = quoteURL(page.page_name)
# use cached copy if possible
cached = self._cache.get(cacheKey)
if cached:
return cached
# each action in this list is a line on the editbar panel
links = []
# parent page
parent = page.getParentPage()
if parent:
links += [parent.link_to(self.request, _("Show Parent", formatted=False))]
# the rest we will do cleverly :-)
# these are the possible actions and their text labels
choices = [ ['edit', 'edit'],
['diff', 'show changes'],
['info', 'get info'],
['raw', 'show raw text'],
['print', 'show print view'],
['refresh', 'delete cache'],
['AttachFile', 'attach file'],
['SpellCheck', 'check spelling'],
['LikePages', 'show like pages'],
['LocalSiteMap', 'show local site map'],
['RenamePage', 'rename page'],
['DeletePage', 'delete page']
]
# determine which actions we can use
available = self.request.getAvailableActions(page)
for action, label in choices:
if action == 'refresh' and not page.canUseCache():
continue
if action == 'edit' and not (page.isWritable() and self.request.user.may.write(page.page_name)):
continue
if action[0].isupper() and not action in available:
continue
links += [link(self.request, '%s?action=%s' % (quotedname, action),
_(label, formatted=False))]
# we will still delegate this next so I can stop rewriting code
links += [self.subscribeLink(page)]
# wrap it all up nicely
html = u'<ul class="editbar">\n%s\n</ul>\n' %\
'\n'.join(['<li>%s</li>' % item for item in links if item != ''])
# cache for next call
self._cache[cacheKey] = html
return html
def header(self, d, **kw):
"""
Assemble page header, which is to say our right-hand panel.
@param d: parameter dictionary
@rtype: string
@return: page header html
"""
_ = self.request.getText
# there are 5 main panels: each one follows this markup
html = u'<div class="sidepanel"><h1>%s</h1>%s</div>'
# "search" panel hack so I don't have to rewrite searchform()
searchpanel = self.searchform(d).replace('<input id="titlesearch"',
'<br><input id="titlesearch"')
# bundle up all our parts
parts = [ self.emit_custom_html(self.cfg.page_header1),
'<div id="header"></div>',
self.emit_custom_html(self.cfg.page_header2),
u'<div id="sidebar">',
html % (_('Search'), searchpanel),
html % (_('Navigation'), self.navibar(d)),
html % (_('Recent'), self.trail(d)),
html % (_('This Page'), self.editbar(d)),
html % (_('User'), self.username(d)),
self.credits(d),
u'</div>',
self.msg(d),
self.startPage(),
self.title(d)
]
return u'\n'.join(parts)
def footer(self, d, **kw):
"""
Assemble page footer
@param d: parameter dictionary
@keyword ...:...
@rtype: string
@return: page footer html
"""
parts = [ u'<div id="pagebottom"></div>',
self.pageinfo(d['page']),
self.endPage(),
self.emit_custom_html(self.cfg.page_footer1),
self.emit_custom_html(self.cfg.page_footer2),
]
return u'\n'.join(parts)
def execute(request):
"""
Generate and return a theme object.
"""
return Theme(request)

444
wiki/theme/monobook.py Normal file
View file

@ -0,0 +1,444 @@
# -*- 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
class Theme(ThemeBase):
name = "monobook"
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('screen', 'monobook'),
('screen', 'screen'),
('print', 'print'),
('projection', 'projection'),
)
# Public functions #####################################################
def header(self, d, **kw):
""" Assemble wiki header
Here we don't add any menu bars, search bars, etc - instead wait
until the footer. This keeps the HTML cleaner and more accessible,
making sure the main content arrives first.
"""
html = [
u'<div id="globalWrapper">',
u'<div id="column-content">',
self.startPage(),
self.msg(d),
self.title(d),
]
return u'\n'.join(html)
def footer(self, d, **keywords):
""" Assemble wiki footer
"""
html = [
# End of page
u'<div class="visualClear"></div>',
self.endPage(),
u'</div>',
self.columnone(d),
u'</div>'
]
return u'\n'.join(html)
def columnone(self, d):
""" assemble all the navigation aids for the page
"""
page = d['page']
html = [
u'<div id="column-one">',
self.editbar(d),
self.username(d),
u'<div class="portlet" id="p-logo">',
self.logo(),
u'</div>',
self.navibar(d),
self.searchform(d),
self.actionmenu(d),
u'<div class="visualClear"></div>',
u'<div id="footer">',
self.pageinfo(page),
self.credits(d),
u'</div>',
u'</div>'
]
return u'\n'.join(html)
def headscript(self, d):
""" Override to not output search/action menu javascript.
(perhaps not a good idea)
"""
return ''
def extendedAttrs(self, title, accesskey):
""" Helper function for assembling titled access key links
"""
return 'title="%(title)s [alt-%(accesskey)s]" accesskey=%(accesskey)s' % \
{'accesskey' : accesskey,
'title' : title}
def editbar(self, d):
""" Display a list of actions for the page. This list will be turned
into a set of tabbed views on the page by the css.
"""
page = d['page']
if not self.shouldShowEditbar(page):
return ''
# Use cached editbar if possible.
cacheKey = 'editbar'
cached = self._cache.get(cacheKey)
if cached:
return cached
request = self.request
_ = self.request.getText
link = wikiutil.link_tag
quotedname = wikiutil.quoteWikinameURL(page.page_name)
# action, title, description, accesskey
tabs = [('show', 'Article', 'View the page content', 'c'),
('edit', 'Edit', 'Edit this page', 'e'),
('diff', 'Show Changes', 'Last page modification', 'd'),
('info', 'Get Info', 'Page history and information', 'h'),
('subscribe', 'Subscribe', 'Subscribe to updates to this page', 'w')]
items = []
current = self.request.form.get('action', ['show'])[0]
for action, title, description, accesskey in tabs:
if action == current:
cls = 'selected'
else:
cls = 'none'
if action == 'edit':
if page.isWritable() and request.user.may.write(page.page_name):
pass
else:
action = 'raw'
title = 'View Source'
description = 'This page is protected. You can view its source'
if action == 'subscribe':
user = self.request.user
if not self.cfg.mail_smarthost or not user.valid:
break
# Email enabled and user valid, get current page status
if user.isSubscribedTo([page.page_name]):
title = 'Unsubscribe'
description = 'Unsubscribe from updates to this page'
if action == 'show':
url = quotedname
else:
url = quotedname + '?action=' + action
attrs = self.extendedAttrs(_(description), accesskey)
link = wikiutil.link_tag(self.request, url, _(title), attrs=attrs)
items.append(u'<li class="%s">%s</li>' % (cls, link))
html = [
u'<div id="p-cactions" class="portlet">',
u'<ul class="editbar">',
''.join(items),
u'</ul>',
u'</div>'
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def actionmenu(self, d):
""" different implementation of the actionmenu (aka toolbox)
"""
page = d['page']
# Use cached actionmenu if possible.
cacheKey = 'actionmenu'
cached = self._cache.get(cacheKey)
if cached:
return cached
request = self.request
_ = request.getText
quotedname = wikiutil.quoteWikinameURL(page.page_name)
menu = [
'raw',
'print',
'refresh',
'AttachFile',
'SpellCheck',
'LikePages',
'LocalSiteMap',
'RenamePage',
'DeletePage',
]
titles = {
'raw': _('Show Raw Text', formatted=False),
'print': _('Show Print View', formatted=False),
'refresh': _('Delete Cache', formatted=False),
'AttachFile': _('Attach File', formatted=False),
'SpellCheck': _('Check Spelling', formatted=False), # rename action!
'RenamePage': _('Rename Page', formatted=False),
'DeletePage': _('Delete Page', formatted=False),
'LikePages': _('Show Like Pages', formatted=False),
'LocalSiteMap': _('Show Local Site Map', formatted=False),
}
links = []
# Format standard actions
available = request.getAvailableActions(page)
for action in menu:
# Enable delete cache only if page can use caching
if action == 'refresh':
if not page.canUseCache():
break
# Actions which are not available for this wiki, user or page
if action[0].isupper() and not action in available:
break;
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, titles[action])
links.append(link)
# Add custom actions not in the standard menu
more = [item for item in available if not item in titles]
more.sort()
if more:
# Add more actions (all enabled)
for action in more:
data = {'action': action, 'disabled': ''}
title = Page(request, action).split_title(request, force=1)
# Use translated version if available
title = _(title, formatted=False)
link = wikiutil.link_tag(self.request, \
quotedname + '?action=' + action, title)
links.append(link)
html = [
u'<div class="portlet" id="p-tb">',
u'<h5>Toolbox</h5>',
u'<div class="pBody">',
u'<ul>',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
html = ''.join(html)
# cache for next call
self._cache[cacheKey] = html
return html
def username(self, d):
""" Assemble the username / userprefs link
Copied from the base class, modified to include hotkeys and link titles
"""
from MoinMoin.Page import Page
request = self.request
_ = request.getText
userlinks = []
# Add username/homepage link for registered users. We don't care
# if it exists, the user can create it.
if request.user.valid:
homepage = Page(request, request.user.name)
title = homepage.split_title(request)
attrs = self.extendedAttrs(_('User Page'), '.')
homelink = homepage.link_to(request, text=title, attrs=attrs)
userlinks.append(homelink)
# Set pref page to localized Preferences page
attrs = self.extendedAttrs(_('My Preferences'), 'u')
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
title = prefpage.split_title(request)
userlinks.append(prefpage.link_to(request, text=title, attrs=attrs))
# Add a logout link (not sure this is really necessary
attrs = self.extendedAttrs(_('log out'), 'o')
page = d['page']
url = wikiutil.quoteWikinameURL(page.page_name) + \
'?action=userform&logout=1'
link = wikiutil.link_tag(self.request, url, 'log out', attrs=attrs)
userlinks.append(link)
else:
# Add prefpage links with title: Login
prefpage = wikiutil.getSysPage(request, 'UserPreferences')
attrs = self.extendedAttrs('Logging in is not required, but brings benefits', 'o')
userlinks.append(prefpage.link_to(request, text=_("Login"), attrs=attrs))
html = [
u'<div class="portlet" id="p-personal">',
u'<ul id="username">',
u'<li class="pt-userpage">%s</li></ul>' % '</li>\n<li>'.join(userlinks),
u'</ul>',
u'</div>'
]
return ''.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'''
<div class="portlet" id="p-search">
<h5><label for="searchInput">%(search_label)s</label></h5>
<div class="pBody">
<form id="searchform" method="get" action="">
<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">
<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>
</div>
</div>
''' % d
return html
def shouldShowEditbar(self, page):
""" Override to include the editbar on edit/preview pages.
(at the risk that the user may accidentally cancel an edit)
"""
if (page.exists(includeDeleted=1) and
self.request.user.may.read(page.page_name)):
return True
return False
def navibar(self, d):
""" Alterations from the base class to include access keys and
descriptions for FrontPage/RecentChanges
"""
request = self.request
found = {} # pages we found. prevent duplicates
links = [] # navibar items
current = d['page_name']
# Process config navi_bar
if request.cfg.navi_bar:
for text in request.cfg.navi_bar:
pagename, link = self.splitNavilink(text)
if pagename == d['page_front_page']:
attrs = self.extendedAttrs('Visit the main page', 'z')
elif pagename == 'RecentChanges':
attrs = self.extendedAttrs('List of recent changes in this wiki', 'r')
else:
attrs = ''
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
# Add user links to wiki links, eliminating duplicates.
userlinks = request.user.getQuickLinks()
for text in userlinks:
# Split text without localization, user know what she wants
pagename, link = self.splitNavilink(text, localize=0)
if not pagename in found:
a = wikiutil.link_tag(request, pagename, attrs=attrs)
links.append(a)
found[pagename] = 1
html = [
u'<div class="portlet" id="p-nav">',
u'<div class="pBody">',
u'<ul id="navibar">',
u'<li>%s</li></ul>' % '</li>\n<li>'.join(links),
u'</ul>',
u'</div>',
u'</div>',
]
return ''.join(html)
def pageinfo(self, page):
""" Simple override from base class.
Remove <p> so footer isn't too big
"""
_ = self.request.getText
if self.shouldShowPageinfo(page):
info = page.lastEditInfo()
if info:
if info['editor']:
info = _("last edited %(time)s by %(editor)s") % info
else:
info = _("last modified %(time)s") % info
return info
return ''
def rtl_stylesheet(self, d):
""" monobook uses a separate css page for rtl alterations.
Add the rtl stylesheet if the user needs it
"""
link = ('<link rel="stylesheet" type="text/css" charset="%s"'
' media="%s" href="%s">')
html = []
if i18n.getDirection(self.request.lang) == 'rtl':
prefix = self.cfg.url_prefix
href = '%s/%s/css/%s.css' % (prefix, self.name, 'rtl')
html.append(link % (self.stylesheetsCharset, 'all', href))
return '\n'.join(html)
def html_head(self, d):
""" Tweak the sending of the head, to include right-to-left
alterations if necessary
"""
html = [
u'<title>%(title)s - %(sitename)s</title>' % d,
self.headscript(d), # Should move to separate .js file
self.html_stylesheets(d),
self.rtl_stylesheet(d),
self.rsslink(),
]
return '\n'.join(html)
def execute(request):
"""
Generate and return a theme object
@param request: the request object
@rtype: MoinTheme
@return: Theme object
"""
return Theme(request)

33
wiki/theme/movieclub.py Normal file
View file

@ -0,0 +1,33 @@
# -*- coding: iso-8859-1 -*-
"""
Theme Movieclub, sous classe de Crans.
"""
from crans import ThemeCrans
class Theme(ThemeCrans):
# Standard set of style sheets
stylesheets = (
# media basename
('all', 'common'),
('all', 'common-reverse'),
('all', 'common-movieclub'),
('screen', 'crans'),
('screen', 'movieclub'),
('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,131 @@
# -*- coding: iso-8859-1 -*-
"""
MoinMoin theme by and for crw.
"""
from MoinMoin import wikiutil
from MoinMoin.Page import Page
from MoinMoin.theme import ThemeBase
class Theme(ThemeBase):
""" here are the functions generating the html responsible for
the look and feel of your wiki site
"""
name = "rightsidebarsmaller"
def wikipanel(self, d):
""" Create wiki panel """
_ = self.request.getText
html = [
u'<div class="sidepanel">',
u'<h1>%s</h1>' % _("Navigation"),
self.navibar(d),
u'</div>',
]
return u'\n'.join(html)
def pagepanel(self, d):
""" Create page panel """
_ = self.request.getText
if self.shouldShowEditbar(d['page']):
html = [
u'<div class="sidepanel">',
u'<h1>%s</h1>' % _("Page"),
self.editbar(d),
u'</div>',
]
return u'\n'.join(html)
return ''
def userpanel(self, d):
""" Create user panel """
_ = self.request.getText
trail = self.trail(d)
if trail:
trail = u'<h2>%s</h2>\n' % _("Recently viewed pages") + trail
html = [
u'<div class="sidepanel">',
u'<h1>%s</h1>' % _("User"),
self.username(d),
trail,
u'</div>'
]
return u'\n'.join(html)
def header(self, d):
"""
Assemble page header
@param d: parameter dictionary
@rtype: string
@return: page header html
"""
_ = self.request.getText
html = [
# Custom html above header
self.emit_custom_html(self.cfg.page_header1),
# Hedar
u'<div id="header">',
self.searchform(d),
self.logo(),
u'</div>',
# Custom html below header (not recomended!)
self.emit_custom_html(self.cfg.page_header2),
# Sidebar
u'<div id="sidebar">',
self.wikipanel(d),
self.pagepanel(d),
self.userpanel(d),
self.credits(d),
u'</div>',
self.msg(d),
# Page
self.startPage(),
self.title(d),
]
return u'\n'.join(html)
def footer(self, d, **keywords):
""" Assemble page footer
@param d: parameter dictionary
@keyword ...:...
@rtype: string
@return: page footer html
"""
page = d['page']
html = [
# Page end
# Used to extend the page to the bottom of the sidebar
u'<div id="pagebottom"></div>',
self.pageinfo(page),
self.endPage(),
# Custom html above footer
self.emit_custom_html(self.cfg.page_footer1),
# And bellow
self.emit_custom_html(self.cfg.page_footer2),
]
return u'\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)

230
wiki/theme/sinorca4moin.py Normal file
View file

@ -0,0 +1,230 @@
# -*- coding: iso-8859-1 -*-
"""MoinMoin theme "sinorca4moin" by David Linke.
Credits to "Haran" who published his sinorca-design at www.oswd.org
"""
from MoinMoin import wikiutil
from MoinMoin.Page import Page
from MoinMoin.theme import ThemeBase
class Theme(ThemeBase):
""" here are the functions generating the html responsible for
the look and feel of your wiki site
"""
name = "sinorca4moin"
def iconbar(self, d):
"""
Assemble the iconbar
@param d: parameter dictionary
@rtype: string
@return: iconbar html
"""
iconbar = []
if self.cfg.page_iconbar and self.request.user.show_toolbar and d['page_name']:
iconbar.append('<ul id="iconbar">\n')
icons = self.cfg.page_iconbar[:]
for icon in icons:
if icon == "up":
if d['page_parent_page']:
iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
elif icon == "subscribe":
iconbar.append('<li>%s</li>\n' % self.make_iconlink(
["subscribe", "unsubscribe"][self.request.user.isSubscribedTo([d['page_name']])], d))
elif icon == "home":
if d['page_home_page']:
iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
else:
iconbar.append('<li>%s</li>\n' % self.make_iconlink(icon, d))
iconbar.append('</ul>\n')
return ''.join(iconbar)
def editbar(self, d):
""" Assemble the page edit bar.
Display on existing page. Replace iconbar, showtext, edit text,
refresh cache and available actions.
@param d: parameter dictionary
@rtype: unicode
@return: iconbar html
"""
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
# Make new edit bar
request = self.request
_ = self.request.getText
link = wikiutil.link_tag
quotedname = wikiutil.quoteWikinameURL(page.page_name)
links = []
add = links.append
# Parent page
#parent = page.getParentPage()
#if parent:
# add(parent.link_to(request, _("Show Parent", formatted=False)))
# Page actions
if page.isWritable() and request.user.may.write(page.page_name):
add(link(request, quotedname + '?action=edit', _('Edit')))
else:
add(_('Immutable Page', formatted=False))
add(link(request, quotedname + '?action=info',
_('Get Info', formatted=False)))
add(self.actionsMenu(page))
# Format
items = '\n'.join(['<li>%s</li>' % item for item in links if item != ''])
html = u'<ul class="editbar">\n%s\n</ul>\n' % items
# cache for next call
self._cache[cacheKey] = html
return html
def wikipanel(self, d):
""" Create wiki panel """
_ = self.request.getText
html = [
u'<div class="sidepanel">',
u' <p class="sideBarTitle">%s</p>' % _("Wiki"),
self.navibar(d),
u'</div>',
]
return u'\n'.join(html)
def pagepanel(self, d):
""" Create page panel """
_ = self.request.getText
if self.shouldShowEditbar(d['page']):
html = [
u'<div class="sidepanel">',
u' <p class="sideBarTitle">%s</p>' % _("Page"),
self.editbar(d),
u'</div>',
]
return u'\n'.join(html)
return ''
def userpanel(self, d):
""" Create user panel """
_ = self.request.getText
html = [
u'<div class="sidepanel">',
u' <p class="sideBarTitle">%s</p>' % _("User"),
self.username(d),
u'</div>'
]
return u'\n'.join(html)
def logo(self):
""" Assemble logo with link to front page
adds h1-tags for sinorca
"""
if self.cfg.logo_string:
pagename = wikiutil.getFrontPage(self.request).page_name
pagename = wikiutil.quoteWikinameURL(pagename)
logo = wikiutil.link_tag(self.request, pagename, self.cfg.logo_string)
html = u'''<div id="logo"> <h1 class="headerTitle">%s</h1></div>''' % logo
return html
return u''
def header(self, d):
"""
Assemble page header
@param d: parameter dictionary
@rtype: string
@return: page header html
"""
_ = self.request.getText
trail = self.trail(d)
html = [
# Header
u'<div id="header">',
# Custom html super-header
self.emit_custom_html(self.cfg.page_header1),
u' <div class="midHeader">',
self.logo(),
u' </div>',
# Custom html below header (not recomended!)
self.emit_custom_html(self.cfg.page_header2),
trail,
u'</div>',
# Iconbar
self.iconbar(d),
# Sidebar
u'<!-- ##### Side Bar ##### -->',
u'<div id="sidebar">',
u'<div class="sidepanel">',
u' <p class="sideBarTitle">Search in %s</p>' % _(self.cfg.sitename),
self.searchform(d),
u'</div>',
self.wikipanel(d),
self.pagepanel(d),
self.userpanel(d),
self.credits(d),
u'</div>',
self.msg(d),
# Page
self.startPage(),
self.title(d),
]
return u'\n'.join(html)
def footer(self, d, **keywords):
""" Assemble page footer
@param d: parameter dictionary
@keyword ...:...
@rtype: string
@return: page footer html
"""
page = d['page']
html = [
# Page end
# Used to extend the page to the bottom of the sidebar
u'<div id="pagebottom"></div>',
self.pageinfo(page),
self.endPage(),
# Custom html above footer
self.emit_custom_html(self.cfg.page_footer1),
# And bellow
self.emit_custom_html(self.cfg.page_footer2),
]
return u'\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)