+your ikiwiki setup file, 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}`.
+
+The `$value` can be anything that perl's Storable module is capable of
+serializing. `$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.
+
+### `%wikistate`
+
+The `%wikistate` hash can be used by a plugin to store persistant state
+that is not bound to any one page. To set a value, use
+`$wikistate{$id}{$key}=$value`, where `$value` is anything Storable can
+serialize, `$key` is any string you like, and `$id` must be the same as the
+"id" parameter passed to `hook()` when registering the plugin, so that the
+state can be dropped if the plugin is no longer used.
+
+### `%links`
+
+The `%links` hash can be used to look up the names of each page that
+a page links to. The name of the page is the key; the value is an array
+reference. Do not modify this hash directly; call `add_link()`.
+
+ $links{"foo"} = ["bar", "baz"];
+
+### `%typedlinks`
+
+The `%typedlinks` hash records links of specific types. Do not modify this
+hash directly; call `add_link()`. The keys are page names, and the values
+are hash references. In each page's hash reference, the keys are link types
+defined by plugins, and the values are hash references with link targets
+as keys, and 1 as a dummy value, something like this:
+
+ $typedlinks{"foo"} = {
+ tag => { short_word => 1, metasyntactic_variable => 1 },
+ next_page => { bar => 1 },
+ };
+
+Ordinary [[WikiLinks|ikiwiki/WikiLink]] appear in `%links`, but not in
+`%typedlinks`.
+
+### `%pagesources`
+
+The `%pagesources` hash can be used to look up the source filename
+of a page. So the key is the page name, and the value is the source
+filename. Do not modify this hash.
+
+Attachments also appear in this hash, with the same key and value.
+
+ $pagesources{"foo"} = "foo.mdwn";
+ $pagesources{"logo/ikiwiki.png"} = "logo/ikiwiki.png";
+
+
+### `%destsources`
+
+The `%destsources` hash records the name of the source file used to
+create each destination file. The key is the output filename (ie,
+"foo/index.html"), and the value is the name of the page that it was built
+from (eg, "foo"). Note that a single source file may create multiple
+destination files. Do not modify this hash directly; call `will_render()`.
+
+Attachments also appear in this hash, with the same key and value.
+
+ $destsources{"foo/index.html"} = "foo";
+ $destsources{"logo/ikiwiki.png"} = "logo/ikiwiki.png";
+
+## Library functions
+
+Several functions are exported to your plugin when you `use IkiWiki;`
+
+### `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.
+
+If called inside a preprocess hook, error() does not abort the entire
+wiki build, but instead replaces the preprocessor [[ikiwiki/directive]] with
+a version containing the error message.
+
+In other hooks, error() is a fatal error, so use with care. Try to avoid
+dying on bad input when building a page, as that will halt
+the entire wiki build and make the wiki unusable.
+
+### `template($;@)`
+
+Creates and returns a [[!cpan HTML::Template]] object. (In a list context,
+returns the parameters needed to construct the obhect.)
+
+The first parameter is the name of the template file. The optional remaining
+parameters are passed to `HTML::Template->new`.
+
+Normally, the template file is first looked for in the templates/ subdirectory
+of the srcdir. Failing that, it is looked for in the templatedir.
+
+Wiki pages can be used as templates. This should be done only for templates
+which it is safe to let wiki users edit. Enable it by passing a filename
+with no ".tmpl" extension. Template pages are normally looked for in
+the templates/ directory. If the page name starts with "/", a page
+elsewhere in the wiki can be used.
+
+If the template is not found, or contains a syntax error, an error is thrown.
+
+### `template_depends($$;@)`
+
+Use this instead of `template()` if the content of a template is being
+included into a page. This causes the page to depend on the template,
+so it will be updated if the template is modified.
+
+Like `template()`, except the second parameter is the page.
+
+### `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".)
+
+Use this when constructing the filename of a html file. Use `urlto` when
+generating a link to a page.
+
+### `pagespec_match_list($$;@)`
+
+Passed a page name, and [[ikiwiki/PageSpec]], returns a list of pages
+in the wiki that match the [[ikiwiki/PageSpec]].
+
+The page will automatically be made to depend on the specified
+[[ikiwiki/PageSpec]], so `add_depends` does not need to be called. This
+is often significantly more efficient than calling `add_depends` and
+`pagespec_match` in a loop. You should use this anytime a plugin
+needs to match a set of pages and do something based on that list.
+
+Unlike pagespec_match, this may throw an error if there is an error in
+the pagespec.
+
+Additional named parameters can be specified:
+
+* `deptype` optionally specifies the type of dependency to add. Use the
+ `deptype` function to generate a dependency type.
+* `filter` is a reference to a function, that is called and passed a page,
+ and returns true if the page should be filtered out of the list.
+* `sort` specifies a sort order for the list. See
+ [[ikiwiki/PageSpec/sorting]] for the avilable sort methods. Note that
+ if a sort method is specified that depends on the
+ page content (such as 'meta(foo)'), the deptype needs to be set to
+ a content dependency.
+* `reverse` if true, sorts in reverse.
+* `num` if nonzero, specifies the maximum number of matching pages that
+ will be returned.
+* `list` makes it only match amoung the specified list of pages.
+ Default is to match amoung all pages in the wiki.
+
+Any other named parameters are passed on to `pagespec_match`, to further
+limit the match.
+
+### `add_depends($$;$)`
+
+Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
+
+By default, dependencies are full content dependencies, meaning that the
+page will be updated whenever anything matching the PageSpec is modified.
+This can be overridden by passing a `deptype` value as the third parameter.
+
+### `pagespec_match($$;@)`
+
+Passed a page name, and [[ikiwiki/PageSpec]], returns a true value if the
+[[ikiwiki/PageSpec]] matches the page.
+
+Note that the return value is overloaded. If stringified, it will be a
+message indicating why the PageSpec succeeded, or failed, to match 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.
+
+### `deptype(@)`
+
+Use this function to generate ikiwiki's internal representation of a
+dependency type from one or more of these keywords:
+
+* `content` is the default. Any change to the content
+ of a page triggers the dependency.
+* `presence` is only triggered by a change to the presence
+ of a page.
+* `links` is only triggered by a change to the links of a page.
+ This includes when a link is added, removed, or changes what
+ it points to due to other changes. It does not include the
+ addition or removal of a duplicate link.
+
+If multiple types are specified, they are combined.
+
+### `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
+`htmllink` 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
+* title - set to add a title attribute 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.
+
+The filename and directory are separate parameters because of
+some security checks done to avoid symlink attacks. Before writing a file,
+it checks to make sure there's not a symlink with its name, to avoid
+following the symlink. If the filename parameter includes a subdirectory
+to put the file in, it also checks if that subdirectory is a symlink, etc.
+The directory parameter, however, is not checked for symlinks. So,
+generally the directory parameter is a trusted toplevel directory like
+the srcdir or destdir, and any subdirectories of this are included in the
+filename parameter.
+
+### `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, and it's important to call it consistently every time, even if
+the file isn't really written this time -- unless you delete any old
+version of the file. In particular, in preview mode, this should still be
+called even if the file isn't going to be written to during the preview.
+
+Ikiwiki uses this information to automatically clean up rendered files when
+the page that rendered them goes away or is changed 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.
+
+### `pagetitle($)`
+
+Give the name of a wiki page, returns a version suitable to be displayed as
+the page's title. This is accomplished by de-escaping escaped characters in
+the page name. "_" is replaced with a space, and '__NN__' is replaced by
+the UTF character with code NN.
+
+### `titlepage($)`
+
+This performs the inverse of `pagetitle`, ie, it converts a page title into
+a wiki page name.
+
+### `linkpage($)`
+
+This converts text that could have been entered by the user as a
+[[ikiwiki/WikiLink]] into a wiki page name.
+
+### `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.
+
+Normally srcfile will fail with an error message if the source file cannot
+be found. The second parameter can be set to a true value to make it return
+undef instead.
+
+### `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.
+
+If the third parameter is true, this is the publication time of a page.
+(Ie, set the html5 pubdate attribute.)
+
+### `gettext`
+
+This is the standard gettext function, although slightly optimised.
+
+### `ngettext`
+
+This is the standard ngettext 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`.
+
+Provide a second parameter whenever possible, since this leads to better
+behaviour for the [[plugins/po]] plugin and `file:///` URLs.
+
+If the second parameter is not specified (or `undef`), the URL will be
+valid from any page on the wiki, or from the CGI; if possible it'll
+be a path starting with `/`, but an absolute URL will be used if
+the wiki and the CGI are on different domains.
+
+If the third parameter is passed and is true, the url will be a fully
+absolute url. This is useful when generating an url to publish elsewhere.
+
+### `newpagefile($$)`
+
+This can be called when creating a new page, to determine what filename
+to save the page to. It's passed a page name, and its type, and returns
+the name of the file to create, relative to the srcdir.
+
+### `targetpage($$;$)`
+
+Passed a page and an extension, returns the filename that page will be
+rendered to.
+
+Optionally, a third parameter can be passed, to specify the preferred
+filename of the page. For example, `targetpage("foo", "rss", "feed")`
+will yield something like `foo/feed.rss`.
+
+### `add_link($$;$)`
+
+This adds a link to `%links`, ensuring that duplicate links are not
+added. Pass it the page that contains the link, and the link text.
+
+An optional third parameter sets the link type. If not specified,
+it is an ordinary [[ikiwiki/WikiLink]].
+
+### `add_autofile($$$)`
+
+Sometimes you may want to add a file to the `srcdir` as a result of content
+of other pages. For example, [[plugins/tag]] pages can be automatically
+created as needed. This function can be used to do that.
+
+The three parameters are the filename to create (relative to the `srcdir`),
+the name of the plugin, and a callback function. The callback will be
+called if it is appropriate to automatically add the file, and should then
+take care of creating it, and doing anything else it needs to (such as
+checking it into revision control). Note that the callback may not always
+be called. For example, if an automatically added file is deleted by the
+user, ikiwiki will avoid re-adding it again.
+
+This function needs to be called during the scan hook, or earlier in the
+build process, in order to add the file early enough for it to be built.
+
+## Miscellaneous
+
+### 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|ikiwiki/WikiLink]] 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]] is also done via
+plugins. See [[RCS_details|rcs/details]] for some more info.
+
+RCS plugins must register a number of hooks. Each hook has type 'rcs',
+and the 'id' field is set to the name of the hook. For example:
+
+ hook(type => "rcs", id => "rcs_update", call => \&rcs_update);
+ hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit);
+
+#### `rcs_update()`
+
+Updates the working directory with any remote changes.
+
+#### `rcs_prepedit($)`
+
+Is passed a file to prepare to edit. It can generate and return an arbitrary
+token, that will be passed into `rcs_commit` when committing. For example,
+it might return the current revision ID of the file, and use that
+information later when merging changes.
+
+#### `rcs_commit(@)`
+
+Passed named parameters: `file`, `message`, `token` (from `rcs_prepedit`),
+and `session` (optional).
+
+Should try to commit the file. Returns `undef` on *success* and a version
+of the page with the rcs's conflict markers on failure.
+
+#### `rcs_commit_staged(@)`
+
+Passed named parameters: `message`, and `session` (optional).
+
+Should commit all staged changes. Returns undef on success, and an
+error message on failure.
+
+Changes can be staged by calls to `rcs_add`, `rcs_remove`, and
+`rcs_rename`.
+
+#### `rcs_add($)`
+
+Adds the passed file to the archive. The filename is relative to the root
+of the srcdir.
+
+Note that this should not commit the new file, it should only
+prepare for it to be committed when rcs_commit (or `rcs_commit_staged`) is
+called. Note that the file may be in a new subdir that is not yet in
+to version control; the subdir can be added if so.
+
+#### `rcs_remove($)`
+
+Remove a file. The filename is relative to the root of the srcdir.
+
+Note that this should not commit the removal, it should only prepare for it
+to be committed when `rcs_commit` (or `rcs_commit_staged`) is called.
+
+#### `rcs_rename($$)`
+
+Rename a file. The filenames are relative to the root of the srcdir.
+
+Note that this should not commit the rename, it should only
+prepare it for when `rcs_commit` (or `rcs_commit_staged`) is called.
+The new filename may be in a new subdir, that is not yet added to
+version control. If so, the subdir will exist already, and should
+be added to revision control.
+
+#### `rcs_recentchanges($)`
+
+Examine the RCS history and generate a list of recent changes.
+The parameter is how many changes to return.
+
+The data structure returned for each change is:
+
+ {
+ rev => # the RCSs id for this commit
+ user => # user who made the change (may be an openid),
+ nickname => # short name for user (optional; not an openid),
+
+ committype => # either "web" or the name of the rcs,
+ when => # time when the change was made,
+ message => [
+ { line => "commit message line 1" },
+ { line => "commit message line 2" },
+ # etc,
+ ],
+ pages => [
+ {
+ page => # name of page changed,
+ diffurl => # optional url to a diff of changes
+ },
+ # repeat for each page changed in this commit,
+ ],
+ }
+
+#### `rcs_diff($;$)`
+
+The first parameter is the rev from `rcs_recentchanges`.
+The optional second parameter is how many lines to return (default: all).
+
+Should return a list of lines of the diff (including \n) in list
+context, and a string containing the whole diff in scalar context.
+
+#### `rcs_getctime($)`
+
+This is used to get the page creation time for a file from the RCS, by looking
+it up in the history.
+
+If the RCS cannot determine a ctime for the file, return 0.
+
+#### `rcs_getmtime($)`
+
+This is used to get the page modification time for a file from the RCS, by
+looking it up in the history.
+
+It's ok if this is not implemented, and throws an error.
+
+If the RCS cannot determine a mtime for the file, return 0.
+
+#### `rcs_receive()`
+
+This is called when ikiwiki is running as a pre-receive hook (or
+equivalent), and is testing if changes pushed into the RCS from an
+untrusted user should be accepted. This is optional, and doesn't make
+sense to implement for all RCSs.
+
+It should examine the incoming changes, and do any sanity
+checks that are appropriate for the RCS to limit changes to safe file adds,
+removes, and changes. If something bad is found, it should die, to abort
+the push. Otherwise, it should return a list of files that were changed,
+in the form:
+
+ {
+ file => # name of file that was changed
+ action => # either "add", "change", or "remove"
+ path => # temp file containing the new file content, only
+ # needed for "add"/"change", and only if the file
+ # is an attachment, not a page
+ }
+
+The list will then be checked to make sure that each change is one that
+is allowed to be made via the web interface.
+
+#### `rcs_preprevert($)`
+
+This is called by the revert web interface. It is passed a RCS-specific
+change ID, and should determine what the effects would be of reverting
+that change, and return the same data structure as `rcs_receive`.
+
+Like `rcs_receive`, it should do whatever sanity checks are appropriate
+for the RCS to limit changes to safe changes, and die if a change would
+be unsafe to revert.
+
+#### `rcs_revert($)`
+
+This is called by the revert web interface. It is passed a named
+parameter rev that is the RCS-specific change ID to revert.
+
+It should try to revert the specified rev, and leave the reversion staged
+so `rcs_commit_staged` will complete it. It should return undef on _success_
+and an error message on failure.
+
+This hook and `rcs_preprevert` are optional, if not implemented, no revert
+web interface will be available.
+
+### `rcs_find_changes($)`
+
+Finds changes committed since the passed RCS-specific rev. Returns
+a hash of the files changed, a hash of the files deleted, and the
+current rev.
+
+This hook is optional.
+
+### `rcs_get_current_rev()`
+
+Gets a RCS-specific rev, which can later be passed to `rcs_find_changes`.
+
+This hook is optional.
+
+### 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. If the match cannot be
+attempted at all, for any page, it can instead return an
+IkiWiki::ErrorReason object explaining why.
+
+When constructing these objects, you should also include information about
+of any pages whose contents or other metadata influenced the result of the
+match. Do this by passing a list of pages, followed by `deptype` values.
+
+For example, "backlink(foo)" is influenced by the contents of page foo;
+"link(foo)" and "title(bar)" are influenced by the contents of any page
+they match; "created_before(foo)" is influenced by the metadata of foo;
+while "glob(*)" is not influenced by the contents of any page.
+
+### Sorting plugins
+
+Similarly, it's possible to write plugins that add new functions as
+[[ikiwiki/pagespec/sorting]] methods. To achieve this, add a function to
+the IkiWiki::SortSpec package named `cmp_foo`, which will be used when sorting
+by `foo` or `foo(...)` is requested.
+
+The names of pages to be compared are in the global variables `$a` and `$b`
+in the IkiWiki::SortSpec package. The function should return the same thing
+as Perl's `cmp` and `<=>` operators: negative if `$a` is less than `$b`,
+positive if `$a` is greater, or zero if they are considered equal. It may
+also raise an error using `error`, for instance if it needs a parameter but
+one isn't provided.
+
+The function will also be passed one or more parameters. The first is
+`undef` if invoked as `foo`, or the parameter `"bar"` if invoked as `foo(bar)`;
+it may also be passed additional, named parameters.
+
+### Setup plugins
+
+The ikiwiki setup file is loaded using a pluggable mechanism. If you look
+at the top of a setup file, it starts with 'use IkiWiki::Setup::Standard',
+and the rest of the file is passed to that module's import method.
+
+It's possible to write other modules in the `IkiWiki::Setup::` namespace that
+can be used to configure ikiwiki in different ways. These modules should,
+when imported, populate `$IkiWiki::Setup::raw_setup` with a reference
+to a hash containing all the config items. They should also implement a
+`gendump` function.
+
+By the way, to parse a ikiwiki setup file and populate `%config`, a
+program just needs to do something like:
+`use IkiWiki::Setup; IkiWiki::Setup::load($filename)`
+
+### Function overriding
+
+Sometimes using ikiwiki's pre-defined hooks is not enough. Your plugin
+may need to replace one of ikiwiki's own functions with a modified version,
+or wrap one of the functions.
+
+For example, your plugin might want to override `displaytime`, to change
+the html markup used when displaying a date. Or it might want to override
+`IkiWiki::formattime`, to change how a date is formatted. Or perhaps you
+want to override `bestlink` and change how ikiwiki deals with [[WikiLinks|ikiwiki/WikiLink]].
+
+By venturing into this territory, your plugin is becoming tightly tied to
+ikiwiki's internals. And it might break if those internals change. But
+don't let that stop you, if you're brave.
+
+Ikiwiki provides an `inject()` function, that is a powerful way to replace
+any function with one of your own. This even allows you to inject a
+replacement for an exported function, like `bestlink`. Everything that
+imports that function will get your version instead. Pass it the name of
+the function to replace, and a new function to call.
+
+For example, here's how to replace `displaytime` with a version using HTML 5
+markup:
+
+ inject(name => 'IkiWiki::displaytime', call => sub {
+ return "<time>".formattime(@_)."</time>";
+ });
+
+Here's how to wrap `bestlink` with a version that tries to handle
+plural words:
+
+ my $origbestlink=\&bestlink;
+ inject(name => 'IkiWiki::bestlink', call => \&mybestlink);
+
+ sub deplural ($) {
+ my $word=shift;
+ $word =~ s/e?s$//; # just an example :-)
+ return $word;
+ }
+
+ sub mybestlink ($$) {
+ my $page=shift;
+ my $link=shift;
+ my $ret=$origbestlink->($page, $link);
+ if (! length $ret) {
+ $ret=$origbestlink->($page, deplural($link));
+ }
+ return $ret;
+ }
+
+### Javascript
+
+Some plugins use javascript to make ikiwiki look a bit more web-2.0-ish.
+
+All javascript code should be put in `.js` files in the `javascript`
+underlay, and plugins using those files can enable use of the underlay by
+calling `add_underlay("javascript");` in their `import` function.
+
+You'll have to arrange for `<script>` tags to be added to the pages that
+use your javascript. This can be done using a `format` hook.
+
+Ikiwiki provides some utility functions in `ikiwiki.js`, for use by other
+javascript code. These include:
+
+#### `getElementsByClass(cls, node, tag)`
+
+Returns an array of elements with the given class. The node and tag are
+optional and define what document node and element names to search.
+
+#### `hook(name, call)`
+
+The function `call` will be run as part of the hook named `name`.
+
+Note that to hook into `window.onload`, you can use the `onload' hook.
+
+#### `run_hooks(name)`
+
+Runs the hooks with the specified name.