オフラインHTMLバリデーター「HTML-validate」がいい感じ　項目一覧もあるヨ

[すっ飛ばして項目一覧へ👇](#項目一覧)

# はじめに
こんにちは、ウィケです。
皆さんは普段、出来上がったHTMLをどうやってチェックしていますか？
W3Cのバリデーターにかけたり、開発環境にリンターを仕込んでおいたり、
はたまた特に何もしていないよーなどいろいろな状況におられることかと思います。

ここのところ、CSSはstylelint、JSはeslintかけとけばオッケー！という風潮になってきているなと感じているのですが、
HTMLはコレ！というものがないのが悩みでした（しいていえばW3CのMarkup Validation Serviceですかね）。
でいろいろ調べていたところ、HTML-validateがいい感じだと思ったのでメモしておきます。

# HTML-validateがオヌヌメの理由

本家サイト: [HTML-validate](https://html-validate.org/)
npmのページ: [html-validate - npm](https://www.npmjs.com/package/html-validate)

## オフラインで使える
これよ～これ。今回の私的決め手です。
お仕事でWeb制作をするとき、内容的にはW3CのMarkup Validation Serviceを利用するので充分だと思うのですが、公開前のサイト情報を外部に送信している点が気になっていました。
もちろん、現状それが危ない！ということはないのですが、なにかの手違いが起きたら怖いですし、外部に出さずに完結できたらいちばんいいよねと思っていたので、オフラインで使えるのは嬉しいです。
（調べたところ、W3Cのチェッカーを自前のサーバーに構築することができるようです。それができればより安全ですが、Javaができないので白目をむきながら見送らせていただきました）

## 頻繁に更新されている  
今のところ数日に１回のペースでバグフィックスなどが行われています。数年単位で放置されているツールも多いのでありがたいことです。

## 詳細にチェックしてくれる
eslintよろしくrecommended（おすすめ設定）があるのですが、それだけでもかなり細かくチェックしてくれます。
HTMLの簡単なlintツールはたくさんありますが、タグの閉じミスなどは判別してくれても、入れ子のルールを守っているか（例えば、`<p>`の中に`<div>`がある 等）はチェックしてくれないものがほとんどです。
凡ミスも文書構造もチェックしてくれるのはありがたいです。

## いろんなツールに対応している  
npm-scriptsで使うのがいちばんお手軽ですが、VSCodeのプラグインやVue、Angularなどいろいろなツールに対応しています。
公式のUser guideにわかりやすくまとめられています（英語ですが）。

# 項目一覧
項目名のリンクで公式の解説ページに飛べます。

執筆時のバージョン: `2.19.0`

## Available rules
| 項目  | 内容 | 備考 | 
| --------  | -------- | -------- | 
| [close-attr](https://html-validate.org/rules/close-attr.html) | *Disallow end tags from having attributes*<br>終了タグに属性がついていないか | **recommended** |
| [close-order](https://html-validate.org/rules/close-order.html) | *Require elements to be closed in correct order*<br>正しい順序で要素が閉じられているか | **recommended** |
| [deprecated](https://html-validate.org/rules/deprecated.html) | *Disallow usage of deprecated elements*<br>非推奨の要素を使用していないか | **recommended**<br>NG: \<center\> |
| [deprecated-rule](https://html-validate.org/rules/deprecated-rule.html) | *Disallow usage of deprecated rules*<br>非推奨のルールを使用していないか | **recommended**<br>このバリデーター内の古いルールを使っていないかということ |
| [doctype-html](https://html-validate.org/rules/doctype-html.html) | *Require usage of "html" doctype*<br>doctype宣言はhtmlか | **recommended**<br>`<!DOCTYPE html>`のみOK<br>レガシーな宣言は許容されない |
| [element-name](https://html-validate.org/rules/element-name.html) | *Disallow invalid element names*<br>無効な要素名がないか | **recommended**<br>カスタム要素のルール<br>・`a-z`で始まっているか<br>・`-`（ダッシュ）が含まれているか |
| [meta-refresh](https://html-validate.org/rules/meta-refresh.html) | *Require meta refresh to have 0 second delay*<br>`meta http-equiv="refresh"`の遅延は0秒か | **recommended**<br>他ページにリダイレクトさせるときは0秒を指定する<br>リロードは許可されない |
| [no-conditional-comment](https://html-validate.org/rules/no-conditional-comment.html) | *Disallow usage of conditional comments*<br>条件付きコメントがないか | **recommended**<br>NG: `<!--[if IE]>` |
| [no-deprecated-attr](https://html-validate.org/rules/no-deprecated-attr.html) | 	*Disallow usage of deprecated attributes*<br>廃止された属性を使っていないか | **recommended** |
| [no-dup-attr](https://html-validate.org/rules/no-dup-attr.html) | *Disallow duplicated attributes*<br>属性が重複していないか | **recommended** |
| [no-dup-class](https://html-validate.org/rules/no-dup-class.html) | *Disallow duplicated classes*<br>クラスが重複していないか | **recommended** |
| [no-dup-id](https://html-validate.org/rules/no-dup-id.html) | *Disallow duplicated IDs*<br>IDが重複していないか | **recommended** |
| [no-raw-characters](https://html-validate.org/rules/no-raw-characters.html) | *Disallow the use of unescaped special characters*<br>特殊文字はエスケープされているか | **recommended**<br>`<` →  `&lt;`<br>`>` → `&gt;`<br>`&` → `&amp;`|
| [no-redundant-role](https://html-validate.org/rules/no-redundant-role.html) | *Disallow usage of redundant roles*<br>冗長なroleを指定していないか | **recommended**<br>NG: `<main role="main">` |
| [no-style-tag](https://html-validate.org/rules/no-style-tag.html) | *Disallow usage of \<style\> tag*<br>\<style\>タグを使用していないか |  |
| [no-unknown-elements](https://html-validate.org/rules/no-unknown-elements.html) | *Disallow usage of unknown elements*<br>不明な要素を使用していないか |  |
| [prefer-button](https://html-validate.org/rules/prefer-button.html) | *Prefer to use \<button\> instead of \<input\> for buttons*<br>buttonに\<input\>ではなく\<button\>を使用しているか | **recommended**<br>NG: `<input type="button">`<br>OK: `<button type="button"></button>` |
| [prefer-tbody](https://html-validate.org/rules/prefer-tbody.html) | *Prefer to wrap \<tr\> inside \<tbody\>*<br>\<tr\>を\<tbody\>で囲っているか | **recommended** |
| [require-sri](https://html-validate.org/rules/require-sri.html) | *Require SRI for resources*<br>リソースにSRIがあるか | 例: jQueryをCDNで利用するときの`integrity`属性 |
| [script-type](https://html-validate.org/rules/script-type.html) | *Require valid type for `<script>`*<br>`<script>`に妥当なtypeがあるか | **recommended** |
| [unrecognized-char-ref](https://html-validate.org/rules/unrecognized-char-ref.html) | *Disallow unrecognized character references*<br>認識されない文字参照を使用していないか | **recommended** |

## Content model
| 項目  | 内容 | 備考 | 
| --------  | -------- | -------- | 
| [attribute-allowed-values](https://html-validate.org/rules/attribute-allowed-values.html) | *Validate permitted attribute values*<br>要素の属性が正しいか | **recommended** |
| [element-permitted-content](https://html-validate.org/rules/element-permitted-content.html) | *Validate permitted content from content model*<br>要素のコンテンツモデルが正しいか | **recommended** |
| [element-permitted-occurrences](https://html-validate.org/rules/element-permitted-occurrences.html) | *Validate permitted number of occurrences from content model*<br>要素の出現回数が正しいか | **recommended**<br>ひとつのtableにtfootはひとつだけ等 |
| [element-permitted-order](https://html-validate.org/rules/element-permitted-order.html) | *Validate required order from content model*<br>要素の順序が正しいか | **recommended** |
| [element-required-attributes](https://html-validate.org/rules/element-required-attributes.html) | *Ensure required attributes are set*<br>要素に必須の属性があるか | **recommended**<br>中身は空でもOK |
| [element-required-content](https://html-validate.org/rules/element-required-content.html) | *Ensure required elements are present*<br>必須の要素があるか | **recommended**<br>`<body>`やhead内`<title>`等 |
| [script-element](https://html-validate.org/rules/script-element.html) | *Require end tag for `<script>`*<br>`<script>`の閉じタグがあるか | **recommended** |
| [void-content ](https://html-validate.org/rules/void-content.html)| *Disallow void element with content*<br>空要素に閉じタグがないか | **recommended**<br>NG: `<img></img>` |

## Accessibility
| 項目  | 内容 | 備考 | 
| --------  | -------- | -------- | 
|[ empty-heading](https://html-validate.org/rules/empty-heading.html) | *Require headings to have textual content*<br>見出し要素にテキストコンテンツが含まれているか | **recommended** |
| [empty-title](https://html-validate.org/rules/empty-title.html) | *Require title to have textual content*<br>`<title>`にテキストコンテンツが含まれているか | **recommended** |
| [input-missing-label](https://html-validate.org/rules/input-missing-label.html) | *Require input to have label*<br>入力要素にlabelが関連付けられているか | `input`や`select`等を`label`で囲うかforで関連付ける |
| [prefer-native-element](https://html-validate.org/rules/prefer-native-element.html) | *Prefer to use native HTML element over roles*<br>roleではなくネイティブのHTML要素を使っているか | **recommended**<br>HTMLで出来るならやろうという意味<br>NG: `<div role="main">`<br>OK: `<main>` |
| [svg-focusable](https://html-validate.org/rules/svg-focusable.html) | *Require \<svg\> to have focusable attribute*<br>svg要素にfocusable属性があるか | **recommended**<br>IE用に明示が必要らしい |
| [wcag/h30](https://html-validate.org/rules/wcag/h30.html) | *WCAG 2.1 H30: Providing link text*<br>リンクにテキストが含まれているか | **recommended**<br>以下のどれかが必要<br>・リンク内テキスト<br>・リンク内画像のalt<br>・リンク本体or子要素のaria-label |
| [wcag/h32](https://html-validate.org/rules/wcag/h32.html) | *WCAG 2.1 H32: Providing submit buttons*<br>`form`に送信ボタンがあるか | **recommended** |
| [wcag/h36](https://html-validate.org/rules/wcag/h36.html) | *WCAG 2.1 H36: Require alt text on images used as submit buttons*<br>送信ボタンとして使われる画像にaltテキストが入っているか | **recommended** |
| [wcag/h37](https://html-validate.org/rules/wcag/h37.html) | *WCAG 2.1 H37: Using alt attributes on img elements*<br>imgにaltがあるか | **recommended** |
| [wcag/h67](https://html-validate.org/rules/wcag/h67.html) | *WCAG 2.1 H67: Using null alt text and no title attribute on img elements*<br>imgでaltが空の場合にtitleを使用していないか | **recommended** |
| [wcag/h71](https://html-validate.org/rules/wcag/h71.html) | *WCAG 2.1 H71: Providing a description for groups of form controls*<br>フォーム入力項目のグループに説明があるか | **recommended**<br>`<fieldset>`のはじめに`<legend>`が必要 |

## SEO
| 項目  | 内容 | 備考 | 
| --------  | -------- | -------- | 
|[ long-title](https://html-validate.org/rules/long-title.html) | *Require title not to have too long text*<br>タイトルが長すぎないか | **recommended** |

## Style
| 項目  | 内容 | 備考 | 
| --------  | -------- | -------- | 
| [attr-case](https://html-validate.org/rules/attr-case.html) | *Require a specific case for attribute names*<br>属性名が指定された形式か | **recommended**<br>初期設定ではlowercase<br>NG: `<p ID="foo">`<br>OK: `<p id="foo">` |
| [attr-quotes](https://html-validate.org/rules/attr-quotes.html) | *Require attribute quoting*<br>属性の引用符が指定された形式か | **recommended**<br>初期設定では、属性値に`"`が含まれていない場合は`"`を使用する |
| [attribute-boolean-style](https://html-validate.org/rules/attribute-boolean-style.html) |*Require a specific style for boolean attributes*<br>boolean属性が指定された形式か | **recommended**<br>初期設定では値を省略する<br>OK: `<input required> `<br>NG: `<input required="">`<br>NG: `<input required="required">`  |
| [attribute-empty-style](https://html-validate.org/rules/attribute-empty-style.html) | *Require a specific style for empty attributes*<br>値のない属性が指定された形式か | **recommended**<br>初期設定では空の文字列を省略する<br>OK: `<a download></a>`<br>NG: `<a download=""></a>` |
|[ class-pattern](https://html-validate.org/rules/class-pattern.html) | *Require classes to match a specific pattern*<br>クラスが指定された形式か | オプションで `kebabcase`, `camelcase`, `underscore`, 正規表現が設定できる |
| [element-case](https://html-validate.org/rules/element-case.html) | *Require a specific case for element names*<br>要素が指定された形式か | **recommended**<br>オプションで `camelcase`, `lowercase`, `pascalcase`, `uppercase` が設定できる。<br>複数設定（どれかに当てはまればOK）もできる |
| [id-pattern](https://html-validate.org/rules/id-pattern.html) | *Require IDs to match a specific pattern*<br>IDが指定された形式か | オプションで `kebabcase`, `camelcase`, `underscore`, 正規表現が設定できる |
| [no-implicit-close](https://html-validate.org/rules/no-implicit-close.html) | *Require elements with optional end tags to be explicitly closed*<br>要素の終了タグを省略していないか | **recommended**<br>NG:<br>`<li>hoge`<br>`<li>fuga`<br>OK:<br>`<li>hoge</li>`<br>`<li>fuga</li>` |
| [no-inline-style](https://html-validate.org/rules/no-inline-style.html) |*Disallow inline style*<br>インラインスタイルを記述していないか | **recommended** |
| [no-self-closing](https://html-validate.org/rules/no-self-closing.html) | *Disallow self-closing elements*<br>要素にコンテンツがない場合も閉じタグがあるか | **recommended**<br>OK: `<div></div>`<br>NG: `<div />` |
|[ no-trailing-whitespace](https://html-validate.org/rules/no-trailing-whitespace.html) | *Disallow trailing whitespace*<br>行末に空白がないか | **recommended** |
| [void](https://html-validate.org/rules/void.html) | *Disallow void element with content*<br>空要素にコンテンツや終了タグがないか | **recommended**<br>この項目は非推奨ぽい<br>他の項目（ `void-content`, `void-style`, `no-self-closing` ）でチェックされる |
| [void-style](https://html-validate.org/rules/void-style.html) | *Require a specific style for closing void elements*<br>空要素の閉じ方が指定された形式か | **recommended**<br>初期設定では終了タグは省略する<br>OK: `<input>`<br>NG: `<input />` |

## Document
| 項目  | 内容 | 備考 | 
| --------  | -------- | -------- | 
| [heading-level](https://html-validate.org/rules/heading-level.html) | *Require headings to start at h1 and be sequentia*<br>見出し要素がh1から始まり、順序が正しいか |  |
| [missing-doctype](https://html-validate.org/rules/missing-doctype.html) | *Require document to have a doctype*<br>doctype宣言があるか |  |
| [no-missing-references](https://html-validate.org/rules/no-missing-references.html) | *Require all element references to exist*<br>参照する要素が存在しているか | `<label for="hoge">`などと指定したときに`hoge`が存在しないのはNGという意味 |

（英語に全く自信がないので、改善提案いただけると喜びます:girl_tone1:）

# おわりに
HTMLって昔っからあるのにいつまで経ってもフワフワしてる感じがします。
CSSやJSと比べても、いちばん素人の方の手が入りやすいので、いちばんチェックしたいはずなのですが……。

W3Cのバリデーターに関しては、大企業ほどマニュアルで使うように指定してくるところが多く安定しているイメージです。
逆にイケイケチームは、JSで吐き出すのでもはやHTMLなどアウト・オブ・眼中なイメージです。
でもどちらの場合も最終的に出力されたHTMLを私は見ていますよ:eyes:
**ミテイルゾ**:eye::eye:

# 参考
[HTML-validate](https://html-validate.org/)
[HTML-validate - Rules](https://html-validate.org/rules/)