Plugins
Docsy loads some of its optional JavaScript features, and any script you add, as
plugins: entries under params.docsy.plugins in your site configuration.
Configure Docsy’s plugins
| Plugin | What it does | Default | Loads on | Docs |
|---|---|---|---|---|
click-to-copy | Adds a copy button to code blocks | On (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 |
To turn a plugin off, set its entry to false:
[params.docsy.plugins]
click-to-copy = falseparams:
docsy:
plugins:
click-to-copy: false{
"params": {
"docsy": {
"plugins": { "click-to-copy": 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). Each entry’s fields, types, and defaults:
# Schema of `params.docsy`, the namespace Docsy reserves for theme settings.
type: map
keys:
plugins:
type: map # keyed by plugin name; a scalar false turns an entry off
key:
pattern: ^[a-z0-9_-]+$
reservedSuffix: _docsy-shim
entry:
enable: { type: bool, default: true }
defer: { type: bool, default: false } # adds `defer` to the script tag
pageGate: { type: string, default: '' } # a .Page.Store flag; '' = none
weight: { type: int, default: 0 } # emission order, ascending, then name
options: { type: map, default: {} } # reaches the module as @params
{}in place of an entry keeps every default.enableis off forfalse,"false", and0, and on for any other value;deferis on fortrue,"true", and1, and off for any other value. The string forms exist for environment overrides.
Warnings
Every registry shape warning carries the id docsy-config (to silence one, see
Configuration § Configuration warnings):
- An unknown field or a non-map
optionsis ignored and the rest of the entry applies. - A name the schema’s pattern rejects or that ends in its reserved suffix, or a scalar entry other than a false spelling, 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 enabled name with no script file (Plugin files) is a
different fault: it warns
docsy-plugin-missing, gated or not (a disabled entry is never looked up).
Add a custom script
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 = {}params:
docsy:
plugins:
NAME: {}{
"params": {
"docsy": {
"plugins": { "NAME": {} }
}
}
}Plugin files
A plugin is one to three files. A project file shadows the theme’s of the same name, which is how you replace one of Docsy’s plugins or its companions.
| File | Contract |
|---|---|
assets/js/plugins/NAME.js | Required. Built on its own with js.Build; options reach it as @params. |
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. |
Companions emit before the script (why). Script and
stylesheet tags carry subresource integrity in every environment. Entry
keys reach templates and plugin scripts lowercase: .Plugin.pagegate,
params.apikey (Configuration § Key spelling).
Security
- Never pipe
.Plugin.optionsthroughsafeHTML,safeJS, orsafeURLin a companion partial: options are site-configured strings, and Hugo’s contextual autoescaping is the defense. - In a plugin script, options are values, not markup: set them through DOM and
CSSOM properties, never by building HTML or stylesheet text around them (an
option interpolated into a
<style>can close the rule and open its own). - Options, like anything reaching a module as
@params, ship world-readable in the built JavaScript: never route secrets through them. - Pin third-party dependencies, never
latest; vendor build-time fetches and serve them with SRI; and use no loader that pulls unpinned secondary code, which SRI on the loader can’t cover. - A plugin that loads remote code gets a
pageGate(a flag your own render hook sets with.Page.Store.Set), so its code ships only where used.
Page flags in included content
Some plugins load only on pages that need them: a pageGate names a page flag,
and Docsy’s markmap render hook sets one whenever a page has a markmap code
block. A flag counts only when it lands on the page that ships.
- 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 how to clear its gate, see
Activating MarkMap support.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.