You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Breaking changes (pre-1.0, zero users):
- strip option replaces stripPatterns + replaceDefaultStrip + keepAsserts
(strip: RegExp[] | false | undefined)
- ?noStrip replaces ?keepAsserts as per-block override
- attribute option removed (hardcoded to "reference")
New features:
- Auto-dedent: common leading whitespace stripped from extracted regions
- Security boundary: allowOutsideRoot defaults to false, preventing
references from escaping rootDir
- Unclosed region detection: build fails if region opened but never closed
- file.fail() for errors with markdown source position context
- Proper ?query flag parsing (split on ?, not includes/replace)
Build:
- CJS generated from ESM via esbuild (eliminates manual duplication)
- npm run build generates index.cjs from index.mjs + lib/*.mjs
- prepublishOnly runs build + test
README rewrite:
- Documented new strip API with PRESET_STRIP composition
- Added auto-dedent section with before/after example
- Added MDX compatibility section
- Added VitePress incompatibility note
- Added false-positive caveat for strip patterns
- Added incremental migration note
- Updated comparison table (auto-dedent and security boundary parity)
- Updated options table and exports table
61 tests, all passing.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: README.md
+60-17Lines changed: 60 additions & 17 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -37,6 +37,8 @@ If the test breaks, CI fails. If the region moves, the build fails. **Stale docs
37
37
38
38
## Quick start
39
39
40
+
Code fences without `reference` are untouched -- migrate one block at a time.
41
+
40
42
Install:
41
43
42
44
```bash
@@ -197,10 +199,12 @@ These patterns are removed from injected code by default:
197
199
|`go`|`if err != nil { t.Fatal`| Go |
198
200
|`markers`| Lines ending with `// test-only` or `# test-only`| Any |
199
201
200
-
To keep assertions visible in a specific block, append `?keepAsserts`:
202
+
The `assert` and `expect()` patterns match lines starting with these keywords. If your library uses these as API calls (not test assertions), pass a custom `strip` list using `PRESET_STRIP` to include only the languages you need.
203
+
204
+
To keep assertions visible in a specific block, append `?noStrip`:
Extracted regions are automatically dedented. Common leading whitespace is removed so that code nested inside test functions or classes renders flush-left in your docs. No option needed -- this is always on.
254
+
255
+
For example, code indented inside a test function:
256
+
257
+
```python
258
+
deftest_create_user():
259
+
# region: create_user
260
+
from myapp import client
261
+
user = client.create_user(name="Alice")
262
+
# endregion: create_user
263
+
```
264
+
265
+
...renders as:
266
+
267
+
```python
268
+
from myapp import client
269
+
user = client.create_user(name="Alice")
237
270
```
238
271
239
272
## Options
240
273
241
274
| Option | Type | Default | Description |
242
275
|---|---|---|---|
243
276
|`rootDir`|`string`|`process.cwd()`| Base directory for resolving reference paths. |
277
+
|`allowOutsideRoot`|`boolean`|`false`| Allow references to files outside `rootDir`. Disabled by default as a security boundary. |
244
278
|`regionMarkers`|`{start, end}[]`|`DEFAULT_REGION_MARKERS`| Region marker pairs. Each `start`/`end` is a RegExp where group 1 captures the region name. |
245
-
|`stripPatterns`|`RegExp[]`|`[]`| Patterns to strip. Merged with defaults unless `replaceDefaultStrip` is true. |
246
-
|`replaceDefaultStrip`|`boolean`|`false`| If true, `stripPatterns` replaces the built-in defaults instead of merging. |
|`attribute`|`string`|`'reference'`| The code fence meta attribute name to look for. |
279
+
|`strip`|`RegExp[]`\|`false`|`undefined` (defaults) | Patterns to strip from injected code. `undefined` uses the built-in defaults. `false` disables stripping. `RegExp[]` replaces the defaults with your custom list. |
@@ -277,8 +306,18 @@ If a referenced file is missing or a region doesn't exist, **the build fails**:
277
306
Error: remark-code-region: region 'create_user' not found in tests/test_users.py
278
307
```
279
308
309
+
If a region is opened but never closed, **the build fails**:
310
+
311
+
```
312
+
Error: remark-code-region: region 'create_user' in tests/test_users.py was opened but never closed
313
+
```
314
+
280
315
This is intentional. Silent stale docs are worse than a build error.
281
316
317
+
## MDX compatibility
318
+
319
+
Works inside MDX components (`<Tabs>`, admonitions) -- the plugin runs at the remark AST level, before MDX processing. Any code fence with a `reference` attribute will be resolved, regardless of where it sits in the markdown tree.
320
+
282
321
## Framework support
283
322
284
323
### Docusaurus
@@ -324,19 +363,23 @@ const result = await remark()
324
363
.process(markdown);
325
364
```
326
365
366
+
VitePress uses markdown-it (not remark) and is not compatible.
367
+
327
368
## Why not remark-code-import?
328
369
329
370
[remark-code-import](https://github.com/kevin940726/remark-code-import) includes code from files using line ranges (`#L3-L6`). It's good for static inclusion, but:
| Include from file |`file=./path.js#L3-L6`|`reference="path.py#region_name"`|
334
-
|**Named regions**| No | Yes — stable across edits |
375
+
|**Named regions**| No | Yes -- stable across edits |
335
376
|**Strip test lines**| No | Auto-strips asserts, expects, test-only markers |
377
+
|**Auto-dedent**| Yes | Yes |
378
+
|**Security boundary**| Yes | Yes (`allowOutsideRoot` defaults to false) |
336
379
| Fail on missing file | Yes | Yes |
337
380
| Line ranges | Yes | No (regions don't shift when code is edited) |
338
381
339
-
Both plugins fail on missing files. The key difference is **how you target code**. Line ranges (`#L3-L6`) shift every time you add or remove a line above them. Named regions are anchored by markers in the source — edit freely above or below, the region stays correct. And auto-stripping test assertions is what makes "code lives in test files" practical — without it, you'd need separate display-only copies.
382
+
Both plugins fail on missing files. The key difference is **how you target code**. Line ranges (`#L3-L6`) shift every time you add or remove a line above them. Named regions are anchored by markers in the source -- edit freely above or below, the region stays correct. And auto-stripping test assertions is what makes "code lives in test files" practical -- without it, you'd need separate display-only copies.
0 commit comments