Index: doc/plugins/write.mdwn
===================================================================
--- doc/plugins/write.mdwn (révision 4255)
+++ doc/plugins/write.mdwn (copie de travail)
@@ -116,9 +116,23 @@
content is going to (different for inlined pages), and a "preview"
parameter is set to a true value if the page is being previewed. All
parameters included in the directive are included as named parameters as
-well. Whatever the function returns goes onto the page in place of the
-directive.
+well.
+Whatever the function returns goes onto the page in place of the directive.
+If a hash is returned it is considered as an intermediate form of the directive
+output. The result will be passed through `convert` before it is embedded in
+the page. You must at least specify a type and content:
+
+ return (type => "html", content => $content);
+
+ return (type => "_link", content => "download here", url => "http://...");
+
+Thanks to the leading underscore, "fake" types such as `"_link"` are not
+identified with filename extensions, but `htmlize` and `convert` hooks can be
+registered with them nonetheless. If you introduce a new type, you must make
+sure it can at least be converted to html, probably by providing a
+corresponding htmlize hook.
+
An optional "scan" parameter, if set to a true value, makes the hook be
called during the preliminary scan that ikiwiki makes of updated pages,
before begining to render pages. This parameter should be set to true if
@@ -137,13 +151,46 @@
hook(type => "htmlize", id => "ext", call => \&htmlize);
Runs on the raw source of a page and turns it into html. The id parameter
-specifies the filename extension that a file must have to be htmlized using
-this plugin. This is how you can add support for new and exciting markup
-languages to ikiwiki.
+usually specifies the filename extension that a file must have to be htmlized
+using this plugin. This is how you can add support for new and exciting markup
+languages to ikiwiki. See also the `convert` hook below for specifying a way
+to embed links, raw html, or other elements inserted by preprocessor directives
+into your newly added language.
-The function is passed named parameters: "page" and "content" and should
-return the htmlized content.
+The function is passed named parameters: "type", "page" and "content" and
+should return the htmlized content.
+### convert
+
+ hook(type => "convert", id => "out,src", call => \&convert_src)
+
+Perform a conversion from `src` to `out`, as specified in the "id" parameter.
+The function is passed named parameters: "content" is the input to be
+converted, and "type" its type (which will be `src`). The converted output must
+be returned.
+
+Formats specified in the id parameters of htmlize and convert hooks are usually
+filename extensions, but extra source types can be defined. Their name must be
+prefixed with an underscore to distinguish them. They may provide additional
+parameters to their associated convert hooks.
+
+When adding a new markup language, you will want to register functions for
+converting elements inserted by proprocessor directives to your new language,
+as well as an htmlize hook for converting it to html. It is a bug if a
+preprocessor directive inserts an element which cannot be converted into html.
+This means an `id => "ext,html"` convert hook, able to embed raw html into the
+new language, will usually be sufficient.
+
+Additionnally, if your language is able to encode hyperlinks, you can provide
+an `id => "ext,_link"` hook as well. The convert hook will be passed the link
+text in the "content" parameter, and the remaining information as additionnal
+ones:
+
+ - "selflink" will be set to 1 if the link refers to the page it will end
+ up on; otherwise,
+ - "url" will contain the target url,
+ - "create" is set to one if the link points to a page creation form.
+
### pagetemplate
hook(type => "pagetemplate", id => "foo", call => \&pagetemplate);
Index: IkiWiki.pm
===================================================================
--- IkiWiki.pm (révision 4255)
+++ IkiWiki.pm (copie de travail)
@@ -27,6 +27,7 @@
memoize("abs2rel");
memoize("pagespec_translate");
memoize("file_pruned");
+memoize("convpath");
sub defaultconfig () { #{{{
return
@@ -249,7 +250,7 @@
sub pagetype ($) { #{{{
my $page=shift;
- if ($page =~ /\.([^.]+)$/) {
+ if ($page =~ /\.([^.,_+]+)$/) {
return $1 if exists $hooks{htmlize}{$1};
}
return;
@@ -537,8 +538,13 @@
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}) {
@@ -546,13 +552,12 @@
if (! $destsources{$bestlink}) {
return $linktext unless length $config{cgiurl};
- return " 1,
+ url => cgiurl(
do => "create",
page => pagetitle(lc($link), 1),
from => $lpage
- ).
- "\">?$linktext"
+ ));
}
}
@@ -560,60 +565,113 @@
$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} = {rel => $opts{rel}} if defined $opts{rel};
- return "$linktext";
+ return convert($type, %link, url => $bestlink);
} #}}}
+sub convert_link { #{{{
+ my %params=@_;
+ my $attrs="";
+
+ if($params{selflink}) {
+ return "$params{content}";
+ }
+ if($params{attrs}) {
+ $attrs=map(" $_=$params{attrs}{$_}", keys %{$params{attrs}});
+ }
+
+ return "" .
+ ($params{create}
+ ? "?$params{content}"
+ : "$params{content}") . "";
+} #}}}
+
+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};
+
+ last if $src eq $srctype;
+ push @q, grep m/^$src,/, keys %{$hooks{convert}};
+ }
+ 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";
+ }
+
+ # walk back
+ my @path;
+ while ($srctype ne $outtype) {
+ push @path, $vhooks{$srctype};
+ ($srctype) = $vhooks{$srctype}{id}=~/^(.*?),/;
+ }
+ return @path;
+} #}}}
+
+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 htmlize ($$$) { #{{{
- my $page=shift;
- my $type=shift;
- my $content=shift;
+ my %page = (page => shift, type => shift, content => shift, @_);
- if (exists $hooks{htmlize}{$type}) {
- $content=$hooks{htmlize}{$type}{call}->(
- page => $page,
- content => $content,
- );
- }
- else {
- error("htmlization of $type not supported");
- }
+ $page{content} = convert("html", %page);
+ run_hooks(sanitize => sub { $page{content}=shift->(%page); });
- run_hooks(sanitize => sub {
- $content=shift->(
- page => $page,
- content => $content,
- );
- });
-
- return $content;
+ return $page{content};
} #}}}
-sub linkify ($$$) { #{{{
+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;
@@ -622,12 +680,13 @@
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.
@@ -689,14 +748,23 @@
$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]]";
@@ -728,16 +796,9 @@
} #}}}
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 () { #{{{
@@ -925,6 +986,10 @@
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;
Index: IkiWiki/Render.pm
===================================================================
--- IkiWiki/Render.pm (révision 4255)
+++ IkiWiki/Render.pm (copie de travail)
@@ -100,7 +100,10 @@
if ($page !~ /.*\/\Q$discussionlink\E$/ &&
(length $config{cgiurl} ||
exists $links{$page."/".$discussionlink})) {
- $template->param(discussionlink => htmllink($page, $page, gettext("Discussion"), noimageinline => 1, forcesubpage => 1));
+ $template->param(discussionlink =>
+ htmllink($page, $page, gettext("Discussion"),
+ type => "html", noimageinline => 1,
+ forcesubpage => 1));
$actions++;
}
}
Index: IkiWiki/CGI.pm
===================================================================
--- IkiWiki/CGI.pm (révision 4255)
+++ IkiWiki/CGI.pm (copie de travail)
@@ -405,7 +405,8 @@
htmlize($page, $type,
linkify($page, "",
preprocess($page, $page,
- filter($page, $page, $form->field('editcontent')), 0, 1))));
+ filter($page, $page, $form->field('editcontent')),
+ 0, 1, $type), $type)));
}
elsif ($form->submitted eq "Save Page") {
$form->tmpl_param("page_preview", "");
Index: doc/plugins/rst.mdwn
===================================================================
--- doc/plugins/rst.mdwn (révision 4269)
+++ doc/plugins/rst.mdwn (copie de travail)
@@ -10,9 +10,11 @@
Note that this plugin does not interoperate very well with the rest of
ikiwiki. Limitations include:
-* There are issues with inserting raw html into documents, as ikiwiki
- does with [[WikiLinks|WikiLink]] and many
- [[PreprocessorDirectives|PreprocessorDirective]].
+* Many [[PreprocessorDirectives|PreprocessorDirective]] include raw html
+ in pages, but this works correctly only as a standalone paragraph.
+* [[WikiLinks|WikiLink]] are expanded with a trailing space, and converted
+ to rst hyperlink references, rather than raw html, which means their
+ styling is lost.
* It's slow; it forks a copy of python for each page. While there is a
perl version of the reStructuredText processor, it is not being kept in
sync with the standard version, so is not used.
Index: IkiWiki/Plugin/rst.pm
===================================================================
--- IkiWiki/Plugin/rst.pm (révision 4269)
+++ IkiWiki/Plugin/rst.pm (copie de travail)
@@ -36,9 +36,25 @@
";
sub import { #{{{
+ hook(type => "convert", id => "rst,_link", call => \&convert_link);
+ hook(type => "convert", id => "rst,html", call => \&convert_html);
hook(type => "htmlize", id => "rst", call => \&htmlize);
} # }}}
+sub convert_link { #{{{
+ my %params=@_;
+ return $params{content} if $params{selflink};
+ return $params{create} ?
+ "\\ `? <$params{url}>`__\\ $params{content} " :
+ "\\ `$params{content}\\ <$params{url}>`_ ";
+} #}}}
+
+sub convert_html { #{{{
+ my %params=@_;
+ $params{content} =~ s/^/ /mg;
+ return "\n\n.. raw:: html\n\n".$params{content}."\n\n";
+} #}}}
+
sub htmlize (@) { #{{{
my %params=@_;
my $content=$params{content};