CSS::Tiny::Styleについて
CSS::Tiny::Styleについて、下記の問題にぶち当たった。
- capnモジュールでインストールする際、Test::Perl::Criticの検査に引っかかる
- 属性名や擬似クラス名にハイフンやアンダースコアが入ると、きちんとパースされない
これらについて少し調べた。
Test::Perl::Criticに引っかかる件
エラーで指示されていた箇所のソースを見てみた。
まず三行目。
#Code before strictures are enabled at line 3, column 14. See page 429 of PBP. (Severity: 5) package CSS::Tiny::Style; use version; $VERSION = qv('0.0.3'); # 3行目 use warnings; use strict; use Carp;
このエラーメッセージが怒っているのは、strictプラグマの前にコードがあること。したがって、strictプラグマがuseされた後にコードを持っていくと、エラーメッセージが出なくなる。しかし、$VERSIONは、スコープの宣言がされてないのでstrictプラグマに引っかかる。versionモジュールの「BEST PRACTICES」を見るとour宣言してるのでそれに従う。
use warnings; use strict; use version; our $VERSION = qv('0.0.3');
もう一つのエラー。
# Stricture disabled at line 138, column 5. See page 429 of PBP. (Severity: 5) no strict 'refs';
PBPでは、no strictは許していないみたい。CSS::Tiny::Styleでは、下記のように関数を呼び出したいからno strictしている。
for (qw/tag id class/) { my $sub = "_$_"; next unless (my $val = &$sub($sel)); # strict 'ref'では禁止されている関数呼び出し
これをやらなければno strictする必要はなくなる。もし面倒だったりどうしても必要な場合は、下記のように記述すれば、Test::Perl::Criticの検査の対象とならなくなる。
no strict 'refs'; ## no critic
以上の対処で、Test::Perl::Criticの検査に通るかどうかを下記のプログラムを書いて確かめた。
#!/usr/bin/perl use strict; use Test::More; eval { require Test::Perl::Critic; Test::Perl::Critic->import(-profile => 't/perlcriticrc') }; plan skip_all => "Test::Perl::Critic is not installed." if $@; all_critic_ok("CSS/Tiny/");
okもらった。
きちんとパースされない件
セレクタにアンダースコアやハイフンが入ると、
CSS::Tiny::Styleの_sel_arrメソッドの下記の部分で無限ループが起こる。
while ($_) { my ($tag, $op); s/([a-zA-Z0-9.\#\*]+)\s*$//; $tag = $1; $op = $1 if (s/(\s*[+>]*\s*)$//); push @d, $tag if $tag; for ($op) { /\+/ && do { push @d, 'left'; last; }; /\>/ && do { push @d, 'parent'; last; }; /^\s+$/ && do { push @d, 'lineage'; last; }; } }
「s/([a-zA-Z0-9.\#\*]+)\s*$//;」の部分で、ハイフンとアンダースコアがマッチしないようになっている。マッチしたものは削除していき、$_が空になったらループを抜け出すようになっているので、無限ループになる。例えば「hato_uhouho」というセレクタがあったら「hato」だけがマッチし、2回目以降のループでは、$_の値は「_uhouho」になるので、ずっとマッチしない。
ということで、単純にハイフンとアンダースコアにマッチするように下記のように書き換えた。
s/([a-zA-Z0-9.\#\*_-]+)\s*$//; $tag = $1;
これで一応、無限ループは回避された。
しかし、ちゃんと動くかどうかはまだ確認していない。
もう少し、CSS::Tinyを細かく読んでことにする。