diff options
52 files changed, 776 insertions, 120 deletions
diff --git a/IkiWiki.pm b/IkiWiki.pm index bcbbabbe0..6a1823c5a 100644 --- a/IkiWiki.pm +++ b/IkiWiki.pm @@ -769,21 +769,30 @@ sub preprocess ($$$;$$) { #{{{ } my $ret; if (! $scan) { - $ret=$hooks{preprocess}{$command}{call}->( - @params, - page => $page, - destpage => $destpage, - preview => $preprocess_preview, - ); + $ret=eval { + $hooks{preprocess}{$command}{call}->( + @params, + page => $page, + destpage => $destpage, + preview => $preprocess_preview, + ); + }; + if ($@) { + chomp $@; + $ret="[[!$command <span class=\"error\">". + gettext("Error").": $@"."</span>]]"; + } } else { # use void context during scan pass - $hooks{preprocess}{$command}{call}->( - @params, - page => $page, - destpage => $destpage, - preview => $preprocess_preview, - ); + eval { + $hooks{preprocess}{$command}{call}->( + @params, + page => $page, + destpage => $destpage, + preview => $preprocess_preview, + ); + }; $ret=""; } $preprocessing{$page}--; diff --git a/IkiWiki/Plugin/aggregate.pm b/IkiWiki/Plugin/aggregate.pm index b5354a823..e000bc864 100644 --- a/IkiWiki/Plugin/aggregate.pm +++ b/IkiWiki/Plugin/aggregate.pm @@ -21,6 +21,7 @@ sub import { #{{{ hook(type => "preprocess", id => "aggregate", call => \&preprocess); hook(type => "delete", id => "aggregate", call => \&delete); hook(type => "savestate", id => "aggregate", call => \&savestate); + hook(type => "htmlize", id => "_aggregated", call => \&htmlize); if (exists $config{aggregate_webtrigger} && $config{aggregate_webtrigger}) { hook(type => "cgi", id => "aggregate", call => \&cgi); } @@ -30,7 +31,10 @@ sub getopt () { #{{{ eval q{use Getopt::Long}; error($@) if $@; Getopt::Long::Configure('pass_through'); - GetOptions("aggregate" => \$config{aggregate}); + GetOptions( + "aggregate" => \$config{aggregate}, + "aggregateinternal!" => \$config{aggregateinternal}, + ); } #}}} sub checkconfig () { #{{{ @@ -110,6 +114,61 @@ sub launchaggregation () { #{{{ return 1; } #}}} +# Pages with extension _aggregated have plain html markup, pass through. +sub htmlize (@) { #{{{ + my %params=@_; + return $params{content}; +} #}}} + +# Used by ikiwiki-transition aggregateinternal. +sub migrate_to_internal { #{{{ + if (! lockaggregate()) { + error("an aggregation process is currently running"); + } + + IkiWiki::lockwiki(); + loadstate(); + $config{verbose}=1; + + foreach my $data (values %guids) { + next unless $data->{page}; + next if $data->{expired}; + + $config{aggregateinternal} = 0; + my $oldname = pagefile($data->{page}); + my $oldoutput = $config{destdir}."/".IkiWiki::htmlpage($data->{page}); + + $config{aggregateinternal} = 1; + my $newname = pagefile($data->{page}); + + debug "moving $oldname -> $newname"; + if (-e $newname) { + if (-e $oldname) { + error("$newname already exists"); + } + else { + debug("already renamed to $newname?"); + } + } + elsif (-e $oldname) { + rename($oldname, $newname) || error("$!"); + } + else { + debug("$oldname not found"); + } + if (-e $oldoutput) { + require IkiWiki::Render; + debug("removing output file $oldoutput"); + IkiWiki::prune($oldoutput); + } + } + + savestate(); + IkiWiki::unlockwiki; + + unlockaggregate(); +} #}}} + sub needsbuild (@) { #{{{ my $needsbuild=shift; @@ -131,7 +190,7 @@ sub preprocess (@) { #{{{ foreach my $required (qw{name url}) { if (! exists $params{$required}) { - return "[[aggregate ".sprintf(gettext("missing %s parameter"), $required)."]]"; + error sprintf(gettext("missing %s parameter"), $required) } } @@ -595,7 +654,7 @@ sub pagefile ($) { #{{{ } #}}} sub htmlfn ($) { #{{{ - return shift().".".$config{htmlext}; + return shift().".".($config{aggregateinternal} ? "_aggregated" : $config{htmlext}); } #}}} my $aggregatelock; diff --git a/IkiWiki/Plugin/conditional.pm b/IkiWiki/Plugin/conditional.pm index 57db01054..6be52eaa6 100644 --- a/IkiWiki/Plugin/conditional.pm +++ b/IkiWiki/Plugin/conditional.pm @@ -15,7 +15,7 @@ sub preprocess_if (@) { #{{{ foreach my $param (qw{test then}) { if (! exists $params{$param}) { - return "[[if ".sprintf(gettext('%s parameter is required'), $param)."]]"; + error sprintf(gettext('%s parameter is required'), $param); } } diff --git a/IkiWiki/Plugin/edittemplate.pm b/IkiWiki/Plugin/edittemplate.pm index 76c1cd42a..d1716a315 100644 --- a/IkiWiki/Plugin/edittemplate.pm +++ b/IkiWiki/Plugin/edittemplate.pm @@ -38,10 +38,10 @@ sub preprocess (@) { #{{{ return "" if $params{page} ne $params{destpage}; if (! exists $params{template} || ! length($params{template})) { - return "[[meta ".gettext("template not specified")."]]"; + error gettext("template not specified") } if (! exists $params{match} || ! length($params{match})) { - return "[[meta ".gettext("match not specified")."]]"; + error gettext("match not specified") } $pagestate{$params{page}}{edittemplate}{$params{match}}=$params{template}; @@ -108,7 +108,9 @@ sub filltemplate ($$) { #{{{ ); }; if ($@) { - return "[[pagetemplate ".gettext("failed to process")." $@]]"; + # Indicate that the earlier preprocessor directive set + # up a template that doesn't work. + return "[[!pagetemplate ".gettext("failed to process")." $@]]"; } $template->param(name => $page); diff --git a/IkiWiki/Plugin/fortune.pm b/IkiWiki/Plugin/fortune.pm index a3b13f687..a78a73d5f 100644 --- a/IkiWiki/Plugin/fortune.pm +++ b/IkiWiki/Plugin/fortune.pm @@ -15,7 +15,7 @@ sub preprocess (@) { #{{{ my $f = `fortune 2>/dev/null`; if ($?) { - return "[[".gettext("fortune failed")."]]"; + error gettext("fortune failed"); } else { return "<pre>$f</pre>\n"; diff --git a/IkiWiki/Plugin/googlecalendar.pm b/IkiWiki/Plugin/googlecalendar.pm index c6409e5e6..7efa1daa3 100644 --- a/IkiWiki/Plugin/googlecalendar.pm +++ b/IkiWiki/Plugin/googlecalendar.pm @@ -19,7 +19,7 @@ sub preprocess (@) { #{{{ # Avoid XSS attacks.. my ($url)=$params{html}=~m#iframe\s+src="http://www\.google\.com/calendar/embed\?([^"<>]+)"#; if (! defined $url || ! length $url) { - return "[[googlecalendar ".gettext("failed to find url in html")."]]"; + error gettext("failed to find url in html") } my ($height)=$params{html}=~m#height="(\d+)"#; my ($width)=$params{html}=~m#width="(\d+)"#; diff --git a/IkiWiki/Plugin/graphviz.pm b/IkiWiki/Plugin/graphviz.pm index fe3559857..b13d15fa6 100644 --- a/IkiWiki/Plugin/graphviz.pm +++ b/IkiWiki/Plugin/graphviz.pm @@ -55,7 +55,7 @@ sub render_graph (\%) { #{{{ waitpid $pid, 0; $SIG{PIPE}="DEFAULT"; - return "[[graph ".gettext("failed to run graphviz")."]]" if ($sigpipe); + error gettext("failed to run graphviz") if $sigpipe; if (! $params{preview}) { writefile($dest, $config{destdir}, $png, 1); @@ -82,7 +82,7 @@ sub graph (@) { #{{{ $params{src} = "" unless defined $params{src}; $params{type} = "digraph" unless defined $params{type}; $params{prog} = "dot" unless defined $params{prog}; - return "[[graph ".gettext("prog not a valid graphviz program")."]]" unless $graphviz_programs{$params{prog}}; + error gettext("prog not a valid graphviz program") unless $graphviz_programs{$params{prog}}; return render_graph(%params); } # }}} diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm index 49e1d57d6..17a9367d3 100644 --- a/IkiWiki/Plugin/img.pm +++ b/IkiWiki/Plugin/img.pm @@ -46,14 +46,14 @@ sub preprocess (@) { #{{{ my $base = IkiWiki::basename($file); eval q{use Image::Magick}; - return "[[img ".gettext("Image::Magick not installed")."]]" if $@; + error gettext("Image::Magick is not installed") if $@; my $im = Image::Magick->new; my $imglink; my $r; if ($params{size} ne 'full') { my ($w, $h) = ($params{size} =~ /^(\d+)x(\d+)$/); - return "[[img ".sprintf(gettext('bad size "%s"'), $params{size})."]]" + error sprintf(gettext('bad size "%s"'), $params{size}) unless (defined $w && defined $h); my $outfile = "$config{destdir}/$dir/${w}x${h}-$base"; @@ -63,14 +63,14 @@ sub preprocess (@) { #{{{ if (-e $outfile && (-M srcfile($file) >= -M $outfile)) { $r = $im->Read($outfile); - return "[[img ".sprintf(gettext("failed to read %s: %s"), $outfile, $r)."]]" if $r; + error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r; } else { $r = $im->Read(srcfile($file)); - return "[[img ".sprintf(gettext("failed to read %s: %s"), $file, $r)."]]" if $r; + error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r; $r = $im->Resize(geometry => "${w}x${h}"); - return "[[img ".sprintf(gettext("failed to resize: %s"), $r)."]]" if $r; + error sprintf(gettext("failed to resize: %s"), $r) if $r; # don't actually write file in preview mode if (! $params{preview}) { @@ -84,7 +84,7 @@ sub preprocess (@) { #{{{ } else { $r = $im->Read(srcfile($file)); - return "[[img ".sprintf(gettext("failed to read %s: %s"), $file, $r)."]]" if $r; + error sprintf(gettext("failed to read %s: %s"), $file, $r) if $r; $imglink = $file; } @@ -101,7 +101,7 @@ sub preprocess (@) { #{{{ } if (! defined($im->Get("width")) || ! defined($im->Get("height"))) { - return "[[img ".sprintf(gettext("failed to determine size of image %s"), $file)."]]"; + error sprintf(gettext("failed to determine size of image %s"), $file) } my $imgtag='<img src="'.$imgurl. diff --git a/IkiWiki/Plugin/inline.pm b/IkiWiki/Plugin/inline.pm index 32915c342..5517e3c94 100644 --- a/IkiWiki/Plugin/inline.pm +++ b/IkiWiki/Plugin/inline.pm @@ -98,7 +98,7 @@ sub preprocess_inline (@) { #{{{ my %params=@_; if (! exists $params{pages}) { - return "[[inline ".gettext("missing pages parameter")."]]"; + error gettext("missing pages parameter"); } my $raw=yesno($params{raw}); my $archive=yesno($params{archive}); diff --git a/IkiWiki/Plugin/linkmap.pm b/IkiWiki/Plugin/linkmap.pm index 82b38f4cb..ab199b723 100644 --- a/IkiWiki/Plugin/linkmap.pm +++ b/IkiWiki/Plugin/linkmap.pm @@ -94,9 +94,7 @@ sub genmap ($) { #{{{ waitpid $pid, 0; $SIG{PIPE}="DEFAULT"; - if ($sigpipe) { - return "[[linkmap ".gettext("failed to run dot")."]]"; - } + error gettext("failed to run dot") if $sigpipe; return $ret; } #}}} diff --git a/IkiWiki/Plugin/meta.pm b/IkiWiki/Plugin/meta.pm index d00b6854f..4e0e9e8c7 100644 --- a/IkiWiki/Plugin/meta.pm +++ b/IkiWiki/Plugin/meta.pm @@ -138,7 +138,7 @@ sub preprocess (@) { #{{{ # editable page as a stylesheet my $stylesheet=bestlink($page, $value.".css"); if (! length $stylesheet) { - return "[[meta ".gettext("stylesheet not found")."]]"; + error gettext("stylesheet not found") } push @{$metaheaders{$page}}, '<link href="'.urlto($stylesheet, $page). '" rel="'.encode_entities($rel). @@ -172,7 +172,7 @@ sub preprocess (@) { #{{{ add_depends($page, $redir_page); my $link=bestlink($page, $redir_page); if (! length $link) { - return "[[meta ".gettext("redir page not found")."]]"; + error gettext("redir page not found") } $value=urlto($link, $page); @@ -185,7 +185,7 @@ sub preprocess (@) { #{{{ my %seen; while (exists $pagestate{$at}{meta}{redir}) { if ($seen{$at}) { - return "[[meta ".gettext("redir cycle is not allowed")."]]"; + error gettext("redir cycle is not allowed") } $seen{$at}=1; $at=$pagestate{$at}{meta}{redir}; diff --git a/IkiWiki/Plugin/pagetemplate.pm b/IkiWiki/Plugin/pagetemplate.pm index 69a2433a8..205f5a9d7 100644 --- a/IkiWiki/Plugin/pagetemplate.pm +++ b/IkiWiki/Plugin/pagetemplate.pm @@ -18,7 +18,7 @@ sub preprocess (@) { #{{{ if (! exists $params{template} || $params{template} !~ /^[-A-Za-z0-9._+]+$/ || ! defined IkiWiki::template_file($params{template})) { - return "[[pagetemplate ".gettext("bad or missing template")."]]"; + error gettext("bad or missing template") } if ($params{page} eq $params{destpage}) { diff --git a/IkiWiki/Plugin/pinger.pm b/IkiWiki/Plugin/pinger.pm index c6fa76e3f..614d42885 100644 --- a/IkiWiki/Plugin/pinger.pm +++ b/IkiWiki/Plugin/pinger.pm @@ -34,7 +34,7 @@ sub needsbuild (@) { #{{{ sub preprocess (@) { #{{{ my %params=@_; if (! exists $params{from} || ! exists $params{to}) { - return "[[ping ".gettext("requires 'from' and 'to' parameters")."]]"; + error gettext("requires 'from' and 'to' parameters"); } if ($params{from} eq $config{url}) { $pagestate{$params{destpage}}{pinger}{$params{to}}=1; diff --git a/IkiWiki/Plugin/polygen.pm b/IkiWiki/Plugin/polygen.pm index 5208a44ec..70378cf1b 100644 --- a/IkiWiki/Plugin/polygen.pm +++ b/IkiWiki/Plugin/polygen.pm @@ -29,7 +29,7 @@ sub preprocess (@) { #{{{ my $grmfile = '/usr/share/polygen/ita/polygen.grm'; if (! -d '/usr/share/polygen') { - return "[[".gettext("polygen not installed")."]]"; + error gettext("polygen not installed"); } find({wanted => sub { if (substr($File::Find::name, -length($grammar)) eq $grammar) { @@ -48,7 +48,7 @@ sub preprocess (@) { #{{{ } if ($?) { - $res="[[".gettext("polygen failed")."]]"; + error gettext("command failed"); } # Strip trailing spaces and newlines so that we flow well with the diff --git a/IkiWiki/Plugin/postsparkline.pm b/IkiWiki/Plugin/postsparkline.pm index 9e885741e..6fc96f8b3 100644 --- a/IkiWiki/Plugin/postsparkline.pm +++ b/IkiWiki/Plugin/postsparkline.pm @@ -29,14 +29,14 @@ sub preprocess (@) { #{{{ } if (! exists $params{formula}) { - return "[[postsparkline ".gettext("missing formula")."]]"; + error gettext("missing formula") } my $formula=$params{formula}; $formula=~s/[^a-zA-Z0-9]*//g; $formula=IkiWiki::possibly_foolish_untaint($formula); if (! length $formula || ! IkiWiki::Plugin::postsparkline::formula->can($formula)) { - return "[[postsparkline ".gettext("unknown formula")."]]"; + error gettext("unknown formula"); } add_depends($params{page}, $params{pages}); @@ -53,7 +53,7 @@ sub preprocess (@) { #{{{ my @data=eval qq{IkiWiki::Plugin::postsparkline::formula::$formula(\\\%params, \@list)}; if ($@) { - return "[[postsparkline error $@]]"; + error $@; } if (! @data) { diff --git a/IkiWiki/Plugin/shortcut.pm b/IkiWiki/Plugin/shortcut.pm index f1a38ea48..8df60cfe2 100644 --- a/IkiWiki/Plugin/shortcut.pm +++ b/IkiWiki/Plugin/shortcut.pm @@ -24,7 +24,7 @@ sub preprocess_shortcut (@) { #{{{ my %params=@_; if (! defined $params{name} || ! defined $params{url}) { - return "[[shortcut ".gettext("missing name or url parameter")."]]"; + error gettext("missing name or url parameter"); } hook(type => "preprocess", no_override => 1, id => $params{name}, diff --git a/IkiWiki/Plugin/sparkline.pm b/IkiWiki/Plugin/sparkline.pm index 69b3512c2..bcff46aeb 100644 --- a/IkiWiki/Plugin/sparkline.pm +++ b/IkiWiki/Plugin/sparkline.pm @@ -60,13 +60,13 @@ sub preprocess (@) { #{{{ } } elsif (! length $value) { - return "[[sparkline ".gettext("parse error")." \"$key\"]]"; + error gettext("parse error")." \"$key\""; } elsif ($key eq 'featurepoint') { my ($x, $y, $color, $diameter, $text, $location)= split(/\s*,\s*/, $value); if (! defined $diameter || $diameter < 0) { - return "[[sparkline ".gettext("bad featurepoint diameter")."]]"; + error gettext("bad featurepoint diameter"); } $x=int($x); $y=int($y); @@ -76,7 +76,7 @@ sub preprocess (@) { #{{{ if (defined $location) { $location=$locmap{$location}; if (! defined $location) { - return "[[sparkline ".gettext("bad featurepoint location")."]]"; + error gettext("bad featurepoint location"); } } $php.=qq{\$sparkline->SetFeaturePoint($x, $y, '$color', $diameter}; @@ -87,23 +87,23 @@ sub preprocess (@) { #{{{ } if ($c eq 0) { - return "[[sparkline ".gettext("missing values")."]]"; + error gettext("missing values"); } my $height=int($params{height} || 20); if ($height < 2 || $height > 100) { - return "[[sparkline ".gettext("bad height value")."]]"; + error gettext("bad height value"); } if ($style eq "Bar") { $php.=qq{\$sparkline->Render($height);\n}; } else { if (! exists $params{width}) { - return "[[sparkline ".gettext("missing width parameter")."]]"; + error gettext("missing width parameter"); } my $width=int($params{width}); if ($width < 2 || $width > 1024) { - return "[[sparkline ".gettext("bad width value")."]]"; + error gettext("bad width value"); } $php.=qq{\$sparkline->RenderResampled($width, $height);\n}; } @@ -141,7 +141,7 @@ sub preprocess (@) { #{{{ waitpid $pid, 0; $SIG{PIPE}="DEFAULT"; if ($sigpipe) { - return "[[sparkline ".gettext("failed to run php")."]]"; + error gettext("failed to run php"); } if (! $params{preview}) { diff --git a/IkiWiki/Plugin/table.pm b/IkiWiki/Plugin/table.pm index 11474c8f0..892ea182e 100644 --- a/IkiWiki/Plugin/table.pm +++ b/IkiWiki/Plugin/table.pm @@ -19,7 +19,7 @@ sub preprocess (@) { #{{{ if (exists $params{file}) { if (! $pagesources{$params{file}}) { - return "[[table ".gettext("cannot find file")."]]"; + error gettext("cannot find file"); } $params{data} = readfile(srcfile($params{file})); add_depends($params{page}, $params{file}); @@ -61,7 +61,7 @@ sub preprocess (@) { #{{{ defined $params{delimiter} ? $params{delimiter} : "|",); } else { - return "[[table ".gettext("unknown data format")."]]"; + error gettext("unknown data format"); } my $header; @@ -69,7 +69,7 @@ sub preprocess (@) { #{{{ $header=shift @data; } if (! @data) { - return "[[table ".gettext("empty data")."]]"; + error gettext("empty data"); } my @lines; diff --git a/IkiWiki/Plugin/template.pm b/IkiWiki/Plugin/template.pm index aa1f57c07..c33dbbb83 100644 --- a/IkiWiki/Plugin/template.pm +++ b/IkiWiki/Plugin/template.pm @@ -16,7 +16,7 @@ sub preprocess (@) { #{{{ my %params=@_; if (! exists $params{id}) { - return "[[template ".gettext("missing id parameter")."]]"; + error gettext("missing id parameter") } my $template_page="templates/$params{id}"; @@ -42,7 +42,7 @@ sub preprocess (@) { #{{{ ); }; if ($@) { - return "[[template ".gettext("failed to process:")." $@]]"; + error gettext("failed to process:")." $@" } $params{basename}=IkiWiki::basename($params{page}); diff --git a/IkiWiki/Plugin/testpagespec.pm b/IkiWiki/Plugin/testpagespec.pm index f9ec90d87..4faef7be1 100644 --- a/IkiWiki/Plugin/testpagespec.pm +++ b/IkiWiki/Plugin/testpagespec.pm @@ -14,7 +14,7 @@ sub preprocess (@) { #{{{ foreach my $param (qw{match pagespec}) { if (! exists $params{$param}) { - return "[[testpagespec $param parameter is required]]"; + error sprintf(gettext("%s parameter is required"), $param); } } diff --git a/IkiWiki/Plugin/teximg.pm b/IkiWiki/Plugin/teximg.pm index 8c3e88c69..6a6bdd4fa 100644 --- a/IkiWiki/Plugin/teximg.pm +++ b/IkiWiki/Plugin/teximg.pm @@ -27,14 +27,14 @@ sub preprocess (@) { #{{{ my $code = $params{code}; if (! defined $code && ! length $code) { - return "[[teximg ".gettext("missing tex code"). "]]"; + error gettext("missing tex code"); } if (check($code)) { return create($code, check_height($height), \%params); } else { - return "[[teximg ".gettext("code includes disallowed latex commands"). "]]"; + error gettext("code includes disallowed latex commands") } } #}}} @@ -85,7 +85,7 @@ sub create ($$$) { #{{{ .qq{" class="teximg" />}; } else { - return qq{[[teximg <a href="$logurl">}.gettext("failed to generate image from code")."</a>]]"; + error qq{<a href="$logurl">}.gettext("failed to generate image from code")."</a>"; } } #}}} diff --git a/debian/changelog b/debian/changelog index f10200a52..9039829ac 100644 --- a/debian/changelog +++ b/debian/changelog @@ -15,10 +15,23 @@ ikiwiki (2.54) UNRELEASED; urgency=low * Change deb dependencies to list Text::Markdown before markdown, since the former, while slower, has a much better html parser that avoids numerous bugs. - * meta, inline: Support guid options, to allow forcing a particular url or - uuid in feeds. (smcv) * Move yesno function out of inline and into IkiWiki core, not exported. - * meta: fix title() PageSpec (smcv) + * Error handling improvement for preprocess hooks. It's now safe to call + error() from such hooks; it will cause a nicely formatted error message + to be inserted into the page. + * Cut the size of the binary package in half by excluding pages for bugs + and todo items from the html shipped in it. + + [ Simon McVittie ] + * meta, inline: Support guid options, to allow forcing a particular url or + uuid in feeds. + * meta: fix title() PageSpec + * Some footer style changes. + * aggregate: Add an `aggregateinternal` option, which allows storing + aggregated data to internal-use files, rather than wiki pages. This + can save disk space, and be faster. + * ikiwiki-transition: Add a `aggregateinternal` transition to rename + the aggregated files. -- Josh Triplett <josh@freedesktop.org> Wed, 09 Jul 2008 21:30:33 -0700 diff --git a/doc/bugs/Broken_URL_to_your_blog_script.mdwn b/doc/bugs/Broken_URL_to_your_blog_script.mdwn new file mode 100644 index 000000000..3d6661d9c --- /dev/null +++ b/doc/bugs/Broken_URL_to_your_blog_script.mdwn @@ -0,0 +1,10 @@ +Joey, I would like to see your blog script I've found +at [[Tips|tips/blog_script]] page, but it seems that the URL +(http://git.kitenet.net/?p=joey/home;a=blob_plain;f=bin/blog) +to its Git repo is broken: + + 403 Forbidden - No such project + +--[[Paweł|ptecza]] + +> [[fixed|done]] --[[Joey]] diff --git a/doc/bugs/__96____96__clear:_both__39____39___for___96__.page__42____39____63__.mdwn b/doc/bugs/__96____96__clear:_both__39____39___for___96__.page__42____39____63__.mdwn index e389ce3ed..a1b5ba94a 100644 --- a/doc/bugs/__96____96__clear:_both__39____39___for___96__.page__42____39____63__.mdwn +++ b/doc/bugs/__96____96__clear:_both__39____39___for___96__.page__42____39____63__.mdwn @@ -15,3 +15,21 @@ adding this `clear: both`? > before the modification date. So all of them have to clear both above and > below. I'm sure there are better ways for the CSS to handle that. > --[[Joey]] + +>> There is indeed a better way - all the optional things below the +>> content are wrapped in `<div id="footer">`, so to have the browser wait +>> until all floating boxes have finished before rendering the footer, it +>> would be sufficient to have `#footer { clear: both; }` and remove all +>> the other footer-related `clear` attributes. I'm not sure what you mean +>> by "clear above and below" - the clear attribute takes values none, left, +>> right or both, and its purpose is to stop floating boxes (sidebars, +>> mainly) from overlapping with footers. +>> +>> ... oh, I see what you mean - this affects inlines too. In inlinepage.tmpl +>> we could wrap the "pseudo-footer" in `<div class="inlinefooter">` too? +>> Then sites could choose whether to set clear:both on the inlinefooter +>> or not, and this would be separate from the same styling on whole pages. +>> +>> [[done]] --[[smcv]] + +[[patch]] diff --git a/doc/bugs/aggregateinline_planets_wrongly_link_to_posts.mdwn b/doc/bugs/aggregateinline_planets_wrongly_link_to_posts.mdwn index e722e9d73..58c247631 100644 --- a/doc/bugs/aggregateinline_planets_wrongly_link_to_posts.mdwn +++ b/doc/bugs/aggregateinline_planets_wrongly_link_to_posts.mdwn @@ -1,6 +1,17 @@ [[!meta title="aggregate/inline planets wrongly link to posts"]] Please see -<http://vcs-pkg.org/planet/>. The headers of posts link to the HTML pages, which ikiwiki scraped. Also, the `\[[meta]]` titles and author directives aren't processed, but included inline. I believe that the headers should link to the posts directly, not the "cached" copies ikiwiki keeps around. +<http://vcs-pkg.org/planet/>. The headers of posts link to the HTML pages, which ikiwiki scraped. +I believe that the headers should link to the posts directly, not the "cached" copies ikiwiki keeps around. + +> As far as I can see, that problem no longer exists. + +Also, the `\[[meta]]` titles and author directives aren't processed, but included inline. + +> Hmm, I don't see that either. What's also not ideal is that the cached copies can be edited. Any edits there will never make it to the VCS and thus won't show up in recentchanges. + +> That can be disabled now by enabling `aggreageinternal` --[[Joey]] + +> Calling this [[done]], please let me know if I missed something. diff --git a/doc/ikiwiki-transition.mdwn b/doc/ikiwiki-transition.mdwn index 693c1db83..3290ca7e9 100644 --- a/doc/ikiwiki-transition.mdwn +++ b/doc/ikiwiki-transition.mdwn @@ -25,6 +25,11 @@ Note that if the page contains wiki links with spaces, which some older versions of ikiwiki accepted, the prefix_directives transition will treat these as preprocessor directives and convert them. +# aggregateinternal + +The `aggregateinternal` mode moves pages aggregated by the aggregate plugin +so that the `aggregateinternal` option can be enabled. + # indexdb The `indexdb` mode handles converting a plain text `.ikiwiki/index` file to diff --git a/doc/ikiwiki.setup b/doc/ikiwiki.setup index 6d327fd98..10cb3da1d 100644 --- a/doc/ikiwiki.setup +++ b/doc/ikiwiki.setup @@ -174,8 +174,12 @@ use IkiWiki::Setup::Standard { # pages anonymous users can edit #anonok_pagespec => "*", - # For use with the aggregate plugin, to allow aggregation to be - # triggered via the web. + # For use with the aggregate plugin. + # Enable aggregation to internal pages. New wikis should set this to 1, + # but if you use aggregate already, read the aggregate plugin docs + # before enabling it. + #aggregateinternal => 1, + # Allow aggregation to be triggered via the web. #aggregate_webtrigger => 1, # For use with the pinger plugin, how many seconds to wait before diff --git a/doc/plugins/aggregate.mdwn b/doc/plugins/aggregate.mdwn index 574c8b125..ecca0232e 100644 --- a/doc/plugins/aggregate.mdwn +++ b/doc/plugins/aggregate.mdwn @@ -1,10 +1,10 @@ -[[template id=plugin name=aggregate author="[[Joey]]"]] -[[tag type/useful]] +[[!template id=plugin name=aggregate author="[[Joey]]"]] +[[!tag type/useful]] This plugin allows content from other feeds to be aggregated into the wiki. -Aggregate a feed as follows +Aggregate a feed as follows: - \[[aggregate name="example blog" + \[[!aggregate name="example blog" dir="example" feedurl="http://example.com/index.rss" url="http://example.com/" updateinterval="15"]] @@ -13,12 +13,17 @@ more frequently than once every 15 minutes, and puts a page per post under the example/ directory in the wiki. You can then use ikiwiki's [[ikiwiki/blog]] support to create a blog of one or -more aggregated feeds. +more aggregated feeds. For example: + + \[[!inline pages="internal(example/*)"]] ## setup -Make sure that you have the [[html]] plugin enabled, as the created pages are -in html format. The [[meta]] and [[tag]] plugins are also recommended. The +New users of aggregate should enable the `aggregateinternal => 1` option in the +.setup file. If you don't do so, you will need to enable the [[html]] plugin +as well as aggregate itself, since feed entries will be stored as HTML. + +The [[meta]] and [[tag]] plugins are also recommended. The [[htmltidy]] plugin is suggested, since feeds can easily contain html problems, some of which tidy can fix. @@ -31,7 +36,7 @@ crontab entry: Alternatively, you can allow `ikiwiki.cgi` to trigger the aggregation. You should only need this if for some reason you cannot use cron, and instead want to use a service such as [WebCron](http://webcron.org). To enable -this, enable on `aggregate_webtrigger` in your setup file. The url to +this, turn on `aggregate_webtrigger` in your setup file. The url to visit is `http://whatever/ikiwiki.cgi?do=aggregate_webtrigger`. Anyone can visit the url to trigger an aggregation run, but it will only check each feed if its `updateinterval` has passed. @@ -59,9 +64,44 @@ directive: * `tag` - A tag to tag each post from the feed with. A good tag to use is the name of the feed. Can be repeated multiple times. The [[tag]] plugin must be enabled for this to work. -* `template` - Template to use for creating the html pages. Defaults to +* `template` - Template to use for creating the aggregated pages. Defaults to aggregatepost. Note that even if you are using subversion or another revision control system, pages created by aggregation will *not* be checked into revision control. + +## internal pages and `aggregateinternal` + +This plugin creates a page for each aggregated item. + +If the `aggregateinternal` option is enabled in the setup file (which is +recommended), aggregated pages are stored in the source directory with a +"._aggregated" extension. These pages cannot be edited by web users, and +do not generate first-class wiki pages. They can still be inlined into a +blog, but you have to use `internal` in [[PageSpecs|IkiWiki/PageSpec]], +like `internal(blog/*)`. + +For backward compatibility, the default is that these pages have the +".html" extension, and are first-class wiki pages -- each one generates +a separate HTML page in the output, and they can even be edited. + +That turns out to not be ideal for aggregated content, because publishing +files for each of those pages is a waste of disk space and CPU, and you +probably don't want to allow them to be edited. So, there is an alternative +method that can be used (and is recommended), turned on by the +`aggregateinternal` option in the setup file. + +If you are already using aggregate and want to enable `aggregateinternal`, +you should follow this process: + +1. Update all [[PageSpecs|ikiwiki/PageSpec]] that refer to the aggregated + pages -- such as those in inlines. Put "internal()" around globs + in those PageSpecs. For example, if the PageSpec was `foo/*`, it should + be changed to `internal(foo/*)`. This has to be done because internal + pages are not matched by regular globs. +2. Turn on `aggregateinternal` in the setup file. +3. Use [[ikiwiki-transition]] to rename all existing aggregated `.html` + files in the srcdir. The command to run is + `ikiwiki-transition aggregateinternal $setupfile`, +4. Refresh the wiki. (`ikiwiki -setup your.setup -refresh`) diff --git a/doc/plugins/write.mdwn b/doc/plugins/write.mdwn index 6b49ec58d..4dc55e302 100644 --- a/doc/plugins/write.mdwn +++ b/doc/plugins/write.mdwn @@ -412,12 +412,13 @@ Aborts with an error message. If the second parameter is passed, it is a function that is called after the error message is printed, to do any final cleanup. -Note that while any plugin can use this for a fatal error, plugins should -try to avoid dying on bad input when building a page, as that will halt -the entire wiki build and make the wiki unusable. So for example, if a -[[ikiwiki/PreProcessorDirective]] is passed bad parameters, it's better to -return an error message, which can appear on the wiki page, rather than -calling error(). +If called inside a preprocess hook, error() does not abort the entire +wiki build, but instead replaces the [[ikiwiki/PreProcessorDirective]] with +a version containing the error message. + +In other hooks, error() is a fatal error, so use with care. Try to avoid +dying on bad input when building a page, as that will halt +the entire wiki build and make the wiki unusable. #### `template($;@)` diff --git a/doc/plugins/write/tutorial.mdwn b/doc/plugins/write/tutorial.mdwn index 8b12fd183..94b72c763 100644 --- a/doc/plugins/write/tutorial.mdwn +++ b/doc/plugins/write/tutorial.mdwn @@ -169,7 +169,7 @@ be a guard on how high it will go. } my $num=$last{$page}++; if ($num > 25) { - return "[[fib will only calculate the first 25 numbers in the sequence]]"; + error "can only calculate the first 25 numbers in the sequence"; } return fib($num); } @@ -182,7 +182,7 @@ does for numbers less than 1. Or for any number that's not an integer. In either case, it will run forever. Here's one way to fix that: if (int($num) != $num || $num < 1) { - return "[[fib positive integers only, please]]"; + error "positive integers only, please"; } As these security problems have demonstrated, even a simple input from the diff --git a/doc/post-commit/discussion.mdwn b/doc/post-commit/discussion.mdwn index 3c2b264fb..08125d9ff 100644 --- a/doc/post-commit/discussion.mdwn +++ b/doc/post-commit/discussion.mdwn @@ -34,3 +34,10 @@ Regards. > notify => 1, > } > ], + + +Hello, I've setup ikiwiki with subversion. I can edit pages from web browser using CGI and, when I go to recentchanges, it shows that modification with "web" word. But, if I modify any .mdwn file, it gets updated in website but it doesn't show in recentchanges entry with "svn" word. If I run "svn ci -m changes", it shows in recentchanges correctly. + +So, I think I miss something, because I don't think I must run "svn add" or "svn commit" anytime I modify or create a wiki file. + +Thanks diff --git a/doc/rcs/git/discussion.mdwn b/doc/rcs/git/discussion.mdwn index 4c7df375a..2bb61c6a1 100644 --- a/doc/rcs/git/discussion.mdwn +++ b/doc/rcs/git/discussion.mdwn @@ -83,3 +83,11 @@ Thanks to gitte on #git on Freenode and of course joeyh. Have a look at [[rcs/de I think it would be a good thing if the various git pages where somehow unified. It seems to me that [[tips/laptop_wiki_with_git]] is currently not so different from [[git]]. Let us see what joeyh thinks about the new git pages, but if this level of detail is to go there, I think it could pretty much include (maybe as sub pages) the info in [[tips/laptop_wiki_with_git]] and [[tips/laptop_wiki_with_git_extended]] --[[DavidBremner]] # Does 'push' from the shallow clones work for you? git-clone and git-fetch explicitly state it doesn't... + +------- + +## Permissions for web users and local users editing and creating pages +What is the right permissions setup for a situation where both web and local users will be editing and creatingt pages? +My usage is this: I have a repository /srv/git/wiki.git chowned to me:apache with 775/664 permissions recursively (where 'me' is my account and the ikiwiki administrator), a /srv/www/ikisrc chowned to apache:apache, and a /srv/www/html/wiki chowned to apache:apache. As is, I can commit to the wiki.git repo (because it is owned by me) and web users can commit to it as well (because the group also has write access) what happens when I create a new page from either of those sources? For example, the apache user running ikiwiki.cgi would create /srv/www/ikisrc/something.mdwn, commit and push it to /srv/git/wiki.git, but that new object is owned by apache:apache. If I then try to commit a change to something.mdwn from a cloned repo sitting on my laptop, for example, will the commit not fail because apache created the files? + +Does that mean that apache:apache should just own everything, and I should only commit through that user (via git:// protocol only, maybe, or ssh as apache instead of myself)? For some reason, my head can't quite wrap itself around the whole permissions issue. Thanks. --mrled diff --git a/doc/rcs/mercurial.mdwn b/doc/rcs/mercurial.mdwn index 5eaae1997..b4baf07f4 100644 --- a/doc/rcs/mercurial.mdwn +++ b/doc/rcs/mercurial.mdwn @@ -2,7 +2,17 @@ system developed by Matt Mackall. Ikiwiki supports storing a wiki in a mercurial repository. -Ikiwiki can run as a post-update hook to update a wiki whenever commits +Ikiwiki can run as a `post-commit` and/or `incoming` hook to update a wiki whenever commits or remote pushes come in. When running as a [[cgi]] with Mercurial, ikiwiki automatically commits edited pages, and uses the Mercurial history to generate the [[RecentChanges]] page. + +Example for a `.hg/hgrc` file in `$SRCDIR`: + + [hooks] + post-commit = /home/abe/bin/rebuildwiki + incoming = /home/abe/bin/rebuildwiki + +Do not use `commit` or `precommit` hooks or ikiwiki will run into a dead lock when committing in `$SRCDIR` + +See also [[todo/mercurial|todo/mercurial]] diff --git a/doc/roadmap.mdwn b/doc/roadmap.mdwn index af46e162b..32752715d 100644 --- a/doc/roadmap.mdwn +++ b/doc/roadmap.mdwn @@ -42,7 +42,8 @@ backwards compatability. Still in the early planning stages, version 3.0 will be an opportunity to make significant transitions. -* Default to using prefix_directives. +* Default to using `prefix_directives`. +* Default to using `aggregateinternal`. ---- diff --git a/doc/style.css b/doc/style.css index 246da1ffc..0e3bfb3e6 100644 --- a/doc/style.css +++ b/doc/style.css @@ -35,12 +35,14 @@ padding: .2em .4em; } -.tags { +.pagefooter { clear: both; } +.tags { +} + #pageinfo { - clear: both; margin: 1em 0; border-top: 1px solid #000; } @@ -140,7 +142,6 @@ div.recentchanges { .pagedate, .pagelicense, .pagecopyright { - clear: both; font-style: italic; display: block; margin-top: 1em; diff --git a/doc/tips/blog_script.mdwn b/doc/tips/blog_script.mdwn index b0f5f14c1..1dfd71538 100644 --- a/doc/tips/blog_script.mdwn +++ b/doc/tips/blog_script.mdwn @@ -1,4 +1,4 @@ -I have a [blog](http://git.kitenet.net/?p=joey/home;a=blob_plain;f=bin/blog) +I have a [blog](http://git.kitenet.net/?p=joey/home.git;a=blob_plain;f=bin/blog) program that I use to write blog posts in a text editor. The first line I enter is used as the title, and it automatically comes up with a unique page name based on the title and handles all the details of posting to my blog. diff --git a/doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn b/doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn index 27d238ecd..b97c81efa 100644 --- a/doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn +++ b/doc/todo/Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename.mdwn @@ -75,5 +75,5 @@ a dedicated plugin, called `genealogictitle` or whatever, and : >> Well, it seems I once more designed a solution before clearly >> defining my problem... What I really need is more generic, can be ->> done as a plugin, and deserves its own todo item (yet to come), so +>> done as a plugin, and deserves its own [[todo|pedigree_plugin]], so >> I'm tagging this one wontfix^W [[done]]. I'm sorry. -- intrigeri diff --git a/doc/todo/Moving_Pages.mdwn b/doc/todo/Moving_Pages.mdwn index 2e0603ca7..38a5d3ad2 100644 --- a/doc/todo/Moving_Pages.mdwn +++ b/doc/todo/Moving_Pages.mdwn @@ -313,3 +313,134 @@ before it is moved? Bail, or shrug and proceed? <TMPL_IF NAME="RECENTCHANGESURL"> <li><a href="<TMPL_VAR RECENTCHANGESURL>">RecentChanges</a></li> </TMPL_IF> + +---- + +I'm going to try to run through a full analysis and design for moving and +deleting pages here. I want to make sure all cases are covered. --[[Joey]] + +## UI + +The UI I envision is to add "Rename" and "Delete" buttons to the file edit +page. Both next to the Save button, and also at the bottom of the attachment +management interface. + +The attachment(s) to rename or delete would be selected using the check boxes +and then the button applies to all of them. Deleting multiple attachments +in one go is fine; renaming multiple attachments in one go is ambiguous, +and it can just error out if more than one is selected for rename. +(Alternatively, it could allow moving them all to a different subdirectory.) + +The Delete buttons lead to a page to confirm the deletion(s). + +The Rename buttons lead to a page with a text edit box for editing the +page name. The title of the page is edited, not the actual filename. + +There will also be a optional comment field, so a commit message can be +written for the rename/delete. + +Note that there's an edge case concerning pages that have a "/" encoded +as part of their title. There's no way for a title edit box to +differentiate between that, and a "/" that is instended to refer to a +subdirectory to move the page to. Consequence is that "/" will always be +treated literally, as a subdir separator; it will not be possible to use +this interface to put an encoded "/" in a page's name. + +Once a page is renamed, ikiwiki will return to the page edit interface, +now for the renamed page. Any modifications that the user had made to the +textarea will be preserved. + +Similarly, when an attachment is renamed, or deleted, return to the page +edit interface (with the attachments displayed). + +When a page is deleted, redirect the user to the toplevel index. + +Note that this design, particularly the return to the edit interface after +rename, means that the rename button can *only* be put on the page edit ui. +It won't be possible to put it on the action bar or somewhere else. (It +would be possible to code up a different rename button that doesn't do +that, and use it elsewhere.) + +## SubPages + +When renaming `foo`, it probably makes sense to also rename +`foo/Discussion`. Should other SubPages in `foo/` also be renamed? I think +it's probably simplest to rename all of its SubPages too. + +When deleting `foo`, I don't think SubPages should be deleted. The +potential for mistakes and abuse is too large. + +## link fixups + +When renaming a page, it's desirable to keep links that point to it +working. Rather than use redirection pages, I think that all pages that +link to it should be modified to fix their links. + +In some cases, a redirection page will be wanted, to keep long-lived urls +working. Since the meta plugin supports creating such pages, and since they +won't always be needed, I think it will be simplest to just leave it up to +the user to create such a redirection page after renaming a page. + +## who can delete/rename what? + +The source page must be editable by the user to be deleted/renamed. +When renaming, the dest page must not already exist, and must be creatable +by the user, too. + +When deleting/renaming attachments, the `allowed_attachments` PageSpec +is checked too. + +## RCS + +Two new optional functions are added to the RCS interface: + +* `rcs_delete(file, message, rcstoken, user, ipaddr)` +* `rcs_rename(old, new, message, rcstoken, user, ipaddr)` + +The page move/rename code will check if these are not available, and error +out. + +Similar to `rcs_commit` both of these take a rcstoken, which is generated +by an earlier `rcs_prepedit`. + +## conflicts + +Cases that have to be dealt with: + +* Alice clicks "delete" button for a page; Bob makes a modification; + Alice confirms deletion. Ideally in this case, Alice should get an error + message that there's a conflict. +* Alice opens edit UI for a page; Bob makes a modification; Alice + clicks delete button and confirms deletion. Again here, Alice should get + a conflict error. Note that this means that the rcstoken should be + recorded when the edit UI is first opened, not when the delete button is + hit. +* Alice and Bob both try to delete a page at the same time. It's fine for + the second one to get a message that it no longer exists. Or just to + silently fail to delete the deleted page.. +* Alice deletes a page; Bob had edit window open for it, and saves + it afterwards. I think that Bob should win in this case; Alice can always + notice the page has been added back, and delete it again. +* Alice clicks "rename" button for a page; Bob makes a modification; + Alice confirms rename. This case seems easy, it should just rename the + modified page. +* Alice opens edit UI for a page; Bob makes a modification; Alice + clicks rename button and confirms rename. Seems same as previous case. +* Alice and Bob both try to rename a page at the same time (to probably + different names). Or one tries to delete, and the other to rename. + I think it's acceptible for the second one to get an error message that + the page no longer exists. +* Alice renames a page; Bob had edit window open for it, and saves + it afterwards, under old name. I think it's acceptible for Bob to succeed + in saving it under the old name in this case, though not ideal. +* Alice renames (or deletes) a page. In the meantime, Bob is uploading an + attachment to it, and finishes after the rename finishes. Is it + acceptible for the attachment to be saved under the old name? +* Alice starts creating a new page. In the meantime, Bob renames a + different page to that name. Alice should get an error message when + committing; and it should have conflict markers. Ie, this should work the + same as if Bob had edited the new page at the same time as Alice did. +* Bob starts renaming a page. In the meantime, Alice creates a new page + with the name he's renaming it to. Here Bob should get a error message + that he can't rename the page to an existing name. (A conflict resolution + edit would also be ok.) diff --git a/doc/todo/aggregate_to_internal_pages.mdwn b/doc/todo/aggregate_to_internal_pages.mdwn index 90b6e5f09..38427133f 100644 --- a/doc/todo/aggregate_to_internal_pages.mdwn +++ b/doc/todo/aggregate_to_internal_pages.mdwn @@ -51,4 +51,9 @@ change their pagespecs to use `internal()`. > to move the pages, and even, possibly update the pagespecs (not sure how > it could figure out which ones tho). --[[Joey]] -[[patch]] +> I've patched ikiwiki-transition to have an aggregateinternal mode. +> See my aggregateinternal branch, again. +> "ikiwiki-transition aggregateinternal $setupfile" moves the pages around, +> although it doesn't update the pagespecs (I wouldn't know how...) --[[smcv]] + +[[tag patch done]] diff --git a/doc/todo/applydiff_plugin.mdwn b/doc/todo/applydiff_plugin.mdwn new file mode 100644 index 000000000..d3eb9793b --- /dev/null +++ b/doc/todo/applydiff_plugin.mdwn @@ -0,0 +1,56 @@ +[[!tag wishlist]] + +[[!toc ]] + +Summary +======= + +Allow a user to apply an arbitrary diff, in order to modify a given +page (or, even better, a given set of pages). + +Rationale +========= + +To edit intensively an ikiwiki-powered website can quickly get +annoying for anybody meeting enough of the following conditions: + +* living mainly offline +* having no commit access to the RCS backing up the site (BTW, please + note I can send my ssh public key to anyone who asks for, free of + charges) +* hating web-browsers and despising textareas +* loving in his/her own preferred `$EDITOR` + +... and when one gathers all of these defaults, she/he is on her/his +way to get mad. Soon. + +Before it's too late, some dareful ones dream of the following +playflow: + +1. Go online. +1. Update local working copy. +1. Go offline. +1. `$EDITOR` : write, report, answer, propose +1. Go online. +1. Update local working copy (and optionally fix conflicts between + local changes and remote ones). +1. Generate a diff. +1. Use a web-browser to paste the diffs (or better, upload them into + a form) somewhere on the wiki, and click "Apply". +1. git pull (to reflect locally the fact that the diff has been + applied to the remote repo) +1. Go offline. + +(This is for sure a bit theoretical: the ones who dream of this would +actually insert various steps about branching, merging and rebasing +random stuff.) + +Design +====== + +This has to be thought very carefully, to avoid one to apply diffs to +pages he/she is not allowed to edit. Restricting a given diff to +modify only *one* page may be easier. + +Implementation +============== diff --git a/doc/todo/color_plugin.mdwn b/doc/todo/color_plugin.mdwn new file mode 100644 index 000000000..8efd4375e --- /dev/null +++ b/doc/todo/color_plugin.mdwn @@ -0,0 +1,36 @@ +Recently I've wanted to colour some piece of text on my Ikiwiki page. +It seems that Markdown can do it only using HTML tags, so I used +`<span class="color">foo bar baz</span>`. + +However, in my opinion mixing Markdown syntax and HTML tags is rather ugly, +so maybe we should create a new color plugin to add more color to Ikiwiki ;) +I know that another Wikis have similar plugin, for example +[WikiDot](http://www.wikidot.com/). + +I've noticed that htmlscrubber plugin strips `style` attribute, because of +security, so probably we need to use `class` attribute of HTML. But then +we have to customize our `local.css` file to add all color we want to use. +It's not as easy in usage like color name or definition as plugin argument, +but I don't have a better idea right now. + +What do you think about it? --[[Paweł|ptecza]] + +> Making a plugin preserve style attributes can be done, it just has to add +> them after the sanitize step, which strips them. The general method is +> adding placeholders first, and replacing them with the real html later. +> +> The hard thing to me seems to be finding a syntax that is better than a +> `<span>`. A preprocessor directive is not really any less ugly than html +> tags, though at least it could play nicely with nested markdown: --[[Joey]] +> +> \[[color red,green """ +> Xmas-colored markdown here +> """]] + +>> I'm glad you like that idea. In my opinion your syntax looks good. +>> Out of curiosity, why did you used 2 colors in your example? What is HTML +>> result for it? ;) + +>> I can try to create that plugin, if you are too busy now. I'm not Perl +>> hacker, but I wrote a lot of Perl scripts in my life and color plugin +>> doesn't seem to be very hard task. --[[Paweł|ptecza]] diff --git a/doc/todo/darcs.mdwn b/doc/todo/darcs.mdwn index c31ce105c..84c99daba 100644 --- a/doc/todo/darcs.mdwn +++ b/doc/todo/darcs.mdwn @@ -480,4 +480,8 @@ It is in a [darcs repository](http://joyful.com/darcsweb/darcsweb.cgi?r=ikiwiki- > conflicts and return a page with conflict markers for the user to fix > the conflict. +I have addressed the recentchanges bit, you can find my hacked up darcs.pm at <http://web.mornfall.net/stuff/web-root/IkiWiki/Rcs/darcs.pm>. + +It's got couple of FIXMEs, and a very site-specific filter for recentchanges. Not sure how to do that better though. I will eventually add web commits, probably of my own (and mention it here). + [[tag patch]] diff --git a/doc/todo/else_parameter_for_map_plugin.mdwn b/doc/todo/else_parameter_for_map_plugin.mdwn new file mode 100644 index 000000000..9508e0855 --- /dev/null +++ b/doc/todo/else_parameter_for_map_plugin.mdwn @@ -0,0 +1,9 @@ +[[!tag patch]] + +[[plugins/map]] (and I) could benefit from a bonus parameter: + + else="Display this if no page matches the PageSpec" + +This was quite simple, so I implemented this (branch "map" in my +ikiwiki repo, see my user page for the up-to-date URL). Not patched the +documentation yet, I'm waiting for feedback first, but I'll do it for sure. -- [[intrigeri]] diff --git a/doc/todo/mercurial.mdwn b/doc/todo/mercurial.mdwn index 0a1098f70..77b538c02 100644 --- a/doc/todo/mercurial.mdwn +++ b/doc/todo/mercurial.mdwn @@ -1,5 +1,3 @@ -* Need to get post commit hook working (or an example of how to use it.) - * See below. --[[bma]] * rcs_notify is not implemented (not needed in this branch --[[Joey]]) * Is the code sufficiently robust? It just warns when mercurial fails. * When rcs_commit is called with a $user that is an openid, it will be diff --git a/doc/todo/pedigree_plugin.mdwn b/doc/todo/pedigree_plugin.mdwn new file mode 100644 index 000000000..9504a964b --- /dev/null +++ b/doc/todo/pedigree_plugin.mdwn @@ -0,0 +1,182 @@ +After realizing (thanks to +[[Allow_TITLE_to_include_part_of_the_path_in_addition_to_the_basename]]) +that I needed some kind of "parentlinks on steroids", I wrote a new +plugin, called pedigree. + +This plugin provides a bunch of loops that one can use in his/her +`HTML::Template`'s to iterate over all or a subset of a page's +parents. Inside these loops, half a dozen variables are made +available, in addition to `PAGE` and `URL` that are already provided +by parentlinks. + +Amongst many possibilities, one can e.g. simply use this plugin to +give every parent link a different `class=` attribute, depending +either on its depth in the path leading to the current page, or on its +distance to it. + +The code and documentation (including simple and complex usage +examples) are in the 'pedigree' Git branch in this repo: + + git://repo.or.cz/ikiwiki/intrigeri.git + +Seems there is also a [gitweb](http://repo.or.cz/w/ikiwiki/intrigeri.git). + +> Ok, I'll take a look. BTW, could you allow user joey on repo.or.cz +> push access to the main ikiwiki repo you set up there? --[[Joey]] + +>> I did not. The main ikiwiki repo on repo.or.cz seems to have been +>> been setup by johannes.schindelin@gmx.de ; mine is what they call +>> a "fork" (but it's not, obviously). -- intrigeri + +Any opinions on the idea/design/implementation? + +> Seems that there should be a more generic way to do `PEDIGREE_BUT_ROOT` +> and `PEDIGREE_BUT_TWO_OLDEST` (also `is_second_ancestor`, +> `is_grand_mother` etc). One way would be to include in `PEDIGREE` +> a set of values like `depth_1`, `depth_2`, etc. The one corresponding +> to the `absdepth` would be true. This would allow a template like this: + + <TMPL_LOOP NAME="PEDIGREE"> + <TMPL_IF NAME="depth_1"> + </TMPL_ELSE> + <TMPL_IF NAME="depth_2"> + </TMPL_ELSE> + <TMPL_VAR PAGE> /* only showing pages 2 levels deep */ + </TMPL_IF> + </TMPL_IF> + </TMPL_LOOP> + +> The only missing information would be `reldepth`, but in the above +> example the author of that template knows that it's `absdepth - 1` +> (Things would be a lot nicer if `HTML::Template` had equality tests!) +> +> Since this would make it more generic and also fix your one documented +> bug, I can see no reason not to do it. ;-) --[[Joey]] + +>> Thanks for your comments. I'll answer soon. (Grrr, I really +>> need to find a way to edit this wiki offline, every minute +>> online costs bucks to me, my old modem gently weeps, +>> and I hate webbrowsers.) -- intrigeri + +>>> Well, I maybe didn't get your idea properly; I may be missing +>>> something obvious, but: + +>>> * I don't understand how this would replace `is_grand_mother`. As a template +>>> writer, I don't know, given an absolute array index (and this is the only +>>> piece of data your solution gives me), if it will be e.g. the before-last +>>> (how do I say this in correct English?) element of an array whose +>>> (variable) size is unknown to me. +>>> * Knowing that `reldepth`'s value is, in a given loop, always equal to +>>> `absdepth - 1` is of little use to me (as a template writer): how do I use +>>> this piece of information programmatically in my templates, if I want all +>>> links with `reldepth==2` to be given the same style? I guess some bits of +>>> Javascript might do the trick, but if it's getting so complicated, I'll +>>> just style my parentlinks another way. + +>>>> Perhaps I misunderstood what `is_grand_mother` is supposed to do. The +>>>> docs were not very clear to me. If it's supposed to be 2 down from +>>>> the page, (and not from the root), this could be achieved by reversing +>>>> the `depth_n` variables. So the page gets `depth_1` set, its parent gets +>>>> `depth_2` set, etc. If you want to be able to include/exclude +>>>> from both ends, you could also have a `height_n` that is 1 for the +>>>> root, and counts upwards. --[[Joey]] + +>>> In my understanding, your suggestion gives us little more than can already +>>> be achieved anyway with `HTML::Template`'s `loop_context_vars` (i.e. +>>> `__first__`, `__last__` and `__counter__`). The only added bonus is doing +>>> custom stuff for an arbitrary element in the loop, chosen by its absolute +>>> depth. Please correct me if needed. + +>>> (Intermezzo: in the meantime, to suit my personal real-world needs, I added +>>> a `DISTANCE` loop-variable. Quoting the documentation, it's "thedistance, +>>> expressed in path elements, from the current page to the current path +>>> element; e.g. this is 1 for the current page's mother, 2 for its +>>> grand-mother, etc.".) + +>>> Anyway, your comments have made me think of other ways to simplify a bit +>>> this plugin, which admittedly provides too much overlapping functionality. +>>> Bellow is my reasoning. + +>>> In one of my own real world examples, my two main use cases are : + +>>> * the "full-blown example" provided in the documentation (i.e. +>>> displaying every parent but mother and grand'ma as a group, and giving +>>> every of these two last ones their dedicated div); +>>> * skipping the two oldest parents, and inside what's left, displaying the +>>> three youngest parents (i.e. mother, grand'ma and grand'grand'ma), each +>>> one with a dedicated style; + +>>> Both of these can be achieved by combining `PEDIGREE`, `DISTANCE`, and some +>>> CSS tricks to hide some parts of the list. `IS_MOTHER` and +>>> `IS_GRAND_MOTHER`, as well as `PEDIGREE_BUT_TWO_OLDEST`, would be convenient +>>> shortcuts, but I do not formally need them. + +>>> So... it seems things can be simplified greatly: + +>>> * I initially added `RELDEPTH` for completeness, but I'm not sure anyone +>>> would use it. Let's give it up. +>>> * Once `RELDEPTH` is lost (modulo Git tendencies to preserve history), the +>>> known bug is gone as well, and `PEDIGREE_BUT_ROOT` and +>>> `PEDIGREE_BUT_TWO_OLDEST` are now only convenient shortcuts functions; +>>> they could as well disappear, if you prefer to. + +>>> It appears then that I'd be personally happy with the single `PEDIGREE` loop +>>> (renamed to `PARENTLINKS`), providing only `PAGE`, `URL`, `ABSDEPTH` (maybe +>>> renamed to `DEPTH`), and `DISTANCE`. This would make my templates a bit more +>>> complicated to write and read, but would also keep the plugin's code to the +>>> bare minimum. Let's say it is my up-to-date proposal. (Well, if the various +>>> shortcuts don't really annoy you, I'd be glad to keep them ;) + +>>>> This sounds fairly similar to what I just described above. (I called +>>>> DISTANCE "height".) I don't know about the CSS tricks; seems like if +>>>> `DEPTH_n` and `DISTANCE_n` are provided, you can test for them inside +>>>> the loop using HTML::Template's lame testing, and isolate any page or +>>>> range of pages. --[[Joey]] + +>>>>> Ok, I definitely like this idea, as an effective and generic +>>>>> page-range selection tool; this seems the way to go to me. + +>>>>> But if you discard the `DEPTH` and `HEIGHT` +>>>>> counters, we lack a way to **style**, for example, every parent link +>>>>> depending on its depth or height; one can do this for arbitrary +>>>>> parents (chosen by their height or depth), but *not* for *any* parent, +>>>>> since there is no way to express, with HTML::Template, something like +>>>>> "display the name of the only `DEPTH_n` variable that is currently +>>>>> true". So I am in favor of keeping the `DEPTH` and `HEIGHT` counters, +>>>>> to allow constructs like: + + <TMPL_LOOP NAME="PARENTLINKS"> + <a href="<TMPL_VAR NAME="URL">" class="parentdistance<TMPL_VAR NAME="DISTANCE">"> + <TMPL_VAR NAME="PAGE"> + </a> / + </TMPL_LOOP> + +>>>>> This seems to me a nice functionality bonus, and should not +>>>>> imply too bloated code. I'm thus going to rewrite the plugin +>>>>> with only `PEDIGREE`, `DEPTH`, `HEIGHT`, `DEPTH_n` and +>>>>> `HEIGHT_n`. -- intrigeri + +>>>>>> Done, and pushed in my pedigree branch. Update: I've also done and +>>>>>> pushed two commits that rename the plugin and replace +>>>>>> the core parentlinks with this one. --[[intrigeri]] + +(I'll try never to rebase this branch, but writing this plugin has +been a pretext for me to start learning Git, so...) + +To finish with, it seems no plugin bundled with ikiwiki uses the current +parentlinks implementation, so one could event think of moving it from the +core to this plugin (which should then be enabled by default, since the +default templates do use parentlinks ;). + +> I think that moving parentlinks out to a plugin is a good idea. +> However, if it's done, I think the plugin should be named parentlinks, +> and should continue to use the same template variables as are used now, +> to avoid needing to change custom templates. Pedigree is a quite nice +> name, but renaming it to parentlinks seems to be the way to go to me. +> --[[Joey]] + +>> Agreed. -- intrigeri + +>> Just commited a testsuite for this plugin, BTW. It's nearly twice +>> big as the plugin itself, I'm wondering... -- intrigeri + diff --git a/doc/users/intrigeri.mdwn b/doc/users/intrigeri.mdwn new file mode 100644 index 000000000..681b3573c --- /dev/null +++ b/doc/users/intrigeri.mdwn @@ -0,0 +1,4 @@ +intrigeri AT boum.org, already loving ikiwiki. + +* [gnupg key](http://gaffer.boum.org/intrigeri/intrigeri.asc) +* Git repository ([gitweb](http://repo.or.cz/w/ikiwiki/intrigeri.git)) with various ikiwiki {feature, bugfix}-branches : `git://repo.or.cz/ikiwiki/intrigeri.git` diff --git a/docwiki.setup b/docwiki.setup index 0a6a86678..ba3dd680d 100644 --- a/docwiki.setup +++ b/docwiki.setup @@ -9,7 +9,7 @@ use IkiWiki::Setup::Standard { underlaydir => "underlays/basewiki", wrappers => [], discussion => 0, - exclude => qr/\/discussion/, + exclude => qr/\/discussion|bugs\/*|todo\/*/, locale => '', verbose => 1, syslog => 0, diff --git a/ikiwiki-transition b/ikiwiki-transition index ce081fe63..3e2c89bf9 100755 --- a/ikiwiki-transition +++ b/ikiwiki-transition @@ -99,12 +99,25 @@ sub hashpassword { } } +sub aggregateinternal { + require IkiWiki::Setup; + require IkiWiki::Plugin::aggregate; + + %config = (IkiWiki::defaultconfig(), IkiWiki::Setup::load(shift)); + IkiWiki::checkconfig(); + + IkiWiki::Plugin::aggregate::migrate_to_internal(); + + print "... now add aggregateinternal => 1 to your .setup file\n"; +} + sub usage { print STDERR "Usage: ikiwiki-transition type ...\n"; print STDERR "Currently supported transition subcommands:\n"; print STDERR " prefix_directives file\n"; print STDERR " indexdb srcdir\n"; print STDERR " hashpassword srcdir\n"; + print STDERR " aggregateinternal setupfile\n"; exit 1; } @@ -120,6 +133,9 @@ elsif ($mode eq 'hashpassword') { elsif ($mode eq 'indexdb') { indexdb(@ARGV); } +elsif ($mode eq 'aggregateinternal') { + aggregateinternal(@ARGV); +} else { usage(); } diff --git a/po/ikiwiki.pot b/po/ikiwiki.pot index f94f5bdd3..71cddfdd0 100644 --- a/po/ikiwiki.pot +++ b/po/ikiwiki.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2008-07-12 23:07-0400\n" +"POT-Creation-Date: 2008-07-13 15:04-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" @@ -71,7 +71,7 @@ msgstr "" msgid "You are banned." msgstr "" -#: ../IkiWiki/CGI.pm:758 ../IkiWiki/CGI.pm:759 +#: ../IkiWiki/CGI.pm:758 ../IkiWiki/CGI.pm:759 ../IkiWiki.pm:782 msgid "Error" msgstr "" @@ -194,7 +194,7 @@ msgstr "" msgid "There are no broken links!" msgstr "" -#: ../IkiWiki/Plugin/conditional.pm:18 +#: ../IkiWiki/Plugin/conditional.pm:18 ../IkiWiki/Plugin/testpagespec.pm:17 #, perl-format msgid "%s parameter is required" msgstr "" @@ -212,7 +212,7 @@ msgstr "" msgid "edittemplate %s registered for %s" msgstr "" -#: ../IkiWiki/Plugin/edittemplate.pm:111 +#: ../IkiWiki/Plugin/edittemplate.pm:113 msgid "failed to process" msgstr "" @@ -233,7 +233,7 @@ msgid "prog not a valid graphviz program" msgstr "" #: ../IkiWiki/Plugin/img.pm:49 -msgid "Image::Magick not installed" +msgid "Image::Magick is not installed" msgstr "" #: ../IkiWiki/Plugin/img.pm:56 @@ -287,7 +287,7 @@ msgstr "" msgid "RPC::XML::Client not found, not pinging" msgstr "" -#: ../IkiWiki/Plugin/linkmap.pm:98 +#: ../IkiWiki/Plugin/linkmap.pm:97 msgid "failed to run dot" msgstr "" @@ -408,7 +408,7 @@ msgid "polygen not installed" msgstr "" #: ../IkiWiki/Plugin/polygen.pm:51 -msgid "polygen failed" +msgid "command failed" msgstr "" #: ../IkiWiki/Plugin/postsparkline.pm:32 @@ -612,47 +612,47 @@ msgstr "" msgid "getctime not implemented" msgstr "" -#: ../IkiWiki/Render.pm:286 ../IkiWiki/Render.pm:307 +#: ../IkiWiki/Render.pm:290 ../IkiWiki/Render.pm:311 #, perl-format msgid "skipping bad filename %s" msgstr "" -#: ../IkiWiki/Render.pm:361 +#: ../IkiWiki/Render.pm:365 #, perl-format msgid "removing old page %s" msgstr "" -#: ../IkiWiki/Render.pm:401 +#: ../IkiWiki/Render.pm:405 #, perl-format msgid "scanning %s" msgstr "" -#: ../IkiWiki/Render.pm:406 +#: ../IkiWiki/Render.pm:410 #, perl-format msgid "rendering %s" msgstr "" -#: ../IkiWiki/Render.pm:427 +#: ../IkiWiki/Render.pm:431 #, perl-format msgid "rendering %s, which links to %s" msgstr "" -#: ../IkiWiki/Render.pm:448 +#: ../IkiWiki/Render.pm:452 #, perl-format msgid "rendering %s, which depends on %s" msgstr "" -#: ../IkiWiki/Render.pm:487 +#: ../IkiWiki/Render.pm:491 #, perl-format msgid "rendering %s, to update its backlinks" msgstr "" -#: ../IkiWiki/Render.pm:499 +#: ../IkiWiki/Render.pm:503 #, perl-format msgid "removing %s, no longer rendered by %s" msgstr "" -#: ../IkiWiki/Render.pm:523 +#: ../IkiWiki/Render.pm:527 #, perl-format msgid "ikiwiki: cannot render %s" msgstr "" @@ -729,6 +729,6 @@ msgstr "" msgid "%s preprocessing loop detected on %s at depth %i" msgstr "" -#: ../IkiWiki.pm:1203 +#: ../IkiWiki.pm:1212 msgid "yes" msgstr "" @@ -6,7 +6,7 @@ use Test::More; my @pages; BEGIN { - @pages=qw(index todo features news plugins/map security); + @pages=qw(index features news plugins/map security); if (! -x "/usr/bin/validate") { plan skip_all => "/usr/bin/validate html validator not present"; } diff --git a/templates/inlinepage.tmpl b/templates/inlinepage.tmpl index 71d57b008..ffcb897a8 100644 --- a/templates/inlinepage.tmpl +++ b/templates/inlinepage.tmpl @@ -1,4 +1,7 @@ <div class="inlinepage"> + +<div class="inlineheader"> + <TMPL_IF NAME="AUTHOR"> <span class="author"> <TMPL_IF NAME="AUTHORURL"> @@ -15,7 +18,14 @@ <a href="<TMPL_VAR PAGEURL>"><TMPL_VAR TITLE></a> </TMPL_IF> </span> + +</div><!--.inlineheader--> + +<div class="inlinecontent"> <TMPL_VAR CONTENT> +</div><!--.inlinecontent--> + +<div class="inlinefooter"> <span class="pagedate"> Posted <TMPL_VAR CTIME> @@ -52,7 +62,9 @@ License: <TMPL_VAR LICENSE> <li><TMPL_VAR DISCUSSIONLINK></li> </TMPL_IF> </ul> -</div> +</div><!--.actions--> </TMPL_IF> -</div> +</div><!--.inlinefooter--> + +</div><!--.inlinepage--> diff --git a/templates/page.tmpl b/templates/page.tmpl index 166f3c560..f2f9c34cc 100644 --- a/templates/page.tmpl +++ b/templates/page.tmpl @@ -17,13 +17,18 @@ </head> <body> +<div class="pageheader"> <div class="header"> <span> +<span class="parentlinks"> <TMPL_LOOP NAME="PARENTLINKS"> <a href="<TMPL_VAR NAME=URL>"><TMPL_VAR NAME=PAGE></a>/ </TMPL_LOOP> +</span> +<span class="title"> <TMPL_VAR TITLE> </span> +</span><!--.header--> <TMPL_IF NAME="SEARCHFORM"> <TMPL_VAR SEARCHFORM> </TMPL_IF> @@ -50,6 +55,7 @@ </ul> </div> </TMPL_IF> +</div> <!-- .pageheader --> <TMPL_IF SIDEBAR> <div id="sidebar"> @@ -61,7 +67,7 @@ <TMPL_VAR CONTENT> </div> -<div id="footer"> +<div id="footer" class="pagefooter"> <div id="pageinfo"> <TMPL_IF NAME="TAGS"> @@ -88,7 +94,7 @@ Links: </span> </span> </TMPL_IF> -</div> +</div><!-- #backlinks --> </TMPL_IF> <TMPL_IF COPYRIGHT> @@ -110,10 +116,10 @@ Last edited <TMPL_VAR NAME=MTIME> <!-- Created <TMPL_VAR NAME=CTIME> --> </div> -</div> +</div><!-- #pageinfo --> <TMPL_IF EXTRAFOOTER><TMPL_VAR EXTRAFOOTER></TMPL_IF> <!-- from <TMPL_VAR NAME=WIKINAME> --> -</div> +</div><!-- .pagefooter #footer --> </body> </html> |