Moves <!-- @include: --> expansion out of markdownToVue and the local
search plugin into an include plugin registered on the renderer, which
wraps renderAsync and expands includes whenever the env carries a file
path. createMarkdownRenderer users and createContentLoader with render
or excerpt enabled now get includes expanded too (previously the
directives silently came through unexpanded), and the expansion is
reachable from the public API without exporting the helper (#4838).
Region selection uses the region engine (all same-named regions
concatenate, matched across comment styles), frontmatter of markdown
files is stripped before locating regions and headings so both share
one coordinate space, and the region suffix is anchored to the end of
the include path, so paths containing # now work.
Files reached by a failed render are still reported, so that creating
a missing snippet or include recovers the page instead of requiring an
edit of the including file.
BREAKING CHANGES:
- a missing region or heading anchor now throws instead of silently
including the whole file, and out-of-bounds or inverted ranges throw
instead of clamping; markdown.include.silent logs a warning and
expands to nothing instead
- markdown.include is a new option; false disables include processing
- custom search _render functions receive the raw source (sync
md.render does not expand includes; use renderAsync)
- the include-expanded source is exposed as env.src
Co-authored-by: Miroma <its.miroma@proton.me>
Co-authored-by: Naloam <110604855+Naloam@users.noreply.github.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
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>
Shared engine for VS Code-style region extraction, used by the snippet
and include rewrites. Compared to findRegion in the snippet plugin, it
returns all same-named regions in document order and matches marker
styles per line instead of locking onto the first style found, so
same-named regions in mixed-comment files (e.g. Vue SFCs) merge. All
open regions are tracked, and an end marker without a name closes the
innermost region opened in its own comment style, so it neither gets
captured by a region of another language nested inside it nor closes
one that was left open there.
The marker regexes follow the folding.markers definitions VS Code ships
per language, which corrects two of the previous ones: REM is
case-insensitive in bat, and #pragma allows a space after the hash.
Those definitions disagree about whether the hash is required - the
marker makes it optional for js and markdown, while html, css, sql, bat
and f# require it - so related comment styles are merged into one regex
each, keeping the hash optional only where at least one of the merged
languages makes it optional. Since a markdown renderer cannot know the
language of an imported file, all styles are tried on every file, which
makes this a superset of what an editor folds. Note that a language
service can disagree with the marker its language ships: TypeScript
requires the hash the ts/js marker makes optional, while the Lua one
accepts it hash-less where we require it. Fixtures covering the marker
forms per language live in brc-dd/region-marker-fixtures.
Quoted Visual Basic region names are matched without their quotes, and
region markers declared as JSON keys are recognized as an extension,
plain JSON having no comments to put a marker in.
Co-authored-by: Miroma <its.miroma@proton.me>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
`markdown.codeCopyButton` now holds both the button tooltip
(`tooltipText`) and the text shown after copying (`copiedText`),
per-locale overridable via `locales.<index>.markdown.codeCopyButton`.
The copied text is emitted as a `data-copied` attribute on the button
and rendered by the theme with `content: attr(data-copied)`.
BREAKING CHANGE: `markdown.codeCopyButtonTitle` is now
`markdown.codeCopyButton.tooltipText`, and its default changed from
"Copy Code" to "Copy code". The `--vp-code-copy-copied-text-content`
CSS variable and its built-in per-language `:lang()` defaults are
removed - set `codeCopyButton.copiedText` (per locale) instead.
close#4431
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Strings baked into pages by the markdown renderer can now be overridden
per locale via `locales.<index>.markdown` in the site config: container
titles (including GitHub-flavored alerts and custom containers) and the
code copy button title. Values resolve against `env.localeIndex` at
render time and fall back to the root markdown options, so the single
shared renderer keeps working unchanged.
close#4431
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New containers can be registered via
`markdown.container.customContainers`, mapping a container name to its
default title. Registered names work as `::: name` blocks and as
GitHub-style alerts (`> [!NAME]`), with custom titles, attributes, and
no-title behaving like the built-in types. Styling is left to the theme
via `.custom-block.name`.
close#3591close#3603close#4228
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A no-title attribute (`::: tip {no-title}`) renders a container without
its title element, and the theme reduces the top padding for containers
without one. It has no effect on `details`, which always needs its
summary. The docs previously hand-rolled this with a raw div and an
inline style - those are now switched to the new syntax.
close#4928close#4932close#4929
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replaces markdown-it-container and merges the GitHub alerts plugin into
the containers module so both share one title map. Rendered output is
byte-compatible with the previous implementation.
This also restores fence-line attributes on containers ({open}, {.class},
etc.), which broke when markdown-it-attrs was replaced with
@mdit/plugin-attrs - its fence rule handled containers too, but had to be
disabled to keep code block meta intact. The container plugin now parses
the trailing braces itself, so the old markdown-it-attrs patch is not
needed in any form.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plugin options that could be disabled with `false` (`attrs`, `emoji`,
`tasklist`, `anchor`, `toc`, `image`, `component`) now also accept
`true`, which - like leaving them unset - enables the plugin with its
default options. Only object values are forwarded to the plugins.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Renders `- [ ] task` syntax via `@mdit/plugin-tasklist`, enabled by
default and configurable through the new `tasklist` markdown option
(set to `false` to disable). The default theme hides list markers for
task items and pulls checkboxes into the list gutter, GitHub-style.
close#413close#1923close#3648close#5110
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The `fence` rule is disabled by default, replacing the patch we carried
to stop curly attributes from consuming code block meta (line
highlighting etc.). Drops both attrs patches and
`@types/markdown-it-attrs`.
BREAKING CHANGE: `markdown.attrs` options are now typed by
`@mdit/plugin-attrs`: `leftDelimiter`, `rightDelimiter`, and
`allowedAttributes` are renamed to `left`, `right`, and `allowed`. A
`rule` option is available for toggling individual attribute rules
(VitePress disables `fence` by default).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Captures what the markdown-it-attrs patch enforces (curly attributes
never consume fence info, preserving line-highlight syntax) plus the
supported attribute placements, as a regression baseline.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
attrs registers its core rule at a fixed position (before linkify)
while anchor pushes to the end of the chain, so user-defined ids from
curly attributes win regardless of registration order. Remove the
comment that claimed the order matters.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- group `MarkdownOptions` into sections by concern (general, syntax
highlighting, code blocks, markdown extensions, vue integration) and
rewrite the jsdocs with a consistent voice, documenting the previously
undocumented `externalLinks` default and correcting the `container`
description (label customization, not plugin pass-through)
- register plugins in accurately-labeled groups (vitepress
customizations, community plugins, mdit-vue plugins) and note the
order-sensitive couplings inline (lineNumbers after preWrapper,
anchor after attrs)
- add a test for the `cjkFriendlyEmphasis` toggle
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Allows custom themes to opt out of markup and behavior added on top of
vanilla markdown rendering:
- `anchor`, `emoji`, `toc`, `component`, `image` now also accept `false`
- new `preWrapper` and `snippet` boolean options (default true)
- `lineNumbers` is a no-op when `preWrapper` is disabled, as its markup
depends on the wrapper
close#4484close#4556
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BREAKING CHANGE: The `markdown.image.lazyLoading` option has been renamed to `markdown.image.lazyLoad`.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
BREAKING CHANGE: VitePress now runs on Vite 5. Please refer https://vitejs.dev/guide/migration for breaking changes and migration guide if you're relying on some Vite-specific things.