Skip to content
This repository was archived by the owner on Sep 24, 2026. It is now read-only.

Report img without alt and interactive content in a; document parser gaps - #2

Merged
casoon merged 3 commits into
masterfrom
fix/missing-findings
Sep 14, 2026
Merged

casoon merged 3 commits into
masterfrom
fix/missing-findings

Conversation

@casoon

@casoon casoon commented Sep 14, 2026

Copy link
Copy Markdown
Owner

Four constructs that vnu flags produced no finding when placed alone in an otherwise valid document. What each one turned out to be:

Case Root cause This PR
<img> without alt Missing rule: only the figure-without-figcaption case existed Fixed: assertion.elements.img-missing-alt, following vnu's general missing-alt branch and its exemptions (aria-label, aria-labelledby, non-empty title; role/other aria-* keep their existing, more specific rules)
<button> inside <a> Missing rule: vnu's interactive-descendant check for a had no counterpart (only a few button-ancestor rules existed) Fixed: elements-interactive-in-a pattern, vnu's full list (button, select, textarea, label, details, dialog, embed, iframe, a, non-hidden input, video/audio[controls], img/object[usemap], [tabindex], interactive roles), one finding per element in vnu's else-if order
stray </div> Parse error not recorded by html5-parser 0.3.0: StrayEndTag is only emitted on the "any other end tag" path (</span>, </b>), not in the block, li, dd/dt or heading end-tag branches Documented gap
misnested <b><i>…</b></i> Parse error not recorded by html5-parser 0.3.0: the adoption agency algorithm repairs the tree without recording an error Documented gap

The two parser cases can't be fixed in this crate. The dropped tokens leave no trace in the tree, the same reason the stray-<!DOCTYPE> gap is already documented in src/parse.rs. The fix is in html5-parser: record the parse error at the remaining §13.2.6.4.7 "in body" end-tag branches and adoption agency steps, release it, then bump the =0.3.0 pin here. Two #[ignore]d regression tests in src/lib.rs reproduce both cases.

Docs

  • README: the parser layer and the "tree-construction-error tracking landed" note now say only part of the tree-construction errors are covered. There is a new "What's not covered" section.
  • docs/guides/vnu-comparison.md and docs/guides/rule-ids.md describe the parser gap. The differential test does not show it: the corpus fixtures vnu flags for a stray </header> or </td> still count as true positives, through unrelated heading and table findings.
  • Showcase: content-model.html now includes both new findings. The JSON was regenerated with cargo run --example findings, and the description in site/src/showcase.ts was updated.
  • CHANGELOG Unreleased entry.

Validation

  • cargo fmt --check, cargo clippy --all-targets -- -D warnings, cargo test (417 passed, 2 known-gap tests ignored)
  • cargo test --release --test differential -- --ignored: true_positive=3745 true_negative=909 false_positive=0 false_negative=1 not_comparable=0. This is unchanged, because the corpus has no fixtures for these two new rules in either direction. No baseline update.
  • Site not rebuilt locally; only a description string changed.

The msrv job was already failing on master before this change: locked dependencies need a newer Rust than the declared 1.85. Not addressed here.

…gaps

Two of four reported missing findings were missing Schematron rules:
- elements-img-missing-alt: vnu's general missing-alt branch (outside
  figure, with its aria-label/aria-labelledby/title exemptions). Only
  the figure-without-figcaption case existed before.
- elements-interactive-in-a: vnu's interactive-descendant-of-a list
  (button, select, textarea, label, details, dialog, embed, iframe, a,
  non-hidden input, controls media, usemap img/object, tabindex,
  interactive roles).

The other two (stray </div>, misnested <b><i>...</b></i>) are parse
errors html5-parser 0.3.0 does not record: it only reports a stray end
tag on the "any other end tag" path and none from the adoption agency
algorithm. The tokens leave no trace in the tree, so the fix belongs in
html5-parser. Documented as a gap in README and docs, with ignored
regression tests.

Differential test unchanged: TP 3745, TN 909, FP 0, FN 1.
html5-parser 0.4.0 records the tree-construction parse errors 0.3.0
dropped silently: stray end tags with no matching element in scope
(</div>, </li>, </h2>, ...), start tags the parser ignores, and
misnested formatting elements repaired by the adoption agency
algorithm. They surface as parser.html5 findings through the existing
mapping; no rule-ID changes needed.

Un-ignore the two known-gap regression tests. README, vnu comparison
and rule-ID docs now list only the parse errors 0.4.0 still misses
(e.g. <div><span></div>, content after </html>).

Differential corpus unchanged: TP 3745, TN 909, FP 0, FN 1.

Cargo.lock is intentionally not updated: html5-parser 0.4.0 is not on
crates.io yet. Run `cargo update -p html5-parser` after publishing.
@casoon
casoon merged commit 2130b77 into master Sep 14, 2026
2 of 4 checks passed
@casoon
casoon deleted the fix/missing-findings branch September 14, 2026 06:37
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant