]> git.vanrenterghem.biz Git - git.ikiwiki.info.git/blobdiff - doc/plugins/write.mdwn
function injection overhaul
[git.ikiwiki.info.git] / doc / plugins / write.mdwn
index b31722dd7f7337479809a8ed6754afba01439a78..2e11e6234ef24b1e7ca64df3b09c950f25772a18 100644 (file)
@@ -123,7 +123,7 @@ make arbitrary changes. The function is passed named parameters "page",
 
 ### preprocess
 
 
 ### preprocess
 
-Adding a [[ikiwiki/PreProcessorDirective]] is probably the most common use
+Adding a preprocessor [[ikiwiki/directive]] is probably the most common use
 of a plugin.
 
         hook(type => "preprocess", id => "foo", call => \&preprocess);
 of a plugin.
 
         hook(type => "preprocess", id => "foo", call => \&preprocess);
@@ -158,7 +158,7 @@ can assume it's being run in scan mode, and avoid doing expensive things at
 that point.)
 
 Note that if the [[htmlscrubber]] is enabled, html in
 that point.)
 
 Note that if the [[htmlscrubber]] is enabled, html in
-[[ikiwiki/PreProcessorDirective]] output is sanitised, which may limit what
+preprocessor [[ikiwiki/directive]] 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
 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
@@ -188,6 +188,10 @@ languages to ikiwiki.
 The function is passed named parameters: "page" and "content" and should
 return the htmlized content.
 
 The function is passed named parameters: "page" and "content" and should
 return the htmlized content.
 
+If `hook` is passed an optional "keepextension" parameter, set to a true
+value, then this extension will not be stripped from the source filename when
+generating the page.
+
 ### pagetemplate
 
        hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
 ### pagetemplate
 
        hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
@@ -356,7 +360,14 @@ This hook is called whenever ikiwiki normally saves its state, just before
 the state is saved. The function can save other state, modify values before
 they're saved, etc.
 
 the state is saved. The function can save other state, modify values before
 they're saved, etc.
 
-## renamepage
+### displaytime
+
+       hook(type => "displaytime", id => "foo", call => \&display);
+
+This hook can be registered to override the regular `displaytime` function.
+Only the last displaytime hook will be used.
+
+### renamepage
 
        hook(type => "renamepage", id => "foo", call => \&renamepage);
 
 
        hook(type => "renamepage", id => "foo", call => \&renamepage);
 
@@ -379,22 +390,29 @@ die if not, which will cause the plugin to not be offered in the configuration
 interface.
 
 The data returned is a list of `%config` options, followed by a hash
 interface.
 
 The data returned is a list of `%config` options, followed by a hash
-describing the option. For example:
+describing the option. There can also be an item named "plugin", which
+describes the plugin as a whole. For example:
 
                 return
                        option_foo => {
                                type => "boolean",
 
                 return
                        option_foo => {
                                type => "boolean",
-                               description => "enable foo",
+                               description => "enable foo?",
+                               advanced => 1,
                                safe => 1,
                                rebuild => 1,
                        },
                        option_bar => {
                                type => "string",
                                example => "hello",
                                safe => 1,
                                rebuild => 1,
                        },
                        option_bar => {
                                type => "string",
                                example => "hello",
-                               description => "what to say",
+                               description => "option bar",
                                safe => 1,
                                rebuild => 0,
                        },
                                safe => 1,
                                rebuild => 0,
                        },
+                       plugin => {
+                               description => "description of this plugin",
+                               safe => 1,
+                               rebuild => 1,
+                       },
 
 * `type` can be "boolean", "string", "integer", "pagespec",
   or "internal" (used for values that are not user-visible). The type is
 
 * `type` can be "boolean", "string", "integer", "pagespec",
   or "internal" (used for values that are not user-visible). The type is
@@ -402,11 +420,19 @@ describing the option. For example:
   hash of these.
 * `example` can be set to an example value.
 * `description` is a short description of the option.
   hash of these.
 * `example` can be set to an example value.
 * `description` is a short description of the option.
-* `description_html` is an optional short description, that can contain html
+* `link` is a link to further information about the option. This can either
+  be a wikilink, or an url.
+* `advanced` can be set to true if the option is more suitable for advanced
+  users.
 * `safe` should be false if the option should not be displayed in unsafe
   configuration methods, such as the web interface. Anything that specifies
   a command to run, a path on disk, or a regexp should be marked as unsafe.
 * `safe` should be false if the option should not be displayed in unsafe
   configuration methods, such as the web interface. Anything that specifies
   a command to run, a path on disk, or a regexp should be marked as unsafe.
-* `rebuild` should be true if changing the option will require a wiki rebuild.
+  If a plugin is marked as unsafe, that prevents it from being
+  enabled/disabled.
+* `rebuild` should be true if changing the option (or enabling/disabling
+  the plugin) will require a wiki rebuild, false if no rebuild is needed,
+  and undef if a rebuild could be needed in some circumstances, but is not
+  strictly required.
 
 ## Plugin interface
 
 
 ## Plugin interface
 
@@ -433,8 +459,8 @@ your ikiwiki setup file, which sets the hash content to configure the wiki.
 
 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,
 
 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}`.
+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
 
 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
@@ -447,6 +473,15 @@ When pages are deleted, ikiwiki automatically deletes their pagestate too.
 Note that page state does not persist across wiki rebuilds, only across
 wiki updates.
 
 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.
+
 ### Other variables
 
 If your plugin needs to access data about other pages in the wiki. It can
 ### Other variables
 
 If your plugin needs to access data about other pages in the wiki. It can
@@ -484,7 +519,7 @@ 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
 cleanup.
 
 If called inside a preprocess hook, error() does not abort the entire
-wiki build, but instead replaces the [[ikiwiki/PreProcessorDirective]] with
+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
 a version containing the error message.
 
 In other hooks, error() is a fatal error, so use with care. Try to avoid
@@ -502,6 +537,9 @@ parameters are passed to `HTML::Template->new`.
 Passed a page name, returns the base name that will be used for a the html
 page created from it. (Ie, it appends ".html".)
 
 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.
+
 #### `add_depends($$)`
 
 Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
 #### `add_depends($$)`
 
 Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
@@ -604,6 +642,23 @@ a type that ikiwiki knowns how to htmlize. Otherwise, returns undef.
 Given the name of a source file, returns the name of the wiki page
 that corresponds to that file.
 
 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
+[[WikiLink]] into a wiki page name.
+
 #### `srcfile($;$)`
 
 Given the name of a source file in the wiki, searches for the file in
 #### `srcfile($;$)`
 
 Given the name of a source file in the wiki, searches for the file in
@@ -642,6 +697,12 @@ 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.
 
 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
 #### `targetpage($$)`
 
 Passed a page and an extension, returns the filename that page will be
@@ -703,8 +764,8 @@ Changes can be staged by calls to `rcs_add, `rcs_remove`, and
 Adds the passed file to the archive. The filename is relative to the root
 of the srcdir.
 
 Adds the passed file to the archive. The filename is relative to the root
 of the srcdir.
 
-Note that this should not check the new file in, it should only
-prepare for it to be checked in when rcs_commit (or `rcs_commit_staged`) is
+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.
 
 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.
 
@@ -712,9 +773,9 @@ to version control; the subdir can be added if so.
 
 Remove a file. The filename is relative to the root of the srcdir.
 
 
 Remove a file. The filename is relative to the root of the srcdir.
 
-Note that this should not check the removal in, it should only prepare for it
-to be checked in when `rcs_commit` (or `rcs_commit_staged`) is called. Note
-that the new file may be in a new subdir that is not yet inversion
+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($$)`
 control; the subdir can be added if so.
 
 #### `rcs_rename($$)`
@@ -789,6 +850,85 @@ 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.
 
 to a hash containing all the config items. They should also implement a
 `gendump` function.
 
-By the way, to parse a ikiwiki setup file, a program just needs to
-do something like:
-`use IkiWiki::Setup; my %setup=IkiWiki::Setup::load($filename)`
+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.
+
+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.