asciidoctor 4.0.0-alpha.6 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/cli.js CHANGED
@@ -126,6 +126,13 @@ const BASE_OPTION_DEFINITIONS = {
126
126
  'require the specified library before executing the processor (repeatable)',
127
127
  metavar: '<library>',
128
128
  },
129
+ extension: {
130
+ type: 'string',
131
+ multiple: true,
132
+ describe:
133
+ 'require the specified extension and register it before executing the processor (repeatable)',
134
+ metavar: '<extension>',
135
+ },
129
136
  version: {
130
137
  type: 'boolean',
131
138
  short: 'V',
@@ -351,6 +358,7 @@ export class Invoker {
351
358
  }
352
359
 
353
360
  this._prepareProcessor(values)
361
+ this._prepareExtensions(values)
354
362
  const { options, failureLevel } = this.options
355
363
 
356
364
  const logger = LoggerManager.getLogger()
@@ -443,9 +451,25 @@ CLI version ${pkg.version}`
443
451
  const requirePaths = values.require
444
452
  if (!requirePaths) return
445
453
  for (const requirePath of requirePaths) {
446
- const lib = requireLibrary(requirePath)
447
- if (lib && typeof lib.register === 'function') {
448
- lib.register(Extensions)
454
+ requireLibrary(requirePath)
455
+ }
456
+ }
457
+
458
+ /** @internal */
459
+ _prepareExtensions(values) {
460
+ const extensionPaths = values.extension
461
+ if (!extensionPaths || extensionPaths.length === 0) return
462
+ const logger = LoggerManager.getLogger()
463
+ for (const extensionPath of extensionPaths) {
464
+ const lib = requireLibrary(extensionPath)
465
+ if (typeof lib?.register === 'function') {
466
+ Extensions.register(function () {
467
+ lib.register(this)
468
+ })
469
+ } else {
470
+ logger.warn(
471
+ `Extension '${extensionPath}' does not export a register function and will be ignored.`
472
+ )
449
473
  }
450
474
  }
451
475
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "asciidoctor",
3
- "version": "4.0.0-alpha.6",
3
+ "version": "4.0.0",
4
4
  "description": "A JavaScript AsciiDoc processor powered by Asciidoctor",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -60,7 +60,7 @@
60
60
  },
61
61
  "homepage": "https://github.com/asciidoctor/asciidoctor.js",
62
62
  "dependencies": {
63
- "@asciidoctor/core": "4.0.0-alpha.6"
63
+ "@asciidoctor/core": "4.0.0"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@biomejs/biome": "^2.4.13",
@@ -38,7 +38,25 @@ export namespace SyntaxProcessorDsl {
38
38
  function resolvesAttributes(...args: any[]): void;
39
39
  }
40
40
  export namespace IncludeProcessorDsl {
41
- function handles(...args: any[]): any;
41
+ /**
42
+ * @overload
43
+ * @param {(target: string) => boolean} fn - Predicate that receives only the include target.
44
+ * @returns {void}
45
+ */
46
+ function handles(fn: (target: string) => boolean): void;
47
+ /**
48
+ * @overload
49
+ * @param {(doc: Document, target: string) => boolean} fn - Predicate that receives the document and the include target.
50
+ * @returns {void}
51
+ */
52
+ function handles(fn: (doc: Document, target: string) => boolean): void;
53
+ /**
54
+ * @overload
55
+ * @param {Document} doc - The document being parsed.
56
+ * @param {string} target - The include target.
57
+ * @returns {boolean}
58
+ */
59
+ function handles(doc: Document, target: string): boolean;
42
60
  }
43
61
  export namespace DocinfoProcessorDsl {
44
62
  function atLocation(value: any): void;
@@ -486,14 +504,38 @@ export class ProcessorExtension extends Extension {
486
504
  processMethod: any;
487
505
  }
488
506
  /**
489
- * A Group registers one or more extensions with a Registry.
507
+ * A Group bundles one or more extension registrations that are re-executed on
508
+ * every document conversion, making the registry safe to reuse.
490
509
  *
491
- * Subclass Group and pass the subclass to Extensions.register(), or call
492
- * the static register() method directly.
510
+ * Subclass Group, override {@link Group#activate}, and either call
511
+ * {@link Group.register} to add it globally or pass the subclass to
512
+ * {@link Extensions.create} / {@link Extensions.register}.
513
+ *
514
+ * @example
515
+ * class MyGroup extends Group {
516
+ * activate (registry) {
517
+ * registry.preprocessor(MyPreprocessor)
518
+ * }
519
+ * }
520
+ * MyGroup.register()
493
521
  */
494
522
  export class Group {
495
- static register(name?: any): void;
496
- activate(_registry: any): void;
523
+ /**
524
+ * Register this Group class globally under the given name.
525
+ *
526
+ * Equivalent to calling `Extensions.register(name, this)`.
527
+ *
528
+ * @param {string|null} [name] - Optional name for the group.
529
+ */
530
+ static register(name?: string | null): void;
531
+ /**
532
+ * Called by {@link Registry#activate} on every document conversion.
533
+ *
534
+ * Override this method to register extensions with the provided registry.
535
+ *
536
+ * @param {Registry} _registry - The registry to register extensions with.
537
+ */
538
+ activate(_registry: Registry): void;
497
539
  }
498
540
  /**
499
541
  * The primary entry point into the extension system.
@@ -501,6 +543,18 @@ export class Group {
501
543
  * Registry holds the extensions which have been registered and activated, has
502
544
  * methods for registering or defining a processor and looks up extensions
503
545
  * stored in the registry during parsing.
546
+ *
547
+ * A registry can be reused across multiple conversions. Extensions registered
548
+ * via a group block (passed to {@link Extensions.create} or
549
+ * {@link Extensions.register}) are re-executed on every activation. Extensions
550
+ * registered directly on the registry instance (e.g. `registry.preprocessor(fn)`)
551
+ * are preserved across activations.
552
+ *
553
+ * @example
554
+ * const registry = Extensions.create('my-ext', function () {
555
+ * this.preprocessor(function () { ... })
556
+ * })
557
+ * // registry can be passed to multiple conversions safely
504
558
  */
505
559
  export class Registry {
506
560
  constructor(groups?: {});
@@ -826,6 +880,13 @@ export namespace Extensions {
826
880
  /**
827
881
  * Create a new Registry, optionally pre-populated with a named block.
828
882
  *
883
+ * When a `block` is provided it is stored as a group and re-executed on every
884
+ * activation, making the registry safe to reuse across multiple conversions.
885
+ * Without a `block`, any extensions registered directly on the returned registry
886
+ * (e.g. `registry.preprocessor(fn)`) are stored in transient state that is
887
+ * cleared on every activation — those registrations will be lost from the second
888
+ * conversion onwards. Prefer the block form when the registry may be reused.
889
+ *
829
890
  * @param {string|null} [name=null] - Optional name for the group; auto-generated if omitted.
830
891
  * @param {Function|null} [block=null] - Optional function to register as the group.
831
892
  * @returns {Registry}
@@ -1032,6 +1093,7 @@ export type SyntaxProcessorDslInterface = ProcessorDslInterface & {
1032
1093
  * DSL interface for include processors.
1033
1094
  */
1034
1095
  export type IncludeProcessorDslInterface = DocumentProcessorDslInterface & {
1096
+ handles(fn: (target: string) => boolean): void;
1035
1097
  handles(fn: (doc: Document, target: string) => boolean): void;
1036
1098
  };
1037
1099
  /**