| blib/lib/Text/Diff/HTML.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 40 | 40 | 100.0 |
| branch | 6 | 8 | 75.0 |
| condition | n/a | ||
| subroutine | 12 | 12 | 100.0 |
| pod | 0 | 5 | 0.0 |
| total | 58 | 65 | 89.2 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Text::Diff::HTML; | ||||||
| 2 | |||||||
| 3 | 1 | 1 | 57261 | use strict; | |||
| 1 | 2 | ||||||
| 1 | 28 | ||||||
| 4 | 1 | 1 | 5 | use vars qw(@ISA $VERSION); | |||
| 1 | 1 | ||||||
| 1 | 44 | ||||||
| 5 | 1 | 1 | 449 | use HTML::Entities; | |||
| 1 | 4902 | ||||||
| 1 | 70 | ||||||
| 6 | 1 | 1 | 462 | use Text::Diff (); # Just to be safe. | |||
| 1 | 10147 | ||||||
| 1 | 127 | ||||||
| 7 | |||||||
| 8 | $VERSION = '0.08'; | ||||||
| 9 | @ISA = qw(Text::Diff::Unified); | ||||||
| 10 | |||||||
| 11 | sub file_header { | ||||||
| 12 | 1 | 1 | 0 | 819 | return ' ' |
||
| 13 | . encode_entities(shift->SUPER::file_header(@_)) | ||||||
| 14 | . ''; | ||||||
| 15 | } | ||||||
| 16 | |||||||
| 17 | sub hunk_header { | ||||||
| 18 | 1 | 1 | 0 | 543 | return ' ' |
||
| 19 | . encode_entities(shift->SUPER::hunk_header(@_)) | ||||||
| 20 | . ''; | ||||||
| 21 | } | ||||||
| 22 | |||||||
| 23 | sub hunk_footer { | ||||||
| 24 | 1 | 1 | 0 | 471 | return ' | ||
| 25 | . encode_entities(shift->SUPER::hunk_footer(@_)) | ||||||
| 26 | . ''; | ||||||
| 27 | } | ||||||
| 28 | |||||||
| 29 | sub file_footer { | ||||||
| 30 | 1 | 1 | 0 | 498 | return ' | ||
| 31 | . encode_entities(shift->SUPER::file_footer(@_)) | ||||||
| 32 | . ''; | ||||||
| 33 | } | ||||||
| 34 | |||||||
| 35 | # Each of the items in $seqs is an array reference. The first one has the | ||||||
| 36 | # contents of the first file and the second has the contents of the second | ||||||
| 37 | # file, all broken into hunks. $ops is an array reference of array references, | ||||||
| 38 | # one corresponding to each of the hunks in the sequences. | ||||||
| 39 | # | ||||||
| 40 | # The contents of each op in $ops tell us what to do with each hunk. Each op | ||||||
| 41 | # can have up to four items: | ||||||
| 42 | # | ||||||
| 43 | # 0: The index of the relevant hunk in the first file sequence. | ||||||
| 44 | # 1: The index of the relevant hunk in the second file sequence. | ||||||
| 45 | # 2: The opcode for the hunk, either '+', '-', or ' '. | ||||||
| 46 | # 3: A flag; not sure what this is, doesn't seem to apply to unified diffs. | ||||||
| 47 | # | ||||||
| 48 | # So what we do is figure out which op we have and output the relevant span | ||||||
| 49 | # element if it is different from the last op. Then we select the hunk from | ||||||
| 50 | # second sequence (SEQ_B_IDX) if it's '+' and the first sequence (SEQ_A_IDX) | ||||||
| 51 | # otherwise, and then output the opcode and the hunk. | ||||||
| 52 | |||||||
| 53 | 1 | 1 | 8 | use constant OPCODE => 2; # "-", " ", "+" | |||
| 1 | 2 | ||||||
| 1 | 47 | ||||||
| 54 | 1 | 1 | 4 | use constant SEQ_A_IDX => 0; | |||
| 1 | 2 | ||||||
| 1 | 47 | ||||||
| 55 | 1 | 1 | 5 | use constant SEQ_B_IDX => 1; | |||
| 1 | 2 | ||||||
| 1 | 240 | ||||||
| 56 | |||||||
| 57 | my %code_map = ( | ||||||
| 58 | '+' => [ 'ins' => 'ins' ], | ||||||
| 59 | '-' => [ 'del' => 'del' ], | ||||||
| 60 | ' ' => [ 'span class="ctx"' => 'span' ] | ||||||
| 61 | ); | ||||||
| 62 | |||||||
| 63 | sub hunk { | ||||||
| 64 | 1 | 1 | 0 | 455 | shift; | ||
| 65 | 1 | 2 | my $seqs = [ shift, shift ]; | ||||
| 66 | 1 | 3 | my $ops = shift; | ||||
| 67 | 1 | 50 | 4 | return unless @$ops; | |||
| 68 | |||||||
| 69 | # Start the span element for the first opcode. | ||||||
| 70 | 1 | 2 | my $last = $ops->[0][ OPCODE ]; | ||||
| 71 | 1 | 4 | my $hunk = qq{<$code_map{ $last }->[0]>}; | ||||
| 72 | |||||||
| 73 | # Output each line of the hunk. | ||||||
| 74 | 1 | 5 | while (my $op = shift @$ops) { | ||||
| 75 | 4 | 54 | my $opcode = $op->[OPCODE]; | ||||
| 76 | 4 | 50 | 9 | my $elem = $code_map{ $opcode } or next; | |||
| 77 | |||||||
| 78 | # Close the last span and start a new one for a new opcode. | ||||||
| 79 | 4 | 100 | 7 | if ($opcode ne $last) { | |||
| 80 | 2 | 5 | $hunk .= "$code_map{ $last }->[1]><$elem->[0]>"; | ||||
| 81 | 2 | 3 | $last = $opcode; | ||||
| 82 | } | ||||||
| 83 | |||||||
| 84 | # Output the appropriate line. | ||||||
| 85 | 4 | 100 | 9 | my $idx = $opcode ne '+' ? SEQ_A_IDX : SEQ_B_IDX; | |||
| 86 | 4 | 13 | $hunk .= encode_entities("$opcode $seqs->[$idx][$op->[$idx]]"); | ||||
| 87 | } | ||||||
| 88 | |||||||
| 89 | 1 | 16 | return $hunk . "$code_map{ $last }->[1]>"; | ||||
| 90 | } | ||||||
| 91 | |||||||
| 92 | 1; | ||||||
| 93 | __END__ |