「システム内の jsp にある label 要素の for 属性が正しく設定されているか調査したい」と知り合いに相談されて、ぱっと解決策が浮かばなかった。
別な行だったり離れていたりする場合があり、単純な文字列検索では難しい。ページ単位でアクセシビリティ系のツールで調査できそうだが、システム内に数多くある Web ページを一括で調査するのは大変そう。あと地味に jsp という単純に html としてパースし辛い対象であることも課題。
結局、NodeJS で簡単なツールを書いて渡したので、メモとして残しておきます。
label 要素の for 属性
今回相談されたのは、例えば以下のように間違った html が読み込まれた場合、
<html>
<body>
<label for="name1">test label</label>
<input id="id1" name="name1" />
</body>
</html>
Chrome ブラウザだと以下のようにエラー表示がされてしまうという状況。
label 要素の for には対象の name でなく、id を渡す必要がある。これ昔はエラーにならなかった、もしかしたら name でも動作してくれたような気さえするのだけれど、今は明確な HTML標準違反になる。
まずは調査対象の一覧を生成してみる
npm とか説明するのは面倒なので、NodeJS 基本ライブラリのみで動作する簡単なツールを作成してみる。まずは File I/O を使って、指定したフォルダ内にあるすべての jsp ファイルのファイル名を表示させてみよう。
const fs = require('fs')
const target = process.argv[2] || '.'
const fmatch = /\.jsp$/
// Search for file names that match the conditions and execute the process
function _process(_fname, _func) {
const dir = fs.opendirSync(_fname)
let dirent
while (dirent = dir.readSync()) {
const fname = _fname + '/' + dirent.name
if (dirent.isDirectory()) {
_process(fname, _func)
} else {
if (fmatch.test(fname)) {
_func(fname)
}
}
}
}
// Main Logic
_process(target, _fname => {
console.log(_fname)
})
再帰を使って、フォルダ内のファイルを順にみていくだけの、わりと平凡な処理ですね。
for 属性の確認ロジックを書いてみる
Main Loop 部分を書き換えます。
同じファイル内にある label の for 属性値の一覧を作成し、ファイル内にその id を指定した入力要素があるか探し、なければ表示します。対象の入力要素、これで足りているかしらん?
// Main Logic
let count = 0
_process(target, _fname => {
const html = String(fs.readFileSync(_fname))
// Generate a list of the for attributes of label elements
const targets = html.match(/<label\s[^>]*for\s*=\s*"[^"]+"/g)
const ids = []
if (targets) {
targets.forEach(target => {
const id = target.match(/<label\s[^>]*for\s*=\s*"([^"]+)"/)
ids.push(id[1])
})
}
// Check if the specified ID exists
let flag = true
ids.forEach(id => {
const reg = '<(?:input|textarea|select|button)\\s[^>]*id\\s*=\\s*"' + id + '"'
if (!html.match(reg)) {
console.log(_fname + ',' + id)
if (flag) {
count++
flag = false
}
}
})
})
console.log('Number of files,' + count)
実行結果は以下の感じ。出力を *.csv ファイルにリダイレクトして保存し、EXCEL などで管理する想定です。
というわけで
さっと作成した簡易ツールなので、それほど便利ではないかもしれませんね。
こちらのコードは利用自由の Creative Commons 0 (CC0) ライセンスとしますので、いろいろ拡張して、自由に使ってみてください。
ではでは。