Plugins
Docsy loads some of its optional JavaScript features as plugins: entries
under params.docsy.plugins in your site configuration.
Configure Docsy’s plugins
| Plugin | What it does (Default / Loads on) | Learn more |
|---|---|---|
click-to-copy | Adds a copy button to code blocks (On, but off under Prism, which has its own / Every page) | Copy to clipboard |
tabpane-persist | Remembers the selected tab across pages (On / Every page (why)) | tabpane |
markmap | Renders markmap code blocks as mind maps (Off / Pages with a markmap code block) | Activating MarkMap support |
mermaid | Renders mermaid code blocks as diagrams (On / Pages with a mermaid code block) | Diagrams with Mermaid |
To turn a plugin off, set its enable field to false:
[params.docsy.plugins.click-to-copy]
enable = falseparams:
docsy:
plugins:
click-to-copy:
enable: false{
"params": {
"docsy": {
"plugins": { "click-to-copy": { "enable": false } }
}
}
}Configuration reference
Docsy’s own plugins are declared in the theme’s hugo.yaml;
your entries merge over them by name and field (Configuration § Theme
defaults). The schema defines each entry’s keys, required fields,
types, defaults, and syntactic patterns:
type: map
entries:
'plugins':
type: map # nonempty
key: # plugin name
type: string # coerced, lowercased
pattern: ^[a-z0-9_-]+$
reservedSuffix: _docsy-shim
value:
type: map
entries:
'enable': { type: bool, required: true } # coerced
'version':
type: string # coerced
pattern: ^[0-9A-Za-z.+-]+$
'options': { type: string } # plugin-defined format; see the plugin's guide
'_defer': { type: bool, default: false } # coerced; plugin-author field: adds `defer` to the script tag
- Fields are optional unless marked
required: true. {}for a theme plugin keeps every inherited field, includingenable.- Language-specific
paramsapply, so an entry can differ per language. enableis off forfalse,"false", and0, and on for any other value. The string forms exist for environment overrides.versionselects the version of a plugin’s dependency, not of the plugin script or of Docsy. To override a theme plugin’s pin, see Mermaid version or MarkMap version.optionsholds a plugin’s own settings, as a string whose format and validation are the plugin’s; Docsy passes the value to the plugin unchanged. For the shape a theme plugin takes, see its guide (Mermaid settings)._deferis the plugin author’s field (the_prefix marks such fields), declared with the plugin (Loading strategy (experimental)); leave it alone on a plugin you didn’t write.
Warnings
Every registry shape warning carries the id docsy-config (to silence one, see
Configuration § Configuration warnings):
- An unknown field is ignored and the rest of the entry applies.
- An unknown key directly under
params.docsyis ignored and the rest of the map applies. - A name the schema’s pattern rejects or that ends in its reserved suffix, a scalar entry, or an entry missing a required field drops the whole entry.
- A
params.docsyorparams.docsy.pluginsthat is not a map empties the registry, Docsy’s own plugins and their deprecated aliases included.plugins: {}keeps them; a valuelessplugins:is null and drops them. - An empty registry after configuration merging warns; a registry with all entries disabled is valid.
- An enabled name with no script file
(Plugin files (experimental)) is a different fault: it warns
docsy-plugin-missing(a disabled entry is never looked up).
version validation applies to entries not already dropped by the shape guards,
including disabled entries. An exact X.Y.Z passes without a version warning;
another value matching the schema’s pattern, such as latest, warns under
NAME-floating-version, where NAME is the entry’s name. A value outside
the pattern, such as a range or operator (^11, >=11, *) or an empty or
malformed string, fails the build and skips the entry before its companion runs.
For why Docsy pins versions, see Pinned script-dependency versions.
Add a custom script
EXPERIMENTAL
This section is experimental; configuring Docsy’s plugins is supported.
For a script that should load at the end of every page, register it as a plugin;
for markup in <head>, inline snippets, or third-party tags, use the head and
body hooks instead.
- Save the script as
assets/js/plugins/NAME.js, withNAMEin lowercase. - Register it under
params.docsy.plugins(configuration reference):
[params.docsy.plugins.NAME]
enable = trueparams:
docsy:
plugins:
NAME:
enable: true{
"params": {
"docsy": {
"plugins": { "NAME": { "enable": true } }
}
}
}Plugin files
A project file shadows the theme’s of the same name, which is how you replace one of Docsy’s plugins, its companions, or its shim.
| File | Contract |
|---|---|
assets/js/plugins/NAME.js | Required. Built on its own with js.Build. |
layouts/_partials/scripts/plugins/NAME.html | Optional companion partial for vendored libraries, markup, or configuration; receives (dict "Page" PAGE "Plugin" ENTRY). |
assets/scss/plugins/NAME.scss | Optional companion stylesheet, through the Sass pipeline. |
layouts/_partials/scripts/plugins/NAME_docsy-shim.html | Optional shim partial; adjust a plugin per page. |
Companions emit before the script (why). Script and stylesheet tags carry subresource integrity in every environment. Entry keys reach templates lowercase (Configuration § Key spelling).
Loading strategy
A plugin’s script runs synchronously by default. For a script that scans the
document once when it runs, set _defer: true. The script then runs after
parsing and sees markup emitted after its tag, including the body-end
hook, as click-to-copy does. Declare _defer where you
register the plugin, or set it in its shim.
Adjust a plugin per page
A shim adjusts a plugin’s registry entry for each page before the plugin
loads. Add one for your own plugin, or for one of Docsy’s. Three of Docsy’s
plugins ship a shim, mermaid, markmap, and click-to-copy: your file
replaces that plugin’s shim and everything it does (shim contract),
so start from a copy of the theme’s file, in scripts/plugins/.
Create layouts/_partials/scripts/plugins/NAME_docsy-shim.html, with the
plugin’s registry name as NAME (shim contract):
{{ $entry := .Plugin -}}
{{ if not (.Page.Store.Get "hasMyFeature") -}}
{{ $entry = merge $entry (dict "enable" false) -}}
{{ end -}}
{{ return $entry -}}
That shim loads the plugin only on pages that use it: a render hook of yours
sets the flag with .Page.Store.Set where the feature’s markup appears. Before
relying on a flag, read
Page flags in included content.
Dependency versions
For a custom plugin with a configurable dependency, set version on its
registry entry (configuration reference) and read
.Plugin.version in the companion partial. Use that value to select the
dependency’s code, for example in a build-time fetch URL. Declaring version
does not fetch code automatically. Omit the field if the plugin has no
dependency version to configure.
The entry’s version is not passed to the plugin script. For a working example,
see the markmap companion in scripts/plugins/.
Plugin settings
A plugin reads its settings from its entry’s options
(configuration reference); the shim receives the
value as the site wrote it and may decode it before the companion runs. Choose
the string’s format and document it with the plugin. It is a string because Hugo
lowercases map keys (why); Docsy’s plugins take a JSON
object, decoded at build time with transform.Unmarshal, or in the browser
with JSON.parse after the companion emits it. For the pattern, see the
mermaid shim and companion in scripts/plugins/ (shim
contract).
Security
- Pin third-party dependencies on the entry’s
version, neverlatest. - Vendor build-time fetches and serve them with SRI.
- Use no loader that pulls unpinned secondary code, which SRI on the loader can’t cover.
- Load remote code only on pages that use it: gate the plugin with a shim.
Page flags in included content
Some plugins load only on pages that need them: Docsy’s markmap render hook
sets a page flag whenever a page has a markmap code block, and the plugin
ships where the flag is set. A flag counts only when it lands on the page whose
output the plugin is emitted into.
- A render hook runs in the context of the page being rendered, so a
markmapblock in content pulled in through.RenderShortcodesflags the page that includes it. - A shortcode runs in the context of the page whose file contains it, so a shortcode in included content would flag the included page, and the including page would never see the flag.
- Content pulled in through
.Contentflags the included page in both cases.
That is why Docsy ships tabpane-persist ungated, on every page: tabpanes come
from a shortcode. For MarkMap’s authoring paths and the remedy, see When a
MarkMap doesn’t render.
Feedback
Cette page est-elle utile?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.