- 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キャリア共通にする) - へぼい日記 より