gulpでphpをhtmlに変換してValidateする。 [gulp-htmlhint]と[gulp-w3cjs]

#きっかけ
- WebサイトのHTMLを.phpでコーディングしている。
- gulpでHTMLのValidateをどうしてもしたい。
- gulpでHTMLをValidateするプラグインはいくつかある。
- .phpファイルをそのままValidateプラグインに通すと、php部分も判定対象になるので「構文エラーです」となってしまい使えない。
- gulpでphp→htmlに変換して、そのhtmlをValidateすればいいのでは？

↓

できました！

#このプラグインを使います
gulp-htmlhint
https://www.npmjs.com/package/gulp-htmlhint
gulp-w3cjs
https://www.npmjs.com/package/gulp-w3cjs

使うのはひとつでいいのですが重ね掛けしています。
理由は後述してあります。

#php → htmlに変換するには・・
こちらをご覧ください

gulpでphpをhtmlに変換する [gulp-php2html]
https://qiita.com/bonsai3/items/c33dfc902aed41899708

#事前準備

- ディレクトリ構成
 
```
/
├ html（php→html変換先、そしてValidate対象）
├ root（変換されるphp置き場）
  └ index.php
├ .htmlhintrc
├ package.json
└ gulpfile.js
```


- package.json

```javascript:package.json
{
    "name": "dev",
    "version": "1.0.0",
    "author": "",
    "main": "gulpfile.js",
    "license": "ISC",
    "devDependencies": {
        "gulp": "^3.9.1",
        "gulp-htmlhint": "^2.2.1",
        "gulp-php2html": "^0.3.2",
        "gulp-plumber": "^1.2.1",
        "gulp-w3cjs": "^1.3.1"
    }
}
```

- gulpfile.js

```javascript:gulpfile.js
// 環境変数
const setting = {
	html: {
		src: "./root/*.php",
		dest: "./html"
	}
};

const gulp = require("gulp");

// プラグインの読み込み
const php2html = require("gulp-php2html");
const htmlhint = require("gulp-htmlhint");
const plumber = require("gulp-plumber");
const w3cjs = require("gulp-w3cjs");

// phpからhtmlに変換するタスクを作成
gulp.task("html", () => {
	return (
		gulp
			// 変換対象のファイル
			.src(setting.html.src)
			// php→html変換
			.pipe(php2html())
			// htmlを保存
			.pipe(gulp.dest(setting.html.dest))
	);
});

// htmlをValidateするタスクを作成
// 「html」を実行してから、この「Validate」タスクを実行する
gulp.task("validate", ["html"], () => {
	return (
		gulp
			// Validate対象のファイル
			.src(setting.html.dest + "/**/*.html")
			// エラー発生時にgulpが強制停止するのを防止
			.pipe(plumber())
			// Validateする
			.pipe(htmlhint(".htmlhintrc"))
			// 追加でValidateする
			.pipe(w3cjs())
			// Validate結果をコマンドラインに表示
			.pipe(htmlhint.failReporter())
	);
});

// ファイルの変更を監視してタスク実行
gulp.task("watch", () => {
	gulp.watch(setting.html.src, ["validate"]);
});

// gulp起動時に実行するタスク
gulp.task("default", ["watch"]);
```

#.htmlhintrc

htmlhintの公式のオプション設定情報です
https://github.com/htmlhint/HTMLHint/wiki/Rules

こちらを参考にして外部ファイル「.htmlhintrc」を作成しました。
今回の設定はこちら↓

```javascript
{
	"tagname-lowercase": true,
	"attr-lowercase": false,
	"attr-value-double-quotes": true,
	"attr-value-not-empty": false,
	"attr-no-duplication": true,
	"doctype-first": false,
	"tag-pair": true,
	"tag-self-close": false,
	"spec-char-escape": true,
	"id-unique": false,
	"src-not-empty": false,
	"title-require": true,
	"head-script-disabled": false,
	"doctype-html5": true,
	"id-class-value": false,
	"style": true,
	"inline-style-disabled": true,
	"inline-script-disabled": false,
	"space-tab-mixed-disabled": "tab",
	"id-class-ad-disabled": false,
	"href-abs-or-rel": false,
	"attr-unsafe-chars": false,
	"alt-require": true
}
```

これをValidate時に読み込ませています。

```javascript
 // Validateする
.pipe(htmlhint(".htmlhintrc"))
```

#ポイント
タスク「html」を実行してから「validate」を実行しています。

この部分です

```javascript
gulp.task("validate", ["html"], () => {
```

#インストール
```CL
# package.jsonの内容をもとに、gulpとプラグインをインストール
$ npm install
```

#gulpを実行（起動）します
```CL
$ gulp
[12:19:45] Using gulpfile （ディレクトリパス）/gulpfile.js
[12:19:45] Starting 'watch'...
[12:19:45] Finished 'watch' after 9.34 ms
[12:19:45] Starting 'default'...
[12:19:45] Finished 'default' after 69
```

#結果

Validateしてみました

###その1

HTMLタグを間違ってみます

```html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<body>

<h1>タイトル</h2>

</body>
</html>
```

&lt;h1>の閉じタグを&lt;/h2>にしました

```CL
[11:16:07] Starting 'html'...
[11:16:07] Finished 'html' after 191 ms
[11:16:07] Starting 'validate'...
[11:16:07] HTML Error: index.html Line 9, Column 13: End tag “h2” seen, but there were open elements.
[11:16:07] <h1>タイトル</h2>
[11:16:07] 'validate' errored after 598 ms
[11:16:07] Error in plugin "gulp-htmlhint"
Message:
    2 errors found in C:(ディレクトリパス)\html\index.html
[L9:C9] Tag must be paired, no start tag: [ </h2> ] (tag-pair)
[L11:C1] Tag must be paired, missing: [ </h1> ], start tag match failed [ <h1> ] on line 9. (tag-pair)
```

無事にエラーがでました。ちゃんと怒ってくれました。
Validateされているようです。

プラグイン「gulp-htmlhint」と「gulp-w3cjs」の両方の結果が表示されます。
どれがどちらのプラグインのエラー表示かよくわからなくなりますが、
利用時にはどうでもよくなります。

「あぁ、なんかエラー出ているな。どこか間違ったな」に気が付ければOKです。

###その2

次はこちらです。

```html
<!DOCTYPE html>
<html>
<head>
	<meta charset="UTF-8">
	<title>test</title>
</head>
<body>

<ul>
	<li></li>
	<div></div>
</ul>

</body>
</html>
```

&lt;ul>の中に&lt;div>が入っています。

```CL
[11:20:27] HTML Error: index.html Line 11, Column 6: Element “div” not allowed as child of element “ul” in this context. (Suppressing further errors from this subtree.)
[11:20:27]      <div></div>
[11:20:27] Finished 'validate' after 652 ms
```

エラーが出ます。
gulp-htmlhintはこの記述を許容したようですが
gulp-w3cjsは怒りました。

「.htmlhintrc」のValidateルール設定が悪いのかもしれませんが・・

逆に
gulp-htmlhintは怒ったけど
gulp-w3cjsは許容した
というパターンもあった（ような思い出がある）ので

ダブルチェックということでValidateプラグインを2つ重ねています。


以上です。
ありがとうございました。