/usr/local/CPAN/mobirc/App/Mobirc/Plugin/HTMLFilter/DoCoMoCSS.pm
package App::Mobirc::Plugin::HTMLFilter::DoCoMoCSS;
use strict;
use MooseX::Plaggerize::Plugin;
use CSS::Tiny;
use XML::LibXML;
use HTML::Selector::XPath qw(selector_to_xpath);
use App::Mobirc::Util;
use Encode;
use Path::Class;
use XML::LibXML::XPathContext;
use App::Mobirc::Validator;
# some code copied from HTML::DoCoMoCSS
hook 'html_filter' => sub {
my ($self, $global_context, $req, $content) = validate_hook('html_filter', @_);
DEBUG "FILTER DOCOMO CSS";
return ($req, $content) unless $req->mobile_agent->is_docomo;
# escape Numeric character reference.
$content =~ s/&#(x[\dA-Fa-f]{4}|\d+);/HTMLCSSINLINERESCAPE$1::::::::/g;
# unescape Numeric character reference.
my $pict_unescape = sub { $content =~ s/HTMLCSSINLINERESCAPE(x[\dA-Z-a-z]{4}|\d+)::::::::/&#$1;/g; return $content; };
my $css = CSS::Tiny->read_string($self->css_text($global_context));
my $doc = eval { XML::LibXML->new->parse_string($content); };
if (my $e = $@) {
warn $e;
return ($req, $pict_unescape->());
}
my $xc = XML::LibXML::XPathContext->new($doc);
my $root = $doc->documentElement();
my $namespace = $root->getAttribute('xmlns');
my $namespace_prefix = '';
if ($namespace) {
# xhtml
$xc->registerNs( 'x', $namespace );
$namespace_prefix = 'x:';
}
# apply inline css
while (my($selector, $style) = each %{ $css }) {
my $style_stringify = join ';', map { "$_:$style->{$_}" } keys %{ $style };
my $xpath = selector_to_xpath($selector);
$xpath =~ s{^//}{//$namespace_prefix};
for my $element ( $xc->findnodes( $xpath ) ) {
my $style_attr = $element->getAttribute('style');
$style_attr = (!$style_attr) ? $style_stringify : (join ";", ($style_attr, $style_stringify));
$style_attr .= ';' unless $style_attr =~ /;$/;
$element->setAttribute('style', $style_attr);
}
}
$content = decode_utf8($doc->toString);
$content =~ s{(<a[^>]+)/>}{$1></a>}gi;
return ($req, $pict_unescape->());
};
sub css_text {
my ($self, $global_context) = @_;
my $root = dir($global_context->config->{global}->{assets_dir}, 'static');
$root->file('mobirc.css')->slurp . "\n" . $root->file('mobile.css')->slurp;
}
1;