1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361
|
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# pythondemo — demo Python ikiwiki plugin
#
# Copyright © martin f. krafft <madduck@madduck.net>
# Released under the terms of the GNU GPL version 2
#
__name__ = 'pythondemo'
__description__ = 'demo Python ikiwiki plugin'
__version__ = '0.1'
__author__ = 'martin f. krafft <madduck@madduck.net>'
__copyright__ = 'Copyright © ' + __author__
__licence__ = 'GPLv2'
from proxy import IkiWikiProcedureProxy
import sys
def debug(s):
sys.stderr.write(__name__ + ':DEBUG:%s\n' % s)
sys.stderr.flush()
proxy = IkiWikiProcedureProxy(__name__, debug_fn=None)
def _arglist_to_dict(args):
if len(args) % 2 != 0:
raise ValueError, 'odd number of arguments, cannot convert to dict'
return dict([args[i:i+2] for i in xrange(0, len(args), 2)])
def getopt_demo(proxy, *args):
# This allows for plugins to perform their own processing of command-line
# options and so add options to the ikiwiki command line. It's called
# during command line processing, with @ARGV full of any options that
# ikiwiki was not able to process on its own. The function should process
# any options it can, removing them from @ARGV, and probably recording the
# configuration settings in %config. It should take care not to abort if
# it sees an option it cannot process, and should just skip over those
# options and leave them in @ARGV.
#
debug("hook `getopt' called with arguments %s" % str(args))
args = proxy.getargv()
if '--demo' in args:
args = [i for i in args if i != '--demo']
proxy.setargv(args)
proxy.hook('getopt', getopt_demo)
def checkconfig_demo(proxy, *args):
# This is useful if the plugin needs to check for or modify ikiwiki's
# configuration. It's called early in the startup process. The function is
# passed no values. It's ok for the function to call error() if something
# isn't configured right.
debug("hook `checkconfig' called with arguments %s" % str(args))
# check that --url has been set
url = proxy.getvar('config', 'url')
if url is None or len(url) == 0:
proxy.error('--url has not been set')
proxy.hook('checkconfig', checkconfig_demo)
def refresh_demo(proxy, *args):
# This hook is called just before ikiwiki scans the wiki for changed
# files. It's useful for plugins that need to create or modify a source
# page. The function is passed no values.
debug("hook `refresh' called with arguments %s" % str(args))
proxy.hook('refresh', refresh_demo)
def needsbuild_demo(proxy, *args):
# This allows a plugin to manipulate the list of files that need to be
# built when the wiki is refreshed. The function is passed a reference to
# an array of pages that will be rebuilt, and can modify the array, either
# adding or removing files from it.
# TODO: how do we modify the array? Joey sees no solution...
# we could just return the array and expect ikiwiki to use that...
debug("hook `needsbuild' called with arguments %s" % str(args))
raise NotImplementedError
#proxy.hook('needsbuild', needsbuild_demo)
def filter_demo(proxy, *args):
# Runs on the raw source of a page, before anything else touches it, and
# can make arbitrary changes. The function is passed named parameters
# "page", "destpage", and "content". It should return the filtered
# content.
kwargs = _arglist_to_dict(args)
debug("hook `filter' called with arguments %s" % kwargs);
return kwargs['content']
proxy.hook('filter', filter_demo)
def preprocess_demo(proxy, *args):
# Each time the directive is processed, the referenced function
# (preprocess in the example above) is called, and is passed named
# parameters. A "page" parameter gives the name of the page that embedded
# the preprocessor directive, while a "destpage" parameter gives the name
# of the page the content is going to (different for inlined pages), and
# a "preview" parameter is set to a true value if the page is being
# previewed. All parameters included in the directive are included as
# named parameters as well. Whatever the function returns goes onto the
# page in place of the directive.
#
# An optional "scan" parameter, if set to a true value, makes the hook be
# called during the preliminary scan that ikiwiki makes of updated pages,
# before begining to render pages. This parameter should be set to true if
# the hook modifies data in %links. Note that doing so will make the hook
# be run twice per page build, so avoid doing it for expensive hooks. (As
# an optimisation, if your preprocessor hook is called in a void contets,
# you can assume it's being run in scan mode.)
#
# Note that if the htmlscrubber is enabled, html in PreProcessorDirective
# output is sanitised, which may limit what your plugin can do. Also, the
# rest of the page content is not in html format at preprocessor time.
# Text output by a preprocessor directive will be linkified and passed
# through markdown (or whatever engine is used to htmlize the page) along
# with the rest of the page.
#
kwargs = _arglist_to_dict(args)
debug("hook `preprocess' called with arguments %s" % kwargs)
del kwargs['preview']
del kwargs['page']
del kwargs['destpage']
ret = 'foobar preprocessor called with arguments:'
for i in kwargs.iteritems():
ret += ' %s=%s' % i
return ret
# put [[!foobar ...]] somewhere to try this
proxy.hook('preprocess', preprocess_demo, id='foobar')
def linkify_demo(proxy, *args):
# This hook is called to convert WikiLinks on the page into html links.
# The function is passed named parameters "page", "destpage", and
# "content". It should return the linkified content.
#
# Plugins that implement linkify must also implement a scan hook, that
# scans for the links on the page and adds them to %links.
kwargs = _arglist_to_dict(args)
debug("hook `linkify' called with arguments %s" % kwargs)
return kwargs['content']
proxy.hook('linkify', linkify_demo)
def scan_demo(proxy, *args):
# This hook is called early in the process of building the wiki, and is
# used as a first pass scan of the page, to collect metadata about the
# page. It's mostly used to scan the page for WikiLinks, and add them to
# %links.
#
# The function is passed named parameters "page" and "content". Its return
# value is ignored.
#
kwargs = _arglist_to_dict(args)
debug("hook `scan' called with arguments %s" % kwargs)
links = proxy.getvar('links', kwargs['page'])
debug("links for page `%s' are: %s" % (kwargs['page'], links))
proxy.setvar('links', kwargs['page'], links)
proxy.hook('scan', scan_demo)
def htmlize_demo(proxy, *args):
# Runs on the raw source of a page and turns it into html. The id
# parameter specifies the filename extension that a file must have to be
# htmlized using this plugin. This is how you can add support for new and
# exciting markup languages to ikiwiki.
#
# The function is passed named parameters: "page" and "content" and should
# return the htmlized content.
kwargs = _arglist_to_dict(args)
debug("hook `htmlize' called with arguments %s" % kwargs)
return kwargs['content']
proxy.hook('htmlize', htmlize_demo)
def pagetemplate_demo(proxy, *args):
# Templates are filled out for many different things in ikiwiki, like
# generating a page, or part of a blog page, or an rss feed, or a cgi.
# This hook allows modifying the variables available on those templates.
# The function is passed named parameters. The "page" and "destpage"
# parameters are the same as for a preprocess hook. The "template"
# parameter is a HTML::Template object that is the template that will be
# used to generate the page. The function can manipulate that template
# object.
#
# The most common thing to do is probably to call $template->param() to
# add a new custom parameter to the template.
# TODO: how do we call $template->param()?
kwargs = _arglist_to_dict(args)
debug("hook `pagetemplate' called with arguments %s" % kwargs)
raise NotImplementedError
#proxy.hook('pagetemplate', pagetemplate_demo)
def templatefile_demo(proxy, *args):
# This hook allows plugins to change the template that is used for a page
# in the wiki. The hook is passed a "page" parameter, and should return
# the name of the template file to use, or undef if it doesn't want to
# change the default ("page.tmpl"). Template files are looked for in
# /usr/share/ikiwiki/templates by default.
#
kwargs = _arglist_to_dict(args)
debug("hook `templatefile' called with arguments %s" % kwargs)
return None #leave the default
proxy.hook('templatefile', templatefile_demo)
def sanitize_demo(proxy, *args):
# Use this to implement html sanitization or anything else that needs to
# modify the body of a page after it has been fully converted to html.
#
# The function is passed named parameters: "page" and "content", and
# should return the sanitized content.
kwargs = _arglist_to_dict(args)
debug("hook `sanitize' called with arguments %s" % kwargs)
return kwargs['content']
proxy.hook('sanitize', sanitize_demo)
def format_demo(proxy, *args):
# The difference between format and sanitize is that sanitize only acts on
# the page body, while format can modify the entire html page including
# the header and footer inserted by ikiwiki, the html document type, etc.
#
# The function is passed named parameters: "page" and "content", and
# should return the formatted content.
kwargs = _arglist_to_dict(args)
debug("hook `format' called with arguments %s" % kwargs)
return kwargs['content']
proxy.hook('format', format_demo)
def delete_demo(proxy, *args):
# Each time a page or pages is removed from the wiki, the referenced
# function is called, and passed the names of the source files that were
# removed.
debug("hook `delete' called with arguments %s" % str(args))
proxy.hook('delete', delete_demo)
def change_demo(proxy, *args):
# Each time ikiwiki renders a change or addition (but not deletion) to the
# wiki, the referenced function is called, and passed the names of the
# source files that were rendered.
debug("hook `change' called with arguments %s" % str(args))
proxy.hook('change', change_demo)
def cgi_demo(proxy, *args):
# Use this to hook into ikiwiki's cgi script. Each registered cgi hook is
# called in turn, and passed a CGI object. The hook should examine the
# parameters, and if it will handle this CGI request, output a page
# (including the http headers) and terminate the program.
#
# Note that cgi hooks are called as early as possible, before any ikiwiki
# state is loaded, and with no session information.
debug("hook `cgi' called with arguments %s" % str(args))
raise NotImplementedError
#proxy.hook('cgi', cgi_demo)
def auth_demo(proxy, *args):
# This hook can be used to implement a different authentication method
# than the standard web form. When a user needs to be authenticated, each
# registered auth hook is called in turn, and passed a CGI object and
# a session object.
#
# If the hook is able to authenticate the user, it should set the session
# object's "name" parameter to the authenticated user's name. Note that if
# the name is set to the name of a user who is not registered, a basic
# registration of the user will be automatically performed.
#
# TODO: how do we set the session parameter?
debug("hook `auth' called with arguments %s" % str(args))
raise NotImplementedError
#proxy.hook('auth', auth_demo)
def sessioncgi_demo(proxy, *args):
# Unlike the cgi hook, which is run as soon as possible, the sessioncgi
# hook is only run once a session object is available. It is passed both
# a CGI object and a session object. To check if the user is in fact
# signed in, you can check if the session object has a "name" parameter
# set.
debug("hook `sessioncgi' called with arguments %s" % str(args))
raise NotImplementedError
#proxy.hook('sessioncgi', sessioncgi_demo)
def canedit_demo(proxy, *args):
# This hook can be used to implement arbitrary access methods to control
# when a page can be edited using the web interface (commits from revision
# control bypass it). When a page is edited, each registered canedit hook
# is called in turn, and passed the page name, a CGI object, and a session
# object.
#
# If the hook has no opinion about whether the edit can proceed, return
# undef, and the next plugin will be asked to decide. If edit can proceed,
# the hook should return "". If the edit is not allowed by this hook, the
# hook should return an error message for the user to see, or a function
# that can be run to log the user in or perform other action necessary for
# them to be able to edit the page.
#
# This hook should avoid directly redirecting the user to a signin page,
# since it's sometimes used to test to see which pages in a set of pages
# a user can edit.
#
# TODO: how do we return a function?
debug("hook `canedit' called with arguments %s" % str(args))
raise NotImplementedError
#proxy.hook('canedit', canedit_demo)
def editcontent_demo(proxy, *args):
# This hook is called when a page is saved (or previewed) using the web
# interface. It is passed named parameters: content, page, cgi, and
# session. These are, respectively, the new page content as entered by the
# user, the page name, a CGI object, and the user's CGI::Session.
#
# It can modify the content as desired, and should return the content.
kwargs = _arglist_to_dict(args)
debug("hook `editcontent' called with arguments %s" % kwargs)
return kwargs['content']
proxy.hook('editcontent', editcontent_demo)
def formbuilder_setup_demo(proxy, *args):
# These hooks allow tapping into the parts of ikiwiki that use
# CGI::FormBuilder to generate web forms. These hooks are passed named
# parameters: cgi, session, form, and buttons. These are, respectively,
# the CGI object, the user's CGI::Session, a CGI::FormBuilder, and
# a reference to an array of names of buttons to go on the form.
#
# Each time a form is set up, the formbuilder_setup hook is called.
# Typically the formbuilder_setup hook will check the form's title, and if
# it's a form that it needs to modify, will call various methods to
# add/remove/change fields, tweak the validation code for the fields, etc.
# It will not validate or display the form.
#
# Just before a form is displayed to the user, the formbuilder hook is
# called. It can be used to validate the form, but should not display it.
#
# TODO: how do we modify the form?
kwargs = _arglist_to_dict(args)
debug("hook `formbuilder_setup' called with arguments %s" % kwargs)
raise NotImplementedError
return kwargs['content']
#proxy.hook('formbuilder_setup', formbuilder_setup_demo)
def formbuilder_demo(proxy, *args):
# These hooks allow tapping into the parts of ikiwiki that use
# CGI::FormBuilder to generate web forms. These hooks are passed named
# parameters: cgi, session, form, and buttons. These are, respectively,
# the CGI object, the user's CGI::Session, a CGI::FormBuilder, and
# a reference to an array of names of buttons to go on the form.
#
# Each time a form is set up, the formbuilder_setup hook is called.
# Typically the formbuilder_setup hook will check the form's title, and if
# it's a form that it needs to modify, will call various methods to
# add/remove/change fields, tweak the validation code for the fields, etc.
# It will not validate or display the form.
#
# Just before a form is displayed to the user, the formbuilder hook is
# called. It can be used to validate the form, but should not display it.
# TODO: how do we modify the form?
kwargs = _arglist_to_dict(args)
debug("hook `formbuilder' called with arguments %s" % kwargs)
raise NotImplementedError
return kwargs['content']
#proxy.hook('formbuilder', formbuilder_demo)
def savestate_demo(proxy, *args):
# This hook is called wheneven ikiwiki normally saves its state, just
# before the state is saved. The function can save other state, modify
# values before they're saved, etc.
#
# TODO: how?
debug("hook `savestate' called with arguments %s" % str(args))
raise NotImplementedError
#proxy.hook('savestate', savestate_demo)
proxy.run()
|