Skip to content

Add CI checks for links, anchors and quizzes - #16

Merged
markaren merged 1 commit into
mainfrom
testing
Jul 26, 2026
Merged

Add CI checks for links, anchors and quizzes#16
markaren merged 1 commit into
mainfrom
testing

Conversation

@markaren

Copy link
Copy Markdown
Owner

A clean mkdocs build says nothing about whether a link still points at a heading that exists, or whether a quiz question has an answer. Both fail silently: the reader lands at the top of a page, or clicks four options and is told all of them are wrong. Four of the eight defects found in the recent review were of exactly this kind.

tools/check_links.py walks the built site rather than the markdown, for two reasons. Heading anchors come from the slugifier, so checking sources means reimplementing it and hoping the copy stays honest. And under /nb/ mkdocs-static-i18n has already chosen between the translation and the English fallback — which is what makes an English anchor like #range-based-for resolve to a Norwegian page whose slug is #range-basert-for. Currently 11516 links, all resolving.

tools/check_quizzes.py asserts every question has exactly one correct option, at least three options, and that no authoring syntax leaked through a block the hook failed to parse.

tools/selftest.py plants a known defect in a copy of the site and asserts the checkers catch it. This is not ceremony — writing it found two real holes. check_links.py ignores the theme navigation, so a test mutating a nav link proves nothing; and check_quizzes.py looked for leaked syntax only on pages where a quiz had parsed, skipping the check in exactly the case where the hook had failed. The second was a genuine bug, fixed here.

Also fixes Chapter5/templates.md, which used std::string without including . The page quotes the template-deduction error, but a reader pasting the code got "std::string is not a member of std" first. Verified: with the include, the deduction error is the first one.

A clean `mkdocs build` says nothing about whether a link still points at a
heading that exists, or whether a quiz question has an answer. Both fail
silently: the reader lands at the top of a page, or clicks four options
and is told all of them are wrong. Four of the eight defects found in the
recent review were of exactly this kind.

tools/check_links.py walks the *built* site rather than the markdown, for
two reasons. Heading anchors come from the slugifier, so checking sources
means reimplementing it and hoping the copy stays honest. And under /nb/
mkdocs-static-i18n has already chosen between the translation and the
English fallback — which is what makes an English anchor like
#range-based-for resolve to a Norwegian page whose slug is
#range-basert-for. Currently 11516 links, all resolving.

tools/check_quizzes.py asserts every question has exactly one correct
option, at least three options, and that no authoring syntax leaked
through a block the hook failed to parse.

tools/selftest.py plants a known defect in a copy of the site and asserts
the checkers catch it. This is not ceremony — writing it found two real
holes. check_links.py ignores the theme navigation, so a test mutating a
nav link proves nothing; and check_quizzes.py looked for leaked syntax
only on pages where a quiz had parsed, skipping the check in exactly the
case where the hook had failed. The second was a genuine bug, fixed here.

Also fixes Chapter5/templates.md, which used std::string without
including <string>. The page quotes the template-deduction error, but a
reader pasting the code got "std::string is not a member of std" first.
Verified: with the include, the deduction error is the first one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@markaren
markaren merged commit bae571c into main Jul 26, 2026
2 checks passed
@markaren
markaren deleted the testing branch July 26, 2026 07:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant