- 2007/6/19 火曜日 4:07:43
- perl
DoCoMoはCSSの外部参照に対応してくれていない。
via モバイル勉強会が開催されました!
んなわけで、作ってみました。
Catalyst::Plugin::CSS::Docomo
package Catalyst::Plugin::CSS::Docomo;
use strict;
use CSS::Tiny;
use CSS::Tiny::Style;
use HTML::TreeBuilder::Select;
use NEXT;
our $VERSION = '0.01';
sub finalize {
my $c = shift;
unless ( $c->response->body and not ref $c->response->body ) {
return $c->NEXT::finalize;
}
unless ( $c->response->content_type =~ /^text|xml$|javascript$/ ) {
return $c->NEXT::finalize;
}
unless ($c->req->mobile_agent->is_docomo) {
return $c->NEXT::finalize;
}
$c->res->content_type('application/xhtml+xml; charset=Shift_JIS');
my $tree = HTML::TreeBuilder::Select->new()->parse($c->res->output)->eof;
my @stylesheets = $tree->select('link[rel="stylesheet"]');
unless (@stylesheets) {
return $c->NEXT::finalize;
}
foreach my $stylesheet_el (@stylesheets) {
my $css = CSS::Tiny->read( $c->path_to('root' . $stylesheet_el->attr('href')) );
if ($css) {
for my $st ($css->styles) {
foreach my $el ($tree->select($st->selector)) {
$st->add_to($el)
}
}
{
no warnings 'redefine';
local *HTML::Element::_xml_escape = &_xml_escape;
$c->res->output($tree->as_XML);
}
}
}
$c->NEXT::finalize;
}
sub _xml_escape {
foreach my $x (@_) {
$x =~ s!([<&>])!'&#'.(ord($1)).';'!seg;
}
return;
}
1;
まぁかなりやっつけ仕事なのはいなめないですが。一応動きます。
キャリア判別のためにCatalyst::Plugin::MobileAgentに依存してます。
他にはCSS::Tiny::Style,HTML::TreeBuilder::Selectあたりを使ってます。それぞれ依存モジュールがどばっとあるので一緒にいれまくってください。
仕組み的には、外部参照していてrootの下にStatic::Simpleとかで読み込ませてるCSSファイルをCSS::Tinyで読み込んでセレクタごとにスタイルをstyle属性に追加しまくるというかんじです。
優先順位なんかはチェックしてないのでどうなるか分りません。
で、これは実はこういうことをやりたくてCPANをあさってたらCSS::Tiny::StyleのSYNOPSISに
#——————————————————
# more interesting example
#——————————————————
# inline a stylesheet onto the single HTML elements
#——————————————————use HTML::TreeBuilder;
my $tree = HTML::TreeBuilder->new();
$tree->parse_file(‘filename.html’);$css = CSS::Tiny->read( ‘stylesheet.css’ );
for my $el ($tree->descendants) {
for my $st ($css->styles) {
if ($st->match($el)) {
$st->add_style($el);
}
}
}
print $tree->as_HTML;
こんなのがかいてあったのでこれがほぼ元ネタです。
$st->match($el)がいまいちな動きだったので
HTML::TreeBuilder::Selectを使うことにしましたけどね。
また、動的にクラスを付与しないとかであれば最初にTTを変換してキャッシュしておくというアプローチのほうが賢いでしょう。
あとは、root配下じゃないcssに対応するためbase_pathなんかが設定できたり、LWPなんかと連動して外部サーバのCSSなんかにも
対応するとなかなか汎用的になるかなぁ。
Catalyst以外でも使えるように別の名前空間でモジュール化してもいいだろうし・・・。
まぁ今日はのところは疲れたのでこれぐらい。必要に駆られないとやらなそうだけどね。
以上、反撃終わり。
コメント:0
トラックバック:0
- この記事のトラックバック URL
- https://blog.everqueue.com/chiba/2007/06/19/14/trackback/
- トラックバックの送信元リスト
- さて、そろそろ反撃してもいいですか?(携帯サイトでCSSを3キャリア共通にする) - へぼい日記 より