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 "\"$linktext\""; + 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 "\"$params{content}\""; +} #}}} + +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};