規則ファイルはhtmllintが読み込む各HTMLヴァージョンに対応した規則を記述したファイルです。あらかじめいくつか用意してありますが、これらは次のような手順で作成されています。

  1. DTDを用意する。SGML宣言は要りません。HTMLのDTD部分だけで十分です。SGML宣言は、あっても無視されます。また、他のDTDを展開するような記述は、ISO Latin 1 などの一部を除き展開されないので、必要ならば実際にそこに展開しておいてください。
    SCRIPTのイベント(intrinsic events)は、ATTLIST で onblur %Script; #IMPLIED のように %Script でパラメタ参照してください。
  2. parsedtd.plを用いて規則ファイルの雛形を作ります。
        perl parsedtd.pl xxxx.dtd > xxxx.rul
  3. DTDが理解できる範囲の記述ならば、規則ファイルxxxx.rulができあがります。あまり複雑なDTDは解釈できません。
  4. 生成される規則ファイルはPerlのスクリプトファイルで、中身は配列などの集まりです。それらは次のとおりです。
    %unknownStyleElements
    もし、この配列が含まれていたら、DTDにparsedtd.plの理解を超えた記述が含まれていたということです。DTDを平易に書き改めるか、parsedtd.plを賢く調教するしかありません。
    ちゃんと解釈できたときは、この配列は含まれていません。
    $emptyTags
    空要素タグ(終了タグのないタグ)です。
    $pairTags
    開始タグと終了タグの対で表現されるタグです。$pairTagsと$emptyTagsで、サポートしている全タグとなります。
    $deprecatedTags
    あまり薦められない形式のタグ。DTD中の、
        <![ %HTML.Deprecated [ <!ELEMENT TAGNAME ....> ]]>
    というような記述から、HTML.DeprecatedがINCLUDEのときに、このTAGNAMEが該当するとみなしています。
    $omitStartTags
    開始タグ省略可能なタグです。実際には、HTMLで開始タグの省略はほとんど行なわれないようです。
    $omitEndTags
    終了タグ省略可能なタグです。これらの中には、省略するのが一般的なタグも含まれます。その区別は、使用される状況から自動的に判定されます。
    $maybeEmpty
    開始タグと終了タグの間の要素が空でもよいタグです。
    %requiredTags
    必ず書かなければならないタグです。これらは、HTML全体の指定ではなく、あるタグ内ではどうかという指定であることに注意してください。
    %onceonlyTags
    あるタグ内の要素に書けるタグのうち、2つ以上書いてはいけないタグです。
    $sequencialTags
    タグ内の要素が順序どおりに現れなければならないタグです。
    %tagsElements
    タグ内の要素として書けるタグの一覧です。#PCDATAというのは普通のテキストを表わします。%で始まるものは、後述する%refParamsへの参照を表わします。
    %excludedElems
    タグ内の要素として禁止されるタグです。ここに指定されているタグは、入れ子になったタグ内の要素にも有効です。
    %includedElems
    タグ内の要素として許されるタグを追加指定します。%excludedElemsよりも優先します。
    $deprecatedElems
    タグ内の要素としてあまり薦められないタグ。自動的には生成されないので、手動かparsedtd.plをもう一度利用して作成します。
    %tagsAttributes
    各タグに指定できる属性の一覧と、その属性がどういう値を取るのかが示されています。CDATAやNUMBERなどは、SGMLで決められている書式を要求されるものです。%で始まるものは、後述する%refParamsへの参照を表わします。
    %requiredAttrs
    タグの属性として必ず指定しなければならない属性です。& で連結されているものはそれらがすべて指定されなければならないことを表わし、| で連結されているものはそれらのうちどれかひとつが指定さればいいことを表わします。parsedtd.plで作った直後はすべて & です。
    %deprecatedAtts/%deprecatedAttsCss
    あまり薦められない属性。これは、自動的には生成されないので、手動かparsedtd.plをもう一度利用して作成します(これについては後述してあります)。
    %deprecatedVals
    あまり薦められない属性値。これも、手動かparsedtd.plをもう一度利用して作成します(これについては後述してあります)。
    %refEntities
    実体宣言です。
    %refParams
    DTD中に大量にあるパラメータ宣言のうち、内部で利用するために残されているものです。ここには、CDATAやNUMBERなどの他に、正規表現と関数呼び出しが指定されています。正規表現は、大文字小文字区別されるので、必要ならば先頭に(?i)を付加して区別されないようにします。&で始まるものが関数呼び出しです。この関数は、htmllint内で用意されているものでなければなりません。parsedtd.plで作った直後はすべてCDATAやNUMBERなどです。
  5. できたばかりの規則ファイルは不完全です。なぜならば、DTDの解析だけでは自動的に読み取れない情報で重要なものが反映されていないからです。それらはたいていはコメントとしてDTD中に記述されているものです。主に次の3点です。
    • 属性値の取り得る値に制約のあるものが多い。DTD中では正規表現などが記述できないので、単にCDATAなどとなっている。
    • タグの属性のうち、どちらか一方が指定されればよいが、指定されなければならないようなものは、DTDでは記述できない。
    • これと似ているが、ある属性が特定の属性値を持つときだけ、他の属性を必要とするような場合。
  6. a.に関しては、%refParamsを書き換えます。ここは、最初はCDATAとかNUMBERとかばかりのはずなので、正規表現などを利用した書き方に変更します。値集合が規定されている属性値は、その大文字小文字が区別されないので、大文字小文字を区別したいようなときはhtmllint内に処理関数を用意しなければなりません。
  7. b.に関しては、%requiredAttrs内の & を | に変更します。DTD中で#REQUIREDとなっていない属性はここに現れないので、もしそういう属性がある場合は追加します。
  8. c.に関しては、うまく抽象化できていないので、それぞれのタグごとに例外処理をします。例えば、<INPUT>のNAME属性は、TYPEによって必要であったりそうでなかったりします。
  9. DTDには望ましくない記述が少なからずあります。例えば、<TABLE BGCOLOR=>の値は色です。色にはcolorというパラメータ宣言が定義されていますが、ここではそれが参照されていません (WilburもMSIEも)。このような本来参照すべきパラメータ宣言を参照していないものが多いので、それらをきちんと参照するようにしなければなりません。そうして、同じ意味のものは同じ%refParamsを参照するようにします。しかし、DTDとしてはどちらも同義なので、一概にDTDが悪いというわけではありません。
  10. ブラウザが勝手に拡張してしまっている属性値があります。例えば、いろいろなタグに出てくるWIDTH属性は、50%のような指定ができるものとそうでないものとがありますが、実際にはDTDどおりではありません。これらは、なるべく許容する方向で修正します。
  11. CDATAで示される属性値のうち、空が好ましくないものが少なからずあります。これらはCDATA+に変更します。
  12. $maybeEmptyは、DTDで (~)* などと記述されていると追加されますが、例えば、<TITLE> などの要素が空であるのは好ましくありません。このようなタグを配列から取り除いておきます。実際には、空でもよさそうなタグの方が少なく、それは次くらいです (私見)。
    • <LISTING>
    • <PLAINTEXT>
    • <PRE>
    • <SCRIPT>
    • <SERVER>
    • <STYLE>
    • <TD>
    • <TEXTAREA>
    • <TH>
    • <XMP>
  13. 各タグごとの%tagsElementsの順序は、$sequencialTagsで$omitStartTagsのときに意味を持ちます。その順序で開始タグが省略されていないか調べるからです。
  14. ラテン文字などに対する外部実体宣言は、("-//W3C//ENTITIES Special//EN//HTML" のような) 代表的なものだけが読み込まれています。もし、読み込まれていない場合は、%refEntitiesに含まれていません。必要ならば追加します。
  15. いくつかの薦められない要素などの情報は、ふたつの規則ファイル (HTML.DeprecatedがINCLUDEなものとIGNOREのもの) を作ってから調べることができます。
        perl parsedtd.pl -d include.rul ignore.rul
    この出力を include.rul に適当に埋め込みます。
  16. common.rulは、他の規則ファイルの不備を補うもので、新しい規則ファイルを作ったときはこのファイルの変更も必要です。他の規則ファイルよりも先に読み込まれます。
  17. common.rulの%doctypesに各DOCTYPEに関する情報を定義します。この連想配列のキーに.rulを付けたものが規則ファイルの名前になります。手抜きをしているので、htmllintのヘルプはこれに連動していません。

以上で規則ファイルの追加作業は終わりです。規則ファイルは htmllint と同じディレクトリに置くか、htmllint.env で指定されたディレクトリに置きます。