+#### `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`.
+
+If the third parameter is passed and is true, an absolute url will be
+constructed instead of the default relative url.
+
+#### `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.
+
+## 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 a file, message, token (from `rcs_prepedit`), user, and ip address.
+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 a message, user, and ip address. 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. Note
+that the new file may be in a new subdir that is not yet in version
+control; the subdir can be added if so.
+
+#### `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 => # name of user who made the change,
+ 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 parameter is the rev from `rcs_recentchanges`.
+Should return a list of lines of the diff (including \n) in list
+context, and 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.
+
+It's ok if this is not implemented, and throws an error.
+
+#### `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 exit
+nonzero, 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.
+
+### 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.
+
+### 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`.