| 1 | package Plagger::Plugin::Filter::Diff; |
|---|
| 2 | |
|---|
| 3 | use strict; |
|---|
| 4 | use base qw( Plagger::Plugin ); |
|---|
| 5 | |
|---|
| 6 | use Plagger::Cache; |
|---|
| 7 | |
|---|
| 8 | use Algorithm::Diff qw( traverse_sequences ); |
|---|
| 9 | |
|---|
| 10 | sub register { |
|---|
| 11 | my($self, $context) = @_; |
|---|
| 12 | $context->register_hook( |
|---|
| 13 | $self, |
|---|
| 14 | 'plugin.init' => \&initialize, |
|---|
| 15 | 'update.entry.fixup' => \&filter, |
|---|
| 16 | ); |
|---|
| 17 | } |
|---|
| 18 | |
|---|
| 19 | sub initialize { |
|---|
| 20 | my($self, $context) = @_; |
|---|
| 21 | |
|---|
| 22 | my $params = { |
|---|
| 23 | base => $self->conf->{path} || File::Spec->catfile(Plagger->context->cache->{base}, 'Filter-Diff'), |
|---|
| 24 | expires => $self->conf->{expires}, |
|---|
| 25 | }; |
|---|
| 26 | |
|---|
| 27 | $self->{cache} = Plagger::Cache->new($params); |
|---|
| 28 | } |
|---|
| 29 | |
|---|
| 30 | sub filter { |
|---|
| 31 | my($self, $context, $args) = @_; |
|---|
| 32 | |
|---|
| 33 | my $entry = $args->{entry}; |
|---|
| 34 | |
|---|
| 35 | my $prev_cache = $self->{cache}->get($entry->permalink) || {}; |
|---|
| 36 | my $prev = (ref $prev_cache eq 'HASH') ? $prev_cache : { body => $prev_cache }; |
|---|
| 37 | my $body_new = $entry->body ? $entry->body->utf8 : undef; |
|---|
| 38 | my $lastmod_new = $entry->date || Plagger::Date->now; |
|---|
| 39 | |
|---|
| 40 | my $body_diffed = ''; |
|---|
| 41 | if ($prev->{body}) { |
|---|
| 42 | Plagger->context->log( debug => "previous entry data found (".$prev->{modified_on}.")" ); |
|---|
| 43 | |
|---|
| 44 | my @lines = split /^/, $body_new; |
|---|
| 45 | my @lines_prev = split /^/, $prev->{body}; |
|---|
| 46 | |
|---|
| 47 | traverse_sequences(\@lines_prev, \@lines, |
|---|
| 48 | { |
|---|
| 49 | DISCARD_B => sub { |
|---|
| 50 | Plagger->context->log( debug => "new line: $lines[$_[1]]" ); |
|---|
| 51 | $body_diffed .= $lines[$_[1]]; |
|---|
| 52 | } |
|---|
| 53 | } |
|---|
| 54 | ); |
|---|
| 55 | $body_diffed =~ s/(?:^\s+|\s+$)//g; |
|---|
| 56 | $entry->body($body_diffed); |
|---|
| 57 | $entry->date($lastmod_new) unless $entry->date; |
|---|
| 58 | } |
|---|
| 59 | else { |
|---|
| 60 | $entry->body('') unless $self->conf->{store_on_firsttime}; |
|---|
| 61 | } |
|---|
| 62 | |
|---|
| 63 | if (!$prev->{modified_on} || ($body_diffed ne '' && ($prev->{modified_on} < $lastmod_new))) { |
|---|
| 64 | Plagger->context->log( debug => "Save entry data: ".$entry->permalink ); |
|---|
| 65 | $self->{cache}->set($entry->permalink, { body => $body_new, diff => $entry->body, modified_on => $lastmod_new }); |
|---|
| 66 | } |
|---|
| 67 | else { |
|---|
| 68 | Plagger->context->log( debug => "use previous diff data."); |
|---|
| 69 | $entry->body($prev->{diff}); |
|---|
| 70 | $entry->date($prev->{modified_on}); |
|---|
| 71 | } |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | 1; |
|---|
| 75 | __END__ |
|---|
| 76 | |
|---|
| 77 | =head1 NAME |
|---|
| 78 | |
|---|
| 79 | Plagger::Plugin::Filter::Diff - Take a difference of the entry body. |
|---|
| 80 | |
|---|
| 81 | =head1 SYNOPSIS |
|---|
| 82 | |
|---|
| 83 | - module: Filter::Diff |
|---|
| 84 | |
|---|
| 85 | =head1 DESCRIPTION |
|---|
| 86 | |
|---|
| 87 | Take a difference of the entry body. |
|---|
| 88 | |
|---|
| 89 | =head1 CONFIG |
|---|
| 90 | |
|---|
| 91 | =over 4 |
|---|
| 92 | |
|---|
| 93 | =item store_on_firsttime |
|---|
| 94 | |
|---|
| 95 | =item path |
|---|
| 96 | |
|---|
| 97 | path to a cache directory for diff. |
|---|
| 98 | |
|---|
| 99 | =item expires |
|---|
| 100 | |
|---|
| 101 | expires of diff cache. |
|---|
| 102 | |
|---|
| 103 | =back |
|---|
| 104 | |
|---|
| 105 | =head1 AUTHOR |
|---|
| 106 | |
|---|
| 107 | Mayuki Sawatari |
|---|
| 108 | |
|---|
| 109 | =head1 SEE ALSO |
|---|
| 110 | |
|---|
| 111 | L<Plagger> |
|---|
| 112 | |
|---|
| 113 | =cut |
|---|