Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ using Documenter
using DocumenterVitepress
using DocumenterCitations
using DocumenterInterLinks
include("overrides.jl")

# examples
example_dir = joinpath(@__DIR__, "src", "examples")
Expand Down Expand Up @@ -80,7 +81,7 @@ makedocs(;
],
checkdocs = :exports,
doctest = true,
plugins = [bib, links]
plugins = [bib, links, VitepressOverrides()]
)

DocumenterVitepress.deploydocs(;
Expand Down
12 changes: 12 additions & 0 deletions docs/overrides.jl
Original file line number Diff line number Diff line change
@@ -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
44 changes: 44 additions & 0 deletions docs/src/.vitepress/overrides.mts
Original file line number Diff line number Diff line change
@@ -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 =
/<summary><a id='([^']+)' href='([^']+)'><span class="jlbinding">(.*?)<\/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) =>
`<h3 id="${id}">${name} <a class="header-anchor" href="${href}">&#8203;</a></h3>`
)
}
return config
}
21 changes: 0 additions & 21 deletions docs/src/.vitepress/theme/custom.css

This file was deleted.

44 changes: 0 additions & 44 deletions docs/src/.vitepress/theme/index.ts

This file was deleted.

80 changes: 80 additions & 0 deletions docs/src/.vitepress/theme/overrides.css
Original file line number Diff line number Diff line change
@@ -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; overrides.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);
}
File renamed without changes.
File renamed without changes
Loading