diff --git a/IkiWiki.pm b/IkiWiki.pm
index 1c87831..5193a29 100644
--- a/IkiWiki.pm
+++ b/IkiWiki.pm
@@ -28,6 +28,7 @@ use Memoize;
memoize("abs2rel");
memoize("pagespec_translate");
memoize("file_pruned");
+memoize("convpath");
sub defaultconfig () { #{{{
return
@@ -251,7 +252,7 @@ sub dirname ($) { #{{{
sub pagetype ($) { #{{{
my $page=shift;
- if ($page =~ /\.([^.]+)$/) {
+ if ($page =~ /\.([^.,_+]+)$/) {
return $1 if exists $hooks{htmlize}{$1};
}
return;
@@ -554,8 +555,13 @@ sub htmllink ($$$;@) { #{{{
else {
$linktext=pagetitle(basename($link));
}
+
+ my %link=(type => "_link", content => $linktext);
+ my $type=$opts{type};
+ $type=pagetype($pagesources{$lpage}) unless $type || !$lpage;
+ $type="html" unless $type;
- return "$linktext"
+ return convert($type, %link, url => $bestlink, selflink => 1)
if length $bestlink && $page eq $bestlink;
if (! $destsources{$bestlink}) {
@@ -563,13 +569,12 @@ sub htmllink ($$$;@) { #{{{
if (! $destsources{$bestlink}) {
return $linktext unless length $config{cgiurl};
- return " 1,
+ url => cgiurl(
do => "create",
page => pagetitle(lc($link), 1),
from => $lpage
- ).
- "\">?$linktext"
+ ));
}
}
@@ -577,63 +582,119 @@ sub htmllink ($$$;@) { #{{{
$bestlink=beautify_url($bestlink);
if (! $opts{noimageinline} && isinlinableimage($bestlink)) {
- return "";
+ return convert($type, %link, type => "_image", url => $bestlink);
}
if (defined $opts{anchor}) {
$bestlink.="#".$opts{anchor};
}
- my @attrs;
- if (defined $opts{rel}) {
- push @attrs, ' rel="'.$opts{rel}.'"';
+ $link{attrs} = {
+ defined $opts{rel} ? (rel => $opts{rel}) : (),
+ defined $opts{class} ? (class => $opts{class}) : (),
+ };
+
+ return convert($type, %link, url => $bestlink);
+} #}}}
+
+sub convert_link { #{{{
+ my %params=@_;
+ my $attrs="";
+
+ if($params{selflink}) {
+ return "$params{content}";
}
- if (defined $opts{class}) {
- push @attrs, ' class="'.$opts{class}.'"';
+ if($params{attrs}) {
+ $attrs=join('', map(" $_='$params{attrs}{$_}'", keys %{$params{attrs}}));
}
+ #if (defined $opts{class}) {
+ # push @attrs, ' class="'.$opts{class}.'"';
+ #}
- return "$linktext";
+ return "" .
+ ($params{create}
+ ? "?$params{content}"
+ : "$params{content}") . "";
} #}}}
-sub htmlize ($$$) { #{{{
- my $page=shift;
- my $type=shift;
- my $content=shift;
+sub convert_image { #{{{
+ my %params=@_;
+ return "
";
+} #}}}
+
+INIT { #{{{
+ hook(type => "convert", id => "html,_link", call => \&convert_link);
+ hook(type => "convert", id => "html,_image", call => \&convert_image);
+} #}}}
+
+sub convpath ($$) { #{{{
+ my $outtype=shift;
+ my $srctype=shift;
+ my %vhooks;
+
+ # breadth-first search
+ my @q=",$outtype";
+ while (my $conv = shift @q) {
+ my ($src) = $conv=~/,(.*)/;
+
+ next if exists $vhooks{$src};
+ $vhooks{$src} = $hooks{convert}{$conv};
- if (exists $hooks{htmlize}{$type}) {
- $content=$hooks{htmlize}{$type}{call}->(
- page => $page,
- content => $content,
- );
+ last if $src eq $srctype;
+ push @q, grep m/^$src,/, keys %{$hooks{convert}};
}
- else {
- error("htmlization of $type not supported");
+ if (! exists $vhooks{$srctype}) {
+ #print STDERR "conversion of $srctype to $outtype unknown\n";
+ return &convpath("html", $srctype) unless $outtype eq "html";
+ error "${outtype}ization of $srctype not supported";
}
- run_hooks(sanitize => sub {
- $content=shift->(
- page => $page,
- content => $content,
- );
- });
+ # walk back
+ my @path;
+ while ($srctype ne $outtype) {
+ push @path, $vhooks{$srctype};
+ ($srctype) = $vhooks{$srctype}{id}=~/^(.*?),/;
+ }
+ return @path;
+} #}}}
- return $content;
+sub convert ($@) { #{{{
+ my $outtype=shift;
+ my %params=@_;
+ my $h;
+
+ foreach $h (convpath($outtype, $params{type})) {
+ %params=(type => ($h->{id} =~ /^([^,]*)/),
+ content => $h->{call}->(%params));
+ }
+
+ return $params{content};
} #}}}
-sub linkify ($$$) { #{{{
+sub htmlize ($$$) { #{{{
+ my %page = (page => shift, type => shift, content => shift, @_);
+
+ $page{content} = convert("html", %page);
+ run_hooks(sanitize => sub { $page{content}=shift->(%page); });
+
+ return $page{content};
+} #}}}
+
+sub linkify ($$$;$) { #{{{
my $lpage=shift; # the page containing the links
my $page=shift; # the page the link will end up on (different for inline)
my $content=shift;
+ my %type = @_ ? (type => shift) : ();
$content =~ s{(\\?)$config{wiki_link_regexp}}{
defined $2
? ( $1
? "[[$2|$3".($4 ? "#$4" : "")."]]"
- : htmllink($lpage, $page, linkpage($3),
+ : htmllink($lpage, $page, linkpage($3), %type,
anchor => $4, linktext => pagetitle($2)))
: ( $1
? "[[$3".($4 ? "#$4" : "")."]]"
- : htmllink($lpage, $page, linkpage($3),
+ : htmllink($lpage, $page, linkpage($3), %type,
anchor => $4))
}eg;
@@ -642,12 +703,13 @@ sub linkify ($$$) { #{{{
my %preprocessing;
our $preprocess_preview=0;
-sub preprocess ($$$;$$) { #{{{
+sub preprocess ($$$;$$$) { #{{{
my $page=shift; # the page the data comes from
my $destpage=shift; # the page the data will appear in (different for inline)
my $content=shift;
my $scan=shift;
my $preview=shift;
+ my $type=shift || pagetype($pagesources{$page});
# Using local because it needs to be set within any nested calls
# of this function.
@@ -709,14 +771,23 @@ sub preprocess ($$$;$$) { #{{{
$command, $page, $preprocessing{$page}).
"]]";
}
- my $ret=$hooks{preprocess}{$command}{call}->(
- @params,
+ my %info=(
page => $page,
destpage => $destpage,
preview => $preprocess_preview,
);
+ my @ret=$hooks{preprocess}{$command}{call}->(
+ @params,
+ %info
+ );
$preprocessing{$page}--;
- return $ret;
+
+ if (@ret==1) {
+ return $ret[0] unless $ret[0]=~/[<>]/;
+ #print STDERR "undeclared html from [[$command]]\n";
+ @ret=(type => "html", content => $ret[0]);
+ }
+ return convert($type, %info, @ret);
}
else {
return "[[$command $params]]";
@@ -748,16 +819,9 @@ sub preprocess ($$$;$$) { #{{{
} #}}}
sub filter ($$$) { #{{{
- my $page=shift;
- my $destpage=shift;
- my $content=shift;
-
- run_hooks(filter => sub {
- $content=shift->(page => $page, destpage => $destpage,
- content => $content);
- });
-
- return $content;
+ my %params=(page => shift, destpage => shift, content => shift);
+ run_hooks(filter => sub { $params{content}=shift->(%params); });
+ return $params{content};
} #}}}
sub indexlink () { #{{{
@@ -947,6 +1011,10 @@ sub hook (@) { # {{{
error 'hook requires type, call, and id parameters';
}
+ if ($param{type} eq "htmlize") {
+ &hook(%param, type => "convert", id => "html,$param{id}");
+ }
+
return if $param{no_override} && exists $hooks{$param{type}}{$param{id}};
$hooks{$param{type}}{$param{id}}=\%param;
diff --git a/IkiWiki/CGI.pm b/IkiWiki/CGI.pm
index 155010a..529a73a 100644
--- a/IkiWiki/CGI.pm
+++ b/IkiWiki/CGI.pm
@@ -415,7 +415,7 @@ sub cgi_editpage ($$) { #{{{
htmlize($page, $type,
linkify($page, "",
preprocess($page, $page,
- filter($page, $page, $content), 0, 1))));
+ filter($page, $page, $content), 0, 1, $type), $type)));
}
elsif ($form->submitted eq "Save Page") {
$form->tmpl_param("page_preview", "");
diff --git a/IkiWiki/Plugin/rst.pm b/IkiWiki/Plugin/rst.pm
index 30f5d16..44a9a48 100644
--- a/IkiWiki/Plugin/rst.pm
+++ b/IkiWiki/Plugin/rst.pm
@@ -36,9 +36,25 @@ print html[html.find('
foo
+bar
+ +END + +is(IkiWiki::htmlize("foo", "rst", "< & >"), << & >
+ +END + +## +# some fudging to make linkify work right; copied from linkify.t +$IkiWiki::pagecase{foo}="foo"; +$links{foo} = []; +$renderedfiles{'foo.mdwn'} = [ 'foo' ]; +$destsources{'foo'} = 'foo.mdwn'; +$IkiWiki::pagecase{link}="link"; +$links{link} = []; +$renderedfiles{'link.mdwn'} = [ 'link' ]; +$destsources{'link'} = 'link.mdwn'; +$config{usedirs}=0; + +is(IkiWiki::linkify('foo','foo','a [[link]] b', "rst"), + 'a \\ `link\\ `_ b', "linkify RST"); + +is(IkiWiki::htmlize("foo", "rst", + IkiWiki::linkify("foo", "foo", "foo [[link]] bar\n\nbaz\n", "rst")), <foo link bar
+baz
+