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.