Replaces the single-regex raw path parsing with a structural parser
that peels [title], {meta} and #region off the end, so meta can no
longer be silently swallowed into the file path. Inside the braces,
everything after the language is now passed through to the fence info
verbatim, allowing multiple attributes and quoted values (e.g.
{ts twoslash key="a b"}). Extensions are derived from the file name,
so dotfiles resolve, region references may contain dots, and {1, 2}
style spacing is tolerated.
Region extraction uses the new region engine, so all same-named
regions are concatenated in document order, and which marker lines are
removed from the output is configurable through stripRegionMarkers.
BREAKING CHANGES:
- a missing snippet file or region now throws instead of rendering an
error message inside the code block (or importing the whole file, in
the region case); the silent option restores non-fatal behavior by
logging a warning and rendering nothing
- the language inferred from a file name now includes uppercase
extensions, which were previously matched as [a-z0-9]+ only, so a
snippet of e.g. Foo.TS is highlighted where it used to render
without a language; suffixes that are not alphanumeric, like .c++ or
.code-snippets, are still not inferred and need the language given
in the braces
- markdown.snippet now accepts an options object in addition to the
boolean toggle
- rawPathToToken, findRegion and dedent are no longer exported from
the plugin module
Co-authored-by: Miroma <its.miroma@proton.me>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Adds readTextFile/readTextFileSync (CRLF/CR -> LF) next to the raw
retrying readFile and switches the markdown-source readers to them
(content loader, dynamic route templates, local search, includes).
Raw reads stay in place where bytes must be preserved (serve, init
scaffolding).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
gray-matter memoizes every parsed result in a plain cache object keyed
by the full input string, except when it is passed an options object.
310f934938/index.js (L44-L47)
such cache is never bounded, or cleared, so on large sites memory usage
skyrockets.
with this change, we are always passing an empty options object on every
call to matter() to bypass its internal cache.
Co-authored-by: Calum H. (IMB11) <contact@cal.engineer>
Original-patch-by: Calum H. (IMB11) <contact@cal.engineer>
Content, include, route-template and search reads now run
concurrently, so large sites can hit EMFILE/ENFILE. Route all async
reads through a shared readFile util that retries with backoff.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Expanding an include that is its own ancestor recursed forever.
Track the ancestor chain and leave such includes unexpanded; the
same file can still be included repeatedly as a sibling.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Resolve includes through replaceAsync and fs/promises so include
files are read without blocking the event loop while pages render
concurrently.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
**BREAKING CHANGE:**
The previous `<!-- @include: ./path/to/file -->` syntax silently ignored errors when files did not exist. This behavior was originally intended as an escape hatch while documenting includes, but better solutions now exist using Shiki transformers.
For most users, no code changes are required. If you now see errors, it means your includes are broken and were previously not being reported.
Users who intentionally reference non-existent files or want to document includes without resolving them can configure `markdown.codeTransformers` with a `postprocess` hook. See `docs/.vitepress/config.ts` in this repo for an example.