html-conform 0.1.0

HTML5 conformance checking as a pure Rust dependency (vnu-comparable, no JVM runtime).
Documentation
# rules

Schematron rules (`.sch`) expressing the assertion layer's co-constraints
(ARIA combinations, form-label requirements, ID uniqueness, etc.) as
declarative XPath — the only place for this domain logic. No Rust code for
co-constraints; see `assertions.rs` and `CLAUDE.md`.

## Named element tests need the `h:` namespace prefix

`src/infoset.rs` gives every plain HTML element the XHTML namespace
(`http://www.w3.org/1999/xhtml`) — needed so `relax_ng`'s vendored HTML5
schema validates correctly (see `plan/DECISIONS.md`'s adapter-contract
entry). XPath 1.0's unprefixed name tests (`th`, `input`, `self::font`, …)
only ever match nodes with **no** namespace — the `xmlns` default
namespace is explicitly excluded from name-test expansion (XPath 1.0 §2.3).
An unprefixed element name test against this infoset therefore silently
matches nothing, not an error, no diagnostic — easy to miss.

Every rule file that names an element (not just `*`) must declare and use
the XHTML namespace prefix:

```xml
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
  <ns prefix="h" uri="http://www.w3.org/1999/xhtml"/>
  <pattern id="...">
    <rule context="h:th[@scope]">
      ...
```

Attribute tests (`@scope`, `@type`, `@aria-hidden`, …) do **not** need the
prefix — ordinary HTML attributes carry no namespace in this crate's
infoset, matching XPath's own unprefixed-attribute expansion rule. Only
*element* name tests need `h:`. The `*` wildcard element test also needs
no prefix (namespace-agnostic by definition). See `rules/aria.sch` (no
prefix needed for its first rule, wildcard-only) vs. `rules/tables.sch`/
`obsolete-elements.sch` (named element tests, prefix required) for worked
examples.