Subscribed unsubscribe Subscribe Subscribe

HTML::FillInFormによるConditional Commentsの扱いがちょっと微妙?

どうもCatalyst::Plugin::FillInFormfillformしたときに不思議な出力をしていて、調べてみると 中のHTML::FillInFormがcommentの部分をゴニョゴニョやっているあたりに問題があるようだった。


例えば、下記のようなコード。

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

use HTML::FillInForm;

my $data = join '', <DATA>;
print HTML::FillInForm->new->fill(
    scalarref => \$data,
    fdata => {}
);

__DATA__
<!DOCTYPE html>
<html>
  <head>
    <title>title</title>
  </head>
  <body>
    <![if !IE]>hoge<![endif]>
    <!--[if !IE]>-->fuga<!--<![endif]-->
    <!piyo>
  </body>
</html>

Catalyst::Plugin::FillInForm::fillformでも、このようにHTML::FillInFormnewしてfillを呼ぶ形になっていて、上記コードを実行すると下記のような結果になる。

<!DOCTYPE html>
<html>
  <head>
    <title>title</title>
  </head>
  <body>
    <![if !IE]>hoge<![endif]>
    <![if !IE]>>fuga<!--<![endif]-->
    <!--piyo-->
  </body>
</html>

"hoge"の行は"downlevel-revealed"と呼ばれるConditional Commentsという形式のもので、問題なくそのまま出力される。
"fuga"の行はそれをvalidation通すために使われる記法らしい。が、これが変な形で出力されてしまっている。
"piyo"の行は正しい形のHTMLコメントではないがHTML::FillInFormによって正しい形式のコメントに変換されている。

About conditional comments (Internet Explorer)
条件付きコメント - Wikipedia


とにかく"fuga"の行がおかしくなってしまっている。HTML::FillInFormを読むと、

sub comment {
    my ( $self, $text ) = @_;
    # if it begins with '[if ' and doesn't end with '<![endif]'
    # it's a "downlevel-revealed" conditional comment (stupid IE)
    # or
    # if it ends with '[endif]' then it's the end of a
    # "downlevel-revealed" conditional comment
    if(
        (
            ( index($text, '[if ') == 0 )
            &&
            ( $text !~ /<!\[endif\]$/ )
        )
        ||
        ( $text eq '[endif]' )
    ) {
        $self->{output} .= '<!' . $text . '>';
    } else {
        $self->{output} .= '<!--' . $text . '-->';
    }
}

という部分があり、どうやらHTML::FillInFormの親クラスHTML::Parserでは<!-- ... -->の形式以外でも<! ...>のような形のものもコメントとして認識し、出力する際にConditional Commentかどうかを判別して完全なコメントアウトではなく<!...>になるよう調整しているようだ。
ところがその除外ルールが<!--[if !IE]>-->にも適用されてしまうため、上記の"fuga"の行がおかしなことになってしまうようだ。


$self->strict_comment(1);で正しくない形式のコメントは無視してしまって

sub comment {
    my ( $self, $text ) = @_;
    $self->{output} .= '<!--' . $text . '-->';
}

とやってしまえば上記のような事態にはならずに済むけど、そういうわけにはいかないのだろうか? そうすることによってチェックされなくなってしまうものが出てしまうとまずいのかな…。