Skip to content

Latest commit

 

History

History
159 lines (137 loc) · 8.76 KB

accessibility.md

File metadata and controls

159 lines (137 loc) · 8.76 KB

Publication accessibility contract

Active Fedference treats the validated HTML manuscript as its canonical, accessibility-enhanced manuscript reading surface. Reveal.js is the paired accessibility-enhanced slide-reading surface: it retains semantic headings, keyboard navigation, responsive tables, figure alternatives and descriptions, high-contrast focus states, and a link to the complete HTML manuscript. The Beamer slide PDFs are explicitly untagged presentation derivatives; successful visual rendering does not promote them to the manuscript's tagged-PDF contract.

The combined manuscript PDF is generated through the source-controlled LuaLaTeX/tagpdf path requested by metadata.tagged_pdf: true. Its release gate requires pdfinfo to report Tagged: yes, qpdf JSON to expose a non-empty catalog /Lang and a StructTreeRoot, and the source-bound language check to pass. Some Poppler builds omit the language line from pdfinfo; that is why the validator checks the PDF catalog as well. Figure alternatives are bound from src/figures/_metadata.py through the figure registry.

Tagged structure is not the same as PDF/UA certification. A PDF/UA claim is allowed only when the retained veraPDF report and manual reading-order, keyboard, reflow/zoom, mathematical-content, and screen-reader checks pass. If those checks are not complete, the accurate status is “tagged PDF producer enabled; PDF/UA conformance not established.” The public v1.0.3 artifact may retain older surface properties; the published v1.0.4 artifact and its regenerated reviewer snapshot satisfy the repository's tagged-structure gate, while PDF/UA conformance remains unestablished.

This is a scoped engineering contract, not a declaration of WCAG conformance. The automated rules cover deterministic properties that this repository can enforce. A public accessibility claim still requires manual keyboard, screen-reader, zoom/reflow, contrast, reading-order, and mathematical-content review.

HTML rules enforced in source

src/publication/web_package.py::validate_web_package fails every generated HTML page unless it has:

  • exactly one non-empty document language and title;
  • exactly one focusable <main id="main-content" tabindex="-1"> landmark;
  • exactly one .skip-link targeting that landmark as the first interactive element;
  • a non-empty alt attribute on every image;
  • a <figcaption> for every figure containing an image;
  • an aria-label on every full-size figure link;
  • no duplicate element identifiers;
  • no missing local assets, broken fragments, raw typed references, or leaked figure Markdown.

These rules support the semantic structure, text alternatives, page language, page title, and bypass-block concerns in WCAG 2.2. The skip-link pattern follows the W3C G1 technique. Passing the checks does not establish WCAG A, AA, or AAA conformance because the validator does not determine alternative-text quality, contrast, meaningful sequence, keyboard usability, assistive-technology behavior, or whether visual encodings remain understandable without color.

Figure descriptions originate in manuscript captions and the figure registry, not in generated HTML edits. Captions must identify the estimand, encodings, units, uncertainty, source relation, and claim boundary without relying on color alone. Complex figures additionally carry a structured long_description; the HTML renderer places it in a labeled disclosure after the caption while keeping the image's concise alternative distinct. Full-size links name the figure and title rather than exposing a generic “open image” label.

Seven quantitative figures also declare stable fig-values:* fallback identifiers. Analysis derives their exact-value tables from the same typed reports used for plotting and writes both machine-readable JSON and a human-readable Markdown table under output/figures/. The figure registry must bind every declared identifier to those artifacts. At release review, inspect whether alternative, caption, long description, and exact table complement one another without needless repetition in at least one screen reader.

PDF and slide boundary

qpdf --check, pdftotext, clean LaTeX logs, raster inspection, and pdfinfo Tagged: yes answer important but different questions. They do not prove PDF/UA reading order, table structure, or assistive-technology interoperability. Tagged PDF supplies a semantic structure and figure alternatives for those purposes; see the PDF Association accessibility resources.

A source-current tagged manuscript PDF requires all of the following from the sibling rendering producer:

  1. the combined manuscript is produced from source, never post-hoc hand-edited;
  2. the source document language and title are present;
  3. figure alternatives are complete in the typed registry and bound to every embedded figure;
  4. pdfinfo reports Tagged: yes, qpdf exposes /Lang and a StructTreeRoot, and the source-bound language check passes;
  5. the source-bound render and release receipts are regenerated after any producer change.

Until the additional veraPDF and manual checks pass, publication prose must say “HTML accessibility-enhanced; tagged PDF structure verified, PDF/UA conformance not established,” not “fully accessible,” “WCAG conformant,” or “PDF/UA conformant.”

The opt-in render.slides.profile: accessible contract separately limits a frame to 80 prose words and eight displayed table-body rows, reserves at least 70% of usable space for figure-led frames, and enforces 28/20/16-point floors for titles, body text, and figure labels. It splits only at semantic block boundaries and rejects uncomposable density rather than splitting equations, lists, code, tables, or figures or silently reducing type. Reveal.js carries the accessible reading affordances and links to the full manuscript; Beamer remains a projection derivative. Passing these automated checks establishes neither a WCAG conformance result for Reveal.js nor PDF/UA conformance for either PDF surface.

Dense figures use source-owned presentation manifests selected by the manuscript's data-slide-manifest attribute. The canonical portrait PNG/PDF pair is retained. Each generator declares the complete ordered panel inventory; the shared presentation saver records the smallest visible Matplotlib label in pixels, binds it to the raster digest, checks a conservative design envelope, and emits a typed manifest. The renderer independently checks actual PDF image scale against the unchanged 16-point floor. The registry verifies both files in each declared panel pair and every raster digest, while stage provenance binds the source, manifest, and panel bytes. A successful subset is not a complete figure-label audit: every required figure must have measured presentation coverage before release. All required figure families implement this path, and the manuscript selectors are checked against the declared manifest inventory. Final source-bound production, embedded-label measurements, and complete PDF/HTML visual inspection remain release gates.

Desktop browser checks also verify that no clipping ancestor hides the edges of widened figure images. A figure can fit within the viewport yet be cut off by a narrower prose container, so viewport-overflow checks alone are insufficient. The browser suite checks this separately from narrow-layout reflow, keyboard focus, full-size link names, and disclosure operation. Geometry is measured after MathJax typesetting, pending viewport reflow, fonts, and images have completed. A separate live-resize check moves an already rendered page between desktop, 200%, and 400% equivalent widths, verifying that equation numbers remain visible and the input mathematics is unchanged. Loading a page at a narrow width alone does not establish this behavior.

Release review sequence

Run source validation first, then generate analysis, hydrate the manuscript, render through the sibling producer, prepare the web package, and execute:

uv run --locked python scripts/validate_web_package.py
uv run --locked python scripts/validate_rendered_surfaces.py
pdfinfo output/pdf/active_fedference_combined.pdf | grep '^Tagged:'
qpdf --json --json-stream-data=none output/pdf/active_fedference_combined.pdf \
  | grep -Eq '"/(Lang|StructTreeRoot)"'
verapdf --format text --flavour ua2 \
  output/pdf/active_fedference_combined.pdf > .tmp/verapdf-ua2.txt

Treat the veraPDF command as a conformance probe, not as a pass by invocation; inspect and retain its complete report. Finally perform the manual checks above in a real browser and PDF reader. Record findings with the render receipt. Do not repair generated files in output/; fix the manuscript, figure producer, or sibling renderer and rerun the producer chain.