Skip to content

Docs: VuePress plugin to strip [V<n>] citation markers and §Sources footers at build#1679

Open
marcin-kordas-hoc wants to merge 5 commits into
developfrom
feat/vuepress-strip-citation-markers
Open

Docs: VuePress plugin to strip [V<n>] citation markers and §Sources footers at build#1679
marcin-kordas-hoc wants to merge 5 commits into
developfrom
feat/vuepress-strip-citation-markers

Conversation

@marcin-kordas-hoc
Copy link
Copy Markdown
Collaborator

@marcin-kordas-hoc marcin-kordas-hoc commented May 25, 2026

Summary

Adds a small markdown-it plugin (~165 LOC) wired into the existing extendMarkdown hook in docs/.vuepress/config.js that 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 [V<n>] markers, and pages carry a trailing § Sources footer that lists the underlying sources. These exist so the audit-harness can 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.

What it does

  • 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 pages that document the audit-harness syntax itself still render correctly.

Files

  • docs/.vuepress/plugins/strip-citation-markers/index.js (plugin, ~165 LOC)
  • docs/.vuepress/plugins/strip-citation-markers/test-fixture.md (fixture)
  • docs/.vuepress/plugins/strip-citation-markers/test.js (Node test, 20 assertions)
  • docs/.vuepress/plugins/strip-citation-markers/test-plugin-order.js (plugin-order integration test)
  • docs/.vuepress/config.js (wire-up: 2 lines)

Test plan

  • node docs/.vuepress/plugins/strip-citation-markers/test.js -> PASS strip-citation-markers (20 assertions)
  • Full vuepress build docs with the fixture temporarily placed under docs/guide/; grep of docs/.vuepress/dist confirms:
    • Zero [V<n>] markers outside <code>/<pre> blocks in rendered HTML
    • Zero §Sources occurrences
    • [V12](url) rendered as a real link
    • Inline `[V99]` and fenced [V7] preserved
  • Reviewer: spot-check by adding a test page with markers, running npm run docs:build, and confirming the body text is clean

Note

Low Risk
Docs-only markdown transform with tests; main risk is mis-stripping footers or links if plugin order or regex rules change.

Overview
Adds a markdown-it plugin wired in docs/.vuepress/config.js so customer-facing docs never show internal audit-harness markup.

At build time it removes bare inline [V<n>] citation markers (with light whitespace cleanup), drops the Sources / § Sources section through the next h1 or before footnote tokens, and leaves real [Vn](url) links and code blocks untouched. The plugin hooks before replacements so heading anchors see cleaned text.

Standalone Node tests cover rendering edge cases, footnote + footer interaction, and footnote_tail vs strip-citation-markers rule order to match the VuePress plugin stack.

Reviewed by Cursor Bugbot for commit 01a3e9b. Bugbot is set up for automated code reviews on this repo. Configure here.

…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.
@netlify
Copy link
Copy Markdown

netlify Bot commented May 25, 2026

Deploy Preview for hyperformula-dev-docs ready!

Name Link
🔨 Latest commit 01a3e9b
🔍 Latest deploy log https://app.netlify.com/projects/hyperformula-dev-docs/deploys/6a17e1ba9db9670008b56790
😎 Deploy Preview https://deploy-preview-1679--hyperformula-dev-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link
Copy Markdown

netlify Bot commented May 25, 2026

Deploy Preview for hyperformula-docs ready!

Name Link
🔨 Latest commit 238c475
🔍 Latest deploy log https://app.netlify.com/projects/hyperformula-docs/deploys/6a14089c8b913d0008dce185
😎 Deploy Preview https://deploy-preview-1679--hyperformula-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Comment thread docs/.vuepress/plugins/strip-citation-markers/index.js
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 25, 2026

Performance comparison of head (01a3e9b) vs base (508d78f)

                                     testName |   base |   head | change
------------------------------------------------------------------------
                                      Sheet A | 490.33 | 489.01 | -0.27%
                                      Sheet B |  150.2 | 153.01 | +1.87%
                                      Sheet T | 138.57 | 138.01 | -0.40%
                                Column ranges | 465.03 | 471.56 | +1.40%
Sheet A:  change value, add/remove row/column |  14.59 |  15.67 | +7.40%
 Sheet B: change value, add/remove row/column | 131.76 | 140.98 | +7.00%
                   Column ranges - add column | 145.19 | 154.41 | +6.35%
                Column ranges - without batch | 450.58 | 468.35 | +3.94%
                        Column ranges - batch | 115.13 | 114.07 | -0.92%

…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.
Comment thread docs/.vuepress/plugins/strip-citation-markers/index.js
…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.
@marcin-kordas-hoc
Copy link
Copy Markdown
Collaborator Author

Tier 2 hardening — mutation gaps + plugin-order lock-in

Follow-up to address two QE findings from the Tier 1 review.

Mutation testing (50% -> closed)

Manual mutation analysis of the strip plugin (mutation-testing skill, manual reasoning over mewt/muton because the SUT is ~160 LOC of pure JS) flagged 5 surviving mutants. Five new assertions added to test.js (10 -> 15 total):

Mutant Mutation New assertion kills it via
M1 \d+ -> \d* in INLINE_CITATION_PATTERN literal [V] (no digits) must survive
M2 drop (?!\() lookahead link text V12 anchored (not collapsed to V)
M3 drop i flag on SOURCES_HEADING_PATTERN lowercase ## sources footer must also be stripped
M5 t.tag === 'h1' -> 'h2' in findFooterEnd content under a post-Sources # Second page h1 must survive (highest-blast-radius mutant)
M11 drop .replace(/[ \t]{2,}/g, ' ') multiple markers should collapse must NOT contain a 2+ space run

SFDIPOT P0 — plugin-order coupling

The strip plugin's findFooterEnd relies on markdown-it-footnote's footnote_* tokens being present in the stream when our splice runs. Added test-plugin-order.js with 10 assertions covering three layers:

  1. 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.
  2. Positive control (config.js ordering: footnote first, strip last): footnotes survive AND markers/footer stripped.
  3. Rule-chain invariant: asserts footnote_tail appears BEFORE strip-citation-markers in md.core.ruler. This is the actual primitive (not md.use() call order — both plugins hook into named ruler positions, so the order that matters is the resulting core.ruler chain). If a future markdown-it-footnote version moves footnote_tail, this assertion fires and points engineers at the root cause directly.

Why option (A) and not (B)

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

marcin-kordas-hoc and others added 2 commits May 26, 2026 02:53
…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>
@codecov
Copy link
Copy Markdown

codecov Bot commented May 28, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 97.16%. Comparing base (508d78f) to head (01a3e9b).
⚠️ Report is 2 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@           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           

see 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ 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.


// 2. §Sources footer must be gone.
assert(
!/Sources/i.test(renderedWithoutCode) || !/source-1/.test(rendered),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test assertion uses OR instead of AND

Medium Severity

The assertion on line 48 uses || (OR) between the two conditions, but the intent is to verify that both the Sources heading text and the source-1 footer body URL are removed. With ||, the assertion passes even if only one condition is met — for example, the heading could leak into the rendered output as long as source-1 is absent, or vice versa. This weakens the test and could mask regressions where the footer is only partially stripped. The operator needs to be &&.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 01a3e9b. Configure here.

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