Recent changes to this wiki:

noted that I fixed the template on my box
diff --git a/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn b/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn
index 4c81981..007d763 100644
--- a/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn
+++ b/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn
@@ -14,3 +14,5 @@ This results in the recentchanges/ page being invalid and rendering quite horrif
 
 Thanks,
 David
+
+PS: I have fixed the template by hand on my server, so it will validate, however ikiwiki.info will not.

diff --git a/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn b/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn
new file mode 100644
index 0000000..4c81981
--- /dev/null
+++ b/doc/bugs/templateForRecentChangesMissingCloseSpan.mdwn
@@ -0,0 +1,16 @@
+In the template for ikiwiki's recent changes page
+
+     /usr/share/ikiwiki/templates/change.tmpl
+
+there is a missing </span> tag after the
+
+     <span class="changedate"><TMPL_VAR COMMITDATE>
+
+This results in the recentchanges/ page being invalid and rendering quite horrifyingly in Internet Exploder.
+
+[I'm running](http://wiki.shlrm.org) (linked so you can see the one I'm running if you need to) the latest version of ikiwiki, and I note that it's broken on [ikiwiki.info](http://validator.w3.org/check?uri=http%3A%2F%2Fikiwiki.info%2Frecentchanges%2F&charset=%28detect+automatically%29&doctype=Inline&group=0&user-agent=W3C_Validator%2F1.767) too :)
+
+[This one on debian](https://www.icanttype.org/recentchanges/) is somehow [valid](http://validator.w3.org/check?uri=https%3A%2F%2Fwww.icanttype.org%2F%2Frecentchanges%2F&charset=%28detect+automatically%29&doctype=Inline&group=0&user-agent=W3C_Validator%2F1.767), although it's using the same template. Perhaps there's an additional scrubbing going on his end.
+
+Thanks,
+David

tag2
diff --git a/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn b/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn
index 98e4280..49c55e2 100644
--- a/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn
+++ b/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn
@@ -9,3 +9,7 @@ Maybe even with parsing of the content and preselecting the tags, that are given
 
 this would need a bit JS-work and somehow on compiletime we need to put the list of tags somewhere, where the cgi could read them from.
 This way, even a pagespec would suffice to determine the usable list of tags and not only the tagbase-variable.
+
+> I think this would be very hard to achieve with the current tag plugin, due to the nature of its implementation.
+> 
+> I've had a "tag2" plugin on the go for a while which supports this. It's in a very rough stage but I'll try to find it and upload it somewhere. -- [[Jon]]

suggesting List of tags when editing content (wishlist)
diff --git a/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn b/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn
new file mode 100644
index 0000000..98e4280
--- /dev/null
+++ b/doc/forum/wishlist-discussion:_Editformular_showing_existing_tags.mdwn
@@ -0,0 +1,11 @@
+# How about:
+
+having a list of all existing tags in the Edit-Formular as a selectionbox?
+
+Assume I have tagbase=/tags/ and for every tag I have given to articles an existing page there.
+
+Would it be possible to list all these tags together with the Formular, as selectionbox.
+Maybe even with parsing of the content and preselecting the tags, that are given in the article and vice-versa when selecting the fields then also generating the \[\[\!tag\]\]-sourcecode ?
+
+this would need a bit JS-work and somehow on compiletime we need to put the list of tags somewhere, where the cgi could read them from.
+This way, even a pagespec would suffice to determine the usable list of tags and not only the tagbase-variable.

diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index ac4d7ed..4f94b77 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -27,3 +27,26 @@ What might be causing this exception and how I might go about debugging exceptio
 >>>>> I don't see how that's relevant. It would help if you showed me
 >>>>> exactly something that could be inserted into a page to cause the
 >>>>> problem. --[[Joey]] 
+
+>>>>>> Correct me if I'm wrong: ikiwiki generates an Omega template from its own templates, such as searchquery.tmpl and puts it into {$srcdir}/.ikiwiki/xapian/templates/query. Omega has its own template syntax, where function names are prefixed with dollar signs (`$`). So, when I call my wiki `$foobar`, ikiwiki generates an Omega template that looks like this snippet:
+
+    <div id="container">
+        <div class="pageheader">
+            <div class="header">
+            <span>
+            <a href="http://example.com">$foobar</    a>/search
+            </span>
+            </div>
+        </div> <!-- .pageheader -->
+    
+        <div id="content">
+            $setmap{prefix,title,S}
+    $setmap{prefix,link,XLINK}
+    $set{thousand,$.}$set{decimal,.}$setmap{BN,,Any Country,uk,England,fr,France}
+    ${
+    $def{PREV,
+    $if{$ne{$topdoc,0},<INPUT TYPE=image NAME="&lt;" ALT="&lt;"
+    SRC="/images/xapian-omega/prev.png" BORDER=0 HEIGHT=30 WIDTH=30>,
+    <IMG ALT="" SRC="/images/xapian-omega/prevoff.png" HEIGHT=30 WIDTH=30>}
+
+>>>>>> So `$foobar` clashes with Omega's template tags. Does this help?

Revert spam
diff --git a/doc/bugs.mdwn b/doc/bugs.mdwn
index f44cfdc..f634b6e 100644
--- a/doc/bugs.mdwn
+++ b/doc/bugs.mdwn
@@ -1,5 +1,5 @@
 If you've found a bug in ikiwiki, post about it here. [[TODO]] items go
-elsewhere. Link <a href="http://www.college-paper.org/custom-essay.html">college essay</a> items to [[bugs/done]] when done.
+elsewhere. Link items to [[bugs/done]] when done.
 
 Also see the [Debian bugs](http://bugs.debian.org/ikiwiki).
 
diff --git a/doc/bugs/bestlink_returns_deleted_pages.mdwn b/doc/bugs/bestlink_returns_deleted_pages.mdwn
index d3c5c80..874f18e 100644
--- a/doc/bugs/bestlink_returns_deleted_pages.mdwn
+++ b/doc/bugs/bestlink_returns_deleted_pages.mdwn
@@ -28,7 +28,7 @@ won't it make sense for bestlink() to check %pagesources first? --[[harishcm]]
 > maybe by keeping a copy of the old backlinks info, then that fix could be
 > applied here too. --[[Joey]]
 
->> Cool that was fast! Well at least half the <a href="http://www.college-paper.org/custom-essay.html college essay">college essay</a> bug is solved :) For now I'll
+>> Cool that was fast! Well at least half the bug is solved :) For now I'll
 >> probably try using a workaround if using bestlink within the needsbuild
 >> or scan hooks. Maybe by testing if pagemtime equals zero. --[[harishcm]]
 
@@ -48,8 +48,8 @@ won't it make sense for bestlink() to check %pagesources first? --[[harishcm]]
     use IkiWiki 3.00;
     
     sub import {
-    	hook(type => "getsetup", id => "bestlinkbug", call => &getsetup);
-    	hook(type => "needsbuild", id => "bestlinkbug", call => &needsbuild);
+    	hook(type => "getsetup", id => "bestlinkbug", call => \&getsetup);
+    	hook(type => "needsbuild", id => "bestlinkbug", call => \&needsbuild);
     }
     
     sub getsetup () {

diff --git a/doc/bugs.mdwn b/doc/bugs.mdwn
index f634b6e..f44cfdc 100644
--- a/doc/bugs.mdwn
+++ b/doc/bugs.mdwn
@@ -1,5 +1,5 @@
 If you've found a bug in ikiwiki, post about it here. [[TODO]] items go
-elsewhere. Link items to [[bugs/done]] when done.
+elsewhere. Link <a href="http://www.college-paper.org/custom-essay.html">college essay</a> items to [[bugs/done]] when done.
 
 Also see the [Debian bugs](http://bugs.debian.org/ikiwiki).
 

diff --git a/doc/bugs/bestlink_returns_deleted_pages.mdwn b/doc/bugs/bestlink_returns_deleted_pages.mdwn
index 874f18e..d3c5c80 100644
--- a/doc/bugs/bestlink_returns_deleted_pages.mdwn
+++ b/doc/bugs/bestlink_returns_deleted_pages.mdwn
@@ -28,7 +28,7 @@ won't it make sense for bestlink() to check %pagesources first? --[[harishcm]]
 > maybe by keeping a copy of the old backlinks info, then that fix could be
 > applied here too. --[[Joey]]
 
->> Cool that was fast! Well at least half the bug is solved :) For now I'll
+>> Cool that was fast! Well at least half the <a href="http://www.college-paper.org/custom-essay.html college essay">college essay</a> bug is solved :) For now I'll
 >> probably try using a workaround if using bestlink within the needsbuild
 >> or scan hooks. Maybe by testing if pagemtime equals zero. --[[harishcm]]
 
@@ -48,8 +48,8 @@ won't it make sense for bestlink() to check %pagesources first? --[[harishcm]]
     use IkiWiki 3.00;
     
     sub import {
-    	hook(type => "getsetup", id => "bestlinkbug", call => \&getsetup);
-    	hook(type => "needsbuild", id => "bestlinkbug", call => \&needsbuild);
+    	hook(type => "getsetup", id => "bestlinkbug", call => &getsetup);
+    	hook(type => "needsbuild", id => "bestlinkbug", call => &needsbuild);
     }
     
     sub getsetup () {

Clarification request
diff --git a/doc/plugins/conditional/discussion.mdwn b/doc/plugins/conditional/discussion.mdwn
index 09e3df9..6e84fdf 100644
--- a/doc/plugins/conditional/discussion.mdwn
+++ b/doc/plugins/conditional/discussion.mdwn
@@ -8,6 +8,19 @@ Using \[\[!if test="tagged(plugin)" then="= Tagged as plugin =" else="*No plugin
 > so tagging a large number of pages with a tag that doesn't exist (which change has
 > been reverted) doesn't make the pagespec match. It would if the tag's page existed. --[[Joey]]
 
+>> So if I understand this correctly... Assuming the tags Tag_A and Tag_B, the existence of 
+>> @wiki-home@/tags/Tag_A.creole, and a number of files with a \[\[!tag Tag_A Tag_B]] the 
+>> following is correct?
+>>
+>> * \[\[!if test="tagged(Tag_A)" then="OK" else="Fail"]] => OK
+>> * \[\[!if test="tagged(Tag_B)" then="OK" else="Fail"]] => Fail
+>> * \[\[!if test="tagged(Tag_A) and tagged(Tag_B)" then="OK" else="Fail"]] => Fail
+>>
+>> Is that the expected behaviour? If so, that's not what I'm seeing here since they all result 
+>> in a Fail. If not, what exactly is wrong with those conditionals? Thanks.
+>>
+>> -- Thiana 
+
 ----
 
 Would there be a way for this plugin to emit fewer blank lines (i.e. *none at all*)?

response
diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index cb75895..ac4d7ed 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -23,3 +23,7 @@ What might be causing this exception and how I might go about debugging exceptio
 >>> --[[Joey]]
 
 >>>> I tried it with both omega 1.0.13 and omega 1.0.18 and the issue is present in both. If I view the contents of {$srcdir}/.ikiwiki/xapian/templates/query, I can see that the wiki title is inserted verbatim and there are calls to `$setmap`, `$set` and `$def` etc in the template. --[[dkobozev]]
+
+>>>>> I don't see how that's relevant. It would help if you showed me
+>>>>> exactly something that could be inserted into a page to cause the
+>>>>> problem. --[[Joey]] 

response
diff --git a/doc/plugins/conditional/discussion.mdwn b/doc/plugins/conditional/discussion.mdwn
index e34df70..09e3df9 100644
--- a/doc/plugins/conditional/discussion.mdwn
+++ b/doc/plugins/conditional/discussion.mdwn
@@ -4,6 +4,10 @@ Using \[\[!if test="tagged(plugin)" then="= Tagged as plugin =" else="*No plugin
 
 -- Thiana
 
+> This wiki has no page named "plugin", so nothing links to it; tags are a species of link
+> so tagging a large number of pages with a tag that doesn't exist (which change has
+> been reverted) doesn't make the pagespec match. It would if the tag's page existed. --[[Joey]]
+
 ----
 
 Would there be a way for this plugin to emit fewer blank lines (i.e. *none at all*)?

Revert "Added use of tag directive so I can play with tags in the sandbox."
This reverts commit b9e7064f70980b58b1bae754bee7fe3eff5fc84d.
Er, no, I don't want a broken tag link on every plugin page, really.
diff --git a/doc/templates/plugin.mdwn b/doc/templates/plugin.mdwn
index d62c879..c1d1974 100644
--- a/doc/templates/plugin.mdwn
+++ b/doc/templates/plugin.mdwn
@@ -6,7 +6,6 @@ Enabled by default: <TMPL_IF core>yes<TMPL_ELSE>no</TMPL_IF><br />
 Included in [[/plugins/goodstuff]]: [[!if test="backlink(plugins/goodstuff)" all=no then="""yes""" else="""no"""]]<br />
 Currently enabled: [[!if test="enabled(<TMPL_VAR name>)" then="yes" else="no"]]<br />
 </span>
-[[!tag plugin <TMPL_VAR name>]]
 [[!if test="sourcepage(plugins/contrib/*)" then="""[[!meta title="<TMPL_VAR name> (third party plugin)"]]"""]]
 <TMPL_IF core>[[!tag plugins/type/core]]</TMPL_IF>
 <TMPL_UNLESS NAME="name">

add link
diff --git a/doc/ikiwiki/directive/map/discussion.mdwn b/doc/ikiwiki/directive/map/discussion.mdwn
index 075b91b..f6eaa6b 100644
--- a/doc/ikiwiki/directive/map/discussion.mdwn
+++ b/doc/ikiwiki/directive/map/discussion.mdwn
@@ -5,6 +5,8 @@ Thanks
 
 -- Thiana
 
+> [[bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used]] --[[Joey]] 
+
 ----
 
 Question: Is there a way to generate a listing that shows *both* title and description meta information? Currently, a \[\[!map ...]] shows only one of the two, but I'd like to generate a navigation that looks like a description list. For example:

diff --git a/doc/plugins/conditional/discussion.mdwn b/doc/plugins/conditional/discussion.mdwn
index 629d059..e34df70 100644
--- a/doc/plugins/conditional/discussion.mdwn
+++ b/doc/plugins/conditional/discussion.mdwn
@@ -1,3 +1,11 @@
+## Conditional broken?
+
+Using \[\[!if test="tagged(plugin)" then="= Tagged as plugin =" else="*No plugins found*"]] on this wiki *should* present the 'Tagged as plugin' heading, instead it emits 'no plugins found'. Is the conditional plugin currently broken for tags or am I misusing it? Thanks.
+
+-- Thiana
+
+----
+
 Would there be a way for this plugin to emit fewer blank lines (i.e. *none at all*)?
 
 For example, having a look at [this page](http://www.bddebian.com/~wiki/Hurd/)'s sidebar.

Added use of tag directive so I can play with tags in the sandbox.
diff --git a/doc/templates/plugin.mdwn b/doc/templates/plugin.mdwn
index c1d1974..d62c879 100644
--- a/doc/templates/plugin.mdwn
+++ b/doc/templates/plugin.mdwn
@@ -6,6 +6,7 @@ Enabled by default: <TMPL_IF core>yes<TMPL_ELSE>no</TMPL_IF><br />
 Included in [[/plugins/goodstuff]]: [[!if test="backlink(plugins/goodstuff)" all=no then="""yes""" else="""no"""]]<br />
 Currently enabled: [[!if test="enabled(<TMPL_VAR name>)" then="yes" else="no"]]<br />
 </span>
+[[!tag plugin <TMPL_VAR name>]]
 [[!if test="sourcepage(plugins/contrib/*)" then="""[[!meta title="<TMPL_VAR name> (third party plugin)"]]"""]]
 <TMPL_IF core>[[!tag plugins/type/core]]</TMPL_IF>
 <TMPL_UNLESS NAME="name">

diff --git a/doc/ikiwiki/directive/map/discussion.mdwn b/doc/ikiwiki/directive/map/discussion.mdwn
index 062b426..075b91b 100644
--- a/doc/ikiwiki/directive/map/discussion.mdwn
+++ b/doc/ikiwiki/directive/map/discussion.mdwn
@@ -1,3 +1,12 @@
+### Sorting
+
+Is there a way to have the generated maps sorted by *title* instead of *filename* when show=title is used?
+Thanks 
+
+-- Thiana
+
+----
+
 Question: Is there a way to generate a listing that shows *both* title and description meta information? Currently, a \[\[!map ...]] shows only one of the two, but I'd like to generate a navigation that looks like a description list. For example:
 
  * This is the title meta information.

diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index 7db12c3..cb75895 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -21,3 +21,5 @@ What might be causing this exception and how I might go about debugging exceptio
 >>> tried setting a page title to '$this' and 'foo $this'.
 >>> That's with version 1.0.18 of omega.
 >>> --[[Joey]]
+
+>>>> I tried it with both omega 1.0.13 and omega 1.0.18 and the issue is present in both. If I view the contents of {$srcdir}/.ikiwiki/xapian/templates/query, I can see that the wiki title is inserted verbatim and there are calls to `$setmap`, `$set` and `$def` etc in the template. --[[dkobozev]]

response
diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index 94de18c..7db12c3 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -14,3 +14,10 @@ What might be causing this exception and how I might go about debugging exceptio
 > could switch to [[google_search_plugin|plugins/google]]. --[[Joey]] 
 
 >> Thanks, Joey. With your help I was able to figure out what was wrong. It's a fun little bug (or feature): the title of my wiki had string `$this` in title and that's what was causing the omega binary to choke. My wiki's title was inserted without escaping into the query template used by omega. Omega treated `$this` in the title as a function name and threw an exception because no such function was defined. To avoid this behavior, I used an html entity in the title, so `$this` became `&#36;this`. I don't think that the wiki title should be inserted into the template without escaping - it can produce an error that's not trivial to debug. If users want to modify the html in the title, they should be editing respective templates, not typing html in the wiki title input. What do you think? --[[dkobozev]]
+
+>>> Sounds like a bug in omega, and one that probably would affect other
+>>> users of omega too. Ikiwiki could work around it by pre-escaping
+>>> data before passing it to xapian. I have not quite managed to reproduce it though;
+>>> tried setting a page title to '$this' and 'foo $this'.
+>>> That's with version 1.0.18 of omega.
+>>> --[[Joey]]

diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index 3cbcdc4..94de18c 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -12,3 +12,5 @@ What might be causing this exception and how I might go about debugging exceptio
 > You could try rebuilding your wiki in case it is somehow
 > caused by a problem with the xapian database. Failing everything, you
 > could switch to [[google_search_plugin|plugins/google]]. --[[Joey]] 
+
+>> Thanks, Joey. With your help I was able to figure out what was wrong. It's a fun little bug (or feature): the title of my wiki had string `$this` in title and that's what was causing the omega binary to choke. My wiki's title was inserted without escaping into the query template used by omega. Omega treated `$this` in the title as a function name and threw an exception because no such function was defined. To avoid this behavior, I used an html entity in the title, so `$this` became `&#36;this`. I don't think that the wiki title should be inserted into the template without escaping - it can produce an error that's not trivial to debug. If users want to modify the html in the title, they should be editing respective templates, not typing html in the wiki title input. What do you think? --[[dkobozev]]

diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index afd7dbe..1a1b128 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -77,3 +77,4 @@ bar
 Hmm, can I dig it?
 
 Test
+pop

diff --git a/doc/sandbox/danc.mdwn b/doc/sandbox/danc.mdwn
new file mode 100644
index 0000000..9766475
--- /dev/null
+++ b/doc/sandbox/danc.mdwn
@@ -0,0 +1 @@
+ok

update
diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index 628276b..3cbcdc4 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -4,9 +4,11 @@ What might be causing this exception and how I might go about debugging exceptio
 
 > Appears to be coming from your xapian omega cgi binary. If you
 > run `strings /usr/lib/cgi-bin/omega/omega` you can see it has
-> "Exception: " in it.
+> "Exception: " in it, and I have found some similar (but not identical)
+> error messages from xapian in a web search.
 > 
 > I don´t know what to suggest, other than upgrade/downgrade/reinstall
-> xapian-omega. You could try rebuilding your wiki in case it is somehow
+> xapian-omega, and contacting the xapian developers for debugging.
+> You could try rebuilding your wiki in case it is somehow
 > caused by a problem with the xapian database. Failing everything, you
 > could switch to [[google_search_plugin|plugins/google]]. --[[Joey]] 

response
diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
index 05d4e3a..628276b 100644
--- a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -1,3 +1,12 @@
 I'm very excited to try out ikiwiki, since it should fit my purposes extremely well, but I'm having trouble with the search plugin. I'm pretty sure that right after I installed ikiwiki and needed dependencies, the search plugin was working fine. However, now when I try to use search, I get "Exception: Unknown function `this'" error on a blank page. I'm not sure how I should go about debugging this issue - my server's (I use Lighttpd 1.4.22) error log has no mention of the exception and there's nothing in /var/log/syslog either.
 
 What might be causing this exception and how I might go about debugging exceptions?
+
+> Appears to be coming from your xapian omega cgi binary. If you
+> run `strings /usr/lib/cgi-bin/omega/omega` you can see it has
+> "Exception: " in it.
+> 
+> I don´t know what to suggest, other than upgrade/downgrade/reinstall
+> xapian-omega. You could try rebuilding your wiki in case it is somehow
+> caused by a problem with the xapian database. Failing everything, you
+> could switch to [[google_search_plugin|plugins/google]]. --[[Joey]] 

diff --git a/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
new file mode 100644
index 0000000..05d4e3a
--- /dev/null
+++ b/doc/forum/Exception:_Unknown_function___96__this__39___.mdwn
@@ -0,0 +1,3 @@
+I'm very excited to try out ikiwiki, since it should fit my purposes extremely well, but I'm having trouble with the search plugin. I'm pretty sure that right after I installed ikiwiki and needed dependencies, the search plugin was working fine. However, now when I try to use search, I get "Exception: Unknown function `this'" error on a blank page. I'm not sure how I should go about debugging this issue - my server's (I use Lighttpd 1.4.22) error log has no mention of the exception and there's nothing in /var/log/syslog either.
+
+What might be causing this exception and how I might go about debugging exceptions?

Revert spammer's whitespace changes
(PS, you're banned.)
diff --git a/doc/index.mdwn b/doc/index.mdwn
index 88eafa1..732cf7a 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -19,7 +19,6 @@ ikiwiki [[!version ]].
 
 ## developer resources
 
-
 The [[RoadMap]] describes where the project is going.
 The [[forum]] is open for discussions.
 [[Bugs]], [[TODO]] items, [[wishlist]] items, and [[patches|patch]]
@@ -27,5 +26,3 @@ can be submitted and tracked using this wiki.
 
 ikiwiki is developed by [[Joey]] and many contributors,
 and is [[FreeSoftware]].
-
-

revert spam
diff --git a/doc/TourBusStop.mdwn b/doc/TourBusStop.mdwn
index 5317c67..8e382bd 100644
--- a/doc/TourBusStop.mdwn
+++ b/doc/TourBusStop.mdwn
@@ -9,7 +9,7 @@ This wiki serves as the home for the ikiwiki wiki engine, providing collaborativ
 * You can turn any set of pages into a [[blog]] or similar news feed,
 * complete with RSS and Atom support.  You can run your weblog on ikiwiki (and [[many_people_do|ikiwikiusers]]), run a Planet-like [[aggregator|plugins/aggregate]] for external feeds, or keep a [[TODO]] and [[bug|bugs]] list with tags for completed items.
 
-* ikiwiki provides a wiki compiler, designed to transform your wiki content into a set of static pages.  You can then serve these pages as static content.  ikiwiki will not fall over during a Slashdotting, because page views don't require the ikiwiki CGI; as long as your web server can keep up, your [site](http://dessouse.net) will survive.  Furthermore, you can choose whether you want to run the ikiwiki CGI for web edits or only handle commits to the underlying version control system; you can even run ikiwiki privately and just manually copy the content to another server.  So if you want to put a wiki up on a server without installing any software on that server, try ikiwiki.
+* ikiwiki provides a wiki compiler, designed to transform your wiki content into a set of static pages.  You can then serve these pages as static content.  ikiwiki will not fall over during a Slashdotting, because page views don't require the ikiwiki CGI; as long as your web server can keep up, your site will survive.  Furthermore, you can choose whether you want to run the ikiwiki CGI for web edits or only handle commits to the underlying version control system; you can even run ikiwiki privately and just manually copy the content to another server.  So if you want to put a wiki up on a server without installing any software on that server, try ikiwiki.
 
 ![Picture of the TourBus](http://www.wikiservice.at/image/wikibus.gif)
 

diff --git a/doc/TourBusStop.mdwn b/doc/TourBusStop.mdwn
index 8e382bd..5317c67 100644
--- a/doc/TourBusStop.mdwn
+++ b/doc/TourBusStop.mdwn
@@ -9,7 +9,7 @@ This wiki serves as the home for the ikiwiki wiki engine, providing collaborativ
 * You can turn any set of pages into a [[blog]] or similar news feed,
 * complete with RSS and Atom support.  You can run your weblog on ikiwiki (and [[many_people_do|ikiwikiusers]]), run a Planet-like [[aggregator|plugins/aggregate]] for external feeds, or keep a [[TODO]] and [[bug|bugs]] list with tags for completed items.
 
-* ikiwiki provides a wiki compiler, designed to transform your wiki content into a set of static pages.  You can then serve these pages as static content.  ikiwiki will not fall over during a Slashdotting, because page views don't require the ikiwiki CGI; as long as your web server can keep up, your site will survive.  Furthermore, you can choose whether you want to run the ikiwiki CGI for web edits or only handle commits to the underlying version control system; you can even run ikiwiki privately and just manually copy the content to another server.  So if you want to put a wiki up on a server without installing any software on that server, try ikiwiki.
+* ikiwiki provides a wiki compiler, designed to transform your wiki content into a set of static pages.  You can then serve these pages as static content.  ikiwiki will not fall over during a Slashdotting, because page views don't require the ikiwiki CGI; as long as your web server can keep up, your [site](http://dessouse.net) will survive.  Furthermore, you can choose whether you want to run the ikiwiki CGI for web edits or only handle commits to the underlying version control system; you can even run ikiwiki privately and just manually copy the content to another server.  So if you want to put a wiki up on a server without installing any software on that server, try ikiwiki.
 
 ![Picture of the TourBus](http://www.wikiservice.at/image/wikibus.gif)
 

diff --git a/doc/index.mdwn b/doc/index.mdwn
index b1ef36b..88eafa1 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -19,7 +19,6 @@ ikiwiki [[!version ]].
 
 ## developer resources
 
-[jup](http://www.google.de)
 
 The [[RoadMap]] describes where the project is going.
 The [[forum]] is open for discussions.

diff --git a/doc/index.mdwn b/doc/index.mdwn
index 732cf7a..b1ef36b 100644
--- a/doc/index.mdwn
+++ b/doc/index.mdwn
@@ -19,6 +19,8 @@ ikiwiki [[!version ]].
 
 ## developer resources
 
+[jup](http://www.google.de)
+
 The [[RoadMap]] describes where the project is going.
 The [[forum]] is open for discussions.
 [[Bugs]], [[TODO]] items, [[wishlist]] items, and [[patches|patch]]
@@ -26,3 +28,5 @@ can be submitted and tracked using this wiki.
 
 ikiwiki is developed by [[Joey]] and many contributors,
 and is [[FreeSoftware]].
+
+

comments
diff --git a/doc/todo/salmon_protocol_for_comment_sharing.mdwn b/doc/todo/salmon_protocol_for_comment_sharing.mdwn
index f4fa0c5..1e56b0a 100644
--- a/doc/todo/salmon_protocol_for_comment_sharing.mdwn
+++ b/doc/todo/salmon_protocol_for_comment_sharing.mdwn
@@ -1,3 +1,21 @@
-The <a href="http://www.salmon-protocol.org/home">Salmon protocol</a> provides for aggregating comments across sites.  If a site that syndicates a feed receives a comment on an item in that feed, it can re-post the comment to the original source.
+The <a href="http://www.salmon-protocol.org/home">Salmon protocol</a>
+provides for aggregating comments across sites.  If a site that syndicates
+a feed receives a comment on an item in that feed, it can re-post the
+comment to the original source.
+
+> Ikiwiki does not allow comments to be posted on items it aggregates.
+> So salmon protocol support would only need to handle the comment
+> receiving side of the protocol.
+> 
+> The current draft protocol document confuses me when it starts talking
+> about using OAuth in the abuse prevention section, since their example
+> does not show use of OAuth, and it's not at all clear to me where the
+> OAuth relationship between aggregator and original source is supposed
+> to come from.
+> 
+> Their security model, which goes on to include Webfinger,
+> thirdparty validation services, XRD, and Magic Signatures, looks sorta
+> like they kept throwing technology,  at it, hoping something will stick. :-P
+> --[[Joey]]
 
 [[!tag wishlist]]

diff --git a/doc/todo/salmon_protocol_for_comment_sharing.mdwn b/doc/todo/salmon_protocol_for_comment_sharing.mdwn
new file mode 100644
index 0000000..f4fa0c5
--- /dev/null
+++ b/doc/todo/salmon_protocol_for_comment_sharing.mdwn
@@ -0,0 +1,3 @@
+The <a href="http://www.salmon-protocol.org/home">Salmon protocol</a> provides for aggregating comments across sites.  If a site that syndicates a feed receives a comment on an item in that feed, it can re-post the comment to the original source.
+
+[[!tag wishlist]]

add news item for ikiwiki 3.20100302
diff --git a/doc/news/version_3.20091202.mdwn b/doc/news/version_3.20091202.mdwn
deleted file mode 100644
index 60f17fe..0000000
--- a/doc/news/version_3.20091202.mdwn
+++ /dev/null
@@ -1,17 +0,0 @@
-ikiwiki 3.20091202 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * meta: Generate meta description tags even when the html scrubber is
-     enabled.
-   * meta: Allow use of DESCRIPTION in templates to get at the meta description
-     value. (Thanks, NicolasLimare)
-   * inline: Use caching of inlined pages to speed up builds of inlines that
-     include feeds. Speedup of about 25% for small inlines; could be much
-     larger for inlines of many, or complex pages.
-   * Added (incomplete) Turkish po file. Closes: #[556744](http://bugs.debian.org/556744)
-     Thanks, Recai Oktaş
-   * date: New plugin that allows inserting date directives that expand to
-     pretty-printed dates, using the same formatting as used for page
-     modification date display, etc.
-   * htmllink: Allow a title attribute to be specified.
-   * calendar: Add title attributes for all links in the calendars.
-   * calendar: Fix month wraparound error that broke in December."""]]
\ No newline at end of file
diff --git a/doc/news/version_3.20100302.mdwn b/doc/news/version_3.20100302.mdwn
new file mode 100644
index 0000000..f439b1b
--- /dev/null
+++ b/doc/news/version_3.20100302.mdwn
@@ -0,0 +1,12 @@
+ikiwiki 3.20100302 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * comments: Display number of comments in comment action link.
+   * Rebuild wikis on upgrade to this version to get the comment counts
+     added to existing pages.
+   * Loosen regexp, to allow empty quoted parameters in directives.
+   * Add force\_overwrite setting to make setup automator overwrite existing
+     files/directories.
+   * Fix admin openid detection in setup automator, and avoid prompting
+     for a password.
+   * Add new --clean option; this makes ikiwiki remove all built
+     files in the destdir, as well as wrappers and the .ikiwiki directory."""]]
\ No newline at end of file

Posting my change to the 404 module
diff --git a/doc/bugs/404_plugin_and_lighttpd.mdwn b/doc/bugs/404_plugin_and_lighttpd.mdwn
index 29ca107..ffbad8a 100644
--- a/doc/bugs/404_plugin_and_lighttpd.mdwn
+++ b/doc/bugs/404_plugin_and_lighttpd.mdwn
@@ -11,3 +11,25 @@ This is with lighttpd 1.4.19 on Debian.
 > I originally wrote the plugin for Apache; [[weakish]] contributed the
 > lighttpd docs and might know more about how to make it work there.
 > --[[smcv]]
+
+>> As I said, I got it working for me, but somebody who knows perl should probably look at it with the aim of making it work for everyone.
+>> I considered having lighttpd construct a proper url for the 404 redirect itself, but I don't know if it can do something like that or not.
+>> For what it's worth, here's the change I made to the module:
+
+    sub cgi ($) {
+            my $cgi=shift;
+            if ($ENV{REQUEST_URI} !~ /ikiwiki\.cgi/) {
+                    my $page = cgi_page_from_404(
+                            Encode::decode_utf8($ENV{SERVER_NAME} . $ENV{REQUEST_URI}),
+                            $config{url}, $config{usedirs});
+                    IkiWiki::Plugin::goto::cgi_goto($cgi, $page);
+            }
+    
+    #       if (exists $ENV{REDIRECT_STATUS} &&
+    #           $ENV{REDIRECT_STATUS} eq '404') {
+    #               my $page = cgi_page_from_404(
+    #                       Encode::decode_utf8($ENV{REDIRECT_URL}),
+    #                       $config{url}, $config{usedirs});
+    #               IkiWiki::Plugin::goto::cgi_goto($cgi, $page);
+    #       }
+    }

diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index 12d6929..345604c 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -140,6 +140,7 @@ Personal sites and blogs
 * [Alex Ghitza homepage and blog](http://aghitza.org/)
 * [Mukund's homepage](http://www.mukund.org/)
 * [Andreas's homepage](http://0x7.ch/) - Ikiwiki, Subversion and CSS template
+* [Chris Dombroski's boring bliki](https://www.icanttype.org/)
 
 Please feel free to add your own ikiwiki site!
 

diff --git a/doc/bugs/404_plugin_and_lighttpd.mdwn b/doc/bugs/404_plugin_and_lighttpd.mdwn
index e60fd20..29ca107 100644
--- a/doc/bugs/404_plugin_and_lighttpd.mdwn
+++ b/doc/bugs/404_plugin_and_lighttpd.mdwn
@@ -3,3 +3,11 @@ Lighttpd apparently sets REDIRECT_STATUS=200 for the server.error-handler-404 pa
 I was able to fix my server to check the REQUEST_URI for ikiwiki.cgi and to continue processing if it was not found, passing $ENV{SEVER_NAME} . $ENV{REQUEST_URI} as the first parameter to cgi_page_from_404. However, my perl is terrible and I just made it work rather than figuring out exactly what to do to get it to work on both lighttpd and apache.
 
 This is with lighttpd 1.4.19 on Debian.
+
+> /cgi-bin/ikiwiki.cgi?do=goto also provides redirection in the same way,
+> if that's any help? You might need to set the lighttpd 404 handler to
+> that, then compose REDIRECT_URL from other variables if necessary.
+>
+> I originally wrote the plugin for Apache; [[weakish]] contributed the
+> lighttpd docs and might know more about how to make it work there.
+> --[[smcv]]

Bug: 404 plugin & lighttpd
diff --git a/doc/bugs/404_plugin_and_lighttpd.mdwn b/doc/bugs/404_plugin_and_lighttpd.mdwn
new file mode 100644
index 0000000..e60fd20
--- /dev/null
+++ b/doc/bugs/404_plugin_and_lighttpd.mdwn
@@ -0,0 +1,5 @@
+Lighttpd apparently sets REDIRECT_STATUS=200 for the server.error-handler-404 page. This breaks the 404 plugin which checks this variable for 404 before processing the URI. It also doesn't seem to set REDIRECT_URL.
+
+I was able to fix my server to check the REQUEST_URI for ikiwiki.cgi and to continue processing if it was not found, passing $ENV{SEVER_NAME} . $ENV{REQUEST_URI} as the first parameter to cgi_page_from_404. However, my perl is terrible and I just made it work rather than figuring out exactly what to do to get it to work on both lighttpd and apache.
+
+This is with lighttpd 1.4.19 on Debian.

diff --git a/doc/bugs/External_links_with_Creole.mdwn b/doc/bugs/External_links_with_Creole.mdwn
new file mode 100644
index 0000000..3d800b0
--- /dev/null
+++ b/doc/bugs/External_links_with_Creole.mdwn
@@ -0,0 +1,3 @@
+When using Creole for markup, creating an external link appears to be impossible. Neither \[[Outside URL|http://example.com]] nor <<http://example.com>> nor \[Outside URL]\(http://example.com) work. The first gets rendered as a broken WikiLink, the second get eaten and the last is not parsed in anyway so you end up with that exact text in your page. 
+
+I'd have made this as a Creole page as a practical demonstration, but that doesn't seem possible here. Here's a page with an example: <https://www.icanttype.org//demo/CreoleExternalLinks>

response
diff --git a/doc/plugins/creole/discussion.mdwn b/doc/plugins/creole/discussion.mdwn
index eab4134..7f47c2c 100644
--- a/doc/plugins/creole/discussion.mdwn
+++ b/doc/plugins/creole/discussion.mdwn
@@ -18,3 +18,5 @@ I've installed Text::WikiCreole 0.05 and enabled the plugin, but I get an error
 I'm moving over a really stinkingly old UseMod and creole seems the nearest match. I've worked out that Bare /Subpage links need to become \[\[Subpage\]\], and Top/Sub links need to be \[\[Top/Sub\]\] (or \[\[Top/Sub|Top/Sub\]\], to display in exactly the same way), but I'm stuck on generic hyperlinks. The creole cheat sheet says I should be able to do \[\[http://url.path/foo|LinkText\]\], but that comes out as a link to create the "linktext" page, and Markdown-style \[Link Text\](http://url.path/foo) just gets rendered as is. Any suggestions? --[[schmonz]]
 
 > Was this problem ever solved? -- Thiana
+
+>> Not by me. If I were looking at the problem now, with fresh eyes, I'd probably bite the bullet and just convert everything to Markdown. --[[schmonz]]

diff --git a/doc/plugins/creole/discussion.mdwn b/doc/plugins/creole/discussion.mdwn
index 38ee2bd..eab4134 100644
--- a/doc/plugins/creole/discussion.mdwn
+++ b/doc/plugins/creole/discussion.mdwn
@@ -12,4 +12,9 @@ I've installed Text::WikiCreole 0.05 and enabled the plugin, but I get an error
 
 >>> forgot, done now --[[Joey]] 
 
+---
+## External Links
+
 I'm moving over a really stinkingly old UseMod and creole seems the nearest match. I've worked out that Bare /Subpage links need to become \[\[Subpage\]\], and Top/Sub links need to be \[\[Top/Sub\]\] (or \[\[Top/Sub|Top/Sub\]\], to display in exactly the same way), but I'm stuck on generic hyperlinks. The creole cheat sheet says I should be able to do \[\[http://url.path/foo|LinkText\]\], but that comes out as a link to create the "linktext" page, and Markdown-style \[Link Text\](http://url.path/foo) just gets rendered as is. Any suggestions? --[[schmonz]]
+
+> Was this problem ever solved? -- Thiana

diff --git a/doc/ikiwiki/directive/inline/discussion.mdwn b/doc/ikiwiki/directive/inline/discussion.mdwn
index 998ba64..6a186cd 100644
--- a/doc/ikiwiki/directive/inline/discussion.mdwn
+++ b/doc/ikiwiki/directive/inline/discussion.mdwn
@@ -1,3 +1,10 @@
+## Combine inline and toggle
+
+Is it possible to combine the behaviour of toggle and inline? ie, have it present of list of 'headlines' which are created from seperate subpages which can be clicked to expand to the body of the inlined page. Thanks.
+
+-- Thiana
+
+---
 ## How do you provide the per post discussion links in your own blog?
 
 > That's configured by the "actions" parameter to the inline directive. See

diff --git a/doc/plugins/rename.mdwn b/doc/plugins/rename.mdwn
index ddaede8..abb3613 100644
--- a/doc/plugins/rename.mdwn
+++ b/doc/plugins/rename.mdwn
@@ -2,7 +2,8 @@
 [[!tag type/web]]
 
 This plugin allows pages or other files to be renamed using the web
-interface.
+interface. Following Unix tradition, renaming also allows moving to a
+different directory.
 
 Users can only rename things that they are allowed to edit or upload.
 

fixed typo
diff --git a/doc/plugins/contrib/report.mdwn b/doc/plugins/contrib/report.mdwn
index e8cbd04..c364d4a 100644
--- a/doc/plugins/contrib/report.mdwn
+++ b/doc/plugins/contrib/report.mdwn
@@ -89,7 +89,7 @@ The "mood_summary" template might be like this:
     ## <TMPL_VAR NAME="HEADER1">
     </TMPL_IF>
     ### <TMPL_VAR NAME="TITLE">
-    (<TMPL_VAR NAME="DATE">) \[[<TMPL_VAR NAME="PAGE"]]
+    (<TMPL_VAR NAME="DATE">) \[[<TMPL_VAR NAME="PAGE">]]
     <TMPL_VAR NAME="DESCRIPTION">
     
 ### Advanced Options

ref new tip from softwaresite page
diff --git a/doc/examples/softwaresite.mdwn b/doc/examples/softwaresite.mdwn
index e43a9d1..99f7911 100644
--- a/doc/examples/softwaresite.mdwn
+++ b/doc/examples/softwaresite.mdwn
@@ -14,3 +14,6 @@ Some additional configuration you might want to do:
 
 * Read the [[tips/integrated_issue_tracking_with_ikiwiki]] article for tips
   about how to use ikiwiki as a BTS.
+
+* Read [[tips/spam_and_softwaresites]] for information on how to keep spam
+  and spam-fighting commits out of your main version control history.

new tip: spam and software sites
diff --git a/doc/tips/spam_and_softwaresites.mdwn b/doc/tips/spam_and_softwaresites.mdwn
new file mode 100644
index 0000000..fe73518
--- /dev/null
+++ b/doc/tips/spam_and_softwaresites.mdwn
@@ -0,0 +1,86 @@
+Any wiki with a form of web-editing enabled will have to deal with
+spam. (See the [[plugins/blogspam]] plugin for one defensive tool you
+can deploy).
+
+If:
+
+ * you are using ikiwiki to manage the website for a [[examples/softwaresite]]
+ * you allow web-based commits, to let people correct documentation, or report
+   bugs, etc.
+ * the documentation is stored in the same revision control repository as your
+   software
+
+It is undesirable to have your software's VCS history tainted by spam and spam
+clean-up commits. Here is one approach you can use to prevent this. This
+example is for the [[git]] version control system, but the principles should
+apply to others.
+
+## Isolate web commits to a specific branch
+
+Create a separate branch to contain web-originated edits (named `doc` in this
+example):
+
+    $ git checkout -b doc
+
+Adjust your setup file accordingly:
+
+    gitmaster_branch => 'doc',
+
+## merging good web commits into the master branch
+
+You will want to periodically merge legitimate web-based commits back into
+your master branch. Ensure that there is no spam in the documentation
+branch. If there is, see 'erase spam from the commit history', below, first.
+
+Once you are confident it's clean:
+
+    # ensure you are on the doc branch
+    $ git branch
+      doc
+    * master
+    $ git merge --ff doc
+
+## removing spam
+
+### short term
+
+In the short term, just revert the spammy commit.
+
+If the spammy commit was the top-most:
+
+    $ git revert HEAD
+
+This will clean the spam out of the files, but it will leave both the spam
+commit and the revert commit in the history.
+
+### erase spam from the commit history
+
+Git allows you to rewrite your commit history.  We will take advantage of this
+to eradicate spam from the history of the doc branch.
+
+This is a useful tool, but it is considered bad practise to rewrite the
+history of public repositories. If your software's repository is public, you
+should make it clear that the history of the `doc` branch in your repository
+is unstable.
+
+Once you have been spammed, use `git rebase` to remove the spam commits from
+the history.  Assuming that your `doc` branch was split off from a branch
+called `master`:
+
+    # ensure you are on the doc branch
+    $ git branch
+    * doc
+      master
+    $ git rebase --interactive master
+
+In your editor session, you will see a series of lines for each commit made to
+the `doc` branch since it was branched from `master` (or since the last merge
+back into `master`). Delete the lines corresponding to spammy commits, then
+save and exit your editor.
+
+Caveat: if there are no commits you want to keep (i.e. all the commits since
+the last merge into master are either spam or spam reverts) then `git rebase`
+will abort. Therefore, this approach only works if you have at least one
+non-spam commit to the documentation since the last merge into `master`. For
+this reason, it's best to tackle spam with reverts until you have at least one
+commit you want merged back into the main history.

wl from report to field plugin pages
diff --git a/doc/plugins/contrib/report.mdwn b/doc/plugins/contrib/report.mdwn
index 7130bcb..e8cbd04 100644
--- a/doc/plugins/contrib/report.mdwn
+++ b/doc/plugins/contrib/report.mdwn
@@ -18,7 +18,7 @@ IkiWiki::Plugin::report - Produce templated reports from page field data.
 
 This plugin provides the **report** directive.  This enables one to report on
 the structured data ("field" values) of multiple pages; the output is formatted
-via a template.  This depends on the "field" plugin.
+via a template.  This depends on the [[plugins/contrib/field]] plugin.
 
 The pages to report on are selected by a PageSpec given by the "pages"
 parameter.  The template is given by the "template" parameter.

Add new --clean option; this makes ikiwiki remove all built files in the destdir, as well as wrappers and the .ikiwiki directory.
diff --git a/IkiWiki.pm b/IkiWiki.pm
index 9df6c90..00eadfd 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -409,6 +409,13 @@ sub getsetup () {
 		safe => 0,
 		rebuild => 0,
 	},
+	clean => {
+		type => "internal",
+		default => 0,
+		description => "running in clean mode",
+		safe => 0,
+		rebuild => 0,
+	},
 	refresh => {
 		type => "internal",
 		default => 0,
diff --git a/IkiWiki/Render.pm b/IkiWiki/Render.pm
index 3ebb1a3..af24df1 100644
--- a/IkiWiki/Render.pm
+++ b/IkiWiki/Render.pm
@@ -683,6 +683,17 @@ sub refresh () {
 	}
 }
 
+sub clean_rendered {
+	lockwiki();
+	loadindex();
+	remove_unrendered();
+	foreach my $page (keys %oldrenderedfiles) {
+		foreach my $file (@{$oldrenderedfiles{$page}}) {
+			prune($config{destdir}."/".$file);
+		}
+	}
+}
+
 sub commandline_render () {
 	lockwiki();
 	loadindex();
diff --git a/Makefile.PL b/Makefile.PL
index 462f736..52421a7 100755
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -51,7 +51,7 @@ docwiki: ikiwiki.out
 	$(PERL) -Iblib/lib $(extramodules) $(tflag) ikiwiki.out -libdir . -setup docwiki.setup -refresh
 
 extra_clean:
-	rm -rf html doc/.ikiwiki
+	$(PERL) -I. $(extramodules) $(tflag) ikiwiki.in -libdir . -setup docwiki.setup -clean
 	rm -f *.man ikiwiki.out ikiwiki.setup plugins/*.pyc
 	$(MAKE) -C po clean
 
diff --git a/debian/changelog b/debian/changelog
index 832bbaa..3b92c59 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,4 +1,4 @@
-ikiwiki (3.20100213) UNRELEASED; urgency=low
+ikiwiki (3.20100228) UNRELEASED; urgency=low
 
   * comments: Display number of comments in comment action link.
   * Rebuild wikis on upgrade to this version to get the comment counts
@@ -8,6 +8,8 @@ ikiwiki (3.20100213) UNRELEASED; urgency=low
     files/directories.
   * Fix admin openid detection in setup automator, and avoid prompting
     for a password.
+  * Add new --clean option; this makes ikiwiki remove all built
+    files in the destdir, as well as wrappers and the .ikiwiki directory.
 
  -- Joey Hess <joeyh@debian.org>  Sun, 14 Feb 2010 17:02:10 -0500
 
diff --git a/doc/usage.mdwn b/doc/usage.mdwn
index e4808d4..a105d7e 100644
--- a/doc/usage.mdwn
+++ b/doc/usage.mdwn
@@ -50,6 +50,14 @@ These options control the mode that ikiwiki operates in.
   If used with --setup --refresh, this makes it also update any configured
   wrappers.
 
+* --clean
+
+  This makes ikiwiki clean up by removing any files it denerated in the 
+  `destination` directory, as well as any configured wrappers, and the
+  `.ikiwiki` state directory. This is mostly useful if you're running
+  ikiwiki in a Makefile to build documentation and want a corresponding
+  `clean` target.
+
 * --cgi
 
   Enable [[CGI]] mode. In cgi mode ikiwiki runs as a cgi script, and
diff --git a/ikiwiki.in b/ikiwiki.in
index b8581d8..ae1251f 100755
--- a/ikiwiki.in
+++ b/ikiwiki.in
@@ -37,6 +37,7 @@ sub getconfig () {
 			"syslog!" => \$config{syslog},
 			"rebuild!" => \$config{rebuild},
 			"refresh!" => \$config{refresh},
+			"clean!" => \$config{clean},
 			"post-commit" => \$config{post_commit},
 			"render=s" => \$config{render},
 			"wrappers!" => \$config{genwrappers},
@@ -135,6 +136,7 @@ sub main () {
 
 		if (@{$config{wrappers}} && 
 		    ! $config{render} && ! $config{dumpsetup} &&
+		    ! $config{clean} &&
 		    ((! $config{refresh} && ! $config{post_commit})
 		     || $config{genwrappers})) {
 			debug(gettext("generating wrappers.."));
@@ -159,7 +161,7 @@ sub main () {
 		
 		# setup implies a wiki rebuild by default
 		if (! $config{refresh} && ! $config{render} &&
-		    ! $config{post_commit}) {
+		    ! $config{post_commit} && ! $config{clean}) {
 			$config{rebuild}=1;
 		}
 	}
@@ -190,6 +192,14 @@ sub main () {
 	elsif ($config{post_commit} && ! commit_hook_enabled()) {
 		# do nothing
 	}
+	elsif ($config{clean}) {
+		require IkiWiki::Render;
+		foreach my $wrapper (@{$config{wrappers}}) {
+			prune($wrapper->{wrapper});
+		}
+		clean_rendered();
+		system("rm", "-rf", $config{wikistatedir});
+	}
 	else {
 		if ($config{rebuild}) {
 			debug(gettext("rebuilding wiki.."));
diff --git a/ikiwiki.spec b/ikiwiki.spec
index 865c9a3..1dba9f4 100644
--- a/ikiwiki.spec
+++ b/ikiwiki.spec
@@ -1,5 +1,5 @@
 Name:           ikiwiki
-Version: 3.20100212
+Version: 3.20100228
 Release:        1%{?dist}
 Summary:        A wiki compiler
 

diff --git a/doc/users/jeanprivat.mdwn b/doc/users/jeanprivat.mdwn
new file mode 100644
index 0000000..4d75a98
--- /dev/null
+++ b/doc/users/jeanprivat.mdwn
@@ -0,0 +1 @@
+Jean Privat is <jean@pryen.org>.

patch for multiple sidebars
diff --git a/doc/todo/beef_up_sidebar_to_allow_for_multiple_sidebars.mdwn b/doc/todo/beef_up_sidebar_to_allow_for_multiple_sidebars.mdwn
index fb942a4..02b8324 100644
--- a/doc/todo/beef_up_sidebar_to_allow_for_multiple_sidebars.mdwn
+++ b/doc/todo/beef_up_sidebar_to_allow_for_multiple_sidebars.mdwn
@@ -13,5 +13,57 @@ those contents instead.
 
 > In mine I just copied sidebar out and made some extra "sidebars", but they go elsewhere. Ugly hack, but it works. --[[simonraven]]
 
+>> Here a simple [[patch]] for multiple sidebars. Not too fancy but better than having multiple copies of the sidebar plugin. --[[jeanprivat]]
+
+<pre>
+--- /usr/share/perl5/IkiWiki/Plugin/sidebar.pm	2010-02-11 22:53:17.000000000 -0500
++++ plugins/IkiWiki/Plugin/sidebar.pm	2010-02-27 09:54:12.524412391 -0500
+@@ -19,12 +19,20 @@
+ 			safe => 1,
+ 			rebuild => 1,
+ 		},
++		active_sidebars => {
++			type => "string",
++			example => qw(sidebar banner footer),
++			description => "Which sidebars must be activated and processed.",
++			safe => 1,
++			rebuild => 1
++		},
+ }
+ 
+-sub sidebar_content ($) {
++sub sidebar_content ($$) {
+ 	my $page=shift;
++	my $sidebar=shift;
+ 	
+-	my $sidebar_page=bestlink($page, "sidebar") || return;
++	my $sidebar_page=bestlink($page, $sidebar) || return;
+ 	my $sidebar_file=$pagesources{$sidebar_page} || return;
+ 	my $sidebar_type=pagetype($sidebar_file);
+ 	
+@@ -49,11 +57,17 @@
+ 
+ 	my $page=$params{page};
+ 	my $template=$params{template};
+-	
+-	if ($template->query(name => "sidebar")) {
+-		my $content=sidebar_content($page);
+-		if (defined $content && length $content) {
+-		        $template->param(sidebar => $content);
++
++	my @sidebars;
++	if (defined $config{active_sidebars} && length $config{active_sidebars}) { @sidebars = @{$config{active_sidebars}}; }
++	else { @sidebars = qw(sidebar); }
++
++	foreach my $sidebar (@sidebars) {
++		if ($template->query(name => $sidebar)) {
++			my $content=sidebar_content($page, $sidebar);
++			if (defined $content && length $content) {
++				$template->param($sidebar => $content);
++			}
+ 		}
+ 	}
+ }
+</pre>
 
 [[!tag wishlist]]

disable some inlines that I don't use much.
diff --git a/doc/users/Will.mdwn b/doc/users/Will.mdwn
index f5effdb..1956263 100644
--- a/doc/users/Will.mdwn
+++ b/doc/users/Will.mdwn
@@ -13,14 +13,16 @@ Unless otherwise specified, any code that I post to this wiki I release under th
 
 ------
 
+Disabling these as I'm not using them much any more...
+
 ### Open Bugs:
 
-[[!inline pages="link(users/Will) and bugs/* and !bugs/done and !bugs/discussion and !link(patch) and !link(bugs/done) and !bugs/*/*" archive="yes" feeds="no" ]]
+\[[!inline pages="link(users/Will) and bugs/* and !bugs/done and !bugs/discussion and !link(patch) and !link(bugs/done) and !bugs/*/*" archive="yes" feeds="no" ]]
 
 ### Open ToDos:
 
-[[!inline pages="link(users/Will) and todo/* and !todo/done and !todo/discussion and !link(patch) and !link(todo/done) and !bugs/*/*" archive="yes" feeds="no" ]]
+\[[!inline pages="link(users/Will) and todo/* and !todo/done and !todo/discussion and !link(patch) and !link(todo/done) and !bugs/*/*" archive="yes" feeds="no" ]]
 
 ### Unapplied Patches:
 
-[[!inline pages="link(users/Will) and (todo/* or bugs/*) and !bugs/done and !bugs/discussion and !todo/done and !todo/discussion and link(patch) and !link(bugs/done) and !link(todo/done) and !bugs/*/*" archive="yes" feeds="no" ]]
+\[[!inline pages="link(users/Will) and (todo/* or bugs/*) and !bugs/done and !bugs/discussion and !todo/done and !todo/discussion and link(patch) and !link(bugs/done) and !link(todo/done) and !bugs/*/*" archive="yes" feeds="no" ]]

made a suggestion
diff --git a/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn b/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn
index bc19e7d..de178d4 100644
--- a/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn
+++ b/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn
@@ -14,3 +14,5 @@ The [[ikiwiki/directive/map]] directive sort by pagename. That looks kind of odd
 >> 1. inline also does sort by pagename even when explicitly told to sort by title.
 >>
 >> 2. I cannot get inline to create a list when the htmltidy plugin is switched on. I have a template which is enclosed in an li tag, and i put the ul tag around the inline manually, but htmltidy breaks this. --martin
+
+>>>> You might want to check if the [[plugins/contrib/report]] plugin solves your problem.  It can sort by title, among other things. --[[KathrynAndersen]]

diff --git a/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn b/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn
index f8e257d..bc19e7d 100644
--- a/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn
+++ b/doc/bugs/map_sorts_by_pagename_and_not_title_when_show__61__title_is_used.mdwn
@@ -1,4 +1,4 @@
-The [[directive/map]] directive sorty by pagename. That looks kind of odd, when used together with show=title. I would expect it to sort by title then.
+The [[ikiwiki/directive/map]] directive sort by pagename. That looks kind of odd, when used together with show=title. I would expect it to sort by title then.
 
 > This would be quite hard to fix. Map sorts the pages it displays by page
 > name, which has the happy effect of making "foo/bar" come after "foo";
@@ -6,3 +6,11 @@ The [[directive/map]] directive sorty by pagename. That looks kind of odd, when
 > it's located in. If sorting by title, that wouldn't hold. So, map
 > would have to be effectively totally rewritten, to build up each group
 > of child pages, and then re-sort those. --[[Joey]] 
+
+>> Ok, you are right, that does would break the tree. This made me think that I do not
+>> need to generate a tree for my particular use case just a list, so i thought i could use [[ikiwiki/directive/inline]] instead.
+>> This created two new issues:
+>>
+>> 1. inline also does sort by pagename even when explicitly told to sort by title.
+>>
+>> 2. I cannot get inline to create a list when the htmltidy plugin is switched on. I have a template which is enclosed in an li tag, and i put the ul tag around the inline manually, but htmltidy breaks this. --martin

diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index 62064e0..12d6929 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -139,6 +139,7 @@ Personal sites and blogs
 * [Backyard Deer](http://www.backyarddeer.com/)
 * [Alex Ghitza homepage and blog](http://aghitza.org/)
 * [Mukund's homepage](http://www.mukund.org/)
+* [Andreas's homepage](http://0x7.ch/) - Ikiwiki, Subversion and CSS template
 
 Please feel free to add your own ikiwiki site!
 

switch to inline, instead of map
diff --git a/doc/users/jon.mdwn b/doc/users/jon.mdwn
index 35bdb5d..d5593dc 100644
--- a/doc/users/jon.mdwn
+++ b/doc/users/jon.mdwn
@@ -55,4 +55,4 @@ Penultimately, the following are merely half-formed thoughts:
 Finally, backlinks (since I have issues with the current backlinks
 implementation, see [[bugs/backlinks onhover thing can go weird]]):
 
-[[!map pages="link(users/Jon)"]]
+[[!inline pages="link(users/Jon)" archive="yes" feeds="no"]]

add a backlink-style map to the bottom of my page
diff --git a/doc/users/jon.mdwn b/doc/users/jon.mdwn
index f08076c..35bdb5d 100644
--- a/doc/users/jon.mdwn
+++ b/doc/users/jon.mdwn
@@ -45,9 +45,14 @@ The following I have been looking at, but are on the back-burner:
   bugs such as [[bugs/tagged() matching wikilinks]]. Code for this lives
   in my github `tag2` branch: <http://github.com/jmtd/ikiwiki>
 
-Finally, the following are merely half-formed thoughts:
+Penultimately, the following are merely half-formed thoughts:
 
  * adding and removing tags to pages via the edit form by ticking and
    unticking checkboxes next to a tag name (rather than entering the 
    directive into the text of the page directly)
  * perhaps the same for meta
+
+Finally, backlinks (since I have issues with the current backlinks
+implementation, see [[bugs/backlinks onhover thing can go weird]]):
+
+[[!map pages="link(users/Jon)"]]

The Fvwm Wiki not a personal site or blog.
diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index 958bd54..62064e0 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -52,6 +52,7 @@ Projects & Organizations
 * [Wetknee Books](http://www.wetknee.com/)
 * [IPOL Image Processing On Line](http://www.ipol.im)
 * [Debian Costa Rica](http://cr.debian.net/)
+* [Fvwm Wiki](http://fvwmwiki.xteddy.org)
 
 Personal sites and blogs
 ========================
@@ -138,7 +139,6 @@ Personal sites and blogs
 * [Backyard Deer](http://www.backyarddeer.com/)
 * [Alex Ghitza homepage and blog](http://aghitza.org/)
 * [Mukund's homepage](http://www.mukund.org/)
-* [Fvwm Wiki](http://fvwmwiki.xteddy.org)
 
 Please feel free to add your own ikiwiki site!
 

The Fvwmwiki uses ikiwiki
diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index c9dea83..958bd54 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -138,6 +138,7 @@ Personal sites and blogs
 * [Backyard Deer](http://www.backyarddeer.com/)
 * [Alex Ghitza homepage and blog](http://aghitza.org/)
 * [Mukund's homepage](http://www.mukund.org/)
+* [Fvwm Wiki](http://fvwmwiki.xteddy.org)
 
 Please feel free to add your own ikiwiki site!
 

ctime idea
diff --git a/doc/todo/auto_getctime_on_fresh_build.mdwn b/doc/todo/auto_getctime_on_fresh_build.mdwn
new file mode 100644
index 0000000..ea95fb8
--- /dev/null
+++ b/doc/todo/auto_getctime_on_fresh_build.mdwn
@@ -0,0 +1,9 @@
+[[!tag wishlist]]
+
+It might be a good idea to enable --getctime when `.ikiwiki` does not
+exist. This way a new checkout of a `srcdir` would automatically get
+ctimes right. (Running --getctime whenever a rebuild is done would be too
+slow.) --[[Joey]] 
+
+Could this be too annoying in some cases, eg, checking out a large wiki
+that needs to get set up right away? --[[Joey]] 

response
diff --git a/doc/todo/double-click_protection_for_form_buttons.mdwn b/doc/todo/double-click_protection_for_form_buttons.mdwn
index 4c0d95b..501be44 100644
--- a/doc/todo/double-click_protection_for_form_buttons.mdwn
+++ b/doc/todo/double-click_protection_for_form_buttons.mdwn
@@ -1 +1,5 @@
 A small piece of JS to prevent double-submitting forms would be quite nice. I seem to have developed a habit of doing this and having to resolve a merge conflict for two initial commits. -- [[Jon]]
+
+> By the time you see that merge conflict, the first commit has
+> already successfully happened, so you can just hit cancel
+> and throw away the second submit. --[[Joey]] 

response
diff --git a/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn b/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn
index 8cc97a0..8613ef0 100644
--- a/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn
+++ b/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn
@@ -5,3 +5,8 @@ I've noticed this with the debian package version 3.20100102.3~bpo50+1.
 Perhaps it is possible to improve this or mention it in the manual page?
 
 --prosper
+
+> --rebuild causes ikiwiki to throw away all its info about what it built
+> before, so it will never clean up pages that have been removed, by any
+> means. Suggest you do a --refresh, possibly followed by a --rebuild
+> if that is really necessary. --[[Joey]]

prevent keyboard mashing
diff --git a/doc/todo/double-click_protection_for_form_buttons.mdwn b/doc/todo/double-click_protection_for_form_buttons.mdwn
new file mode 100644
index 0000000..4c0d95b
--- /dev/null
+++ b/doc/todo/double-click_protection_for_form_buttons.mdwn
@@ -0,0 +1 @@
+A small piece of JS to prevent double-submitting forms would be quite nice. I seem to have developed a habit of doing this and having to resolve a merge conflict for two initial commits. -- [[Jon]]

fix 'done' link
diff --git a/doc/todo/conflict_free_comment_merges.mdwn b/doc/todo/conflict_free_comment_merges.mdwn
index 2cef0ee..e84400c 100644
--- a/doc/todo/conflict_free_comment_merges.mdwn
+++ b/doc/todo/conflict_free_comment_merges.mdwn
@@ -20,4 +20,4 @@ What do you think [[smcv]]? --[[Joey]]
 > are quite low since it modifies the input text and adds a date stamp to
 > it.
 >
-> Anyway, I think it's good, [[[done]] --[[Joey]] 
+> Anyway, I think it's good, [[done]] --[[Joey]] 

Correct broken links
diff --git a/doc/users/jogo.mdwn b/doc/users/jogo.mdwn
index 6f87cbc..e8068a1 100644
--- a/doc/users/jogo.mdwn
+++ b/doc/users/jogo.mdwn
@@ -1,5 +1,5 @@
  * An [economic game](http://sef.matabio.net/) in french, which [use](http://sef.matabio.net/wiki/) IkiWiki.
- * Some [plugins](http://kimya.matabio.net/tcgi/hg/IkiPlugins/file/).
- * An alternative [base wiki](http://kimya.matabio.net/tcgi/hg/FrIkiWiki/file/) in french.
+ * Some [plugins](http://www.matabio.net/tcgi/hg/IkiPlugins/file/).
+ * An alternative [base wiki](http://www.matabio.net/tcgi/hg/FrIkiWiki/file/) in french.
 
 email: `jogo matabio net`.

diff --git a/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn b/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn
new file mode 100644
index 0000000..8cc97a0
--- /dev/null
+++ b/doc/bugs/rebuild_after_changing_the_underlaydir_config_option.mdwn
@@ -0,0 +1,7 @@
+It seems that rebuild a wiki (`ikiwiki --rebuild`) after changing the `underlaydir` config option doesn't remove the pages coming from the previous underlaydir. 
+
+I've noticed this with the debian package version 3.20100102.3~bpo50+1.
+
+Perhaps it is possible to improve this or mention it in the manual page?
+
+--prosper

Add my homepage generated by Ikiwiki
diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index df2d6b6..c9dea83 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -137,6 +137,7 @@ Personal sites and blogs
 * [Cosmic Cookout](http://www.cosmiccookout.com/)
 * [Backyard Deer](http://www.backyarddeer.com/)
 * [Alex Ghitza homepage and blog](http://aghitza.org/)
+* [Mukund's homepage](http://www.mukund.org/)
 
 Please feel free to add your own ikiwiki site!
 

new feature request: identifying trivial edits
diff --git a/doc/todo/mark_edit_as_trivial__44___identify__47__filter_on_trivial_changes.mdwn b/doc/todo/mark_edit_as_trivial__44___identify__47__filter_on_trivial_changes.mdwn
new file mode 100644
index 0000000..2b2b024
--- /dev/null
+++ b/doc/todo/mark_edit_as_trivial__44___identify__47__filter_on_trivial_changes.mdwn
@@ -0,0 +1,11 @@
+One feature of mediawiki which I quite like is the ability to mark a change as 'minor', or 'trivial'. This can then be used to filter the 'recentchanges' page, to only show substantial edits.
+
+The utility of this depends entirely on whether the editors use it properly.
+
+I currently use an inline on the front page of my personal homepage to show the most recent pages (by creation date) within a subsection of my site (a blog). Blog posts are rarely modified much after they are 'created' (or published - I bodge the creation time via meta when I publish a post. It might sit in draft form indefinitely), so this effectively shows only non-trivial changes.
+
+I would like to have a short list of the most recent modifications to the site on the front page. I therefore want to sort by modified time rather than creation time, but exclude edits that I self-identify as minor. I also only want to take a short number of items, the top 5, and display only their titles (which may be derived from filename, or set via meta again).
+
+I'm still thinking through how this might be achieved in an ikiwiki-suitable fashion, but I think I need a scheme to identify certain edits as trivial. This would have to work via web edits (easier: could add a check box to the edit form) and plain changes in the VCS (harder: scan for keywords in a commit message? in a VCS-agnostic fashion?)
+
+[[!tag wishlist]]

s/redirect/redir/
diff --git a/doc/users/NicolasLimare.mdwn b/doc/users/NicolasLimare.mdwn
index c409e3a..56a950f 100644
--- a/doc/users/NicolasLimare.mdwn
+++ b/doc/users/NicolasLimare.mdwn
@@ -1 +1 @@
-[[!meta redirect="nil"]]
+[[!meta redir="nil"]]

typo
diff --git a/doc/todo/cdate_and_mdate_available_for_templates.mdwn b/doc/todo/cdate_and_mdate_available_for_templates.mdwn
index 29c36b9..70d8fc8 100644
--- a/doc/todo/cdate_and_mdate_available_for_templates.mdwn
+++ b/doc/todo/cdate_and_mdate_available_for_templates.mdwn
@@ -1,4 +1,4 @@
-[[!tag whishlist]]
+[[!tag wishlist]]
 
 `CDATE_3339`, `CDATE_822`, `MDATE_3339` and `MDATE_822` template variables would be useful for evey page, at least for my templates with Dublin Core metadata.
 

whishlist
diff --git a/doc/todo/cdate_and_mdate_available_for_templates.mdwn b/doc/todo/cdate_and_mdate_available_for_templates.mdwn
new file mode 100644
index 0000000..29c36b9
--- /dev/null
+++ b/doc/todo/cdate_and_mdate_available_for_templates.mdwn
@@ -0,0 +1,15 @@
+[[!tag whishlist]]
+
+`CDATE_3339`, `CDATE_822`, `MDATE_3339` and `MDATE_822` template variables would be useful for evey page, at least for my templates with Dublin Core metadata.
+
+I tried to pick the relevant lines of the [[inline|plugins/inline]] plugin and hack it into a custom plugin, but it failed miserably because of my obvious lack of perl litteracy...
+
+Anyway, I'm sure this is almost nothing...
+
+* `sub date_822 ($) {}`
+* `sub date_3339 ($) {}`
+* and something like `$template->param('cdate_822' => date_822($IkiWiki::pagectime{$page}));`
+
+Anyone can fill the missing lines?
+
+-- [[nil]]

import
diff --git a/doc/users/nil.mdwn b/doc/users/nil.mdwn
new file mode 100644
index 0000000..e1826ce
--- /dev/null
+++ b/doc/users/nil.mdwn
@@ -0,0 +1,8 @@
+nil first used ikiwiki on a site/wiki/blog/something... and felt this approach much more comfortable than the usual web-only ones.
+Since then, ikiwiki is a kind of swiss army knife when it comes to build anything for the web.
+
+Can be reached at nicolas at limare.net
+
+The current big ikiwiki-powered project is <http://www.ipol.im> 
+
+TODO: document "how to split public/edition interfaces"

fix
diff --git a/doc/users/NicolasLimare.mdwn b/doc/users/NicolasLimare.mdwn
index 602d28b..c409e3a 100644
--- a/doc/users/NicolasLimare.mdwn
+++ b/doc/users/NicolasLimare.mdwn
@@ -1 +1 @@
-[[meta redirect="nil"]]
+[[!meta redirect="nil"]]

redirect
diff --git a/doc/users/NicolasLimare.mdwn b/doc/users/NicolasLimare.mdwn
index 003449d..602d28b 100644
--- a/doc/users/NicolasLimare.mdwn
+++ b/doc/users/NicolasLimare.mdwn
@@ -1,9 +1 @@
-Nicolas (nil) uses ikiwiki on a site/wiki/blog/something... and feels this approach much more comfortable than the usual web-only ones.
-
-He didn't touch any perl code before using ikiwiki, ant that was the first opportunity to propose tiny patches.
-
-Actualy, he would have felt much more comfortable with a python ikiwiki... :)
-
-Can be reached at nicolas at limare.net
-
-By the way, I can make translations to french if needed. And maybe to japanese.
\ No newline at end of file
+[[meta redirect="nil"]]

diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index ee060e0..df2d6b6 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -51,6 +51,7 @@ Projects & Organizations
 * [Fachschaft Informatik HU Berlin](http://fachschaft.informatik.hu-berlin.de/)
 * [Wetknee Books](http://www.wetknee.com/)
 * [IPOL Image Processing On Line](http://www.ipol.im)
+* [Debian Costa Rica](http://cr.debian.net/)
 
 Personal sites and blogs
 ========================

diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index 4502b58..ee060e0 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -135,6 +135,7 @@ Personal sites and blogs
 * [Avian Aqua Miser](http://www.avianaquamiser.com/)
 * [Cosmic Cookout](http://www.cosmiccookout.com/)
 * [Backyard Deer](http://www.backyarddeer.com/)
+* [Alex Ghitza homepage and blog](http://aghitza.org/)
 
 Please feel free to add your own ikiwiki site!
 

+ ipol.im
diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index 469fc0f..4502b58 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -50,6 +50,7 @@ Projects & Organizations
 * [The Philolexian Society of Columbia University](http://www.columbia.edu/cu/philo/)
 * [Fachschaft Informatik HU Berlin](http://fachschaft.informatik.hu-berlin.de/)
 * [Wetknee Books](http://www.wetknee.com/)
+* [IPOL Image Processing On Line](http://www.ipol.im)
 
 Personal sites and blogs
 ========================

add ngettext support & optimize gettext handling
As I was adding ngettext support, I realized I could optimize the gettext
functions by memoizing the creation of the gettext object. Note that
the object creation is still deferred until a gettext function is called,
to avoid unnecessary startup penalties on code paths that do not need
gettext.
A side benefit is that separate stub functions are no longer needed to
handle the C language case.
diff --git a/IkiWiki.pm b/IkiWiki.pm
index a96ff12..b9a419d 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -20,7 +20,7 @@ use Exporter q{import};
 our @EXPORT = qw(hook debug error template htmlpage deptype
                  add_depends pagespec_match pagespec_match_list bestlink
 		 htmllink readfile writefile pagetype srcfile pagename
-		 displaytime will_render gettext urlto targetpage
+		 displaytime will_render gettext ngettext urlto targetpage
 		 add_underlay pagetitle titlepage linkpage newpagefile
 		 inject add_link
                  %config %links %pagestate %wikistate %renderedfiles
@@ -1820,27 +1820,38 @@ sub file_pruned ($;$) {
 sub define_gettext () {
 	# If translation is needed, redefine the gettext function to do it.
 	# Otherwise, it becomes a quick no-op.
-	no warnings 'redefine';
+	my $gettext_obj;
+	my $getobj;
 	if ((exists $ENV{LANG} && length $ENV{LANG}) ||
 	    (exists $ENV{LC_ALL} && length $ENV{LC_ALL}) ||
 	    (exists $ENV{LC_MESSAGES} && length $ENV{LC_MESSAGES})) {
-	    	*gettext=sub {
-			my $gettext_obj=eval q{
+	    	$getobj=sub {
+			$gettext_obj=eval q{
 				use Locale::gettext q{textdomain};
 				Locale::gettext->domain('ikiwiki')
 			};
-
-			if ($gettext_obj) {
-				$gettext_obj->get(shift);
-			}
-			else {
-				return shift;
-			}
 		};
 	}
-	else {
-		*gettext=sub { return shift };
-	}
+
+	no warnings 'redefine';
+	*gettext=sub {
+		$getobj->() if $getobj;
+		if ($gettext_obj) {
+			$gettext_obj->get(shift);
+		}
+		else {
+			return shift;
+		}
+	};
+  	*ngettext=sub {
+		$getobj->() if $getobj;
+		if ($gettext_obj) {
+			$gettext_obj->nget(@_);
+		}
+		else {
+			return ($_[2] == 1 ? $_[0] : $_[1])
+		}
+	};
 }
 
 sub gettext {
@@ -1848,6 +1859,11 @@ sub gettext {
 	gettext(@_);
 }
 
+sub ngettext {
+	define_gettext();
+	ngettext(@_);
+}
+
 sub yesno ($) {
 	my $val=shift;
 
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index a8c9de2..96a2aa1 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -911,6 +911,10 @@ time.
 
 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

diff --git a/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn b/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
index 931e339..72f2d38 100644
--- a/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
+++ b/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
@@ -34,3 +34,14 @@ I'd rather cleanup some of the file(name)s  of unexpected characters. --[[jwalze
 
 
 But what I see now is not quite helpful, as it seems, STDERR and DEBUG are asyncronous, so they mix up in a way, that I can't really see, whats the problem ...  Maybe I'm better off for troubleshooting, to insert an printf to strerr to have it in the same stream.. --[[jwalzer]]
+
+
+----
+
+**Update:** The "print STDERR $file;"-Trick did it .. I was able to find a mdwn-file, that (was generated by a script of me) had \0xAB in it.
+
+Nevertheless I still wonder if this should be a problem. This character happend to be in an *\[\[meta title='$CHAR'\]\]-tag* and an *\[$CHAR\]http://foo)-Link*
+
+Should this throw an warning? Maybe this warning could be catched an reported inclusively the containing filename? maybe even with an override, if one knows that it is correct that way? --[[jwalzer]]
+
+[[!tag solved]]

Update - trying to debug it
diff --git a/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn b/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
index 56ac4b8..931e339 100644
--- a/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
+++ b/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
@@ -13,3 +13,24 @@ Is there a way to have ikiwiki output the position, where it encounters the char
 
 Probably all this has to do with locale-settings, and usage of mixed locales in a distributed setup ...
 I'd rather cleanup some of the file(name)s  of unexpected characters. --[[jwalzer]]
+
+--------
+
+**Update** : So I took the chance to insert debug into ikiwiki.pm:
+
+     root@novalis:/usr/share/perl5# diff -p /tmp/IkiWiki.orig.pm IkiWiki.pm 
+     *** /tmp/IkiWiki.orig.pm        Sun Feb 14 15:16:08 2010
+     --- IkiWiki.pm  Sun Feb 14 15:16:28 2010
+     *************** sub readfile ($;$$) {
+     *** 768,773 ****
+     --- 768,774 ----
+             }
+       
+             local $/=undef;
+     +       debug("opening File: $file:");
+             open (my $in, "<", $file) || error("failed to read $file: $!");
+             binmode($in) if ($binary);
+             return \*$in if $wantfd;
+
+
+But what I see now is not quite helpful, as it seems, STDERR and DEBUG are asyncronous, so they mix up in a way, that I can't really see, whats the problem ...  Maybe I'm better off for troubleshooting, to insert an printf to strerr to have it in the same stream.. --[[jwalzer]]

new thread
diff --git a/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn b/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
new file mode 100644
index 0000000..56ac4b8
--- /dev/null
+++ b/doc/forum/Warnings:___39__utf8___34____92__xAB__34___does_not_map_to_Unicode_at___47__usr__47__share__47__perl5__47__IkiWiki.pm_line_774__44_____60____36__in__62___chunk_1.__39__.mdwn
@@ -0,0 +1,15 @@
+# getting Warnings about UTF8-Chars.
+
+I'm  getting multiple warnings:
+
+      utf8 "\xAB" does not map to Unicode at /usr/share/perl5/IkiWiki.pm line 774, <$in> chunk 1.
+
+
+I'm assuming this is once per File, but even in verbose mode, it doesn't tell me which file is a problem.
+It first reads all the files, and afterwards when parsing/compiling them, it outputs the warning, so I can't
+deduce the offending files.
+
+Is there a way to have ikiwiki output the position, where it encounters the character?
+
+Probably all this has to do with locale-settings, and usage of mixed locales in a distributed setup ...
+I'd rather cleanup some of the file(name)s  of unexpected characters. --[[jwalzer]]

clarify
diff --git a/doc/todo/openid_user_filtering.mdwn b/doc/todo/openid_user_filtering.mdwn
index 7f8b2a5..6a318c4 100644
--- a/doc/todo/openid_user_filtering.mdwn
+++ b/doc/todo/openid_user_filtering.mdwn
@@ -10,4 +10,4 @@ Would only allow edits from openIDs of that form.
 
 > This kind of thing can be [[done]] now: --[[Joey]] 
 > 
->	locked_pages => "user(http://*.webvm.net/)"
+>	locked_pages => "* and !user(http://*.webvm.net/)"

close
diff --git a/doc/todo/openid_user_filtering.mdwn b/doc/todo/openid_user_filtering.mdwn
index 8b2d008..7f8b2a5 100644
--- a/doc/todo/openid_user_filtering.mdwn
+++ b/doc/todo/openid_user_filtering.mdwn
@@ -7,3 +7,7 @@ So I suggest an ikiwiki configuration like:
      users => ["*.webvm.net"],
 
 Would only allow edits from openIDs of that form.
+
+> This kind of thing can be [[done]] now: --[[Joey]] 
+> 
+>	locked_pages => "user(http://*.webvm.net/)"

Added information about python implementation for reference
diff --git a/doc/todo/abbreviation.mdwn b/doc/todo/abbreviation.mdwn
index d241667..f288009 100644
--- a/doc/todo/abbreviation.mdwn
+++ b/doc/todo/abbreviation.mdwn
@@ -2,4 +2,6 @@ We might want some kind of abbreviation and acronym plugin. --[[JoshTriplett]]
 
  * Not sure if this is what you mean, but I'd love a way to make works which match existing page names automatically like (eg. if there is a page called "MySQL" then any time the word MySQL is mentioned it should become a link to that page).  -- [[AdamShand]]
 
+ * The python-markdown-extras package has support for [abbreviations](http://www.freewisdom.org/projects/python-markdown/Abbreviations), with the syntax that you just use the abbreviation in text (e.g. HTML) and then define the abbreviations at the end (like "footnote-style" links). For consistency, it might be good to use the same syntax, which apparently derives from [PHP-markdown-extra](http://michelf.com/projects/php-markdown/extra/#abbr).
+
 [[wishlist]]

add news item for ikiwiki 3.20100212
diff --git a/doc/news/version_3.20091113.mdwn b/doc/news/version_3.20091113.mdwn
deleted file mode 100644
index 5791740..0000000
--- a/doc/news/version_3.20091113.mdwn
+++ /dev/null
@@ -1,18 +0,0 @@
-ikiwiki 3.20091113 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * underlay: Fix example values put in setup file to be array
-     references.
-   * underlay: Avoid crashing if lists of underlays (or template
-     directories) are not configured.
-   * Moved the postscan hook to run on the raw html of a page, before
-     the template is filled out. This improves the search plugin's indexing,
-     since it will not include navigational elements from the page template
-     or sidebar.
-   * localstyle: New plugin, allows overrding the toplevel local.css
-     with one that is closer to a page.
-   * httpauth: Add cgiauthurl setting that can be used to do http basic auth
-     only when ikiwiki needs authentication, rather than for any access to
-     the cgi/wiki.
-   * inline: Do not generate feeds for nested inlines.
-   * inline: Allow direct inclusion of non-page files in raw mode.
-   * inline: Fix display of all pages when archive=yes or show=0 are used."""]]
diff --git a/doc/news/version_3.20100212.mdwn b/doc/news/version_3.20100212.mdwn
new file mode 100644
index 0000000..3dcfe5f
--- /dev/null
+++ b/doc/news/version_3.20100212.mdwn
@@ -0,0 +1,26 @@
+ikiwiki 3.20100212 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * template: Preprocess parameters before htmlizing.
+   * img: Fix a bug that could taint @links with undef values.
+   * setup automator: Configure Term::Readline to use bold for prompt, rather
+     than default underline. Closes: #[517656](http://bugs.debian.org/517656)
+   * Allow jumping directly into account registration process by going to
+     ikiwiki.cgi?do=register
+   * Improve display of openid in preferences page.
+   * Add link to userpage (or creation link) to top of preferences page.
+   * opendiscussion: This plugin will also now allow posting comments
+     to otherwise locked-down sites.
+   * auto-blog.setup: Lock all pages, so only admin can post to the blog
+     by default, and enable opendiscussion so others can comment.
+   * Fix color and format plugins to appear in the websetup interface.
+   * amazon\_s3: Fix to support the EU S3 datacenter, which is more picky
+     about attempts to create already existing buckets.
+   * httpauth: When cgiauthurl is configured, httpauth can now be used
+     alongside other authentication methods (like openid or anonok). Rather
+     than always redirect to the cgiauthurl for authentication, there is now
+     a button on the login form to use it.
+   * httpauth: Add httpauth\_pagespec setting that can be used to limit
+     pages to only being edited via users authed with httpauth.
+   * Allow globs to be used in user() pagespecs.
+   * Group related plugins into sections in the setup file, and drop
+     unused rcs plugins from the setup file."""]]
\ No newline at end of file

formatting
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index 4fd9c43..a8c9de2 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -536,7 +536,7 @@ The data returned is a list of `%config` options, followed by a hash
 describing the option. There can also be an item named "plugin", which
 describes the plugin as a whole. For example:
 
-                return
+		return
 			plugin => {
 				description => "description of this plugin",
 				safe => 1,
@@ -736,7 +736,7 @@ 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($$;@)`
+### `pagespec_match($$;@)`
 
 Passed a page name, and [[ikiwiki/PageSpec]], returns a true value if the
 [[ikiwiki/PageSpec]] matches the page.
@@ -766,7 +766,7 @@ dependency type from one or more of these keywords:
 
 If multiple types are specified, they are combined.
 
-#### `bestlink($$)`
+### `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
@@ -774,7 +774,7 @@ 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($$$;@)`
+### `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

layout
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index d94216e..4fd9c43 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -31,7 +31,7 @@ is accomplished by calling various hooks provided by plugins.
 
 ### compiler
 
-As a compiler, starts by calling the `refresh` hook. Then it checks
+As a compiler, ikiwiki starts by calling the `refresh` hook. Then it checks
 the wiki's source to find new or changed pages. The `needsbuild` hook is
 then called to allow manipulation of the list of pages that need to be
 built. 
@@ -48,10 +48,11 @@ page had previously produced are removed.
 
 ### cgi
 
-The flow between hooks when ikiwiki is run as a cgi is best illistrated by
+The flow between hooks when ikiwiki is run as a cgi is best illustrated by
 an example.
 
-* *Alice browses to a page and clicks Edit.*
+Alice browses to a page and clicks Edit.
+
 * Ikiwiki is run as a cgi. It assigns Alice a session cookie, and,
   by calling the `auth` hooks, sees that she is not yet logged in.
 * The `sessioncgi` hooks are then called, and one of them,
@@ -61,7 +62,9 @@ an example.
   Alice is not signed in.
 * The [[signinedit]] plugin then launches the signin process. A signin
   page is built by calling the `formbuilder_setup` hook.
-* *Alice signs in with her openid.*
+
+Alice signs in with her openid.
+
 * The [[openid]] plugin's `formbuilder` hook sees that an openid was
   entered in the signin form, and redirects to Alice's openid provider.
 * Alice's openid provider calls back to ikiwiki. The [[openid]] plugin
@@ -70,7 +73,9 @@ an example.
   a page.
 * Now all the `canedit` hooks are happy. The [[editpage]] plugin calls
   `formbuilder_setup` to display the page editing form.
-* *Alice saves her change to the page.*
+
+Alice saves her change to the page.
+
 * The [[editpage]] plugin's `formbuilder` hook sees that the Save button
   was pressed, and calls the `checkcontent` and `editcontent` hooks.
   Then it saves the page to disk, and branches into the compiler part

add highlevel view of when hooks are called during compile and cgi phases
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index f2b96b6..d94216e 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -9,16 +9,73 @@ Ikiwiki is a compiler
 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. The [[tutorial]] has some other examples of ways that ikiwiki
-being a compiler may trip up the unwary.
+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.
+
+The [[tutorial]] has some other examples of ways that ikiwiki being a
+compiler may trip up the unwary.
 """]]
 
 [[!toc levels=2]]
 
+## Highlevel view of ikiwiki
+
+Ikiwiki mostly has two modes of operation. It can either be running
+as a compiler, building or updating a wiki; or as a cgi program, providing
+user interface for editing pages, etc. Almost everything ikiwiki does
+is accomplished by calling various hooks provided by plugins.
+
+### compiler
+
+As a compiler, starts by calling the `refresh` hook. Then it checks
+the wiki's source to find new or changed pages. The `needsbuild` hook is
+then called to allow manipulation of the list of pages that need to be
+built. 
+
+Now that it knows what pages it needs to build, ikiwiki runs two
+compile passes. First, it runs `scan` hooks, which collect metadata about
+the pages. Then it runs a page rendering pipeline, by calling in turn these
+hooks: `filter`, `preprocess`, `linkify`, `htmlize`, `postscan`,
+`pagetemplate`, `sanitize`, `format`.
+
+After all necessary pages are built, it calls the `change` hook. Finally,
+if a page is was deleted, the `delete` hook is called, and the files that
+page had previously produced are removed.
+
+### cgi
+
+The flow between hooks when ikiwiki is run as a cgi is best illistrated by
+an example.
+
+* *Alice browses to a page and clicks Edit.*
+* Ikiwiki is run as a cgi. It assigns Alice a session cookie, and,
+  by calling the `auth` hooks, sees that she is not yet logged in.
+* The `sessioncgi` hooks are then called, and one of them,
+  from the [[editpage]] plugin, notices that the cgi has been told "do=edit".
+* The [[editpage]] plugin calls the `canedit` hook to check if this
+  page edit is allowed. The [[signinedit]] plugin has a hook that says not:
+  Alice is not signed in.
+* The [[signinedit]] plugin then launches the signin process. A signin
+  page is built by calling the `formbuilder_setup` hook.
+* *Alice signs in with her openid.*
+* The [[openid]] plugin's `formbuilder` hook sees that an openid was
+  entered in the signin form, and redirects to Alice's openid provider.
+* Alice's openid provider calls back to ikiwiki. The [[openid]] plugin
+  has an `auth` hook that finishes the openid signin process.
+* Signin complete, ikiwiki returns to what Alice was doing before; editing
+  a page.
+* Now all the `canedit` hooks are happy. The [[editpage]] plugin calls
+  `formbuilder_setup` to display the page editing form.
+* *Alice saves her change to the page.*
+* The [[editpage]] plugin's `formbuilder` hook sees that the Save button
+  was pressed, and calls the `checkcontent` and `editcontent` hooks.
+  Then it saves the page to disk, and branches into the compiler part
+  of ikiwiki to refresh the wiki.
+
 ## Types of plugins
 
 Most ikiwiki [[plugins]] are written in perl, like ikiwiki. This gives the
@@ -530,13 +587,13 @@ function of the ikiwiki wrapper when it is being generated.
 
 Several variables are exported to your plugin when you `use IkiWiki;`
 
-### %config
+### `%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
 your ikiwiki setup file, which sets the hash content to configure the wiki.
 
-### %pagestate
+### `%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,
@@ -554,7 +611,7 @@ 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
+### `%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
@@ -563,7 +620,7 @@ 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
+### `%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
@@ -571,7 +628,15 @@ reference. Do not modify this hash directly; call `add_link()`.
 
 	$links{"foo"} = ["bar", "baz"];
 
-### %destsources
+### `%pagesources`
+
+The `%pagesources` has 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.
+
+	$pagesources{"foo"} = "foo.mdwn";
+
+### `%destsources`
 
 The `%destsources` hash records the name of the source file used to
 create each destination file. The key is the output filename (ie,
@@ -581,16 +646,10 @@ destination files. Do not modify this hash directly; call `will_render()`.
 	
 	$destsources{"foo/index.html"} = "foo.mdwn";
 
-### %pagesources
-
-The `%pagesources` has 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.
-
-	$pagesources{"foo"} = "foo.mdwn";
-
 ## 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.

add variable value examples
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index 07bfd72..f2b96b6 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -3,7 +3,7 @@ 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]].
 
-[[!template type="note" text="""
+[[!template id="note" text="""
 Ikiwiki is a compiler
 
 One thing to keep in mind when writing a plugin is that ikiwiki is a wiki
@@ -569,6 +569,8 @@ 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"];
+
 ### %destsources
 
 The `%destsources` hash records the name of the source file used to
@@ -576,6 +578,8 @@ create each destination file. The key is the output filename (ie,
 "foo/index.html"), and the value is the source filename that it was built
 from (eg, "foo.mdwn"). Note that a single source file may create multiple
 destination files. Do not modify this hash directly; call `will_render()`.
+	
+	$destsources{"foo/index.html"} = "foo.mdwn";
 
 ### %pagesources
 
@@ -583,6 +587,8 @@ The `%pagesources` has 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.
 
+	$pagesources{"foo"} = "foo.mdwn";
+
 ## Library functions
 
 ### `hook(@)`

move note to sidebox
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index 17c54ff..07bfd72 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -3,6 +3,20 @@ 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]].
 
+[[!template type="note" text="""
+Ikiwiki is a compiler
+
+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. The [[tutorial]] has some other examples of ways that ikiwiki
+being a compiler may trip up the unwary.
+"""]]
+
 [[!toc levels=2]]
 
 ## Types of plugins
@@ -31,18 +45,6 @@ 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.
 
-## Remember: Ikiwiki is a compiler
-
-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. The [[tutorial]] has some other examples of ways that ikiwiki
-being a compiler may trip up the unwary.
-
 ## Plugin interface
 
 To import the ikiwiki plugin interface:

heading tweaks
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index 712dda8..17c54ff 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -524,17 +524,17 @@ describes the plugin as a whole. For example:
 This hook is used to inject C code (which it returns) into the `main`
 function of the ikiwiki wrapper when it is being generated.
 
-### Exported variables
+## Exported variables
 
 Several variables are exported to your plugin when you `use IkiWiki;`
 
-#### %config
+### %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
 your ikiwiki setup file, which sets the hash content to configure the wiki.
 
-#### %pagestate
+### %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,
@@ -552,7 +552,7 @@ 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
+### %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
@@ -561,13 +561,13 @@ 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
+### %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()`.
 
-#### %destsources
+### %destsources
 
 The `%destsources` hash records the name of the source file used to
 create each destination file. The key is the output filename (ie,
@@ -575,15 +575,15 @@ create each destination file. The key is the output filename (ie,
 from (eg, "foo.mdwn"). Note that a single source file may create multiple
 destination files. Do not modify this hash directly; call `will_render()`.
 
-#### %pagesources
+### %pagesources
 
 The `%pagesources` has 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.
 
-### Library functions
+## Library functions
 
-#### `hook(@)`
+### `hook(@)`
 
 Hook into ikiwiki's processing. See the discussion of hooks above.
 
@@ -592,12 +592,12 @@ 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($)`
+### `debug($)`
 
 Logs a debugging message. These are supressed unless verbose mode is turned
 on.
 
-#### `error($;$)`
+### `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
@@ -611,13 +611,13 @@ 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($;@)`
+### `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($)`
+### `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".)
@@ -625,7 +625,7 @@ 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($$;@)`
+### `pagespec_match_list($$;@)`
 
 Passed a page name, and [[ikiwiki/PageSpec]], returns a list of pages
 in the wiki that match the [[ikiwiki/PageSpec]]. 
@@ -656,7 +656,7 @@ Additional named parameters can be specified:
 Any other named parameters are passed on to `pagespec_match`, to further
 limit the match.
 
-#### `add_depends($$;$)`
+### `add_depends($$;$)`
 
 Makes the specified page depend on the specified [[ikiwiki/PageSpec]].
 
@@ -678,7 +678,7 @@ 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(@)`
+### `deptype(@)`
 
 Use this function to generate ikiwiki's internal representation of a
 dependency type from one or more of these keywords:
@@ -730,7 +730,7 @@ control some options. These are:
 * class - set to add a css class to the link
 * title - set to add a title attribute to the link
 
-#### `readfile($;$)`
+### `readfile($;$)`
 
 Given a filename, reads and returns the entire file.
 
@@ -739,7 +739,7 @@ in binary mode.
 
 A failure to read the file will result in it dying with an error.
 
-#### `writefile($$$;$$)`
+### `writefile($$$;$$)`
 
 Given a filename, a directory to put it in, and the file's content,
 writes a file. 
@@ -767,7 +767,7 @@ 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($$)`
+### `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
@@ -783,34 +783,34 @@ 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($)`
+### `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($)`
+### `pagename($)`
 
 Given the name of a source file, returns the name of the wiki page
 that corresponds to that file.
 
-#### `pagetitle($)`
+### `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($)`
+### `titlepage($)`
 
 This performs the inverse of `pagetitle`, ie, it converts a page title into
 a wiki page name.
 
-#### `linkpage($)`
+### `linkpage($)`
 
 This converts text that could have been entered by the user as a
 [[ikiwiki/WikiLink]] into a wiki page name.
 
-#### `srcfile($;$)`
+### `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
@@ -820,7 +820,7 @@ 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($)`

(Diff truncated)
reorg and expand docs of some variables
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index fbaabb6..712dda8 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -31,7 +31,7 @@ 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
+## Remember: Ikiwiki is a compiler
 
 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
@@ -40,7 +40,23 @@ 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.
+being edited. The [[tutorial]] has some other examples of ways that ikiwiki
+being a compiler may trip up the unwary.
+
+## Plugin interface
+
+To import the ikiwiki plugin interface:
+
+	use IkiWiki '3.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.
 
 ## Registering plugins
 
@@ -508,28 +524,17 @@ describes the plugin as a whole. For example:
 This hook is used to inject C code (which it returns) into the `main`
 function of the ikiwiki wrapper when it is being generated.
 
-## Plugin interface
-
-To import the ikiwiki plugin interface:
+### Exported variables
 
-	use IkiWiki '3.00';
+Several variables are exported to your plugin when you `use IkiWiki;`
 
-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
+#### %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
 your ikiwiki setup file, which sets the hash content to configure the wiki.
 
-### %pagestate
+#### %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,
@@ -547,7 +552,7 @@ 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
+#### %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
@@ -556,19 +561,25 @@ 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
+#### %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()`.
+
+#### %destsources
 
-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:
+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 source filename that it was built
+from (eg, "foo.mdwn"). Note that a single source file may create multiple
+destination files. Do not modify this hash directly; call `will_render()`.
 
-* `%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.
+#### %pagesources
 
-Also, the `%IkiWiki::version` variable contains the version number for the
-ikiwiki program.
+The `%pagesources` has 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.
 
 ### Library functions
 
@@ -614,22 +625,6 @@ 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.
 
-### `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.
-
 #### `pagespec_match_list($$;@)`
 
 Passed a page name, and [[ikiwiki/PageSpec]], returns a list of pages
@@ -683,6 +678,22 @@ 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

add section information
diff --git a/IkiWiki/Plugin/404.pm b/IkiWiki/Plugin/404.pm
index 85486e5..8adfd5d 100644
--- a/IkiWiki/Plugin/404.pm
+++ b/IkiWiki/Plugin/404.pm
@@ -21,6 +21,7 @@ sub getsetup () {
 			# server admin action too
 			safe => 0,
 			rebuild => 0,
+			section => "web",
 		}
 }
 
diff --git a/IkiWiki/Plugin/aggregate.pm b/IkiWiki/Plugin/aggregate.pm
index 5a9eb43..c18d413 100644
--- a/IkiWiki/Plugin/aggregate.pm
+++ b/IkiWiki/Plugin/aggregate.pm
@@ -43,6 +43,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "special-purpose",
 		},
 		aggregateinternal => {
 			type => "boolean",
diff --git a/IkiWiki/Plugin/amazon_s3.pm b/IkiWiki/Plugin/amazon_s3.pm
index cfd8cd3..f2f4dbc 100644
--- a/IkiWiki/Plugin/amazon_s3.pm
+++ b/IkiWiki/Plugin/amazon_s3.pm
@@ -45,6 +45,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0,
 			rebuild => 0,
+			section => "special-purpose",
 		},
 		amazon_s3_key_id => {
 			type => "string",
diff --git a/IkiWiki/Plugin/attachment.pm b/IkiWiki/Plugin/attachment.pm
index cbe6efc..ad1dd9b 100644
--- a/IkiWiki/Plugin/attachment.pm
+++ b/IkiWiki/Plugin/attachment.pm
@@ -19,6 +19,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "web",
 		},
 		allowed_attachments => {
 			type => "pagespec",
diff --git a/IkiWiki/Plugin/autoindex.pm b/IkiWiki/Plugin/autoindex.pm
index 555856b..e50464d 100644
--- a/IkiWiki/Plugin/autoindex.pm
+++ b/IkiWiki/Plugin/autoindex.pm
@@ -16,6 +16,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "special-purpose",
 		},
 }
 
diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm
index caed0d5..1e71749 100644
--- a/IkiWiki/Plugin/comments.pm
+++ b/IkiWiki/Plugin/comments.pm
@@ -38,6 +38,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1,
+			section => "web",
 		},
 		comments_pagespec => {
 			type => 'pagespec',
diff --git a/IkiWiki/Plugin/editdiff.pm b/IkiWiki/Plugin/editdiff.pm
index 7df6a9f..d8f53a4 100644
--- a/IkiWiki/Plugin/editdiff.pm
+++ b/IkiWiki/Plugin/editdiff.pm
@@ -19,6 +19,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "web",
 		},
 }
 
diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm
index a163b0d..5f0551d 100644
--- a/IkiWiki/Plugin/edittemplate.pm
+++ b/IkiWiki/Plugin/edittemplate.pm
@@ -23,6 +23,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "web",
 		},
 }
 
diff --git a/IkiWiki/Plugin/getsource.pm b/IkiWiki/Plugin/getsource.pm
index d155543..b362de7 100644
--- a/IkiWiki/Plugin/getsource.pm
+++ b/IkiWiki/Plugin/getsource.pm
@@ -17,6 +17,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1,
+			section => "web",
 		},
 		getsource_mimetype => {
 			type => "string",
diff --git a/IkiWiki/Plugin/google.pm b/IkiWiki/Plugin/google.pm
index 483fa17..48ad4c8 100644
--- a/IkiWiki/Plugin/google.pm
+++ b/IkiWiki/Plugin/google.pm
@@ -17,6 +17,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1,
+			section => "web",
 		},
 }
 
diff --git a/IkiWiki/Plugin/goto.pm b/IkiWiki/Plugin/goto.pm
index 439552f..03bd682 100644
--- a/IkiWiki/Plugin/goto.pm
+++ b/IkiWiki/Plugin/goto.pm
@@ -14,6 +14,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "web",
 		}
 }
 
diff --git a/IkiWiki/Plugin/mirrorlist.pm b/IkiWiki/Plugin/mirrorlist.pm
index d0a6107..92be791 100644
--- a/IkiWiki/Plugin/mirrorlist.pm
+++ b/IkiWiki/Plugin/mirrorlist.pm
@@ -15,6 +15,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1,
+			section => "web",
 		},
 		mirrorlist => {
 			type => "string",
diff --git a/IkiWiki/Plugin/norcs.pm b/IkiWiki/Plugin/norcs.pm
index bfe84c0..e6a05a3 100644
--- a/IkiWiki/Plugin/norcs.pm
+++ b/IkiWiki/Plugin/norcs.pm
@@ -25,6 +25,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0, # rcs plugin
 			rebuild => 0,
+			section => "rcs",
 		},
 }
 
diff --git a/IkiWiki/Plugin/pingee.pm b/IkiWiki/Plugin/pingee.pm
index f5386d0..aafce9e 100644
--- a/IkiWiki/Plugin/pingee.pm
+++ b/IkiWiki/Plugin/pingee.pm
@@ -15,6 +15,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "special-purpose",
 		},
 }
 
diff --git a/IkiWiki/Plugin/pinger.pm b/IkiWiki/Plugin/pinger.pm
index c20ecb5..a797fc7 100644
--- a/IkiWiki/Plugin/pinger.pm
+++ b/IkiWiki/Plugin/pinger.pm
@@ -21,6 +21,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "special-purpose",
 		},
 		pinger_timeout => {
 			type => "integer",
diff --git a/IkiWiki/Plugin/remove.pm b/IkiWiki/Plugin/remove.pm
index 3c1e0c7..f59d026 100644
--- a/IkiWiki/Plugin/remove.pm
+++ b/IkiWiki/Plugin/remove.pm
@@ -18,6 +18,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "web",
 		},
 }
 
diff --git a/IkiWiki/Plugin/rename.pm b/IkiWiki/Plugin/rename.pm
index 8213d21..3908443 100644
--- a/IkiWiki/Plugin/rename.pm
+++ b/IkiWiki/Plugin/rename.pm
@@ -18,6 +18,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,

(Diff truncated)
another (last?) tag change
diff --git a/doc/plugins/postsparkline.mdwn b/doc/plugins/postsparkline.mdwn
index c81f91b..b0733e3 100644
--- a/doc/plugins/postsparkline.mdwn
+++ b/doc/plugins/postsparkline.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=postsparkline author="[[Joey]]"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/postsparkline]] [[ikiwiki/directive]].
 It uses the [[sparkline]] plugin to create a sparkline of

one more
diff --git a/doc/plugins/map.mdwn b/doc/plugins/map.mdwn
index 8f5a9f1..b164d5c 100644
--- a/doc/plugins/map.mdwn
+++ b/doc/plugins/map.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=map author="Alessandro Dotti Contra"]]
-[[!tag type/meta]]
+[[!tag type/meta type/widget]]
 
 This plugin provides the [[ikiwiki/directive/map]] [[ikiwiki/directive]],
 which generates a hierarchical page map for the wiki.

more tag reorg
diff --git a/doc/plugins/editpage.mdwn b/doc/plugins/editpage.mdwn
index b830e51..346ee7c 100644
--- a/doc/plugins/editpage.mdwn
+++ b/doc/plugins/editpage.mdwn
@@ -1,4 +1,5 @@
 [[!template id=plugin name=editpage core=1 author="[[Joey]]"]]
+[[!tag type/web]]
 
 This plugin allows editing wiki pages in the web interface. It's enabled by
 default if [[cgi]] is enabled; disable it if you want cgi for other things
diff --git a/doc/plugins/getsource.mdwn b/doc/plugins/getsource.mdwn
index 20040cc..d5404a6 100644
--- a/doc/plugins/getsource.mdwn
+++ b/doc/plugins/getsource.mdwn
@@ -1,4 +1,5 @@
 [[!template id=plugin name=getsource author="[[Will_Uther|Will]]"]]
+[[!tag type/web]]
 
 This plugin adds a "Source" link to the top of each page that uses
 the CGI to display the page's source.
diff --git a/doc/plugins/inline.mdwn b/doc/plugins/inline.mdwn
index 6c32825..3eb849f 100644
--- a/doc/plugins/inline.mdwn
+++ b/doc/plugins/inline.mdwn
@@ -1,4 +1,5 @@
 [[!template id=plugin name=inline core=1 author="[[Joey]]"]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/inline]]
 [[ikiwiki/directive]], which allows including one wiki page
diff --git a/doc/plugins/mirrorlist.mdwn b/doc/plugins/mirrorlist.mdwn
index 6e4964e..aedc1f4 100644
--- a/doc/plugins/mirrorlist.mdwn
+++ b/doc/plugins/mirrorlist.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=mirror author="[[Joey]]"]]
-[[!tag type/chrome]]
+[[!tag type/web]]
 
 This plugin allows adding links a list of mirrors to each page in the
 wiki. For each mirror, a name and an url should be specified. Pages are
diff --git a/doc/plugins/parentlinks.mdwn b/doc/plugins/parentlinks.mdwn
index ef262a3..c2d364b 100644
--- a/doc/plugins/parentlinks.mdwn
+++ b/doc/plugins/parentlinks.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=parentlinks core=1 author="[[intrigeri]]"]]
-[[!tag type/link]]
+[[!tag type/link type/chrome]]
 
 This plugin generates the links to a page's parents that typically appear
 at the top of a wiki page.
diff --git a/doc/plugins/recentchanges.mdwn b/doc/plugins/recentchanges.mdwn
index 9375296..823f685 100644
--- a/doc/plugins/recentchanges.mdwn
+++ b/doc/plugins/recentchanges.mdwn
@@ -1,4 +1,5 @@
 [[!template id=plugin name=recentchanges core=1 author="[[Joey]]"]]
+[[!tag type/meta]]
 
 This plugin examines the [[revision_control_system|rcs]] history and
 generates a page describing each recent change made to the wiki. These
diff --git a/doc/plugins/recentchangesdiff.mdwn b/doc/plugins/recentchangesdiff.mdwn
index a7b113a..57299f9 100644
--- a/doc/plugins/recentchangesdiff.mdwn
+++ b/doc/plugins/recentchangesdiff.mdwn
@@ -1,4 +1,5 @@
 [[!template id=plugin name=recentchangesdiff core=0 author="[[Joey]]"]]
+[[!tag type/meta]]
 
 This plugin extends the [[recentchanges]] plugin, adding a diff for each
 change. The diffs are by default hidden from display on the recentchanges
diff --git a/doc/plugins/rsync.mdwn b/doc/plugins/rsync.mdwn
index 315b663..e488861 100644
--- a/doc/plugins/rsync.mdwn
+++ b/doc/plugins/rsync.mdwn
@@ -1,4 +1,5 @@
 [[!template id=plugin name=rsync author="[[schmonz]]"]]
+[[!tag type/special-purpose]]
 
 This plugin allows ikiwiki to push generated pages to another host
 by running a command such as `rsync`.

more tag reorg
diff --git a/doc/plugins/date.mdwn b/doc/plugins/date.mdwn
index b8dbdfe..2a33f01 100644
--- a/doc/plugins/date.mdwn
+++ b/doc/plugins/date.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=date author="[[Joey]]"]]
-[[!tag type/meta]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/date]]
 [[ikiwiki/directive]], which provides a way to display an arbitrary date
diff --git a/doc/plugins/linkmap.mdwn b/doc/plugins/linkmap.mdwn
index 89cb9d8..7e51cd9 100644
--- a/doc/plugins/linkmap.mdwn
+++ b/doc/plugins/linkmap.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=linkmap author="[[Joey]]"]]
 [[!tag type/meta]]
+[[!tag type/widget]]
 [[!tag type/slow]]
 
 This plugin provides the [[ikiwiki/directive/linkmap]] [[ikiwiki/directive]].
diff --git a/doc/plugins/listdirectives.mdwn b/doc/plugins/listdirectives.mdwn
index 2d9bce0..df854de 100644
--- a/doc/plugins/listdirectives.mdwn
+++ b/doc/plugins/listdirectives.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=listdirectives author="Will"]]
 [[!tag type/meta]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/listdirectives]]
 [[ikiwiki/directive]], which inserts a list of currently available
diff --git a/doc/plugins/orphans.mdwn b/doc/plugins/orphans.mdwn
index e403c2d..09ad0a5 100644
--- a/doc/plugins/orphans.mdwn
+++ b/doc/plugins/orphans.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=orphans author="[[Joey]]"]]
 [[!tag type/meta]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/orphans]]
 [[ikiwiki/directive]], which generates a list of possibly orphaned pages --
diff --git a/doc/plugins/pagecount.mdwn b/doc/plugins/pagecount.mdwn
index a56027e..71872fa 100644
--- a/doc/plugins/pagecount.mdwn
+++ b/doc/plugins/pagecount.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=pagecount author="[[Joey]]"]]
 [[!tag type/meta]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/pagecount]]
 [[ikiwiki/directive]], which displays the number of pages
diff --git a/doc/plugins/pagestats.mdwn b/doc/plugins/pagestats.mdwn
index c3eba63..347e39a 100644
--- a/doc/plugins/pagestats.mdwn
+++ b/doc/plugins/pagestats.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=pagestats author="Enrico Zini"]]
-[[!tag type/meta type/tags]]
+[[!tag type/meta type/tags type/widget]]
 
 This plugin provides the [[ikiwiki/directive/pagestats]]
 [[ikiwiki/directive]], which can generate stats about how pages link to
diff --git a/doc/plugins/progress.mdwn b/doc/plugins/progress.mdwn
index e1b560c..20736d1 100644
--- a/doc/plugins/progress.mdwn
+++ b/doc/plugins/progress.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=progress author="[[Will]]"]]
-[[!tag type/meta]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/progress]]
 [[ikiwiki/directive]], which generates a progress bar.
diff --git a/doc/plugins/version.mdwn b/doc/plugins/version.mdwn
index 43027bd..326a2e7 100644
--- a/doc/plugins/version.mdwn
+++ b/doc/plugins/version.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=version author="[[Joey]]"]]
 [[!tag type/meta]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/version]]
 [[ikiwiki/directive]], which inserts the current version

plugin tag reorg
diff --git a/doc/plugins/404.mdwn b/doc/plugins/404.mdwn
index ad332ee..53dace3 100644
--- a/doc/plugins/404.mdwn
+++ b/doc/plugins/404.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=404 author="[[Simon_McVittie|smcv]]"]]
-[[!tag type/useful]]
+[[!tag type/web]]
 
 This plugin lets you use the IkiWiki CGI script as an Apache 404 handler,
 to give the behaviour of various other wiki engines where visiting a
diff --git a/doc/plugins/aggregate.mdwn b/doc/plugins/aggregate.mdwn
index e2efcd8..bb828b0 100644
--- a/doc/plugins/aggregate.mdwn
+++ b/doc/plugins/aggregate.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=aggregate author="[[Joey]]"]]
-[[!tag type/useful]]
+[[!tag type/special-purpose]]
 
 This plugin allows content from other feeds to be aggregated into the
 wiki. To specify feeds to aggregate, use the
diff --git a/doc/plugins/autoindex.mdwn b/doc/plugins/autoindex.mdwn
index 03e2d12..d1133e4 100644
--- a/doc/plugins/autoindex.mdwn
+++ b/doc/plugins/autoindex.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=autoindex core=0 author="[[Joey]]"]]
-[[!tag type/useful]]
+[[!tag type/special-purpose]]
 
 This plugin searches for [[SubPages|ikiwiki/subpage]] with a missing parent
 page, and generates the parent pages. The generated page content is
diff --git a/doc/plugins/calendar.mdwn b/doc/plugins/calendar.mdwn
index bc1bc6c..49fd906 100644
--- a/doc/plugins/calendar.mdwn
+++ b/doc/plugins/calendar.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=calendar author="[[ManojSrivastava]]"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides a [[ikiwiki/directive/calendar]] [[ikiwiki/directive]].
 The directive displays a calendar, similar to the typical calendars shown on
diff --git a/doc/plugins/color.mdwn b/doc/plugins/color.mdwn
index dbb8b87..d639bf5 100644
--- a/doc/plugins/color.mdwn
+++ b/doc/plugins/color.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=color core=0 author="[[ptecza]]"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides a [[ikiwiki/directive/color]] [[ikiwiki/directive]].
 The directive can be used to color a piece of text on a page.
diff --git a/doc/plugins/comments.mdwn b/doc/plugins/comments.mdwn
index f933d32..775ef75 100644
--- a/doc/plugins/comments.mdwn
+++ b/doc/plugins/comments.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=comments author="[[Simon_McVittie|smcv]]"]]
-[[!tag type/useful]]
+[[!tag type/web]]
 
 This plugin adds "blog-style" comments. Unlike the wiki-style freeform 
 Discussion pages, these comments are posted by a simple form, cannot later
diff --git a/doc/plugins/contrib/postal.mdwn b/doc/plugins/contrib/postal.mdwn
index b2f8753..c522f8b 100644
--- a/doc/plugins/contrib/postal.mdwn
+++ b/doc/plugins/contrib/postal.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=postal author="[[DavidBremner]]"]]
-[[!tag type/useful]]
+[[!tag type/special-purpose]]
 
 The `postal` plugin allows users to send mail to
 a special address to comment on a page. It uses the [[mailbox]]
diff --git a/doc/plugins/cutpaste.mdwn b/doc/plugins/cutpaste.mdwn
index f74f8a2..ea3665c 100644
--- a/doc/plugins/cutpaste.mdwn
+++ b/doc/plugins/cutpaste.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=cutpaste author="[[Enrico]]"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/cut]],
 [[ikiwiki/directive/copy]] and [[ikiwiki/directive/paste]]
diff --git a/doc/plugins/ddate.mdwn b/doc/plugins/ddate.mdwn
index 741606a..17bb16c 100644
--- a/doc/plugins/ddate.mdwn
+++ b/doc/plugins/ddate.mdwn
@@ -1,6 +1,7 @@
 [[!template id=plugin name=ddate author="[[Joey]]"]]
 [[!tag type/fun]]
 [[!tag type/date]]
+[[!tag type/chrome]]
 
 Enables use of Discordian dates. `--timeformat` can be used to change
 the date format; see `ddate(1)`.
diff --git a/doc/plugins/filecheck.mdwn b/doc/plugins/filecheck.mdwn
index f4563d5..e5f68b2 100644
--- a/doc/plugins/filecheck.mdwn
+++ b/doc/plugins/filecheck.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=filecheck core=0 author="[[Joey]]"]]
-[[!tag type/useful]]
+[[!tag type/special-purpose]]
 
 This plugin enhances the regular [[ikiwiki/PageSpec]] syntax with
 some additional tests, for things like file size, mime type, and virus
diff --git a/doc/plugins/format.mdwn b/doc/plugins/format.mdwn
index 5ec0842..b41d365 100644
--- a/doc/plugins/format.mdwn
+++ b/doc/plugins/format.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=format core=0 author="[[Joey]]"]]
-[[!tag type/useful]]
+[[!tag type/widget]]
 
 This plugin allows mixing different page formats together, by embedding
 text formatted one way inside a page formatted another way. This is done
diff --git a/doc/plugins/fortune.mdwn b/doc/plugins/fortune.mdwn
index 9966f45..3cb125a 100644
--- a/doc/plugins/fortune.mdwn
+++ b/doc/plugins/fortune.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=fortune author="[[Joey]]"]]
 [[!tag type/fun]]
+[[!tag type/widget]]
 
 This plugin implements the [[ikiwiki/directive/fortune]] [[ikiwiki/directive]].
 This directive  uses the `fortune` program to insert a fortune into the page.
diff --git a/doc/plugins/goto.mdwn b/doc/plugins/goto.mdwn
index 9c401c5..8e1de7a 100644
--- a/doc/plugins/goto.mdwn
+++ b/doc/plugins/goto.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=goto author="[[Simon_McVittie|smcv]]"]]
-[[!tag type/useful]]
+[[!tag type/web]]
 
 This plugin adds a `do=goto` mode for the IkiWiki CGI script. It's mainly
 for internal use by the [[404]], [[comments]] and [[recentchanges]]
diff --git a/doc/plugins/graphviz.mdwn b/doc/plugins/graphviz.mdwn
index 8237ae9..65130ae 100644
--- a/doc/plugins/graphviz.mdwn
+++ b/doc/plugins/graphviz.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=graphviz author="[[JoshTriplett]]"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/graph]] [[ikiwiki/directive]].
 This directive allows embedding [graphviz](http://www.graphviz.org/) graphs in a
diff --git a/doc/plugins/haiku.mdwn b/doc/plugins/haiku.mdwn
index 74eac1c..448733d 100644
--- a/doc/plugins/haiku.mdwn
+++ b/doc/plugins/haiku.mdwn
@@ -1,5 +1,6 @@
 [[!template id=plugin name=haiku author="[[Joey]]"]]
 [[!tag type/fun]]
+[[!tag type/widget]]
 
 This plugin provides a [[ikiwiki/directive/haiku]] [[ikiwiki/directive]].
 The directive allows inserting a randomly generated haiku into a wiki page.
diff --git a/doc/plugins/img.mdwn b/doc/plugins/img.mdwn
index 1144387..a6cd90f 100644
--- a/doc/plugins/img.mdwn
+++ b/doc/plugins/img.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=img author="Christian Mock"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/img]] [[ikiwiki/directive]].
 While ikiwiki supports inlining full-size images by making a
diff --git a/doc/plugins/mirrorlist.mdwn b/doc/plugins/mirrorlist.mdwn
index b371e8e..6e4964e 100644
--- a/doc/plugins/mirrorlist.mdwn
+++ b/doc/plugins/mirrorlist.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=mirror author="[[Joey]]"]]
-[[!tag type/special-purpose]]
+[[!tag type/chrome]]
 
 This plugin allows adding links a list of mirrors to each page in the
 wiki. For each mirror, a name and an url should be specified. Pages are
diff --git a/doc/plugins/more.mdwn b/doc/plugins/more.mdwn
index 81a9e67..a0664e8 100644
--- a/doc/plugins/more.mdwn
+++ b/doc/plugins/more.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=more author="Ben"]]
-[[!tag type/chrome]]
+[[!tag type/widget]]
 
 This plugin provides the [[ikiwiki/directive/more]] [[ikiwiki/directive]],
 which is a way to have a "more" link on a post in a blog, that leads to the
diff --git a/doc/plugins/poll.mdwn b/doc/plugins/poll.mdwn

(Diff truncated)
format plugin categorization
diff --git a/IkiWiki/Plugin/creole.pm b/IkiWiki/Plugin/creole.pm
index 425e710..a1e4b31 100644
--- a/IkiWiki/Plugin/creole.pm
+++ b/IkiWiki/Plugin/creole.pm
@@ -17,6 +17,7 @@ sub getsetup {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/highlight.pm b/IkiWiki/Plugin/highlight.pm
index 9bdde85..947fb69 100644
--- a/IkiWiki/Plugin/highlight.pm
+++ b/IkiWiki/Plugin/highlight.pm
@@ -23,6 +23,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 		tohighlight => {
 			type => "string",
diff --git a/IkiWiki/Plugin/hnb.pm b/IkiWiki/Plugin/hnb.pm
index bd2177a..32c9cf3 100644
--- a/IkiWiki/Plugin/hnb.pm
+++ b/IkiWiki/Plugin/hnb.pm
@@ -23,6 +23,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/html.pm b/IkiWiki/Plugin/html.pm
index a7d5e8c..4dbae08 100644
--- a/IkiWiki/Plugin/html.pm
+++ b/IkiWiki/Plugin/html.pm
@@ -21,6 +21,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm
index 4ddf097..b892eab 100644
--- a/IkiWiki/Plugin/mdwn.pm
+++ b/IkiWiki/Plugin/mdwn.pm
@@ -16,7 +16,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
-			section => "core",
+			section => "format",
 		},
 		multimarkdown => {
 			type => "boolean",
diff --git a/IkiWiki/Plugin/otl.pm b/IkiWiki/Plugin/otl.pm
index 3ab2441..3801a6e 100644
--- a/IkiWiki/Plugin/otl.pm
+++ b/IkiWiki/Plugin/otl.pm
@@ -17,6 +17,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm
index f880118..2cbfb0a 100644
--- a/IkiWiki/Plugin/po.pm
+++ b/IkiWiki/Plugin/po.pm
@@ -85,7 +85,8 @@ sub getsetup () {
 	return
 		plugin => {
 			safe => 0,
-			rebuild => 1,
+			rebuild => 1, # format plugin
+			section => "format",
 		},
 		po_master_language => {
 			type => "string",
diff --git a/IkiWiki/Plugin/rawhtml.pm b/IkiWiki/Plugin/rawhtml.pm
index ad8a610..0838bcb 100644
--- a/IkiWiki/Plugin/rawhtml.pm
+++ b/IkiWiki/Plugin/rawhtml.pm
@@ -16,6 +16,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # changes file types
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/textile.pm b/IkiWiki/Plugin/textile.pm
index 8cc5a79..56bb4bf 100644
--- a/IkiWiki/Plugin/textile.pm
+++ b/IkiWiki/Plugin/textile.pm
@@ -19,6 +19,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/txt.pm b/IkiWiki/Plugin/txt.pm
index 8599bdc..1ed9f08 100644
--- a/IkiWiki/Plugin/txt.pm
+++ b/IkiWiki/Plugin/txt.pm
@@ -29,6 +29,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "format",
 		},
 }
 
diff --git a/IkiWiki/Plugin/wikitext.pm b/IkiWiki/Plugin/wikitext.pm
index accb03b..b24630b 100644
--- a/IkiWiki/Plugin/wikitext.pm
+++ b/IkiWiki/Plugin/wikitext.pm
@@ -16,6 +16,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0, # format plugin
 			rebuild => undef,
+			section => "format",
 		},
 }
 
diff --git a/doc/plugins/conditional.mdwn b/doc/plugins/conditional.mdwn
index 95ffb27..27a99bb 100644
--- a/doc/plugins/conditional.mdwn
+++ b/doc/plugins/conditional.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=conditional core=1 author="[[Joey]]"]]
-[[!tag type/format]]
+[[!tag type/special-purpose]]
 
 This plugin provides the [[ikiwiki/directive/if]] [[ikiwiki/directive]].
 With this directive, you can make text be conditionally displayed on a page.
diff --git a/doc/plugins/format.mdwn b/doc/plugins/format.mdwn
index 91e707f..5ec0842 100644
--- a/doc/plugins/format.mdwn
+++ b/doc/plugins/format.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=format core=0 author="[[Joey]]"]]
-[[!tag type/format]]
+[[!tag type/useful]]
 
 This plugin allows mixing different page formats together, by embedding
 text formatted one way inside a page formatted another way. This is done
diff --git a/doc/plugins/graphviz.mdwn b/doc/plugins/graphviz.mdwn
index b89f16b..8237ae9 100644
--- a/doc/plugins/graphviz.mdwn
+++ b/doc/plugins/graphviz.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=graphviz author="[[JoshTriplett]]"]]
-[[!tag type/chrome type/format]]
+[[!tag type/chrome]]
 
 This plugin provides the [[ikiwiki/directive/graph]] [[ikiwiki/directive]].
 This directive allows embedding [graphviz](http://www.graphviz.org/) graphs in a
diff --git a/doc/plugins/more.mdwn b/doc/plugins/more.mdwn
index e9a9712..81a9e67 100644
--- a/doc/plugins/more.mdwn
+++ b/doc/plugins/more.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=more author="Ben"]]
-[[!tag type/format]]
+[[!tag type/chrome]]
 
 This plugin provides the [[ikiwiki/directive/more]] [[ikiwiki/directive]],
 which is a way to have a "more" link on a post in a blog, that leads to the
diff --git a/doc/plugins/shortcut.mdwn b/doc/plugins/shortcut.mdwn
index cca1f4b..68896f4 100644
--- a/doc/plugins/shortcut.mdwn
+++ b/doc/plugins/shortcut.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=shortcut author="[[Joey]]"]]
-[[!tag type/format]]
+[[!tag type/useful]]
 
 This plugin provides the [[ikiwiki/directive/shortcut]] [[ikiwiki/directive]].
 It allows external links to commonly linked to sites to be made
diff --git a/doc/plugins/table.mdwn b/doc/plugins/table.mdwn
index 10a85bb..fb83004 100644
--- a/doc/plugins/table.mdwn
+++ b/doc/plugins/table.mdwn
@@ -1,5 +1,5 @@
 [[!template id=plugin name=table author="[[VictorMoral]]"]]
-[[!tag type/format]]
+[[!tag type/useful]]
 
 This plugin provides the [[ikiwiki/directive/table]] [[ikiwiki/directive]].

(Diff truncated)
fix openid pagespec example
diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn
index 8d8b1a5..5c191f2 100644
--- a/doc/ikiwiki/pagespec.mdwn
+++ b/doc/ikiwiki/pagespec.mdwn
@@ -45,7 +45,7 @@ Some more elaborate limits can be added to what matches using these functions:
 * "`user(username)`" - tests whether a modification is being made by a
   user with the specified username. If openid is enabled, an openid can also
   be put here. Glob patterns can be used in the username. For example, 
-  to match all openid users, use `user(*://.*)`
+  to match all openid users, use `user(*://*)`
 * "`admin()`" - tests whether a modification is being made by one of the
   wiki admins.
 * "`ip(address)`" - tests whether a modification is being made from the

Group related plugins into sections in the setup file, and drop unused rcs plugins from the setup file.
diff --git a/IkiWiki/Plugin/anonok.pm b/IkiWiki/Plugin/anonok.pm
index 243b989..0e74cbf 100644
--- a/IkiWiki/Plugin/anonok.pm
+++ b/IkiWiki/Plugin/anonok.pm
@@ -15,6 +15,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "auth",
 		},
 		anonok_pagespec => {
 			type => "pagespec",
diff --git a/IkiWiki/Plugin/blogspam.pm b/IkiWiki/Plugin/blogspam.pm
index 626c8ec..c4e5cf3 100644
--- a/IkiWiki/Plugin/blogspam.pm
+++ b/IkiWiki/Plugin/blogspam.pm
@@ -18,6 +18,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "auth",
 		},
 		blogspam_pagespec => {
 			type => 'pagespec',
diff --git a/IkiWiki/Plugin/bzr.pm b/IkiWiki/Plugin/bzr.pm
index 8830073..1ffdc23 100644
--- a/IkiWiki/Plugin/bzr.pm
+++ b/IkiWiki/Plugin/bzr.pm
@@ -36,6 +36,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0, # rcs plugin
 			rebuild => undef,
+			section => "rcs",
 		},
 		bzr_wrapper => {
 			type => "string",
diff --git a/IkiWiki/Plugin/conditional.pm b/IkiWiki/Plugin/conditional.pm
index aad6178..beeddc6 100644
--- a/IkiWiki/Plugin/conditional.pm
+++ b/IkiWiki/Plugin/conditional.pm
@@ -16,6 +16,7 @@ sub getsetup {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "core",
 		},
 }
 
diff --git a/IkiWiki/Plugin/cvs.pm b/IkiWiki/Plugin/cvs.pm
index f6db8bc..26a3e9d 100644
--- a/IkiWiki/Plugin/cvs.pm
+++ b/IkiWiki/Plugin/cvs.pm
@@ -85,6 +85,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0, # rcs plugin
 			rebuild => undef,
+			section => "rcs",
 		},
 		cvsrepo => {
 			type => "string",
diff --git a/IkiWiki/Plugin/darcs.pm b/IkiWiki/Plugin/darcs.pm
index 0d68f27..1c9538e 100644
--- a/IkiWiki/Plugin/darcs.pm
+++ b/IkiWiki/Plugin/darcs.pm
@@ -92,6 +92,7 @@ sub getsetup() {
 		plugin => {
 			safe => 0, # rcs plugin
 			rebuild => undef,
+			section => "rcs",
 		},
 		darcs_wrapper => {
 			type => "string",
diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm
index 9211cca..44fe551 100644
--- a/IkiWiki/Plugin/editpage.pm
+++ b/IkiWiki/Plugin/editpage.pm
@@ -17,6 +17,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1,
+			section => "core",
 		},
 }
 
diff --git a/IkiWiki/Plugin/git.pm b/IkiWiki/Plugin/git.pm
index 1eec6ae..b02f4a5 100644
--- a/IkiWiki/Plugin/git.pm
+++ b/IkiWiki/Plugin/git.pm
@@ -68,6 +68,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0, # rcs plugin
 			rebuild => undef,
+			section => "rcs",
 		},
 		git_wrapper => {
 			type => "string",
diff --git a/IkiWiki/Plugin/htmlscrubber.pm b/IkiWiki/Plugin/htmlscrubber.pm
index a249cdf..ee284a4 100644
--- a/IkiWiki/Plugin/htmlscrubber.pm
+++ b/IkiWiki/Plugin/htmlscrubber.pm
@@ -40,6 +40,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "core",
 		},
 		htmlscrubber_skip => {
 			type => "pagespec",
diff --git a/IkiWiki/Plugin/httpauth.pm b/IkiWiki/Plugin/httpauth.pm
index b2bb270..478f674 100644
--- a/IkiWiki/Plugin/httpauth.pm
+++ b/IkiWiki/Plugin/httpauth.pm
@@ -20,6 +20,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "auth",
 		},
 		cgiauthurl => {
 			type => "string",
diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
index 4018525..44919e5 100644
--- a/IkiWiki/Plugin/inline.pm
+++ b/IkiWiki/Plugin/inline.pm
@@ -49,6 +49,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "core",
 		},
 		rss => {
 			type => "boolean",
diff --git a/IkiWiki/Plugin/link.pm b/IkiWiki/Plugin/link.pm
index 4c1add9..3838aec 100644
--- a/IkiWiki/Plugin/link.pm
+++ b/IkiWiki/Plugin/link.pm
@@ -20,6 +20,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1,
+			section => "core",
 		},
 }
 
diff --git a/IkiWiki/Plugin/lockedit.pm b/IkiWiki/Plugin/lockedit.pm
index 74ddbb1..1466e83 100644
--- a/IkiWiki/Plugin/lockedit.pm
+++ b/IkiWiki/Plugin/lockedit.pm
@@ -15,6 +15,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,
+			section => "auth",
 		},
 		locked_pages => {
 			type => "pagespec",
diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm
index 3de59ef..4ddf097 100644
--- a/IkiWiki/Plugin/mdwn.pm
+++ b/IkiWiki/Plugin/mdwn.pm
@@ -16,6 +16,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 1, # format plugin
+			section => "core",
 		},
 		multimarkdown => {
 			type => "boolean",
diff --git a/IkiWiki/Plugin/mercurial.pm b/IkiWiki/Plugin/mercurial.pm
index 11fdec5..ea00a33 100644
--- a/IkiWiki/Plugin/mercurial.pm
+++ b/IkiWiki/Plugin/mercurial.pm
@@ -36,6 +36,7 @@ sub getsetup () {
 		plugin => {
 			safe => 0, # rcs plugin
 			rebuild => undef,
+			section => "rcs",
 		},
 		mercurial_wrapper => {
 			type => "string",
diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm
index 55c9ddb..5f046cb 100644
--- a/IkiWiki/Plugin/meta.pm
+++ b/IkiWiki/Plugin/meta.pm
@@ -20,6 +20,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => undef,
+			section => "core",
 		},
 }
 
diff --git a/IkiWiki/Plugin/moderatedcomments.pm b/IkiWiki/Plugin/moderatedcomments.pm
index 2555927..afe1cee 100644
--- a/IkiWiki/Plugin/moderatedcomments.pm
+++ b/IkiWiki/Plugin/moderatedcomments.pm
@@ -15,6 +15,7 @@ sub getsetup () {
 		plugin => {
 			safe => 1,
 			rebuild => 0,

(Diff truncated)