0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

label 要素の for 属性が正しく設定されているか調査する

Posted at

「システム内の 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 ブラウザだと以下のようにエラー表示がされてしまうという状況。

image.png

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 などで管理する想定です。

image.png

というわけで

さっと作成した簡易ツールなので、それほど便利ではないかもしれませんね。

こちらのコードは利用自由の Creative Commons 0 (CC0) ライセンスとしますので、いろいろ拡張して、自由に使ってみてください。

ではでは。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?