ホーム > perl > さて、そろそろ反撃してもいいですか?(携帯サイトでCSSを3キャリア共通にする)

さて、そろそろ反撃してもいいですか?(携帯サイトでCSSを3キャリア共通にする)

  • 投稿者: chiba
  • 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以外でも使えるように別の名前空間でモジュール化してもいいだろうし・・・。
まぁ今日はのところは疲れたのでこれぐらい。必要に駆られないとやらなそうだけどね。

以上、反撃終わり。

はてなブックマーク - さて、そろそろ反撃してもいいですか?(携帯サイトでCSSを3キャリア共通にする)

コメント:0

コメントフォーム
入力した情報を記憶する

トラックバック:0

この記事のトラックバック URL
https://blog.everqueue.com/chiba/2007/06/19/14/trackback/
トラックバックの送信元リスト
さて、そろそろ反撃してもいいですか?(携帯サイトでCSSを3キャリア共通にする) - へぼい日記 より

ホーム > perl > さて、そろそろ反撃してもいいですか?(携帯サイトでCSSを3キャリア共通にする)

検索
フィード
メタ情報

ページの上部に戻る