API
Most users only need conf.py settings and the command line. These modules are the public surface for extending or embedding the builder. This page is itself produced by the builder it documents.
Index
sphinx_vitepress.setup(app) | Register the vitepress builder and its configuration values. |
|---|---|
sphinx_vitepress.builder.VitepressBuilder(app) | |
sphinx_vitepress.translator.VitepressTranslator(...) | Emit VitePress-flavored markdown instead of plain GitHub markdown. |
sphinx_vitepress.escape.escape_vue(text) | Escape text so Vue's template compiler treats it as plain prose. |
sphinx_vitepress.prune.prune_virtual_page_links(...) | Remove links to pages this builder does not generate. |
sphinx_vitepress.sidebar.build_sidebar(env) | Nested VitePress sidebar mirroring the root document's toctrees. |
sphinx_vitepress.sidebar.build_nav(sidebar) | Top navigation: home, then each sidebar group as a dropdown. |
sphinx_vitepress.accents.resolve(value) | Normalize vitepress_accent into {"light": stops, "dark": stops}. |
sphinx_vitepress.accents.render_css(value) | CSS defining the accent variables the bundled theme reads. |
sphinx_vitepress.frontmatter.render(data) | Render a frontmatter block, or "" when there is nothing to emit. |
sphinx_vitepress.inventory.write_inventory(builder) | Write objects.inv for the built site. |
sphinx_vitepress.linkcode.make_resolver(base_url) | Build a linkcode_resolve for a URL prefix ending in a ref. |
sphinx_vitepress.versions.determine_bases(...) | Deploy folder names for a build. |
sphinx_vitepress.versions.collect_versions(...) | Every deployed base (folders carrying a siteinfo.js), picker order: stable first, then dev, then releases newest-first. |
sphinx_vitepress.deploy.run_deploy(source, ...) | Build source into deploy_dir/<base> for every deploy base, then refresh versions.js and the root redirect. |
sphinx_vitepress.nodejs.run_vitepress(site, ...) | Run vitepress <command> (build/dev) in site; returns the exit code. |
The extension
sphinx-vitepress: a Sphinx builder that renders documentation with VitePress.
setup functionsource
sphinx_vitepress.setup(app)Register the vitepress builder and its configuration values.
The builder
The vitepress Sphinx builder.
Subclasses sphinx-markdown-builder’s MarkdownBuilder (MIT, Liran Funaro): the base class provides outdated-doc tracking, .md writing, and get_target_uri (extension-suffixed links, which VitePress resolves). This class swaps in the VitePress translator; sidebar/config generation and objects.inv emission land here in finish() during M2/M4.
VitepressBuilder classsource
class sphinx_vitepress.builder.VitepressBuilder(app, env=None)- Parameters:
- app (Sphinx)
- env (BuildEnvironment)
VitepressBuilder.name attribute
name = 'vitepress'The builder’s name. This is the value used to select builders on the command line.
VitepressBuilder.epilog attribute
epilog = i'The VitePress markdown files are in %(outdir)s.'The message emitted upon successful build completion. This can be a printf-style template string with the following keys: outdir, project
VitepressBuilder.default_translator_class attributesource
default_translator_classalias of VitepressTranslator
VitepressBuilder.supported_linkcode attribute
supported_linkcode = 'vitepress'sphinx.ext.linkcode gates its [source] links behind only:: html unless a builder claims support. Ours become “source” badges on the docstring cards, so opt in under this builder’s own tag.
VitepressBuilder.init methodsource
init()Load necessary templates and perform initialization. The default implementation does nothing.
- Return type: None
VitepressBuilder.get_outdated_docs methodsource
get_outdated_docs()Return an iterable of output files that are outdated, or a string describing what an update build will build.
If the builder does not output individual files corresponding to source files, return a string here. If it does, return an iterable of those files that need to be written.
VitepressBuilder.write_doc methodsource
write_doc(docname, doctree)Write one page, then prepend its configured frontmatter.
- Parameters:
- docname (str) – Sphinx name of the document being written.
- doctree (docutils.nodes.document) – Its resolved doctree.
- Return type: None
VitepressBuilder.finish methodsource
finish()Finish the building process.
The default implementation does nothing.
- Return type: None
VitePress-flavored markdown translator.
Subclasses sphinx-markdown-builder’s MarkdownTranslator (MIT, Liran Funaro) and overrides emission where VitePress markdown diverges from plain GitHub markdown: admonitions become ::: containers, text is Vue-safe escaped, headings carry explicit {#id} anchors, raw HTML is fenced off from Vue, and code-fence languages unknown to shiki are remapped.
The behavioral reference is DocumenterVitepress.jl’s src/writer.jl (local copy in the repo root); the rules are documented in DESIGN.md §B/§C.
ADMONITIONS data
sphinx_vitepress.translator.ADMONITIONS: dict[str, tuple[str, str]] = {'attention': ('warning', 'Attention'), 'caution': ('warning', 'Caution'), 'danger': ('danger', 'Danger'), 'error': ('danger', 'Error'), 'hint': ('tip', 'Hint'), 'important': ('warning', 'Important'), 'note': ('tip', 'Note'), 'seealso': ('info', 'See also'), 'tip': ('tip', 'Tip'), 'warning': ('warning', 'Warning')}Sphinx/docutils admonition name -> (VitePress container kind, title). VitePress kinds are limited to: info | tip | warning | danger | details.
VIRTUAL_PAGES data
sphinx_vitepress.translator.VIRTUAL_PAGES = frozenset({'genindex', 'modindex', 'py-modindex', 'search'})Pages the Sphinx HTML builders synthesize but that have no VitePress equivalent (its built-in local search replaces them). Nearly every Sphinx project’s index page links to these, and VitePress fails builds on dead links, so the links are emitted as plain text instead. Genuinely broken links are left alone, since VitePress should catch those.
VitepressTranslator classsource
class sphinx_vitepress.translator.VitepressTranslator(document, builder)Emit VitePress-flavored markdown instead of plain GitHub markdown.
- Parameters:
- document (nodes.document)
- builder (VitepressBuilder)
VitepressTranslator.visit_note methodsource
visit_note(_node)Sphinx note directive.
- Parameters: _node (Element)
- Return type: None
VitepressTranslator.visit_hint methodsource
visit_hint(_node)Sphinx hint directive.
- Parameters: _node (Element)
- Return type: None
VitepressTranslator.visit_important methodsource
visit_important(_node)Sphinx important directive.
- Parameters: _node (Element)
- Return type: None
VitepressTranslator.visit_warning methodsource
visit_warning(_node)Sphinx warning directive.
- Parameters: _node (Element)
- Return type: None
VitepressTranslator.visit_seealso methodsource
visit_seealso(_node)Sphinx see also directive.
- Parameters: _node (Element)
- Return type: None
VitepressTranslator.visit_admonition methodsource
visit_admonition(node)Generic .. admonition:: Custom Title -> info container.
- Parameters: node (Element)
- Return type: None
VitepressTranslator.visit_versionmodified methodsource
visit_versionmodified(node)Node for version change entries. Currently used for “versionadded”, “versionchanged” and “deprecated” directives. Type will hold something like ‘deprecated’
- Parameters: node (Element)
- Return type: None
VitepressTranslator.visit_desc_signature methodsource
visit_desc_signature(node)API object signature: always anchored so cross-references resolve.
- Parameters: node (Element)
- Return type: None
VitepressTranslator.visit_math_block methodsource
visit_math_block(_node)docutils math block
- Parameters: _node (Element)
- Return type: None
VitepressTranslator.depart_math_block methodsource
depart_math_block(_node)docutils math block
- Parameters: _node (Element)
- Return type: None
Escaping and pruning
Vue-safe escaping for VitePress markdown output.
VitePress compiles every markdown page as a Vue template, so three things in plain prose are hazards that classic markdown escaping does not cover:
</>start HTML/component tags.dict[str, int]is safe butCallable<T>-style text or a stray<Response>is a build error.{{starts a Vue interpolation, so{{ placeholder }}text either errors or silently evaluates.- Fenced code blocks are auto-
v-preby VitePress and need no treatment; inline code is handled separately by the translator (wrapped in<span v-pre>only when it contains{{).
Following DocumenterVitepress.jl’s writer (writer.jl ~L1144), & is deliberately NOT escaped: VitePress copies heading text verbatim into per-page search JSON, and double-escaping there reads worse than the rare literal < a user may type.
escape_vue functionsource
sphinx_vitepress.escape.escape_vue(text)Escape text so Vue’s template compiler treats it as plain prose.
Drop navigation that points at pages VitePress does not have.
Nearly every Sphinx project ends its index with the stock “Indices and tables” block linking to genindex/modindex/search. Only the HTML builders synthesize those pages, so in a VitePress site the block is a heading over two or three inert bullets.
Whole list items (or paragraphs) that consist of nothing but such a link are removed, along with any list or section left empty as a result. A link used inside a sentence is left in place. The translator renders it as plain text, so the sentence still reads correctly.
prune_virtual_page_links functionsource
sphinx_vitepress.prune.prune_virtual_page_links(doctree, suffix)Remove links to pages this builder does not generate.
- Parameters:
- doctree (docutils.nodes.document) – The resolved doctree, modified in place.
- suffix (str) – The URI suffix internal links carry, so a target can be matched against the virtual page names.
- Return type: None
Site generation
Sidebar and nav generation from Sphinx’s toctree structure.
Each .. toctree:: becomes a VitePress sidebar group: its :caption: is the group heading and its entries are the items, recursing into the toctrees those entries declare. Captioned groups also become nav dropdowns, which is how a multi-section manual reads as a menu rather than a flat row.
Titles come from the toctree entries themselves where the author supplied one, and from env.titles otherwise.
build_sidebar functionsource
sphinx_vitepress.sidebar.build_sidebar(env)Nested VitePress sidebar mirroring the root document’s toctrees.
build_nav functionsource
sphinx_vitepress.sidebar.build_nav(sidebar)Top navigation: home, then each sidebar group as a dropdown.
A captioned group (one with items but no page of its own) becomes a VitePress nav dropdown; a plain page becomes a direct link.
User-selectable accent palettes.
The bundled theme paints links, buttons, active nav items and hero gradients from four accent stops, supplied as CSS variables. Projects pick a palette with vitepress_accent: either a preset name (sampled from the matplotlib colormap of the same name, so the site can match the figures in it) or explicit colors.
Stops run dark to light and are used by role, not position, so both themes stay readable: light mode links use deep (high contrast on white) while dark mode uses bright/glow.
PRESETS data
sphinx_vitepress.accents.PRESETS: dict[str, tuple[str, str, str, str]] = {'afmhot': ('#a93000', '#e66600', '#ff8000', '#ffb333'), 'blue': ('#0060a8', '#0087d7', '#0c9ff4', '#5fd7ff'), 'cividis': ('#00204d', '#31446b', '#666970', '#a69d75'), 'inferno': ('#781c6d', '#bb3754', '#ed6925', '#fbb61a'), 'magma': ('#6b1d81', '#b63679', '#f1605d', '#fe9f6d'), 'ocean': ('#005b7f', '#0087b3', '#00a9c4', '#57cfd6'), 'plasma': ('#6a00a8', '#b12a90', '#e16462', '#fca636'), 'viridis': ('#3b528b', '#21918c', '#5ec962', '#a0da39')}name -> (deep, mid, bright, glow), sampled from matplotlib colormaps.
resolve functionsource
sphinx_vitepress.accents.resolve(value)Normalize vitepress_accent into {"light": stops, "dark": stops}.
Accepts a preset name, a single hex color, a 4-color sequence, or a mapping with light/dark keys holding any of those.
render_css functionsource
sphinx_vitepress.accents.render_css(value)CSS defining the accent variables the bundled theme reads.
Per-page VitePress frontmatter.
VitePress reads a YAML block at the top of each page; the important use is layout: home, which turns a page into the hero/features landing page.
The block is emitted as JSON, which is valid YAML (a flow mapping), so no YAML emitter is needed and no escaping bugs are possible. VitePress’s frontmatter parser accepts it.
render functionsource
sphinx_vitepress.frontmatter.render(data)Render a frontmatter block, or "" when there is nothing to emit.
Emit a Sphinx objects.inv for the built VitePress site.
Only Sphinx’s HTML builders write an inventory natively, so we do it ourselves: every documented object (py:* roles, std:doc pages, std:label targets) becomes resolvable FROM other Sphinx projects via ordinary intersphinx. The file goes to public/ under the source root (VitePress’s static-assets directory), which is copied verbatim to the site root, exactly where intersphinx looks (<site>/objects.inv).
write_inventory functionsource
sphinx_vitepress.inventory.write_inventory(builder)Write objects.inv for the built site.
- Parameters: builder (sphinx_vitepress.builder.VitepressBuilder) – The running builder; its output directory receives the file.
- Return type: None
Link each documented object to the exact lines that define it.
sphinx.ext.linkcode asks the project for a URL per object but leaves the work of finding one to conf.py, so most projects either copy the same twenty lines of inspect handling or settle for linking to the top of a module. Setting vitepress_source_url installs a resolver that finds the object’s file and line range and produces, for example:
https://github.com/you/project/blob/main/src/pkg/core.py#L42-L57The file path is taken relative to the git working tree the source lives in, so it matches the repository layout without further configuration.
make_resolver functionsource
sphinx_vitepress.linkcode.make_resolver(base_url)Build a linkcode_resolve for a URL prefix ending in a ref.
- Parameters: base_url (str) – Everything up to the repository-relative path, for example
https://github.com/you/project/blob/main. Pin a commit rather than a branch if the links should keep pointing at the code the documentation was built from. - Returns: A resolver suitable for
linkcode_resolveinconf.py. - Return type: callable
Deployment
Versioned-docs bookkeeping, ported from DocumenterVitepress.jl’s model.
A deployed site is a tree of independent VitePress builds:
gh-pages/
stable/ # full build, base=/repo/stable/
v1/ # full build, base=/repo/v1/
dev/ # full build from the dev branch
versions.js # var DOC_VERSIONS = [...] (read by VersionPicker.vue)
index.html # redirect to stable/ (or dev/ if no release yet)Each build folder carries a siteinfo.js declaring its own version; the root versions.js is regenerated by scanning for those files, so old versions keep working without being rebuilt.
determine_bases functionsource
sphinx_vitepress.versions.determine_bases(version, <abbr title="Keyword-only parameters separator (PEP 3102)">*</abbr>, keep='breaking', devurl='dev')Deploy folder names for a build.
None means a dev build -> [devurl]. A release tag like v1.2.3 expands according to keep:
"breaking"(default):["v1", "stable"](["v0.2", "stable"]for 0.x, where the minor is the breaking line)"minor":["v1.2", "v1", "stable"]"patch":["v1.2.3", "v1.2", "v1", "stable"]
write_siteinfo functionsource
sphinx_vitepress.versions.write_siteinfo(base_dir, name)Stamp a build folder with its own version name.
collect_versions functionsource
sphinx_vitepress.versions.collect_versions(deploy_dir, <abbr title="Keyword-only parameters separator (PEP 3102)">*</abbr>, devurl='dev')Every deployed base (folders carrying a siteinfo.js), picker order: stable first, then dev, then releases newest-first.
Assemble a versioned deploy tree (the DocumenterVitepress model).
Each base gets its own full VitePress build (asset URLs embed base, so folders cannot be copies of one another). The markdown workdir is reused across bases, so npm install runs at most once per deploy.
Pushing the resulting tree to gh-pages is left to CI (see .github/workflows/docs.yml for the reference workflow).
run_deploy functionsource
sphinx_vitepress.deploy.run_deploy(source, deploy_dir, <abbr title="Keyword-only parameters separator (PEP 3102)">*</abbr>, version, repo_base='/', keep='breaking', devurl='dev')Build source into deploy_dir/<base> for every deploy base, then refresh versions.js and the root redirect. Returns an exit code.
Locate and drive the Node toolchain.
Only the CLI touches Node. The Sphinx builder itself always finishes with markdown + config on disk, so docs can be generated on machines without Node and built elsewhere.
NodeToolchainError exceptionsource
exception sphinx_vitepress.nodejs.NodeToolchainErrorA required Node tool is missing from PATH.
ensure_node_modules functionsource
sphinx_vitepress.nodejs.ensure_node_modules(site)Install the site’s Node dependencies if they are missing or stale.
The install is repeated when package.json changes, so upgrading sphinx-vitepress (which may pin a newer VitePress) does not keep building an existing output directory against the old dependencies.
- Parameters: site (Path)
- Return type: None