Skip to content

Commit f49d15b

Browse files
test(docs): run md-companions strip test in CI (HF-154)
The md-companions markdown stripper is the acceptance gate for the agent-friendly docs (per-page .md companions + llms.txt), but its test lived at docs/.vuepress/plugins/md-companions/strip.test.js — a path and suffix Jest's testMatch (`test/**/*spec.(ts|js)`) never discovers, so it never ran in CI. - Move the assertions into test/docs/md-companions-strip.spec.js as a Jest spec, where the default glob picks them up. The file is `.js`, so Karma's `.spec.ts`-only require.context skips it (the stripper is plain Node code, not part of the browser bundle). - Add an ESLint override for `**/test/**/*.spec.js` mirroring the existing `scripts/*.js` relaxations (node env, allow require of untyped modules). - Remove the orphan strip.test.js. - CHANGELOG: note the agent-friendly docs under [Unreleased] > Added. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent c429eeb commit f49d15b

4 files changed

Lines changed: 77 additions & 48 deletions

File tree

.eslintrc.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,5 +165,23 @@ module.exports = {
165165
'no-undef': 'off',
166166
},
167167
},
168+
{
169+
// Plain-Node Jest specs (e.g. docs tooling tests that `require` JS modules
170+
// rather than importing typed sources). Same relaxations as `scripts/*.js`.
171+
files: ['**/test/**/*.spec.js'],
172+
env: {
173+
node: true,
174+
},
175+
rules: {
176+
'@typescript-eslint/no-var-requires': 'off',
177+
'@typescript-eslint/no-unsafe-argument': 'off',
178+
'@typescript-eslint/no-unsafe-assignment': 'off',
179+
'@typescript-eslint/no-unsafe-call': 'off',
180+
'@typescript-eslint/no-unsafe-member-access': 'off',
181+
'@typescript-eslint/no-unsafe-return': 'off',
182+
'@typescript-eslint/restrict-template-expressions': 'off',
183+
'no-undef': 'off',
184+
},
185+
},
168186
],
169187
}

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
99

1010
### Added
1111

12+
- Added agent-friendly documentation: per-page `.md` companions, a Copy-Markdown button, an `llms.txt` index, and a coding-agent setup guide. [#1696](https://github.com/handsontable/hyperformula/pull/1696)
1213
- Added an Indonesian (Bahasa Indonesia) language pack. [#1674](https://github.com/handsontable/hyperformula/pull/1674)
1314

1415
## [3.3.0] - 2026-05-20

docs/.vuepress/plugins/md-companions/strip.test.js

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* CI-discoverable tests for the md-companions VuePress plugin's markdown
3+
* stripper (HF-154, agent-friendly docs). The stripper turns VuePress-flavoured
4+
* markdown into clean markdown for the per-page `.md` companions and `llms.txt`,
5+
* so its fidelity is the acceptance gate for the feature.
6+
*
7+
* This is a `.js` spec under `test/` so Jest's testMatch (`test/**\/*spec.(ts|js)`)
8+
* discovers it, while Karma (which only globs `.spec.ts`) skips it — the stripper
9+
* is plain Node code that does not run in the browser bundle.
10+
*/
11+
const { stripVuePressSyntax } = require('../../docs/.vuepress/plugins/md-companions/strip')
12+
13+
describe('md-companions stripVuePressSyntax', () => {
14+
it('converts a tip container with a title to a blockquote', () => {
15+
expect(stripVuePressSyntax(':::tip Heads up\nBe careful here.\n:::'))
16+
.toBe('> **Heads up**\n>\n> Be careful here.')
17+
})
18+
19+
it('converts a titleless warning container to a blockquote', () => {
20+
expect(stripVuePressSyntax(':::warning\nDanger zone.\n:::'))
21+
.toBe('> Danger zone.')
22+
})
23+
24+
it('leaves ::: tokens inside a code fence untouched', () => {
25+
expect(stripVuePressSyntax('```js\nconst x = ":::tip";\n```'))
26+
.toBe('```js\nconst x = ":::tip";\n```')
27+
})
28+
29+
it('removes <script> blocks', () => {
30+
expect(stripVuePressSyntax('Text before\n<script>\nconsole.log(1)\n</script>\nText after'))
31+
.toBe('Text before\nText after')
32+
})
33+
34+
it('removes self-closing Vue components', () => {
35+
expect(stripVuePressSyntax('Intro\n<CodingAgentWizard />\nOutro'))
36+
.toBe('Intro\nOutro')
37+
})
38+
39+
it('removes the [[toc]] marker', () => {
40+
expect(stripVuePressSyntax('# Title\n[[toc]]\nBody'))
41+
.toBe('# Title\nBody')
42+
})
43+
44+
it('preserves plain markdown content', () => {
45+
expect(stripVuePressSyntax('# H\n\n`code`\n\n[link](/guide/x)\n\n| a | b |\n|---|---|'))
46+
.toBe('# H\n\n`code`\n\n[link](/guide/x)\n\n| a | b |\n|---|---|')
47+
})
48+
49+
it('strips :::example (live demo) containers entirely', () => {
50+
expect(stripVuePressSyntax('## Demo\n\n::: example #ex1 --html 1\n@[code](example.html)\n:::\n\nOutro'))
51+
.toBe('## Demo\n\nOutro')
52+
})
53+
54+
it('does not let an inner 3-backtick fence close a 4-backtick outer fence', () => {
55+
expect(stripVuePressSyntax('````markdown\n```js\ncode\n```\n````'))
56+
.toBe('````markdown\n```js\ncode\n```\n````')
57+
})
58+
})

0 commit comments

Comments
 (0)