ziguzagu.org

CSS::Parse::Packed

CSS::Parse::Packed というモジュールを CPAN に up しましたので、使い方なんかを解説したいと思います。ちなみに CPAN 初登録です。むふ。

使いかた

CSS モジュールの parser のひとつなので、CSS モジュールの使いかた準拠です。詳しくは CSS モジュールの POD なんかを参照してください。

以下、サンプルです。

#!/usr/bin/perl
use strict;
use warnings;
use CSS;

my @styles = (
    q{body { background-color:#FFFFFF; font-size: 1em; }},
    q{body { padding:6px; font-size: 1.5em; }},
);

my $css = CSS->new({ parser => 'CSS::Parse::Packed' });
$css->parse_string($_) for @styles;
print $css->output;

出力結果はこうなります。

body { padding: 6px; background-color: #FFFFFF; font-size: 1.5em }

標準の parser たちとなにが違うのか?

CSS モジュールの標準の parser たちは、ひとつのセレクタを parse したら順番に配列に入れていきます。そのため output メソッドからは入れたものが順番にでてきます。前述のサンプルの parser をデフォルトの CSS::Parse::Lite に変更すると以下のような結果がでてきます。

body { background-color: #FFFFFF; font-size: 1em }
body { padding: 6px; font-size: 1.5em }

そのままHTMLに埋め込んだりする分にはなんの問題もないです。

ただし、get_style_by_selector という指定したセレクタの style を取得するというメソッドがあるのですが、これが配列の先頭からなめていって最初にでたものをそのまま返す、というつくりになっています。先のサンプルを以下のように変更してみます。

my $css = CSS->new({ parser => 'CSS::Parse::Packed' });
$css->parse_string($_) for @styles;
print $css->get_style_by_selector('body');

CSS::Parse::Lite を使った場合の出力は、

body { background-color: #FFFFFF; font-size: 1em }

となります。最初の1つが出てくるのみです。実際に、body にはもうひとつ別の style が書かれているのですが、それを取得することはできません。CSS::Parse::Packed を使うと以下が出てきます。

body { padding: 6px; background-color: #FFFFFF; font-size: 1.5em }

ブラウザが実際に解釈する(であろう)プロパティがすべて入っている状態です。

CSS::Parse::Packed は、はっきりいうとこの get_style_by_selector で上記のような結果を取得したい場合に使う parser という感じです。

使いどころ

えー、あんまりないと思いますがひとつだけ。

DoCoMo の XHTML で CSS が使えるのですが inline css のみ対応なので、実際に CSS に対応させるのはひじょーに面倒くさいです。そこで、CSS モジュールの登場なのですが、CSS ファイルを分割したい(共通+ページごととか)場合などは、標準の parser + get_style_by_selector だと、最初にでてきたセレクタのみ適用されてしまってしょぼーん、という問題があります。

そこで、CSS::Parse::Packed を使うと複数のファイルでスタイルがそれぞれ定義されていても、ひとつのセレクタにまとめてくれるので、本来適用されるプロパティが全部もってこれます。

まとめ

という感じで、レアな状況にニッチに対応するモジュールです。

あと、今のところ実際に CSS を parse する仕組みは CSS::Parse::Lite の正規表現をそのまま使っていますが、需要があれば今後は別の parse 方法も使えるような形にもっていったほうがよいかなぁ、と思っていたりします。

どうぞよろしく。