Recent changes to this wiki:

diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index a78068cc8..c3d1156c1 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -5,6 +5,8 @@ Why doesn't the following work?..
 
 Sure it is. 
 
+I hope baby.
+
 Nope my friend.
 
 List:

diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index 8dfa9ad02..a78068cc8 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -1,5 +1,6 @@
 ###Is this a heading? 
 
+Why doesn't the following work?..
 [[!color  foreground=white background=#ff0000 text="White text on red background"]]
 
 Sure it is. 

diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index 95e772e0c..8dfa9ad02 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -1,5 +1,7 @@
 ###Is this a heading? 
 
+[[!color  foreground=white background=#ff0000 text="White text on red background"]]
+
 Sure it is. 
 
 Nope my friend.

Announce 3.20190228 and 3.20170111.1
diff --git a/doc/news/version_3.20171001.mdwn b/doc/news/version_3.20171001.mdwn
deleted file mode 100644
index 3d51b8776..000000000
--- a/doc/news/version_3.20171001.mdwn
+++ /dev/null
@@ -1,23 +0,0 @@
-ikiwiki 3.20171001 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
- * [ [[Joey Hess|joey]] ]
-   * htmlscrubber: Add support for the video tag's `loop` and `muted`
-     attributes. Those were not in the original html5 spec, but have been
-     added in the whatwg html living standard and have wide browser support.
-   * emailauth, passwordauth: Avoid leaving `cgisess_*` files in the
-     system temp directory.
- * [ [[Simon McVittie|smcv]] ]
-   * core: Don't decode the result of `strftime` if it is already tagged as
-     UTF-8, as it might be since Perl >= 5.21.1. (Closes: #[869240](http://bugs.debian.org/869240))
-   * img: Strip metadata from resized images when the deterministic config
-     option is set. Thanks, [[intrigeri]]
-   * receive: Avoid `asprintf()` in `IkiWiki::Receive`, to avoid implicit
-     declaration, potential misbehaviour on 64-bit platforms, and lack
-     of portability to non-GNU platforms
-   * t: Add a regression test for untrusted git push
-   * receive: Fix untrusted git push with git (>= 2.11) by passing through
-     the necessary environment variables to make the quarantine area work
-   * debian: Declare compliance with Debian Policy 4.1.1
- * [ [[Amitai Schleier|schmonz]] ]
-   * l10n: Fix the build with po4a 0.52, by ensuring that `msgstr` ends
-     with a newline if and only if `msgid` does"""]]
diff --git a/doc/news/version_3.20190228.mdwn b/doc/news/version_3.20190228.mdwn
new file mode 100644
index 000000000..c26e8ad51
--- /dev/null
+++ b/doc/news/version_3.20190228.mdwn
@@ -0,0 +1,43 @@
+ikiwiki 3.20190228 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+   * aggregate: Use LWPx::ParanoidAgent if available.
+     Previously blogspam, openid and pinger used this module if available,
+     but aggregate did not. This prevents server-side request forgery or
+     local file disclosure, and mitigates denial of service when slow
+     "tarpit" URLs are accessed.
+     ([[!debcve CVE-2019-9187]])
+   * blogspam, openid, pinger: Use a HTTP proxy if configured, even if
+     LWPx::ParanoidAgent is installed.
+     Previously, only aggregate would obey proxy configuration. If a proxy
+     is used, the proxy (not ikiwiki) is responsible for preventing attacks
+     like CVE-2019-9187.
+   * aggregate, blogspam, openid, pinger: Do not access non-http, non-https
+     URLs.
+     Previously, these plugins would have allowed non-HTTP-based requests if
+     LWPx::ParanoidAgent was not installed. Preventing file URIs avoids local
+     file disclosure, and preventing other rarely-used URI schemes like
+     gopher mitigates request forgery attacks.
+   * aggregate, openid, pinger: Document LWPx::ParanoidAgent as strongly
+     recommended.
+     These plugins can request attacker-controlled URLs in some site
+     configurations.
+   * blogspam: Document LWPx::ParanoidAgent as desirable.
+     This plugin doesn't request attacker-controlled URLs, so it's
+     non-critical here.
+   * blogspam, openid, pinger: Consistently use cookiejar if configured.
+     Previously, these plugins would only obey this configuration if
+     LWPx::ParanoidAgent was not installed, but this appears to have been
+     unintended.
+   * po: Always filter .po files.
+     The po plugin in previous ikiwiki releases made the second and
+     subsequent filter call per (page, destpage) pair into a no-op,
+     apparently in an attempt to prevent *recursive* filtering (which as
+     far as we can tell can't happen anyway), with the undesired effect
+     of interpreting the raw .po file as page content (e.g. Markdown)
+     if it was inlined into the same page twice, which is apparently
+     something that tails.org does. Simplify this by deleting the code
+     that prevented repeated filtering. Thanks, intrigeri
+     (Closes: #[911356](http://bugs.debian.org/911356))"""]]
+
+ikiwiki 3.20170111.1 was also released, backporting the LWP-related
+changes from 3.20190228 to the branch used in Debian 9 'stretch'.

Add an anchor for /security/#cve-2019-9187
diff --git a/doc/security.mdwn b/doc/security.mdwn
index 378a2e4bc..fcc33fd48 100644
--- a/doc/security.mdwn
+++ b/doc/security.mdwn
@@ -612,7 +612,7 @@ in version 3.20141016.4.
 
 ([[!debcve CVE-2017-0356]]/OVE-20170111-0001)
 
-## Server-side request forgery via aggregate plugin
+## <span id="cve-2019-9187">Server-side request forgery via aggregate plugin</span>
 
 The ikiwiki maintainers discovered that the [[plugins/aggregate]] plugin
 did not use [[!cpan LWPx::ParanoidAgent]]. On sites where the

Recommend against cvsps3 (haven't tried it).
diff --git a/doc/rcs/cvs.mdwn b/doc/rcs/cvs.mdwn
index 2b191f257..a8f2f2754 100644
--- a/doc/rcs/cvs.mdwn
+++ b/doc/rcs/cvs.mdwn
@@ -5,7 +5,8 @@ Versions System]] with ikiwiki.
 
 ### Usage
 7. Install [[!cpan File::chdir]], [[!cpan File::ReadBackwards]],
-   [cvsps](http://www.cobite.com/cvsps/), and
+   [cvsps](http://www.cobite.com/cvsps/)
+   (note: probably not [cvsps3](http://www.catb.org/~esr/cvsps/)), and
    [cvsweb](http://www.freebsd.org/projects/cvsweb.html) or the like.
 7. Adjust CVS-related parameters in your setup file.
 

doc: Document security issues involving LWP::UserAgent
Recommend the LWPx::ParanoidAgent module where appropriate.
It is particularly important for openid, since unauthenticated users
can control which URLs that plugin will contact. Conversely, it is
non-critical for blogspam, since the URL to be contacted is under
the wiki administrator's control.
diff --git a/doc/plugins/aggregate.mdwn b/doc/plugins/aggregate.mdwn
index 75123d923..b1db828d1 100644
--- a/doc/plugins/aggregate.mdwn
+++ b/doc/plugins/aggregate.mdwn
@@ -11,6 +11,10 @@ The [[meta]] and [[tag]] plugins are also recommended to be used with this
 one. Either the [[htmltidy]] or [[htmlbalance]] plugin is suggested, since
 feeds can easily contain html problems, some of which these plugins can fix.
 
+Installing the [[!cpan LWPx::ParanoidAgent]] Perl module is strongly
+recommended. The [[!cpan LWP]] module can also be used, but is susceptible
+to server-side request forgery.
+
 ## triggering aggregation
 
 You will need to run ikiwiki periodically from a cron job, passing it the
diff --git a/doc/plugins/blogspam.mdwn b/doc/plugins/blogspam.mdwn
index 745fc48e2..0ebae7d84 100644
--- a/doc/plugins/blogspam.mdwn
+++ b/doc/plugins/blogspam.mdwn
@@ -11,6 +11,8 @@ To check for and moderate comments, log in to the wiki as an admin,
 go to your Preferences page, and click the "Comment Moderation" button.
 
 The plugin requires the [[!cpan JSON]] perl module.
+The [[!cpan LWPx::ParanoidAgent]] Perl module is recommended,
+although this plugin can also fall back to [[!cpan LWP]].
 
 You can control how content is tested via the `blogspam_options` setting.
 The list of options is [here](http://blogspam.net/api/2.0/testComment.html#options).
diff --git a/doc/plugins/openid.mdwn b/doc/plugins/openid.mdwn
index 4c8e0d381..a061cb43f 100644
--- a/doc/plugins/openid.mdwn
+++ b/doc/plugins/openid.mdwn
@@ -7,8 +7,11 @@ into the wiki.
 The plugin needs the [[!cpan Net::OpenID::Consumer]] perl module.
 Version 1.x is needed in order for OpenID v2 to work.
 
-The [[!cpan LWPx::ParanoidAgent]] perl module is used if available, for
-added security. Finally, the [[!cpan Crypt::SSLeay]] perl module is needed
+The [[!cpan LWPx::ParanoidAgent]] Perl module is strongly recommended.
+The [[!cpan LWP]] module can also be used, but is susceptible to
+server-side request forgery.
+
+The [[!cpan Crypt::SSLeay]] Perl module is needed
 to support users entering "https" OpenID urls.
 
 This plugin is enabled by default, but can be turned off if you want to
diff --git a/doc/plugins/pinger.mdwn b/doc/plugins/pinger.mdwn
index 00d83e1bb..f37979ac6 100644
--- a/doc/plugins/pinger.mdwn
+++ b/doc/plugins/pinger.mdwn
@@ -10,9 +10,11 @@ can be kept up-to-date.
 To configure what URLs to ping, use the [[ikiwiki/directive/ping]]
 [[ikiwiki/directive]].
 
-The [[!cpan LWP]] perl module is used for pinging. Or the [[!cpan
-LWPx::ParanoidAgent]] perl module is used if available, for added security.
-Finally, the [[!cpan Crypt::SSLeay]] perl module is needed to support pinging
+The [[!cpan LWPx::ParanoidAgent]] Perl module is strongly recommended.
+The [[!cpan LWP]] module can also be used, but is susceptible
+to server-side request forgery.
+
+The [[!cpan Crypt::SSLeay]] perl module is needed to support pinging
 "https" urls.
 
 By default the pinger will try to ping a site for 15 seconds before timing
diff --git a/doc/security.mdwn b/doc/security.mdwn
index e7770dd27..378a2e4bc 100644
--- a/doc/security.mdwn
+++ b/doc/security.mdwn
@@ -611,3 +611,52 @@ This was fixed in ikiwiki 3.20170111, with fixes backported to Debian 8
 in version 3.20141016.4.
 
 ([[!debcve CVE-2017-0356]]/OVE-20170111-0001)
+
+## Server-side request forgery via aggregate plugin
+
+The ikiwiki maintainers discovered that the [[plugins/aggregate]] plugin
+did not use [[!cpan LWPx::ParanoidAgent]]. On sites where the
+aggregate plugin is enabled, authorized wiki editors could tell ikiwiki
+to fetch potentially undesired URIs even if LWPx::ParanoidAgent was
+installed:
+
+* local files via `file:` URIs
+* other URI schemes that might be misused by attackers, such as `gopher:`
+* hosts that resolve to loopback IP addresses (127.x.x.x)
+* hosts that resolve to RFC 1918 IP addresses (192.168.x.x etc.)
+
+This could be used by an attacker to publish information that should not have
+been accessible, cause denial of service by requesting "tarpit" URIs that are
+slow to respond, or cause undesired side-effects if local web servers implement
+["unsafe"](https://tools.ietf.org/html/rfc7231#section-4.2.1) GET requests.
+([[!debcve CVE-2019-9187]])
+
+Additionally, if the LWPx::ParanoidAgent module was not installed, the
+[[plugins/blogspam]], [[plugins/openid]] and [[plugins/pinger]] plugins
+would fall back to [[!cpan LWP]], which is susceptible to similar attacks.
+This is unlikely to be a practical problem for the blogspam plugin because
+the URL it requests is under the control of the wiki administrator, but
+the openid plugin can request URLs controlled by unauthenticated remote
+users, and the pinger plugin can request URLs controlled by authorized
+wiki editors.
+
+This is addressed in ikiwiki 3.20190228 as follows, with the same fixes
+backported to Debian 9 in version 3.20170111.1:
+
+* URI schemes other than `http:` and `https:` are not accepted, preventing
+  access to `file:`, `gopher:`, etc.
+
+* If a proxy is [[configured in the ikiwiki setup file|tips/using_a_proxy]],
+  it is used for all outgoing `http:` and `https:` requests. In this case
+  the proxy is responsible for blocking any requests that are undesired,
+  including loopback or RFC 1918 addresses.
+
+* If a proxy is not configured, and LWPx::ParanoidAgent is installed,
+  it will be used. This prevents loopback and RFC 1918 IP addresses, and
+  sets a timeout to avoid denial of service via "tarpit" URIs.
+
+* Otherwise, the ordinary LWP user-agent will be used. This allows requests
+  to loopback and RFC 1918 IP addresses, and has less robust timeout
+  behaviour. We are not treating this as a vulnerability: if this
+  behaviour is not acceptable for your site, please make sure to install
+  LWPx::ParanoidAgent or disable the affected plugins.
diff --git a/doc/tips/using_a_proxy.mdwn b/doc/tips/using_a_proxy.mdwn
new file mode 100644
index 000000000..39df3c42a
--- /dev/null
+++ b/doc/tips/using_a_proxy.mdwn
@@ -0,0 +1,22 @@
+Some ikiwiki plugins make outgoing HTTP requests from the web server:
+
+* [[plugins/aggregate]] (to download Atom and RSS feeds)
+* [[plugins/blogspam]] (to check whether a comment or edit is spam)
+* [[plugins/openid]] (to authenticate users)
+* [[plugins/pinger]] (to ping other ikiwiki installations)
+
+If your ikiwiki installation cannot contact the Internet without going
+through a proxy, you can configure this in the [[setup file|setup]] by
+setting environment variables:
+
+    ENV:
+        http_proxy: "http://proxy.example.com:8080"
+        https_proxy: "http://proxy.example.com:8080"
+        # optional
+        no_proxy: ".example.com,www.example.org"
+
+Note that some plugins will use the configured proxy for all destinations,
+even if they are listed in `no_proxy`.
+
+To avoid server-side request forgery attacks, ensure that your proxy does
+not allow requests to addresses that are considered to be internal.

Announce v3.20190207
diff --git a/doc/news/version_3.20170622.mdwn b/doc/news/version_3.20170622.mdwn
deleted file mode 100644
index 33962b769..000000000
--- a/doc/news/version_3.20170622.mdwn
+++ /dev/null
@@ -1,31 +0,0 @@
-ikiwiki 3.20170622 released with [[!toggle text="these changes"]]
-[[!toggleable text="""
-   * `t/git-cgi.t`: Wait 1 second before doing a revert that should work.
-     This hopefully fixes a race condition in which the test failed
-     around 6% of the time. (Closes: #[862494](http://bugs.debian.org/862494))
-   * Guard against set-but-empty `REMOTE_USER` CGI variable on
-     misconfigured nginx servers, and in general treat sessions with
-     a set-but-empty name as if they were not signed in.
-   * When the CGI fails, print the error to stderr, not "Died"
-   * mdwn: Don't mangle <code>&lt;style&gt;</code> into <code>&lt;elyts&gt;</code> under some circumstances
-   * mdwn: Enable footnotes by default when using the default Discount
-     implementation. A new `mdwn_footnotes` option can be used to disable
-     footnotes in MultiMarkdown and Discount.
-   * mdwn: Don't enable alphabetically labelled ordered lists by
-     default when using the default Discount implementation. A new
-     `mdwn_alpha_list` option can be used to restore the old
-     interpretation.
-   * osm: Convert savestate hook into a changes hook. savestate is not
-     the right place to write wiki content, and in particular this
-     breaks websetup if osm's dependencies are not installed, even
-     if the osm plugin is not actually enabled.
-     (Closes: #[719913](http://bugs.debian.org/719913))
-   * toc: if the heading is of the form `<h1 id="...">`, use that for
-     the link in the table of contents (but continue to generate
-     `<a name="index42"></a>` in case someone was relying on it).
-     Thanks, [[Antoine Beaupré|anarcat]]
-   * color: Do not leak markup into contexts that take only the plain
-     text, such as toc
-   * meta: Document `\[[!meta name="foo" content="bar"]]`
-   * debian: Use preferred https URL for Format of `debian/copyright`
-   * debian: Declare compliance with Debian Policy 4.0.0"""]]
diff --git a/doc/news/version_3.20190207.mdwn b/doc/news/version_3.20190207.mdwn
new file mode 100644
index 000000000..8e5696ffd
--- /dev/null
+++ b/doc/news/version_3.20190207.mdwn
@@ -0,0 +1,34 @@
+ikiwiki 3.20190207 released with [[!toggle text="these changes"]]
+[[!toggleable text="""
+ * [ Amitai Schleier ]
+   * graph: Add an optional "file" parameter
+   * emailauth: When email can't be sent, show the error message
+   * osm: Don't raise errors if tags don't have attached icons
+   * cgi: Avoid C compiler warnings for waitpid() on NetBSD
+ * [ Simon McVittie ]
+   * Hide popup template content from documentation (Closes: #[898836](http://bugs.debian.org/898836))
+   * meta: Make [[!meta date]] show an error if dates are invalid or
+     Date::Parse can't be loaded
+   * inline: Cope with non-ASCII `rootpage` parameter.
+     Thanks, Feng Shu
+   * table: Cope with non-ASCII content in CSV format tables.
+     Thanks, Feng Shu
+   * trail: Allow unescaped punctuation in `pagenames` parameter
+   * comments: Hide "add comment" link from print stylesheet.
+     Thanks, Antoine Beaupré
+   * recentchangesdiff, relativedate, toggle:
+     Import JavaScript at the end of the page content, not the beginning,
+     so that the browser can render content as soon as possible.
+     Thanks, Antoine Beaupré
+   * debian: Allow Breezy as an alternative to bzr
+     Thanks, Jelmer Vernooij
+   * inline: Add basic test coverage for [[!inline rootpage]]
+   * table: Add basic test coverage
+   * po: Add enough test coverage to reproduce Debian #911356
+   * comments: Improve test coverage
+   * tests: Exercise Unicode more
+ * [ Joey Hess ]
+   * aggregate: Fix aggregation of posts without a title.
+     Thanks, Alexandre Oliva
+   * poll: Added postlink and posttrail options for better multi-page polls.
+   * Fix permalink to comments."""]]
\ No newline at end of file

review
diff --git a/doc/todo/pagespec_aliases.mdwn b/doc/todo/pagespec_aliases.mdwn
index 396a93c0f..bd64a5040 100644
--- a/doc/todo/pagespec_aliases.mdwn
+++ b/doc/todo/pagespec_aliases.mdwn
@@ -1,3 +1,4 @@
+[[!tag reviewed]]
 [[!template id=gitbranch branch=jon/pagespec_alias author="[[Jon]]"]]
 [[!tag patch wishlist]]I quite often find myself repeating a boiler-plate
 [[ikiwiki/pagespec]] chunk, e.g.
@@ -175,3 +176,38 @@ that I'd got it up to a merge-request state; I've dusted it off and done some
 clean up and testing, but it's working (albeit not via websetup). I've revamped
 the docs and rebased the branch. Can someone please consider merging ([[joey]]
 or [[smcv]]?) or otherwise feed back on this? Thanks! — [[Jon]] (2018-09-25)
+
+> To hide it from `websetup`, the `example` needs to be a hash reference
+> like `example => { images => "*.png or *.jpg or *.gif" }`, I think?
+> (Please try it on a websetup-enabled wiki, possibly by copying
+> `t/manual/git_revert` to `t/manual/websetup` and adapting it as required.)
+>
+> For a less magical variant, you could consider using `alias(images)`
+> instead of `images()` for the pagespec syntax that is enabled by the
+> example above. I'm not sure which way is better.
+>
+> If `safe_key` fails, you probably want to log a warning, or even fail
+> `checkconfig` with a fatal `error`?
+>
+> If `checkconfig` detects that the given pagespec function already
+> exists, for example `title` after loading the meta plugin, you probably
+> want to log a warning or fail? It seems you can detect this with
+> `defined ref *$subname{CODE}`.
+>
+> If you define a loop of mutually recursive aliases (or even an alias
+> that refers to itself), I think you'll get infinite recursion.
+> You can probably bypass that with a construct like:
+>
+>     my $entered;
+>     *{ $subname } = sub {
+>         return IkiWiki::ErrorReason->new("Alias $key is defined recursively") if $entered;
+>         $entered = 1;
+>         my $result = IkiWiki::pagespec_match($path, $value);
+>         $entered = 0;
+>         return $result;
+>     }
+>
+> (but don't take my word for it, a regression test would tell you whether
+> this works.)
+>
+> --[[smcv]]

comment
diff --git a/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn b/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn
index e3a57e184..690f89d5d 100644
--- a/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn
+++ b/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn
@@ -7,3 +7,16 @@ normally, however, HTML creation will be disabled and no reference to
 these translations will be visible on the website.
 
 See also downstream bug report in tails: <https://labs.riseup.net/code/issues/15355>
+
+> From the downstream bug report it appears this branch is not yet
+> considered ready (as of February 2019), so I haven't attempted to
+> review it.
+>
+> As with everything else in the `po` plugin: I would really want to see
+> some regression test coverage before merging this, because as far as I'm
+> aware none of the ikiwiki maintainers use the `po` plugin, so we are
+> not able to detect regressions other than via the automated tests. That
+> isn't a good situation to be in for a plugin that uses `IkiWiki::inject`
+> to monkey-patch ikiwiki internals. If this plugin is important to you,
+> more test coverage would be very much appreciated.
+> --[[smcv]]

tag as reviewed
diff --git a/doc/todo/support_multi-row_table_headers.mdwn b/doc/todo/support_multi-row_table_headers.mdwn
index 07198fd5c..11bb909e2 100644
--- a/doc/todo/support_multi-row_table_headers.mdwn
+++ b/doc/todo/support_multi-row_table_headers.mdwn
@@ -1,4 +1,6 @@
 [[!template id=gitbranch branch=jon/table_headerblock author="[[Jon]]"]]
+[[!tag reviewed]]
+
 It would be great if it were possible to support multi-row table headers in the [[plugins/table]] plugin, so you could do e.g.
 
         \[[!table header="""

respond
diff --git a/doc/todo/support_multi-row_table_headers.mdwn b/doc/todo/support_multi-row_table_headers.mdwn
index 1d418a41b..07198fd5c 100644
--- a/doc/todo/support_multi-row_table_headers.mdwn
+++ b/doc/todo/support_multi-row_table_headers.mdwn
@@ -96,3 +96,33 @@ and easily underneath.
 
 I'd appreciate your take on the above suggestions [[smcv]] before I roll my sleeves up.
 Thanks! — [[Jon]] (2018-09-24)
+
+> I continue to think that the `header` parameter shouldn't be sometimes a
+> description of which parts of the table are header, and sometimes the header
+> data itself; so if you want an inline header, it should indeed have a
+> distinct name.
+>
+> If you can think of a good name for the new parameter, and can document it
+> reasonably clearly, then I would be OK with having a separate parameter that
+> is the externally-provided header. I don't know what the right name for that
+> parameter would be: `headercontent` or `headerblock` is unwieldy but I can't
+> think of anything better.
+>
+> It would maybe simplify things to make it mutually exclusive with `header`,
+> but then you wouldn't be able to express things like "the first column of my
+> CSV is a header, the first row is just an ordinary row, and please add
+> this literal header row to the top".
+>
+> It might help to write the documentation and/or tests first, and then
+> implement it afterwards, when you have an "API" you're happy with.
+>
+> Corner cases:
+>
+> How would it work if you want to add a literal header column on the left
+> rather than adding a literal header row on the top? If you add both, what
+> happens at the top left corner?
+>
+> Is it necessary to be able to add header columns on the right (for RTL
+> languages?), or header rows (footer rows, I suppose) on the bottom?
+>
+> --[[smcv]]

Exclude reviewed patches from this list
diff --git a/doc/patch.mdwn b/doc/patch.mdwn
index 7d0f9847c..800748873 100644
--- a/doc/patch.mdwn
+++ b/doc/patch.mdwn
@@ -8,5 +8,8 @@ If your patch is non-trivial and might need several iterations to get
 right, or you'd just like to make it easy for [[Joey]] to apply it,
 please consider publishing a [[git]] [[branch|branches]].
 
+Patches that have been reviewed and need changes before they are merged
+are listed separately, on the [[reviewed]] list.
+
 [[!inline pages="(todo/* or bugs/*) and link(patch) and !link(bugs/done) and
-!link(todo/done) and !*/Discussion" rootpage="todo" archive="yes"]]
+!link(todo/done) and !link(reviewed) and !*/Discussion" rootpage="todo" archive="yes"]]

close
diff --git a/CHANGELOG b/CHANGELOG
index d8ac33d6d..1fa0a7c92 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -17,6 +17,10 @@ ikiwiki (3.20180312) UNRELEASED; urgency=medium
   * trail: Allow unescaped punctuation in `pagenames` parameter
   * comments: Hide "add comment" link from print stylesheet.
     Thanks, Antoine Beaupré
+  * recentchangesdiff, relativedate, toggle:
+    Import JavaScript at the end of the page content, not the beginning,
+    so that the browser can render content as soon as possible.
+    Thanks, Antoine Beaupré
   * debian: Allow Breezy as an alternative to bzr
     Thanks, Jelmer Vernooij
   * inline: Add basic test coverage for [[!inline rootpage]]
diff --git a/doc/todo/fix_javascript_load_ordering.mdwn b/doc/todo/fix_javascript_load_ordering.mdwn
index 6a4e15ff2..ef07a3ae9 100644
--- a/doc/todo/fix_javascript_load_ordering.mdwn
+++ b/doc/todo/fix_javascript_load_ordering.mdwn
@@ -18,3 +18,5 @@ Javascript on the *closing* `</body>` tag instead of the *opening* tag.
 
 It also improves the regex to tolerate spaces before the `</body>` tag,
 as some templates have (proper) indentation for the tag.
+
+> [[Applied|done]], thanks --[[smcv]]

Mark as applied
diff --git a/CHANGELOG b/CHANGELOG
index 60701dbb6..d8ac33d6d 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -15,6 +15,8 @@ ikiwiki (3.20180312) UNRELEASED; urgency=medium
   * table: Cope with non-ASCII content in CSV format tables.
     Thanks, Feng Shu
   * trail: Allow unescaped punctuation in `pagenames` parameter
+  * comments: Hide "add comment" link from print stylesheet.
+    Thanks, Antoine Beaupré
   * debian: Allow Breezy as an alternative to bzr
     Thanks, Jelmer Vernooij
   * inline: Add basic test coverage for [[!inline rootpage]]
diff --git a/doc/todo/hide_add_comment_button_in_print.mdwn b/doc/todo/hide_add_comment_button_in_print.mdwn
index cbfaca888..7ed2645b3 100644
--- a/doc/todo/hide_add_comment_button_in_print.mdwn
+++ b/doc/todo/hide_add_comment_button_in_print.mdwn
@@ -45,4 +45,6 @@ Thanks! -- [[anarcat]]
 [remove]: https://gitlab.com/anarcat/ikiwiki-bootstrap-anarcat/commit/94521766f4206882c44764253452ec666d90d5c1
 [this patch]: https://gitlab.com/anarcat/ikiwiki/commit/33630b561623b8dca946916b733807e9b8c97849.patch
 
+> [[Applied|done]] --[[smcv]]
+
 [[!tag patch]]

old regexp would have failed for old comment page names
diff --git a/doc/bugs/permalink_not_set_for_comments.mdwn b/doc/bugs/permalink_not_set_for_comments.mdwn
index b6ef5cb31..d41da9c35 100644
--- a/doc/bugs/permalink_not_set_for_comments.mdwn
+++ b/doc/bugs/permalink_not_set_for_comments.mdwn
@@ -37,4 +37,7 @@ two underscores. I think that is the root of the bug. --[[Joey]]
 >> * *d* marks `\d+` (one or more digits)
 >> * *u* marks the literal `_`
 >>
+>> The old regexp would have failed for the older format
+>> `foo/comment_1._comment`, though.
+>>
 >> --[[smcv]]

git-cgi.t: Exercise an alphanumeric, but non-ASCII, root page
My previous attempt to reproduce this bug used a non-alphanumeric
ASCII character. This is not currently considered to be a valid
value for rootpage, although for a "do what I mean" approach, perhaps
we should accept it and pass it through titlepage() or linkpage().
Using Chinese characters (which are considered to match [[:alnum:]]
even though the Chinese script is not, strictly speaking, an alphabet),
as in the original bug report, reproduces the bug.
diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index 29879e9f0..d45325711 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -64,28 +64,21 @@ not deal with Chinese char, the below link can work
     
 ---
 
-> Please could you try to make a minimal example or test, perhaps in the [[sandbox]]
-> on this wiki or as a unit test in `t/git-cgi.t` in the ikiwiki source code, that
-> demonstrates this bug and would be fixed by your patch? I tried to write a test
-> for this, and I was able to make a test that uses a UTF-8 `rootpage` and fails;
-> but your patch doesn't seem to fix it, so you must be seeing something different.
-> I think there might be more than one bug here.
+> [Request for clarification removed]
 >
-> If you've found multiple bugs, a separate example or test for each one would be
-> easiest to deal with.
+> I've now been able to reproduce this bug, and confirmed that your patch
+> fixes it. [[Patch now applied|done]].
 >
-> In your original report, you said the `rootpage` was ASCII and started with `./`:
-> `./bugs`. Then you mentioned Chinese characters (any non-ASCII character like é or ¬
-> should behave the same as Chinese here) and attached a patch that alters how those
-> are handled, without affecting what would happen to a `rootpage` that starts
-> with `./`; so I'm confused about what the bug was, and what you are fixing?
+> (For other maintainers' reference: when testing Unicode bugs that
+> relate to page titles, using Unicode that is considered to be
+> punctuation, like ¬ or emoji, will probably not work; page titles
+> treat `[:alnum:]` and `^[:alnum:]` differently.)
 >
-> I've added tests to `t/git-cgi.t` which demonstrate
-> [a blog form for a `rootpage` named `writable/blog` working correctly](http://source.ikiwiki.branchable.com/?p=source.git;a=commitdiff;h=9c0694b14c0c8ed0dee4ff4ed57f689919707cd7;hp=a10d86bbaebee2d6a30b66b4366d3f0247264678)
-> (which passes), and
-> [a `rootpage` named `writable/¬blog` not working correctly](http://source.ikiwiki.branchable.com/?p=source.git;a=commitdiff;h=2bd72cd0e01b8bb433b368e11ff9db779a21ccef;hp=9c0694b14c0c8ed0dee4ff4ed57f689919707cd7)
-> (which fails, and is marked as *TODO*).
-> The patch above doesn't seem to make the second new test pass.
+> In future bug reports it would be useful if you could provide a minimal
+> example or test, perhaps on the [[sandbox]] on this wiki or as a unit
+> test in `t/*.t` in the ikiwiki source code, that demonstrates this bug
+> and would be fixed by the patch. If you've found multiple bugs, a
+> separate example or test for each one would be easiest to deal with.
 >
 > You can run all the tests with:
 >
diff --git a/t/git-cgi.t b/t/git-cgi.t
index 79cd62f61..3556bc038 100755
--- a/t/git-cgi.t
+++ b/t/git-cgi.t
@@ -1,7 +1,9 @@
 #!/usr/bin/perl
+use utf8;
 use warnings;
 use strict;
 
+use Encode;
 use Test::More;
 
 BEGIN {
@@ -133,7 +135,7 @@ sub run_cgi {
 		} keys(%envvars);
 	});
 
-	return $out;
+	return decode_utf8($out);
 }
 
 sub run_git {
@@ -169,6 +171,8 @@ sub test {
 		'[[!inline pages="writable/blog/*" actions=yes rootpage=writable/blog postform=yes show=0]]');
 	write_old_file('doc/writable/__172__blog.mdwn', 't/tmp/in',
 		'[[!inline pages="writable/¬blog/*" actions=yes rootpage="writable/¬blog" postform=yes show=0]]');
+	write_old_file('doc/writable/中文.mdwn', 't/tmp/in',
+		'[[!inline pages="writable/中文/*" actions=yes rootpage="writable/中文" postform=yes show=0]]');
 
 	unless ($installed) {
 		ok(! system(qw(cp -pRL doc/wikiicons t/tmp/in/doc/)));
@@ -332,24 +336,20 @@ sub test {
 	);
 	like($content, qr{<option selected="selected" value="writable/blog/hello">writable/blog/hello</option>});
 
-	# This attempts to reproduce the bug from
-	# doc/bugs/About___37__2F_problem, in which you can't make new posts
-	# to a blog with a non-ASCII rootpage.
-	$content = readfile('t/tmp/out/writable/__172__blog/index.html');
-	like($content, qr{<input type="hidden" name="from" value="writable/¬blog"});
-	TODO: {
-	local $TODO = 'doc/bugs/About___37__2F_problem';
+	# Regression test for a bug in which we couldn't use an
+	# alphanumeric, but non-ASCII, root page.
+	$content = readfile('t/tmp/out/writable/中文/index.html');
+	like($content, qr{<input type="hidden" name="from" value="writable/中文"});
 	$content = run_cgi(method => 'get',
 		params => {
 			do => 'blog',
-			from => 'writable/¬blog',
+			from => 'writable/中文',
 			subpage => '1',
 			title => 'hello',
 		},
 	);
-	like($content, qr{<option selected="selected" value="writable/¬blog/hello">writable/¬blog/hello</option>});
+	like($content, qr{<option selected="selected" value="writable/中文/hello">writable/中文/hello</option>});
 	unlike($content, qr{Error: bad page name});
-	}
 }
 
 test();

link to recently-added tests
diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index 15f64b883..29879e9f0 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -80,9 +80,11 @@ not deal with Chinese char, the below link can work
 > are handled, without affecting what would happen to a `rootpage` that starts
 > with `./`; so I'm confused about what the bug was, and what you are fixing?
 >
-> I've added tests to `t/git-cgi.t` which demonstrate a blog form for a `rootpage`
-> named `writable/blog` working correctly (which passes), and a `rootpage` named
-> `writable/¬blog` not working correctly (which fails, and is marked as *TODO*).
+> I've added tests to `t/git-cgi.t` which demonstrate
+> [a blog form for a `rootpage` named `writable/blog` working correctly](http://source.ikiwiki.branchable.com/?p=source.git;a=commitdiff;h=9c0694b14c0c8ed0dee4ff4ed57f689919707cd7;hp=a10d86bbaebee2d6a30b66b4366d3f0247264678)
+> (which passes), and
+> [a `rootpage` named `writable/¬blog` not working correctly](http://source.ikiwiki.branchable.com/?p=source.git;a=commitdiff;h=2bd72cd0e01b8bb433b368e11ff9db779a21ccef;hp=9c0694b14c0c8ed0dee4ff4ed57f689919707cd7)
+> (which fails, and is marked as *TODO*).
 > The patch above doesn't seem to make the second new test pass.
 >
 > You can run all the tests with:

I'm confused about what the bug is, and what's being fixed. Can you give a complete test or example?
diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index f855485d2..15f64b883 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -62,6 +62,39 @@ not deal with Chinese char, the below link can work
     -- 
     2.19.0
     
+---
 
-
-
+> Please could you try to make a minimal example or test, perhaps in the [[sandbox]]
+> on this wiki or as a unit test in `t/git-cgi.t` in the ikiwiki source code, that
+> demonstrates this bug and would be fixed by your patch? I tried to write a test
+> for this, and I was able to make a test that uses a UTF-8 `rootpage` and fails;
+> but your patch doesn't seem to fix it, so you must be seeing something different.
+> I think there might be more than one bug here.
+>
+> If you've found multiple bugs, a separate example or test for each one would be
+> easiest to deal with.
+>
+> In your original report, you said the `rootpage` was ASCII and started with `./`:
+> `./bugs`. Then you mentioned Chinese characters (any non-ASCII character like é or ¬
+> should behave the same as Chinese here) and attached a patch that alters how those
+> are handled, without affecting what would happen to a `rootpage` that starts
+> with `./`; so I'm confused about what the bug was, and what you are fixing?
+>
+> I've added tests to `t/git-cgi.t` which demonstrate a blog form for a `rootpage`
+> named `writable/blog` working correctly (which passes), and a `rootpage` named
+> `writable/¬blog` not working correctly (which fails, and is marked as *TODO*).
+> The patch above doesn't seem to make the second new test pass.
+>
+> You can run all the tests with:
+>
+>     ./Makefile.PL
+>     make
+>     make test
+>
+> or a single test with something like:
+>
+>     ./Makefile.PL
+>     make
+>     PERL5LIB=. ./t/git-cgi.t
+>
+> --[[smcv]]

close bug
diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index dc94db596..8e7aa6fc3 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -80,7 +80,9 @@ The below patch seem to deal with this problem:
      			debug(sprintf(gettext('parse fail at line %d: %s'), 
     -- 
     2.19.0
-    
+
+> Thanks, I've applied that patch and added test coverage. [[done]] --[[smcv]]
+
 ----
 
 I can confirm that the above patch fixes the issue for me. Thanks! I'm not an ikiwiki committer, but I would encourage them to consider the above. Whilst I'm at it, I would be *really* grateful for some input on [[todo/support_multi-row_table_headers]] which relates to the same plugin. [[Jon]]

respond
diff --git a/doc/bugs/permalink_not_set_for_comments.mdwn b/doc/bugs/permalink_not_set_for_comments.mdwn
index 2e74a2622..b6ef5cb31 100644
--- a/doc/bugs/permalink_not_set_for_comments.mdwn
+++ b/doc/bugs/permalink_not_set_for_comments.mdwn
@@ -23,3 +23,18 @@ two underscores. I think that is the root of the bug. --[[Joey]]
 > preprocessed again, not immediately. That's ok for notifyemail,
 > but other uses of permalink might need a wiki rebuild to get the bug fix.
 > --[[Joey]]
+>
+>> I'm not sure that I see how the regexp was wrong? It's looking for,
+>> for example,
+>>
+>>     foo/comment_1_eaab671848ee6129f6fe9399474eeac0._comment
+>>        sccccccccdu
+>>
+>> where
+>>
+>> * *s* marks the literal `/`
+>> * *cccc* marks `comments_pagename`
+>> * *d* marks `\d+` (one or more digits)
+>> * *u* marks the literal `_`
+>>
+>> --[[smcv]]

Fix syntax and escaping
diff --git a/doc/plugins/map.mdwn b/doc/plugins/map.mdwn
index c257d365f..5b009f424 100644
--- a/doc/plugins/map.mdwn
+++ b/doc/plugins/map.mdwn
@@ -15,5 +15,5 @@ Example:
 
 It's also possible to search for specific tags or links:
 
-    [[!map pages="todo/* and !todo/done and !link(todo/done)]]
+    \[[!map pages="todo/* and !todo/done and !link(todo/done)"]]
 """]]

Reset example
This reverts commit 0b53772b99248d2868fac688cdaa227ad61ac08e
diff --git a/doc/examples/blog/posts/hthn.mdwn b/doc/examples/blog/posts/hthn.mdwn
deleted file mode 100644
index 8fb80c2fa..000000000
--- a/doc/examples/blog/posts/hthn.mdwn
+++ /dev/null
@@ -1 +0,0 @@
-thonk

inline is another option of course
diff --git a/doc/tags.mdwn b/doc/tags.mdwn
index f16aa619b..c8f31423d 100644
--- a/doc/tags.mdwn
+++ b/doc/tags.mdwn
@@ -22,5 +22,5 @@ particular set of tags. Or just look at the [[BackLinks]] to a tag page to
 see all the pages that are tagged with it. [[Plugins]] can be written to do
 anything else with tags that you might desire.
 
-Once you have tags, you can use the [[plugins/pagestats]] or [[plugins/map]] plugins to
+Once you have tags, you can use the [[plugins/pagestats]], [[plugins/inline]] or [[plugins/map]] plugins to
 generate tag clouds and lists.

show tagging example
diff --git a/doc/plugins/map.mdwn b/doc/plugins/map.mdwn
index b164d5ca8..c257d365f 100644
--- a/doc/plugins/map.mdwn
+++ b/doc/plugins/map.mdwn
@@ -5,7 +5,15 @@ This plugin provides the [[ikiwiki/directive/map]] [[ikiwiki/directive]],
 which generates a hierarchical page map for the wiki.
 
 [[!if test="enabled(map)" then="""
-Here's an example map, for the plugins section of this wiki:
+This will create an a map, for the plugins section of this wiki:
+
+    \[[!map pages="(plugins or plugins/*) and !*/*/*"]]
+
+Example:
 
 [[!map pages="(plugins or plugins/*) and !*/*/*"]]
+
+It's also possible to search for specific tags or links:
+
+    [[!map pages="todo/* and !todo/done and !link(todo/done)]]
 """]]

link to the map plugin, which i find more useful to show tagged pages
diff --git a/doc/tags.mdwn b/doc/tags.mdwn
index 71d925b24..f16aa619b 100644
--- a/doc/tags.mdwn
+++ b/doc/tags.mdwn
@@ -22,5 +22,5 @@ particular set of tags. Or just look at the [[BackLinks]] to a tag page to
 see all the pages that are tagged with it. [[Plugins]] can be written to do
 anything else with tags that you might desire.
 
-Once you have tags, you can use the [[plugins/pagestats]] plugin to
-generate tag clouds.
+Once you have tags, you can use the [[plugins/pagestats]] or [[plugins/map]] plugins to
+generate tag clouds and lists.

diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index 681ec2ee1..95e772e0c 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -22,7 +22,7 @@ This is the [[SandBox]], a page anyone can edit to try out ikiwiki
 vvvv
 CamelCase ?
 
-[[!tag sandbox]]
+[[!tag sandbox tag2]]
 
 What about [[this page]], nono better [[that page]]?
 

followup
diff --git a/doc/bugs/permalink_not_set_for_comments.mdwn b/doc/bugs/permalink_not_set_for_comments.mdwn
index 9ca8200b5..2e74a2622 100644
--- a/doc/bugs/permalink_not_set_for_comments.mdwn
+++ b/doc/bugs/permalink_not_set_for_comments.mdwn
@@ -14,3 +14,12 @@ permalink:
 
 `comments_pagename` is `comment_` so the above code needs a comment page to contain
 two underscores. I think that is the root of the bug. --[[Joey]]
+
+> Removed the trailing underscore in the regexp, so it should be fixed,
+> though I have not tested the fix. Leaving this bug open until it's
+> confirmed fixed. (I deployed it to branchable.)
+> 
+> This will only fix the stored permalink metadata for a comment when its get
+> preprocessed again, not immediately. That's ok for notifyemail,
+> but other uses of permalink might need a wiki rebuild to get the bug fix.
+> --[[Joey]]

bug report
diff --git a/doc/bugs/permalink_not_set_for_comments.mdwn b/doc/bugs/permalink_not_set_for_comments.mdwn
new file mode 100644
index 000000000..9ca8200b5
--- /dev/null
+++ b/doc/bugs/permalink_not_set_for_comments.mdwn
@@ -0,0 +1,16 @@
+Changes to comments result in notifyemail sending emails with broken urls like 
+"http://whatever/foo/comment_1_10a49d69282155c5c3e66dc58f64f956/"
+
+notifyemail uses meta permalink if set, so it must not be set for comment
+pages.
+
+In the comments plugin, there's this code, which is supposed to set
+permalink:
+
+        if ($params{page} =~ m/\/\Q$config{comments_pagename}\E\d+_/) {
+                $pagestate{$page}{meta}{permalink} = urlto(IkiWiki::dirname($params{page})).
+                        "#".page_to_id($params{page});
+        }
+
+`comments_pagename` is `comment_` so the above code needs a comment page to contain
+two underscores. I think that is the root of the bug. --[[Joey]]

diff --git a/doc/examples/blog/posts/hthn.mdwn b/doc/examples/blog/posts/hthn.mdwn
new file mode 100644
index 000000000..8fb80c2fa
--- /dev/null
+++ b/doc/examples/blog/posts/hthn.mdwn
@@ -0,0 +1 @@
+thonk

User link and description changed
diff --git a/doc/ikiwikiusers.mdwn b/doc/ikiwikiusers.mdwn
index 3a810a731..d14e4898c 100644
--- a/doc/ikiwikiusers.mdwn
+++ b/doc/ikiwikiusers.mdwn
@@ -194,7 +194,7 @@ Personal sites and blogs
 * [Salient Dream](http://www.salientdream.com/) - All Things Strange. 
 * [Anton Berezin's blog](http://blog.tobez.org/)
 * [Waldgarten]( http://waldgarten.greenonion.org/ ) News and documentation of a permaculture inspired neighbourhood-garden located in Hamburg, Germany.
-* [Frohdo](https://frohdo.de) - With raw food against back pain and other diseases
+* [Waldfarm](https://waldfarm.de) - Natural Life by Natural Farming, Natürliches Leben mit natürlicher Landwirtschaft
 * [[OscarMorante]]'s [personal site](http://oscar.morante.eu).
 * [Puckspage]( http://www.puckspage.org/ ) Political and personal blog in German. The name comes from the elf out of midsummer nights dream.  
 * [[LucaCapello]]'s [homepage](http://luca.pca.it)

markdown backquotes
diff --git a/doc/sandbox.mdwn b/doc/sandbox.mdwn
index 5a2a10987..681ec2ee1 100644
--- a/doc/sandbox.mdwn
+++ b/doc/sandbox.mdwn
@@ -39,9 +39,12 @@ pre formated text?
 ~~~
 
 ```
-testing markdown
+testing markdown  
+    with leading    and enclosed spaces
 ```
 
+markdown `inline` single-backquotes?
+
 # one
 
 - foo

diff --git a/doc/users/alexeidz.mdwn b/doc/users/alexeidz.mdwn
index f6ada1795..1fa4c251a 100644
--- a/doc/users/alexeidz.mdwn
+++ b/doc/users/alexeidz.mdwn
@@ -1,3 +1,4 @@
 PROBLEM_1
 PROBLEM_2
 PROBLEM_3
+PROBLEM_4

diff --git a/doc/users/alexeidz.mdwn b/doc/users/alexeidz.mdwn
new file mode 100644
index 000000000..f6ada1795
--- /dev/null
+++ b/doc/users/alexeidz.mdwn
@@ -0,0 +1,3 @@
+PROBLEM_1
+PROBLEM_2
+PROBLEM_3

followup
diff --git a/doc/bugs/Unable_to_access_pagespec_preferences_on_https:__47____47__joeyh.name__47__/comment_1_8e26ec8941be9f6b16cec97281df7aaf._comment b/doc/bugs/Unable_to_access_pagespec_preferences_on_https:__47____47__joeyh.name__47__/comment_1_8e26ec8941be9f6b16cec97281df7aaf._comment
new file mode 100644
index 000000000..940366a7c
--- /dev/null
+++ b/doc/bugs/Unable_to_access_pagespec_preferences_on_https:__47____47__joeyh.name__47__/comment_1_8e26ec8941be9f6b16cec97281df7aaf._comment
@@ -0,0 +1,17 @@
+[[!comment format=mdwn
+ username="joey"
+ subject="""comment 1"""
+ date="2018-12-12T14:40:46Z"
+ content="""
+Sending an auth token with every notification email would
+not be good from a security POV.
+
+But, the ikiwiki username that has subscribed could be included in the
+emails; the url to the prefs could possibly even have it prefilled
+(unless CSRF protection or something prevents that).
+
+> I think now when I login via either method I'm accessing the account with a username
+
+No, ikiwiki accounts are not connected like this. If you log in with the
+old account it will have separate subscription prefs than the new account.
+"""]]

diff --git a/doc/users/xuqi.mdwn b/doc/users/xuqi.mdwn
index f127147e8..b2bddb070 100644
--- a/doc/users/xuqi.mdwn
+++ b/doc/users/xuqi.mdwn
@@ -1 +1 @@
-Hi there, I'm Xu Qi. I am an editor (who process and critique literature works, I don't compete with Vim or Emacs). I have been using [[ikiwiki]] on and off for 4 years. Comments welcome.
+Hi there, I'm XU Qi (he/him). I am an editor (who process and critique literature works, I don't compete with Vim or Emacs). I have been using [[ikiwiki]] on and off for 4 years. Comments welcome.

diff --git a/doc/users/xuqi.mdwn b/doc/users/xuqi.mdwn
new file mode 100644
index 000000000..f127147e8
--- /dev/null
+++ b/doc/users/xuqi.mdwn
@@ -0,0 +1 @@
+Hi there, I'm Xu Qi. I am an editor (who process and critique literature works, I don't compete with Vim or Emacs). I have been using [[ikiwiki]] on and off for 4 years. Comments welcome.

de-indenting
diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn
index 9045d032d..59a0506d3 100644
--- a/doc/ikiwiki/pagespec.mdwn
+++ b/doc/ikiwiki/pagespec.mdwn
@@ -71,7 +71,7 @@ SandBox", since no page can match both expressions.
 
 If you want to include only one level of subpages, you can use
 
-      blog/* and !blog/*/*
+    blog/* and !blog/*/*
 
 More complex expressions can also be created, by using parentheses for
 grouping. For example, to match pages in a blog that are tagged with either

example for inlining only one level of subpages
diff --git a/doc/ikiwiki/pagespec.mdwn b/doc/ikiwiki/pagespec.mdwn
index 0f298ad78..9045d032d 100644
--- a/doc/ikiwiki/pagespec.mdwn
+++ b/doc/ikiwiki/pagespec.mdwn
@@ -69,6 +69,10 @@ want to combine expression like that; "or" when it's enough for a page to
 match one expression. Note that it doesn't make sense to say "index and
 SandBox", since no page can match both expressions.
 
+If you want to include only one level of subpages, you can use
+
+      blog/* and !blog/*/*
+
 More complex expressions can also be created, by using parentheses for
 grouping. For example, to match pages in a blog that are tagged with either
 of two tags, use:

fail to inject IkiWiki::showform
diff --git a/doc/bugs/IkiWiki::showform_can_not_be_injected__63__.mdwn b/doc/bugs/IkiWiki::showform_can_not_be_injected__63__.mdwn
new file mode 100644
index 000000000..fd63f3eef
--- /dev/null
+++ b/doc/bugs/IkiWiki::showform_can_not_be_injected__63__.mdwn
@@ -0,0 +1,71 @@
+I want inject IkiWiki::showform and use replace submit button with translated button,
+but it seem no effect in cgi, does IkiWiki::showfrom can not be injectd when run as cgi?
+
+by the way, what about add a post-showform hook to ikiwiki?
+
+the below is my code:
+    
+    #!/usr/bin/perl
+    package IkiWiki::Plugin::chinesize;
+    
+    use warnings;
+    use strict;
+    use IkiWiki 3.00;
+    
+    inject(name => 'IkiWiki::showform', call => \&myshowform);
+    
+    sub myshowform ($$$$;@) {
+        	        my $form=prepform(@_);
+        	        shift;
+        	        my $buttons=shift;
+        	        my $session=shift;
+        	        my $cgi=shift;
+                    
+                    my $str=cgitemplate($cgi, $form->title,
+                                              $form->render(submit => $buttons), @_);
+                    
+                    my %names = ("Save Page" => "保存页面",
+                                 "Preview"   => "预览",
+                                 "Cancel"    => "取消",
+                                 "Diff"      => "差异比较",
+                                 "Rename"    => "重命名",
+                                 "Remove"    => "删除",
+                                 "Login"     => "登录",
+                                 "Register"  => "注册",
+                                 "Logout"    => "退出",
+                                 "Setup"     => "设置",
+                                 "Users"     => "所有用户",
+                                 "Name"      => "用户名",
+                                 "Password"  => "密码",
+                                 "Email"     => "电子邮件",
+                                 "Save Preferences"   => "保存选项",
+                                 "Confirm Password"   => "再次输入密码",
+                                 "Create Account"     => "创建帐户",
+                                 "Reset Password"     => "重置密码",
+                                 "Insert Links"       => "插入链接",
+                                 "Rename Attachment"  => "重命名附件",
+                                 "Remove Attachments" => "删除附件",
+                                 "FormattingHelp"     => "格式帮助",
+                                 "Reset"              => "重置",
+                                 "Save Setup"         => "保存设置",
+                                 "Advanced Mode"      => "高级模式",
+                                 "Account Creation Password" => "请输入帐户创建密码(管理员预设)"
+                                 );
+                    
+                    foreach my $old_name (keys(%names))
+                    {
+                    my $new_name = Encode::decode_utf8($names{$old_name});
+                    $str =~ s/<input +id="([_A-Za-z0-9]+)" +name="([_A-Za-z0-9]+)" +type="([_A-Za-z0-9]+)" +value="($old_name)" +\/>/<button id="$1" name="$2" type="$3" value="$4">$new_name<\/button>/g;
+                    $str =~ s/<input +name="([_A-Za-z0-9]+)" +type="([_A-Za-z0-9]+)" +value="($old_name)" +\/>/<button name="$1" type="$2" value="$3">$new_name<\/button>/g;
+                    $str =~ s/<input +class="([_A-Za-z0-9]+)" +id="([_A-Za-z0-9]+)" +name="([_A-Za-z0-9]+)" +type="([_A-Za-z0-9]+)" +value="($old_name)" +\/>/<button class="$1" id="$2" name="$3" type="$4" value="$5">$new_name<\/button>/g;
+                    $str =~ s/<div class="([_A-Za-z0-9]+)" id="([_A-Za-z0-9]+)">$old_name<\/div>/<div class="$1" id="$2">$new_name<\/div>/g;
+                    $str =~ s/<div class="([_A-Za-z0-9]+)" id="([_A-Za-z0-9]+)"><span class="([_A-Za-z0-9]+)">$old_name<\/span><\/div>/<div class="$1" id="$2"><span class="$3">$new_name<\/span><\/div>/g;
+                    $str =~ s/<a href="\.\/ikiwiki\/formatting\/">($old_name)<\/a>/<a href="\.\/ikiwiki\/formatting\/">$new_name<\/a>/g;
+                    };
+                    
+        	        printheader($session);
+        	        print $str
+                    
+                    }
+                    
+    

patch works for me
diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index d9ca6ec1f..dc94db596 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -81,6 +81,6 @@ The below patch seem to deal with this problem:
     -- 
     2.19.0
     
+----
 
-    
-
+I can confirm that the above patch fixes the issue for me. Thanks! I'm not an ikiwiki committer, but I would encourage them to consider the above. Whilst I'm at it, I would be *really* grateful for some input on [[todo/support_multi-row_table_headers]] which relates to the same plugin. [[Jon]]

ack
diff --git a/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn b/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
index 825a55403..fd25c0826 100644
--- a/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
+++ b/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
@@ -10,3 +10,5 @@ Instead of oddmuse style longtable, we can use YAML as table format:
     -
       a: 3
       b: 4
+
+> I think this is a great idea. It could be handled in the existing [[plugins/table]] plugin, with a new format= parameter. YAML sounds more attractive to me than oddmuse. -- [[Jon]]

rename and remove plug can not work well with gettext
diff --git a/doc/bugs/rename_and_remove_plug_can_not_work_well_with_gettext.mdwn b/doc/bugs/rename_and_remove_plug_can_not_work_well_with_gettext.mdwn
new file mode 100644
index 000000000..803e864f7
--- /dev/null
+++ b/doc/bugs/rename_and_remove_plug_can_not_work_well_with_gettext.mdwn
@@ -0,0 +1,3 @@
+I have found that the gettext string can not be translated to Chinese
+when I set LC_ALL to zh_CN.UTF-8
+

diff --git a/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn b/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
index fa54a975e..825a55403 100644
--- a/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
+++ b/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
@@ -1,6 +1,6 @@
 When we edit a table with many many columns, use csv or dsv format is
 not comfortable to work, what about let table plugin support a format
-like (oddmuse longtable plug)[https://oddmuse.org/download/oddmuse-2.3.13/tables-long.pl] 
+like [oddmuse longtable plug](https://oddmuse.org/download/oddmuse-2.3.13/tables-long.pl) 
 
 Instead of oddmuse style longtable, we can use YAML as table format:
 

Suggest let table plugin support a kind of longtable
diff --git a/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn b/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
new file mode 100644
index 000000000..fa54a975e
--- /dev/null
+++ b/doc/todo/Let_table_plugin_support_a_kind_of_long_table.mdwn
@@ -0,0 +1,12 @@
+When we edit a table with many many columns, use csv or dsv format is
+not comfortable to work, what about let table plugin support a format
+like (oddmuse longtable plug)[https://oddmuse.org/download/oddmuse-2.3.13/tables-long.pl] 
+
+Instead of oddmuse style longtable, we can use YAML as table format:
+
+    -
+      a: 1
+      b: 2
+    -
+      a: 3
+      b: 4

diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index e915d0f3a..f855485d2 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -63,7 +63,5 @@ not deal with Chinese char, the below link can work
     2.19.0
     
 
-2.19.0
-
 
 

Add a patch deal with UTF-8 csv table's problem
diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index fe71686e6..d9ca6ec1f 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -34,3 +34,53 @@ The below example works well too
 >> A related problem, also fixed by using DSV, is messing up the encoding of non-ASCII, non-wide characters, e.g. £ (workaround was to use &amp;pound; instead) -- [[Jon]]
 
 >>> Sorry, I have faced the same error: \[[!table Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.24/Encode.pm line 243.]] -- [[tumashu1]]
+
+---
+
+The below patch seem to deal with this problem:
+
+    From d6ed90331b31e4669222c6831f7a0f40f0677fe1 Mon Sep 17 00:00:00 2001
+    From: Feng Shu <tumashu@163.com>
+    Date: Sun, 2 Dec 2018 08:41:39 +0800
+    Subject: [PATCH 2/2] Fix table plugin can handle UTF-8 csv format
+    
+    ---
+     IkiWiki/Plugin/table.pm | 3 ++-
+     1 file changed, 2 insertions(+), 1 deletion(-)
+    
+    From ad1a92c796d907ad293e572a168b6e9a8219623f Mon Sep 17 00:00:00 2001
+    From: Feng Shu <tumashu@163.com>
+    Date: Sun, 2 Dec 2018 08:41:39 +0800
+    Subject: [PATCH 2/2] Fix table plugin can handle UTF-8 csv format
+    
+    ---
+     IkiWiki/Plugin/table.pm | 3 ++-
+     1 file changed, 2 insertions(+), 1 deletion(-)
+    
+    diff --git a/IkiWiki/Plugin/table.pm b/IkiWiki/Plugin/table.pm
+    index f3c425a37..7fea8ab1c 100644
+    --- a/IkiWiki/Plugin/table.pm
+    +++ b/IkiWiki/Plugin/table.pm
+    @@ -135,6 +135,7 @@ sub split_csv ($$) {
+     	my $csv = Text::CSV->new({ 
+     		sep_char	=> $delimiter,
+     		binary		=> 1,
+    +		decode_utf8 => 1,
+     		allow_loose_quotes => 1,
+     	}) || error("could not create a Text::CSV object");
+     	
+    @@ -143,7 +144,7 @@ sub split_csv ($$) {
+     	foreach my $line (@text_lines) {
+     		$l++;
+     		if ($csv->parse($line)) {
+    -			push(@data, [ map { decode_utf8 $_ } $csv->fields() ]);
+    +			push(@data, [ $csv->fields() ]);
+     		}
+     		else {
+     			debug(sprintf(gettext('parse fail at line %d: %s'), 
+    -- 
+    2.19.0
+    
+
+    
+

Add a patch decode_utf8 inline's root page
diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index bb021efb4..e915d0f3a 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -32,3 +32,38 @@ not deal with Chinese char, the below link can work
 > Ideally either the `inline` directive or the `blog` request handler would
 > understand and remove `./`, if it's something that makes sense in this context.
 > --[[smcv]]
+
+---
+
+> I have found the problem, it is inline plugin can not decode_utf8 "from", the below is patch:
+
+    From f79dde20b275707f70df2d481919a079abec6c19 Mon Sep 17 00:00:00 2001
+    From: Feng Shu <tumashu@163.com>
+    Date: Sun, 2 Dec 2018 08:38:34 +0800
+    Subject: [PATCH 1/2] Fix inline plugin can no set rootpage to a UTF-8 page
+    
+    ---
+     IkiWiki/Plugin/inline.pm | 2 +-
+     1 file changed, 1 insertion(+), 1 deletion(-)
+    
+    diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm
+    index a85cd5d2f..f40956821 100644
+    --- a/IkiWiki/Plugin/inline.pm
+    +++ b/IkiWiki/Plugin/inline.pm
+    @@ -125,7 +125,7 @@ sub sessioncgi ($$) {
+     			error(gettext("please enter a page title"));
+     		}
+     		# if the page already exists, munge it to be unique
+    -		my $from=$q->param('from');
+    +		my $from=decode_utf8($q->param('from'));
+     		my $add="";
+     		while (exists $IkiWiki::pagecase{lc($from."/".$page.$add)}) {
+     			$add=1 unless length $add;
+    -- 
+    2.19.0
+    
+
+2.19.0
+
+
+

add redirection
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
new file mode 100644
index 000000000..140ffbf70
--- /dev/null
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -0,0 +1 @@
+[[!meta redir="bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content"]]

rename bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn to bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
diff --git a/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
similarity index 100%
rename from doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
rename to doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
diff --git a/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt b/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content/20180628-patch.txt
similarity index 100%
rename from doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt
rename to doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content/20180628-patch.txt

update for rename of bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt to bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content/20180628-patch.txt
diff --git a/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn b/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
index 547eba375..a926135b0 100644
--- a/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
+++ b/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
@@ -37,7 +37,7 @@ This would result in the following translation:
     This is the inlined content.
     This is the inlined content.
 
-[[Initially proposed patch from Chris Lamb|bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt]]
+[[Initially proposed patch from Chris Lamb|bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file,_not_translated_content/20180628-patch.txt]]
 
 [[!tag patch]]
 

update for rename of todo/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt to bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt
diff --git a/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index 89074f79a..547eba375 100644
--- a/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -37,7 +37,7 @@ This would result in the following translation:
     This is the inlined content.
     This is the inlined content.
 
-[[Initially proposed patch from Chris Lamb|20180628-patch.txt]]
+[[Initially proposed patch from Chris Lamb|bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt]]
 
 [[!tag patch]]
 

rename todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn to bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
similarity index 100%
rename from doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
rename to doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt b/doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt
similarity index 100%
rename from doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt
rename to doc/bugs/Re-use_translated_content_instead_of_skipping_if_previously_translated/20180628-patch.txt

refer to a branch
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index 3763cd9b0..89074f79a 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -170,3 +170,10 @@ commit was actually relevant to `po` users?
 Naming is the easy part of this review: the `alreadyfiltered` family of
 functions are not named like cache getter/setter functions. This could
 be resolved by renaming.
+
+---
+
+[[!template id=gitbranch branch=smcv/wip/po-filter-every-time browse="https://git.pseudorandom.co.uk/smcv/ikiwiki.git/log/refs/heads/wip/po-filter-every-time" author="[[Simon_McVittie|smcv]]"]]
+
+If it's valid to remove the `alreadyfiltered` mechanism, my
+`wip/po-filter-every-time` branch does that. Please test?

po: Always filter .po files
The input to filter hooks is meant to be the content of a source file
on disk. If we only filter once per (page, destpage) pair, and a page
is inlined into the same destpage more than once, then the second
occurrence will render as the result of htmlizing .po source as if
it was Markdown (or whatever the type of the corresponding master page
is), which is never going to end well.
The alreadyfiltered mechanism was added in commit 1e874b3f to avoid
preprocessing loops, but I'm not sure where it could lead to a loop:
filter hooks are only called from IkiWiki::filter, which is only called
on page content from disk or on proposed content being previewed.
According to <https://bugs.debian.org/911356#41>, deleting the
alreadyfiltered mechanism resolves the problem, as well as simplifying
the code.
Closes: #911356
Tested-by: intrigeri
diff --git a/CHANGELOG b/CHANGELOG
index ad37e72e8..5237ee7b8 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,18 @@
+ikiwiki (3.20190208) UNRELEASED; urgency=medium
+
+  * po: Always filter .po files.
+    The po plugin in previous ikiwiki releases made the second and
+    subsequent filter call per (page, destpage) pair into a no-op,
+    apparently in an attempt to prevent *recursive* filtering (which as
+    far as we can tell can't happen anyway), with the undesired effect
+    of interpreting the raw .po file as page content (e.g. Markdown)
+    if it was inlined into the same page twice, which is apparently
+    something that tails.org does. Simplify this by deleting the code
+    that prevented repeated filtering. Thanks, intrigeri
+    (Closes: #911356)
+
+ -- Simon McVittie <smcv@debian.org>  Sun, 24 Feb 2019 17:11:39 +0000
+
 ikiwiki (3.20190207) upstream; urgency=medium
 
   [ Amitai Schleier ]
diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm
index 418e8e58a..13b98b739 100644
--- a/IkiWiki/Plugin/po.pm
+++ b/IkiWiki/Plugin/po.pm
@@ -51,7 +51,6 @@ sub import {
 	hook(type => "checkcontent", id => "po", call => \&checkcontent);
 	hook(type => "canremove", id => "po", call => \&canremove);
 	hook(type => "canrename", id => "po", call => \&canrename);
-	hook(type => "editcontent", id => "po", call => \&editcontent);
 	hook(type => "formbuilder_setup", id => "po", call => \&formbuilder_setup, last => 1);
 	hook(type => "formbuilder", id => "po", call => \&formbuilder);
 
@@ -303,9 +302,8 @@ sub filter (@) {
 	my $page = $params{page};
 	my $destpage = $params{destpage};
 	my $content = $params{content};
-	if (istranslation($page) && ! alreadyfiltered($page, $destpage)) {
+	if (istranslation($page)) {
 		$content = po_to_markup($page, $content);
-		setalreadyfiltered($page, $destpage);
 	}
 	return $content;
 }
@@ -520,15 +518,6 @@ sub canrename (@) {
 	return undef;
 }
 
-# As we're previewing or saving a page, the content may have
-# changed, so tell the next filter() invocation it must not be lazy.
-sub editcontent () {
-	my %params=@_;
-
-	unsetalreadyfiltered($params{page}, $params{page});
-	return $params{content};
-}
-
 sub formbuilder_setup (@) {
 	my %params=@_;
 	my $form=$params{form};
@@ -737,42 +726,6 @@ sub myisselflink ($$) {
 }
 
 # ,----
-# | Blackboxes for private data
-# `----
-
-{
-	my %filtered;
-
-	sub alreadyfiltered($$) {
-		my $page=shift;
-		my $destpage=shift;
-
-		return exists $filtered{$page}{$destpage}
-			 && $filtered{$page}{$destpage} eq 1;
-	}
-
-	sub setalreadyfiltered($$) {
-		my $page=shift;
-		my $destpage=shift;
-
-		$filtered{$page}{$destpage}=1;
-	}
-
-	sub unsetalreadyfiltered($$) {
-		my $page=shift;
-		my $destpage=shift;
-
-		if (exists $filtered{$page}{$destpage}) {
-			delete $filtered{$page}{$destpage};
-		}
-	}
-
-	sub resetalreadyfiltered() {
-		undef %filtered;
-	}
-}
-
-# ,----
 # | Helper functions
 # `----
 
@@ -1146,7 +1099,6 @@ sub commit_and_refresh ($) {
 		IkiWiki::rcs_update();
 	}
 	# Reinitialize module's private variables.
-	resetalreadyfiltered();
 	resettranslationscache();
 	flushmemoizecache();
 	# Trigger a wiki refresh.
diff --git a/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn b/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
index a926135b0..26d3717b9 100644
--- a/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
+++ b/doc/bugs/po:_second_or_subsequent_inline_of_translated_page_inlines_.po_file__44___not_translated_content.mdwn
@@ -177,3 +177,6 @@ be resolved by renaming.
 
 If it's valid to remove the `alreadyfiltered` mechanism, my
 `wip/po-filter-every-time` branch does that. Please test?
+
+> intrigeri says [this change works as intended on tails.org](https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=911356#41),
+> so I've applied it. [[done]] --[[smcv]]
diff --git a/t/po.t b/t/po.t
index 82f9e2078..ccb508bef 100755
--- a/t/po.t
+++ b/t/po.t
@@ -447,25 +447,10 @@ like($output{'debian911356.fr'}, qr{
 	\s*
 	<p>Entre\sles\sinlines</p>
 	\s*
-	.*	# TODO: This paragraph gets mangled (Debian #911356)
-	\s*
-	<p>Après\sles\sinlines</p>
-}sx);
-
-TODO: {
-local $TODO = "Debian bug #911356";
-like($output{'debian911356.fr'}, qr{
-	<p>Avant\sla\spremière\sinline</p>
-	\s*
-	<p>Contenu\sfrançais</p>
-	\s*
-	<p>Entre\sles\sinlines</p>
-	\s*
 	<p>Contenu\sfrançais</p>
 	\s*
 	<p>Après\sles\sinlines</p>
 }sx);
-};
 
 # Variation of Debian #911356 without using raw inlines.
 like($output{debian911356ish}, qr{
@@ -511,28 +496,6 @@ like($output{'debian911356ish.fr'}, qr{
 	\s*
 	<p>Entre\sles\sinlines</p>
 	\s*
-	.*	# TODO: This paragraph gets mangled (Debian #911356)
-	\s*
-	<p>Après\sles\sinlines</p>
-}sx);
-
-TODO: {
-local $TODO = "Debian bug #911356";
-like($output{'debian911356ish.fr'}, qr{
-	<p>Avant\sla\spremière\sinline</p>
-	\s*
-	<!--feedlinks-->
-	\s*
-	<div\sclass="inlinecontent">
-	\s*
-	<h6>debian911356-inlined\.fr</h6>
-	\s*
-	<p>Contenu\sfrançais</p>
-	\s*
-	</div><!--inlinecontent-->
-	\s*
-	<p>Entre\sles\sinlines</p>
-	\s*
 	<!--feedlinks-->
 	\s*
 	<div\sclass="inlinecontent">
@@ -545,6 +508,5 @@ like($output{'debian911356ish.fr'}, qr{
 	\s*
 	<p>Après\sles\sinlines</p>
 }sx);
-};
 
 done_testing;

ikiwiki.info doesn't have fenced code blocks yet
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index e0dec5cfa..3763cd9b0 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -108,14 +108,12 @@ Looking back at the history of the `po` plugin, it seems that the
 `alreadyfiltered` mechanism was introduced (under a different name,
 with less abstraction) by [[intrigeri]] in commit 1e874b3f:
 
-```
-po plugin[filter]: avoid converting more than once per destfile
+    po plugin[filter]: avoid converting more than once per destfile
 
-Only the first filter function call on a given {page,destpage} must convert it
-from the PO file, subsequent calls must leave the passed $content unmodified.
+    Only the first filter function call on a given {page,destpage} must convert it
+    from the PO file, subsequent calls must leave the passed $content unmodified.
 
-Else, preprocessing loops are the rule.
-```
+    Else, preprocessing loops are the rule.
 
 I don't understand this. Under what circumstances would we pass content
 through the filter hooks, and then pass it back through the same filter

Escape directives in code
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index 0483f2c10..e0dec5cfa 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -5,13 +5,13 @@ copyright headers!) being inserted into the page instead.
 
 For example, given a "index.mdwn" containing:
 
-    [[!inline pages="inline" raw="yes"]]
-    [[!inline pages="inline" raw="yes"]]
+    \[[!inline pages="inline" raw="yes"]]
+    \[[!inline pages="inline" raw="yes"]]
 
 … and an "index.de.po" of:
 
-    msgid "[[!inline pages=\"inline\" raw=\"yes\"]]\n"
-    msgstr "[[!inline pages=\"inline.de\" raw=\"yes\"]]\n"
+    msgid "\[[!inline pages=\"inline\" raw=\"yes\"]]\n"
+    msgstr "\[[!inline pages=\"inline.de\" raw=\"yes\"]]\n"
 
 … together with an "inline.mdwn" of:
 

Review
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index 749551ccc..0483f2c10 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -1,99 +1,53 @@
-    From: Chris Lamb <lamby@debian.org>
-    Date: Thu, 28 Jun 2018 19:30:15 +0100
-    Subject: [PATCH] Re-use translated content instead of skipping if previously
-     translated.
-    
-    This fixes an issue where an initial `inline` directive would be translated
-    correctly, but subsequent inlines of the same would result in the raw
-    contents of the `.po` file being inserted into the page instead.
-    
-    For example, given a `index.mdwn` containing:
-    
-        \[[!inline pages="inline" raw="yes"]]
-        \[[!inline pages="inline" raw="yes"]]
-    
-    .. and an `index.de.po` of:
-    
-        msgid "\[[!inline pages=\"inline\" raw=\"yes\"]]\n"
-        msgstr "\[[!inline pages=\"inline.de\" raw=\"yes\"]]\n"
-    
-    .. together with an `inline.mdwn` of:
-    
-       This is inlined content.
-    
-    .. and an `inline.de.po` of:
-    
-        msgid "This is inlined content."
-        msgstr "This is German inlined content."
-    
-    .. would result in the following translation:
-    
-        This is the inlined content.
-        # SOME DESCRIPTIVE TITLE
-        # Copyright (C) YEAR Free Software Foundation, Inc.
-        # This file is distributed under the same license as the PACKAGE package.
-        # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
-    
-    .. instead of, of course:
-    
-        This is the inlined content.
-        This is the inlined content.
-    ---
-     IkiWiki/Plugin/po.pm | 15 +++++++++------
-     1 file changed, 9 insertions(+), 6 deletions(-)
-    
-    diff --git a/IkiWiki/Plugin/po.pm b/IkiWiki/Plugin/po.pm
-    index 418e8e58a..ecd1f5499 100644
-    --- a/IkiWiki/Plugin/po.pm
-    +++ b/IkiWiki/Plugin/po.pm
-    @@ -303,9 +303,12 @@ sub filter (@) {
-     	my $page = $params{page};
-     	my $destpage = $params{destpage};
-     	my $content = $params{content};
-    -	if (istranslation($page) && ! alreadyfiltered($page, $destpage)) {
-    -		$content = po_to_markup($page, $content);
-    -		setalreadyfiltered($page, $destpage);
-    +	if (istranslation($page)) {
-    +		if (!defined(alreadyfiltered($page, $destpage))) {
-    +			$content = po_to_markup($page, $content);
-    +			setalreadyfiltered($page, $destpage, $content);
-    +		}
-    +		$content = alreadyfiltered($page, $destpage);
-     	}
-     	return $content;
-     }
-    @@ -747,15 +750,15 @@ sub myisselflink ($$) {
-     		my $page=shift;
-     		my $destpage=shift;
-     
-    -		return exists $filtered{$page}{$destpage}
-    -			 && $filtered{$page}{$destpage} eq 1;
-    +		return $filtered{$page}{$destpage};
-     	}
-     
-     	sub setalreadyfiltered($$) {
-     		my $page=shift;
-     		my $destpage=shift;
-    +		my $content=shift;
-     
-    -		$filtered{$page}{$destpage}=1;
-    +		$filtered{$page}{$destpage}=$content;
-     	}
-     
-     	sub unsetalreadyfiltered($$) {
-    -- 
-    2.18.0
-    
+There is an issue where an initial "inline" directive would be
+translated correctly but subsequent inlines of the same page would
+result in the raw contents of the ".po" file (ie. starting with the raw
+copyright headers!) being inserted into the page instead.
+
+For example, given a "index.mdwn" containing:
+
+    [[!inline pages="inline" raw="yes"]]
+    [[!inline pages="inline" raw="yes"]]
+
+… and an "index.de.po" of:
+
+    msgid "[[!inline pages=\"inline\" raw=\"yes\"]]\n"
+    msgstr "[[!inline pages=\"inline.de\" raw=\"yes\"]]\n"
+
+… together with an "inline.mdwn" of:
+
+   This is inlined content.
+
+… and an "inline.de.po" of:
+
+    msgid "This is inlined content."
+    msgstr "This is German inlined content."
+
+§
+
+This would result in the following translation:
+
+    This is the inlined content.
+    # SOME DESCRIPTIVE TITLE
+    # Copyright (C) YEAR Free Software Foundation, Inc.
+    # This file is distributed under the same license as the PACKAGE package.
+    # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+
+… instead of (of course)
+
+    This is the inlined content.
+    This is the inlined content.
+
+[[Initially proposed patch from Chris Lamb|20180628-patch.txt]]
+
 [[!tag patch]]
 
 > Thank you Chris! I've reviewed the patch (with my "original author of the po plugin" hat on) and it looks good to me. I'm not 100% sure about `alreadyfiltered` being the best name for something that's not a predicated anymore but it's good enough. Then I wore my end-user hat and confirmed that with Chris' patch applied, the reproducer we had for this bug at Tails works fine. So IMO we're good to go and I recommend to apply this patch. Thanks in advance! -- [[intrigeri]]
 
-
 > Any update on getting this merged? — [[lamby]], Fri, 24 Aug 2018 12:36:37 +0200
 
 > Indeed, would love to see this merged! What might be the next steps here? — [[lamby]],  Thu, 18 Oct 2018 17:57:37 -0400
 
-> I've filed this in Debian GNU/Linux at https://bugs.debian.org/911356 — [[lamby]], Thu, 18 Oct 2018 20:18:58 -0400
+> I've filed this in Debian GNU/Linux at <https://bugs.debian.org/911356> — [[lamby]], Thu, 18 Oct 2018 20:18:58 -0400
 
 >> As I said on the Debian bug, I think we badly need test coverage for
 >> this sort of thing, otherwise it *will* regress. The po plugin is
@@ -103,5 +57,118 @@
 >> bugs) without anyone realising.
 >>
 >> For now I've added a failing test-case for this particular bug.
->> I'll try to review this soon and understand the po plugin, the patch,
->> why the bug exists and why the patch fixes it. --[[smcv]]
+>> --[[smcv]]
+
+---
+
+Review from [[smcv]]:
+
+The patch attached to the Debian bug and the patch pasted here (which
+I've moved to an attachment) appear to be different, but I'm not going to
+do a line-by-line review of the patches and their differences for now
+because I'm not sure their approach is fully correct.
+
+As we know, the two hardest things in computer science are naming, cache
+invalidation and off-by-one errors. Unfortunately this patch has issues
+with naming and cache invalidation. It's effectively turning the
+`alreadyfiltered` mechanism into a cache of memoized results of calling
+`po_to_markup()` on pages' content, keyed by the page name and the
+`destpage`, which is either the page name again or the name of a page
+into which the `page` is to be inlined (even though the result of
+`po_to_markup()` doesn't actually vary with the `destpage`).
+
+This naturally raises the usual concerns about having a cache:
+
+* How large does it grow?
+* Do we invalidate it every time we need to?
+* Do we even need it?
+
+The cache size is mainly a concern for large wikis being rebuilt. If you
+have a wiki with 1000 translated pages in 3 languages each, each of which
+is inlined into an average of one other page, then by the time you finish
+a rebuild you'll be holding 6000 translated pages in memory. If we change
+the `alreadyfiltered` mechanism to be keyed by the page name and not the
+(page, destpage) pair, that drops to 3000, but that's still
+O(pages \* languages) which seems like a lot. As a general design
+principle, ikiwiki tries not to hold full content in RAM for more than
+the currently-processed page.
+
+We invalidate the `alreadyfiltered` for a (page, page) pair in an
+editcontent hook, and we never invalidate (page, destpage) pairs for
+page != destpage at all. Are we sure there is no other circumstance in
+which the content of a page can change?
+
+One of the things I tried doing for a simple solution was to remove the
+cache altogether, because I wasn't sure why we had this `alreadyfiltered`
+mechanism in the first place. This passes tests, which suggests that
+either the `alreadyfiltered` mechanism is unnecessary, or our regression
+test coverage for `po` is insufficient.
+
+Looking back at the history of the `po` plugin, it seems that the

(Diff truncated)
Fix broken link in basewiki
Links from pages in the basewiki (which is also a subset of ikiwiki's
own wiki) to pages on ikiwiki's own wiki have to use [[!iki]] so that
they will not become broken links when the page in question is copied
into other installations.
Detected by ./t/basewiki_brokenlinks.t.
diff --git a/doc/ikiwiki/directive/meta.mdwn b/doc/ikiwiki/directive/meta.mdwn
index 89a32946a..777712f32 100644
--- a/doc/ikiwiki/directive/meta.mdwn
+++ b/doc/ikiwiki/directive/meta.mdwn
@@ -77,7 +77,8 @@ a quote in the text by writing `&quot;` and so on.
 
   Specifies the creation date of the page. This creates a 
   `<meta name="date" content="...">` header in the HTML output, but also
-  modifies the internal `ctime` in the [[internal index|tips/inside_dot_ikiwiki/]].
+  modifies the internal `ctime` in the
+  [[!iki tips/inside_dot_ikiwiki desc="internal index"]].
   The date can be entered in nearly any format, since it's parsed by
   [[!cpan TimeDate]] but invalid dates yield an error in 3.20180321
   or later.

po: Add failing test for Debian bug #911356
diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index 57386ad75..749551ccc 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -95,5 +95,13 @@
 
 > I've filed this in Debian GNU/Linux at https://bugs.debian.org/911356 — [[lamby]], Thu, 18 Oct 2018 20:18:58 -0400
 
-
-
+>> As I said on the Debian bug, I think we badly need test coverage for
+>> this sort of thing, otherwise it *will* regress. The po plugin is
+>> relatively complicated and hooks into lots of places in ikiwiki,
+>> and I don't think any of the active ikiwiki maintainers use it
+>> themselves, which means it can easily break (or have pre-existing
+>> bugs) without anyone realising.
+>>
+>> For now I've added a failing test-case for this particular bug.
+>> I'll try to review this soon and understand the po plugin, the patch,
+>> why the bug exists and why the patch fixes it. --[[smcv]]
diff --git a/t/po.t b/t/po.t
index 0db56edc9..3e9b9b7fd 100755
--- a/t/po.t
+++ b/t/po.t
@@ -3,6 +3,7 @@
 use warnings;
 use strict;
 use File::Temp qw{tempdir};
+use utf8;
 
 BEGIN {
 	unless (eval { require Locale::Po4a::Chooser }) {
@@ -17,7 +18,7 @@ BEGIN {
 	}
 }
 
-use Test::More tests => 114;
+use Test::More;
 
 BEGIN { use_ok("IkiWiki"); }
 
@@ -44,7 +45,7 @@ $config{po_slave_languages} = {
 			       es => 'Castellano',
 			       fr => "Français"
 			      };
-$config{po_translatable_pages}='index or test1 or test2 or translatable';
+$config{po_translatable_pages}='index or test1 or test2 or translatable or debian*';
 $config{po_link_to}='negotiated';
 IkiWiki::loadplugins();
 ok(IkiWiki::loadplugin('meta'), "meta plugin loaded");
@@ -67,8 +68,15 @@ $pagesources{'translatable'}='translatable.mdwn';
 $pagesources{'translatable.fr'}='translatable.fr.po';
 $pagesources{'translatable.es'}='translatable.es.po';
 $pagesources{'nontranslatable'}='nontranslatable.mdwn';
+$pagesources{'debian911356'}='debian911356.mdwn';
+$pagesources{'debian911356.fr'}='debian911356.fr.po';
+$pagesources{'debian911356-inlined'}='debian911356-inlined.mdwn';
+$pagesources{'debian911356-inlined.fr'}='debian911356-inlined.fr.po';
+my $now=time;
 foreach my $page (keys %pagesources) {
 	$IkiWiki::pagecase{lc $page}=$page;
+	$IkiWiki::pagectime{$page}=$now;
+	$IkiWiki::pagemtime{$page}=$now;
 }
 
 ### populate srcdir
@@ -80,6 +88,42 @@ writefile('test2.mdwn', $config{srcdir}, 'test2 content');
 writefile('test3.mdwn', $config{srcdir}, 'test3 content');
 writefile('translatable.mdwn', $config{srcdir}, '[[nontranslatable]]');
 writefile('nontranslatable.mdwn', $config{srcdir}, '[[/]] [[translatable]]');
+writefile('debian911356.mdwn', $config{srcdir}, <<EOF);
+Before first inline
+
+[[!inline pages="debian911356-inlined" raw="yes"]]
+
+Between inlines
+
+[[!inline pages="debian911356-inlined" raw="yes"]]
+
+After inlines
+EOF
+writefile('debian911356-inlined.mdwn', $config{srcdir}, <<EOF);
+English content
+EOF
+writefile('debian911356.fr.po', $config{srcdir}, <<EOF);
+msgid "" msgstr ""
+"MIME-Version: 1.0\\n"
+"Content-Type: text/plain; charset=UTF-8\\n"
+"Content-Transfer-Encoding: 8bit\\n"
+
+msgid "Before first inline"
+msgstr "Avant la première inline"
+
+msgid "[[!inline pages=\\"debian911356-inlined\\" raw=\\"yes\\"]]\\n"
+msgstr "[[!inline pages=\\"debian911356-inlined.fr\\" raw=\\"yes\\"]]\\n"
+
+msgid "Between inlines"
+msgstr "Entre les inlines"
+
+msgid "After inlines"
+msgstr "Après les inlines"
+EOF
+writefile('debian911356-inlined.fr.po', $config{srcdir}, <<EOF);
+msgid "English content"
+msgstr "Contenu français"
+EOF
 
 ### istranslatable/istranslation
 # we run these tests twice because memoization attempts made them
@@ -248,3 +292,68 @@ ok(IkiWiki::Plugin::po::islanguagecode('es'));
 ok(IkiWiki::Plugin::po::islanguagecode('arn'));
 ok(! IkiWiki::Plugin::po::islanguagecode('es_'));
 ok(! IkiWiki::Plugin::po::islanguagecode('_en'));
+
+# Actually render translated pages
+use IkiWiki::Render;
+
+my %output;
+foreach my $page (keys %pagesources) {
+	my $source = "$config{srcdir}/$pagesources{$page}";
+	if (-e $source) {
+		IkiWiki::scan($pagesources{$page});
+		my $content = readfile($source);
+		print STDERR "-------------------------------------\n";
+		#print STDERR "SOURCE: $page: $content\n";
+		$content = IkiWiki::filter($page, $page, $content);
+		#print STDERR "FILTERED: $page: $content\n";
+		$content = IkiWiki::preprocess($page, $page, $content);
+		#print STDERR "PREPROCESSED: $page: $content\n";
+		$content = IkiWiki::linkify($page, $page, $content);
+		#print STDERR "LINKIFIED: $page: $content\n";
+		$content = IkiWiki::htmlize($page, $page, IkiWiki::pagetype($pagesources{$page}), $content);
+		print STDERR "HTMLIZED: $page: $content\n";
+		$output{$page} = $content;
+		ok(utf8::is_utf8($content), "htmlized content should be utf8");
+	}
+}
+
+like($output{debian911356}, qr{
+	<p>Before\sfirst\sinline</p>
+	\s*
+	<p>English\scontent</p>
+	\s*
+	<p>Between\sinlines</p>
+	\s*
+	<p>English\scontent</p>
+	\s*
+	<p>After\sinlines</p>
+}sx);
+
+like($output{'debian911356.fr'}, qr{
+	<p>Avant\sla\spremière\sinline</p>
+	\s*
+	<p>Contenu\sfrançais</p>
+	\s*
+	<p>Entre\sles\sinlines</p>
+	\s*
+	.*	# TODO: This paragraph gets mangled (Debian #911356)
+	\s*
+	<p>Après\sles\sinlines</p>
+}sx);
+
+TODO: {
+local $TODO = "Debian bug #911356";
+like($output{'debian911356.fr'}, qr{
+	<p>Avant\sla\spremière\sinline</p>
+	\s*
+	<p>Contenu\sfrançais</p>
+	\s*
+	<p>Entre\sles\sinlines</p>
+	\s*
+	<p>Contenu\sfrançais</p>
+	\s*
+	<p>Après\sles\sinlines</p>
+}sx);
+};
+
+done_testing;

I don't think the Chinese text causes this
diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index 4b5ae384d..bb021efb4 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -21,3 +21,14 @@ I have found that it is not "%2F"'s problem, it just that inline directive can
 not deal with Chinese char, the below link can work
 
     http://172.16.0.109/ikiwiki.cgi?do=blog&from=aaa%2Fbugs&subpage=1&title=aaa
+
+---
+
+> I don't think this is actually caused by the Chinese text. The problem is that
+> you used `rootpage="./bugs"`, which leads to the `blog` request handler
+> generating an invalid page name. If you change it to `rootpage="bugs"` does
+> that fix the error?
+>
+> Ideally either the `inline` directive or the `blog` request handler would
+> understand and remove `./`, if it's something that makes sense in this context.
+> --[[smcv]]

comments (no review yet)
diff --git a/doc/plugins/osm/discussion.mdwn b/doc/plugins/osm/discussion.mdwn
index 957ff3f9a..ff3cb8d36 100644
--- a/doc/plugins/osm/discussion.mdwn
+++ b/doc/plugins/osm/discussion.mdwn
@@ -71,6 +71,31 @@ rather not have to carry around a local copy of his work to get a map
 with waypoints on my HTTPS site. [[smcv]], can you spare some round
 tuits to give us your thoughts? --[[schmonz]]
 
+> I've never used the osm plugin, so I don't know how well it works at the moment.
+> I think the lack of test coverage has been a significant factor in it not actually
+> working. Even if we don't have test-driven development, the next best thing is
+> bug-driven testing: every time something regresses, we should have a test that
+> asserts it doesn't fail like that again.
+>
+> If the current osm plugin is at all usable, then we'd need to look at the specific
+> ways in which the new one is incompatible, but if the current osm plugin doesn't
+> actually work anyway, then the new one can't break working sites...
+>
+> Determining whether there's HTML injection is certainly an important thing to
+> review. We need to be able to say what's trusted, what's attacker-controlled, and
+> what was originally attacker-controlled but has been sanitized or escaped and
+> hence has reached a trusted state.
+>
+> As an upstream developer, I would say that my preferred approach to Leaflet would
+> be to vendor it and use the vendored copy by default, but have a configuration
+> parameter to load it from a CDN instead. In the Debian package, to avoid the
+> situation we've got into with jQuery where we have a vendored copy that we
+> don't dare to update to a new version because we don't know what it will break,
+> I think there should be a dependency on libjs-leaflet and a dpkg trigger to
+> copy its files into our underlay (ideally we'd symlink it, but ikiwiki doesn't
+> follow symlinks, and I don't think an approach to symlinks in underlays that
+> isn't a security flaw is going to happen any time soon). --[[smcv]]
+
 ----
 
 Just stumbled onto this. 

Revert spam
This reverts commit c600ed0e710d82601acf5ae4005b940f5cba8c08
diff --git a/doc/forum/How_to_install_Text:Multimarkdown__63__/comment_2_5192a5348ee10fc35349cac1b1e6f61f._comment b/doc/forum/How_to_install_Text:Multimarkdown__63__/comment_2_5192a5348ee10fc35349cac1b1e6f61f._comment
deleted file mode 100644
index c0fee9c30..000000000
--- a/doc/forum/How_to_install_Text:Multimarkdown__63__/comment_2_5192a5348ee10fc35349cac1b1e6f61f._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=html
- username="luciferwhite"
- avatar="http://cdn.libravatar.org/avatar/f29fd1395f5b340e1d257a0923467c53"
- subject="Re: How to understand the process of installation"
- date="2018-07-27T17:13:04Z"
- content="""
-You have to great to know the proper way of installing the part which will be more productive for the developer to find out the exact part which is going to take the best way to somehow need the perfect guide <a href=\"https://supportprop58.com/windows-10-audio-crackling/\">windows 10 sound crackling</a> that will show you the perfect process to install the multilayer .
-"""]]

diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
index 9a8fed22f..4b5ae384d 100644
--- a/doc/bugs/About___37__2F_problem.mdwn
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -14,3 +14,10 @@ Its url include a %2F, like below:
 > http://172.16.0.109/ikiwiki.cgi?do=blog&from=.%2Fbugs&subpage=1&title=aaa
 
 I use ikiwiki 3.20180311
+
+----
+
+I have found that it is not "%2F"'s problem, it just that inline directive can
+not deal with Chinese char, the below link can work
+
+    http://172.16.0.109/ikiwiki.cgi?do=blog&from=aaa%2Fbugs&subpage=1&title=aaa

diff --git a/doc/bugs/About___37__2F_problem.mdwn b/doc/bugs/About___37__2F_problem.mdwn
new file mode 100644
index 000000000..9a8fed22f
--- /dev/null
+++ b/doc/bugs/About___37__2F_problem.mdwn
@@ -0,0 +1,16 @@
+I use inline to create a blog like the below:
+
+    \[[!inline pages="./bugs/* and !./bugs/done and !./bugs/discussion and 
+    !link(patch) and !link(./bugs/done) and !./bugs/*/*"
+    actions=yes rootpage="./bugs" postform="yes" postformtext="请用一句话简述问题,然后点击 Edit 按钮添加具体细节" show=0]]
+
+
+When I use posform to add a new page, it show:
+
+> Error: bad page name 
+
+Its url include a %2F, like below:
+
+> http://172.16.0.109/ikiwiki.cgi?do=blog&from=.%2Fbugs&subpage=1&title=aaa
+
+I use ikiwiki 3.20180311

diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index 89f406d5d..fe71686e6 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -32,3 +32,5 @@ The below example works well too
 > That file is owned by the `libperl5` package, but I think I've seen an error mentioning `Text::CSV` i.e. `libtext-csv-perl` when I've encountered this before. -- [[Jon]]
 
 >> A related problem, also fixed by using DSV, is messing up the encoding of non-ASCII, non-wide characters, e.g. £ (workaround was to use &amp;pound; instead) -- [[Jon]]
+
+>>> Sorry, I have faced the same error: \[[!table Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.24/Encode.pm line 243.]] -- [[tumashu1]]

related issue
diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index d0031fecf..89f406d5d 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -30,3 +30,5 @@ The below example works well too
     [\[!table Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.24/Encode.pm line 243.]]
 
 > That file is owned by the `libperl5` package, but I think I've seen an error mentioning `Text::CSV` i.e. `libtext-csv-perl` when I've encountered this before. -- [[Jon]]
+
+>> A related problem, also fixed by using DSV, is messing up the encoding of non-ASCII, non-wide characters, e.g. £ (workaround was to use &amp;pound; instead) -- [[Jon]]

error output when trying
diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index 69d184702..d0031fecf 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -22,3 +22,11 @@ The below example works well too
     1,2,你好
     """
     ]]
+
+----
+
+> You don't say what actually happens when you try this, but I hit something similar trying unicode symbols in a CSV-based table. (I wasn't aware of the DSV work-around. Thanks!) The specific error  I get trying is
+
+    [\[!table Error: Cannot decode string with wide characters at /usr/lib/x86_64-linux-gnu/perl/5.24/Encode.pm line 243.]]
+
+> That file is owned by the `libperl5` package, but I think I've seen an error mentioning `Text::CSV` i.e. `libtext-csv-perl` when I've encountered this before. -- [[Jon]]

rename postvote to postlink
This better explains what it contains, which is a wikilink to the page
to go to after posting the vote. And postlink is more consistent a name
with posttrail.
diff --git a/CHANGELOG b/CHANGELOG
index 892dca041..cb7a7a038 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,7 +10,7 @@ ikiwiki (3.20180312) UNRELEASED; urgency=medium
   [ Joey Hess ]
   * aggregate: Fix aggregation of posts without a title.
     Thanks, Alexandre Oliva
-  * poll: Added postvote and posttrail options for better multi-page polls.
+  * poll: Added postlink and posttrail options for better multi-page polls.
 
  -- Simon McVittie <smcv@debian.org>  Wed, 16 May 2018 13:09:27 +0100
 
diff --git a/IkiWiki/Plugin/poll.pm b/IkiWiki/Plugin/poll.pm
index 734fe487e..5a09e2087 100644
--- a/IkiWiki/Plugin/poll.pm
+++ b/IkiWiki/Plugin/poll.pm
@@ -69,8 +69,8 @@ sub preprocess (@) {
 			$ret.="<input type=\"hidden\" name=\"num\" value=\"$num\" />\n";
 			$ret.="<input type=\"hidden\" name=\"page\" value=\"$params{page}\" />\n";
 			$ret.="<input type=\"hidden\" name=\"choice\" value=\"$choice\" />\n";
-			if (defined $params{postvote}) {
-				$ret.="<input type=\"hidden\" name=\"postvote\" value=\"".linkpage($params{postvote})."\" />\n";
+			if (defined $params{postlink}) {
+				$ret.="<input type=\"hidden\" name=\"postlink\" value=\"".linkpage($params{postlink})."\" />\n";
 			}
 			if (defined $params{posttrail}) {
 				$ret.="<input type=\"hidden\" name=\"posttrail\" value=\"".linkpage($params{posttrail})."\" />\n";
@@ -119,8 +119,8 @@ sub sessioncgi ($$) {
 		}
 
 		my $postvote=urlto($page);
-		if (defined $cgi->param('postvote') && length $cgi->param('postvote')) {
-			$postvote=urlto(bestlink($page, $cgi->param('postvote')));
+		if (defined $cgi->param('postlink') && length $cgi->param('postlink')) {
+			$postvote=urlto(bestlink($page, $cgi->param('postlink')));
 		}
 		elsif (defined $cgi->param('posttrail') && length $cgi->param('posttrail')) {
 			my $trailname=bestlink($page, $cgi->param('posttrail'));
diff --git a/doc/ikiwiki/directive/poll.mdwn b/doc/ikiwiki/directive/poll.mdwn
index 7b9fdfdc5..caaeaeaf0 100644
--- a/doc/ikiwiki/directive/poll.mdwn
+++ b/doc/ikiwiki/directive/poll.mdwn
@@ -23,7 +23,7 @@ Parameters:
   another choice to the poll.
 * `total` - Show total number of votes at bottom of poll. Default is "yes".
 * `percent` - Whether to display percents. Default is "yes".
-* `postvote` - By default after voting the updated page containing the poll
+* `postlink` - By default after voting the updated page containing the poll
   is displayed. This parameter allows advancing onward to another page.
   This is useful for multi-page polls.
 * `posttrail` - Similar to postvote, but allows advancing to the next page

poll: Added postvote and posttrail options for better multi-page polls.
Modern web users probably expect the poll to move on automatically to the
next question, and this allows for that behavior.
Note that bestlink() runs at vote time, which avoids needing to make the
page containing the poll depend on the page that sets up a trail, as the
current trail at vote time will be used.
This commit was sponsored by Eric Drechsel on Patreon.
diff --git a/CHANGELOG b/CHANGELOG
index b00dc8218..892dca041 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -10,6 +10,7 @@ ikiwiki (3.20180312) UNRELEASED; urgency=medium
   [ Joey Hess ]
   * aggregate: Fix aggregation of posts without a title.
     Thanks, Alexandre Oliva
+  * poll: Added postvote and posttrail options for better multi-page polls.
 
  -- Simon McVittie <smcv@debian.org>  Wed, 16 May 2018 13:09:27 +0100
 
diff --git a/IkiWiki/Plugin/poll.pm b/IkiWiki/Plugin/poll.pm
index eb0e6ef04..734fe487e 100644
--- a/IkiWiki/Plugin/poll.pm
+++ b/IkiWiki/Plugin/poll.pm
@@ -69,6 +69,12 @@ sub preprocess (@) {
 			$ret.="<input type=\"hidden\" name=\"num\" value=\"$num\" />\n";
 			$ret.="<input type=\"hidden\" name=\"page\" value=\"$params{page}\" />\n";
 			$ret.="<input type=\"hidden\" name=\"choice\" value=\"$choice\" />\n";
+			if (defined $params{postvote}) {
+				$ret.="<input type=\"hidden\" name=\"postvote\" value=\"".linkpage($params{postvote})."\" />\n";
+			}
+			if (defined $params{posttrail}) {
+				$ret.="<input type=\"hidden\" name=\"posttrail\" value=\"".linkpage($params{posttrail})."\" />\n";
+			}
 			$ret.="<input type=\"submit\" value=\"".gettext("vote")."\" />\n";
 		}
 		$ret.="</p>\n<hr class=poll align=left width=\"$percent%\"/>\n";
@@ -112,13 +118,25 @@ sub sessioncgi ($$) {
 			error("bad page name");
 		}
 
+		my $postvote=urlto($page);
+		if (defined $cgi->param('postvote') && length $cgi->param('postvote')) {
+			$postvote=urlto(bestlink($page, $cgi->param('postvote')));
+		}
+		elsif (defined $cgi->param('posttrail') && length $cgi->param('posttrail')) {
+			my $trailname=bestlink($page, $cgi->param('posttrail'));
+			my $trailnext=$pagestate{$page}{trail}{item}{$trailname}[1];
+			if (defined $trailnext) {
+				$postvote=urlto($trailnext);
+			}
+		}
+
 		# Did they vote before? If so, let them change their vote,
 		# and check for dups.
 		my $choice_param="poll_choice_${page}_$num";
 		my $oldchoice=$session->param($choice_param);
 		if (defined $oldchoice && $oldchoice eq $choice) {
 			# Same vote; no-op.
-			IkiWiki::redirect($cgi, urlto($page));
+			IkiWiki::redirect($cgi, $postvote);
 			exit;
 		}
 
@@ -149,7 +167,7 @@ sub sessioncgi ($$) {
 		};
 		$content =~ s{(\\?)\[\[\Q$prefix\E\s+([^]]+)\s*\]\]}{$edit->($1, $2)}seg;
 
-		# Store their vote, update the page, and redirect to it.
+		# Store their vote, update the page, and redirect.
 		writefile($pagesources{$page}, $config{srcdir}, $content);
 		$session->param($choice_param, $choice);
 		IkiWiki::cgi_savesession($session);
@@ -174,8 +192,7 @@ sub sessioncgi ($$) {
 		eval q{use CGI::Cookie};
 		error($@) if $@;
 		my $cookie = CGI::Cookie->new(-name=> $session->name, -value=> $session->id);
-		print $cgi->redirect(-cookie => $cookie,
-			-url => urlto($page));
+		print $cgi->redirect(-cookie => $cookie, -url => $postvote);
 		exit;
 	}
 }
diff --git a/doc/ikiwiki/directive/poll.mdwn b/doc/ikiwiki/directive/poll.mdwn
index 0b47a2167..7b9fdfdc5 100644
--- a/doc/ikiwiki/directive/poll.mdwn
+++ b/doc/ikiwiki/directive/poll.mdwn
@@ -23,5 +23,12 @@ Parameters:
   another choice to the poll.
 * `total` - Show total number of votes at bottom of poll. Default is "yes".
 * `percent` - Whether to display percents. Default is "yes".
+* `postvote` - By default after voting the updated page containing the poll
+  is displayed. This parameter allows advancing onward to another page.
+  This is useful for multi-page polls.
+* `posttrail` - Similar to postvote, but allows advancing to the next page
+  on a trail after a vote. The value of the parameter is the name of the
+  page that defines the trail to follow. The trail plugin must be
+  enabled for this to work.
 
 [[!meta robots="noindex, follow"]]

diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index a943081cb..69d184702 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -17,7 +17,7 @@ But the below example works well.
 
 The below example works well too
 
-    [[!table format=dsv delimiter=, data="""
+    \[[!table format=dsv delimiter=, data="""
     a,b,c
     1,2,你好
     """

diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
index e3980293b..a943081cb 100644
--- a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -13,3 +13,12 @@ But the below example works well.
     1,2,3
     """
     ]]
+
+
+The below example works well too
+
+    [[!table format=dsv delimiter=, data="""
+    a,b,c
+    1,2,你好
+    """
+    ]]

diff --git a/doc/bugs/table_can_not_deal_with_Chinese_.mdwn b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
new file mode 100644
index 000000000..e3980293b
--- /dev/null
+++ b/doc/bugs/table_can_not_deal_with_Chinese_.mdwn
@@ -0,0 +1,15 @@
+Table directive can not deal with Chinese, when format csv
+
+    \[[!table format=csv data="""
+    a,b,c
+    1,2,你好
+    """
+    ]]
+
+But the below example works well.
+
+    \[[!table format=csv data="""
+    a,b,c
+    1,2,3
+    """
+    ]]

avoiding ban?
diff --git a/doc/todo/anti-spam_protection.mdwn b/doc/todo/anti-spam_protection.mdwn
index c653ab30a..cf07fe7eb 100644
--- a/doc/todo/anti-spam_protection.mdwn
+++ b/doc/todo/anti-spam_protection.mdwn
@@ -55,3 +55,36 @@ That removed 2265 comments. I reviewed the remaining 643 by hand and deleted the
 Now, I don't want to point fingers, but there sure seems to be some problems with china there and i'm tempted to just block those entire networks. :/
 
 Anyways... Someone mentioned Spamassassin in the original request, and I just [read](https://lwn.net/SubscriberLink/769917/130e156925fc690e/) that some people *are* using spamassassin for website spam control. Has anyone gave that a try? --[[anarcat]]
+
+----
+
+Another note that might be of interest here... One of the things that script was doing was to generate a list of IPs to be inserted into `ikiwiki.setup`. Unfortunately, that doesn't seem to work:
+
+    $ ~anarcat/bin/ikiwiki-comment-moderate 
+    found 165 pending comments
+    IP distribution:
+          1  ip="110.86.179.146"
+    [...]
+         10  ip="175.44.35.10"
+         11  ip="175.44.35.236"
+    banlist would look like:
+    - ip(110.86.179.146)
+    # 112.111.162.159 already present
+    # 112.111.163.216 already present
+    [...]
+    # 36.250.185.52 already present
+    # 36.250.185.55 already present
+    # 36.250.186.113 already present
+    - ip(59.60.123.211)
+    to remove comments from a specific IP, use this, for example:
+    find . -name '*._comment_pending' | xargs grep -l 'ip="$ip"'| xargs rm
+    to flush all pending comments, use:
+    find . -name '*._comment_pending' -delete
+
+In other words, many of the comments in moderation are actually
+supposed to be blocked, as their IPs are in the `banned_users`
+list. Now I know my way around a UNIX system well enough to deal with
+this another way - I'm thinking of fail2ban or a simple Apache rewrite
+table (and it might easier and faster too) - but I wonder why those
+IPs can still post comments when they are listed in
+`banned_users`... -- [[anarcat]]

update my entry
diff --git a/doc/git.mdwn b/doc/git.mdwn
index 5286f83dc..0f959a2c3 100644
--- a/doc/git.mdwn
+++ b/doc/git.mdwn
@@ -70,7 +70,7 @@ think about merging them. This is recommended. :-)
 * [[users/leg]] `git://at.magma-soft.at/ikiwiki.info`
 * [[thcipriani]] `https://github.com/thcipriani/ikiwiki.git` ([[browse|https://github.com/thcipriani/ikiwiki]])
 * [[tincho]] `git@github.com:TheTincho/ikiwiki.git` ([[browse|https://github.com/TheTincho/ikiwiki]])
-* hefee `https://salsa.debian.org/hefee/ikiwiki`
+* [[hefee]] `https://salsa.debian.org/hefee/ikiwiki.git/` ([[browse|https://salsa.debian.org/hefee/ikiwiki]])
 ## branches
 
 Current branches of ikiwiki are listed on [[branches]].

update description & remove tag patch
diff --git a/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn b/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn
index aecfa68d3..e3a57e184 100644
--- a/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn
+++ b/doc/todo/_Add_ikiwiki_PO-Plugin_to_ignore_languages.mdwn
@@ -1,7 +1,9 @@
-[[!tag patch]]
 [[!template  id=gitbranch branch=feature/15355-po-plugin-disable-languages author="[[hefee]]"]]
 
-In order to be able to prepare more translations before publishing them, it is a good a idea to have disabled languages.
-Currently there are some small issues that need to cleanup before able to push this into ikiwiki upstream.
+`po_disabled_languages` is used to disable languages on the website. It
+can be used to prepare new translations, while it will hide those from
+the end-user. More precisely, PO files for these languages are updated
+normally, however, HTML creation will be disabled and no reference to
+these translations will be visible on the website.
 
 See also downstream bug report in tails: <https://labs.riseup.net/code/issues/15355>

more spam issues. this is definitely not done.
diff --git a/doc/todo/anti-spam_protection.mdwn b/doc/todo/anti-spam_protection.mdwn
index f0c6c19b6..c653ab30a 100644
--- a/doc/todo/anti-spam_protection.mdwn
+++ b/doc/todo/anti-spam_protection.mdwn
@@ -34,3 +34,24 @@ to check for common spam signatures. --[[Joey]]
 I am sorry to say that neither those solutions are sufficient for a site that allows anonymous comments. blogspam lets thousands of commits through here, as i described in [[todo/commandline_comment_moderation]]. Now, maybe I didn't configure blogspam correctly, I am not sure. I just enabled the plugin and set `blogspam_pagespec: postcomment(blog/*) or */discussion`. I have also imported the blocklist from this wiki's ikiwiki.setup, generated from [[spam_fighting]]. I have had to add around 10 IPs to that list already.
 
 It seems to me a list of blocked URLs or blocked IPs as mentionned above would be an interesting solution. blogspam is great, but the API doesn't seem to support reporting IPs or bad content back, which seems to be a major problem in working around false negatives. I'm tempted to just remove the `done` tag above, because this is clearly not fixed for me here... --[[anarcat]]
+
+----
+
+Update, ~3 years later... Situation hasn't improved much. If anything, things are worse now as [blogspam](https://blogspam.net/) was [almost shutdown](https://blog.steve.fi/possibly_retiring_blogspam_net.html). It's still up, but it's unclear if it's doing anything. I just went through comment moderation for about 3000 comments, all of which were spam, except *one*. And the only reason I went there is because I *asked* someone to comment on a blog post instead of writing me privately so I *knew* there was something for me there. That was more than 5 months of comments backlog, and it was obviously too much to review by hand, so I removed things according to some patterns. For example, anything with phpBB-like markup is probably spam, so I cleared those up:
+
+    find .  -name '*._comment_pending' -a -print0  | xargs -0 grep -l -Z '\[url=' | xargs -0 rm
+
+That removed 2265 comments. I reviewed the remaining 643 by hand and deleted them all. I used [ikiwiki-comment-moderate](https://gitlab.com/anarcat/scripts/blob/master/ikiwiki-comment-moderate) to generate a list of IPs to block. The top 5 /16 blocks were:
+
+    18 112.5 China Mobile communications corporation
+    31 110.89 Chinanet
+    36 36.250 China Unicom
+    44 112.111 China Unicom
+    45 36.248 China Unicom
+    74 175.44 China Unicom
+
+(Left column is the number of IPs affected in the /16. Middle is the /16. Right is an assertion of the owner.) Attacks came from 104 distinct /24 blocks and 66 distinct /16.
+
+Now, I don't want to point fingers, but there sure seems to be some problems with china there and i'm tempted to just block those entire networks. :/
+
+Anyways... Someone mentioned Spamassassin in the original request, and I just [read](https://lwn.net/SubscriberLink/769917/130e156925fc690e/) that some people *are* using spamassassin for website spam control. Has anyone gave that a try? --[[anarcat]]

Give graph an optional "file" param, like table's.
diff --git a/IkiWiki/Plugin/graphviz.pm b/IkiWiki/Plugin/graphviz.pm
index d4018edaa..479da6f73 100644
--- a/IkiWiki/Plugin/graphviz.pm
+++ b/IkiWiki/Plugin/graphviz.pm
@@ -95,6 +95,14 @@ sub render_graph (\%) {
 sub graph (@) {
 	my %params=@_;
 
+	if (exists $params{file}) {
+		if (! exists $pagesources{$params{file}}) {
+			error gettext("cannot find file");
+		}
+		$params{src} = readfile(srcfile($params{file}));
+		add_depends($params{page}, $params{file});
+	}
+
 	# Support wikilinks in the graph source.
 	my $src=$params{src};
 	$src="" unless defined $src;
diff --git a/doc/ikiwiki/directive/graph.mdwn b/doc/ikiwiki/directive/graph.mdwn
index 7021e47fb..1463420d7 100644
--- a/doc/ikiwiki/directive/graph.mdwn
+++ b/doc/ikiwiki/directive/graph.mdwn
@@ -21,6 +21,7 @@ ikiwiki, [[WikiLinks|ikiwiki/wikilink]] can also be used. For example:
 The `graph` directive supports the following parameters:
 
 - `src` - The graphviz source to render.
+* `file` - A file in the wiki containing the graphviz source.
 - `type` - The type of graph to render: `graph` or `digraph`.  Defaults to
   `digraph`.
 - `prog` - The graphviz program to render with: `dot`, `neato`, `fdp`, `twopi`,

diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index a03259c03..57386ad75 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -93,4 +93,7 @@
 
 > Indeed, would love to see this merged! What might be the next steps here? — [[lamby]],  Thu, 18 Oct 2018 17:57:37 -0400
 
+> I've filed this in Debian GNU/Linux at https://bugs.debian.org/911356 — [[lamby]], Thu, 18 Oct 2018 20:18:58 -0400
+
+
 

diff --git a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
index 1260ce19f..a03259c03 100644
--- a/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
+++ b/doc/todo/Re-use_translated_content_instead_of_skipping_if_previously_translated.mdwn
@@ -91,4 +91,6 @@
 
 > Any update on getting this merged? — [[lamby]], Fri, 24 Aug 2018 12:36:37 +0200
 
+> Indeed, would love to see this merged! What might be the next steps here? — [[lamby]],  Thu, 18 Oct 2018 17:57:37 -0400
+
 

removed
diff --git a/doc/forum/An_assets_directory_for_my_wiki_with_git_lfs_or_annex__63__/comment_8_8ecc48807d369a5b5cf0ce3abcbddbc4._comment b/doc/forum/An_assets_directory_for_my_wiki_with_git_lfs_or_annex__63__/comment_8_8ecc48807d369a5b5cf0ce3abcbddbc4._comment
deleted file mode 100644
index 377d57d46..000000000
--- a/doc/forum/An_assets_directory_for_my_wiki_with_git_lfs_or_annex__63__/comment_8_8ecc48807d369a5b5cf0ce3abcbddbc4._comment
+++ /dev/null
@@ -1,8 +0,0 @@
-[[!comment format=mdwn
- username="DataComputist"
- avatar="http://cdn.libravatar.org/avatar/a17d83194742f0bd57df1e9fc6858c8f"
- subject="Could someone document the steps to achieve this?"
- date="2018-10-16T07:01:52Z"
- content="""
-I have the exact same need. My Ikiwiki instance containing hundreds of megabytes of photos have a huge Git history, and ikiwiki refresh takes a really long time (>7 mins). I really need help.
-"""]]

Added a comment: Could someone document the steps to achieve this?
diff --git a/doc/forum/An_assets_directory_for_my_wiki_with_git_lfs_or_annex__63__/comment_8_8ecc48807d369a5b5cf0ce3abcbddbc4._comment b/doc/forum/An_assets_directory_for_my_wiki_with_git_lfs_or_annex__63__/comment_8_8ecc48807d369a5b5cf0ce3abcbddbc4._comment
new file mode 100644
index 000000000..377d57d46
--- /dev/null
+++ b/doc/forum/An_assets_directory_for_my_wiki_with_git_lfs_or_annex__63__/comment_8_8ecc48807d369a5b5cf0ce3abcbddbc4._comment
@@ -0,0 +1,8 @@
+[[!comment format=mdwn
+ username="DataComputist"
+ avatar="http://cdn.libravatar.org/avatar/a17d83194742f0bd57df1e9fc6858c8f"
+ subject="Could someone document the steps to achieve this?"
+ date="2018-10-16T07:01:52Z"
+ content="""
+I have the exact same need. My Ikiwiki instance containing hundreds of megabytes of photos have a huge Git history, and ikiwiki refresh takes a really long time (>7 mins). I really need help.
+"""]]

another thing to remove from prints
diff --git a/doc/todo/hide_add_comment_button_in_print.mdwn b/doc/todo/hide_add_comment_button_in_print.mdwn
new file mode 100644
index 000000000..cbfaca888
--- /dev/null
+++ b/doc/todo/hide_add_comment_button_in_print.mdwn
@@ -0,0 +1,48 @@
+[[!template  id=gitbranch branch=anarcat/print-no-comment author="[[anarcat]]"]]
+
+Print versions are often a neglected part of a style sheet, but it's
+great when people can actually print your webpage and get a satisfying
+result.
+
+This often means removing a bunch of stuff that are irrelevant for
+print. Ikiwiki already does a bunch of those things in the
+base stylesheet:
+
+    /* things to hide in printouts */
+    @media print {
+    	.actions { display: none; }
+    	.tags { display: none; }
+    	.trails { display: none; }
+    	.feedbutton { display: none; }
+    	#searchform { display: none; }
+    	.blogform, #blogform { display: none; }
+    	#backlinks { display: none; }
+    }
+
+But I think we should remove more. In particular, the `addcomment`
+button is not relevant at all for print versions. There might be more:
+in my [bootstrap theme][], I also had to [remove][] the whole footer,
+because it was overlapping with the page content. It's unfortunate
+because it removes the copyright notice, but I don't know how else to
+fix this.
+
+Anyways, how about [this patch][]?
+
+    --- a/doc/style.css
+    +++ b/doc/style.css
+    @@ -286,6 +286,7 @@ div.progress-done {
+     	#searchform { display: none; }
+     	.blogform, #blogform { display: none; }
+     	#backlinks { display: none; }
+    +	.addcomment { display: none; }
+     }
+     
+     /* infobox template */
+
+Thanks! -- [[anarcat]]
+
+[bootstrap theme]: https://gitlab.com/anarcat/ikiwiki-bootstrap-anarcat
+[remove]: https://gitlab.com/anarcat/ikiwiki-bootstrap-anarcat/commit/94521766f4206882c44764253452ec666d90d5c1
+[this patch]: https://gitlab.com/anarcat/ikiwiki/commit/33630b561623b8dca946916b733807e9b8c97849.patch
+
+[[!tag patch]]

remove the "add comment" button from printed media
diff --git a/doc/style.css b/doc/style.css
index 8c16e7a2f..9f8289969 100644
--- a/doc/style.css
+++ b/doc/style.css
@@ -286,6 +286,7 @@ div.progress-done {
 	#searchform { display: none; }
 	.blogform, #blogform { display: none; }
 	#backlinks { display: none; }
+	.addcomment { display: none; }
 }
 
 /* infobox template */

Added a comment: More thoughts about Ikiwiki
diff --git a/doc/forum/Some_thoughts_about_Ikiwiki/comment_2_d1026de462b7491ce2ed2f72f08d463a._comment b/doc/forum/Some_thoughts_about_Ikiwiki/comment_2_d1026de462b7491ce2ed2f72f08d463a._comment
new file mode 100644
index 000000000..e411f462f
--- /dev/null
+++ b/doc/forum/Some_thoughts_about_Ikiwiki/comment_2_d1026de462b7491ce2ed2f72f08d463a._comment
@@ -0,0 +1,14 @@
+[[!comment format=mdwn
+ username="spalax"
+ avatar="http://cdn.libravatar.org/avatar/3f1353e4135221fc25bfecd1b812bcc8"
+ subject="More thoughts about Ikiwiki"
+ date="2018-10-10T14:43:32Z"
+ content="""
+I eventually switched my [website](http://ababsurdo.fr) to [lektor](http://getlektor.com). It is more modern than ikiwiki (and written in Python, so its easier for me to dig into the code). Here are more thoughts about Ikiwiki, compared to Lektor.
+
+- Ikiwiki community is great! Even these days, when there is very few activity, when people ask for help (either on this website, or on IRC), they get quick answers (as opposed to Lektor, where I had to wait up to six weeks to get an answer (not blaming lektor contributors: I know they have a life too, and owe me nothing: just congratulating Ikiwiki contributors)).
+- Ikiwiki does not hide errors! Several times, with Lektor, I scratched my head, not understanding why some stuff silently didn't work.
+- I think this has been mentionned elsewhere, but Ikiwiki hard-coded templates make it hard/impossible to change some simple things.
+
+I am a bit sad no longer using Ikiwiki. I like the project and the people behind it. Thanks a lot!
+"""]]

About the unmaintained compile plugin
diff --git a/doc/plugins/contrib/compile/discussion.mdwn b/doc/plugins/contrib/compile/discussion.mdwn
index fbf9f22ea..1cad06128 100644
--- a/doc/plugins/contrib/compile/discussion.mdwn
+++ b/doc/plugins/contrib/compile/discussion.mdwn
@@ -50,3 +50,98 @@ command...
 > Any thoughts?
 >
 > -- [[Louis|spalax]]
+
+---
+
+<span id="status">
+# This plugin is unmaintained
+</span>
+
+Unfortunately, since [[I am no longer using Ikiwiki|forum/Some_thoughts_about_Ikiwiki/]], this plugin is unmaintained. I had great ideas for a new version of this plugin (and [started some work](https://atelier.gresille.org/projects/gresille-ikiwiki/repository?utf8=%E2%9C%93&rev=compile2)), but I will not finish this work. I am dumping my TODO list for this plugin (in French) for those who might be interested.
+
+[[!toggle id="TODO" text="See the TODO list."]]
+
+[[!toggleable id="TODO" text="""
+  - [ ] Ajouter un test slideshow avec un minimum de code utilisateur
+    - http://slidesjs.com/
+    - https://stackoverflow.com/questions/12912048/how-to-maintain-aspect-ratio-using-html-img-tag
+  - [x] Faire aussi des tests qui utilisent le YAML du setup
+  - [ ] Se déparrasser des ``DEST_XXX_URL``.
+  - [ ] Se débarrasser des listes de ``config[destname]``.
+  - [x] supprimer source, nosource.
+  - [x] Voir si on supprime `make`
+  - [ ] Voir si la configuration ne peut pas se faire en YAML
+    - [x] Non
+    - [ ] Utiliser du YAML.
+  - [ ] Renommer
+    - [ ] type = rule
+    - [ ] destname = dest
+    - [ ] filenames = src
+    - [ ] ??
+  - [ ] Parser correctement la configuration (fichier de setup + arguments de la directive)
+  - [ ] Traiter src comme un pagespec? Au moins comme un glob?
+  - [ ] Variables :
+    - Génériques :
+      - pagedir: sub/page
+      - tmpdir: /home/user/wiki/.ikiwiki/3840938038409
+      - wikidir: /home/user/wiki
+      - destdir: $config{destdir}
+      - id: un identifiant unique ?
+    - Fichiers :
+      - Variables
+        - PAS DE `SRC*`: TOUT DANS DEST
+        - destname: foo.pdf ($destbasename.$destextension)
+        - destbasename: foo
+        - destextension: pdf
+        - desturl: http://...foo.pdf
+        - destwikiname: sub/page/foo/foo.pdf ($dirname/$destname)
+        - destfullname: /var/www/wiki/sub/page/foo/foo.pdf ($destdir/$destwikiname)
+        - destcontent: contenu de foo.pdf
+      - Variations
+        - destname0, destname1: premier, deuxième fichier source
+        - idem pour les autres variables
+        - destnamelist: liste des fichiers sources, tels qu'accessibles depuis le répertoire temporaire (shell, pour la commande seulement)
+        - destlist: liste des fichiers sources (en utilisant HTML::Template, pour les templates seulement)
+  - [ ] Traiter ``destname`` comme un glob.
+    - [ ] Accéder au premier destname avec DESTNAME.
+    - [ ] Accéder à tous les destname avec DESTNAME0, DESTNAME1, etc.
+    - [ ] Accéder à une liste de destname utilisable dans un `<TMPL_LOOP>`
+  - [ ] Supprimer les fichiers temporaires au début.
+  - [ ] Créer des dossiers temporaires en fonction du hash de ``SOURCEPAGE/FILES/COMMAND``.
+  - [ ] Ne pas re-compiler si le répertoire existe déjà.
+  - [ ] destname ne renomme pas le fichier : il sélectionne quel fichier publier.
+  - [ ] Mais fournir des templates par défaut :
+    - [ ] `compile_source`
+    - [ ] `compile_link` (avec des `var_text` et `var_srctext`)
+    - [ ] `compile_album` (avec un `var_width` et `var_height` et un `slideshow.js` seulement en exemple)
+    - [ ] `compile_raw`
+  - [ ] Doc: Fournir des exemples de règles
+    - [ ] gimp, libreoffice, latex, album, etc.
+  - [ ] Le fichier source n'est pas copié par défaut: si on en a besoin, il faut le mentionner dans les destnames.
+  - [ ] Documentation
+    - [ ] Slideshow (sans compilation)
+    - [ ] Tous les moyens d'accéder aux fichiers (destname, destname0, destnamelist, destlist[destname], etc.)
+  - [ ] Ne pas charger compile2 si compile est activé
+    - [ ] Mettre une option pour forcer
+  - [ ] wikistate: stocker compilé/erreur (rien du tout = pas encore compilé)
+  - [ ] Ajouter un argument `page` pour faire comme si la commande était appelée depuis ladite page?
+  - [ ] Marquer compile comme obsolète
+    - [ ] Source
+    - [ ] Documentation sur ikiwiki
+    - [ ] Warning dans le code
+    - [ ] git tag compile/v0.2
+  - [ ] Prévenir que bibtex2html est obsolète
+"""]]
+
+---
+
+# Quick and dirty replacement
+
+For those how might be interested: I switched from Ikiwiki to [another static site generator](http://getlektor.com), which does not have a `compile` plugin. Before writing it, I used a quick and dirty solution: using a custom `Makefile`, I use `make build` to build my website, which :
+
+- compile the files (e.g. latex documents);
+- build the website.
+
+It started as a quick and dirty fix, but I think I am keeping it.
+
+It should work with Ikiwiki too.

fix user link
diff --git a/doc/todo/pagespec_aliases.mdwn b/doc/todo/pagespec_aliases.mdwn
index 6e52dcd53..396a93c0f 100644
--- a/doc/todo/pagespec_aliases.mdwn
+++ b/doc/todo/pagespec_aliases.mdwn
@@ -173,5 +173,5 @@ Unfortunately I haven't figured out how to do the dependencies - I'd really appr
 Hi, it's been 7 years since I last looked at this, and I'm surprised to find
 that I'd got it up to a merge-request state; I've dusted it off and done some
 clean up and testing, but it's working (albeit not via websetup). I've revamped
-the docs and rebased the branch. Can someone please consider merging ([[joeyh]]
+the docs and rebased the branch. Can someone please consider merging ([[joey]]
 or [[smcv]]?) or otherwise feed back on this? Thanks! — [[Jon]] (2018-09-25)

7 year ping: dusted off and ready for re-reviewing please
diff --git a/doc/todo/pagespec_aliases.mdwn b/doc/todo/pagespec_aliases.mdwn
index 748444a2f..6e52dcd53 100644
--- a/doc/todo/pagespec_aliases.mdwn
+++ b/doc/todo/pagespec_aliases.mdwn
@@ -167,3 +167,11 @@ Unfortunately I haven't figured out how to do the dependencies - I'd really appr
 >>>>> Do you mean that you want them to work in any pagespec, or that you *don't* want them to work in any pagespec? -- [[KathrynAndersen]]
 
 >>>>>> I mean I would want them to work in any pagespec. — [[Jon]]
+
+----
+
+Hi, it's been 7 years since I last looked at this, and I'm surprised to find
+that I'd got it up to a merge-request state; I've dusted it off and done some
+clean up and testing, but it's working (albeit not via websetup). I've revamped
+the docs and rebased the branch. Can someone please consider merging ([[joeyh]]
+or [[smcv]]?) or otherwise feed back on this? Thanks! — [[Jon]] (2018-09-25)

+done
diff --git a/doc/todo/monochrome_theme.mdwn b/doc/todo/monochrome_theme.mdwn
index eaf51c080..50cbf25df 100644
--- a/doc/todo/monochrome_theme.mdwn
+++ b/doc/todo/monochrome_theme.mdwn
@@ -46,3 +46,5 @@ Perhaps controversially, I think that this would be a good basis for a default t
 >>>>>   so the impact is pretty small. (except perhaps if someone specifies an absolute
 >>>>>   `cgiurl` path?)  The additional customization is belt-and-braces.
 >>>>>   — [[Jon]]
+
+[[done]]

proposed reworking; requesting smcv take another look
diff --git a/doc/todo/support_multi-row_table_headers.mdwn b/doc/todo/support_multi-row_table_headers.mdwn
index 6f13bbb23..1d418a41b 100644
--- a/doc/todo/support_multi-row_table_headers.mdwn
+++ b/doc/todo/support_multi-row_table_headers.mdwn
@@ -77,3 +77,22 @@ It would be great if it were possible to support multi-row table headers in the
 > > addressed my immediate need so it's the one I'm deploying at $ork for the
 > > time being. I'm unlikely to have time to implement this solution in the
 > > near future. -- [[Jon]]
+
+----
+
+I'd quite like to revisit this if that's ok. I'm still carrying a fork of
+table.pm locally to add this feature as I find it so useful. The main objection
+you made back in 2014 seems to be overloading the header= parameter, and I agree
+that this is not ideal. So I'm happy to resubmit this with an alternative parameter
+name for the new purpose. But I balked at the idea of implementing something like 
+an NLP processor to define the header range. And I must stress how useful it is in
+practise to separate out the header definition from the data: quite often I don't
+want headers in my CSV files at all, for example, so I can perform rudimentary analysis
+on them with command line tools without having to factor in a header line (how many
+records?  = `wc -l`; sorting on fields simply with `sort -k` etc.). Having them
+separate means I can have machine-generated or manipulated CSV files of data and then
+use ikiwiki to mark them up for human reading, but change or regenerate the data quickly
+and easily underneath.
+
+I'd appreciate your take on the above suggestions [[smcv]] before I roll my sleeves up.
+Thanks! — [[Jon]] (2018-09-24)

ping - any opinions on this?
diff --git a/doc/todo/Modern_standard_layout.mdwn b/doc/todo/Modern_standard_layout.mdwn
index 64399b1b2..bb6356a6d 100644
--- a/doc/todo/Modern_standard_layout.mdwn
+++ b/doc/todo/Modern_standard_layout.mdwn
@@ -64,5 +64,10 @@ seems to be broken for edit/preview workflow. I might investigate/file about tha
                                                                                                                        
 I wonder if someone feels the same, since you defaulted to actiontabs on branchable.                                   
                                                                                                                        
-Thanks, [[users/Jon]].  (PS: Every log in method failed for me with Firefox Quantum
-trying to post this. Untrusted git push also failed.)
+Thanks, [[users/Jon]]. (2017-12-28)
+
+----
+
+9 month ping, does [[Joey]] or [[smcv]] have any kind of opinion on this matter,
+subsequent to my last comment? I ask because both of your takes on the issue are from
+way back in 2011. — [[Jon]] (2018-09-24)

pingbacks dead? webmentions instead?
diff --git a/doc/todo/pingback_support.mdwn b/doc/todo/pingback_support.mdwn
index 7b3b158ee..5d93e6094 100644
--- a/doc/todo/pingback_support.mdwn
+++ b/doc/todo/pingback_support.mdwn
@@ -39,3 +39,26 @@ case I will consider this done with an entry in [[tips]]; otherwise a
 > all urls found. --[[Joey]] 
 
 >> Is there any update on this? This would be highly useful and is the main reason why I am not using my blog more regularly, yet. (And yes, now that git-annex is doing everything I need and more, I thought I should revisit this one, as well). -- RichiH
+
+----
+
+Happy 9th anniversary, bug!
+
+For whatever reason I was compelled to look at this situation afresh. I've
+added some instrumentation to my own site to see whether there's any external
+attempts to issue pingbacks to my own site, to gauge whether it's worthwhile
+spending any more time on this. But it looks like pingback in the wider world
+might be dead or dying.
+
+[I started a conversation on Twitter with the inventor of Pingback to see what
+he thought](https://twitter.com/jmtd/status/1042730998839107585). He suggested
+taking a look at "webmentions". here's some preliminary reading on those:
+
+ * <https://indieweb.org/Webmention>
+ * <https://kryogenix.org/days/2014/11/29/enabling-webmentions/>
+ * <https://www.kryogenix.org/days/2014/11/30/vouching-for-webmentions-hashing-for-vouches/>
+
+At this point I don't know if webmentions actually has more traction than pingback,
+but the key issue I guess is whether it's growing. I'm going to (but am yet to) add
+corresponding instrumentation to my site to try and track that, too.
+-- [[Jon]] (2018-09-24)

diff --git a/doc/plugins/osm/discussion.mdwn b/doc/plugins/osm/discussion.mdwn
index 5736a2430..957ff3f9a 100644
--- a/doc/plugins/osm/discussion.mdwn
+++ b/doc/plugins/osm/discussion.mdwn
@@ -95,3 +95,5 @@ I've done some initial testing now and I'm wondering if behaviour has changed wi
 
 >>> What I meant was that you could add a wiki link (to a page with a map) next to each waypoint to simulate the old behaviour. 
 >>> Maps with subsets of waypoints, waypoint in multiple maps: no, because a single GeoJSON file is created for each "map". But something that could be added is the ability to merge multiple maps into one view, as separate layers. --[[users/tincho]]
+
+>>>> A wiki link to a map page will show the whole map zoomed out I presume so that won't be helful when I have pois across the globe and you want to know which side of a building the photo is taken from :( Merging maps would be a very good feature! If it could be done with a pagespec type thing it would be awesome. For my use case I could then have a map at each building page showing the locations of all the photos under that page. The map file would be reasonably small. If these maps could then be merged via a directive with globbing of some sort into a mega-map that would be a very flexibly solution that automatically updates when I add new maps (buildings). I just need to use my non-existent programming skills to force my hack plugins into automatically creating per album maps.  -[[users/kjs]]

separate another thread of discussion
diff --git a/doc/plugins/osm/discussion.mdwn b/doc/plugins/osm/discussion.mdwn
index b00f1b89d..5736a2430 100644
--- a/doc/plugins/osm/discussion.mdwn
+++ b/doc/plugins/osm/discussion.mdwn
@@ -85,6 +85,8 @@ Looks like good changes to me!
 
 > The issue about not getting all the waipoints until you rebuild has been solved, the current plugin had issues with keeping track of updated and deleted waypoints which is now fixed in my branch. --[[users/Tincho]]
 
+----
+
 I've done some initial testing now and I'm wondering if behaviour has changed with regards to the waypoint link. With the old plugin I get a map marker and link to the main map from each waypoint. See <http://img.kalleswork.net/Peter_Celsing-Filmhuset/IMGP7104/> for example, the marker is below the image. My initial tests with your plugin doesn't create this link as far as I can tell. Have I misconfigured something or is it indeed missing? --[[users/kjs]]
 
 > It is not there any more (I should document this, thanks for pointing it out). I thought that it was not good to have that marker inserted unconditionally; also, there is no full-page map any more with this plugin (which required a cgi mode). The alternative will be to have a page with the map, and adding a link to it. --[[users/Tincho]]

reply to question about new plugin
diff --git a/doc/plugins/osm/discussion.mdwn b/doc/plugins/osm/discussion.mdwn
index f9d6e8966..b00f1b89d 100644
--- a/doc/plugins/osm/discussion.mdwn
+++ b/doc/plugins/osm/discussion.mdwn
@@ -90,3 +90,6 @@ I've done some initial testing now and I'm wondering if behaviour has changed wi
 > It is not there any more (I should document this, thanks for pointing it out). I thought that it was not good to have that marker inserted unconditionally; also, there is no full-page map any more with this plugin (which required a cgi mode). The alternative will be to have a page with the map, and adding a link to it. --[[users/Tincho]]
 
 >> That's unfortunate for me as embedding a map on each page with a waypoint is a bit to expensive bandwidth wise. It will slow down the browsing to much. Are there any means of creating maps with subsets of waypoints. Perhaps tags somehow? Can a waypoint appear on multiple maps? I'm thinking having the waypoint appear on a central mega-map and on a sub map, In my case a per building map. Currently all my map info is automatically generated from the exif data. So I just upload the images to an underlay dir and git push my 'building' page which then generates an image gallery and a map of all my photos. I'm trying to avoid typing to much! ;) --[[users/kjs]]
+
+>>> What I meant was that you could add a wiki link (to a page with a map) next to each waypoint to simulate the old behaviour. 
+>>> Maps with subsets of waypoints, waypoint in multiple maps: no, because a single GeoJSON file is created for each "map". But something that could be added is the ability to merge multiple maps into one view, as separate layers. --[[users/tincho]]

rename branch to avoid conflict with upstream bootstrap branch
diff --git a/doc/plugins/contrib/bootstrap.mdwn b/doc/plugins/contrib/bootstrap.mdwn
index 9ed0af593..47b59cebd 100644
--- a/doc/plugins/contrib/bootstrap.mdwn
+++ b/doc/plugins/contrib/bootstrap.mdwn
@@ -1,7 +1,7 @@
 [[!meta author="anarcat"]]
 [[!template id=plugin name=bootstrap author="[[anarcat]]"]]
 [[!tag type/chrome]]
-[[!template  id=gitbranch branch=anarcat/bootstrap author="[[anarcat]]"]]
+[[!template  id=gitbranch branch=anarcat/bootstrap-plugin author="[[anarcat]]"]]
 
 ## Rationale
 

forgot to sign my comment
diff --git a/doc/plugins/osm/discussion.mdwn b/doc/plugins/osm/discussion.mdwn
index bb83a2b2c..f9d6e8966 100644
--- a/doc/plugins/osm/discussion.mdwn
+++ b/doc/plugins/osm/discussion.mdwn
@@ -89,4 +89,4 @@ I've done some initial testing now and I'm wondering if behaviour has changed wi
 
 > It is not there any more (I should document this, thanks for pointing it out). I thought that it was not good to have that marker inserted unconditionally; also, there is no full-page map any more with this plugin (which required a cgi mode). The alternative will be to have a page with the map, and adding a link to it. --[[users/Tincho]]
 
->> That's unfortunate for me as embedding a map on each page with a waypoint is a bit to expensive bandwidth wise. It will slow down the browsing to much. Are there any means of creating maps with subsets of waypoints. Perhaps tags somehow? Can a waypoint appear on multiple maps? I'm thinking having the waypoint appear on a central mega-map and on a sub map, In my case a per building map. Currently all my map info is automatically generated from the exif data. So I just upload the images to an underlay dir and git push my 'building' page which then generates an image gallery and a map of all my photos. I'm trying to avoid typing to much! ;)
+>> That's unfortunate for me as embedding a map on each page with a waypoint is a bit to expensive bandwidth wise. It will slow down the browsing to much. Are there any means of creating maps with subsets of waypoints. Perhaps tags somehow? Can a waypoint appear on multiple maps? I'm thinking having the waypoint appear on a central mega-map and on a sub map, In my case a per building map. Currently all my map info is automatically generated from the exif data. So I just upload the images to an underlay dir and git push my 'building' page which then generates an image gallery and a map of all my photos. I'm trying to avoid typing to much! ;) --[[users/kjs]]

diff --git a/doc/plugins/osm/discussion.mdwn b/doc/plugins/osm/discussion.mdwn
index be9c5c215..bb83a2b2c 100644
--- a/doc/plugins/osm/discussion.mdwn
+++ b/doc/plugins/osm/discussion.mdwn
@@ -88,3 +88,5 @@ Looks like good changes to me!
 I've done some initial testing now and I'm wondering if behaviour has changed with regards to the waypoint link. With the old plugin I get a map marker and link to the main map from each waypoint. See <http://img.kalleswork.net/Peter_Celsing-Filmhuset/IMGP7104/> for example, the marker is below the image. My initial tests with your plugin doesn't create this link as far as I can tell. Have I misconfigured something or is it indeed missing? --[[users/kjs]]
 
 > It is not there any more (I should document this, thanks for pointing it out). I thought that it was not good to have that marker inserted unconditionally; also, there is no full-page map any more with this plugin (which required a cgi mode). The alternative will be to have a page with the map, and adding a link to it. --[[users/Tincho]]
+
+>> That's unfortunate for me as embedding a map on each page with a waypoint is a bit to expensive bandwidth wise. It will slow down the browsing to much. Are there any means of creating maps with subsets of waypoints. Perhaps tags somehow? Can a waypoint appear on multiple maps? I'm thinking having the waypoint appear on a central mega-map and on a sub map, In my case a per building map. Currently all my map info is automatically generated from the exif data. So I just upload the images to an underlay dir and git push my 'building' page which then generates an image gallery and a map of all my photos. I'm trying to avoid typing to much! ;)

Remove unreachable git repositories
diff --git a/doc/git.mdwn b/doc/git.mdwn
index 0f959a2c3..1b21a93ac 100644
--- a/doc/git.mdwn
+++ b/doc/git.mdwn
@@ -33,12 +33,8 @@ think about merging them. This is recommended. :-)
 * [[gmcmanus]] `git://github.com/gmcmanus/ikiwiki.git`
 * [[jelmer]] `git://git.samba.org/jelmer/ikiwiki.git`
 * [[jon]] `git://github.com/jmtd/ikiwiki.git`
-* [[ikipostal|DavidBremner]] `git://pivot.cs.unb.ca/git/ikipostal.git`
-* [[ikimailbox|DavidBremner]] `git://pivot.cs.unb.ca/git/ikimailbox.git`
-* [[ikiplugins|DavidBremner]] `git://pivot.cs.unb.ca/git/ikiplugins.git`
 * [[jonas|JonasSmedegaard]] `git://source.jones.dk/ikiwiki-upstream`
 * [[arpitjain]] `git://github.com/arpitjain11/ikiwiki.git`
-* [[chrysn]] `git://prometheus.amsuess.com/ikiwiki`
 * [[schmonz]] `git://github.com/schmonz/ikiwiki.git`
 * [[KathrynAndersen]] `git://github.com/rubykat/ikiplugins.git`
 * [[ktf]] `git://github.com/ktf/ikiwiki.git`
@@ -48,18 +44,14 @@ think about merging them. This is recommended. :-)
 * [[privat]] `git://github.com/privat/ikiwiki.git`
 * [[blipvert]] `git://github.com/blipvert/ikiwiki.git`
 * [[wtk]] `git://github.com/wking/ikiwiki.git`
-* [[sunny256]] `git://github.com/sunny256/ikiwiki.git`
 * [[levitte]] `git://github.com/levitte/ikiwiki.git`
-* jo `git://git.debian.org/users/jo-guest/ikiwiki.git`
-  ([browse](http://git.debian.org/?p=users/jo-guest/ikiwiki.git;a=summary))
-* [[sajolida]] `http://un.poivron.org/~sajolida/ikiwiki.git/`
+* [[sajolida]] `https://un.poivron.org/~sajolida/ikiwiki.git/`
 * [[yds]] `git://github.com/yds/ikiwiki.git`
 * [[pelle]] `git://github.com/hemmop/ikiwiki.git`
 * [[chrismgray]] `git://github.com/chrismgray/ikiwiki.git`
 * [[ttw]] `git://github.com/ttw/ikiwiki.git`
 * [[anarcat]] `https://gitlab.com/anarcat/ikiwiki.git`
 * anderbubble `git://civilfritz.net/ikiwiki.git`
-* frioux `git://github.com/frioux/ikiwiki`
 * llipavsky `git://github.com/llipavsky/ikiwiki`
 * [[mhameed]] `git://github.com/mhameed/ikiwiki.git`
 * [[spalax]] `git://github.com/paternal/ikiwiki.git` ([[browse|https://github.com/paternal/ikiwiki]])