diff options
author | Yorhel <git@yorhel.nl> | 2008-11-15 11:51:58 +0100 |
---|---|---|
committer | Yorhel <git@yorhel.nl> | 2008-11-15 11:51:58 +0100 |
commit | db820616d0f5c7f49e725987b6cd900944e4ffd0 (patch) | |
tree | 1c1763eaf527a70b84b5a67a0ba6ccc32ef6ff93 /lib/VNDB/Util/CommonHTML.pm | |
parent | dbaba80b10273270a16e91118fa12e081d4707f7 (diff) |
Wrote revision and diff viewer
Character-level diffs instead of the old word-level diffs.
Still only works on plaintext, though.
Not really sure about the style, either.
Diffstat (limited to 'lib/VNDB/Util/CommonHTML.pm')
-rw-r--r-- | lib/VNDB/Util/CommonHTML.pm | 118 |
1 files changed, 116 insertions, 2 deletions
diff --git a/lib/VNDB/Util/CommonHTML.pm b/lib/VNDB/Util/CommonHTML.pm index f2c4d6ff..25e25982 100644 --- a/lib/VNDB/Util/CommonHTML.pm +++ b/lib/VNDB/Util/CommonHTML.pm @@ -3,10 +3,12 @@ package VNDB::Util::CommonHTML; use strict; use warnings; -use YAWF ':html'; +use YAWF ':html', 'xml_escape'; use Exporter 'import'; +use Algorithm::Diff 'sdiff'; +use VNDB::Func; -our @EXPORT = qw|htmlMainTabs htmlDenied htmlBrowse htmlBrowseNavigate|; +our @EXPORT = qw|htmlMainTabs htmlDenied htmlBrowse htmlBrowseNavigate htmlRevision|; # generates the "main tabs". These are the commonly used tabs for @@ -178,4 +180,116 @@ sub htmlBrowseNavigate { } +# Shows a revision, including diff if there is a previous revision. +# Arguments: v|p|r, old revision, new revision, @fields +# Where @fields is a list of fields as arrayrefs with: +# [ shortname, displayname, %options ], +# Where %options: +# diff => 1/0, whether do show a diff on this field +# serialize => coderef, should convert the field into a readable string, no HTML allowed +sub htmlRevision { + my($self, $type, $old, $new, @fields) = @_; + div class => 'mainbox revision'; + h1 'Revision '.$new->{rev}; + + # previous/next revision links + a class => 'prev', href => sprintf('/%s%d.%d', $type, $new->{id}, $new->{rev}-1), '<- earlier revision' + if $new->{rev} > 1; + a class => 'next', href => sprintf('/%s%d.%d', $type, $new->{id}, $new->{rev}+1), 'later revision ->' + if $new->{cid} != $new->{latest}; + p class => 'center'; + a href => "/$type$new->{id}", "$type$new->{id}"; + end; + + # no previous revision, just show info about the revision itself + if(!$old) { + div; + revheader($type, $new); + br; + b 'Edit summary:'; + br; br; + lit bb2html($new->{comments})||'[no summary]'; + end; + } + + # otherwise, compare the two revisions + else { + table; + thead; + Tr; + td; lit ' '; end; + td; revheader($type, $old); end; + td; revheader($type, $new); end; + end; + Tr; + td; lit ' '; end; + td colspan => 2; + b 'Edit summary of revision '.$new->{rev}.':'; + br; br; + lit bb2html($new->{comments})||'[no summary]'; + end; + end; + end; + my $i = 1; + revdiff(\$i, $old, $new, @$_) for (@fields); + end; + } + end; +} + +sub revheader { # type, obj + my($type, $obj) = @_; + b 'Revision '.$obj->{rev}; + txt ' ('; + a href => "/$type$obj->{id}?rev=1", 'edit'; + txt ')'; + br; + txt 'By '; + a href => "/u$obj->{requester}", $obj->{username}; + txt ' on '; + lit date $obj->{added}, 'full'; +} + +sub revdiff { + my($i, $old, $new, $short, $name, %o) = @_; + + my $ser1 = $o{serialize} ? $o{serialize}->($old->{$short}) : $old->{$short}; + my $ser2 = $o{serialize} ? $o{serialize}->($new->{$short}) : $new->{$short}; + return if $ser1 eq $ser2; + + if($o{diff} && $ser1 && $ser2) { + my($r1,$r2,$ch) = ('','','u'); + for (sdiff([ split //, $ser1 ], [ split //, $ser2 ])) { + if($ch ne $_->[0]) { + if($ch ne 'u') { + $r1 .= '</b>'; + $r2 .= '</b>'; + } + $r1 .= '<b class="diff_del">' if $_->[0] eq '-' || $_->[0] eq 'c'; + $r2 .= '<b class="diff_add">' if $_->[0] eq '+' || $_->[0] eq 'c'; + } + $ch = $_->[0]; + $r1 .= xml_escape $_->[1] if $ch ne '+'; + $r2 .= xml_escape $_->[2] if $ch ne '-'; + } + $r1 .= '</b>' if $ch eq '-' || $ch eq 'c'; + $r2 .= '</b>' if $ch eq '+' || $ch eq 'c'; + $ser1 = $r1; + $ser2 = $r2; + } else { + $ser1 = xml_escape $ser1; + $ser2 = xml_escape $ser2; + } + + $ser1 = '[empty]' if !$ser1 && $ser1 ne '0'; + $ser2 = '[empty]' if !$ser2 && $ser2 ne '0'; + + Tr $$i++ % 2 ? (class => 'odd') : (); + td class => 'tcname', $name; + td; lit $ser1; end; + td; lit $ser2; end; + end; +} + + 1; |