Implementation
Code-level structure, Hugo/Docsy templates, SCSS/JS customizations, patches, and internal shims
Subsystems
- Script loading: the plugin loop’s
shim contract, shape guards, build pipeline, and the security rules Docsy’s
own plugins follow
Patches and workarounds
1 - Script loading
The plugin loop’s shim contract, shape guards, build pipeline, and the security rules Docsy’s own plugins follow
_partials/scripts/plugins.html implements
params.docsy.plugins. For the configuration reference and the plugin file
contract, see the plugins guide; for the design rationale, the design
notes; for the tests that pin this contract, the quality
notes.
Loop mechanics
The template’s comments carry the mechanics and their rationale. The loop reads
the theme’s schema through hugo.Data; the guide renders the same
file, so the entry contract has one home.
Shims
For when to add or replace a shim, see the guide’s Adjust a plugin per
page; this section is the contract.
The loop resolves a shim by registry name with the schema’s reserved
_docsy-shim suffix and, when the partial exists, invokes it with
(dict "Page" PAGE "Plugin" ENTRY): the page being rendered, and the merged,
normalized entry. The call comes after normalization and name validation, so a
shim cannot reorder emission. It comes before the required-field and version
guards, the enable check, and asset lookup, so a shim runs for a disabled entry
too, and what it returns is what those two guards test.
The partial must return the entry it received, adjusted with merge so the
fields it leaves alone keep their normalized values; anything but a map fails
the build.
A shim is also where a plugin gates itself: on a page that doesn’t need the
plugin, it returns the entry with enable false (Gating
decisions). When support for a deprecated parameter ends, remove
its mapping and warning from the shim and keep the rest.
Shape guards
Enforcement is hand-coded in the loop against the schema; what each guard warns
about, ignores, or empties is the guide’s Warnings list. A
refused version skips the entry.
Build and emission
The file contract is the guide’s; the pipeline adds one step
beyond it, minification in production (why companions first).
Security constraints
Docsy’s own plugins follow the guide’s rules for plugin
authors. In addition:
- Validate a configuration value against an allowlist before it reaches a fetch
URL: the loop does this for every supplied entry
version, so a companion
only checks that its plugin provides a pin. - Residual exposure, disclosed in the guide’s MarkMap version
section: the autoloader’s runtime libraries.
- Imported Hugo modules are trusted: their
params merge into the site’s, so a
module can register or turn off plugins, and its layouts can shim them, as it
already supplies layouts and assets.
2 - ScrollSpy patch
Runtime patch for Bootstrap ScrollSpy to handle invalid CSS selector IDs.
As of Docsy 0.13.0
Summary
Docsy 0.13.0 includes a runtime patch for Bootstrap ScrollSpy that
fixes a bug affecting pages with heading IDs that aren’t valid CSS selectors.
The patch ensures that active TOC entry
tracking works reliably for all
pages.
Problem
As of Bootstrap 5.3.8 (the version used by Docsy 0.13.0), ScrollSpy fails if
a page contains a heading ID that is not also a valid CSS # selector. This can
happen, for example, if a heading ID starts with a digit. For technical details
about this bug, see #2329.
Solution
Docsy 0.13.0 implements a runtime patch for ScrollSpy that intercepts
ScrollSpy’s initialization to properly handle heading IDs starting with digits
or containing other characters that form invalid CSS selectors. This allows
active TOC entry tracking to work correctly without altering the original
heading IDs, so links to headings continue to work as expected.
The patch is automatically applied when ScrollSpy is enabled (which is the
default). For implementation details, see #2382, #2383.
Maintenance
CI/CD automatically keeps the patch up-to-date when Bootstrap is updated. The
_test:full:pre script extracts the method from Bootstrap, applies the patch,
and updates the runtime patch file. If the Bootstrap method code has changed to
a degree that the patch no longer works, CI will fail, indicating that the patch
file needs manual review and updates.
Until the upstream ScrollSpy fix is released in a future Bootstrap version,
this patch ensures that active TOC entry tracking works reliably for all pages.
References