markuplintのクセにつまずく

HTML Linter今昔

ここ数年 HTML のよさげな Linter を探していた。HTML については歴史が古い分、ツールについても挙動の古いものも多い。

大昔で言えば Another HTML-lint が日本では有名どころであり、また W3C にも W3C Validator があったが、いずれも Web UI で、コマンドラインで起動して一括で処理するには向いていなかった。

最近だと Another HTML-lint にも W3C Validator にも後継があって、特に W3C のものは

The Nu Html Checker (v.Nu)

に公開されていて、これは pip, npm でもインストールできる。インストールはできるが Java Runtime も必要になる。試しに docker run を叩いてみたら何も返事がない状態になってしまったので npm で

vnu-jar - npm

を入れてみたが、どうもこれは完成品の HTML を相手にすべきもののようだ。そうなるとコーディング中にシュッと利用できる ESLint や Stylelint のようなものというよりは、もう少し後工程のためのものと言えそうだ。

これはあまり現代的な感じがしないのと、動的サイトに対しては結局できあがった仕組みに対して URL を叩いて取得してくる方法になるので HTML / CSS コーディングの工程からだいぶ距離ができてしまう。

pure npmでサッと使えるmarkuplintがよさそう

一方で Web フロントエンドの環境としてとりあえず Node.js が動くのはある程度期待してよいと思われるので、npm でシュッと叩けるものはないかと探してみたが、どうも道半ばで放置されているものが多そうに見える。

そんな中、

markuplint - A Linter for All Markup Languages. | markuplint

を見つけたのだが、これは面白い。何しろ 2022-05-15 時点で

  • PHP
  • ERB
  • Mustache
  • Liquid

に対応している。一見古びたフォーマットのように見えるが、「これこれ、こういうものこそ実は linter 掛けたいやつ」と喜んでしまった。というか個人的にはだいぶ助かる。

しかし、謎の「文字参照でエスケープするべきです」

とりあえず

markuplint --init

してできあがった、recommended ルール付きの設定ファイルを使って実際のサイトに対して lint を実行すると以下のような課題に当たった。

  1. doctype が必要と言う
  2. h1 が必要と言う
  3. なぜか普通のタグの始まりの < に対して「不正な文字は文字参照でエスケープするべきです」と言う

このうち 1, 2 についてはすぐに当たりがついた。HTML をパーシャルに分割したり共通の layout ファイルを用意したりしているためもあって、lint 対象の HTML は完全な HTML になっていない。また、これらはすぐに設定からオフにすることができた。

その他、細かい属性や ARIA roles など、自分の知識の足りていない部分を確認することができたのはよかった。しかし 3 だけは理解できなかった。

謎の再現

例えば

markuplint の repository から test/fixtures/001.html

markuplint/001.html at dev · markuplint/markuplint

yarn cli --config test/fixtures/.markuplintrc test/fixtures/001.html

と実行すると pass する普通の HTML 文書である。

ここから doctype と <html> を削除すると end-tag の <>

不正な文字は文字参照でエスケープするべきです

と言われてしまう。

ところが <head> の中身だけにすると怒られなくなる。

どうも HTML 文書全体か一部かの判別をどこかで行なっているように見える。このルールが分からない。

これが分からないと partial や layout に対して安心して lint を実行することができない。まぁ特定のファイルを除外するとかできなくはないんだけど、本当にエスケープしてほしい箇所も弾かれなくなってしまうし、これは実に惜しい…。

これが解決できないとすると結局ビルド済みの完全な HTML を対象にすべき、という話になってしまう。だとすると Liquid や ERB の parser も不要なわけですよ。

どうしたもんだろねぇ。(解決はしてません。)

More