Validate the generated HTML
Owner:
Ivan Hawkes
Feed the built pages through an HTML validator and clean up what it reports.
Audit Checklist
- Extra
</div>in the navigation partial: thedivthat wrapped the recursive sub-menu output sat directly inside<ul class="sub-menu">, turning every submenu entry into anliunder adiv. - Trailing slashes on void elements (
<link/>,<source/>,<img/>,<br/>) left alone. They come from Hugo’s own templates and from long-standing content, they are valid HTML5, and the stylisticvoid-stylerule stays off. - Render code block extra attributes (
id,tabindex) kept: they drive the copy-to-clipboard button and keyboard scrolling. - No
articleelement wraps page content. - Author dates use
dateFormatin thedatetimeattribute anddateFormatHumanfor display.
What The Validator Caught
- Kanban summary tables sitting inside a
ul(_partials/kanban/kanban-list-short.html). liunderdivfrom the recursive nav partial: 7,074 reports.divinsidetbodyfrom_partials/recipes/recipe-times.html.<thclass=...>and<tdclass=...>from the table render hook, which trimmed the space beforeclass; the link render hook did the same totitle, producing<atitle=...>(17 reports).- The “Image unavailable.” fallback emitted a
pinside a paragraph. - Dashboard section pages embedded whole scratch pages in their cards, nesting
main,navandfooterinside the page; they link now. - Raw markup in content: an unbalanced blockquote in a post, which closed a paragraph in the middle of the page.
Acceptance Criteria
pnpm run testbuilds the site and runshtml-validateoverpublic/**/*.htmlwith thehtml-validate:standardpreset, exiting non-zero on any report.- The publish workflow runs
pnpm run test:htmlafterhugo buildand fails before the Pages artifact is uploaded. - Hugo’s pagination redirect stubs (
public/**/page/*/index.html) are ignored; Hugo writes them with aheadand nobody. - The hand-authored CSS fixtures under
public/dashboard/raw/are ignored: the odd markup is the point of those pages, so it is left as written. - Card listings show
.Description, not.Summary, so embedded card text cannot repeat a heading id across one page.