asciidoctor 4.0.0-alpha.6 → 4.0.1

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.1",
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.1"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@biomejs/biome": "^2.4.13",
@@ -73,6 +73,6 @@
73
73
  "pug": "^3.0.3"
74
74
  },
75
75
  "volta": {
76
- "node": "24.16.0"
76
+ "node": "24.18.0"
77
77
  }
78
78
  }
@@ -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
  /**
package/types/index.d.cts CHANGED
@@ -54,6 +54,7 @@ import { Section } from './section.js';
54
54
  import { Reader } from './reader.js';
55
55
  import { SyntaxHighlighterBase } from './syntax_highlighter.js';
56
56
  import { LoggerManager } from './logging.js';
57
+ import { LogMessage } from './logging.js';
57
58
  import { MemoryLogger } from './logging.js';
58
59
  import { NullLogger } from './logging.js';
59
60
  import { HttpCache } from './http_cache.js';
@@ -83,4 +84,4 @@ import { deriveBackendTraits } from './converter.js';
83
84
  import { DefaultFactory as DefaultSyntaxHighlighterFactory } from './syntax_highlighter.js';
84
85
  import Html5Converter from './converter/html5.js';
85
86
  import { SyntaxHighlighter } from './syntax_highlighter.js';
86
- export { convert, convertFile, Document, DocumentTitle, Author, Footnote, ImageReference, RevisionInfo, Logger, AbstractNode, AbstractBlock, Inline, Block, List, ListItem, Section, Reader, SyntaxHighlighterBase, LoggerManager, MemoryLogger, NullLogger, HttpCache, MemoryHttpCache, HttpCacheManager, SafeMode, ContentModel, Timings, Registry, Processor, ProcessorExtension, Preprocessor, TreeProcessor, Postprocessor, IncludeProcessor, DocinfoProcessor, BlockProcessor, InlineMacroProcessor, BlockMacroProcessor, Extensions, Cursor, Converter as ConverterFactory, ConverterBase, CustomFactory as ConverterCustomFactory, DefaultConverterFactory, deriveBackendTraits, DefaultSyntaxHighlighterFactory, Html5Converter, SyntaxHighlighter };
87
+ export { convert, convertFile, Document, DocumentTitle, Author, Footnote, ImageReference, RevisionInfo, Logger, AbstractNode, AbstractBlock, Inline, Block, List, ListItem, Section, Reader, SyntaxHighlighterBase, LoggerManager, LogMessage, MemoryLogger, NullLogger, HttpCache, MemoryHttpCache, HttpCacheManager, SafeMode, ContentModel, Timings, Registry, Processor, ProcessorExtension, Preprocessor, TreeProcessor, Postprocessor, IncludeProcessor, DocinfoProcessor, BlockProcessor, InlineMacroProcessor, BlockMacroProcessor, Extensions, Cursor, Converter as ConverterFactory, ConverterBase, CustomFactory as ConverterCustomFactory, DefaultConverterFactory, deriveBackendTraits, DefaultSyntaxHighlighterFactory, Html5Converter, SyntaxHighlighter };
package/types/index.d.ts CHANGED
@@ -53,6 +53,7 @@ import { Section } from './section.js';
53
53
  import { Reader } from './reader.js';
54
54
  import { SyntaxHighlighterBase } from './syntax_highlighter.js';
55
55
  import { LoggerManager } from './logging.js';
56
+ import { LogMessage } from './logging.js';
56
57
  import { MemoryLogger } from './logging.js';
57
58
  import { NullLogger } from './logging.js';
58
59
  import { HttpCache } from './http_cache.js';
@@ -82,4 +83,4 @@ import { deriveBackendTraits } from './converter.js';
82
83
  import { DefaultFactory as DefaultSyntaxHighlighterFactory } from './syntax_highlighter.js';
83
84
  import Html5Converter from './converter/html5.js';
84
85
  import { SyntaxHighlighter } from './syntax_highlighter.js';
85
- export { convert, convertFile, Document, DocumentTitle, Author, Footnote, ImageReference, RevisionInfo, Logger, AbstractNode, AbstractBlock, Inline, Block, List, ListItem, Section, Reader, SyntaxHighlighterBase, LoggerManager, MemoryLogger, NullLogger, HttpCache, MemoryHttpCache, HttpCacheManager, SafeMode, ContentModel, Timings, Registry, Processor, ProcessorExtension, Preprocessor, TreeProcessor, Postprocessor, IncludeProcessor, DocinfoProcessor, BlockProcessor, InlineMacroProcessor, BlockMacroProcessor, Extensions, Cursor, Converter as ConverterFactory, ConverterBase, CustomFactory as ConverterCustomFactory, DefaultConverterFactory, deriveBackendTraits, DefaultSyntaxHighlighterFactory, Html5Converter, SyntaxHighlighter };
86
+ export { convert, convertFile, Document, DocumentTitle, Author, Footnote, ImageReference, RevisionInfo, Logger, AbstractNode, AbstractBlock, Inline, Block, List, ListItem, Section, Reader, SyntaxHighlighterBase, LoggerManager, LogMessage, MemoryLogger, NullLogger, HttpCache, MemoryHttpCache, HttpCacheManager, SafeMode, ContentModel, Timings, Registry, Processor, ProcessorExtension, Preprocessor, TreeProcessor, Postprocessor, IncludeProcessor, DocinfoProcessor, BlockProcessor, InlineMacroProcessor, BlockMacroProcessor, Extensions, Cursor, Converter as ConverterFactory, ConverterBase, CustomFactory as ConverterCustomFactory, DefaultConverterFactory, deriveBackendTraits, DefaultSyntaxHighlighterFactory, Html5Converter, SyntaxHighlighter };
@@ -95,22 +95,66 @@ export namespace Logger {
95
95
  export { BasicFormatter };
96
96
  export namespace AutoFormattingMessage {
97
97
  /**
98
- * Attach auto-formatting to any plain object carrying { text, source_location }.
99
- * @param {{text: string, source_location?: string}} obj
98
+ * Attach auto-formatting to any plain object carrying
99
+ * { text, source_location, include_location }.
100
+ *
101
+ * The location(s) are rendered only by inspect()/toString() (used when a
102
+ * stderr Logger formats the line); the structured `source_location` /
103
+ * `include_location` remain on the object so a MemoryLogger can record them
104
+ * on the resulting LogMessage without duplicating them inside `text`.
105
+ * @param {{text: string, source_location?: any, include_location?: any}} obj
100
106
  * @returns {typeof obj} The same object with inspect() and toString() added.
101
107
  */
102
108
  function attach(obj: {
103
109
  text: string;
104
- source_location?: string;
110
+ source_location?: any;
111
+ include_location?: any;
105
112
  }): typeof obj;
106
113
  }
107
114
  }
115
+ /** Wrapper stored by MemoryLogger; provides getSeverity/getText/getSourceLocation. */
116
+ export class LogMessage {
117
+ /**
118
+ * @param {string} severity - Severity label, e.g. 'ERROR'.
119
+ * @param {string|{text: string, source_location?: import('./reader.js').Cursor}|null} message
120
+ */
121
+ constructor(severity: string, message: string | {
122
+ text: string;
123
+ source_location?: import("./reader.js").Cursor;
124
+ } | null);
125
+ message: string | {
126
+ text: string;
127
+ source_location?: import("./reader.js").Cursor;
128
+ };
129
+ /** @type {string} */
130
+ severity: string;
131
+ /** @type {string} */
132
+ text: string;
133
+ /** @type {import('./reader.js').Cursor|null} */
134
+ sourceLocation: import("./reader.js").Cursor | null;
135
+ /**
136
+ * @returns {string} The severity label, e.g. 'ERROR'.
137
+ */
138
+ getSeverity(): string;
139
+ /**
140
+ * @returns {string} The message text.
141
+ */
142
+ getText(): string;
143
+ /**
144
+ * @returns {import('./reader.js').Cursor|undefined} The source location, if any.
145
+ */
146
+ getSourceLocation(): import("./reader.js").Cursor | undefined;
147
+ }
108
148
  /** In-memory logger that stores all log messages for later inspection. */
109
149
  export class MemoryLogger {
110
150
  static create(): MemoryLogger;
111
151
  level: number;
112
- messages: any[];
113
- getMessages(): any[];
152
+ /** @type {LogMessage[]} */
153
+ messages: LogMessage[];
154
+ /**
155
+ * @returns {LogMessage[]} The log messages recorded so far, in order.
156
+ */
157
+ getMessages(): LogMessage[];
114
158
  getMaxSeverity(): number;
115
159
  add(severity: any, message?: any, progname?: any): boolean;
116
160
  debug(msg: any, pn: any): boolean;
package/types/reader.d.ts CHANGED
@@ -123,13 +123,13 @@ export class Reader {
123
123
  createLogMessage(text: any, context?: {}): any;
124
124
  get logger(): any;
125
125
  /** @param {string} msg @param {{ sourceLocation?: any, includeLocation?: any }} [opts] */
126
- _logWarn(msg: string, { sourceLocation, includeLocation }?: {
126
+ _logWarn(msg: string, opts?: {
127
127
  sourceLocation?: any;
128
128
  includeLocation?: any;
129
129
  }): void;
130
130
  _logError(msg: any, opts?: {}): void;
131
131
  /** @param {string} msg @param {{ sourceLocation?: any }} [opts] */
132
- _logInfo(msg: string, { sourceLocation }?: {
132
+ _logInfo(msg: string, opts?: {
133
133
  sourceLocation?: any;
134
134
  }): void;
135
135
  }
@@ -4,9 +4,9 @@ export namespace Substitutors {
4
4
  *
5
5
  * @param {string|string[]} text - The text to process; must not be null.
6
6
  * @param {string[]} [subs=NORMAL_SUBS] - The substitutions to perform.
7
- * @returns {string|string[]} Text with substitutions applied.
7
+ * @returns {Promise<string|string[]>} Text with substitutions applied.
8
8
  */
9
- function applySubs(text: string | string[], subs?: string[]): string | string[];
9
+ function applySubs(text: string | string[], subs?: string[]): Promise<string | string[]>;
10
10
  /** Apply normal substitutions (alias for applySubs with default args). */
11
11
  function applyNormalSubs(text: any): Promise<string | string[]>;
12
12
  /** Apply substitutions for header metadata and attribute assignments.
@@ -32,9 +32,9 @@ export namespace Substitutors {
32
32
  * Substitute quoted text (emphasis, strong, monospaced, etc.)
33
33
  *
34
34
  * @param {string} text
35
- * @returns {string}
35
+ * @returns {Promise<string>}
36
36
  */
37
- function subQuotes(text: string): string;
37
+ function subQuotes(text: string): Promise<string>;
38
38
  /**
39
39
  * Substitute attribute references in the specified text.
40
40
  *
@@ -54,39 +54,39 @@ export namespace Substitutors {
54
54
  * Substitute inline macros (links, images, etc.)
55
55
  *
56
56
  * @param {string} text
57
- * @returns {string}
57
+ * @returns {Promise<string>}
58
58
  */
59
- function subMacros(text: string): string;
59
+ function subMacros(text: string): Promise<string>;
60
60
  /**
61
61
  * Substitute post replacements (hard line breaks).
62
62
  *
63
63
  * @param {string} text
64
- * @returns {string}
64
+ * @returns {Promise<string>}
65
65
  */
66
- function subPostReplacements(text: string): string;
66
+ function subPostReplacements(text: string): Promise<string>;
67
67
  /**
68
68
  * Apply verbatim substitutions on source.
69
69
  *
70
70
  * @param {string} source
71
71
  * @param {boolean} processCallouts
72
- * @returns {string}
72
+ * @returns {Promise<string>}
73
73
  */
74
- function subSource(source: string, processCallouts: boolean): string;
74
+ function subSource(source: string, processCallouts: boolean): Promise<string>;
75
75
  /**
76
76
  * Substitute callout source references.
77
77
  *
78
78
  * @param {string} text
79
- * @returns {string}
79
+ * @returns {Promise<string>}
80
80
  */
81
- function subCallouts(text: string): string;
81
+ function subCallouts(text: string): Promise<string>;
82
82
  /**
83
83
  * Highlight (colorize) the source code using a syntax highlighter.
84
84
  *
85
85
  * @param {string} source
86
86
  * @param {boolean} processCallouts
87
- * @returns {string}
87
+ * @returns {Promise<string>}
88
88
  */
89
- function highlightSource(source: string, processCallouts: boolean): string;
89
+ function highlightSource(source: string, processCallouts: boolean): Promise<string>;
90
90
  /**
91
91
  * Resolve line numbers to highlight from a test string.
92
92
  *
@@ -107,9 +107,9 @@ export namespace Substitutors {
107
107
  * Restore passthrough text by reinserting into placeholder positions.
108
108
  *
109
109
  * @param {string} text
110
- * @returns {string}
110
+ * @returns {Promise<string>}
111
111
  */
112
- function restorePassthroughs(text: string): string;
112
+ function restorePassthroughs(text: string): Promise<string>;
113
113
  /**
114
114
  * Resolve the list of comma-delimited subs against the possible options.
115
115
  *
@@ -143,9 +143,9 @@ export namespace Substitutors {
143
143
  * @param {string} attrlist
144
144
  * @param {string[]} [posattrs=[]]
145
145
  * @param {Object} [opts={}]
146
- * @returns {Object}
146
+ * @returns {Promise<Object>}
147
147
  */
148
- function parseAttributes(attrlist: string, posattrs?: string[], opts?: any): any;
148
+ function parseAttributes(attrlist: string, posattrs?: string[], opts?: any): Promise<any>;
149
149
  function extractAttributesFromText(text: any, defaultText?: any): Promise<any[]>;
150
150
  function extractCallouts(source: any): any[];
151
151
  function restoreCallouts(source: any, calloutMarks: any, sourceOffset?: any): Promise<string>;