From 3bd224be2b6d450d4fe92fa98db0d6152d212bbc Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 3 Aug 2026 13:07:24 -0400 Subject: [PATCH 1/3] docs: vendor the VitePress config; serve static assets from public/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `MarkdownVitepress` does not expose `themeConfig.search` or `markdown.config`, so `docs/src/.vitepress/config.mts` is vendored from the DocumenterVitepress template with the MPSKit-specific hooks added on top. Since a vendored copy silently rots, `make.jl` checksums the upstream template and warns when it changes, naming the two template versions our copy is known to be a faithful superset of. VitePress serves files under `src/public/` verbatim at the site root, which is what the logo and favicon need; `src/assets/` is for files Documenter itself processes. Move them accordingly and add the landing-page feature icons alongside. The new `theme/custom.css` also repairs the base font stack behind #477. VitePress self-hosts Inter as a variable font (`wght` axis 100–900, emitted into the site's own `assets/`) and names it first in `--vp-font-family-base`. The DocumenterVitepress template then overrides that variable with `"Barlow", "Inter var experimental", "Inter var", …`: Barlow is never loaded, the two `Inter var` names are what VitePress called the face before it moved to Inter v4 (vuejs/vitepress#3694), and plain `"Inter"` is absent — so the bundled font went unused and text fell through to a platform substitute, which on Linux exposed no real bold face. Restoring VitePress' own stack verbatim gets real 600/700 faces back, with no webfont to add and nothing fetched from a third party. Co-Authored-By: Claude Opus 5 (1M context) --- docs/Project.toml | 3 + docs/make.jl | 19 +++ docs/src/.vitepress/config.mts | 202 ++++++++++++++++++++++++ docs/src/.vitepress/theme/custom.css | 103 ++++++++++++ docs/src/{assets => public}/favicon.ico | Bin docs/src/{assets => public}/logo.svg | 0 6 files changed, 327 insertions(+) create mode 100644 docs/src/.vitepress/config.mts rename docs/src/{assets => public}/favicon.ico (100%) rename docs/src/{assets => public}/logo.svg (100%) diff --git a/docs/Project.toml b/docs/Project.toml index 87a66b634..b6a10b9fa 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -11,8 +11,10 @@ MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" +SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" +TensorKitTensors = "41b62e7d-e9d1-4e23-942c-79a97adf954b" TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" [sources] @@ -23,3 +25,4 @@ Documenter = "1.11" DocumenterCitations = "1.5" DocumenterInterLinks = "1" DocumenterVitepress = "0.3.7" +TensorKitTensors = "0.2" diff --git a/docs/make.jl b/docs/make.jl index 59ded9221..2ea281eb0 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -11,6 +11,25 @@ using Documenter using DocumenterVitepress using DocumenterCitations using DocumenterInterLinks +using SHA: sha256 + +# `src/.vitepress/config.mts` is vendored from the DocumenterVitepress template (see the +# header comment there) so that we can hook `themeConfig.search` and `markdown.config`, +# which `MarkdownVitepress` does not expose. Warn when upstream changes the template, so +# that our copy can be re-synced — or dropped, once the fixes land upstream. +let template = joinpath(pkgdir(DocumenterVitepress), "template", "src", ".vitepress", "config.mts") + # Templates the vendored copy is known to be a faithful superset of; v0.3.4 and v0.3.5 + # differ only by the (inert for us) NOINDEX marker. + vendored_from = ( + "ca5a958eb398b3219557633f017467cfa07f4882dc2dfe55b12d1f6c0e70d729", # v0.3.4 + "56289223983a3844417eae597f81da878f395792a529721e7873178c92d60721", # v0.3.5 + ) + actual = bytes2hex(sha256(read(template))) + actual in vendored_from || @warn """ + DocumenterVitepress' `config.mts` template has changed since `docs/src/.vitepress/config.mts` \ + was vendored from it. Re-sync the vendored copy (keeping the `MPSKit:` additions), or delete \ + it if upstream now ships them.""" template actual +end # examples example_dir = joinpath(@__DIR__, "src", "examples") diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts new file mode 100644 index 000000000..1c23640a1 --- /dev/null +++ b/docs/src/.vitepress/config.mts @@ -0,0 +1,202 @@ +// ============================================================================ +// VENDORED FILE — keep in sync with DocumenterVitepress. +// +// This is a verbatim copy of the DocumenterVitepress **v0.3.5** template at +// `template/src/.vitepress/config.mts`, plus the MPSKit additions marked with +// `MPSKit:` below. DocumenterVitepress copies this file into the build as-is +// and then performs its `REPLACE_ME_DOCUMENTER_VITEPRESS*` substitutions on it +// (see `modify_config_file` in DocumenterVitepress/src/vitepress_config.jl), so +// the nav, sidebar, base, outDir, ... all keep working. +// +// We only vendor it because `themeConfig.search.options` and `markdown.config` +// are not reachable from `docs/make.jl`. Both additions below belong upstream +// in DocumenterVitepress — see `docs/UPSTREAM_DVP_NOTES.md`. Once upstream +// ships them, DELETE this file and the drift guard in `docs/make.jl`. +// +// `docs/make.jl` hashes the installed DocumenterVitepress template and warns if +// it has changed, which means this copy needs re-syncing. +// ============================================================================ + +import { defineConfig } from 'vitepress' +import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' +import { mathjaxPlugin } from './mathjax-plugin' +import { juliaReplTransformer } from './julia-repl-transformer' +import footnote from "markdown-it-footnote"; +import path from 'path' + +const mathjax = mathjaxPlugin() + +function getBaseRepository(base: string): string { + if (!base || base === '/') return '/'; + const parts = base.split('/').filter(Boolean); + return parts.length > 0 ? `/${parts[0]}/` : '/'; +} + +// MPSKit: --------------------------------------------------------------- +// DocumenterVitepress renders each docstring as a raw `
` block whose +// anchor lives in the ``: +// +// +// MPSKit.FiniteMPS +// +// VitePress' local search only splits a page into indexable sections at +// headings (`......`), so an `@autodocs` page is +// indexed as one single huge document: docstrings rank poorly against short +// manual sections and every hit links to the top of the page. Rewriting each +// summary into a heading *for indexing only* gives one search entry per +// docstring, titled with the binding and deep-linking to its anchor. +// See QuantumKitHub/MPSKit.jl#478. +// +// The replacement has to mirror the shape VitePress' own heading anchors have, +// because the indexer reads the section title from the text *before* the anchor +// (`headingContentRegex = /(.*?).*?<\/a>/i`) and drops any +// section whose title comes out empty. +const DOCSTRING_SUMMARY = + /(.*?)<\/span><\/a>.*?<\/summary>/g + +// MPSKit: --------------------------------------------------------------- +// Documenter rewrites every markdown heading inside a docstring into a +// bold-only paragraph before any writer sees it (`recursive_heading_to_bold!` +// in Documenter/src/expander_pipeline.jl), so `# Constructors` reaches +// VitePress as `

Constructors

` with nothing to style. +// Tag exactly those paragraphs so `theme/custom.css` can render them as +// section headings again. See QuantumKitHub/MPSKit.jl#477. +// +// Scoped to docstring `
` blocks, and requires the paragraph to consist +// of nothing but one ``, so that a paragraph merely *starting* with +// bold text (e.g. "**Not every algorithm ...** — see the table below") is left +// alone. +function docstringHeadings(md) { + md.core.ruler.push('mpskit_docstring_headings', (state) => { + const tokens = state.tokens + let depth = 0 + for (let i = 0; i < tokens.length; i++) { + const token = tokens[i] + + if (token.type === 'html_block') { + if (/]*\bclass=['"][^'"]*\bjldocstring\b/.test(token.content)) depth++ + else if (depth > 0 && /<\/details>/.test(token.content)) depth-- + continue + } + + if (depth === 0 || token.type !== 'paragraph_open') continue + const inline = tokens[i + 1] + if (!inline || inline.type !== 'inline' || !inline.children) continue + + // markdown-it emits empty `text` tokens around inline markup. + const children = inline.children.filter( + (c) => !(c.type === 'text' && c.content === '') + ) + if (children.length < 2) continue + if (children[0].type !== 'strong_open') continue + if (children[children.length - 1].type !== 'strong_close') continue + + token.attrJoin('class', 'jldocstring-heading') + } + }) +} +// ----------------------------------------------------------------------- + +const baseTemp = { + base: 'REPLACE_ME_DOCUMENTER_VITEPRESS',// TODO: replace this in makedocs! +} + +const navTemp = { + nav: 'REPLACE_ME_DOCUMENTER_VITEPRESS', +} + +const nav = [ + ...navTemp.nav, + { + component: 'VersionPicker' + } +] + +// https://vitepress.dev/reference/site-config +export default defineConfig({ + base: 'REPLACE_ME_DOCUMENTER_VITEPRESS',// TODO: replace this in makedocs! + title: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + description: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + lastUpdated: true, + cleanUrls: true, + outDir: 'REPLACE_ME_DOCUMENTER_VITEPRESS', // This is required for MarkdownVitepress to work correctly... + head: [ + ['link', { rel: 'icon', href: 'REPLACE_ME_DOCUMENTER_VITEPRESS_FAVICON' }], + ['script', {src: `${getBaseRepository(baseTemp.base)}versions.js`}], + // ['script', {src: '/versions.js'], for custom domains, I guess if deploy_url is available. + ['script', {src: `${baseTemp.base}siteinfo.js`}], + // REPLACE_ME_DOCUMENTER_VITEPRESS_NOINDEX + ], + + markdown: { + codeTransformers: [juliaReplTransformer()], + config(md) { + md.use(tabsMarkdownPlugin); + md.use(footnote); + mathjax.markdownConfig(md); + md.use(docstringHeadings); // MPSKit: see above + }, + theme: { + light: "github-light", + dark: "github-dark" + }, + }, + vite: { + plugins: [ + mathjax.vitePlugin, + ], + define: { + __DEPLOY_ABSPATH__: JSON.stringify('REPLACE_ME_DOCUMENTER_VITEPRESS_DEPLOY_ABSPATH'), + }, + resolve: { + alias: { + '@': path.resolve(__dirname, '../components') + } + }, + optimizeDeps: { + exclude: [ + '@nolebase/vitepress-plugin-enhanced-readabilities/client', + 'vitepress', + '@nolebase/ui', + ], + }, + ssr: { + noExternal: [ + // If there are other packages that need to be processed by Vite, you can add them here. + '@nolebase/vitepress-plugin-enhanced-readabilities', + '@nolebase/ui', + ], + }, + }, + themeConfig: { + outline: 'deep', + logo: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + search: { + provider: 'local', + options: { + detailedView: true, + // MPSKit: index every docstring as its own section — see above. + _render(src, env, md) { + const html = md.render(src, env) + if (env.frontmatter?.search === false) return '' + return html.replace( + DOCSTRING_SUMMARY, + (_match, id, href, name) => + `

${name} ​

` + ) + } + } + }, + nav, + sidebar: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + sidebarDrawer: 'REPLACE_ME_DOCUMENTER_VITEPRESS_SIDEBAR_DRAWER', + editLink: 'REPLACE_ME_DOCUMENTER_VITEPRESS', + socialLinks: [ + { icon: 'github', link: 'REPLACE_ME_DOCUMENTER_VITEPRESS' } + ], + footer: { + message: 'Made with DocumenterVitepress.jl
', + copyright: `© Copyright ${new Date().getUTCFullYear()}.` + } + } +}) diff --git a/docs/src/.vitepress/theme/custom.css b/docs/src/.vitepress/theme/custom.css index bcc238a95..2d7a52802 100644 --- a/docs/src/.vitepress/theme/custom.css +++ b/docs/src/.vitepress/theme/custom.css @@ -1,3 +1,45 @@ +/* ===== Bold text on Linux ===== + VitePress' reset sets `font-synthesis: style` on , permitting a synthesised + oblique but not a synthesised weight. That is fine wherever the resolved font has + a real bold face — as `-apple-system` and `Segoe UI` do — but the + DocumenterVitepress font stack names three families it never loads ("Barlow", + "Inter var experimental", "Inter var"), and on Linux fontconfig satisfies those + *and* the platform names after them with a single regular face. `font-weight: 700` + then computes correctly and still renders at regular weight, which is why bold + docstring headings, admonition titles and inline read as plain text on + Linux while being fine on macOS and Windows (QuantumKitHub/MPSKit.jl#477). + + Allowing weight synthesis fixes that without touching the font stack, so nothing + changes on platforms that already resolve a real bold face. Proposed upstream; drop + this once DocumenterVitepress ships it. Note that the deeper problem is separate: + VitePress self-hosts Inter with a real 100–900 weight axis, but the stack above + names the family names it used before v4 renamed the face to plain "Inter" + (vuejs/vitepress#3694), so that font is downloaded and never used. Naming it would + give real bold faces instead of synthesised ones, but would also change body text + on every platform — a look-and-feel decision for upstream, not a bug fix. */ +body { + font-synthesis: weight style; +} + +/* ===== Docstring section headings ===== + Documenter rewrites markdown headings inside docstrings into bold-only + paragraphs (`recursive_heading_to_bold!`), so there is no to style. The + markdown-it rule in `.vitepress/config.mts` tags exactly those paragraphs; + give them a heading-like treatment — bold, plus a light rule beneath. */ +.jldocstring.custom-block p.jldocstring-heading { + margin: 1.5rem 0 0.6rem; + padding-bottom: 0.25rem; + font-size: 1em; + font-weight: 700; + line-height: 1.4; + color: var(--vp-c-text-1); + border-bottom: 1px solid var(--vp-c-divider); +} + +.jldocstring.custom-block p.jldocstring-heading strong { + font-weight: inherit; +} + /* ===== MPSKit branding ===== */ /* Accent color matching the (green) MPSKit logo in light mode. Dark mode already uses the green palette defined by the DVP template. */ @@ -9,6 +51,67 @@ --vp-c-brand-light: #389826; } +/* ===== Admonitions ===== + Documenter draws `!!! note` / `!!! warning` as a bordered box with a bold, + category-coloured, icon-marked header. DocumenterVitepress maps them onto + VitePress custom blocks, whose title is neither coloured nor icon-marked, and + whose border is transparent — so the blocks stop reading as callouts. Worse, + DVP maps every `note` onto the `tip` container and then restyles `tip` to a + flat grey box in dark mode, so the docs' notes lose their colour entirely. + + Restore a Documenter-like treatment: accent-coloured bold title with an icon, + a coloured left rule, and body text at full contrast. `:not(.jldocstring)` + keeps this off docstrings, which also carry the `custom-block` class. */ +.vp-doc .custom-block:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-default-1); + padding: 14px 16px; + border-left-width: 4px; + border-left-color: var(--mpskit-admonition-accent); + color: var(--vp-c-text-1); +} + +.custom-block:not(.jldocstring) .custom-block-title { + display: flex; + align-items: center; + gap: 0.5em; + margin-bottom: 8px; + font-weight: 700; + color: var(--mpskit-admonition-accent); +} + +.custom-block:not(.jldocstring) .custom-block-title::before { + content: ""; + flex: none; + width: 1.15em; + height: 1.15em; + background-color: currentColor; + /* fa-circle-exclamation, the icon Documenter puts on every admonition */ + --mpskit-admonition-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm-1 5h2v7h-2Zm0 9h2v2h-2Z'/%3E%3C/svg%3E"); + -webkit-mask: var(--mpskit-admonition-icon) center / contain no-repeat; + mask: var(--mpskit-admonition-icon) center / contain no-repeat; +} + +/* `note` and `tip` are indistinguishable by the time the markdown reaches us — + DVP maps both onto the `tip` container — so they share the tip palette. The + background is restated because the DVP template overrides it to a flat grey in + dark mode, which is what drained the colour out of every `!!! note`. */ +.vp-doc .custom-block.tip:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-tip-1); + background-color: var(--vp-c-tip-soft); +} +.vp-doc .custom-block.warning:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-warning-1); +} +.vp-doc .custom-block.danger:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-danger-1); +} +.vp-doc .custom-block.caution:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-caution-1); +} +.vp-doc .custom-block.important:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-important-1); +} + /* ===== Color-invertible diagrams ===== The manual embeds line-drawing diagrams (black on transparent) via `@raw html` . Legible on a light background diff --git a/docs/src/assets/favicon.ico b/docs/src/public/favicon.ico similarity index 100% rename from docs/src/assets/favicon.ico rename to docs/src/public/favicon.ico diff --git a/docs/src/assets/logo.svg b/docs/src/public/logo.svg similarity index 100% rename from docs/src/assets/logo.svg rename to docs/src/public/logo.svg From 97a953c38462b43bfa59f65be4a766521a85f23e Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 5 Oct 2026 13:57:08 -0400 Subject: [PATCH 2/3] docs: simplify VitePress customizations and load style overrides --- docs/Project.toml | 2 - docs/make.jl | 12 +-- docs/src/.vitepress/config.mts | 91 ++++------------- docs/src/.vitepress/theme/custom.css | 124 ------------------------ docs/src/.vitepress/theme/overrides.css | 80 +++++++++++++++ 5 files changed, 103 insertions(+), 206 deletions(-) delete mode 100644 docs/src/.vitepress/theme/custom.css create mode 100644 docs/src/.vitepress/theme/overrides.css diff --git a/docs/Project.toml b/docs/Project.toml index b6a10b9fa..d8f96b431 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -14,7 +14,6 @@ Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" -TensorKitTensors = "41b62e7d-e9d1-4e23-942c-79a97adf954b" TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" [sources] @@ -25,4 +24,3 @@ Documenter = "1.11" DocumenterCitations = "1.5" DocumenterInterLinks = "1" DocumenterVitepress = "0.3.7" -TensorKitTensors = "0.2" diff --git a/docs/make.jl b/docs/make.jl index 2ea281eb0..50b69e635 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -13,21 +13,17 @@ using DocumenterCitations using DocumenterInterLinks using SHA: sha256 -# `src/.vitepress/config.mts` is vendored from the DocumenterVitepress template (see the -# header comment there) so that we can hook `themeConfig.search` and `markdown.config`, -# which `MarkdownVitepress` does not expose. Warn when upstream changes the template, so -# that our copy can be re-synced — or dropped, once the fixes land upstream. +# Warn when the upstream template changes so the local search/markdown hooks can +# be re-synced. These hooks are not exposed by MarkdownVitepress. let template = joinpath(pkgdir(DocumenterVitepress), "template", "src", ".vitepress", "config.mts") - # Templates the vendored copy is known to be a faithful superset of; v0.3.4 and v0.3.5 - # differ only by the (inert for us) NOINDEX marker. vendored_from = ( "ca5a958eb398b3219557633f017467cfa07f4882dc2dfe55b12d1f6c0e70d729", # v0.3.4 - "56289223983a3844417eae597f81da878f395792a529721e7873178c92d60721", # v0.3.5 + "56289223983a3844417eae597f81da878f395792a529721e7873178c92d60721", # v0.3.5–v0.3.7 ) actual = bytes2hex(sha256(read(template))) actual in vendored_from || @warn """ DocumenterVitepress' `config.mts` template has changed since `docs/src/.vitepress/config.mts` \ - was vendored from it. Re-sync the vendored copy (keeping the `MPSKit:` additions), or delete \ + was vendored from it. Re-sync the vendored copy (keeping the docstring hooks), or delete \ it if upstream now ships them.""" template actual end diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts index 1c23640a1..a4b2e1906 100644 --- a/docs/src/.vitepress/config.mts +++ b/docs/src/.vitepress/config.mts @@ -1,21 +1,7 @@ -// ============================================================================ -// VENDORED FILE — keep in sync with DocumenterVitepress. -// -// This is a verbatim copy of the DocumenterVitepress **v0.3.5** template at -// `template/src/.vitepress/config.mts`, plus the MPSKit additions marked with -// `MPSKit:` below. DocumenterVitepress copies this file into the build as-is -// and then performs its `REPLACE_ME_DOCUMENTER_VITEPRESS*` substitutions on it -// (see `modify_config_file` in DocumenterVitepress/src/vitepress_config.jl), so -// the nav, sidebar, base, outDir, ... all keep working. -// -// We only vendor it because `themeConfig.search.options` and `markdown.config` -// are not reachable from `docs/make.jl`. Both additions below belong upstream -// in DocumenterVitepress — see `docs/UPSTREAM_DVP_NOTES.md`. Once upstream -// ships them, DELETE this file and the drift guard in `docs/make.jl`. -// -// `docs/make.jl` hashes the installed DocumenterVitepress template and warns if -// it has changed, which means this copy needs re-syncing. -// ============================================================================ +// Based on DocumenterVitepress's v0.3.5–v0.3.7 template. Keep the upstream +// placeholders: DocumenterVitepress substitutes them when building the site. +// MPSKit additions provide docstring search sections and heading styling (#477, #478). +// Remove those additions and the template hash guard once upstream provides them. import { defineConfig } from 'vitepress' import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' @@ -32,70 +18,31 @@ function getBaseRepository(base: string): string { return parts.length > 0 ? `/${parts[0]}/` : '/'; } -// MPSKit: --------------------------------------------------------------- -// DocumenterVitepress renders each docstring as a raw `
` block whose -// anchor lives in the ``: -// -// -// MPSKit.FiniteMPS -// -// VitePress' local search only splits a page into indexable sections at -// headings (`......`), so an `@autodocs` page is -// indexed as one single huge document: docstrings rank poorly against short -// manual sections and every hit links to the top of the page. Rewriting each -// summary into a heading *for indexing only* gives one search entry per -// docstring, titled with the binding and deep-linking to its anchor. -// See QuantumKitHub/MPSKit.jl#478. -// -// The replacement has to mirror the shape VitePress' own heading anchors have, -// because the indexer reads the section title from the text *before* the anchor -// (`headingContentRegex = /(.*?).*?<\/a>/i`) and drops any -// section whose title comes out empty. +// VitePress indexes headings, so give each docstring summary a heading in the +// search render only. The title must precede the anchor for its section indexer. const DOCSTRING_SUMMARY = /(.*?)<\/span><\/a>.*?<\/summary>/g -// MPSKit: --------------------------------------------------------------- -// Documenter rewrites every markdown heading inside a docstring into a -// bold-only paragraph before any writer sees it (`recursive_heading_to_bold!` -// in Documenter/src/expander_pipeline.jl), so `# Constructors` reaches -// VitePress as `

Constructors

` with nothing to style. -// Tag exactly those paragraphs so `theme/custom.css` can render them as -// section headings again. See QuantumKitHub/MPSKit.jl#477. -// -// Scoped to docstring `
` blocks, and requires the paragraph to consist -// of nothing but one ``, so that a paragraph merely *starting* with -// bold text (e.g. "**Not every algorithm ...** — see the table below") is left -// alone. +// Documenter turns docstring headings into bold-only paragraphs. Mark paragraphs +// wrapped in one strong span; overrides.css scopes their styling to docstrings. +// Keeping the scope in CSS avoids tracking raw HTML (including nested details). function docstringHeadings(md) { - md.core.ruler.push('mpskit_docstring_headings', (state) => { - const tokens = state.tokens - let depth = 0 + md.core.ruler.push('mpskit_docstring_headings', ({ tokens }) => { for (let i = 0; i < tokens.length; i++) { - const token = tokens[i] - - if (token.type === 'html_block') { - if (/]*\bclass=['"][^'"]*\bjldocstring\b/.test(token.content)) depth++ - else if (depth > 0 && /<\/details>/.test(token.content)) depth-- - continue - } - - if (depth === 0 || token.type !== 'paragraph_open') continue - const inline = tokens[i + 1] - if (!inline || inline.type !== 'inline' || !inline.children) continue - - // markdown-it emits empty `text` tokens around inline markup. - const children = inline.children.filter( + if (tokens[i].type !== 'paragraph_open') continue + const children = tokens[i + 1]?.children?.filter( (c) => !(c.type === 'text' && c.content === '') ) - if (children.length < 2) continue - if (children[0].type !== 'strong_open') continue - if (children[children.length - 1].type !== 'strong_close') continue - - token.attrJoin('class', 'jldocstring-heading') + if (children?.[0]?.type !== 'strong_open') continue + // The matching close must end the paragraph, excluding text or another + // strong span after it while allowing emphasis and links inside the span. + const end = children.findIndex( + (c) => c.type === 'strong_close' && c.level === children[0].level + ) + if (end === children.length - 1) tokens[i].attrJoin('class', 'jldocstring-heading') } }) } -// ----------------------------------------------------------------------- const baseTemp = { base: 'REPLACE_ME_DOCUMENTER_VITEPRESS',// TODO: replace this in makedocs! diff --git a/docs/src/.vitepress/theme/custom.css b/docs/src/.vitepress/theme/custom.css deleted file mode 100644 index 2d7a52802..000000000 --- a/docs/src/.vitepress/theme/custom.css +++ /dev/null @@ -1,124 +0,0 @@ -/* ===== Bold text on Linux ===== - VitePress' reset sets `font-synthesis: style` on , permitting a synthesised - oblique but not a synthesised weight. That is fine wherever the resolved font has - a real bold face — as `-apple-system` and `Segoe UI` do — but the - DocumenterVitepress font stack names three families it never loads ("Barlow", - "Inter var experimental", "Inter var"), and on Linux fontconfig satisfies those - *and* the platform names after them with a single regular face. `font-weight: 700` - then computes correctly and still renders at regular weight, which is why bold - docstring headings, admonition titles and inline read as plain text on - Linux while being fine on macOS and Windows (QuantumKitHub/MPSKit.jl#477). - - Allowing weight synthesis fixes that without touching the font stack, so nothing - changes on platforms that already resolve a real bold face. Proposed upstream; drop - this once DocumenterVitepress ships it. Note that the deeper problem is separate: - VitePress self-hosts Inter with a real 100–900 weight axis, but the stack above - names the family names it used before v4 renamed the face to plain "Inter" - (vuejs/vitepress#3694), so that font is downloaded and never used. Naming it would - give real bold faces instead of synthesised ones, but would also change body text - on every platform — a look-and-feel decision for upstream, not a bug fix. */ -body { - font-synthesis: weight style; -} - -/* ===== Docstring section headings ===== - Documenter rewrites markdown headings inside docstrings into bold-only - paragraphs (`recursive_heading_to_bold!`), so there is no to style. The - markdown-it rule in `.vitepress/config.mts` tags exactly those paragraphs; - give them a heading-like treatment — bold, plus a light rule beneath. */ -.jldocstring.custom-block p.jldocstring-heading { - margin: 1.5rem 0 0.6rem; - padding-bottom: 0.25rem; - font-size: 1em; - font-weight: 700; - line-height: 1.4; - color: var(--vp-c-text-1); - border-bottom: 1px solid var(--vp-c-divider); -} - -.jldocstring.custom-block p.jldocstring-heading strong { - font-weight: inherit; -} - -/* ===== MPSKit branding ===== */ -/* Accent color matching the (green) MPSKit logo in light mode. - Dark mode already uses the green palette defined by the DVP template. */ -:root { - --vp-c-brand: var(--julia-green); - --vp-c-brand-1: #389826; - --vp-c-brand-2: #2f8420; - --vp-c-brand-3: #277018; - --vp-c-brand-light: #389826; -} - -/* ===== Admonitions ===== - Documenter draws `!!! note` / `!!! warning` as a bordered box with a bold, - category-coloured, icon-marked header. DocumenterVitepress maps them onto - VitePress custom blocks, whose title is neither coloured nor icon-marked, and - whose border is transparent — so the blocks stop reading as callouts. Worse, - DVP maps every `note` onto the `tip` container and then restyles `tip` to a - flat grey box in dark mode, so the docs' notes lose their colour entirely. - - Restore a Documenter-like treatment: accent-coloured bold title with an icon, - a coloured left rule, and body text at full contrast. `:not(.jldocstring)` - keeps this off docstrings, which also carry the `custom-block` class. */ -.vp-doc .custom-block:not(.jldocstring) { - --mpskit-admonition-accent: var(--vp-c-default-1); - padding: 14px 16px; - border-left-width: 4px; - border-left-color: var(--mpskit-admonition-accent); - color: var(--vp-c-text-1); -} - -.custom-block:not(.jldocstring) .custom-block-title { - display: flex; - align-items: center; - gap: 0.5em; - margin-bottom: 8px; - font-weight: 700; - color: var(--mpskit-admonition-accent); -} - -.custom-block:not(.jldocstring) .custom-block-title::before { - content: ""; - flex: none; - width: 1.15em; - height: 1.15em; - background-color: currentColor; - /* fa-circle-exclamation, the icon Documenter puts on every admonition */ - --mpskit-admonition-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm-1 5h2v7h-2Zm0 9h2v2h-2Z'/%3E%3C/svg%3E"); - -webkit-mask: var(--mpskit-admonition-icon) center / contain no-repeat; - mask: var(--mpskit-admonition-icon) center / contain no-repeat; -} - -/* `note` and `tip` are indistinguishable by the time the markdown reaches us — - DVP maps both onto the `tip` container — so they share the tip palette. The - background is restated because the DVP template overrides it to a flat grey in - dark mode, which is what drained the colour out of every `!!! note`. */ -.vp-doc .custom-block.tip:not(.jldocstring) { - --mpskit-admonition-accent: var(--vp-c-tip-1); - background-color: var(--vp-c-tip-soft); -} -.vp-doc .custom-block.warning:not(.jldocstring) { - --mpskit-admonition-accent: var(--vp-c-warning-1); -} -.vp-doc .custom-block.danger:not(.jldocstring) { - --mpskit-admonition-accent: var(--vp-c-danger-1); -} -.vp-doc .custom-block.caution:not(.jldocstring) { - --mpskit-admonition-accent: var(--vp-c-caution-1); -} -.vp-doc .custom-block.important:not(.jldocstring) { - --mpskit-admonition-accent: var(--vp-c-important-1); -} - -/* ===== Color-invertible diagrams ===== - The manual embeds line-drawing diagrams (black on transparent) via - `@raw html` . Legible on a light background - as-is; invert them in dark mode so they read as light-on-dark. */ -.color-invertible { - transition: filter 0.2s ease; -} -.dark .color-invertible { - filter: invert(1) hue-rotate(180deg); -} diff --git a/docs/src/.vitepress/theme/overrides.css b/docs/src/.vitepress/theme/overrides.css new file mode 100644 index 000000000..cb3050a1e --- /dev/null +++ b/docs/src/.vitepress/theme/overrides.css @@ -0,0 +1,80 @@ +/* Allow bold synthesis for the upstream font stack on Linux (#477). */ +body { + font-synthesis: weight style; +} + +/* Documenter flattens headings to bold paragraphs; config.mts marks them. */ +.jldocstring.custom-block p.jldocstring-heading { + margin: 1.5rem 0 0.6rem; + padding-bottom: 0.25rem; + font-size: 1em; + font-weight: 700; + line-height: 1.4; + color: var(--vp-c-text-1); + border-bottom: 1px solid var(--vp-c-divider); +} + +/* Match the logo in light mode; keep the upstream dark palette. */ +:root:not(.dark) { + --vp-c-brand: var(--julia-green); + --vp-c-brand-1: #389826; + --vp-c-brand-2: #2f8420; + --vp-c-brand-3: #277018; + --vp-c-brand-light: #389826; +} + +/* Add category-colored titles, icons and left borders to admonitions. */ +.vp-doc .custom-block:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-default-1); + padding: 14px 16px; + border-left-width: 4px; + border-left-color: var(--mpskit-admonition-accent); + color: var(--vp-c-text-1); +} + +.custom-block:not(.jldocstring) .custom-block-title { + display: flex; + align-items: center; + gap: 0.5em; + margin-bottom: 8px; + font-weight: 700; + color: var(--mpskit-admonition-accent); +} + +.custom-block:not(.jldocstring) .custom-block-title::before { + content: ""; + flex: none; + width: 1.15em; + height: 1.15em; + background-color: currentColor; + /* fa-circle-exclamation, the icon Documenter puts on every admonition */ + --mpskit-admonition-icon: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a10 10 0 1 0 0 20 10 10 0 0 0 0-20Zm-1 5h2v7h-2Zm0 9h2v2h-2Z'/%3E%3C/svg%3E"); + -webkit-mask: var(--mpskit-admonition-icon) center / contain no-repeat; + mask: var(--mpskit-admonition-icon) center / contain no-repeat; +} + +/* DVP maps notes to tips and overrides their dark background to gray. */ +.vp-doc .custom-block.tip:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-tip-1); + background-color: var(--vp-c-tip-soft); +} +.vp-doc .custom-block.warning:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-warning-1); +} +.vp-doc .custom-block.danger:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-danger-1); +} +.vp-doc .custom-block.caution:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-caution-1); +} +.vp-doc .custom-block.important:not(.jldocstring) { + --mpskit-admonition-accent: var(--vp-c-important-1); +} + +/* Keep transparent line drawings legible in dark mode. */ +.color-invertible { + transition: filter 0.2s ease; +} +.dark .color-invertible { + filter: invert(1) hue-rotate(180deg); +} From bdadb256f011f38a8e4cef929da988d610ce7731 Mon Sep 17 00:00:00 2001 From: lkdvos Date: Mon, 5 Oct 2026 14:04:11 -0400 Subject: [PATCH 3/3] docs: extend upstream VitePress config through overrides --- docs/Project.toml | 1 - docs/make.jl | 18 +-- docs/overrides.jl | 12 ++ docs/src/.vitepress/config.mts | 149 ------------------------ docs/src/.vitepress/overrides.mts | 44 +++++++ docs/src/.vitepress/theme/index.ts | 44 ------- docs/src/.vitepress/theme/overrides.css | 2 +- 7 files changed, 59 insertions(+), 211 deletions(-) create mode 100644 docs/overrides.jl delete mode 100644 docs/src/.vitepress/config.mts create mode 100644 docs/src/.vitepress/overrides.mts delete mode 100644 docs/src/.vitepress/theme/index.ts diff --git a/docs/Project.toml b/docs/Project.toml index d8f96b431..87a66b634 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -11,7 +11,6 @@ MPSKit = "bb1c41ca-d63c-52ed-829e-0820dda26502" MPSKitModels = "ca635005-6f8c-4cd1-b51d-8491250ef2ab" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" Polynomials = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" -SHA = "ea8e919c-243c-51af-8825-aaa63cd721ce" Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" TensorKit = "07d1fe3e-3e46-537d-9eac-e9e13d0d4cec" TensorOperations = "6aa20fa7-93e2-5fca-9bc0-fbd0db3c71a2" diff --git a/docs/make.jl b/docs/make.jl index 50b69e635..710318cab 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -11,21 +11,7 @@ using Documenter using DocumenterVitepress using DocumenterCitations using DocumenterInterLinks -using SHA: sha256 - -# Warn when the upstream template changes so the local search/markdown hooks can -# be re-synced. These hooks are not exposed by MarkdownVitepress. -let template = joinpath(pkgdir(DocumenterVitepress), "template", "src", ".vitepress", "config.mts") - vendored_from = ( - "ca5a958eb398b3219557633f017467cfa07f4882dc2dfe55b12d1f6c0e70d729", # v0.3.4 - "56289223983a3844417eae597f81da878f395792a529721e7873178c92d60721", # v0.3.5–v0.3.7 - ) - actual = bytes2hex(sha256(read(template))) - actual in vendored_from || @warn """ - DocumenterVitepress' `config.mts` template has changed since `docs/src/.vitepress/config.mts` \ - was vendored from it. Re-sync the vendored copy (keeping the docstring hooks), or delete \ - it if upstream now ships them.""" template actual -end +include("overrides.jl") # examples example_dir = joinpath(@__DIR__, "src", "examples") @@ -95,7 +81,7 @@ makedocs(; ], checkdocs = :exports, doctest = true, - plugins = [bib, links] + plugins = [bib, links, VitepressOverrides()] ) DocumenterVitepress.deploydocs(; diff --git a/docs/overrides.jl b/docs/overrides.jl new file mode 100644 index 000000000..36e0afcce --- /dev/null +++ b/docs/overrides.jl @@ -0,0 +1,12 @@ +# Apply local overrides after DocumenterVitepress generates its upstream config. +struct VitepressOverrides <: Documenter.Plugin end + +function DocumenterVitepress.vitepress_config_transform(::VitepressOverrides, config::String) + marker = r"(?m)^export\s+default\s+" + occursin(marker, config) || error("DocumenterVitepress config has no default export to extend") + return replace(config, marker => "const upstreamConfig = "; count = 1) * """ + + import { withOverrides } from './overrides.mts' + export default withOverrides(upstreamConfig) + """ +end diff --git a/docs/src/.vitepress/config.mts b/docs/src/.vitepress/config.mts deleted file mode 100644 index a4b2e1906..000000000 --- a/docs/src/.vitepress/config.mts +++ /dev/null @@ -1,149 +0,0 @@ -// Based on DocumenterVitepress's v0.3.5–v0.3.7 template. Keep the upstream -// placeholders: DocumenterVitepress substitutes them when building the site. -// MPSKit additions provide docstring search sections and heading styling (#477, #478). -// Remove those additions and the template hash guard once upstream provides them. - -import { defineConfig } from 'vitepress' -import { tabsMarkdownPlugin } from 'vitepress-plugin-tabs' -import { mathjaxPlugin } from './mathjax-plugin' -import { juliaReplTransformer } from './julia-repl-transformer' -import footnote from "markdown-it-footnote"; -import path from 'path' - -const mathjax = mathjaxPlugin() - -function getBaseRepository(base: string): string { - if (!base || base === '/') return '/'; - const parts = base.split('/').filter(Boolean); - return parts.length > 0 ? `/${parts[0]}/` : '/'; -} - -// VitePress indexes headings, so give each docstring summary a heading in the -// search render only. The title must precede the anchor for its section indexer. -const DOCSTRING_SUMMARY = - /(.*?)<\/span><\/a>.*?<\/summary>/g - -// Documenter turns docstring headings into bold-only paragraphs. Mark paragraphs -// wrapped in one strong span; overrides.css scopes their styling to docstrings. -// Keeping the scope in CSS avoids tracking raw HTML (including nested details). -function docstringHeadings(md) { - md.core.ruler.push('mpskit_docstring_headings', ({ tokens }) => { - for (let i = 0; i < tokens.length; i++) { - if (tokens[i].type !== 'paragraph_open') continue - const children = tokens[i + 1]?.children?.filter( - (c) => !(c.type === 'text' && c.content === '') - ) - if (children?.[0]?.type !== 'strong_open') continue - // The matching close must end the paragraph, excluding text or another - // strong span after it while allowing emphasis and links inside the span. - const end = children.findIndex( - (c) => c.type === 'strong_close' && c.level === children[0].level - ) - if (end === children.length - 1) tokens[i].attrJoin('class', 'jldocstring-heading') - } - }) -} - -const baseTemp = { - base: 'REPLACE_ME_DOCUMENTER_VITEPRESS',// TODO: replace this in makedocs! -} - -const navTemp = { - nav: 'REPLACE_ME_DOCUMENTER_VITEPRESS', -} - -const nav = [ - ...navTemp.nav, - { - component: 'VersionPicker' - } -] - -// https://vitepress.dev/reference/site-config -export default defineConfig({ - base: 'REPLACE_ME_DOCUMENTER_VITEPRESS',// TODO: replace this in makedocs! - title: 'REPLACE_ME_DOCUMENTER_VITEPRESS', - description: 'REPLACE_ME_DOCUMENTER_VITEPRESS', - lastUpdated: true, - cleanUrls: true, - outDir: 'REPLACE_ME_DOCUMENTER_VITEPRESS', // This is required for MarkdownVitepress to work correctly... - head: [ - ['link', { rel: 'icon', href: 'REPLACE_ME_DOCUMENTER_VITEPRESS_FAVICON' }], - ['script', {src: `${getBaseRepository(baseTemp.base)}versions.js`}], - // ['script', {src: '/versions.js'], for custom domains, I guess if deploy_url is available. - ['script', {src: `${baseTemp.base}siteinfo.js`}], - // REPLACE_ME_DOCUMENTER_VITEPRESS_NOINDEX - ], - - markdown: { - codeTransformers: [juliaReplTransformer()], - config(md) { - md.use(tabsMarkdownPlugin); - md.use(footnote); - mathjax.markdownConfig(md); - md.use(docstringHeadings); // MPSKit: see above - }, - theme: { - light: "github-light", - dark: "github-dark" - }, - }, - vite: { - plugins: [ - mathjax.vitePlugin, - ], - define: { - __DEPLOY_ABSPATH__: JSON.stringify('REPLACE_ME_DOCUMENTER_VITEPRESS_DEPLOY_ABSPATH'), - }, - resolve: { - alias: { - '@': path.resolve(__dirname, '../components') - } - }, - optimizeDeps: { - exclude: [ - '@nolebase/vitepress-plugin-enhanced-readabilities/client', - 'vitepress', - '@nolebase/ui', - ], - }, - ssr: { - noExternal: [ - // If there are other packages that need to be processed by Vite, you can add them here. - '@nolebase/vitepress-plugin-enhanced-readabilities', - '@nolebase/ui', - ], - }, - }, - themeConfig: { - outline: 'deep', - logo: 'REPLACE_ME_DOCUMENTER_VITEPRESS', - search: { - provider: 'local', - options: { - detailedView: true, - // MPSKit: index every docstring as its own section — see above. - _render(src, env, md) { - const html = md.render(src, env) - if (env.frontmatter?.search === false) return '' - return html.replace( - DOCSTRING_SUMMARY, - (_match, id, href, name) => - `

${name} ​

` - ) - } - } - }, - nav, - sidebar: 'REPLACE_ME_DOCUMENTER_VITEPRESS', - sidebarDrawer: 'REPLACE_ME_DOCUMENTER_VITEPRESS_SIDEBAR_DRAWER', - editLink: 'REPLACE_ME_DOCUMENTER_VITEPRESS', - socialLinks: [ - { icon: 'github', link: 'REPLACE_ME_DOCUMENTER_VITEPRESS' } - ], - footer: { - message: 'Made with DocumenterVitepress.jl
', - copyright: `© Copyright ${new Date().getUTCFullYear()}.` - } - } -}) diff --git a/docs/src/.vitepress/overrides.mts b/docs/src/.vitepress/overrides.mts new file mode 100644 index 000000000..03970e439 --- /dev/null +++ b/docs/src/.vitepress/overrides.mts @@ -0,0 +1,44 @@ +// VitePress indexes headings, so give each docstring summary a heading in the +// search render only. The title must precede the anchor for its section indexer. +const DOCSTRING_SUMMARY = + /(.*?)<\/span><\/a>.*?<\/summary>/g + +// Documenter turns docstring headings into bold-only paragraphs. Mark paragraphs +// wrapped in one strong span; overrides.css scopes their styling to docstrings. +// Keeping the scope in CSS avoids tracking raw HTML (including nested details). +function docstringHeadings(md) { + md.core.ruler.push('mpskit_docstring_headings', ({ tokens }) => { + for (let i = 0; i < tokens.length; i++) { + if (tokens[i].type !== 'paragraph_open') continue + const children = tokens[i + 1]?.children?.filter( + (c) => !(c.type === 'text' && c.content === '') + ) + if (children?.[0]?.type !== 'strong_open') continue + // The matching close must end the paragraph, excluding text or another + // strong span after it while allowing emphasis and links inside the span. + const end = children.findIndex( + (c) => c.type === 'strong_close' && c.level === children[0].level + ) + if (end === children.length - 1) tokens[i].attrJoin('class', 'jldocstring-heading') + } + }) +} + +// Extend the generated config while retaining all upstream plugins and options. +export function withOverrides(config) { + const configureMarkdown = config.markdown.config + config.markdown.config = (md) => { + configureMarkdown(md) + md.use(docstringHeadings) + } + config.themeConfig.search.options._render = (src, env, md) => { + const html = md.render(src, env) + if (env.frontmatter?.search === false) return '' + return html.replace( + DOCSTRING_SUMMARY, + (_match, id, href, name) => + `

${name} ​

` + ) + } + return config +} diff --git a/docs/src/.vitepress/theme/index.ts b/docs/src/.vitepress/theme/index.ts deleted file mode 100644 index ada1bbeae..000000000 --- a/docs/src/.vitepress/theme/index.ts +++ /dev/null @@ -1,44 +0,0 @@ -// .vitepress/theme/index.ts -import { h } from 'vue' -import DefaultTheme from 'vitepress/theme' -import type { Theme as ThemeConfig } from 'vitepress' -import 'virtual:mathjax-styles.css'; - -import { - NolebaseEnhancedReadabilitiesMenu, - NolebaseEnhancedReadabilitiesScreenMenu, -} from '@nolebase/vitepress-plugin-enhanced-readabilities/client' - -import VersionPicker from "@/VersionPicker.vue" -import AuthorBadge from '@/AuthorBadge.vue' -import Authors from '@/Authors.vue' -import SidebarDrawerToggle from '@/SidebarDrawerToggle.vue' - -import { enhanceAppWithTabs } from 'vitepress-plugin-tabs/client' - -import '@nolebase/vitepress-plugin-enhanced-readabilities/client/style.css' -import './style.css' // template default, auto-supplied to the build by DVP -import './docstrings.css' // template default, auto-supplied to the build by DVP -import './custom.css' // MPSKit customizations (this repo) - -export const Theme: ThemeConfig = { - extends: DefaultTheme, - Layout() { - return h(DefaultTheme.Layout, null, { - 'nav-bar-content-after': () => [ - h(NolebaseEnhancedReadabilitiesMenu), // Enhanced Readabilities menu - ], - // A enhanced readabilities menu for narrower screens (usually smaller than iPad Mini) - 'nav-screen-content-after': () => h(NolebaseEnhancedReadabilitiesScreenMenu), - // Sidebar drawer toggle button (to the left of search bar) - 'nav-bar-content-before': () => h(SidebarDrawerToggle), - }) - }, - enhanceApp({ app, router, siteData }) { - enhanceAppWithTabs(app); - app.component('VersionPicker', VersionPicker); - app.component('AuthorBadge', AuthorBadge) - app.component('Authors', Authors) - } -} -export default Theme diff --git a/docs/src/.vitepress/theme/overrides.css b/docs/src/.vitepress/theme/overrides.css index cb3050a1e..8bde80adc 100644 --- a/docs/src/.vitepress/theme/overrides.css +++ b/docs/src/.vitepress/theme/overrides.css @@ -3,7 +3,7 @@ body { font-synthesis: weight style; } -/* Documenter flattens headings to bold paragraphs; config.mts marks them. */ +/* Documenter flattens headings to bold paragraphs; overrides.mts marks them. */ .jldocstring.custom-block p.jldocstring-heading { margin: 1.5rem 0 0.6rem; padding-bottom: 0.25rem;