From 4691a2ad39cce273231fddd9a589b4f8fdc1b063 Mon Sep 17 00:00:00 2001
From: Joey Hess <joey@kodama.kitenet.net>
Date: Wed, 23 Jul 2008 18:14:20 -0400
Subject: [PATCH] add renamepage hooks

Implemented for regular wikilinks, with a test suite.
---
 IkiWiki/Plugin/link.pm | 24 ++++++++++++++++++++++++
 debian/changelog       |  2 ++
 doc/plugins/write.mdwn |  9 +++++++++
 t/renamepage.t         | 42 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 77 insertions(+)
 create mode 100755 t/renamepage.t

diff --git a/IkiWiki/Plugin/link.pm b/IkiWiki/Plugin/link.pm
index 24579057c..51afaec9e 100644
--- a/IkiWiki/Plugin/link.pm
+++ b/IkiWiki/Plugin/link.pm
@@ -80,4 +80,28 @@ sub scan (@) { #{{{
 	}
 } # }}}
 
+sub renamepage (@) { #{{{
+	my %params=@_;
+	my $page=$params{page};
+	my $old=$params{oldpage};
+	my $new=$params{newpage};
+
+	$params{content} =~ s{(?<!\\)$link_regexp}{
+		my $link=$2;
+		if (bestlink($page, $2) eq $old) {
+			if (index($2, "/") == 0) {
+				$link="/$new";
+			}
+			else {
+				$link=$new;
+			}
+		}
+		defined $1
+			? ( "[[$1|$link".($3 ? "#$3" : "")."]]" )
+			: ( "[[$link".   ($3 ? "#$3" : "")."]]" )
+	}eg;
+
+	return $params{content};
+} #}}}
+
 1
diff --git a/debian/changelog b/debian/changelog
index cfe168825..3e6fba586 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -6,6 +6,8 @@ ikiwiki (2.55) UNRELEASED; urgency=low
     (Sponsored by The TOVA Company.) (This one's for you, Kyle.)
   * All rcs backends need to implement rcs_remove, rcs_commitstaged,
     and rcs_rename. (Done for svn, git).
+  * This version adds renamepage hooks, which can be used to modify page content,
+    including links, during renames.
   * prefix_directives enabled in doc wiki, all preprocessor directives
     converted. (Simon McVittie)
   * editpage: Don't show attachments link when attachments are disabled.
diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn
index 12bd33662..3dd8bdaa1 100644
--- a/doc/plugins/write.mdwn
+++ b/doc/plugins/write.mdwn
@@ -348,6 +348,15 @@ This hook is called whenever ikiwiki normally saves its state, just before
 the state is saved. The function can save other state, modify values before
 they're saved, etc.
 
+## renamepage
+
+	hook(type => "renamepage", id => "foo", call => \&renamepage);
+
+This hook is called by the [[plugins/rename]] plugin when it renames
+something. The hook is passed named parameters: `page`, `oldpage`,
+`newpage`, and `content`, and should try to modify the content to reflect
+the name change. For example, by converting links to point to the new page.
+
 ## Plugin interface
 
 To import the ikiwiki plugin interface:
diff --git a/t/renamepage.t b/t/renamepage.t
new file mode 100755
index 000000000..ce62bf468
--- /dev/null
+++ b/t/renamepage.t
@@ -0,0 +1,42 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+use Test::More tests => 11;
+use Encode;
+
+BEGIN { use_ok("IkiWiki"); }
+BEGIN { use_ok("IkiWiki::Plugin::link"); }
+
+%config=IkiWiki::defaultconfig();
+$config{srcdir}=$config{destdir}="/dev/null";
+IkiWiki::checkconfig();
+
+# tests of the link plugin's renamepage function
+sub try {
+	my ($page, $oldpage, $newpage, $content)=@_;
+
+	%IkiWiki::pagecase=();
+	%links=();
+	$IkiWiki::config{userdir}="foouserdir";
+	foreach my $page ($page, $oldpage, $newpage) {
+		$IkiWiki::pagecase{lc $page}=$page;
+		$links{$page}=[];
+	}
+
+	IkiWiki::Plugin::link::renamepage(
+			page => $page, 
+			oldpage => $oldpage,
+			newpage => $newpage,
+			content => $content,
+	);
+}
+is(try("z", "foo" => "bar", "[[xxx]]"), "[[xxx]]"); # unrelated link
+is(try("z", "foo" => "bar", "[[bar]]"), "[[bar]]"); # link already to new page
+is(try("z", "foo" => "bar", "[[foo]]"), "[[bar]]"); # basic conversion to new page name
+is(try("z", "foo" => "bar", "[[/foo]]"), "[[/bar]]"); # absolute link
+is(try("z", "foo" => "bar", "[[foo]] [[xxx]]"), "[[bar]] [[xxx]]"); # 2 links, 1 converted
+is(try("z", "foo" => "bar", "[[xxx|foo]]"), "[[xxx|bar]]"); # conversion w/text
+is(try("z", "foo" => "bar", "[[foo#anchor]]"), "[[bar#anchor]]"); # with anchor
+is(try("z", "foo" => "bar", "[[xxx|foo#anchor]]"), "[[xxx|bar#anchor]]"); # with anchor
+is(try("z", "foo" => "bar", "[[!moo ]]"), "[[!moo ]]"); # preprocessor directive unchanged
+is(try("bugs", "bugs/foo" => "wishlist/bar", "[[foo]]"), "[[wishlist/bar]]"); # subpage link
-- 
2.39.5