Imports initiaux
darcs-hash:20060416092713-72cb0-421d3cbb49699fce4971355f5dbbaa19091945e8.gz
This commit is contained in:
parent
0192d9e074
commit
1e7ce4861e
7 changed files with 1645 additions and 0 deletions
688
wiki/macro/Gallery.py
Normal file
688
wiki/macro/Gallery.py
Normal file
|
@ -0,0 +1,688 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
"""
|
||||
Gallery.py Version 0.86
|
||||
|
||||
This macro creates dynamic tabulated displays based on attachment contents
|
||||
|
||||
@copyright: 2004,2005 by Simon Ryan <simon<at>smartblackbox.com> http://smartblackbox.com/simon
|
||||
@license: GPL
|
||||
|
||||
Special thanks go to:
|
||||
My beautiful wife Jenny: For keeping the kids at bay long enough for me to code it :-)
|
||||
Adam Shand: For his GallerySoftware feature wish list, support, ideas and suggestions.
|
||||
|
||||
Usage: [[Gallery(key1=value1,key2=value2....)]]
|
||||
|
||||
where the following keys are valid:
|
||||
thumbnailwidth = no of pixels wide to make the thumbnails
|
||||
webnailwidth = width in pixels of the web sized images
|
||||
numberofcolumns = no of columns used in the thumbnail table
|
||||
|
||||
Bugs:
|
||||
|
||||
Continued rotation will degrade the tmp images (but they can be forced to regen)
|
||||
|
||||
Features:
|
||||
|
||||
Simple usage, just put [[Gallery]] on any page and upload some pictures as attachments
|
||||
Rotate buttons
|
||||
Annotation
|
||||
Should work with MoinMoin versions 1.2.x and 1.3.x
|
||||
Support for Python Imaging Library
|
||||
Works with FastCGI mode
|
||||
|
||||
|
||||
Not yet implemented:
|
||||
Handling of video formats
|
||||
|
||||
Speed up:
|
||||
# When you get really sick of how slow the moinmoin image system is,
|
||||
# you can either reconfigure your setup for FastCGI (highly recommended)
|
||||
# or: set the following variables in your wikiconfig.py
|
||||
gallerytempdir (the path to a writable directory)
|
||||
gallerytempurl (the path in your webservers url space where this directory can be read from)
|
||||
eg:
|
||||
gallerytempdir='/var/www/html/nails'
|
||||
gallerytempurl='/nails'
|
||||
or maybe:
|
||||
gallerytempurl=url_prefix+'/nails'
|
||||
# There are other ways of getting speedups for attachments, but these methods are the safest (IMHO)
|
||||
|
||||
"""
|
||||
|
||||
__author__ = "Simon D. Ryan"
|
||||
__version__ = "0.86"
|
||||
|
||||
from MoinMoin import config, wikiutil
|
||||
import string, cStringIO, os
|
||||
import commands, shutil
|
||||
from random import randint
|
||||
try:
|
||||
import Image
|
||||
except:
|
||||
pass
|
||||
|
||||
class Globs:
|
||||
# A quick place to plonk those shared variables
|
||||
thumbnailwidth='200'
|
||||
webnailwidth='600'
|
||||
numberofcolumns=4
|
||||
adminmsg=''
|
||||
debuglevel=0
|
||||
originals={}
|
||||
convertbin=''
|
||||
annotated={}
|
||||
attachmentdir=''
|
||||
gallerytempdirroot=''
|
||||
gallerytempdir=''
|
||||
gallerytempurl=''
|
||||
galleryrotchar=''
|
||||
pagename=''
|
||||
admin=''
|
||||
bcomp=''
|
||||
baseurl=''
|
||||
timeout=40
|
||||
allowedextensions=['jpg','jpeg','png','bmp','tiff','gif']
|
||||
|
||||
def message(astring,level=1):
|
||||
if level<=Globs.debuglevel:
|
||||
Globs.adminmsg=Globs.adminmsg+'<font color="#FF0000"><strong>Gallery</strong></font>: '+astring+'<br>\n'
|
||||
|
||||
def version():
|
||||
return(' version <b>'+Globs.version+'</b> by Simon D. Ryan.'+\
|
||||
'<br>Copyright 2004,2005 Simon D. Ryan<br>Gallery is a MoinMoin macro and is released under the '+\
|
||||
'<a href="http://www.gnu.org/licenses/gpl.txt">GPL</a>\n'+\
|
||||
'<p>Upload some images as attachments to <a href="'+Globs.baseurl+Globs.pagename+'?action=AttachFile"><b>'+Globs.pagename+'</b></a> and I will generate a gallery for you.')
|
||||
|
||||
# Thanks to denny<at>ece.arizona.edu
|
||||
# This can be replaced with a static translation table to speed things up (later)
|
||||
def mktrans():
|
||||
# Allow only letters and digits and a few other valid file characters
|
||||
alphanumeric=string.letters+string.digits+'.,-_\'!"'
|
||||
source_string=""
|
||||
destination_string=""
|
||||
for i in range(256):
|
||||
source_string=source_string+chr(i)
|
||||
if chr(i) in alphanumeric:
|
||||
destination_string=destination_string+chr(i)
|
||||
else:
|
||||
destination_string=destination_string+' '
|
||||
return string.maketrans(source_string,destination_string)
|
||||
|
||||
def qlink(pagename, querystring, query, description=''):
|
||||
# Returns a hyperlink constructed as a form query on pagename
|
||||
if not description:
|
||||
description=query
|
||||
return '<a href="'+Globs.baseurl+pagename+'?'+querystring+'='+query+Globs.bcomp+'">'+description+'</a>'
|
||||
|
||||
def navibar(target,querystring):
|
||||
# Returns a navigational bar with PREV,THUMBS,NEXT
|
||||
positions=Globs.originals.keys()
|
||||
positions.sort()
|
||||
thumbs='<a href="'+Globs.subname+'">THUMBS</a>'
|
||||
index=positions.index(target)
|
||||
back,forward='',''
|
||||
if not index==0:
|
||||
# We are not the first so we can provide a back link
|
||||
back=qlink(Globs.pagename, querystring, positions[index-1], 'PREV')
|
||||
if not index==len(positions)-1:
|
||||
# We are not the last so we can provide a forward link
|
||||
forward=qlink(Globs.pagename, querystring, positions[index+1], 'NEXT')
|
||||
return '<table><tr><td>'+back+'</td><td>'+thumbs+'</td><td>'+forward+'</td></tr></table>'
|
||||
|
||||
def toolbar(target,naillevel):
|
||||
if Globs.admin:
|
||||
rotateleft='<input type="submit" name="rotate" value="rotate left">'
|
||||
rotateright='<input type="submit" name="rotate" value="rotate right">'
|
||||
htarget='<input type=hidden value="'+target+'" name="'+naillevel+'">'
|
||||
compat='<input type=hidden value="show" name="action">'
|
||||
return '<form METHOD=POST><table><tr><td>'+rotateleft+'</td><td>'+rotateright+'</td></tr></table>\n'+htarget+compat+'</form>'
|
||||
else:
|
||||
return ''
|
||||
|
||||
def buildnails(items):
|
||||
# For now we use commands.getoutput to do our dirty work
|
||||
# Later we can build a batch job and fork it off.
|
||||
|
||||
# Make sure our temp directory is writable and generate a message if it isn't
|
||||
try:
|
||||
if not os.path.isfile(Globs.gallerytempdir+'/tmp.writetest'):
|
||||
# There is probably a less ugly was to do this using stat (later)
|
||||
open(Globs.gallerytempdir+'/tmp.writetest','w').close()
|
||||
except IOError:
|
||||
message('I had some trouble writing to the temp directory. Is it owned by me and writable?',0)
|
||||
|
||||
# Don't go further if there is a lock in place
|
||||
if os.path.isfile(Globs.attachmentdir+'/tmp.lock'):
|
||||
message("I'm currently busy generating thumbnails and webnails, please try again later.",0)
|
||||
return ''
|
||||
|
||||
# Find the convert binary in standard locations
|
||||
if not globals().has_key('Image'):
|
||||
if not os.path.isfile('/usr/bin/convert'):
|
||||
if not os.path.isfile('/usr/X11R6/bin/convert'):
|
||||
message('<b>Please install ImageMagick or PIL so I can build thumbnails and webnails</b><p>',0)
|
||||
return
|
||||
else:
|
||||
Globs.convertbin='/usr/X11R6/bin/convert'
|
||||
else:
|
||||
Globs.convertbin='/usr/bin/convert'
|
||||
else:
|
||||
# Use Python Imaging Library
|
||||
Globs.convertbin='Image'
|
||||
|
||||
# Create a lock file in the attachments dir so we can always remotely remove it if there is a problem
|
||||
open(Globs.attachmentdir+'/tmp.lock','w').close()
|
||||
|
||||
import time
|
||||
tstart=time.time()
|
||||
pid,pid2='',''
|
||||
|
||||
# For each original file, check for the existance of a nail
|
||||
for item in items:
|
||||
basename,prefix,width=item
|
||||
|
||||
# Check to see if we tarry too long on the road
|
||||
if tstart and (time.time()-tstart) > Globs.timeout:
|
||||
# This is taking waaay too long let us fork and detach else the browser will time out or worse, the webserver may kill us
|
||||
pid = os.fork()
|
||||
if pid != 0:
|
||||
# We are in the parent so we break out
|
||||
message('The thumbnail generation process was taking too long so it has been backgrounded. Please try again later to see the full set of thumbnails',0)
|
||||
break
|
||||
else:
|
||||
# Once we are forked we want to ignore the time
|
||||
tstart=''
|
||||
# Break away from the controlling terminal, so that the web server cannot kill us by killing our parent
|
||||
os.setsid()
|
||||
# Fork again so we can get away without a controlling terminal
|
||||
pid2 = os.fork()
|
||||
if (pid2 != 0):
|
||||
os._exit(0)
|
||||
else:
|
||||
# Close all open file descriptors
|
||||
try:
|
||||
max_fd = os.sysconf("SC_OPEN_MAX")
|
||||
except (AttributeError, ValueError):
|
||||
max_fd = 256
|
||||
for fd in range(0, max_fd):
|
||||
try:
|
||||
os.close(fd)
|
||||
except OSError:
|
||||
pass
|
||||
# Redirect the standard file descriptors to /dev/null
|
||||
os.open("/dev/null", os.O_RDONLY) # stdin
|
||||
os.open("/dev/null", os.O_RDWR) # stdout
|
||||
os.open("/dev/null", os.O_RDWR) # stderr
|
||||
|
||||
# Now we are finally free to continue the conversions as a daemon
|
||||
# If you would like to know more about the above, see:
|
||||
# Advanced Programming in the Unix Environment: W. Richard Stevens
|
||||
# It is also explained in:
|
||||
# Unix Network Programming (Volume 1): W. Richard Stevens
|
||||
|
||||
#pathtooriginal='"'+Globs.attachmentdir+'/'+Globs.originals[basename]+'"'
|
||||
pathtooriginal='"'+os.path.join(Globs.attachmentdir,Globs.originals[basename])+'"'
|
||||
# Warning:
|
||||
# Take care if modifying the following line,
|
||||
# you may inadvertantly overwrite your original images!
|
||||
if not Globs.convertbin == 'Image':
|
||||
#print 'building nail for '+pathtooriginal
|
||||
#convout=commands.getoutput('%s -geometry %s \"%s\" "\"%s/%s.%s.jpg\""' % (Globs.convertbin,width+'x'+width,pathtooriginal,Globs.gallerytempdir,prefix,basename))
|
||||
convout=commands.getoutput('%s -geometry %s %s "%s/%s.%s.jpg"' % (Globs.convertbin,width+'x'+width,pathtooriginal,Globs.gallerytempdir,prefix,basename))
|
||||
convout=''
|
||||
convout=string.strip(convout)
|
||||
if convout:
|
||||
message(convout)
|
||||
else:
|
||||
# Use PIL (strip off the "")
|
||||
im = Image.open(pathtooriginal[1:-1])
|
||||
# Use the integer version for PIL
|
||||
width=string.atoi(width)
|
||||
im.thumbnail((width,width), Image.ANTIALIAS)
|
||||
im.save(os.path.join(Globs.gallerytempdir,prefix)+'.'+basename+'.jpg','JPEG')
|
||||
|
||||
if (not pid) and (not pid2):
|
||||
# Release the lock file when finished
|
||||
os.unlink(Globs.attachmentdir+'/tmp.lock')
|
||||
|
||||
# We have built thumbnails so we can deposit an indicator file to prevent rebuilding next time
|
||||
if not os.path.isfile(Globs.attachmentdir+'/delete.me.to.regenerate.thumbnails.and.webnails'):
|
||||
open(Globs.attachmentdir+'/delete.me.to.regenerate.thumbnails.and.webnails','w').close()
|
||||
|
||||
|
||||
def rotate(target,direction):
|
||||
# Rotate the images
|
||||
# Don't go further if there is a lock in place
|
||||
if os.path.isfile(Globs.attachmentdir+'/tmp.lock'):
|
||||
message("I'm currently busy generating thumbnails and webnails. Please try your rotate request again later.",0)
|
||||
return ''
|
||||
|
||||
# Find the correct binary
|
||||
if not globals().has_key('Image'):
|
||||
if not os.path.isfile('/usr/bin/mogrify'):
|
||||
if not os.path.isfile('/usr/X11R6/bin/mogrify'):
|
||||
message('<b>Please install ImageMagick so I can build thumbnails and webnails</b><p>',0)
|
||||
return
|
||||
else:
|
||||
Globs.convertbin='/usr/X11R6/bin/mogrify'
|
||||
else:
|
||||
Globs.convertbin='/usr/bin/mogrify'
|
||||
else:
|
||||
Globs.convertbin = 'Image'
|
||||
|
||||
# Do the actual rotations
|
||||
if direction=='rotate right':
|
||||
degs='90'
|
||||
else:
|
||||
degs='270'
|
||||
if not Globs.convertbin == 'Image':
|
||||
convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/tmp.webnail.'+target+'.jpg"')
|
||||
convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/tmp.thumbnail.'+target+'.jpg"')
|
||||
if not os.path.isfile(Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg'):
|
||||
# Generate from original
|
||||
pathtooriginal=Globs.attachmentdir+'/'+Globs.originals[target]
|
||||
shutil.copy(pathtooriginal,Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg')
|
||||
convout=commands.getoutput(Globs.convertbin+' -rotate '+degs+' "'+Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg"')
|
||||
else:
|
||||
# Use PIL (strip off the "")
|
||||
if direction=='rotate right':
|
||||
degs=270.0
|
||||
else:
|
||||
degs=90.0
|
||||
im = os.path.join(Globs.gallerytempdir,'tmp.webnail.')+target+'.jpg'
|
||||
imw = Image.open(im)
|
||||
imw.rotate(degs).save(im,'JPEG')
|
||||
im = os.path.join(Globs.gallerytempdir,'tmp.thumbnail.')+target+'.jpg'
|
||||
imw = Image.open(im)
|
||||
imw.rotate(degs).save(im,'JPEG')
|
||||
imo = os.path.join(Globs.gallerytempdir,'tmp.rotated.')+target+'.jpg'
|
||||
if not os.path.isfile(Globs.gallerytempdir+'/tmp.rotated.'+target+'.jpg'):
|
||||
# Generate from original
|
||||
im=Globs.attachmentdir+'/'+Globs.originals[target]
|
||||
else:
|
||||
im = imo
|
||||
imw = Image.open(im)
|
||||
imw.rotate(degs).save(imo,'JPEG')
|
||||
|
||||
def getannotation(target):
|
||||
# Annotations are stored as a file for now (later to be stored in images)
|
||||
atext=''
|
||||
if Globs.annotated.has_key(target):
|
||||
atext=open(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt').readline()
|
||||
message('was annotated')
|
||||
else:
|
||||
message('was not annotated')
|
||||
# replace double quotes with the html escape so quoted annotations appear
|
||||
return string.replace(atext,'"','"')
|
||||
|
||||
def execute(macro, args):
|
||||
|
||||
Globs.version=__version__
|
||||
|
||||
# Containers
|
||||
formvals={}
|
||||
thumbnails={}
|
||||
webnails={}
|
||||
rotated={}
|
||||
try:
|
||||
import wikiconfig
|
||||
except:
|
||||
wikiconfig=''
|
||||
|
||||
# Class variables need to be specifically set
|
||||
# (except for the case where a value is to be shared with another Gallery macro on the same wiki page)
|
||||
Globs.originals={}
|
||||
Globs.annotated={}
|
||||
Globs.attachmentdir=''
|
||||
Globs.admin=''
|
||||
Globs.adminmsg=''
|
||||
Globs.pagename=''
|
||||
|
||||
# process arguments
|
||||
if args:
|
||||
# Arguments are comma delimited key=value pairs
|
||||
sargs=string.split(args,',')
|
||||
for item in sargs:
|
||||
sitem=string.split(item,'=')
|
||||
if len(sitem)==2:
|
||||
key,value=sitem[0],sitem[1]
|
||||
if key=='thumbnailwidth':
|
||||
Globs.thumbnailwidth=value
|
||||
elif key=='webnailwidth':
|
||||
Globs.webnailwidth=value
|
||||
elif key=='numberofcolumns':
|
||||
try:
|
||||
Globs.numberofcolumns=string.atoi(value)
|
||||
except TypeError:
|
||||
pass
|
||||
# Experimental, uncomment at own risk
|
||||
#elif key=='pagename':
|
||||
# Globs.pagename=value
|
||||
|
||||
transtable=mktrans()
|
||||
|
||||
# Useful variables
|
||||
dontregen=''
|
||||
annotationmessage=''
|
||||
Globs.baseurl=macro.request.getBaseURL()+'/'
|
||||
if not Globs.pagename:
|
||||
#Globs.pagename = string.replace(macro.formatter.page.page_name,'/','_2f')
|
||||
Globs.pagename = macro.formatter.page.page_name
|
||||
# This fixes the subpages bug. subname is now used instead of pagename when creating certain urls
|
||||
Globs.subname = string.split(Globs.pagename,'/')[-1]
|
||||
# Hmmm. A bug in moinmoin? underscores are getting escaped. These doubly escaped pagenames are even appearing in data/pages
|
||||
try:
|
||||
# Try the old MoinMoin-1.2.x way first
|
||||
textdir=config.text_dir
|
||||
pagepath = string.replace(wikiutil.getPagePath(Globs.pagename),'_5f','_')
|
||||
except:
|
||||
pagepath = macro.formatter.page.getPagePath()
|
||||
Globs.attachmentdir = pagepath+'/attachments'
|
||||
Globs.galleryrotchar='?'
|
||||
if hasattr(macro,'cfg') and hasattr(macro.cfg,'gallerytempdir') and hasattr(macro.cfg,'gallerytempurl'):
|
||||
Globs.gallerytempdirroot=macro.cfg.gallerytempdir
|
||||
Globs.gallerytempdir=macro.cfg.gallerytempdir+'/'+Globs.pagename+'/'
|
||||
Globs.gallerytempurl=macro.cfg.gallerytempurl+'/'+Globs.pagename+'/'
|
||||
elif hasattr(wikiconfig,'gallerytempdir') and hasattr(wikiconfig,'gallerytempurl'):
|
||||
message('gallerytempdir and gallerytempurl found')
|
||||
Globs.gallerytempdirroot=wikiconfig.gallerytempdir
|
||||
Globs.gallerytempdir=wikiconfig.gallerytempdir+'/'+Globs.pagename+'/'
|
||||
Globs.gallerytempurl=wikiconfig.gallerytempurl+'/'+Globs.pagename+'/'
|
||||
elif hasattr(wikiconfig,'attachments'):
|
||||
Globs.gallerytempdirroot=wikiconfig.attachments['dir']
|
||||
Globs.gallerytempdir=wikiconfig.attachments['dir']+'/'+Globs.pagename+'/attachments/'
|
||||
Globs.gallerytempurl=wikiconfig.attachments['url']+'/'+Globs.pagename+'/attachments/'
|
||||
Globs.attachmentdir = Globs.gallerytempdir
|
||||
else:
|
||||
Globs.gallerytempdir=Globs.attachmentdir
|
||||
Globs.gallerytempurl=Globs.subname+'?action=AttachFile&do=get&target='
|
||||
# MoinMoin no longer allows us to use a ? to trigger a refetch, so we pass it a &
|
||||
Globs.galleryrotchar='&'
|
||||
if args:
|
||||
args=macro.request.getText(args)
|
||||
|
||||
# HTML Constants
|
||||
tleft='<table><tr><td><center>'
|
||||
tmidd='</center></td><td><center>'
|
||||
trigh='</center></td></tr></table>\n'
|
||||
# Add this to the end of each URL to keep some versions of moinmoin happy
|
||||
Globs.bcomp='&action=show'
|
||||
|
||||
# Process any form items into a dictionary (values become unique)
|
||||
for item in macro.form.items():
|
||||
if not formvals.has_key(item[0]):
|
||||
# Here is where we clean the untrusted web input
|
||||
# (sometimes we get foreign keys from moinmoin when the page is edited)
|
||||
try:
|
||||
formvals[item[0]]=string.translate(item[1][0],transtable)
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# Figure out if we have delete privs
|
||||
try:
|
||||
# If a user can delete the page containing the Gallery, then they are considered a Gallery administrator
|
||||
# This probably should be configurable via a wikiconfig variable eg: galleryadminreq = <admin|delete|any>
|
||||
if macro.request.user.may.delete(macro.formatter.page.page_name):
|
||||
Globs.admin='true'
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
out=cStringIO.StringIO()
|
||||
|
||||
# Grab a list of the files in the attachment directory
|
||||
if os.path.isdir(Globs.attachmentdir):
|
||||
if Globs.gallerytempdir==Globs.attachmentdir:
|
||||
afiles=os.listdir(Globs.attachmentdir)
|
||||
else:
|
||||
if not os.path.isdir(Globs.gallerytempdirroot):
|
||||
message('You need to create the temp dir first:'+Globs.gallerytempdirroot,0)
|
||||
return macro.formatter.rawHTML(
|
||||
Globs.adminmsg+'<p>')
|
||||
if not os.path.isdir(Globs.gallerytempdir):
|
||||
# Try to create it if it is absent
|
||||
spagename=string.split(Globs.pagename,'/')
|
||||
compbit=''
|
||||
for component in spagename:
|
||||
compbit=compbit+'/'+component
|
||||
try:
|
||||
os.mkdir(Globs.gallerytempdirroot+compbit)
|
||||
except:
|
||||
message('Please check permissions on temp dir:'+Globs.gallerytempdirroot,0)
|
||||
return macro.formatter.rawHTML(
|
||||
Globs.adminmsg+'<p>')
|
||||
|
||||
if os.path.isdir(Globs.gallerytempdir):
|
||||
afiles=os.listdir(Globs.attachmentdir)+os.listdir(Globs.gallerytempdir)
|
||||
else:
|
||||
message('You need to create the temp dir first:'+Globs.gallerytempdir,0)
|
||||
return macro.formatter.rawHTML(
|
||||
Globs.adminmsg+'<p>')
|
||||
|
||||
# Split out the thumbnails and webnails
|
||||
for item in afiles:
|
||||
if item.startswith('tmp.thumbnail.'):
|
||||
origname=item[14:-4]
|
||||
thumbnails[origname]=''
|
||||
elif item.startswith('tmp.webnail.'):
|
||||
origname=item[12:-4]
|
||||
webnails[origname]=''
|
||||
elif item.startswith('tmp.rotated.'):
|
||||
origname=item[12:-4]
|
||||
rotated[origname]=''
|
||||
elif item.startswith('tmp.annotation.'):
|
||||
origname=item[15:-4]
|
||||
Globs.annotated[origname]=''
|
||||
elif item == 'delete.me.to.regenerate.thumbnails.and.webnails':
|
||||
dontregen='true'
|
||||
elif item == 'tmp.writetest' or item == 'tmp.lock':
|
||||
pass
|
||||
else:
|
||||
# This must be one of the original images
|
||||
lastdot=string.rfind(item,'.')
|
||||
origname=item[:lastdot]
|
||||
ext = item[lastdot+1:]
|
||||
if string.lower(ext) not in Globs.allowedextensions:
|
||||
continue
|
||||
Globs.originals[origname]=item
|
||||
else:
|
||||
message(version(),0)
|
||||
return macro.formatter.rawHTML( Globs.adminmsg )
|
||||
|
||||
if not Globs.gallerytempdir==Globs.attachmentdir and os.path.isfile(Globs.attachmentdir+'/tmp.writetest'):
|
||||
# If we are using the new gallerytempdir and we were using the old system then make sure there are no
|
||||
# remnant files from the old system in the attachment dir to confuse us
|
||||
message('You have changed to using a gallerytempdir so I am cleaning old tmp files from your attachment dir.',0)
|
||||
for item in webnails.keys():
|
||||
try:
|
||||
os.unlink(Globs.attachmentdir+'/tmp.webnail.'+item+'.jpg')
|
||||
except:
|
||||
pass
|
||||
# Try deleting any old thumbnails which may be in the attachment directory
|
||||
for item in thumbnails.keys():
|
||||
try:
|
||||
os.unlink(Globs.attachmentdir+'/tmp.thumbnail.'+item+'.jpg')
|
||||
except:
|
||||
pass
|
||||
# Try deleting any old rotated originals which may be in the attachment directory
|
||||
for item in rotated.keys():
|
||||
try:
|
||||
os.unlink(Globs.attachmentdir+'/tmp.rotated.'+item+'.jpg')
|
||||
except:
|
||||
pass
|
||||
os.unlink(Globs.attachmentdir+'/tmp.writetest')
|
||||
|
||||
newnails=[]
|
||||
# Any thumbnails need to be built?
|
||||
for key in Globs.originals.keys():
|
||||
if (not thumbnails.has_key(key)) or (not dontregen):
|
||||
# Create a thumbnail for this original
|
||||
newnails.append((key,'tmp.thumbnail',Globs.thumbnailwidth))
|
||||
# Any webnails need to be built?
|
||||
for key in Globs.originals.keys():
|
||||
if (not webnails.has_key(key)) or (not dontregen):
|
||||
# Create a webnail for this original
|
||||
newnails.append((key,'tmp.webnail',Globs.webnailwidth))
|
||||
# Ok, lets build them all at once
|
||||
if not len(newnails)==0:
|
||||
buildnails(newnails)
|
||||
|
||||
# If a regen of thumbnails and webnails has occurred, then we should also delete any tmp.rotated files.
|
||||
if not dontregen:
|
||||
for key in rotated.keys():
|
||||
# Wrapped in a try except since child processes may try to unlink a second time
|
||||
try:
|
||||
os.unlink(Globs.gallerytempdir+'/tmp.rotated.'+key+'.jpg')
|
||||
except:
|
||||
pass
|
||||
|
||||
if formvals.has_key('annotate'):
|
||||
if Globs.admin and formvals.has_key('target'):
|
||||
target=formvals['target']
|
||||
# Write an annotation file
|
||||
atext=string.replace(formvals['annotate'],'"','"')
|
||||
target=formvals['target']
|
||||
ouf=open(Globs.attachmentdir+'/tmp.annotation.'+target+'.txt','w')
|
||||
ouf.write(atext)
|
||||
ouf.close()
|
||||
message('Annotation updated to <i>'+atext+'</i>',0)
|
||||
# Now update the annotated dictionary
|
||||
if not Globs.annotated.has_key(target):
|
||||
Globs.annotated[target]=''
|
||||
|
||||
if formvals.has_key('webnail'):
|
||||
# Does the webnail exist?
|
||||
message('webnail requested')
|
||||
target=formvals['webnail']
|
||||
rotend=''
|
||||
if Globs.originals.has_key(target):
|
||||
out.write(navibar(target,'webnail'))
|
||||
if formvals.has_key('rotate'):
|
||||
direction=formvals['rotate']
|
||||
message(direction)
|
||||
rotate(target,direction)
|
||||
rotend=Globs.galleryrotchar+'rot='+repr(randint(1,10000))
|
||||
# Put things in a table
|
||||
out.write(tleft)
|
||||
# Lets build up an image tag
|
||||
out.write('<a href="'+Globs.baseurl+Globs.pagename+'?original='+target+'&action=content"><img src="'+Globs.gallerytempurl+'tmp.webnail.'+target+'.jpg'+rotend+'"></a>\n')
|
||||
out.write(trigh)
|
||||
out.write(tleft)
|
||||
|
||||
atext=getannotation(target)
|
||||
|
||||
# Are we an administrator?
|
||||
if Globs.admin:
|
||||
# We always provide an annotation text field
|
||||
out.write('<form action='+Globs.subname+' name=annotate METHOD=POST>')
|
||||
out.write('<input maxLength=256 size=55 name=annotate value="'+atext+'">')
|
||||
out.write('<input type=hidden value="'+target+'" name="target">')
|
||||
out.write('<input type=hidden value="show" name="action">')
|
||||
out.write('<input type=hidden value="'+target+'" name="webnail">')
|
||||
out.write('</form>')
|
||||
else:
|
||||
out.write(atext)
|
||||
out.write(trigh)
|
||||
out.write(toolbar(target,'webnail'))
|
||||
|
||||
else:
|
||||
message('I do not have file: '+target,0)
|
||||
elif formvals.has_key('original'):
|
||||
# Now we just construct a single item rather than a table
|
||||
# Does the webnail exist?
|
||||
message('original requested')
|
||||
target=formvals['original']
|
||||
rotend=''
|
||||
if not Globs.originals.has_key(target):
|
||||
message('I do not have file: '+target,0)
|
||||
else:
|
||||
if formvals.has_key('rotate'):
|
||||
direction=formvals['rotate']
|
||||
message(direction)
|
||||
rotate(target,direction)
|
||||
rotend=Globs.galleryrotchar+'rot='+repr(randint(1,10000))
|
||||
rotated[target]=''
|
||||
# Lets build up an image tag
|
||||
out.write(navibar(target,'original'))
|
||||
out.write(tleft)
|
||||
originalfilename=Globs.originals[target]
|
||||
# If there is a rotated version, show that instead
|
||||
if rotated.has_key(target):
|
||||
out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.gallerytempurl+'tmp.rotated.'+target+'.jpg'+rotend+'"></a>\n')
|
||||
else:
|
||||
out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.subname+'?action=AttachFile&do=get&target='+originalfilename+'"></a>\n')
|
||||
out.write(trigh)
|
||||
out.write(tleft)
|
||||
|
||||
atext=getannotation(target)
|
||||
|
||||
# Are we an administrator?
|
||||
if Globs.admin:
|
||||
# We always provide an annotation text field
|
||||
out.write('<form action='+Globs.subname+' name=annotate METHOD=POST>')
|
||||
out.write('<input maxLength=256 size=55 name=annotate value="'+atext+'">')
|
||||
out.write('<input type=hidden value="'+target+'" name="target">')
|
||||
out.write('<input type=hidden value="show" name="action">')
|
||||
out.write('<input type=hidden value="'+target+'" name="original">')
|
||||
out.write('</form>')
|
||||
else:
|
||||
out.write(atext)
|
||||
out.write(trigh)
|
||||
out.write(toolbar(target,'original'))
|
||||
|
||||
elif formvals.has_key('rotate'):
|
||||
# We rotate all sizes of this image to the left or right
|
||||
message('rotate requested')
|
||||
target=formvals['target']
|
||||
direction=formvals['rotate']
|
||||
if not Globs.originals.has_key(target):
|
||||
message('I do not have file: '+target,0)
|
||||
else:
|
||||
# Do the rotation
|
||||
rotate(target,direction)
|
||||
# Display the new image in webnail mode
|
||||
# We may need a way of forcing the browser to reload the newly rotated image here (later)
|
||||
out.write(tleft)
|
||||
out.write('<a href="'+Globs.baseurl+Globs.pagename+'?webnail='+target+Globs.bcomp+'"><img src="'+Globs.gallerytempurl+'tmp.webnail.'+target+'.jpg"></a>\n')
|
||||
out.write(trigh)
|
||||
|
||||
else:
|
||||
# Finally lets build a table of thumbnails
|
||||
thumbs=Globs.originals.keys()
|
||||
thumbs.sort()
|
||||
thumbs.reverse()
|
||||
# If version number is requested (append a ?version=tellme&action=show to the page request)
|
||||
# or if there are no original images, just give help message and return
|
||||
if formvals.has_key('version') or len(thumbs)==0:
|
||||
message(version(),0)
|
||||
return macro.formatter.rawHTML( Globs.adminmsg )
|
||||
out.write('\n<table>')
|
||||
cease=''
|
||||
rollover=''
|
||||
while 1:
|
||||
out.write('<tr>')
|
||||
for i in range(Globs.numberofcolumns):
|
||||
try:
|
||||
item=thumbs.pop()
|
||||
except IndexError:
|
||||
cease='true'
|
||||
break
|
||||
|
||||
# Alt text
|
||||
atext=getannotation(item)
|
||||
rollover='alt="'+atext+'" title="'+atext+'"'
|
||||
|
||||
# Table entry for thumbnail image
|
||||
out.write('<td><a href="'+Globs.baseurl+Globs.pagename+'?webnail='+item+Globs.bcomp+'"><center><img src="'+Globs.gallerytempurl+'tmp.thumbnail.'+item+'.jpg" '+rollover+'></a></center></td>')
|
||||
out.write('</tr>\n')
|
||||
if cease:
|
||||
out.write('</table>')
|
||||
break
|
||||
|
||||
out.seek(0)
|
||||
# Finally output any administrative messages at the top followed by any generated content
|
||||
return macro.formatter.rawHTML(
|
||||
Globs.adminmsg+'<p>'
|
||||
+out.read()
|
||||
)
|
||||
|
173
wiki/macro/ImageLink.py
Normal file
173
wiki/macro/ImageLink.py
Normal file
|
@ -0,0 +1,173 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
"""
|
||||
MoinMoin - ImageLink Macro
|
||||
|
||||
PURPOSE:
|
||||
This macro is used to set a link as WikiName for an attached image. Optional the size of the
|
||||
image could be adjusted. If no WikiName is given the attachment is linked to the image itselfs.
|
||||
|
||||
CALLING SEQUENCE:
|
||||
[[ImageLink(attachment|URL,[WikiName|URL],[width=width,[height=heigt]])]]
|
||||
|
||||
INPUTS:
|
||||
attachment:image name of attachment or the URL to an image
|
||||
|
||||
OPTIONAL INPUTS:
|
||||
WikiName: the page to set the link to or the URL to link to
|
||||
|
||||
|
||||
KEYWORD PARAMETERS:
|
||||
width: width of the embedded image
|
||||
height: height of the embedded image
|
||||
|
||||
EXAMPLE:
|
||||
[[ImageLink(plot.png,FrontPage,width=20,height=20)]]
|
||||
[[ImageLink(plot.png,FrontPage,height=20)]]
|
||||
[[ImageLink(plot.png,FrontPage)]]
|
||||
[[ImageLink(plot.png,width=20,height=20)]]
|
||||
[[ImageLink(plot.png,width=20)]]
|
||||
[[ImageLink(plot.png)]]
|
||||
[[ImageLink(http://localhost/wiki/modern/img/to_slide.png,http://localhost/StartSeite,width=50)]]
|
||||
[[ImageLink(http://localhost/wiki/modern/img/to_slide.png,FrontPage,width=50)]]
|
||||
[[ImageLink(plot.png,http://localhost/StartSeite,width=50)]]
|
||||
[[ImageLink(http://localhost/wiki/modern/img/to_slide.png)]]
|
||||
[[ImageLink(http://localhost/wiki/modern/img/to_slide.png,alt=whateveryouwant)]]
|
||||
|
||||
PROCEDURE:
|
||||
This routine requires attachment enabled. If the attachment isn't downloaded at all
|
||||
the attachment line is shown.
|
||||
If you give only one image size argument e.g. width only the other one is calculated
|
||||
|
||||
It must be in "MoinMoin/macro"
|
||||
|
||||
Please remove the version number from the file name!
|
||||
|
||||
From JeffKunce ImageLink.py I have copied _is_URL to this routine. I have no better idea too.
|
||||
|
||||
HISTORY:
|
||||
The first published version on MoinMoin I know of ImageLink was written by JeffKunce in 2001.
|
||||
|
||||
MODIFICATION HISTORY:
|
||||
@copyright: 2004 by Reimar Bauer (R.Bauer@fz-juelich.de)
|
||||
@license: GNU GPL, see COPYING for details.
|
||||
|
||||
Marcin Zalewski:
|
||||
Some things that were causing problems on my wiki are changed
|
||||
(wikiutil.link_tag and macro.formatter.pagelink implemented)
|
||||
|
||||
Marcin Zalewski:
|
||||
Added title attribute to the created link. One could generalize that to
|
||||
add arbitrary attributes.
|
||||
|
||||
One could also add class attributes to <a> and/or
|
||||
<img> elements. I do not see the need for such modifications. If however this is
|
||||
to be done in the future one would need to add 'html_class' key to the kw dictionary
|
||||
with a corresponding value to add class to <img> element. To add class to <a> element
|
||||
one needs to add 'css_class' key with a corresponding value to the dictionary passed to
|
||||
pagelink call.
|
||||
Reimar Bauer:
|
||||
2004-12-23 Adopted to MoinMoin Version 1.3.1-1
|
||||
2004-12-23 SYNTAX CHANGE Version 1.3.1-2
|
||||
width and height and probably other keywords must be called as keywords (e.g. height=20)
|
||||
2004-12-31 Version 1.3.1-3 code clean up
|
||||
2005-01-16 Bug fixed in the errorhandler found and patch code from Malte Helmert
|
||||
2005-03-05 Version 1.3.3-5 Bug fixed found by cypress
|
||||
''If I put [[ImageLink(moinmoin.png)]] it bombs''
|
||||
2005-03-28 Version 1.3.3-6 feature request added by CDPark:
|
||||
''Can we use an external image? And an external target? ''
|
||||
2005-04-16 Version 1.3.3-7 no default alt tag definition requested by CDPark and AlexanderSchremmer
|
||||
Chong-Dae Park:
|
||||
2005-04-17 Version 1.3.3-8 code refactored
|
||||
IMG with no alt tag is not recommended in the HTML standard.
|
||||
It keeps user specified alt tag. If it is not, it tries to use WikiName or image name instead.
|
||||
Reimar Bauer:
|
||||
2005-04-21 Version 1.3.3-9 bug fixed
|
||||
When the image does not exist yet, it gives you a "Upload Image" link, this link does not
|
||||
work. I suspect that this only is a problem on sub-pages, caused by incorrect escaping of
|
||||
"/". -- CraigJohnson
|
||||
|
||||
|
||||
"""
|
||||
|
||||
from MoinMoin.action import AttachFile
|
||||
from MoinMoin import wikiutil, config
|
||||
import os,string
|
||||
|
||||
def _is_URL(aString):
|
||||
'''answer true if aString is a URL.
|
||||
The method used here is pretty dumb. Improvements are welcome.
|
||||
jjk 03/28/01'''
|
||||
return string.find(aString, '://')>0
|
||||
|
||||
|
||||
def execute(macro, text):
|
||||
|
||||
kw ={} # create a dictionary for the formatter.image call
|
||||
|
||||
if text:
|
||||
args=text.split(',')
|
||||
else:
|
||||
args=[]
|
||||
|
||||
number_args=len(args)
|
||||
count=0
|
||||
for a in args :
|
||||
if (a.find('=') > -1):
|
||||
count=count+1
|
||||
key=a.split('=')
|
||||
kw[str(key[0])]=wikiutil.escape(string.join(key[1],''), quote=1)
|
||||
|
||||
number_args=number_args-count
|
||||
|
||||
if (number_args < 1):
|
||||
msg='Not enough arguments to ImageLink macro! Try [[ImageLink(attachment,[WikiName],[width=width,[height=heigt]])]]'
|
||||
return macro.formatter.sysmsg(1)+macro.formatter.text(msg)+ macro.formatter.sysmsg(0)
|
||||
|
||||
|
||||
attname=wikiutil.taintfilename(macro.formatter.text(args[0]))
|
||||
if (number_args >= 2) :
|
||||
wikiname=args[1]
|
||||
current_pagename=macro.formatter.page.page_name
|
||||
|
||||
|
||||
if _is_URL(args[0]):
|
||||
kw['src']=args[0]
|
||||
else:
|
||||
kw['src']=AttachFile.getAttachUrl(current_pagename,attname,macro.request)
|
||||
attachment_path = os.path.join(AttachFile.getAttachDir(macro.request,current_pagename), attname)
|
||||
|
||||
if not os.path.exists(attachment_path):
|
||||
|
||||
import urllib
|
||||
linktext = macro.request.getText('Upload new attachment "%(filename)s"'%{
|
||||
"filename":attname})
|
||||
|
||||
return wikiutil.link_tag(macro.request,
|
||||
"%(pagename)s?action=AttachFile&rename=%(newname)s" % {
|
||||
"pagename":current_pagename,
|
||||
"newname": attname},linktext)
|
||||
|
||||
|
||||
|
||||
if not kw.has_key('alt'):
|
||||
if (number_args == 1) or _is_URL(args[1]):
|
||||
if _is_URL(args[0]):
|
||||
# Get image name http://here.com/dir/image.gif -> image.gif
|
||||
kw['alt'] = wikiutil.taintfilename(macro.formatter.text(args[0].split('/')[-1]))
|
||||
kw['alt'] = args[0].split('/')[-1]
|
||||
else:
|
||||
kw['alt'] = attname
|
||||
else:
|
||||
kw['alt'] = wikiname
|
||||
|
||||
if (number_args == 1):
|
||||
image_link=macro.formatter.image(**kw)
|
||||
return macro.formatter.url(1,kw['src'] )+image_link +macro.formatter.url(0)
|
||||
|
||||
if (number_args == 2 ):
|
||||
image_link=macro.formatter.image(**kw)
|
||||
if _is_URL(args[1]):
|
||||
return macro.formatter.url(1,args[1] )+image_link+macro.formatter.url(0)
|
||||
else:
|
||||
return macro.formatter.pagelink(1,wikiname)+image_link+macro.formatter.url(0)
|
||||
|
220
wiki/macro/ProgressBar.py
Normal file
220
wiki/macro/ProgressBar.py
Normal file
|
@ -0,0 +1,220 @@
|
|||
"""
|
||||
MoinMoin - ProgressBar Macro
|
||||
Generates a progress bar (in the form of a table)
|
||||
|
||||
@copyright: Pascal Bauermeister <pascal DOT bauermeister AT gmail DOT cm>
|
||||
@license: GPL
|
||||
|
||||
Updates:
|
||||
|
||||
* [v0.1.1] Sun Dec 18 21:31:17 CET 2005
|
||||
Changed table cell percentage markup.
|
||||
|
||||
* [v0.1.0] Fri Dec 16 22:30:10 CET 2005
|
||||
Original version
|
||||
|
||||
----
|
||||
|
||||
The ProgressBar macro generates a table showing a progress indicator.
|
||||
|
||||
Usage:
|
||||
[[ ProgressBar ]]
|
||||
[[ ProgressBar (TABLEWIDTH TABLEFORMAT PROGRESS%) ]]
|
||||
[[ ProgressBar (TABLEWIDTH TABLEFORMAT CURRENT/STEPS) ]]
|
||||
[[ ProgressBar (TABLEWIDTH TABLEFORMAT STARTDATE,ENDDATE) ]]
|
||||
|
||||
If no arguments are given, the usage is inserted in the HTML result.
|
||||
|
||||
Options:
|
||||
|
||||
TABLEWIDTH (optional prefix)
|
||||
A wiki tablewidth attribute value between []'s
|
||||
Examples:
|
||||
[100%]
|
||||
[80px]
|
||||
|
||||
TABLEFORMAT (optional prefix)
|
||||
A pair of wiki table attribute, to format the inactive and active cells.
|
||||
Examples:
|
||||
<bgcolor="black"><bgcolor="white"> # black on white bar
|
||||
<tablewidth="90%" bgcolor="black"><bgcolor="white"> # same, 90% table
|
||||
|
||||
A third format may be given for STARTDATE,ENDDATE usage
|
||||
|
||||
By default: <tablewidth="100px"#808080><><#8080ff>
|
||||
|
||||
PROGRESS
|
||||
Will display a table with two cells:
|
||||
- left: completion, taking PROGRESS % of the table width
|
||||
- right: remaining
|
||||
|
||||
CURRENT/STEPS
|
||||
Will display a table with STEPS cells, CURRENT of which are active.
|
||||
|
||||
STARTDATE,ENDDATE
|
||||
Will display a table with the number of days, with the cell
|
||||
representing today in active format and background in inactive format.
|
||||
|
||||
If today is before STARTDATE, the left-most cell will be in the
|
||||
3rd format. If today is after ENDDATE the rightmost cell will be
|
||||
in the 3rd format.
|
||||
|
||||
Dates are in this format: YYYY-MM-DD
|
||||
|
||||
Debugging
|
||||
Please prepend a '?' to the arguments.
|
||||
|
||||
Examples:
|
||||
[[ProgressBar(60%)]]
|
||||
[[ProgressBar(6/10)]]
|
||||
[[ProgressBar(2005-11-01,2006-01-06)]]
|
||||
|
||||
[[ProgressBar([50%] 60%)]]
|
||||
[[ProgressBar([50px] 60%)]]
|
||||
[[ProgressBar([90%]<#8080ff><#808080> 6/10)]]
|
||||
----
|
||||
"""
|
||||
|
||||
|
||||
# Imports
|
||||
import time, re, StringIO
|
||||
from MoinMoin import version
|
||||
from MoinMoin.parser import wiki
|
||||
|
||||
Dependencies = ["time"] # macro cannot be cached
|
||||
|
||||
|
||||
class _Error (Exception):
|
||||
pass
|
||||
|
||||
|
||||
def escape (str):
|
||||
return str.replace ('&','&').replace ('<', '<').replace ('>', '>')
|
||||
|
||||
def usage (full = False):
|
||||
|
||||
"""Returns the interesting part of the module's doc"""
|
||||
|
||||
if full:
|
||||
return __doc__
|
||||
else:
|
||||
rx = re.compile ("--$(.*)^--", re.DOTALL + re.MULTILINE)
|
||||
return rx.findall (__doc__) [0].strip ()
|
||||
|
||||
|
||||
def s2t (s):
|
||||
return time.mktime (time.strptime (s, "%Y-%m-%d"))
|
||||
|
||||
|
||||
def execute (macro, text, args_re=None):
|
||||
|
||||
try: res = _execute (macro, text)
|
||||
except Exception, msg:
|
||||
return """
|
||||
<p><strong class="error">
|
||||
Error: macro ProgressBar: %s</strong> </p>
|
||||
""" % escape ("%s" % msg)
|
||||
return res
|
||||
|
||||
|
||||
def _execute (macro, text):
|
||||
|
||||
fmt = ['#808080','','#8080ff']
|
||||
width ="100px"
|
||||
res = ""
|
||||
text = text.strip ()
|
||||
|
||||
# help if empty text
|
||||
help = len (text) == 0
|
||||
|
||||
# debug if starts with '?'
|
||||
if text.startswith ('?'):
|
||||
debug = True
|
||||
text = text [1:]
|
||||
else:
|
||||
debug = False
|
||||
orig_text = text
|
||||
|
||||
# Formats
|
||||
try:
|
||||
# Table width
|
||||
if text.startswith ('['):
|
||||
pos = text.rfind (']')
|
||||
width = text [1:pos]
|
||||
text = text [pos+1:].strip ()
|
||||
|
||||
# Cells format
|
||||
if text.startswith ('<'):
|
||||
pos = text.rfind ('>')
|
||||
f = text [1:pos].split ('><')
|
||||
text = text [pos+1:].strip ()
|
||||
fmt [:len (f)] = f
|
||||
except:
|
||||
help = True
|
||||
|
||||
# Show help
|
||||
if help:
|
||||
return """
|
||||
<p>
|
||||
<pre>%s</pre></p>
|
||||
""" % escape (usage (0))
|
||||
|
||||
# Cell formatting utility
|
||||
def cell (txt, fmt):
|
||||
if len (txt) == 0:
|
||||
fmt = 'tablewidth="%s" ' % width + fmt
|
||||
txt = "||"
|
||||
if len (fmt): t = "<%s> ||" % fmt
|
||||
else: t = " ||"
|
||||
return txt + t
|
||||
|
||||
# Progress
|
||||
if text.endswith ('%'):
|
||||
for f in fmt [0] + ' %s' % text, fmt [1] :
|
||||
res = cell (res, f)
|
||||
|
||||
# Current/Steps
|
||||
elif text.find ('/') > 0:
|
||||
cur, steps = map (int, text.split ('/'))
|
||||
for i in range (steps):
|
||||
res = cell (res, fmt [i>=cur])
|
||||
|
||||
# Start/end date
|
||||
else:
|
||||
starts, ends = map (lambda s:s.strip (), text.split (","))
|
||||
start, end = s2t (starts), s2t (ends)
|
||||
now = time.mktime (time.localtime ())
|
||||
|
||||
duration = int ( (end-start) / 86400)
|
||||
progress = int ( (now-start) / 86400) -1
|
||||
pcent = int (90 / duration)
|
||||
|
||||
for i in range (duration):
|
||||
if i == 0 and progress < 0:
|
||||
f = fmt [2]
|
||||
elif i == progress:
|
||||
f = fmt [0]
|
||||
else:
|
||||
f = fmt [1]
|
||||
res = cell (res, f)
|
||||
|
||||
if progress >= duration:
|
||||
res = cell (res, fmt [2])
|
||||
else:
|
||||
res = cell (res, fmt [1])
|
||||
|
||||
# Output
|
||||
if debug:
|
||||
res = "{{{[[ProgressBar(%s)]]\n%s}}}\n%s" % (orig_text, res, res)
|
||||
return _format (res, macro.request, macro.formatter)
|
||||
|
||||
|
||||
def _format (src_text, request, formatter):
|
||||
# parse the text (in wiki source format) and make HTML,
|
||||
# after diverting sys.stdout to a string
|
||||
str_out = StringIO.StringIO () # create str to collect output
|
||||
request.redirect (str_out) # divert output to that string
|
||||
# parse this line
|
||||
wiki.Parser (src_text, request).format (formatter)
|
||||
request.redirect () # restore output
|
||||
return str_out.getvalue () # return what was generated
|
244
wiki/macro/RandomIncludeQuote.py
Normal file
244
wiki/macro/RandomIncludeQuote.py
Normal file
|
@ -0,0 +1,244 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
"""
|
||||
MoinMoin - RandomIncludeQuote macro
|
||||
|
||||
This macro includes the formatted content of the given page(s). See
|
||||
|
||||
http://purl.net/wiki/moinmaster/HelpOnMacros/Include
|
||||
|
||||
for detailed docs.
|
||||
|
||||
@copyright: 2000-2004 by Jürgen Hermann <jh@web.de>
|
||||
@copyright: 2000-2001 by Richard Jones <richard@bizarsoftware.com.au>
|
||||
@license: GNU GPL, see COPYING for details.
|
||||
"""
|
||||
|
||||
#Dependencies = ["pages"] # included page
|
||||
Dependencies = ["time"] # works around MoinMoinBugs/TableOfContentsLacksLinks
|
||||
|
||||
import re, StringIO
|
||||
from MoinMoin import wikiutil
|
||||
from MoinMoin.Page import Page
|
||||
from MoinMoin.util import web
|
||||
|
||||
_sysmsg = '<p><strong class="%s">%s</strong></p>'
|
||||
|
||||
## keep in sync with TableOfContents macro!
|
||||
_arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
|
||||
_arg_level = r',\s*(?P<level>\d*)'
|
||||
_arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
|
||||
_arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
|
||||
_arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
|
||||
_arg_items = r'(,\s*items=(?P<items>\d+))?'
|
||||
_arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
|
||||
_arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
|
||||
_arg_editlink = r'(,\s*(?P<editlink>editlink))?'
|
||||
_args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s)?$' % (
|
||||
_arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
|
||||
_arg_skipitems, _arg_titlesonly, _arg_editlink)
|
||||
|
||||
_title_re = r"^(?P<heading>\s*(?P<hmarker>=+)\s.*\s(?P=hmarker))$"
|
||||
|
||||
def extract_titles(body, title_re):
|
||||
titles = []
|
||||
for title, _ in title_re.findall(body):
|
||||
h = title.strip()
|
||||
level = 1
|
||||
while h[level:level+1] == '=': level = level+1
|
||||
depth = min(5,level)
|
||||
title_text = h[level:-level].strip()
|
||||
titles.append((title_text, level))
|
||||
return titles
|
||||
|
||||
def execute(macro, text, args_re=re.compile(_args_re_pattern), title_re=re.compile(_title_re, re.M), called_by_toc=0):
|
||||
request = macro.request
|
||||
_ = request.getText
|
||||
|
||||
# return immediately if getting links for the current page
|
||||
if request.mode_getpagelinks:
|
||||
return ''
|
||||
|
||||
# parse and check arguments
|
||||
args = args_re.match(text)
|
||||
if not args:
|
||||
return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text,))
|
||||
|
||||
# prepare including page
|
||||
result = []
|
||||
print_mode = macro.form.has_key('action') and macro.form['action'][0] == "print"
|
||||
this_page = macro.formatter.page
|
||||
if not hasattr(this_page, '_macroInclude_pagelist'):
|
||||
this_page._macroInclude_pagelist = {}
|
||||
|
||||
# get list of pages to include
|
||||
inc_name = wikiutil.AbsPageName(request, this_page.page_name, args.group('name'))
|
||||
pagelist = [inc_name]
|
||||
if inc_name.startswith("^"):
|
||||
try:
|
||||
inc_match = re.compile(inc_name)
|
||||
except re.error:
|
||||
pass # treat as plain page name
|
||||
else:
|
||||
# Get user filtered readable page list
|
||||
pagelist = request.rootpage.getPageList(filter=inc_match.match)
|
||||
|
||||
# sort and limit page list
|
||||
pagelist.sort()
|
||||
sort_dir = args.group('sort')
|
||||
if sort_dir == 'descending':
|
||||
pagelist.reverse()
|
||||
max_items = args.group('items')
|
||||
if max_items:
|
||||
pagelist = pagelist[:int(max_items)]
|
||||
|
||||
skipitems = 0
|
||||
if args.group("skipitems"):
|
||||
skipitems = int(args.group("skipitems"))
|
||||
titlesonly = args.group('titlesonly')
|
||||
editlink = args.group('editlink')
|
||||
|
||||
# iterate over pages
|
||||
for inc_name in pagelist:
|
||||
if not request.user.may.read(inc_name):
|
||||
continue
|
||||
if this_page._macroInclude_pagelist.has_key(inc_name):
|
||||
result.append(u'<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name,))
|
||||
continue
|
||||
if skipitems:
|
||||
skipitems -= 1
|
||||
continue
|
||||
fmt = macro.formatter.__class__(request, is_included=True)
|
||||
fmt._base_depth = macro.formatter._base_depth
|
||||
inc_page = Page(request, inc_name, formatter=fmt)
|
||||
inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
|
||||
|
||||
# check for "from" and "to" arguments (allowing partial includes)
|
||||
body = inc_page.get_raw_body() + '\n'
|
||||
from_pos = 0
|
||||
to_pos = -1
|
||||
from_re = args.group('from')
|
||||
if from_re:
|
||||
try:
|
||||
from_match = re.compile(from_re, re.M).search(body)
|
||||
except re.error, e:
|
||||
##result.append("*** fe=%s ***" % e)
|
||||
from_match = re.compile(re.escape(from_re), re.M).search(body)
|
||||
if from_match:
|
||||
from_pos = from_match.end()
|
||||
else:
|
||||
result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
|
||||
to_re = args.group('to')
|
||||
if to_re:
|
||||
try:
|
||||
to_match = re.compile(to_re, re.M).search(body, from_pos)
|
||||
except re.error:
|
||||
to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
|
||||
if to_match:
|
||||
to_pos = to_match.start()
|
||||
else:
|
||||
result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
|
||||
|
||||
if titlesonly:
|
||||
newbody = []
|
||||
levelstack = []
|
||||
for title, level in extract_titles(body[from_pos:to_pos], title_re):
|
||||
if levelstack:
|
||||
if level > levelstack[-1]:
|
||||
result.append(macro.formatter.bullet_list(1))
|
||||
levelstack.append(level)
|
||||
else:
|
||||
while levelstack and level < levelstack[-1]:
|
||||
result.append(macro.formatter.bullet_list(0))
|
||||
levelstack.pop()
|
||||
if not levelstack or level != levelstack[-1]:
|
||||
result.append(macro.formatter.bullet_list(1))
|
||||
levelstack.append(level)
|
||||
else:
|
||||
result.append(macro.formatter.bullet_list(1))
|
||||
levelstack.append(level)
|
||||
result.append(macro.formatter.listitem(1))
|
||||
result.append(inc_page.link_to(request, title))
|
||||
result.append(macro.formatter.listitem(0))
|
||||
while levelstack:
|
||||
result.append(macro.formatter.bullet_list(0))
|
||||
levelstack.pop()
|
||||
continue
|
||||
|
||||
if from_pos or to_pos != -1:
|
||||
inc_page.set_raw_body(body[from_pos:to_pos], modified=True)
|
||||
##result.append("*** f=%s t=%s ***" % (from_re, to_re))
|
||||
##result.append("*** f=%d t=%d ***" % (from_pos, to_pos))
|
||||
|
||||
if called_by_toc:
|
||||
result.append(inc_page.get_raw_body())
|
||||
continue
|
||||
|
||||
if not hasattr(request, "_Include_backto"):
|
||||
request._Include_backto = this_page.page_name
|
||||
|
||||
# do headings
|
||||
level = None
|
||||
if args.group('heading') and args.group('hquote'):
|
||||
heading = args.group('htext') or inc_page.split_title(request)
|
||||
level = 1
|
||||
if args.group('level'):
|
||||
level = int(args.group('level'))
|
||||
if print_mode:
|
||||
result.append(macro.formatter.heading(1, level) +
|
||||
macro.formatter.text(heading) +
|
||||
macro.formatter.heading(0, level))
|
||||
else:
|
||||
import sha
|
||||
from MoinMoin import config
|
||||
# this heading id might produce duplicate ids,
|
||||
# if the same page is included multiple times
|
||||
# Encode stuf we feed into sha module.
|
||||
pntt = (inc_name + heading).encode(config.charset)
|
||||
hid = "head-" + sha.new(pntt).hexdigest()
|
||||
request._page_headings.setdefault(pntt, 0)
|
||||
request._page_headings[pntt] += 1
|
||||
if request._page_headings[pntt] > 1:
|
||||
hid += '-%d'%(request._page_headings[pntt],)
|
||||
result.append(
|
||||
#macro.formatter.heading(1, level, hid,
|
||||
# icons=edit_icon.replace('<img ', '<img align="right" ')) +
|
||||
macro.formatter.heading(1, level, hid) +
|
||||
inc_page.link_to(request, heading, css_class="include-heading-link") +
|
||||
macro.formatter.heading(0, level)
|
||||
)
|
||||
|
||||
# set or increment include marker
|
||||
this_page._macroInclude_pagelist[inc_name] = \
|
||||
this_page._macroInclude_pagelist.get(inc_name, 0) + 1
|
||||
|
||||
# output the included page
|
||||
strfile = StringIO.StringIO()
|
||||
request.redirect(strfile)
|
||||
try:
|
||||
cid = request.makeUniqueID("Include_%s" % wikiutil.quoteWikinameFS(inc_page.page_name))
|
||||
inc_page.send_page(request, content_only=1, content_id=cid)
|
||||
result.append(strfile.getvalue())
|
||||
finally:
|
||||
request.redirect()
|
||||
|
||||
# decrement or remove include marker
|
||||
if this_page._macroInclude_pagelist[inc_name] > 1:
|
||||
this_page._macroInclude_pagelist[inc_name] = \
|
||||
this_page._macroInclude_pagelist[inc_name] - 1
|
||||
else:
|
||||
del this_page._macroInclude_pagelist[inc_name]
|
||||
|
||||
# if no heading and not in print mode, then output a helper link
|
||||
if editlink and not (level or print_mode):
|
||||
result.extend([
|
||||
'<div class="include-link">',
|
||||
inc_page.link_to(request, '[%s]' % (inc_name,), css_class="include-page-link"),
|
||||
inc_page.link_to(request, '[%s]' % (_('edit'),), css_class="include-edit-link", querystr={'action': 'edit', 'backto': request._Include_backto}),
|
||||
'</div>',
|
||||
])
|
||||
# XXX page.link_to is wrong now, it escapes the edit_icon html as it escapes normal text
|
||||
|
||||
# return include text
|
||||
return ''.join(result)
|
||||
|
||||
# vim:ts=4:sw=4:et
|
219
wiki/macro/RandomPageInclude.py
Normal file
219
wiki/macro/RandomPageInclude.py
Normal file
|
@ -0,0 +1,219 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
#Dependencies = ["pages"] # included page
|
||||
Dependencies = ["time"] # works around MoinMoinBugs/TableOfContentsLacksLinks
|
||||
|
||||
import re, StringIO
|
||||
from MoinMoin import wikiutil, search
|
||||
from MoinMoin.Page import Page
|
||||
from MoinMoin.util import web
|
||||
from random import choice
|
||||
|
||||
_sysmsg = '<p><strong class="%s">%s</strong></p>'
|
||||
|
||||
## keep in sync with TableOfContents macro!
|
||||
_arg_heading = r'(?P<heading>,)\s*(|(?P<hquote>[\'"])(?P<htext>.+?)(?P=hquote))'
|
||||
_arg_level = r',\s*(?P<level>\d*)'
|
||||
_arg_from = r'(,\s*from=(?P<fquote>[\'"])(?P<from>.+?)(?P=fquote))?'
|
||||
_arg_to = r'(,\s*to=(?P<tquote>[\'"])(?P<to>.+?)(?P=tquote))?'
|
||||
_arg_sort = r'(,\s*sort=(?P<sort>(ascending|descending)))?'
|
||||
_arg_items = r'(,\s*items=(?P<items>\d+))?'
|
||||
_arg_skipitems = r'(,\s*skipitems=(?P<skipitems>\d+))?'
|
||||
_arg_titlesonly = r'(,\s*(?P<titlesonly>titlesonly))?'
|
||||
_arg_editlink = r'(,\s*(?P<editlink>editlink))?'
|
||||
_args_re_pattern = r'^(?P<name>[^,]+)(%s(%s)?%s%s%s%s%s%s%s)?$' % (
|
||||
_arg_heading, _arg_level, _arg_from, _arg_to, _arg_sort, _arg_items,
|
||||
_arg_skipitems, _arg_titlesonly, _arg_editlink)
|
||||
|
||||
_title_re = r"^(?P<heading>\s*(?P<hmarker>=+)\s.*\s(?P=hmarker))$"
|
||||
|
||||
def extract_titles(body, title_re):
|
||||
titles = []
|
||||
for title, _ in title_re.findall(body):
|
||||
h = title.strip()
|
||||
level = 1
|
||||
while h[level:level+1] == '=': level = level+1
|
||||
depth = min(5,level)
|
||||
title_text = h[level:-level].strip()
|
||||
titles.append((title_text, level))
|
||||
return titles
|
||||
|
||||
def execute(macro, text, args_re=re.compile(_args_re_pattern), title_re=re.compile(_title_re, re.M), called_by_toc=0):
|
||||
request = macro.request
|
||||
_ = request.getText
|
||||
|
||||
qnumber = choice(range(1, 10, 1))
|
||||
text = u'QuestionnaireCrans/Question\d+[a-z]?$,, from="^= Question =$", to="^----$"'
|
||||
|
||||
# return immediately if getting links for the current page
|
||||
if request.mode_getpagelinks:
|
||||
return ''
|
||||
|
||||
# parse and check arguments
|
||||
args = args_re.match(text)
|
||||
if not args:
|
||||
return (_sysmsg % ('error', _('Invalid include arguments "%s"!')) % (text,))
|
||||
|
||||
# Search the pages and return the results
|
||||
query = search.QueryParser(regex=1).parse_query(args.group('name'))
|
||||
results = search.searchPages(request, query)
|
||||
results.sortByPagename()
|
||||
pagelist = [results.hits[qnumber].page_name]
|
||||
|
||||
# prepare including page
|
||||
result = []
|
||||
print_mode = macro.form.has_key('action') and macro.form['action'][0] == "print"
|
||||
this_page = macro.formatter.page
|
||||
if not hasattr(this_page, '_macroInclude_pagelist'):
|
||||
this_page._macroInclude_pagelist = {}
|
||||
|
||||
skipitems = 0
|
||||
if args.group("skipitems"):
|
||||
skipitems = int(args.group("skipitems"))
|
||||
titlesonly = args.group('titlesonly')
|
||||
editlink = args.group('editlink')
|
||||
|
||||
# iterate over pages
|
||||
for inc_name in pagelist:
|
||||
if not request.user.may.read(inc_name):
|
||||
continue
|
||||
if this_page._macroInclude_pagelist.has_key(inc_name):
|
||||
result.append(u'<p><strong class="error">Recursive include of "%s" forbidden</strong></p>' % (inc_name,))
|
||||
continue
|
||||
if skipitems:
|
||||
skipitems -= 1
|
||||
continue
|
||||
fmt = macro.formatter.__class__(request, is_included=True)
|
||||
fmt._base_depth = macro.formatter._base_depth
|
||||
inc_page = Page(request, inc_name, formatter=fmt)
|
||||
inc_page._macroInclude_pagelist = this_page._macroInclude_pagelist
|
||||
|
||||
# check for "from" and "to" arguments (allowing partial includes)
|
||||
body = inc_page.get_raw_body() + '\n'
|
||||
from_pos = 0
|
||||
to_pos = -1
|
||||
from_re = args.group('from')
|
||||
if from_re:
|
||||
try:
|
||||
from_match = re.compile(from_re, re.M).search(body)
|
||||
except re.error, e:
|
||||
##result.append("*** fe=%s ***" % e)
|
||||
from_match = re.compile(re.escape(from_re), re.M).search(body)
|
||||
if from_match:
|
||||
from_pos = from_match.end()
|
||||
else:
|
||||
result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % from_re)
|
||||
to_re = args.group('to')
|
||||
if to_re:
|
||||
try:
|
||||
to_match = re.compile(to_re, re.M).search(body, from_pos)
|
||||
except re.error:
|
||||
to_match = re.compile(re.escape(to_re), re.M).search(body, from_pos)
|
||||
if to_match:
|
||||
to_pos = to_match.start()
|
||||
else:
|
||||
result.append(_sysmsg % ('warning', 'Include: ' + _('Nothing found for "%s"!')) % to_re)
|
||||
|
||||
if titlesonly:
|
||||
newbody = []
|
||||
levelstack = []
|
||||
for title, level in extract_titles(body[from_pos:to_pos], title_re):
|
||||
if levelstack:
|
||||
if level > levelstack[-1]:
|
||||
result.append(macro.formatter.bullet_list(1))
|
||||
levelstack.append(level)
|
||||
else:
|
||||
while levelstack and level < levelstack[-1]:
|
||||
result.append(macro.formatter.bullet_list(0))
|
||||
levelstack.pop()
|
||||
if not levelstack or level != levelstack[-1]:
|
||||
result.append(macro.formatter.bullet_list(1))
|
||||
levelstack.append(level)
|
||||
else:
|
||||
result.append(macro.formatter.bullet_list(1))
|
||||
levelstack.append(level)
|
||||
result.append(macro.formatter.listitem(1))
|
||||
result.append(inc_page.link_to(request, title))
|
||||
result.append(macro.formatter.listitem(0))
|
||||
while levelstack:
|
||||
result.append(macro.formatter.bullet_list(0))
|
||||
levelstack.pop()
|
||||
continue
|
||||
|
||||
if from_pos or to_pos != -1:
|
||||
inc_page.set_raw_body(body[from_pos:to_pos], modified=True)
|
||||
##result.append("*** f=%s t=%s ***" % (from_re, to_re))
|
||||
##result.append("*** f=%d t=%d ***" % (from_pos, to_pos))
|
||||
|
||||
if called_by_toc:
|
||||
result.append(inc_page.get_raw_body())
|
||||
continue
|
||||
|
||||
if not hasattr(request, "_Include_backto"):
|
||||
request._Include_backto = this_page.page_name
|
||||
|
||||
# do headings
|
||||
level = None
|
||||
if args.group('heading') and args.group('hquote'):
|
||||
heading = args.group('htext') or inc_page.split_title(request)
|
||||
level = 1
|
||||
if args.group('level'):
|
||||
level = int(args.group('level'))
|
||||
if print_mode:
|
||||
result.append(macro.formatter.heading(1, level) +
|
||||
macro.formatter.text(heading) +
|
||||
macro.formatter.heading(0, level))
|
||||
else:
|
||||
import sha
|
||||
from MoinMoin import config
|
||||
# this heading id might produce duplicate ids,
|
||||
# if the same page is included multiple times
|
||||
# Encode stuf we feed into sha module.
|
||||
pntt = (inc_name + heading).encode(config.charset)
|
||||
hid = "head-" + sha.new(pntt).hexdigest()
|
||||
request._page_headings.setdefault(pntt, 0)
|
||||
request._page_headings[pntt] += 1
|
||||
if request._page_headings[pntt] > 1:
|
||||
hid += '-%d'%(request._page_headings[pntt],)
|
||||
result.append(
|
||||
#macro.formatter.heading(1, level, hid,
|
||||
# icons=edit_icon.replace('<img ', '<img align="right" ')) +
|
||||
macro.formatter.heading(1, level, hid) +
|
||||
inc_page.link_to(request, heading, css_class="include-heading-link") +
|
||||
macro.formatter.heading(0, level)
|
||||
)
|
||||
|
||||
# set or increment include marker
|
||||
this_page._macroInclude_pagelist[inc_name] = \
|
||||
this_page._macroInclude_pagelist.get(inc_name, 0) + 1
|
||||
|
||||
# output the included page
|
||||
strfile = StringIO.StringIO()
|
||||
request.redirect(strfile)
|
||||
try:
|
||||
cid = request.makeUniqueID("Include_%s" % wikiutil.quoteWikinameFS(inc_page.page_name))
|
||||
inc_page.send_page(request, content_only=1, content_id=cid)
|
||||
result.append(strfile.getvalue())
|
||||
finally:
|
||||
request.redirect()
|
||||
|
||||
# decrement or remove include marker
|
||||
if this_page._macroInclude_pagelist[inc_name] > 1:
|
||||
this_page._macroInclude_pagelist[inc_name] = \
|
||||
this_page._macroInclude_pagelist[inc_name] - 1
|
||||
else:
|
||||
del this_page._macroInclude_pagelist[inc_name]
|
||||
|
||||
# if no heading and not in print mode, then output a helper link
|
||||
if editlink and not (level or print_mode):
|
||||
result.extend([
|
||||
'<div class="include-link">',
|
||||
inc_page.link_to(request, '[%s]' % (inc_name,), css_class="include-page-link"),
|
||||
inc_page.link_to(request, '[%s]' % (_('edit'),), css_class="include-edit-link", querystr={'action': 'edit', 'backto': request._Include_backto}),
|
||||
'</div>',
|
||||
])
|
||||
# XXX page.link_to is wrong now, it escapes the edit_icon html as it escapes normal text
|
||||
|
||||
# return include text
|
||||
return ''.join(result)
|
||||
|
||||
# vim:ts=4:sw=4:et
|
57
wiki/macro/RandomQuoteNum.py
Normal file
57
wiki/macro/RandomQuoteNum.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: iso-8859-1 -*-
|
||||
"""
|
||||
MoinMoin - RandomQuote Macro
|
||||
|
||||
Selects a random quote from FortuneCookies or a given page.
|
||||
|
||||
Usage:
|
||||
[[RandomQuote()]]
|
||||
[[RandomQuote(WikiTips)]]
|
||||
|
||||
Comments:
|
||||
It will look for list delimiters on the page in question.
|
||||
It will ignore anything that is not in an "*" list.
|
||||
|
||||
@copyright: 2002-2004 by Jürgen Hermann <jh@web.de>
|
||||
@license: GNU GPL, see COPYING for details.
|
||||
|
||||
Originally written by Thomas Waldmann.
|
||||
Gustavo Niemeyer added wiki markup parsing of the quotes.
|
||||
"""
|
||||
|
||||
import random, StringIO
|
||||
from MoinMoin.Page import Page, wikiutil
|
||||
|
||||
Dependencies = ["time"]
|
||||
|
||||
def execute(macro, args):
|
||||
_ = macro.request.getText
|
||||
|
||||
pagename = args or 'FortuneCookies'
|
||||
if macro.request.user.may.read(pagename):
|
||||
page = Page(macro.request, pagename)
|
||||
raw = page.get_raw_body()
|
||||
else:
|
||||
raw = ""
|
||||
|
||||
# this selects lines looking like a list item
|
||||
# !!! TODO: make multi-line quotes possible (optionally split by "----" or something)
|
||||
quotes = raw.splitlines()
|
||||
quotes = [quote.strip() for quote in quotes]
|
||||
quotes = [quote[2:] for quote in quotes if quote.startswith('1. ')]
|
||||
|
||||
if not quotes:
|
||||
return (macro.formatter.highlight(1) +
|
||||
_('No quotes on %(pagename)s.') % {'pagename': pagename} +
|
||||
macro.formatter.highlight(0))
|
||||
|
||||
quote = random.choice(quotes)
|
||||
page.set_raw_body(quote, 1)
|
||||
out = StringIO.StringIO()
|
||||
macro.request.redirect(out)
|
||||
page.send_page(macro.request, content_only=1, content_id="RandomQuote_%s" % wikiutil.quoteWikinameFS(page.page_name) )
|
||||
quote = out.getvalue()
|
||||
macro.request.redirect()
|
||||
|
||||
return quote
|
||||
|
44
wiki/macro/latex.py
Normal file
44
wiki/macro/latex.py
Normal file
|
@ -0,0 +1,44 @@
|
|||
#FORMAT python
|
||||
"""
|
||||
See the latex parser, this is just a thin wrapper around it.
|
||||
"""
|
||||
# Imports
|
||||
from MoinMoin import wikiutil
|
||||
import re
|
||||
|
||||
Dependencies = []
|
||||
|
||||
splitre = re.compile(r'([^\\])%')
|
||||
|
||||
class latex:
|
||||
def __init__(self, macro, args):
|
||||
self.macro = macro
|
||||
self.formatter = macro.formatter
|
||||
self.text = args
|
||||
|
||||
def renderInPage(self):
|
||||
# return immediately if getting links for the current page
|
||||
if self.macro.request.mode_getpagelinks:
|
||||
return ''
|
||||
|
||||
if self.text is None: # macro call without parameters
|
||||
return ''
|
||||
|
||||
# get an exception? for moin before 1.3.2 use the following line instead:
|
||||
# L = wikiutil.importPlugin('parser', 'latex', 'Parser', self.macro.cfg.data_dir)
|
||||
L = wikiutil.importPlugin(self.macro.cfg, 'parser', 'latex', 'Parser')
|
||||
if L is None:
|
||||
return self.formatter.text("<<please install the latex parser>>")
|
||||
l = L('', self.macro.request)
|
||||
tmp = splitre.split(self.text, 1)
|
||||
if len(tmp) == 3:
|
||||
prologue,p2,tex=tmp
|
||||
prologue += p2
|
||||
else:
|
||||
prologue = ''
|
||||
tex = tmp[0]
|
||||
return l.get(self.formatter, tex, prologue)
|
||||
|
||||
|
||||
def execute(macro, args):
|
||||
return latex(macro, args).renderInPage()
|
Loading…
Add table
Add a link
Reference in a new issue