Docs: VuePress plugin to strip [V<n>] citation markers and §Sources footers at build#1679
Docs: VuePress plugin to strip [V<n>] citation markers and §Sources footers at build#1679marcin-kordas-hoc wants to merge 8 commits into
Conversation
…ooters at build
Internal authoring uses an audit-harness convention where factual claims
are annotated with inline `[V<n>]` markers and pages carry a trailing
`§ Sources` footer. These annotations let the audit-harness re-verify
every claim before content ships - they are never meant for end users.
When any annotated spec or note ends up published as docs, the markers
must not leak into the rendered site. This adds a small markdown-it
plugin (~120 LOC) wired into the existing `extendMarkdown` hook in
`docs/.vuepress/config.js`. It walks the token stream and:
- Removes inline `[V<n>]` markers (only the bare form; real markdown
links like `[V12](url)` are preserved).
- Removes the `Sources` / `§ Sources` heading and everything below it
up to the next top-level (`h1`) heading.
- Leaves `code_inline`, `code_block` and `fence` tokens untouched so
docs that document the audit-harness syntax itself still render
correctly.
Verified by:
- A standalone Node test
(`docs/.vuepress/plugins/strip-citation-markers/test.js`) covering
six assertions against
`docs/.vuepress/plugins/strip-citation-markers/test-fixture.md`.
- A full `vuepress build docs` run with the fixture temporarily placed
under `docs/guide/`; grep of `docs/.vuepress/dist` confirmed zero
`[V<n>]` markers outside `<code>`/`<pre>` blocks and zero `§Sources`
occurrences in rendered HTML.
✅ Deploy Preview for hyperformula-dev-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for hyperformula-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Performance comparison of head (084c293) vs base (508d78f) |
…st §Sources splice Bugbot #3297000925 caught that `transformTokens` in the strip-citation-markers plugin spliced from a `§ Sources` heading all the way to either the next h1 or end-of-stream. Because `config.js` also registers `markdown-it-footnote`, which appends `footnote_block` / `footnote_anchor` / `footnote_open` / `footnote_close` / `footnote_ref` tokens at the END of the token stream, a page that ended with a Sources footer AND had footnote references would silently lose its footnotes. `findFooterEnd` now also stops at the first token whose type starts with `footnote_`, so footnote tokens always survive the splice. Added one synthetic token-stream assertion and one full-pipeline assertion (running markdown-it with markdown-it-footnote AND the strip plugin) to lock the invariant in.
…markdown-it-footnote ordering Tier 2 hardening for the strip-citation-markers plugin (#1679). Mutation testing (manual analysis, 50% baseline score) flagged 5 surviving mutants. Five new assertions added to test.js (10 -> 15 total): - M1: zero-digit '[V]' must NOT be stripped (regex requires \d+) - M2: link text 'V12' anchored so removing the (?!\() lookahead is caught - M3: lowercase '## sources' heading must also be stripped (i flag) - M5: h1 boundary in findFooterEnd respected (h2 -> h1 mutation no longer silent) - M11: double-space collapse after marker removal is verified SFDIPOT P0 finding: plugin-order coupling with markdown-it-footnote is load-bearing. Added test-plugin-order.js with 10 assertions covering: - Negative control (no footnote plugin): markers/footer still stripped, but no footnote anchor appears (locks the 'footnote tokens come from a separate plugin' assumption) - Positive control (config.js ordering): footnotes survive, markers and footer stripped - Rule-chain invariant: footnote_tail must appear BEFORE strip-citation-markers in md.core.ruler — this is the actual mechanism that makes the wiring work and the primitive that future refactors must preserve vuepress build verified clean.
Follow-up: hardened test coverageTwo extra layers of test coverage added while reviewing the plugin. Stronger assertions in
|
| Guards against | Assertion |
|---|---|
\d+ weakened to \d* in INLINE_CITATION_PATTERN |
literal [V] (no digits) must survive |
dropping the (?!\() lookahead |
link text V12 stays anchored (not collapsed to V) |
dropping the i flag on SOURCES_HEADING_PATTERN |
lowercase ## sources footer is also stripped |
t.tag === 'h1' changed to 'h2' in findFooterEnd |
content under a post-Sources # Second page h1 survives |
dropping .replace(/[ \t]{2,}/g, ' ') |
multiple markers should collapse must not contain a 2+ space run |
Plugin-order coupling — test-plugin-order.js
findFooterEnd relies on markdown-it-footnote's footnote_* tokens being present in the stream when our splice runs. Added 10 assertions across three layers:
- Negative control (no footnote plugin loaded): markers + footer still stripped, but no footnote anchor appears. Anchors the "footnote tokens come from a separate plugin" assumption.
- Positive control (config.js ordering: footnote first, strip last): footnotes survive AND markers/footer stripped.
- Rule-chain invariant: asserts
footnote_tailappears beforestrip-citation-markersinmd.core.ruler. This is the actual primitive (notmd.use()call order — both plugins hook into named ruler positions, so what matters is the resultingcore.rulerchain). If a futuremarkdown-it-footnoteversion movesfootnote_tail, this assertion fires and points engineers straight at the root cause.
Why a test, not a runtime guard
Considered an assertion inside the plugin's md.use registration that warns if markdown-it-footnote is missing. Rejected: runtime warnings in a docs-build plugin add noise and would couple the plugin to a specific footnote-plugin identity. The test artifact is strictly better — it documents the contract, fails loud on regression, and adds zero runtime overhead.
Verification
node docs/.vuepress/plugins/strip-citation-markers/test.js->PASS strip-citation-markers (15 assertions)node docs/.vuepress/plugins/strip-citation-markers/test-plugin-order.js->PASS strip-citation-markers/test-plugin-order (10 assertions: 3 negative + 4 positive + 3 rule-chain)npx vuepress build docs->success Generated static files in docs/.vuepress/dist/docs
Commit: 4f0d2e7
…n match Bugbot flagged that `isSourcesHeading` tested the strict end-anchored SOURCES_HEADING_PATTERN against the raw heading inline content. Because footer detection runs before inline [V<n>] stripping, an authored heading like `§ Sources [V1]` failed the `\s*$` anchor and the Sources footer was never detected for such pages. Normalize the heading content via the existing pure `stripInlineMarkers` helper before the regex test. Add tests for both the Bugbot edge case (`§ Sources [V1]` heading) and a mutation-killer guarding that the plain `§ Sources` heading still triggers the strip.
… test fixture VuePress 1 does not recognise \`text\` as a valid Prism fence language. Replace with an unlabelled fence to avoid the I5 harness check failure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 01a3e9b. Configure here.
…gacy [V<n>] The strip-citation-markers plugin matched only the pre-2026-05-21 uppercase [V<n>] form, so current markers ([vrf_1], [dec_3], ...; parser ^\[[a-z][a-z0-9_]*\]$) leaked verbatim into rendered docs. Widen the inline pattern to the lowercase prefix+_digits grammar, keeping [V<n>] as a legacy alternative and the (?!\() link guard. Add fixtures for the lowercase grammar plus over-strip guards ([note]/[abc] preserved).
…s headings are not stripped
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #1679 +/- ##
========================================
Coverage 97.16% 97.16%
========================================
Files 175 176 +1
Lines 15319 15322 +3
Branches 3356 3356
========================================
+ Hits 14884 14887 +3
Misses 427 427
Partials 8 8 🚀 New features to boost your workflow:
|
|
I don't think we need this plugin. I'd rather rely on #1678 to make sure there is no citation markers in the public documentation |

Summary
Adds a small markdown-it plugin wired into the existing
extendMarkdownhook indocs/.vuepress/config.jsthat strips internal audit-harness annotations at build time so they never appear in customer-facing docs.Why
Internal authoring uses an audit-harness convention: factual claims are annotated inline with citation markers, and pages carry a trailing
§AuditSourcesfooter listing the underlying sources. These exist so the audit-harness can re-verify every claim before content ships — they are never meant for end users.What it does
[V<n>]and the current lowercase[<prefix>_<digits>]form (e.g.[vrf_1],[dec_3]); bare form only, real markdown links like[V12](url)are preserved.§AuditSourcesfooter heading and everything below it up to the next top-level (h1) heading. The marker is a deliberately unique token, so legitimateSources/§ Sourcesheadings are preserved (guarded by a test).code_inline,code_blockandfencetokens untouched so pages that document the audit-harness syntax still render.Files
docs/.vuepress/plugins/strip-citation-markers/index.js(plugin)docs/.vuepress/plugins/strip-citation-markers/test-fixture.md(fixture)docs/.vuepress/plugins/strip-citation-markers/test.js(Node test, 24 assertions)docs/.vuepress/plugins/strip-citation-markers/test-plugin-order.js(plugin-order integration test)docs/.vuepress/config.js(wire-up)Test plan
node docs/.vuepress/plugins/strip-citation-markers/test.js→PASS strip-citation-markers (24 assertions)node docs/.vuepress/plugins/strip-citation-markers/test-plugin-order.js→ PASS§AuditSourcesfooters and zero bare citation markers outside<code>/<pre>;[V12](url)rendered as a real link; inline/fenced markers preserved; legitimateSourcesheadings preserved.Note
Low Risk
Docs-only build pipeline change with broad test coverage; main risk is accidental removal of legitimate markdown if patterns or plugin order regress.
Overview
Adds a VuePress markdown-it plugin that strips internal audit-harness content at docs build time, and registers it in
extendMarkdownafterfootnotePluginandincludeCodeSnippet.The plugin mutates the parsed token stream: it removes bare inline citation markers (legacy
[V<n>]and current[prefix_<digits>], but not[label](url)), drops the§AuditSourcessection through the nexth1or beforefootnote_*tokens, and leaves code blocks untouched. It hookscore.rulerbeforereplacementsso heading anchors see cleaned text.Standalone Node tests cover fixture rendering, footnote/plugin order, and edge cases (legitimate
Sourcesheadings, over-stripping guards).Reviewed by Cursor Bugbot for commit 084c293. Bugbot is set up for automated code reviews on this repo. Configure here.