otsune's SnakeOil RSSフィード

python -c "print''.join([chr(x) for x in 111&1101,110+~-~11,10^11*11,110+~-~11,-~101,-~11^11*11,~-110,111&11*11,11+11+10,11|~-0110,1-~11^11*11,10^11*11,-~11^11*11,110,101])"

2007-05-16

del.icio.usのrssが数値文字参照なのでFilter::Entitiesを書いた

| del.icio.usのrssが数値文字参照なのでFilter::Entitiesを書いた - otsune's SnakeOil  を含むブックマーク はてなブックマーク - del.icio.usのrssが数値文字参照なのでFilter::Entitiesを書いた - otsune's SnakeOil  del.icio.usのrssが数値文字参照なのでFilter::Entitiesを書いた - otsune's SnakeOil  のブックマークコメント

lib/Plagger/Util.pmとかlib/Plagger/Text.pmあたりにその辺を処理するメソッド有ったような記憶だったけど、どうも見当たらなかったのでFilterプラグインで対処。

Publish::LivedoorClipやPublish::Buzzurlすると、日本語タイトルやコメントが欠落する現象が出たので。どうも数値参照だとサポートしきれていない?(Publish::HatenaBookmarkはAtomPP経由のためか、そういう不具合は出ていない)

多分、Engadget JapaneseのRSSをいい具合にするのにも使えるはず。

lib/Plagger/Plugin/Filter/Entities.pm

package Plagger::Plugin::Filter::Entities;
use strict;
use base qw( Plagger::Plugin );

use HTML::Entities;

sub register {
    my($self, $context) = @_;
    $context->register_hook(
        $self,
        'update.entry.fixup' => \&filter,
    );
}

sub filter {
    my ($self, $context, $args) = @_;

    my $prop = $self->conf->{property} || 'body';
    $prop = [ $prop ] unless ref $prop;

    for my $p (@{$prop}) {
        my $src = $args->{entry}->{$p};
        my $str = decode_entities( $src );
        unless ($str eq $src) {
            $src->data($str);
            $context->log(debug => "decode $p: $str");
        }
    }
}

1;
__END__

=head1 NAME

Plagger::Plugin::Filter::Entities - decode HTML Numeric character references

=head1 SYNOPSIS

  - module: Filter::Entities
    config:
      property:
        - title
        - body
        - summary

=head1 DESCRIPTION

such a numeric character reference as '宮川' is converted 
into the Unicode character string by using HTML::Entities

=head1 CONFIG

=over 4

=item property

Specify the property name of L<Plagger::Entry> you want to use.
It defaults to 'body'.

=back

=head1 AUTHOR

Masafumi Otsune

=head1 SEE ALSO

L<Plagger::Entry>, L<HTML::Entities>

=cut

t/plugins/Filter-Entities/base.t

use strict;
use utf8;
use t::TestPlagger;

test_plugin_deps;
plan 'no_plan';
run_eval_expected;

__END__
=== 
--- input config
plugins:
  - module: CustomFeed::Debug
    config:
      title: Entities
      entry:
        - title: '&#23470;&#24029;&#36948;&#24422;'
          body: miyagawa
        - title: '<script src=""></script>'
          body: '<&#115;&#99;&#114;&#105;&#112;&#116; &#115;&#114;&#99;="&#104;&#116;&#116;&#112;&#58;//&#101;&#120;&#97;&#109;&#112;&#108;&#101;.&#106;&#112;/&#104;&#111;&#103;&#101;.&#106;&#115;"></&#115;&#99;&#114;&#105;&#112;&#116;>'
        - title: 'CD TUBE&#x306E;yusukebe&#x540D;&#x6307;&#x3057;&#x304B;&#x3002;'
          summary: '&#x8A00;&#x8449;&#x304C;&#x77DB;&#x76FE;&#x3057;&#x3066;&#x308B;&#xFF01; &#x26;gt;&#x516C;&#x5E73;&#x306A;&#x30CB;&#x30B3;&#x30CB;&#x30B3;&#x683C;&#x5DEE;&#x793E;&#x4F1A;'
  - module: Filter::Entities
    config:
      property:
        - title
        - body
        - summary
--- expected
is $context->update->feeds->[0]->entries->[0]->title, '宮川達彦';
is $context->update->feeds->[0]->entries->[0]->body, 'miyagawa';
is $context->update->feeds->[0]->entries->[1]->title, '<script src=""></script>';
is $context->update->feeds->[0]->entries->[1]->body, '<script src="http://example.jp/hoge.js"></script>';
like $context->update->feeds->[0]->entries->[2]->title, qr/CD TUBEのyusukebe名指しか。/;
is $context->update->feeds->[0]->entries->[2]->summary, '言葉が矛盾してる! &gt;公平なニコニコ格差社会';
トラックバック - http://subtech.g.hatena.ne.jp/otsune/20070516