a11ytrace

    Pure HTML accessibility checks for MoonBit projects.

    accessibility
    a11y
    html
    lint
    Download zip
    Author
    Version
    0.4.0
    License
    Apache-2.0
    Last updated
    19 hours ago
    Downloads
    16

    #A11yTrace

    A11yTrace is a small, pure MoonBit library for statically checking HTML accessibility rules.

    #Current development checkout

    This checkout provides 73 selectable built-in IDs, deliberately separated into 43 confirmed Finding checks, 6 static hints, and 24 ReviewItem triggers. That directory is not an automatic WCAG-conformance count. The public WCAG directory contains 55 current WCAG 2.2 A/AA criteria plus historical 4.1.1 (removed in 2.2): 9 are partially checked from static HTML, 33 have manual-review steps, and 13 are not assessed. Zero findings never means WCAG conformance.

    For detailed JSON, assessment is findings, needs_review, no_static_findings, or parse_errors; a report with only ReviewItems is explicitly needs_review.

    #Install from Mooncakes

    From a new MoonBit project, install the release and import its public module name:

    moon new a11ytrace-demo cd a11ytrace-demo moon add youyong5/a11ytrace@0.4.0

    Add this import to the generated cmd/main/moon.pkg before its pkgtype declaration:

    ///|
    import {
    "youyong5/a11ytrace",
    }

    Then replace cmd/main/main.mbt with this minimal audit and run it:

    ///|
    fn main {
    match @a11ytrace.audit_html_fragment("<img src=\"logo.svg\">") {
    Findings(findings) => println(findings[0].rule_id)
    FindingsWithParseErrors(findings, _) => println(findings[0].rule_id)
    ParseErrors(diagnostics) => println(diagnostics[0].message)
    }
    }

    moon run cmd/main

    #Dependency and use

    It uses bobzhang/html_parser 0.1.8 to parse HTML into a DOM; A11yTrace does not parse HTML with regular expressions.

    import {
    "youyong5/a11ytrace" @a11ytrace,
    }

    match @a11ytrace.audit_html("<img src=\"logo.svg\">") {
    Findings(findings) => println(findings[0].element_path)
    FindingsWithParseErrors(findings, errors) => {
    println(findings[0].element_path)
    println(errors[0].message)
    }
    ParseErrors(errors) => println(errors[0].message)
    }

    audit_html does no file I/O, so callers choose where HTML comes from and how results are presented. When its input contains <!doctype or <html, it uses the parser's full-document mode and includes document-only rules. Markup without either marker keeps the library's fragment-compatible behavior; use audit_html_fragment when auditing a component explicitly.

    For a focused check, available_rule_ids() returns the accepted IDs in stable order and audit_html_with_rules(html, enabled_rule_ids) runs only the requested rules. audit_html(html) still runs every current rule. An empty selection runs no rules while retaining parser diagnostics; an unknown ID returns ConfigurationError(UnknownRuleId(id)) rather than being ignored. Repeated IDs do not duplicate findings.

    let selected = ["img-alt-missing", "heading-level-skipped"]

    match @a11ytrace.audit_html_with_rules(html, selected) {
    Audited(Findings(findings)) => ()
    Audited(FindingsWithParseErrors(findings, errors)) => ()
    Audited(ParseErrors(errors)) => ()
    ConfigurationError(UnknownRuleId(rule_id)) =>
    // Correct the rule ID before running an audit.
    ()
    }

    heading-level-skipped is a suggestion for structural review, so it can be useful to select it independently in a content-build check. Selection does not change the caller-provided array, and all selected rules share one parsed DOM; findings remain in document order.

    #Rule directory and combinations

    available_rules() -> Array[RuleMetadata] is the single built-in rule directory behind available_rule_ids(). Each copied record has id, summary, category, scope (Document, Fragment, or DocumentOrFragment), result_kind (ConfirmedFinding, StaticHint, or ManualReview), reference_url, and boundary. Use rule_metadata(id) for one record. content_rule_ids(), document_rule_ids(), and review_rule_ids() return fresh, named selections; callers can still pass any IDs to the established selection APIs.

    match @a11ytrace.rule_metadata("aria-hidden-focus-review") {
    Some(rule) => println(rule.boundary)
    None => ()
    }
    let page_rules = @a11ytrace.document_rule_ids()

    #WCAG 2.1/2.2 coverage directory

    The library exposes a version-aware A/AA criterion directory without turning an audit into a conformance claim. wcag_aa_criteria() returns copied WcagCriterion records with id, title, level, in_wcag21, in_wcag22, coverage_status, mapped rule_ids, concrete review_steps, and an official reference URL. wcag_criterion(id) looks up one record. The directory retains historical 4.1.1 as RemovedInWcag22; it must not be treated as a WCAG 2.2 criterion.

    let report = @a11ytrace.audit_html_with_wcag_coverage(page_html)
    // report.audit.findings are static signals.
    // report.audit.review_items need browser/CSS/runtime verification.
    // report.criteria describes coverage, never whether the page passed a criterion.
    match @a11ytrace.wcag_criterion("2.4.11") {
    Some(criterion) => println(criterion.review_steps)
    None => ()
    }

    See WCAG-COVERAGE.md for every WCAG 2.1/2.2 A/AA criterion, the version difference, mappings, and the required review step. render_wcag_audit_json(report) produces {"audit": {…detailed result…},"criteria": […coverage records…]}. Each criterion uses the stable coverage_status strings partial_automatic, manual_review, not_assessed, or removed_in_wcag22; none is a pass status. The current directory has 56 records: 9 partial-automatic, 33 manual-review, 13 not-assessed, and the one WCAG 2.1 historical record removed in WCAG 2.2.

    #HTML fragment audit

    Components and template generators can audit local markup directly with audit_html_fragment(fragment). audit_html_fragment_with_rules(fragment, enabled_rule_ids) has the same ConfiguredAuditResult and unknown-rule behavior as audit_html_with_rules.

    let card = "<button></button><img src=\"report.png\">"

    match @a11ytrace.audit_html_fragment_with_rules(
    card,
    ["button-name-missing", "img-alt-missing"],
    ) {
    Audited(result) => {
    let json = @a11ytrace.render_audit_json(result)
    // Consume the component findings in document order.
    }
    ConfigurationError(UnknownRuleId(rule_id)) => ()
    }

    Fragment parsing preserves the same deterministic paths, source locations when available, parser diagnostics, heading behavior, and template exclusion as normal auditing; in particular, the first native heading in a fragment may use any level. Name references are limited to the supplied markup: an aria-labelledby target or <label for> outside the fragment cannot be resolved and does not count as a name.

    Document-only rules, including document-title-missing and html-lang-missing, never run through either fragment entry point. To check a page title and language, provide a full document:

    ///|
    let page = "<!doctype html><html lang=\"en\"><head><title>Orders</title></head><body></body></html>"

    ///|
    let result = @a11ytrace.audit_html(page)

    The in-module consumer example is a separate MoonBit package that imports only this library's public API. Run it from the repository root with:

    moon run --target native examples/consumer

    #JSON output

    render_audit_json(result : AuditResult) -> String produces compact, parseable JSON using MoonBit's moonbitlang/core/json library. Every document has these fields, regardless of status:

    • status: "findings", "findings_with_parse_errors", or "parse_errors".
    • findings: an array of objects with rule_id, message, suggestion, element_path, line, and column.
    • parse_diagnostics: an array of objects with code, message, line, and column.

    line and column are JSON numbers when supplied by the parser and JSON null when unavailable. A "findings" result with an empty findings array means only that these implemented static checks found nothing; it does not mean the page meets all accessibility standards.

    Render only an Audited result. A rule-selection ConfigurationError is not serialized as an empty audit: report or correct UnknownRuleId before obtaining an AuditResult.

    import {
    "moonbitlang/core/json" @json,
    "youyong5/a11ytrace" @a11ytrace,
    }

    match @a11ytrace.audit_html_with_rules(html, ["img-alt-missing"]) {
    Audited(result) => {
    let document = @a11ytrace.render_audit_json(result)
    let parsed = @json.parse(document)
    // Read the documented status/findings/parse_diagnostics fields from parsed.
    }
    ConfigurationError(UnknownRuleId(rule_id)) => ()
    }

    • A static-site generator can audit each rendered page before writing it.
    • A documentation-site build can audit generated guide fragments.
    • A frontend CI job can audit fixture or server-rendered HTML and fail on findings.

    #Detailed static audit and manual review

    audit_html_detailed(html) and audit_html_fragment_detailed(fragment) retain the same parser status and definite findings as the compatible audit APIs, while exposing review_items separately. A review item has rule_id, reason, element_path, line, and column; it means static markup alone cannot establish the result. audit_html_detailed_with_rules and audit_html_fragment_detailed_with_rules return DetailedConfiguredAuditResult, preserving the same explicit unknown-ID behavior while retaining review items. render_detailed_audit_json(result) retains its existing fields and adds assessment: findings, needs_review, no_static_findings, or parse_errors. In particular, a report containing only review items is needs_review, never a pass. It does not serialize a rule-selection configuration error, because configuration errors must still be handled before an audit is run.

    ///|
    let detailed = @a11ytrace.audit_html_fragment_detailed(
    "<div aria-hidden=\"true\"><button aria-label=\"Close\"></button></div>",
    )

    ///|
    let json = @a11ytrace.render_detailed_audit_json(detailed)
    // detailed.findings: confirmed static signals
    // detailed.review_items: browser/CSS review needed

    #Native CLI example

    The library remains the primary interface; the optional native executable in cmd/a11ytrace only reads one local HTML file and calls the public API above. Build or run it with MoonBit:

    moon run --target native cmd/a11ytrace -- examples/cli-example.html moon run --target native cmd/a11ytrace -- examples/cli-example.html --format json moon run --target native cmd/a11ytrace -- examples/review-only.html --format detailed-json moon run --target native cmd/a11ytrace -- examples/cli-example.html --rules img-alt-missing,link-name-missing moon run --target native cmd/a11ytrace -- --help

    --format json remains compatible and writes only render_audit_json output to stdout; it intentionally does not contain review items. --format detailed-json writes only render_detailed_audit_json output, including review_items. A document with only review items has an empty findings array, which means neither “fully passed” nor that browser review is unnecessary. Text output displays a rule ID, element path, source location when known, message, and any parser diagnostics. Unknown rule IDs, malformed arguments, and file-read failures write an error instead of a report. The currently available public MoonBit APIs used by this small native example do not expose a portable process-exit setter, so those error paths currently exit with status 0. Do not use this CLI's exit status alone as a CI success signal; callers that need enforced exit codes should use the library API from their own build integration.

    #Current rule and boundary

    The rule directory now has 73 independently selectable checks and review triggers. In addition to the rules below, it covers selected ARIA required properties and ID relationships; static names for selected ARIA widgets; direct list/definition-list structure; empty table headers; unsafe viewport zoom tokens; and located media, keyboard, focus, target-size, dragging, pointer, motion, form, authentication, status-message, language, contrast and sequence review markers. These manual-review items are deliberately separate from confirmed findings.

    img-alt-missing reports an <img> that has no alt attribute. An explicit alt="" is accepted for decorative images, as is any non-empty alt value. The rule does not determine whether an image is decorative, whether alternative text is good, or whether a whole document conforms to WCAG.

    form-control-name-missing reports unnamed <input>, <select>, and <textarea> controls, excluding hidden and button-like input types. It recognizes text-bearing labels, non-empty ARIA names, and title as a fallback; it does not implement the complete browser Accessible Name algorithm.

    link-name-missing reports an <a href> without recognizable text, non-empty image alt text, ARIA name, or fallback title. It ignores script, style, and template text. It checks presence of a name, not whether the destination is described clearly; when no supported source is present, SVG-containing links are conservatively left unreported until SVG name sources are supported.

    button-name-missing reports unnamed native <button>, input[type="button"], and input[type="image"]; custom role="button" is outside this rule. It recognizes supported native text, image alt, value, ARIA, and title sources as appropriate, while leaving SVG-only native buttons unreported until SVG name sources are supported. It is a static name-presence check, not a WCAG conformance conclusion.

    heading-level-skipped suggests reviewing a native heading that jumps down two or more levels from the preceding heading; the first heading may start at any level. heading-name-missing reports empty native headings unless supported text, image alt, or ARIA naming is present. Neither rule infers headings from visual styling or implements a complete browser Accessible Name algorithm.

    document-title-missing and html-lang-missing apply only to complete-document input and require a non-empty head <title> and <html lang> respectively. iframe-name-missing accepts a non-empty title, aria-label, or resolvable text-bearing aria-labelledby target. duplicate-id reports later repeated non-empty IDs in the same audited input scope; duplicated IDs are deliberately not trusted for ARIA or label resolution.

    reference-target-invalid reports missing or ambiguous non-empty targets used by label[for], aria-labelledby, or aria-describedby; it does not call a separately named control “unnamed” merely because one of its references is invalid. label-for-target-not-labelable separately reports only a unique label[for] target that is a known non-labelable built-in HTML element, such as a div or hidden input; it accepts button, non-hidden input, meter, output, progress, select, and textarea, and skips custom elements because form association is not statically knowable. label-multiple-labelable-descendants reports each label once when it contains two or more known built-in labelable descendants; explicit for does not exempt a second descendant, while hidden inputs, template contents, and unknown custom elements are not counted. These are definite HTML association/content-model findings, not per-instance WCAG conclusions. table-headers-invalid checks that each headers token resolves to another unique td or th in the same nearest table. area-alt-missing requires non-empty alt on an <area href>; an area without href is outside that rule.

    body-aria-hidden reports aria-hidden="true" on the body of a complete document. multiple-main is a static structural prompt for every main after the first in a complete document. When a document has multiple <nav> landmarks, navigation-landmark-name-missing reports a landmark without a supported static distinguishing name and navigation-landmark-name-duplicate reports a later repeated static name. These page-structure rules do not run for fragments.

    aria-hidden-focus-review is a review item rather than a confirmed finding. It identifies a potentially focusable native element or explicit tabindex within an aria-hidden="true" element or ancestor; descendant aria-hidden="false" cannot undo an ancestor's hidden state. Disabled native controls are excluded, but aria-disabled alone is not. CSS, scripting, and browser focus behavior decide the final outcome. aria-abstract-role reports an abstract ARIA 1.2 role only when no concrete fallback token exists. role-value-invalid reports a non-empty role list only when it has no concrete WAI-ARIA 1.2 fallback, so role="future-role button" is accepted and role="widget checkbox" is checked as a checkbox without a second abstract-role finding.

    role-button-name-missing, role-link-name-missing, and role-radio-name-missing check effective custom role="button", role="link", and role="radio" elements for the same bounded static sources as other name rules: descendant text, non-empty image alt, aria-labelledby, aria-label, and title. Native buttons, <a href>, and form controls are excluded when an existing native name rule already owns the element, avoiding duplicate name findings. SVG-only cases become ReviewItems rather than definite missing-name findings. Custom radios also require aria-checked; native input[type="radio"] is not reported for using its HTML state instead.

    role-textbox-name-missing and role-searchbox-name-missing check effective custom role="textbox" and role="searchbox" only for author-provided static names: a supported local aria-labelledby target, non-empty aria-label, or fallback title. They deliberately do not treat ordinary descendants, contenteditable text, placeholder, or aria-placeholder as names. Native <input> and <textarea> remain under form-control-name-missing. An aria-labelledby target containing SVG without another supported static source becomes a ReviewItem because this bounded parser does not compute SVG/browser naming.

    meta-refresh-delay applies only to complete documents and reports a meta[http-equiv="refresh"] with a supported numeric delay greater than zero. It does not check refresh loops, long-delay exceptions, malformed delay syntax, or runtime changes. aria-required-property-missing also checks effective custom role="scrollbar" for both aria-controls and aria-valuenow, reporting the missing property or the two missing properties in one Finding; an invalid supplied controls target remains an aria-idref-invalid issue. aria-range-value-invalid checks explicit finite numeric aria-valuemin, aria-valuemax, and aria-valuenow on custom effective slider/scrollbar roles, uses 0/100 only for omitted min/max, and keeps omitted aria-valuenow under the required-property rule. It does not apply to spinbutton, progressbar, or native form controls. aria-attribute-undefined checks only whether an aria-* name belongs to WAI-ARIA 1.2, including 1.2 additions and deprecated-but-defined names; it does not validate permission or values. aria-state-value-invalid checks only these explicitly listed static values: boolean aria-busy, aria-disabled, aria-modal, aria-multiline, aria-multiselectable, aria-readonly, and aria-required; true/false/undefined aria-expanded and aria-hidden; tristate aria-checked (except effective role="radio", which accepts only true/false) and aria-pressed; and token values for aria-current and aria-invalid. table-scope-invalid only reports an explicit invalid th[scope] keyword, never an omitted scope or a td[scope]; it does not infer table associations.

    button-implicit-submit is a static best-practice prompt, not an accessibility violation finding: it reports a native <button> inside a <form> only when type is missing or empty, because it defaults to submit. Explicit type="submit" and type="button", buttons outside forms, invalid type values, and form-owner behavior through a form attribute are outside its narrow scope.

    All name-related checks share an ID and label[for] index built once from the recovered DOM. Multiple aria-labelledby references are processed in IDREF order; a uniquely resolved direct target can contribute non-empty aria-label, text/descendant image alt, or fallback title. A usable result takes precedence over aria-label and native/content/title fallbacks on the named element. Missing, empty, duplicate, or fragment-external references do not establish a name. Cyclic and self-reference graphs are never followed recursively, though a directly referenced node can still contribute one of its own supported static sources. A directly referenced static text node is accepted even if its markup has hidden or aria-hidden; A11yTrace does not compute rendered visibility or the browser name algorithm. This is informed by Accessible Name and Description Computation 1.2, not a complete implementation: CSS generated/hidden content, SVG, shadow DOM, slots, embedded controls, script-created DOM, and browser accessibility-tree behavior require manual or browser-based review.

    For example, both rules can be reported from one fragment:

    match @a11ytrace.audit_html("<img src=\"chart.svg\"><input placeholder=\"Email\">") {
    Findings(findings) => {
    // findings[0].rule_id == "img-alt-missing"
    // findings[1].rule_id == "form-control-name-missing"
    }
    FindingsWithParseErrors(findings, errors) => ()
    ParseErrors(errors) => ()
    }

    Current rules can be reported in document order:

    match @a11ytrace.audit_html("<img src=\"chart.svg\"><input><a href=\"/details\"></a><button></button><h2>Section</h2><h4></h4>") {
    Findings(findings) => {
    // image, form, link, button, heading-level, and heading-name findings
    }
    FindingsWithParseErrors(findings, errors) => ()
    ParseErrors(errors) => ()
    }

    The parser uses HTML5-style recovery. Recoverable parser diagnostics produce FindingsWithParseErrors: the recovered DOM is still checked and diagnostics stay visible. ParseErrors is reserved for a parser failure that prevents a DOM audit. Findings include a deterministic CSS-style element_path; their optional line and column are source start-tag locations supplied by the parser, and remain absent when the parser has no source position.

    See RULES.md for rule rationale and REFERENCE-COMPARISON.md for the scoped comparison with HTML-Validate, axe-core, and ACT references. The release-review RULE-INVENTORY.md lists every selectable ID, its actual outcome type and trigger, WCAG/practice mapping, source location, and named test evidence.

    #License and attribution

    A11yTrace's audit rules and library code are original work licensed under Apache-2.0 (see LICENSE). It depends on, but does not copy, bobzhang/html_parser 0.1.8 and the native CLI's moonbitlang/async 0.19.0; both dependencies are Apache-2.0 licensed.

    HTML-Validate is an MIT-licensed reference project, and axe-core and W3C ACT Rules are reference material only; A11yTrace does not include or copy their source code.

    AuditResult

    pub(all) enum AuditResult {
    Findings(Array[Finding])
    FindingsWithParseErrors(Array[Finding], Array[ParseDiagnostic])
    ParseErrors(Array[ParseDiagnostic])
    }

    A result produced by audit_html.

    FindingsWithParseErrors preserves recoverable parser diagnostics while still auditing the parser's recovered DOM. ParseErrors means the parser could not return a DOM for auditing.

    ConfiguredAuditResult

    pub(all) enum ConfiguredAuditResult {
    Audited(AuditResult)
    ConfigurationError(RuleConfigurationError)
    }

    A result produced by audit_html_with_rules.

    DetailedAuditResult

    pub(all) struct DetailedAuditResult {
    status : DetailedAuditStatus
    findings : Array[Finding]
    parse_diagnostics : Array[ParseDiagnostic]
    review_items : Array[ReviewItem]
    }

    A detailed audit result that keeps definite findings, parser diagnostics, and manual-review items separate.

    DetailedAuditStatus

    pub(all) enum DetailedAuditStatus {
    Findings
    FindingsWithParseErrors
    ParseErrors
    }

    The parser and finding status of a detailed audit.

    DetailedConfiguredAuditResult

    pub(all) enum DetailedConfiguredAuditResult {
    Audited(DetailedAuditResult)
    ConfigurationError(RuleConfigurationError)
    }

    A result produced by a detailed rule-selected audit.

    Finding

    pub(all) struct Finding {
    rule_id : String
    message : String
    suggestion : String
    element_path : String
    line : Int?
    column : Int?
    }

    A single accessibility finding.

    element_path is a deterministic CSS-style path based on element names and :nth-of-type() positions. line and column are the parser's optional, 1-based source location for the element start tag.

    ParseDiagnostic

    pub(all) struct ParseDiagnostic {
    code : String
    message : String
    line : Int?
    column : Int?
    }

    A parse diagnostic reported before audit rules are evaluated.

    ReviewItem

    pub(all) struct ReviewItem {
    rule_id : String
    reason : String
    element_path : String
    line : Int?
    column : Int?
    }

    A static check that requires browser, CSS, or runtime information before it can be treated as a confirmed issue.

    RuleCategory

    pub(all) enum RuleCategory {
    ContentName
    DocumentStructure
    Interaction
    Relationships
    Aria
    Timing
    }

    A broad grouping used by the stable rule directory.

    RuleConfigurationError

    pub(all) enum RuleConfigurationError {
    UnknownRuleId(String)
    }

    An invalid rule-selection configuration.

    RuleMetadata

    pub(all) struct RuleMetadata {
    id : String
    summary : String
    category : RuleCategory
    scope : RuleScope
    result_kind : RuleResultKind
    reference_url : String
    boundary : String
    }

    Stable, read-only metadata describing one built-in rule.

    RuleResultKind

    pub(all) enum RuleResultKind {
    ConfirmedFinding
    StaticHint
    ManualReview
    }

    The confidence represented by a rule's output.

    RuleScope

    pub(all) enum RuleScope {
    Document
    Fragment
    DocumentOrFragment
    }

    The input scope in which a rule is evaluated.

    WcagAuditResult

    pub(all) struct WcagAuditResult {
    audit : DetailedAuditResult
    criteria : Array[WcagCriterion]
    }

    A detailed audit alongside the complete static-coverage directory. Empty findings do not mean the criteria have passed.

    WcagCoverageStatus

    pub(all) enum WcagCoverageStatus {
    PartialAutomatic
    ManualReview
    NotAssessed
    RemovedInWcag22
    }

    How far A11yTrace can assess one WCAG criterion from static HTML. This describes coverage, never a page conformance outcome.

    WcagCriterion

    pub(all) struct WcagCriterion {
    id : String
    title : String
    level : WcagLevel
    in_wcag21 : Bool
    in_wcag22 : Bool
    coverage_status : WcagCoverageStatus
    rule_ids : Array[String]
    review_steps : String
    reference_url : String
    }

    A version-aware A/AA WCAG success-criterion coverage record.

    WcagLevel

    pub(all) enum WcagLevel {
    A
    AA
    }

    The WCAG conformance level for an A/AA success criterion.

    audit_html

    fn audit_html(html : String) -> AuditResult

    Audit HTML with the rules currently implemented by A11yTrace.

    This is a pure operation: it performs no file I/O and can be used by a build tool, test suite, or another MoonBit package. Input with parser diagnostics returns FindingsWithParseErrors, so ordinary HTML5 recovery does not hide rule findings. A parser failure returns ParseErrors.

    Inputs with an HTML document marker (<!doctype or <html) are parsed as complete documents and run document-only rules. For compatibility, markup without such a marker retains fragment-style parsing; use audit_html_fragment to explicitly audit a component fragment.

    audit_html_detailed

    fn audit_html_detailed(html : String) -> DetailedAuditResult

    Audit HTML and keep definite findings separate from items needing browser or CSS review. Unlike audit_html, this result exposes review_items.

    audit_html_detailed_with_rules

    fn audit_html_detailed_with_rules(html : String, enabled_rule_ids : Array[String]) -> DetailedConfiguredAuditResult

    Audit HTML with selected rules while retaining manual-review items. Unknown IDs are returned before parsing, as with audit_html_with_rules.

    audit_html_fragment

    fn audit_html_fragment(fragment : String) -> AuditResult

    Audit an HTML fragment with every current A11yTrace rule.

    This is useful for a component or generated template that is not wrapped in a complete document. Labels and ARIA references are resolved only within the supplied fragment.

    audit_html_fragment_detailed

    fn audit_html_fragment_detailed(fragment : String) -> DetailedAuditResult

    Audit an HTML fragment and keep manual-review items separate from definite findings and parser diagnostics.

    audit_html_fragment_detailed_with_rules

    fn audit_html_fragment_detailed_with_rules(fragment : String, enabled_rule_ids : Array[String]) -> DetailedConfiguredAuditResult

    Audit a fragment with selected rules while retaining manual-review items.

    audit_html_fragment_with_rules

    fn audit_html_fragment_with_rules(fragment : String, enabled_rule_ids : Array[String]) -> ConfiguredAuditResult

    Audit an HTML fragment with only the selected rule IDs.

    Its rule-selection and parser-diagnostic behavior matches audit_html_with_rules. Unknown IDs return ConfigurationError before parsing the fragment.

    audit_html_with_rules

    fn audit_html_with_rules(html : String, enabled_rule_ids : Array[String]) -> ConfiguredAuditResult

    Audit HTML with only the selected rule IDs.

    An empty array runs no rules but still returns parser diagnostics. Repeated IDs are treated as one selection. An unknown ID returns ConfigurationError before parsing.

    audit_html_with_wcag_coverage

    fn audit_html_with_wcag_coverage(html : String) -> WcagAuditResult

    Audit a complete-document-or-fragment input and return its detailed result with coverage records. Coverage status is not a pass/fail determination.

    available_rule_ids

    fn available_rule_ids() -> Array[String]

    Return the stable IDs accepted by audit_html_with_rules.

    available_rules

    fn available_rules() -> Array[RuleMetadata]

    Return copied metadata for every built-in rule in stable ID order.

    content_rule_ids

    fn content_rule_ids() -> Array[String]

    Return the content-name rule IDs as a convenient selection.

    document_rule_ids

    fn document_rule_ids() -> Array[String]

    Return the complete-document structural rule IDs as a convenient selection.

    render_audit_json

    fn render_audit_json(result : AuditResult) -> String

    Render an audit result as a compact JSON document for programmatic use.

    The JSON object always contains status, findings, and parse_diagnostics. Optional source positions are rendered as JSON null when the parser did not provide them.

    render_detailed_audit_json

    fn render_detailed_audit_json(result : DetailedAuditResult) -> String

    Render a detailed audit result as compact JSON. It has the stable fields status, findings, parse_diagnostics, and review_items.

    render_wcag_audit_json

    fn render_wcag_audit_json(result : WcagAuditResult) -> String

    Render a detailed audit and its WCAG coverage directory as JSON. The criteria records describe assessment capability, never passed criteria.

    review_rule_ids

    fn review_rule_ids() -> Array[String]

    Return the rule IDs that can produce manual-review items.

    rule_metadata

    fn rule_metadata(rule_id : String) -> RuleMetadata?

    Look up copied metadata for one built-in rule ID.

    wcag_aa_criteria

    fn wcag_aa_criteria() -> Array[WcagCriterion]

    Return copied A/AA WCAG 2.1 and 2.2 coverage records, including the historical 4.1.1 entry removed from WCAG 2.2.

    wcag_criterion

    fn wcag_criterion(id : String) -> WcagCriterion?

    Look up a copied WCAG A/AA coverage record by success-criterion ID.

    Source Files