summaryrefslogtreecommitdiff
path: root/lib/VNDB/Util/CommonHTML.pm
diff options
context:
space:
mode:
authorYorhel <git@yorhel.nl>2008-11-15 11:51:58 +0100
committerYorhel <git@yorhel.nl>2008-11-15 11:51:58 +0100
commitdb820616d0f5c7f49e725987b6cd900944e4ffd0 (patch)
tree1c1763eaf527a70b84b5a67a0ba6ccc32ef6ff93 /lib/VNDB/Util/CommonHTML.pm
parentdbaba80b10273270a16e91118fa12e081d4707f7 (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.pm118
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 '&nbsp;'; end;
+ td; revheader($type, $old); end;
+ td; revheader($type, $new); end;
+ end;
+ Tr;
+ td; lit '&nbsp;'; 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;