Merge branch 'master' of ssh://git.ikiwiki.info/srv/git/ikiwiki.info into tova
[ikiwiki.git] / IkiWiki / Plugin / editdiff.pm
1 #!/usr/bin/perl
2 # This plugin adds a "Diff" button to the page edit form.
3 package IkiWiki::Plugin::editdiff;
4
5 use warnings;
6 use strict;
7 use IkiWiki 2.00;
8 use HTML::Entities;
9 use IPC::Open2;
10
11 sub import { #{{{
12         hook(type => "formbuilder_setup", id => "editdiff",
13                 call => \&formbuilder_setup);
14 } #}}}
15
16 sub diff ($$) { #{{{
17         my $orig=shift;
18         my $content=shift;
19
20         my $sigpipe=0;
21         $SIG{PIPE} = sub { $sigpipe=1; };
22
23         my $pid = open2(*DIFFOUT, *DIFFIN, 'diff', '-u', $orig, '-');
24         binmode($_, ':utf8') foreach (*DIFFIN, *DIFFOUT);
25
26         print DIFFIN $content;
27         close DIFFIN;
28         my $ret='';
29         while (<DIFFOUT>) {
30                 if (defined $ret) {
31                         $ret.=$_;
32                 }
33                 elsif (/^\@\@/) {
34                         $ret=$_;
35                 }
36         }
37         close DIFFOUT;
38         waitpid $pid, 0;
39
40         $SIG{PIPE}="default";
41         return "couldn't run diff\n" if $sigpipe;
42
43         return "<pre>".encode_entities($ret)."</pre>";
44 } #}}}
45
46 sub formbuilder_setup { #{{{
47         my %params=@_;
48         my $form=$params{form};
49         my $page=$form->field("page");
50
51         return if $form->field("do") ne "edit";
52
53         $page = IkiWiki::titlepage(IkiWiki::possibly_foolish_untaint($page));
54         return unless exists $pagesources{$page};
55
56         push @{$params{buttons}}, "Diff";
57
58         if ($form->submitted eq "Diff") {
59                 my $content=$form->field('editcontent');
60                 $content=~s/\r\n/\n/g;
61                 $content=~s/\r/\n/g;
62
63                 my $diff = diff(srcfile($pagesources{$page}), $content);
64                 $form->tmpl_param("page_preview", $diff);
65         }
66 } #}}}
67
68 1