@asciidoctor/core 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/build/browser/index.js +99 -20
- package/build/node/index.cjs +99 -20
- package/package.json +1 -1
- package/src/extensions.js +125 -22
- package/types/extensions.d.ts +68 -6
package/build/browser/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var version = "4.0.0
|
|
1
|
+
var version = "4.0.0";
|
|
2
2
|
const packageJson = {
|
|
3
3
|
version: version};
|
|
4
4
|
|
|
@@ -13466,6 +13466,7 @@ function _uniform(str, chr, len) {
|
|
|
13466
13466
|
* DSL interface for include processors.
|
|
13467
13467
|
*
|
|
13468
13468
|
* @typedef {DocumentProcessorDslInterface & {
|
|
13469
|
+
* handles(fn: (target: string) => boolean): void;
|
|
13469
13470
|
* handles(fn: (doc: Document, target: string) => boolean): void;
|
|
13470
13471
|
* }} IncludeProcessorDslInterface
|
|
13471
13472
|
*/
|
|
@@ -13516,7 +13517,7 @@ function _uniform(str, chr, len) {
|
|
|
13516
13517
|
* - Called with a single Function argument → stores it as the process block.
|
|
13517
13518
|
* - Called with non-Function arguments → invokes the stored process block.
|
|
13518
13519
|
*
|
|
13519
|
-
* The this context inside a stored process function is bound to the processor
|
|
13520
|
+
* The `this` context inside a stored process function is bound to the processor
|
|
13520
13521
|
* instance at definition time.
|
|
13521
13522
|
*/
|
|
13522
13523
|
const ProcessorDsl = {
|
|
@@ -13690,6 +13691,35 @@ const SyntaxProcessorDsl = {
|
|
|
13690
13691
|
const IncludeProcessorDsl = {
|
|
13691
13692
|
...DocumentProcessorDsl,
|
|
13692
13693
|
|
|
13694
|
+
/**
|
|
13695
|
+
* @overload
|
|
13696
|
+
* @param {(target: string) => boolean} fn - Predicate that receives only the include target.
|
|
13697
|
+
* @returns {void}
|
|
13698
|
+
*/
|
|
13699
|
+
/**
|
|
13700
|
+
* @overload
|
|
13701
|
+
* @param {(doc: Document, target: string) => boolean} fn - Predicate that receives the document and the include target.
|
|
13702
|
+
* @returns {void}
|
|
13703
|
+
*/
|
|
13704
|
+
/**
|
|
13705
|
+
* @overload
|
|
13706
|
+
* @param {Document} doc - The document being parsed.
|
|
13707
|
+
* @param {string} target - The include target.
|
|
13708
|
+
* @returns {boolean}
|
|
13709
|
+
*/
|
|
13710
|
+
/**
|
|
13711
|
+
* Register a function that decides whether this include processor handles a given target,
|
|
13712
|
+
* or invoke the registered handler.
|
|
13713
|
+
*
|
|
13714
|
+
* **Setter form** — register a predicate. The callback may accept either just the target
|
|
13715
|
+
* string (arity 1) or both the document and the target string (arity 2).
|
|
13716
|
+
*
|
|
13717
|
+
* **Invoker form** — call the registered predicate with `(doc, target)` and return its
|
|
13718
|
+
* result, or return `true` if no predicate has been registered.
|
|
13719
|
+
*
|
|
13720
|
+
* @param {...*} args
|
|
13721
|
+
* @returns {boolean | void}
|
|
13722
|
+
*/
|
|
13693
13723
|
handles(...args) {
|
|
13694
13724
|
if (args.length === 1 && typeof args[0] === 'function') {
|
|
13695
13725
|
const fn = args[0];
|
|
@@ -14457,6 +14487,8 @@ class ProcessorExtension extends Extension {
|
|
|
14457
14487
|
super(kind, instance, instance.config);
|
|
14458
14488
|
this.processMethod =
|
|
14459
14489
|
processMethod || ((...args) => instance.process(...args));
|
|
14490
|
+
/** @internal */
|
|
14491
|
+
this._direct = false;
|
|
14460
14492
|
}
|
|
14461
14493
|
}
|
|
14462
14494
|
|
|
@@ -14484,10 +14516,24 @@ const SYNTAX_PROCESSOR_CLASSES = {
|
|
|
14484
14516
|
* Registry holds the extensions which have been registered and activated, has
|
|
14485
14517
|
* methods for registering or defining a processor and looks up extensions
|
|
14486
14518
|
* stored in the registry during parsing.
|
|
14519
|
+
*
|
|
14520
|
+
* A registry can be reused across multiple conversions. Extensions registered
|
|
14521
|
+
* via a group block (passed to {@link Extensions.create} or
|
|
14522
|
+
* {@link Extensions.register}) are re-executed on every activation. Extensions
|
|
14523
|
+
* registered directly on the registry instance (e.g. `registry.preprocessor(fn)`)
|
|
14524
|
+
* are preserved across activations.
|
|
14525
|
+
*
|
|
14526
|
+
* @example
|
|
14527
|
+
* const registry = Extensions.create('my-ext', function () {
|
|
14528
|
+
* this.preprocessor(function () { ... })
|
|
14529
|
+
* })
|
|
14530
|
+
* // registry can be passed to multiple conversions safely
|
|
14487
14531
|
*/
|
|
14488
14532
|
class Registry {
|
|
14489
14533
|
constructor(groups = {}) {
|
|
14490
14534
|
this.groups = groups;
|
|
14535
|
+
/** @internal */
|
|
14536
|
+
this._activating = false;
|
|
14491
14537
|
this._reset();
|
|
14492
14538
|
}
|
|
14493
14539
|
|
|
@@ -14504,18 +14550,26 @@ class Registry {
|
|
|
14504
14550
|
...Object.values(Extensions.groups()),
|
|
14505
14551
|
...Object.values(this.groups),
|
|
14506
14552
|
];
|
|
14507
|
-
|
|
14508
|
-
|
|
14509
|
-
|
|
14510
|
-
if (
|
|
14511
|
-
|
|
14512
|
-
|
|
14513
|
-
|
|
14514
|
-
|
|
14553
|
+
this._activating = true;
|
|
14554
|
+
try {
|
|
14555
|
+
for (const group of extGroups) {
|
|
14556
|
+
if (typeof group === 'function') {
|
|
14557
|
+
// Check if it is a class (constructor) with an activate prototype method.
|
|
14558
|
+
if (
|
|
14559
|
+
group.prototype &&
|
|
14560
|
+
typeof group.prototype.activate === 'function'
|
|
14561
|
+
) {
|
|
14562
|
+
new group().activate(this);
|
|
14563
|
+
} else {
|
|
14564
|
+
// Plain function — call in the context of this registry (like instance_exec).
|
|
14565
|
+
group.length === 0 ? group.call(this) : group(this);
|
|
14566
|
+
}
|
|
14567
|
+
} else if (group && typeof group.activate === 'function') {
|
|
14568
|
+
group.activate(this);
|
|
14515
14569
|
}
|
|
14516
|
-
} else if (group && typeof group.activate === 'function') {
|
|
14517
|
-
group.activate(this);
|
|
14518
14570
|
}
|
|
14571
|
+
} finally {
|
|
14572
|
+
this._activating = false;
|
|
14519
14573
|
}
|
|
14520
14574
|
return this
|
|
14521
14575
|
}
|
|
@@ -15091,6 +15145,7 @@ class Registry {
|
|
|
15091
15145
|
}
|
|
15092
15146
|
|
|
15093
15147
|
const extension = new ProcessorExtension(kind, processorInstance);
|
|
15148
|
+
extension._direct = !this._activating;
|
|
15094
15149
|
extension.config.position === '>>'
|
|
15095
15150
|
? store.unshift(extension)
|
|
15096
15151
|
: store.push(extension);
|
|
@@ -15162,27 +15217,44 @@ class Registry {
|
|
|
15162
15217
|
}
|
|
15163
15218
|
|
|
15164
15219
|
store[name] = new ProcessorExtension(kind, processorInstance);
|
|
15220
|
+
store[name]._direct = !this._activating;
|
|
15165
15221
|
return store[name]
|
|
15166
15222
|
}
|
|
15167
15223
|
|
|
15168
15224
|
/** @internal */
|
|
15169
15225
|
_reset() {
|
|
15226
|
+
// Keep extensions registered directly (outside a group); only clear group-registered ones.
|
|
15227
|
+
// Extensions tagged with _direct=true survive across activations.
|
|
15228
|
+
const keepArr = (arr) => {
|
|
15229
|
+
const kept = arr?.filter((e) => e._direct) ?? [];
|
|
15230
|
+
return kept.length ? kept : null
|
|
15231
|
+
};
|
|
15232
|
+
const keepMap = (map) => {
|
|
15233
|
+
if (!map) return null
|
|
15234
|
+
const kept = Object.create(null);
|
|
15235
|
+
for (const [k, v] of Object.entries(map)) if (v._direct) kept[k] = v;
|
|
15236
|
+
return Object.keys(kept).length ? kept : null
|
|
15237
|
+
};
|
|
15170
15238
|
/** @internal */
|
|
15171
|
-
this._preprocessor_extensions =
|
|
15239
|
+
this._preprocessor_extensions = keepArr(this._preprocessor_extensions);
|
|
15172
15240
|
/** @internal */
|
|
15173
|
-
this._tree_processor_extensions =
|
|
15241
|
+
this._tree_processor_extensions = keepArr(this._tree_processor_extensions);
|
|
15174
15242
|
/** @internal */
|
|
15175
|
-
this._postprocessor_extensions =
|
|
15243
|
+
this._postprocessor_extensions = keepArr(this._postprocessor_extensions);
|
|
15176
15244
|
/** @internal */
|
|
15177
|
-
this._include_processor_extensions =
|
|
15245
|
+
this._include_processor_extensions = keepArr(
|
|
15246
|
+
this._include_processor_extensions
|
|
15247
|
+
);
|
|
15178
15248
|
/** @internal */
|
|
15179
|
-
this._docinfo_processor_extensions =
|
|
15249
|
+
this._docinfo_processor_extensions = keepArr(
|
|
15250
|
+
this._docinfo_processor_extensions
|
|
15251
|
+
);
|
|
15180
15252
|
/** @internal */
|
|
15181
|
-
this._block_extensions =
|
|
15253
|
+
this._block_extensions = keepMap(this._block_extensions);
|
|
15182
15254
|
/** @internal */
|
|
15183
|
-
this._block_macro_extensions =
|
|
15255
|
+
this._block_macro_extensions = keepMap(this._block_macro_extensions);
|
|
15184
15256
|
/** @internal */
|
|
15185
|
-
this._inline_macro_extensions =
|
|
15257
|
+
this._inline_macro_extensions = keepMap(this._inline_macro_extensions);
|
|
15186
15258
|
this.document = null;
|
|
15187
15259
|
}
|
|
15188
15260
|
|
|
@@ -15265,6 +15337,13 @@ const Extensions = {
|
|
|
15265
15337
|
/**
|
|
15266
15338
|
* Create a new Registry, optionally pre-populated with a named block.
|
|
15267
15339
|
*
|
|
15340
|
+
* When a `block` is provided it is stored as a group and re-executed on every
|
|
15341
|
+
* activation, making the registry safe to reuse across multiple conversions.
|
|
15342
|
+
* Without a `block`, any extensions registered directly on the returned registry
|
|
15343
|
+
* (e.g. `registry.preprocessor(fn)`) are stored in transient state that is
|
|
15344
|
+
* cleared on every activation — those registrations will be lost from the second
|
|
15345
|
+
* conversion onwards. Prefer the block form when the registry may be reused.
|
|
15346
|
+
*
|
|
15268
15347
|
* @param {string|null} [name=null] - Optional name for the group; auto-generated if omitted.
|
|
15269
15348
|
* @param {Function|null} [block=null] - Optional function to register as the group.
|
|
15270
15349
|
* @returns {Registry}
|
package/build/node/index.cjs
CHANGED
|
@@ -5,7 +5,7 @@ const node_fs = require('node:fs');
|
|
|
5
5
|
const path = require('node:path');
|
|
6
6
|
|
|
7
7
|
var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
|
|
8
|
-
var version = "4.0.0
|
|
8
|
+
var version = "4.0.0";
|
|
9
9
|
const packageJson = {
|
|
10
10
|
version: version};
|
|
11
11
|
|
|
@@ -13473,6 +13473,7 @@ function _uniform(str, chr, len) {
|
|
|
13473
13473
|
* DSL interface for include processors.
|
|
13474
13474
|
*
|
|
13475
13475
|
* @typedef {DocumentProcessorDslInterface & {
|
|
13476
|
+
* handles(fn: (target: string) => boolean): void;
|
|
13476
13477
|
* handles(fn: (doc: Document, target: string) => boolean): void;
|
|
13477
13478
|
* }} IncludeProcessorDslInterface
|
|
13478
13479
|
*/
|
|
@@ -13523,7 +13524,7 @@ function _uniform(str, chr, len) {
|
|
|
13523
13524
|
* - Called with a single Function argument → stores it as the process block.
|
|
13524
13525
|
* - Called with non-Function arguments → invokes the stored process block.
|
|
13525
13526
|
*
|
|
13526
|
-
* The this context inside a stored process function is bound to the processor
|
|
13527
|
+
* The `this` context inside a stored process function is bound to the processor
|
|
13527
13528
|
* instance at definition time.
|
|
13528
13529
|
*/
|
|
13529
13530
|
const ProcessorDsl = {
|
|
@@ -13697,6 +13698,35 @@ const SyntaxProcessorDsl = {
|
|
|
13697
13698
|
const IncludeProcessorDsl = {
|
|
13698
13699
|
...DocumentProcessorDsl,
|
|
13699
13700
|
|
|
13701
|
+
/**
|
|
13702
|
+
* @overload
|
|
13703
|
+
* @param {(target: string) => boolean} fn - Predicate that receives only the include target.
|
|
13704
|
+
* @returns {void}
|
|
13705
|
+
*/
|
|
13706
|
+
/**
|
|
13707
|
+
* @overload
|
|
13708
|
+
* @param {(doc: Document, target: string) => boolean} fn - Predicate that receives the document and the include target.
|
|
13709
|
+
* @returns {void}
|
|
13710
|
+
*/
|
|
13711
|
+
/**
|
|
13712
|
+
* @overload
|
|
13713
|
+
* @param {Document} doc - The document being parsed.
|
|
13714
|
+
* @param {string} target - The include target.
|
|
13715
|
+
* @returns {boolean}
|
|
13716
|
+
*/
|
|
13717
|
+
/**
|
|
13718
|
+
* Register a function that decides whether this include processor handles a given target,
|
|
13719
|
+
* or invoke the registered handler.
|
|
13720
|
+
*
|
|
13721
|
+
* **Setter form** — register a predicate. The callback may accept either just the target
|
|
13722
|
+
* string (arity 1) or both the document and the target string (arity 2).
|
|
13723
|
+
*
|
|
13724
|
+
* **Invoker form** — call the registered predicate with `(doc, target)` and return its
|
|
13725
|
+
* result, or return `true` if no predicate has been registered.
|
|
13726
|
+
*
|
|
13727
|
+
* @param {...*} args
|
|
13728
|
+
* @returns {boolean | void}
|
|
13729
|
+
*/
|
|
13700
13730
|
handles(...args) {
|
|
13701
13731
|
if (args.length === 1 && typeof args[0] === 'function') {
|
|
13702
13732
|
const fn = args[0];
|
|
@@ -14464,6 +14494,8 @@ class ProcessorExtension extends Extension {
|
|
|
14464
14494
|
super(kind, instance, instance.config);
|
|
14465
14495
|
this.processMethod =
|
|
14466
14496
|
processMethod || ((...args) => instance.process(...args));
|
|
14497
|
+
/** @internal */
|
|
14498
|
+
this._direct = false;
|
|
14467
14499
|
}
|
|
14468
14500
|
}
|
|
14469
14501
|
|
|
@@ -14491,10 +14523,24 @@ const SYNTAX_PROCESSOR_CLASSES = {
|
|
|
14491
14523
|
* Registry holds the extensions which have been registered and activated, has
|
|
14492
14524
|
* methods for registering or defining a processor and looks up extensions
|
|
14493
14525
|
* stored in the registry during parsing.
|
|
14526
|
+
*
|
|
14527
|
+
* A registry can be reused across multiple conversions. Extensions registered
|
|
14528
|
+
* via a group block (passed to {@link Extensions.create} or
|
|
14529
|
+
* {@link Extensions.register}) are re-executed on every activation. Extensions
|
|
14530
|
+
* registered directly on the registry instance (e.g. `registry.preprocessor(fn)`)
|
|
14531
|
+
* are preserved across activations.
|
|
14532
|
+
*
|
|
14533
|
+
* @example
|
|
14534
|
+
* const registry = Extensions.create('my-ext', function () {
|
|
14535
|
+
* this.preprocessor(function () { ... })
|
|
14536
|
+
* })
|
|
14537
|
+
* // registry can be passed to multiple conversions safely
|
|
14494
14538
|
*/
|
|
14495
14539
|
class Registry {
|
|
14496
14540
|
constructor(groups = {}) {
|
|
14497
14541
|
this.groups = groups;
|
|
14542
|
+
/** @internal */
|
|
14543
|
+
this._activating = false;
|
|
14498
14544
|
this._reset();
|
|
14499
14545
|
}
|
|
14500
14546
|
|
|
@@ -14511,18 +14557,26 @@ class Registry {
|
|
|
14511
14557
|
...Object.values(Extensions.groups()),
|
|
14512
14558
|
...Object.values(this.groups),
|
|
14513
14559
|
];
|
|
14514
|
-
|
|
14515
|
-
|
|
14516
|
-
|
|
14517
|
-
if (
|
|
14518
|
-
|
|
14519
|
-
|
|
14520
|
-
|
|
14521
|
-
|
|
14560
|
+
this._activating = true;
|
|
14561
|
+
try {
|
|
14562
|
+
for (const group of extGroups) {
|
|
14563
|
+
if (typeof group === 'function') {
|
|
14564
|
+
// Check if it is a class (constructor) with an activate prototype method.
|
|
14565
|
+
if (
|
|
14566
|
+
group.prototype &&
|
|
14567
|
+
typeof group.prototype.activate === 'function'
|
|
14568
|
+
) {
|
|
14569
|
+
new group().activate(this);
|
|
14570
|
+
} else {
|
|
14571
|
+
// Plain function — call in the context of this registry (like instance_exec).
|
|
14572
|
+
group.length === 0 ? group.call(this) : group(this);
|
|
14573
|
+
}
|
|
14574
|
+
} else if (group && typeof group.activate === 'function') {
|
|
14575
|
+
group.activate(this);
|
|
14522
14576
|
}
|
|
14523
|
-
} else if (group && typeof group.activate === 'function') {
|
|
14524
|
-
group.activate(this);
|
|
14525
14577
|
}
|
|
14578
|
+
} finally {
|
|
14579
|
+
this._activating = false;
|
|
14526
14580
|
}
|
|
14527
14581
|
return this
|
|
14528
14582
|
}
|
|
@@ -15098,6 +15152,7 @@ class Registry {
|
|
|
15098
15152
|
}
|
|
15099
15153
|
|
|
15100
15154
|
const extension = new ProcessorExtension(kind, processorInstance);
|
|
15155
|
+
extension._direct = !this._activating;
|
|
15101
15156
|
extension.config.position === '>>'
|
|
15102
15157
|
? store.unshift(extension)
|
|
15103
15158
|
: store.push(extension);
|
|
@@ -15169,27 +15224,44 @@ class Registry {
|
|
|
15169
15224
|
}
|
|
15170
15225
|
|
|
15171
15226
|
store[name] = new ProcessorExtension(kind, processorInstance);
|
|
15227
|
+
store[name]._direct = !this._activating;
|
|
15172
15228
|
return store[name]
|
|
15173
15229
|
}
|
|
15174
15230
|
|
|
15175
15231
|
/** @internal */
|
|
15176
15232
|
_reset() {
|
|
15233
|
+
// Keep extensions registered directly (outside a group); only clear group-registered ones.
|
|
15234
|
+
// Extensions tagged with _direct=true survive across activations.
|
|
15235
|
+
const keepArr = (arr) => {
|
|
15236
|
+
const kept = arr?.filter((e) => e._direct) ?? [];
|
|
15237
|
+
return kept.length ? kept : null
|
|
15238
|
+
};
|
|
15239
|
+
const keepMap = (map) => {
|
|
15240
|
+
if (!map) return null
|
|
15241
|
+
const kept = Object.create(null);
|
|
15242
|
+
for (const [k, v] of Object.entries(map)) if (v._direct) kept[k] = v;
|
|
15243
|
+
return Object.keys(kept).length ? kept : null
|
|
15244
|
+
};
|
|
15177
15245
|
/** @internal */
|
|
15178
|
-
this._preprocessor_extensions =
|
|
15246
|
+
this._preprocessor_extensions = keepArr(this._preprocessor_extensions);
|
|
15179
15247
|
/** @internal */
|
|
15180
|
-
this._tree_processor_extensions =
|
|
15248
|
+
this._tree_processor_extensions = keepArr(this._tree_processor_extensions);
|
|
15181
15249
|
/** @internal */
|
|
15182
|
-
this._postprocessor_extensions =
|
|
15250
|
+
this._postprocessor_extensions = keepArr(this._postprocessor_extensions);
|
|
15183
15251
|
/** @internal */
|
|
15184
|
-
this._include_processor_extensions =
|
|
15252
|
+
this._include_processor_extensions = keepArr(
|
|
15253
|
+
this._include_processor_extensions
|
|
15254
|
+
);
|
|
15185
15255
|
/** @internal */
|
|
15186
|
-
this._docinfo_processor_extensions =
|
|
15256
|
+
this._docinfo_processor_extensions = keepArr(
|
|
15257
|
+
this._docinfo_processor_extensions
|
|
15258
|
+
);
|
|
15187
15259
|
/** @internal */
|
|
15188
|
-
this._block_extensions =
|
|
15260
|
+
this._block_extensions = keepMap(this._block_extensions);
|
|
15189
15261
|
/** @internal */
|
|
15190
|
-
this._block_macro_extensions =
|
|
15262
|
+
this._block_macro_extensions = keepMap(this._block_macro_extensions);
|
|
15191
15263
|
/** @internal */
|
|
15192
|
-
this._inline_macro_extensions =
|
|
15264
|
+
this._inline_macro_extensions = keepMap(this._inline_macro_extensions);
|
|
15193
15265
|
this.document = null;
|
|
15194
15266
|
}
|
|
15195
15267
|
|
|
@@ -15272,6 +15344,13 @@ const Extensions = {
|
|
|
15272
15344
|
/**
|
|
15273
15345
|
* Create a new Registry, optionally pre-populated with a named block.
|
|
15274
15346
|
*
|
|
15347
|
+
* When a `block` is provided it is stored as a group and re-executed on every
|
|
15348
|
+
* activation, making the registry safe to reuse across multiple conversions.
|
|
15349
|
+
* Without a `block`, any extensions registered directly on the returned registry
|
|
15350
|
+
* (e.g. `registry.preprocessor(fn)`) are stored in transient state that is
|
|
15351
|
+
* cleared on every activation — those registrations will be lost from the second
|
|
15352
|
+
* conversion onwards. Prefer the block form when the registry may be reused.
|
|
15353
|
+
*
|
|
15275
15354
|
* @param {string|null} [name=null] - Optional name for the group; auto-generated if omitted.
|
|
15276
15355
|
* @param {Function|null} [block=null] - Optional function to register as the group.
|
|
15277
15356
|
* @returns {Registry}
|
package/package.json
CHANGED
package/src/extensions.js
CHANGED
|
@@ -75,6 +75,7 @@ import { MacroNameRx, CC_ANY } from './rx.js'
|
|
|
75
75
|
* DSL interface for include processors.
|
|
76
76
|
*
|
|
77
77
|
* @typedef {DocumentProcessorDslInterface & {
|
|
78
|
+
* handles(fn: (target: string) => boolean): void;
|
|
78
79
|
* handles(fn: (doc: Document, target: string) => boolean): void;
|
|
79
80
|
* }} IncludeProcessorDslInterface
|
|
80
81
|
*/
|
|
@@ -125,7 +126,7 @@ import { MacroNameRx, CC_ANY } from './rx.js'
|
|
|
125
126
|
* - Called with a single Function argument → stores it as the process block.
|
|
126
127
|
* - Called with non-Function arguments → invokes the stored process block.
|
|
127
128
|
*
|
|
128
|
-
* The this context inside a stored process function is bound to the processor
|
|
129
|
+
* The `this` context inside a stored process function is bound to the processor
|
|
129
130
|
* instance at definition time.
|
|
130
131
|
*/
|
|
131
132
|
export const ProcessorDsl = {
|
|
@@ -299,6 +300,35 @@ export const SyntaxProcessorDsl = {
|
|
|
299
300
|
export const IncludeProcessorDsl = {
|
|
300
301
|
...DocumentProcessorDsl,
|
|
301
302
|
|
|
303
|
+
/**
|
|
304
|
+
* @overload
|
|
305
|
+
* @param {(target: string) => boolean} fn - Predicate that receives only the include target.
|
|
306
|
+
* @returns {void}
|
|
307
|
+
*/
|
|
308
|
+
/**
|
|
309
|
+
* @overload
|
|
310
|
+
* @param {(doc: Document, target: string) => boolean} fn - Predicate that receives the document and the include target.
|
|
311
|
+
* @returns {void}
|
|
312
|
+
*/
|
|
313
|
+
/**
|
|
314
|
+
* @overload
|
|
315
|
+
* @param {Document} doc - The document being parsed.
|
|
316
|
+
* @param {string} target - The include target.
|
|
317
|
+
* @returns {boolean}
|
|
318
|
+
*/
|
|
319
|
+
/**
|
|
320
|
+
* Register a function that decides whether this include processor handles a given target,
|
|
321
|
+
* or invoke the registered handler.
|
|
322
|
+
*
|
|
323
|
+
* **Setter form** — register a predicate. The callback may accept either just the target
|
|
324
|
+
* string (arity 1) or both the document and the target string (arity 2).
|
|
325
|
+
*
|
|
326
|
+
* **Invoker form** — call the registered predicate with `(doc, target)` and return its
|
|
327
|
+
* result, or return `true` if no predicate has been registered.
|
|
328
|
+
*
|
|
329
|
+
* @param {...*} args
|
|
330
|
+
* @returns {boolean | void}
|
|
331
|
+
*/
|
|
302
332
|
handles(...args) {
|
|
303
333
|
if (args.length === 1 && typeof args[0] === 'function') {
|
|
304
334
|
const fn = args[0]
|
|
@@ -1072,22 +1102,48 @@ export class ProcessorExtension extends Extension {
|
|
|
1072
1102
|
super(kind, instance, instance.config)
|
|
1073
1103
|
this.processMethod =
|
|
1074
1104
|
processMethod || ((...args) => instance.process(...args))
|
|
1105
|
+
/** @internal */
|
|
1106
|
+
this._direct = false
|
|
1075
1107
|
}
|
|
1076
1108
|
}
|
|
1077
1109
|
|
|
1078
1110
|
// ── Group ─────────────────────────────────────────────────────────────────────
|
|
1079
1111
|
|
|
1080
1112
|
/**
|
|
1081
|
-
* A Group
|
|
1113
|
+
* A Group bundles one or more extension registrations that are re-executed on
|
|
1114
|
+
* every document conversion, making the registry safe to reuse.
|
|
1115
|
+
*
|
|
1116
|
+
* Subclass Group, override {@link Group#activate}, and either call
|
|
1117
|
+
* {@link Group.register} to add it globally or pass the subclass to
|
|
1118
|
+
* {@link Extensions.create} / {@link Extensions.register}.
|
|
1082
1119
|
*
|
|
1083
|
-
*
|
|
1084
|
-
*
|
|
1120
|
+
* @example
|
|
1121
|
+
* class MyGroup extends Group {
|
|
1122
|
+
* activate (registry) {
|
|
1123
|
+
* registry.preprocessor(MyPreprocessor)
|
|
1124
|
+
* }
|
|
1125
|
+
* }
|
|
1126
|
+
* MyGroup.register()
|
|
1085
1127
|
*/
|
|
1086
1128
|
export class Group {
|
|
1129
|
+
/**
|
|
1130
|
+
* Register this Group class globally under the given name.
|
|
1131
|
+
*
|
|
1132
|
+
* Equivalent to calling `Extensions.register(name, this)`.
|
|
1133
|
+
*
|
|
1134
|
+
* @param {string|null} [name] - Optional name for the group.
|
|
1135
|
+
*/
|
|
1087
1136
|
static register(name = null) {
|
|
1088
1137
|
Extensions.register(name, this)
|
|
1089
1138
|
}
|
|
1090
1139
|
|
|
1140
|
+
/**
|
|
1141
|
+
* Called by {@link Registry#activate} on every document conversion.
|
|
1142
|
+
*
|
|
1143
|
+
* Override this method to register extensions with the provided registry.
|
|
1144
|
+
*
|
|
1145
|
+
* @param {Registry} _registry - The registry to register extensions with.
|
|
1146
|
+
*/
|
|
1091
1147
|
activate(_registry) {
|
|
1092
1148
|
throw new Error(
|
|
1093
1149
|
`${this.constructor.name} must implement the activate method`
|
|
@@ -1119,10 +1175,24 @@ const SYNTAX_PROCESSOR_CLASSES = {
|
|
|
1119
1175
|
* Registry holds the extensions which have been registered and activated, has
|
|
1120
1176
|
* methods for registering or defining a processor and looks up extensions
|
|
1121
1177
|
* stored in the registry during parsing.
|
|
1178
|
+
*
|
|
1179
|
+
* A registry can be reused across multiple conversions. Extensions registered
|
|
1180
|
+
* via a group block (passed to {@link Extensions.create} or
|
|
1181
|
+
* {@link Extensions.register}) are re-executed on every activation. Extensions
|
|
1182
|
+
* registered directly on the registry instance (e.g. `registry.preprocessor(fn)`)
|
|
1183
|
+
* are preserved across activations.
|
|
1184
|
+
*
|
|
1185
|
+
* @example
|
|
1186
|
+
* const registry = Extensions.create('my-ext', function () {
|
|
1187
|
+
* this.preprocessor(function () { ... })
|
|
1188
|
+
* })
|
|
1189
|
+
* // registry can be passed to multiple conversions safely
|
|
1122
1190
|
*/
|
|
1123
1191
|
export class Registry {
|
|
1124
1192
|
constructor(groups = {}) {
|
|
1125
1193
|
this.groups = groups
|
|
1194
|
+
/** @internal */
|
|
1195
|
+
this._activating = false
|
|
1126
1196
|
this._reset()
|
|
1127
1197
|
}
|
|
1128
1198
|
|
|
@@ -1139,18 +1209,26 @@ export class Registry {
|
|
|
1139
1209
|
...Object.values(Extensions.groups()),
|
|
1140
1210
|
...Object.values(this.groups),
|
|
1141
1211
|
]
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
if (
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1212
|
+
this._activating = true
|
|
1213
|
+
try {
|
|
1214
|
+
for (const group of extGroups) {
|
|
1215
|
+
if (typeof group === 'function') {
|
|
1216
|
+
// Check if it is a class (constructor) with an activate prototype method.
|
|
1217
|
+
if (
|
|
1218
|
+
group.prototype &&
|
|
1219
|
+
typeof group.prototype.activate === 'function'
|
|
1220
|
+
) {
|
|
1221
|
+
new group().activate(this)
|
|
1222
|
+
} else {
|
|
1223
|
+
// Plain function — call in the context of this registry (like instance_exec).
|
|
1224
|
+
group.length === 0 ? group.call(this) : group(this)
|
|
1225
|
+
}
|
|
1226
|
+
} else if (group && typeof group.activate === 'function') {
|
|
1227
|
+
group.activate(this)
|
|
1150
1228
|
}
|
|
1151
|
-
} else if (group && typeof group.activate === 'function') {
|
|
1152
|
-
group.activate(this)
|
|
1153
1229
|
}
|
|
1230
|
+
} finally {
|
|
1231
|
+
this._activating = false
|
|
1154
1232
|
}
|
|
1155
1233
|
return this
|
|
1156
1234
|
}
|
|
@@ -1726,6 +1804,7 @@ export class Registry {
|
|
|
1726
1804
|
}
|
|
1727
1805
|
|
|
1728
1806
|
const extension = new ProcessorExtension(kind, processorInstance)
|
|
1807
|
+
extension._direct = !this._activating
|
|
1729
1808
|
extension.config.position === '>>'
|
|
1730
1809
|
? store.unshift(extension)
|
|
1731
1810
|
: store.push(extension)
|
|
@@ -1797,27 +1876,44 @@ export class Registry {
|
|
|
1797
1876
|
}
|
|
1798
1877
|
|
|
1799
1878
|
store[name] = new ProcessorExtension(kind, processorInstance)
|
|
1879
|
+
store[name]._direct = !this._activating
|
|
1800
1880
|
return store[name]
|
|
1801
1881
|
}
|
|
1802
1882
|
|
|
1803
1883
|
/** @internal */
|
|
1804
1884
|
_reset() {
|
|
1885
|
+
// Keep extensions registered directly (outside a group); only clear group-registered ones.
|
|
1886
|
+
// Extensions tagged with _direct=true survive across activations.
|
|
1887
|
+
const keepArr = (arr) => {
|
|
1888
|
+
const kept = arr?.filter((e) => e._direct) ?? []
|
|
1889
|
+
return kept.length ? kept : null
|
|
1890
|
+
}
|
|
1891
|
+
const keepMap = (map) => {
|
|
1892
|
+
if (!map) return null
|
|
1893
|
+
const kept = Object.create(null)
|
|
1894
|
+
for (const [k, v] of Object.entries(map)) if (v._direct) kept[k] = v
|
|
1895
|
+
return Object.keys(kept).length ? kept : null
|
|
1896
|
+
}
|
|
1805
1897
|
/** @internal */
|
|
1806
|
-
this._preprocessor_extensions =
|
|
1898
|
+
this._preprocessor_extensions = keepArr(this._preprocessor_extensions)
|
|
1807
1899
|
/** @internal */
|
|
1808
|
-
this._tree_processor_extensions =
|
|
1900
|
+
this._tree_processor_extensions = keepArr(this._tree_processor_extensions)
|
|
1809
1901
|
/** @internal */
|
|
1810
|
-
this._postprocessor_extensions =
|
|
1902
|
+
this._postprocessor_extensions = keepArr(this._postprocessor_extensions)
|
|
1811
1903
|
/** @internal */
|
|
1812
|
-
this._include_processor_extensions =
|
|
1904
|
+
this._include_processor_extensions = keepArr(
|
|
1905
|
+
this._include_processor_extensions
|
|
1906
|
+
)
|
|
1813
1907
|
/** @internal */
|
|
1814
|
-
this._docinfo_processor_extensions =
|
|
1908
|
+
this._docinfo_processor_extensions = keepArr(
|
|
1909
|
+
this._docinfo_processor_extensions
|
|
1910
|
+
)
|
|
1815
1911
|
/** @internal */
|
|
1816
|
-
this._block_extensions =
|
|
1912
|
+
this._block_extensions = keepMap(this._block_extensions)
|
|
1817
1913
|
/** @internal */
|
|
1818
|
-
this._block_macro_extensions =
|
|
1914
|
+
this._block_macro_extensions = keepMap(this._block_macro_extensions)
|
|
1819
1915
|
/** @internal */
|
|
1820
|
-
this._inline_macro_extensions =
|
|
1916
|
+
this._inline_macro_extensions = keepMap(this._inline_macro_extensions)
|
|
1821
1917
|
this.document = null
|
|
1822
1918
|
}
|
|
1823
1919
|
|
|
@@ -1900,6 +1996,13 @@ export const Extensions = {
|
|
|
1900
1996
|
/**
|
|
1901
1997
|
* Create a new Registry, optionally pre-populated with a named block.
|
|
1902
1998
|
*
|
|
1999
|
+
* When a `block` is provided it is stored as a group and re-executed on every
|
|
2000
|
+
* activation, making the registry safe to reuse across multiple conversions.
|
|
2001
|
+
* Without a `block`, any extensions registered directly on the returned registry
|
|
2002
|
+
* (e.g. `registry.preprocessor(fn)`) are stored in transient state that is
|
|
2003
|
+
* cleared on every activation — those registrations will be lost from the second
|
|
2004
|
+
* conversion onwards. Prefer the block form when the registry may be reused.
|
|
2005
|
+
*
|
|
1903
2006
|
* @param {string|null} [name=null] - Optional name for the group; auto-generated if omitted.
|
|
1904
2007
|
* @param {Function|null} [block=null] - Optional function to register as the group.
|
|
1905
2008
|
* @returns {Registry}
|
package/types/extensions.d.ts
CHANGED
|
@@ -38,7 +38,25 @@ export namespace SyntaxProcessorDsl {
|
|
|
38
38
|
function resolvesAttributes(...args: any[]): void;
|
|
39
39
|
}
|
|
40
40
|
export namespace IncludeProcessorDsl {
|
|
41
|
-
|
|
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
|
|
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
|
|
492
|
-
*
|
|
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
|
-
|
|
496
|
-
|
|
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
|
/**
|