569 lines
22 KiB
Markdown
569 lines
22 KiB
Markdown
Ikiwiki's plugin interface allows all kinds of useful [[plugins]] to be
|
|
written to extend ikiwiki in many ways. Despite the length of this page,
|
|
it's not really hard. This page is a complete reference to everything a
|
|
plugin might want to do. There is also a quick [[tutorial]].
|
|
|
|
[[toc levels=2]]
|
|
|
|
## Types of plugins
|
|
|
|
Most ikiwiki [[plugins]] are written in perl, like ikiwiki. This gives the
|
|
plugin full access to ikiwiki's internals, and is the most efficient.
|
|
However, plugins can actually be written in any language that supports XML
|
|
RPC. These are called [[external]] plugins.
|
|
|
|
A plugin written in perl is a perl module, in the `IkiWiki::Plugin`
|
|
namespace. The name of the plugin is typically in lowercase, such as
|
|
`IkiWiki::Plugin::inline`. Ikiwiki includes a `IkiWiki::Plugin::skeleton`
|
|
that can be fleshed out to make a useful plugin.
|
|
`IkiWiki::Plugin::pagecount` is another simple example. All perl plugins
|
|
should `use IkiWiki` to import the ikiwiki plugin interface. It's a good
|
|
idea to include the version number of the plugin interface that your plugin
|
|
expects: `use IkiWiki 2.00`.
|
|
|
|
An external plugin is an executable program. It can be written in any
|
|
language. Its interface to ikiwiki is via XML RPC, which it reads from
|
|
ikiwiki on its standard input, and writes to ikiwiki on its standard
|
|
output. For more details on writing external plugins, see [[external]].
|
|
|
|
Despite these two types of plugins having such different interfaces,
|
|
they're the same as far as how they hook into ikiwiki. This document will
|
|
explain how to write both sorts of plugins, albeit with an emphasis on perl
|
|
plugins.
|
|
|
|
## Considerations
|
|
|
|
One thing to keep in mind when writing a plugin is that ikiwiki is a wiki
|
|
*compiler*. So plugins influence pages when they are built, not when they
|
|
are loaded. A plugin that inserts the current time into a page, for
|
|
example, will insert the build time. Also, as a compiler, ikiwiki avoids
|
|
rebuilding pages unless they have changed, so a plugin that prints some
|
|
random or changing thing on a page will generate a static page that won't
|
|
change until ikiwiki rebuilds the page for some other reason, like the page
|
|
being edited.
|
|
|
|
## Registering plugins
|
|
|
|
Plugins should, when imported, call `hook()` to hook into ikiwiki's
|
|
processing. The function uses named parameters, and use varies depending on
|
|
the type of hook being registered -- see below. Note that a plugin can call
|
|
the function more than once to register multiple hooks. All calls to
|
|
`hook()` should be passed a "type" parameter, which gives the type of
|
|
hook, a "id" paramter, which should be a unique string for this plugin, and
|
|
a "call" parameter, which tells what function to call for the hook.
|
|
|
|
An optional "last" parameter, if set to a true value, makes the hook run
|
|
after all other hooks of its type. Useful if the hook depends on some other
|
|
hook being run first.
|
|
|
|
## Types of hooks
|
|
|
|
In roughly the order they are called.
|
|
|
|
### getopt
|
|
|
|
hook(type => "getopt", id => "foo", call => \&getopt);
|
|
|
|
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.
|
|
|
|
### checkconfig
|
|
|
|
hook(type => "checkconfig", id => "foo", call => \&checkconfig);
|
|
|
|
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.
|
|
|
|
### refresh
|
|
|
|
hook(type => "refresh", id => "foo", call => \&refresh);
|
|
|
|
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.
|
|
|
|
### needsbuild
|
|
|
|
hook(type => "needsbuild", id => "foo", call => \&needsbuild);
|
|
|
|
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.
|
|
|
|
### filter
|
|
|
|
hook(type => "filter", id => "foo", call => \&filter);
|
|
|
|
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.
|
|
|
|
### preprocess
|
|
|
|
Adding a [[ikiwiki/PreProcessorDirective]] is probably the most common use
|
|
of a plugin.
|
|
|
|
hook(type => "preprocess", id => "foo", call => \&preprocess);
|
|
|
|
Replace "foo" with the command name that will be used inside brackets for
|
|
the preprocessor directive.
|
|
|
|
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
|
|
[[ikiwiki/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.
|
|
|
|
### htmlize
|
|
|
|
hook(type => "htmlize", id => "ext", call => \&htmlize);
|
|
|
|
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.
|
|
|
|
### pagetemplate
|
|
|
|
hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
|
|
|
|
[[Templates|wikitemplates]] 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 [[cpan 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.
|
|
|
|
### templatefile
|
|
|
|
hook(type => "templatefile", id => "foo", call => \&templatefile);
|
|
|
|
This hook allows plugins to change the [[template|wikitemplates]] 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.
|
|
|
|
### sanitize
|
|
|
|
hook(type => "sanitize", id => "foo", call => \&sanitize);
|
|
|
|
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.
|
|
|
|
### format
|
|
|
|
hook(type => "format", id => "foo", call => \&format);
|
|
|
|
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.
|
|
|
|
### delete
|
|
|
|
hook(type => "delete", id => "foo", call => \&delete);
|
|
|
|
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.
|
|
|
|
### change
|
|
|
|
hook(type => "change", id => "foo", call => \&render);
|
|
|
|
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.
|
|
|
|
### cgi
|
|
|
|
hook(type => "cgi", id => "foo", call => \&cgi);
|
|
|
|
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.
|
|
|
|
### auth
|
|
|
|
hook(type => "auth", id => "foo", call => \&auth);
|
|
|
|
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.
|
|
|
|
### sessioncgi
|
|
|
|
hook(type => "sessioncgi", id => "foo", call => \&sessioncgi);
|
|
|
|
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.
|
|
|
|
### canedit
|
|
|
|
hook(type => "canedit", id => "foo", call => \&pagelocked);
|
|
|
|
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.
|
|
|
|
### editcontent
|
|
|
|
hook(type => "editcontent", id => "foo", call => \&editcontent);
|
|
|
|
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.
|
|
|
|
### formbuilder
|
|
|
|
hook(type => "formbuilder_setup", id => "foo", call => \&formbuilder_setup);
|
|
hook(type => "formbuilder", id => "foo", call => \&formbuilder);
|
|
|
|
These hooks allow tapping into the parts of ikiwiki that use [[cpan
|
|
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.
|
|
|
|
### savestate
|
|
|
|
hook(type => "savestate", id => "foo", call => \&savestate);
|
|
|
|
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.
|
|
|
|
## Plugin interface
|
|
|
|
To import the ikiwiki plugin interface:
|
|
|
|
use IkiWiki '1.00';
|
|
|
|
This will import several variables and functions into your plugin's
|
|
namespace. These variables and functions are the ones most plugins need,
|
|
and a special effort will be made to avoid changing them in incompatible
|
|
ways, and to document any changes that have to be made in the future.
|
|
|
|
Note that IkiWiki also provides other variables and functions that are not
|
|
exported by default. No guarantee is made about these in the future, so if
|
|
it's not exported, the wise choice is to not use it.
|
|
|
|
### %config
|
|
|
|
A plugin can access the wiki's configuration via the `%config`
|
|
hash. The best way to understand the contents of the hash is to look at
|
|
[[ikiwiki.setup]], which sets the hash content to configure the wiki.
|
|
|
|
### %pagestate
|
|
|
|
The `%pagestate` hash can be used by plugins to save state that they will need
|
|
next time ikiwiki is run. The hash holds per-page state, so to set a value,
|
|
use `%pagestate{$page}{$id}{$key}=$value`, and to retrieve the value,
|
|
use `%pagestate{$page}{$id}{$key}`.
|
|
|
|
`$key` can be any string you like, but `$id` must be the same as the "id"
|
|
parameter passed to `hook()` when registering the plugin. This is so
|
|
ikiwiki can know when to delete pagestate for plugins that are no longer
|
|
used.
|
|
|
|
When pages are deleted, ikiwiki automatically deletes their pagestate too.
|
|
|
|
Note that page state does not persist across wiki rebuilds, only across
|
|
wiki updates.
|
|
|
|
### Other variables
|
|
|
|
If your plugin needs to access data about other pages in the wiki. It can
|
|
use the following hashes, using a page name as the key:
|
|
|
|
* `%links` lists the names of each page that a page links to, in an array
|
|
reference.
|
|
* `%destsources` contains the name of the source file used to create each
|
|
destination file.
|
|
* `%pagesources` contains the name of the source file for each page.
|
|
|
|
Also, the %IkiWiki::version variable contains the version number for the
|
|
ikiwiki program.
|
|
|
|
### Library functions
|
|
|
|
#### `hook(@)`
|
|
|
|
Hook into ikiwiki's processing. See the discussion of hooks above.
|
|
|
|
Note that in addition to the named parameters described above, a parameter
|
|
named `no_override` is supported, If it's set to a true value, then this hook
|
|
will not override any existing hook with the same id. This is useful if
|
|
the id can be controled by the user.
|
|
|
|
#### `debug($)`
|
|
|
|
Logs a debugging message. These are supressed unless verbose mode is turned
|
|
on.
|
|
|
|
#### `error($;$)`
|
|
|
|
Aborts with an error message. If the second parameter is passed, it is a
|
|
function that is called after the error message is printed, to do any final
|
|
cleanup.
|
|
|
|
Note that while any plugin can use this for a fatal error, plugins should
|
|
try to avoid dying on bad input, as that will halt the entire wiki build
|
|
and make the wiki unusable. So for example, if a
|
|
[[ikiwiki/PreProcessorDirective]] is passed bad parameters, it's better to
|
|
return an error message, which can appear on the wiki page, rather than
|
|
calling error().
|
|
|
|
#### `template($;@)`
|
|
|
|
Creates and returns a [[cpan HTML::Template]] object. The first parameter
|
|
is the name of the file in the template directory. The optional remaining
|
|
parameters are passed to `HTML::Template->new`.
|
|
|
|
#### `htmlpage($)`
|
|
|
|
Passed a page name, returns the base name that will be used for a the html
|
|
page created from it. (Ie, it appends ".html".)
|
|
|
|
#### `add_depends($$)`
|
|
|
|
Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
|
|
|
|
#### `pagespec_match($$;@)`
|
|
|
|
Passed a page name, and [[ikiwiki/PageSpec]], returns true if the
|
|
[[ikiwiki/PageSpec]] matches the page.
|
|
|
|
Additional named parameters can be passed, to further limit the match.
|
|
The most often used is "location", which specifies the location the
|
|
PageSpec should match against. If not passed, relative PageSpecs will match
|
|
relative to the top of the wiki.
|
|
|
|
#### `bestlink($$)`
|
|
|
|
Given a page and the text of a link on the page, determine which
|
|
existing page that link best points to. Prefers pages under a
|
|
subdirectory with the same name as the source page, failing that
|
|
goes down the directory tree to the base looking for matching
|
|
pages, as described in [[ikiwiki/SubPage/LinkingRules]].
|
|
|
|
#### `htmllink($$$;@)`
|
|
|
|
Many plugins need to generate html links and add them to a page. This is
|
|
done by using the `htmllink` function. The usual way to call
|
|
`htmlllink` is:
|
|
|
|
htmllink($page, $page, $link)
|
|
|
|
Why is `$page` repeated? Because if a page is inlined inside another, and a
|
|
link is placed on it, the right way to make that link is actually:
|
|
|
|
htmllink($page, $destpage, $link)
|
|
|
|
Here `$destpage` is the inlining page. A `destpage` parameter is passed to
|
|
some of the hook functions above; the ones that are not passed it are not used
|
|
during inlining and don't need to worry about this issue.
|
|
|
|
After the three required parameters, named parameters can be used to
|
|
control some options. These are:
|
|
|
|
* noimageinline - set to true to avoid turning links into inline html images
|
|
* forcesubpage - set to force a link to a subpage
|
|
* linktext - set to force the link text to something
|
|
* anchor - set to make the link include an anchor
|
|
* rel - set to add a rel attribute to the link
|
|
* class - set to add a css class to the link
|
|
|
|
#### `readfile($;$)`
|
|
|
|
Given a filename, reads and returns the entire file.
|
|
|
|
The optional second parameter, if set to a true value, makes the file be read
|
|
in binary mode.
|
|
|
|
A failure to read the file will result in it dying with an error.
|
|
|
|
#### `writefile($$$;$$)`
|
|
|
|
Given a filename, a directory to put it in, and the file's content,
|
|
writes a file.
|
|
|
|
The optional fourth parameter, if set to a true value, makes the file be
|
|
written in binary mode.
|
|
|
|
The optional fifth parameter can be used to pass a function reference that
|
|
will be called to handle writing to the file. The function will be called
|
|
and passed a file descriptor it should write to, and an error recovery
|
|
function it should call if the writing fails. (You will not normally need to
|
|
use this interface.)
|
|
|
|
A failure to write the file will result in it dying with an error.
|
|
|
|
If the destination directory doesn't exist, it will first be created.
|
|
|
|
#### `will_render($$)`
|
|
|
|
Given a page name and a destination file name (not including the base
|
|
destination directory), register that the page will result in that file
|
|
being rendered. It's important to call this before writing to any file in
|
|
the destination directory.
|
|
|
|
Ikiwiki uses this information to automatically clean up rendered files when
|
|
the page that rendered them goes away or is changes to no longer render
|
|
them. will_render also does a few important security checks.
|
|
|
|
#### `pagetype($)`
|
|
|
|
Given the name of a source file, returns the type of page it is, if it's
|
|
a type that ikiwiki knowns how to htmlize. Otherwise, returns undef.
|
|
|
|
#### `pagename($)`
|
|
|
|
Given the name of a source file, returns the name of the wiki page
|
|
that corresponds to that file.
|
|
|
|
#### `srcfile($)`
|
|
|
|
Given the name of a source file in the wiki, searches for the file in
|
|
the source directory and the underlay directories (most recently added
|
|
underlays first), and returns the full path to the first file found.
|
|
|
|
#### `add_underlay($)`
|
|
|
|
Adds a directory to the set of underlay directories that ikiwiki will
|
|
search for files.
|
|
|
|
If the directory name is not absolute, ikiwiki will assume it is in
|
|
the parent directory of the configured underlaydir.
|
|
|
|
#### `displaytime($;$)`
|
|
|
|
Given a time, formats it for display.
|
|
|
|
The optional second parameter is a strftime format to use to format the
|
|
time.
|
|
|
|
#### `gettext`
|
|
|
|
This is the standard gettext function, although slightly optimised.
|
|
|
|
#### `urlto($$)`
|
|
|
|
Construct a relative url to the first parameter from the page named by the
|
|
second. The first parameter can be either a page name, or some other
|
|
destination file, as registered by `will_render`.
|
|
|
|
#### `targetpage($$)`
|
|
|
|
Passed a page and an extension, returns the filename that page will be
|
|
rendered to.
|
|
|
|
## Internal use pages
|
|
|
|
Sometimes it's useful to put pages in the wiki without the overhead of
|
|
having them be rendered to individual html files. Such internal use pages
|
|
are collected together to form the RecentChanges page, for example.
|
|
|
|
To make an internal use page, register a filename extension that starts
|
|
with "_". Internal use pages cannot be edited with the web interface,
|
|
generally shouldn't contain wikilinks or preprocessor directives (use
|
|
either on them with extreme caution), and are not matched by regular
|
|
PageSpecs glob patterns, but instead only by a special `internal()`
|
|
[[ikiwiki/PageSpec]].
|
|
|
|
## RCS plugins
|
|
|
|
ikiwiki's support for [[revision_control_systems|rcs]] also uses pluggable
|
|
perl modules. These are in the `IkiWiki::RCS` namespace, for example
|
|
`IkiWiki::RCS::svn`.
|
|
|
|
Each RCS plugin must support all the `IkiWiki::rcs_*` functions.
|
|
See IkiWiki::RCS::Stub for the full list of functions. It's ok if
|
|
`rcs_getctime` does nothing except for throwing an error.
|
|
|
|
See [[RCS_details|rcs/details]] for some more info.
|
|
|
|
## PageSpec plugins
|
|
|
|
It's also possible to write plugins that add new functions to
|
|
[[PageSpecs|ikiwiki/PageSpec]]. Such a plugin should add a function to the
|
|
IkiWiki::PageSpec package, that is named `match_foo`, where "foo()" is
|
|
how it will be accessed in a [[ikiwiki/PageSpec]]. The function will be passed
|
|
two parameters: The name of the page being matched, and the thing to match
|
|
against. It may also be passed additional, named parameters. It should return
|
|
a IkiWiki::SuccessReason object if the match succeeds, or an
|
|
IkiWiki::FailReason object if the match fails.
|