Skip to content

v4.0.0

Choose a tag to compare

@github-actions github-actions released this 22 Jun 18:04

Summary

This release is a complete rewrite of Asciidoctor.js — the Opal runtime and transpiled Ruby code have been replaced by a native JavaScript implementation.
The public API has been preserved as closely as possible from version 3, but there are breaking changes.
Please refer to the migration guide before upgrading.

Release meta

Released on: 2026-06-22
Released by: github-actions[bot]
Published by: GitHub

Logs: full diff

Changelog

Bug Fixes

  • Fix registry reuse — extensions registered directly on a registry instance (e.g. registry.preprocessor(fn)) now survive the internal reset and are preserved across multiple conversions, matching the behaviour of group-block registrations (Extensions.create(name, block)); both patterns are now safe to reuse

Improvements

  • Document registry reuse behaviour — extensions registered via a group block (Extensions.create(name, block)) survive the internal reset and are safe to reuse across multiple conversions; extensions registered directly on a registry instance are cleared on every activation and will be silently lost after the first conversion
  • Add --extension CLI option to load and register Asciidoctor extension files — the option calls the register(registry) named export of the loaded module with a shared registry; can be repeated to load multiple extensions
  • Clarify --require CLI option — it now only loads the module as a side effect and no longer auto-calls any exported function; use --extension to register Asciidoctor extensions, and --require for libraries that configure themselves on load (syntax highlighters, polyfills, etc.)
  • Improve JSDoc for IncludeProcessorDsl#handles — add @overload signatures documenting the two setter forms (arity-1 (target) and arity-2 (doc, target)) and the invoker form; update IncludeProcessorDslInterface typedef to expose both setter overloads

Breaking Changes

  • --require no longer inspects or calls a register export from the loaded module — this auto-call was already broken (it passed the Extensions namespace instead of a registry instance); any extension that relied on this behaviour must be updated to either export a register(registry) function and be loaded via --extension, or self-register using Extensions.register() at the top level to remain loadable via --require