diff options
author | Simon McVittie <smcv@debian.org> | 2012-03-18 15:31:41 +0000 |
---|---|---|
committer | Simon McVittie <smcv@debian.org> | 2012-03-18 15:31:41 +0000 |
commit | 4e54fa1144065b7ff99e88e6c61ff1fdcf6175c9 (patch) | |
tree | 6759b80b8722ea532385c9a3ccc74897b784967d /IkiWiki/Plugin | |
parent | d70ba7cff3fc6cc78ea2f8eb0713212478ab6ba7 (diff) | |
parent | 0a9bb3edc2a9819ba87de1b6e57155120b6aba44 (diff) | |
download | ikiwiki-4e54fa1144065b7ff99e88e6c61ff1fdcf6175c9.tar ikiwiki-4e54fa1144065b7ff99e88e6c61ff1fdcf6175c9.tar.gz |
Merge tag '3.20120202' into trail3-integrated
Diffstat (limited to 'IkiWiki/Plugin')
-rw-r--r-- | IkiWiki/Plugin/attachment.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/calendar.pm | 15 | ||||
-rw-r--r--[-rwxr-xr-x] | IkiWiki/Plugin/comments.pm | 3 | ||||
-rw-r--r-- | IkiWiki/Plugin/cvs.pm | 168 | ||||
-rw-r--r-- | IkiWiki/Plugin/editpage.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/graphviz.pm | 114 | ||||
-rw-r--r-- | IkiWiki/Plugin/highlight.pm | 2 | ||||
-rw-r--r-- | IkiWiki/Plugin/img.pm | 8 | ||||
-rw-r--r-- | IkiWiki/Plugin/mdwn.pm | 26 | ||||
-rw-r--r-- | IkiWiki/Plugin/recentchangesdiff.pm | 12 | ||||
-rw-r--r-- | IkiWiki/Plugin/tag.pm | 2 |
11 files changed, 229 insertions, 125 deletions
diff --git a/IkiWiki/Plugin/attachment.pm b/IkiWiki/Plugin/attachment.pm index fd4096edf..5a180cd5c 100644 --- a/IkiWiki/Plugin/attachment.pm +++ b/IkiWiki/Plugin/attachment.pm @@ -272,6 +272,7 @@ sub attachments_save { my @attachments; my $dir=attachment_holding_location($form->field('page')); foreach my $filename (glob("$dir/*")) { + $filename=Encode::decode_utf8($filename); next unless -f $filename; my $destdir=$config{srcdir}."/". linkpage(IkiWiki::possibly_foolish_untaint( @@ -345,6 +346,7 @@ sub attachment_list ($) { my $dir=attachment_holding_location($page); my $heldmsg=gettext("this attachment is not yet saved"); foreach my $file (glob("$dir/*")) { + $file=Encode::decode_utf8($file); next unless -f $file; my $base=IkiWiki::basename($file); my $f=$loc.$base; diff --git a/IkiWiki/Plugin/calendar.pm b/IkiWiki/Plugin/calendar.pm index c7d2b7c01..fc497b3c7 100644 --- a/IkiWiki/Plugin/calendar.pm +++ b/IkiWiki/Plugin/calendar.pm @@ -22,7 +22,6 @@ use warnings; use strict; use IkiWiki 3.00; use Time::Local; -use POSIX (); my $time=time; my @now=localtime($time); @@ -123,10 +122,10 @@ sub format_month (@) { } # Find out month names for this, next, and previous months - my $monthabbrev=POSIX::strftime("%b", @monthstart); - my $monthname=POSIX::strftime("%B", @monthstart); - my $pmonthname=POSIX::strftime("%B", localtime(timelocal(0,0,0,1,$pmonth-1,$pyear-1900))); - my $nmonthname=POSIX::strftime("%B", localtime(timelocal(0,0,0,1,$nmonth-1,$nyear-1900))); + my $monthabbrev=strftime_utf8("%b", @monthstart); + my $monthname=strftime_utf8("%B", @monthstart); + my $pmonthname=strftime_utf8("%B", localtime(timelocal(0,0,0,1,$pmonth-1,$pyear-1900))); + my $nmonthname=strftime_utf8("%B", localtime(timelocal(0,0,0,1,$nmonth-1,$nyear-1900))); my $archivebase = 'archives'; $archivebase = $config{archivebase} if defined $config{archivebase}; @@ -182,7 +181,7 @@ EOF my %dowabbr; for my $dow ($week_start_day..$week_start_day+6) { my @day=localtime(timelocal(0,0,0,$start_day++,$params{month}-1,$params{year}-1900)); - my $downame = POSIX::strftime("%A", @day); + my $downame = strftime_utf8("%A", @day); my $dowabbr = substr($downame, 0, 1); $downame{$dow % 7}=$downame; $dowabbr{$dow % 7}=$dowabbr; @@ -329,8 +328,8 @@ EOF for (my $month = 1; $month <= 12; $month++) { my @day=localtime(timelocal(0,0,0,15,$month-1,$params{year}-1900)); my $murl; - my $monthname = POSIX::strftime("%B", @day); - my $monthabbr = POSIX::strftime("%b", @day); + my $monthname = strftime_utf8("%B", @day); + my $monthabbr = strftime_utf8("%b", @day); $calendar.=qq{\t<tr>\n} if ($month % $params{months_per_row} == 1); my $tag; my $mtag=sprintf("%02d", $month); diff --git a/IkiWiki/Plugin/comments.pm b/IkiWiki/Plugin/comments.pm index 3ad2a0e13..91a482ed6 100755..100644 --- a/IkiWiki/Plugin/comments.pm +++ b/IkiWiki/Plugin/comments.pm @@ -9,7 +9,6 @@ use warnings; use strict; use IkiWiki 3.00; use Encode; -use POSIX qw(strftime); use constant PREVIEW => "Preview"; use constant POST_COMMENT => "Post comment"; @@ -460,7 +459,7 @@ sub editcomment ($$) { } $content .= " subject=\"$subject\"\n"; - $content .= " date=\"" . decode_utf8(strftime('%Y-%m-%dT%H:%M:%SZ', gmtime)) . "\"\n"; + $content .= " date=\"" . strftime_utf8('%Y-%m-%dT%H:%M:%SZ', gmtime) . "\"\n"; my $editcontent = $form->field('editcontent'); $editcontent="" if ! defined $editcontent; diff --git a/IkiWiki/Plugin/cvs.pm b/IkiWiki/Plugin/cvs.pm index 71566d212..0a6cbfaf6 100644 --- a/IkiWiki/Plugin/cvs.pm +++ b/IkiWiki/Plugin/cvs.pm @@ -35,10 +35,14 @@ use IkiWiki; use File::chdir; + +# GENERAL PLUGIN API CALLS + sub import { - hook(type => "genwrapper", id => "cvs", call => \&genwrapper); hook(type => "checkconfig", id => "cvs", call => \&checkconfig); hook(type => "getsetup", id => "cvs", call => \&getsetup); + hook(type => "genwrapper", id => "cvs", call => \&genwrapper); + hook(type => "rcs", id => "rcs_update", call => \&rcs_update); hook(type => "rcs", id => "rcs_prepedit", call => \&rcs_prepedit); hook(type => "rcs", id => "rcs_commit", call => \&rcs_commit); @@ -52,17 +56,6 @@ sub import { hook(type => "rcs", id => "rcs_getmtime", call => \&rcs_getmtime); } -sub genwrapper () { - return <<EOF; - { - int j; - for (j = 1; j < argc; j++) - if (strstr(argv[j], "New directory") != NULL) - exit(0); - } -EOF -} - sub checkconfig () { if (! defined $config{cvspath}) { $config{cvspath}="ikiwiki"; @@ -132,39 +125,22 @@ sub getsetup () { }, } -sub cvs_info ($$) { - my $field=shift; - my $file=shift; - - local $CWD = $config{srcdir}; - - my $info=`cvs status $file`; - my ($ret)=$info=~/^\s*$field:\s*(\S+)/m; - return $ret; +sub genwrapper () { + return <<EOF; + { + int j; + for (j = 1; j < argc; j++) + if (strstr(argv[j], "New directory") != NULL) + exit(0); + } +EOF } -sub cvs_runcvs(@) { - my @cmd = @_; - unshift @cmd, 'cvs', '-Q'; - - local $CWD = $config{srcdir}; - - open(my $savedout, ">&STDOUT"); - open(STDOUT, ">", "/dev/null"); - my $ret = system(@cmd); - open(STDOUT, ">&", $savedout); - return ($ret == 0) ? 1 : 0; -} - -sub cvs_is_controlling { - my $dir=shift; - $dir=$config{srcdir} unless defined($dir); - return (-d "$dir/CVS") ? 1 : 0; -} +# VCS PLUGIN API CALLS sub rcs_update () { - return unless cvs_is_controlling; + return unless cvs_is_controlling(); cvs_runcvs('update', '-dP'); } @@ -175,7 +151,7 @@ sub rcs_prepedit ($) { # The file is relative to the srcdir. my $file=shift; - return unless cvs_is_controlling; + return unless cvs_is_controlling(); # For cvs, return the revision of the file when # editing begins. @@ -183,31 +159,13 @@ sub rcs_prepedit ($) { return defined $rev ? $rev : ""; } -sub commitmessage (@) { - my %params=@_; - - if (defined $params{session}) { - if (defined $params{session}->param("name")) { - return "web commit by ". - $params{session}->param("name"). - (length $params{message} ? ": $params{message}" : ""); - } - elsif (defined $params{session}->remote_addr()) { - return "web commit from ". - $params{session}->remote_addr(). - (length $params{message} ? ": $params{message}" : ""); - } - } - return $params{message}; -} - sub rcs_commit (@) { # Tries to commit the page; returns undef on _success_ and # a version of the page with the rcs's conflict markers on failure. # The file is relative to the srcdir. my %params=@_; - return unless cvs_is_controlling; + return unless cvs_is_controlling(); # Check to see if the page has been changed by someone # else since rcs_prepedit was called. @@ -250,9 +208,6 @@ sub rcs_add ($) { my $parent=IkiWiki::dirname($file); my @files_to_add = ($file); - eval q{use File::MimeInfo}; - error($@) if $@; - until ((length($parent) == 0) || cvs_is_controlling("$config{srcdir}/$parent")){ push @files_to_add, $parent; $parent = IkiWiki::dirname($parent); @@ -261,15 +216,8 @@ sub rcs_add ($) { while ($file = pop @files_to_add) { if (@files_to_add == 0) { # file - my $filemime = File::MimeInfo::default($file); - if (defined($filemime) && $filemime eq 'text/plain') { - cvs_runcvs('add', $file) || - warn("cvs add $file failed\n"); - } - else { - cvs_runcvs('add', '-kb', $file) || - warn("cvs add binary $file failed\n"); - } + cvs_runcvs('add', cvs_keyword_subst_args($file)) || + warn("cvs add $file failed\n"); } else { # directory @@ -283,7 +231,7 @@ sub rcs_remove ($) { # filename is relative to the root of the srcdir my $file=shift; - return unless cvs_is_controlling; + return unless cvs_is_controlling(); cvs_runcvs('rm', '-f', $file) || warn("cvs rm $file failed\n"); @@ -293,7 +241,7 @@ sub rcs_rename ($$) { # filenames relative to the root of the srcdir my ($src, $dest)=@_; - return unless cvs_is_controlling; + return unless cvs_is_controlling(); local $CWD = $config{srcdir}; @@ -309,7 +257,7 @@ sub rcs_recentchanges ($) { my $num = shift; my @ret; - return unless cvs_is_controlling; + return unless cvs_is_controlling(); eval q{use Date::Parse}; error($@) if $@; @@ -493,4 +441,74 @@ sub rcs_getmtime ($) { error "rcs_getmtime is not implemented for cvs\n"; # TODO } + +# INTERNAL SUPPORT ROUTINES + +sub commitmessage (@) { + my %params=@_; + + if (defined $params{session}) { + if (defined $params{session}->param("name")) { + return "web commit by ". + $params{session}->param("name"). + (length $params{message} ? ": $params{message}" : ""); + } + elsif (defined $params{session}->remote_addr()) { + return "web commit from ". + $params{session}->remote_addr(). + (length $params{message} ? ": $params{message}" : ""); + } + } + return $params{message}; +} + +sub cvs_info ($$) { + my $field=shift; + my $file=shift; + + local $CWD = $config{srcdir}; + + my $info=`cvs status $file`; + my ($ret)=$info=~/^\s*$field:\s*(\S+)/m; + return $ret; +} + +sub cvs_is_controlling { + my $dir=shift; + $dir=$config{srcdir} unless defined($dir); + return (-d "$dir/CVS") ? 1 : 0; +} + +sub cvs_keyword_subst_args ($) { + my $file = shift; + + local $CWD = $config{srcdir}; + + eval q{use File::MimeInfo}; + error($@) if $@; + my $filemime = File::MimeInfo::default($file); + # if (-T $file) { + + if (defined($filemime) && $filemime eq 'text/plain') { + return ($file); + } + else { + return ('-kb', $file); + } +} + +sub cvs_runcvs(@) { + my @cmd = @_; + unshift @cmd, 'cvs', '-Q'; + + local $CWD = $config{srcdir}; + + open(my $savedout, ">&STDOUT"); + open(STDOUT, ">", "/dev/null"); + my $ret = system(@cmd); + open(STDOUT, ">&", $savedout); + + return ($ret == 0) ? 1 : 0; +} + 1 diff --git a/IkiWiki/Plugin/editpage.pm b/IkiWiki/Plugin/editpage.pm index a5c29a352..54051c58c 100644 --- a/IkiWiki/Plugin/editpage.pm +++ b/IkiWiki/Plugin/editpage.pm @@ -231,7 +231,7 @@ sub cgi_editpage ($$) { if ! $form->submitted && lc($page) ne $page; } elsif (lc $page eq lc $config{discussionpage}) { - @page_locs=$best_loc=$page="$from/".lc($page); + @page_locs=$best_loc="$from/".lc($page); } else { my $dir=$from."/"; diff --git a/IkiWiki/Plugin/graphviz.pm b/IkiWiki/Plugin/graphviz.pm index 4ed8b89f1..b9f997e04 100644 --- a/IkiWiki/Plugin/graphviz.pm +++ b/IkiWiki/Plugin/graphviz.pm @@ -10,7 +10,8 @@ use IPC::Open2; sub import { hook(type => "getsetup", id => "graphviz", call => \&getsetup); - hook(type => "preprocess", id => "graph", call => \&graph); + hook(type => "needsbuild", id => "version", call => \&needsbuild); + hook(type => "preprocess", id => "graph", call => \&graph, scan => 1); } sub getsetup () { @@ -26,66 +27,117 @@ my %graphviz_programs = ( "dot" => 1, "neato" => 1, "fdp" => 1, "twopi" => 1, "circo" => 1 ); +sub needsbuild { + my $needsbuild=shift; + foreach my $page (keys %pagestate) { + if (exists $pagestate{$page}{graph} && + exists $pagesources{$page} && + grep { $_ eq $pagesources{$page} } @$needsbuild) { + # remove state, will be re-added if + # the graph is still there during the rebuild + delete $pagestate{$page}{graph}; + } + } + return $needsbuild; +} + sub render_graph (\%) { my %params = %{(shift)}; - - my $src = "$params{type} g {\n"; - $src .= "charset=\"utf-8\";\n"; + + my $src = "charset=\"utf-8\";\n"; $src .= "ratio=compress;\nsize=\"".($params{width}+0).", ".($params{height}+0)."\";\n" if defined $params{width} and defined $params{height}; $src .= $params{src}; $src .= "}\n"; - - # Use the sha1 of the graphviz code as part of its filename. + + # Use the sha1 of the graphviz code as part of its filename, + # and as a unique identifier for its imagemap. eval q{use Digest::SHA}; error($@) if $@; - my $dest=$params{page}."/graph-". - IkiWiki::possibly_foolish_untaint(Digest::SHA::sha1_hex($src)). - ".png"; + my $sha=IkiWiki::possibly_foolish_untaint(Digest::SHA::sha1_hex($params{type}.$src)); + $src = "$params{type} graph$sha {\n".$src; + + my $dest=$params{page}."/graph-".$sha.".png"; will_render($params{page}, $dest); - if (! -e "$config{destdir}/$dest") { + my $map=$pagestate{$params{destpage}}{graph}{$sha}; + if (! -e "$config{destdir}/$dest" || ! defined $map) { + # Use ikiwiki's function to create the image file, this makes + # sure needed subdirs are there and does some sanity checking. + writefile($dest, $config{destdir}, ""); + my $pid; my $sigpipe=0; $SIG{PIPE}=sub { $sigpipe=1 }; - $pid=open2(*IN, *OUT, "$params{prog} -Tpng"); + $pid=open2(*IN, *OUT, "$params{prog} -Tpng -o '$config{destdir}/$dest' -Tcmapx"); # open2 doesn't respect "use open ':utf8'" + binmode (IN, ':utf8'); binmode (OUT, ':utf8'); print OUT $src; close OUT; - my $png; - { - local $/ = undef; - $png = <IN>; - } + local $/ = undef; + $map=$pagestate{$params{destpage}}{graph}{$sha}=<IN>; close IN; waitpid $pid, 0; $SIG{PIPE}="DEFAULT"; - error gettext("failed to run graphviz") if $sigpipe; - - if (! $params{preview}) { - writefile($dest, $config{destdir}, $png, 1); - } - else { - # in preview mode, embed the image in a data uri - # to avoid temp file clutter - eval q{use MIME::Base64}; - error($@) if $@; - return "<img src=\"data:image/png;base64,". - encode_base64($png)."\" />"; - } + error gettext("failed to run graphviz") if ($sigpipe || $?); } - return "<img src=\"".urlto($dest, $params{destpage})."\" />\n"; + return "<img src=\"".urlto($dest, $params{destpage}). + "\" usemap=\"#graph$sha\" />\n". + $map; } sub graph (@) { my %params=@_; - $params{src} = "" unless defined $params{src}; + + # Support wikilinks in the graph source. + my $src=$params{src}; + $src="" unless defined $src; + $src=IkiWiki::linkify($params{page}, $params{destpage}, $params{src}); + return unless defined wantarray; # scan mode short-circuit + if ($src ne $params{src}) { + # linkify makes html links, but graphviz wants plain + # urls. This is, frankly a hack: Process source as html, + # throw out everything inside tags that is not a href. + my $s; + my $nested=0; + use HTML::Parser; + error $@ if $@; + my $p=HTML::Parser->new(api_version => 3); + $p->handler(start => sub { + my %attrs=%{shift()}; + if (exists $attrs{href}) { + if ($s=~/href\s*=\s*"$/) { + $s.=$attrs{href}; + } + elsif ($s=~/href\s*=\s*$/) { + $s.="\"$attrs{href}\""; + } + else { + $s.="href=\"$attrs{href}\""; + } + } + $nested++; + }, "attr"); + $p->handler(end => sub { + $nested--; + }); + $p->handler(default => sub { + $s.=join("", @_) unless $nested; + }, "text"); + $p->parse($src); + $p->eof; + $params{src}=$s; + } + else { + $params{src}=$src; + } + $params{type} = "digraph" unless defined $params{type}; $params{prog} = "dot" unless defined $params{prog}; error gettext("prog not a valid graphviz program") unless $graphviz_programs{$params{prog}}; diff --git a/IkiWiki/Plugin/highlight.pm b/IkiWiki/Plugin/highlight.pm index 33d136fbf..4e86207f1 100644 --- a/IkiWiki/Plugin/highlight.pm +++ b/IkiWiki/Plugin/highlight.pm @@ -52,7 +52,7 @@ sub getsetup () { sub checkconfig () { eval q{use highlight}; - if (highlight::DataDir->can('new')){ + if (highlight::DataDir->can('new')) { $data_dir=new highlight::DataDir(); $data_dir->searchDataDir(""); } else { diff --git a/IkiWiki/Plugin/img.pm b/IkiWiki/Plugin/img.pm index b98e843d4..b92e24cc0 100644 --- a/IkiWiki/Plugin/img.pm +++ b/IkiWiki/Plugin/img.pm @@ -118,7 +118,6 @@ sub preprocess (@) { error sprintf(gettext("failed to read %s: %s"), $outfile, $r) if $r; } else { - ($dwidth, $dheight)=($w, $h); $r = $im->Resize(geometry => "${w}x${h}"); error sprintf(gettext("failed to resize: %s"), $r) if $r; @@ -132,9 +131,10 @@ sub preprocess (@) { $imglink = $file; } } - - $dwidth = $im->Get("width") unless defined $dwidth; - $dheight = $im->Get("height") unless defined $dheight; + + # always get the true size of the resized image + $dwidth = $im->Get("width"); + $dheight = $im->Get("height"); } } else { diff --git a/IkiWiki/Plugin/mdwn.pm b/IkiWiki/Plugin/mdwn.pm index b892eabee..430194bff 100644 --- a/IkiWiki/Plugin/mdwn.pm +++ b/IkiWiki/Plugin/mdwn.pm @@ -25,6 +25,13 @@ sub getsetup () { safe => 1, rebuild => 1, }, + nodiscount => { + type => "boolean", + example => 0, + description => "disable use of markdown discount?", + safe => 1, + rebuild => 1, + }, } my $markdown_sub; @@ -50,6 +57,25 @@ sub htmlize (@) { } } } + if (! defined $markdown_sub && + (! exists $config{nodiscount} || ! $config{nodiscount})) { + eval q{use Text::Markdown::Discount}; + if (! $@) { + $markdown_sub=sub { + my $t=shift; + # Workaround for discount binding bug + # https://rt.cpan.org/Ticket/Display.html?id=73657 + return "" if $t=~/^\s*$/; + # Workaround for discount's eliding + # of <style> blocks. + # https://rt.cpan.org/Ticket/Display.html?id=74016 + $t=~s/<style/<elyts/ig; + my $r=Text::Markdown::Discount::markdown($t); + $r=~s/<elyts/<style/ig; + return $r; + } + } + } if (! defined $markdown_sub) { eval q{use Text::Markdown}; if (! $@) { diff --git a/IkiWiki/Plugin/recentchangesdiff.pm b/IkiWiki/Plugin/recentchangesdiff.pm index 71297572d..418822793 100644 --- a/IkiWiki/Plugin/recentchangesdiff.pm +++ b/IkiWiki/Plugin/recentchangesdiff.pm @@ -31,13 +31,21 @@ sub pagetemplate (@) { my @lines=IkiWiki::rcs_diff($params{rev}, $maxlines+1); if (@lines) { my $diff; + my $trunc=0; if (@lines > $maxlines) { - $diff=join("", @lines[0..($maxlines-1)])."\n". - gettext("(Diff truncated)"); + $diff=join("", @lines[0..($maxlines-1)]); + $trunc=1; } else { $diff=join("", @lines); } + if (length $diff > 102400) { + $diff=substr($diff, 0, 10240); + $trunc=1; + } + if ($trunc) { + $diff.="\n".gettext("(Diff truncated)"); + } # escape html $diff = encode_entities($diff); # escape links and preprocessor stuff diff --git a/IkiWiki/Plugin/tag.pm b/IkiWiki/Plugin/tag.pm index 096c92616..605f41599 100644 --- a/IkiWiki/Plugin/tag.pm +++ b/IkiWiki/Plugin/tag.pm @@ -201,7 +201,7 @@ sub pagetemplate (@) { if (defined $tags && %$tags) { eval q{use HTML::Entities}; $template->param(categories => - [map { category => HTML::Entities::encode_entities(tagname($_)) }, + [map { category => HTML::Entities::encode_entities_numeric(tagname($_)) }, sort keys %$tags]); } } |