@nodable/flexible-xml-parser 1.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/fxp.d.cts ADDED
@@ -0,0 +1,652 @@
1
+ /**
2
+ * Flex XML Parser — TypeScript Definitions (CommonJS)
3
+ *
4
+ * This file mirrors src/fxp.d.ts for consumers using `require()`.
5
+ * It is referenced from the `exports["."].require.types` field in package.json.
6
+ */
7
+
8
+ /**
9
+ * Object form of a skip-tag entry — allows per-node control of nested depth
10
+ * tracking and enclosure skipping when scanning for the closing tag.
11
+ *
12
+ * ```ts
13
+ * import { xmlEnclosures } from 'flex-xml-parser';
14
+ *
15
+ * const parser = new XMLParser({
16
+ * skip: {
17
+ * tags: [
18
+ * "..secret",
19
+ * { expression: "root.internal", nested: true, skipEnclosures: [...xmlEnclosures] },
20
+ * ]
21
+ * }
22
+ * });
23
+ * ```
24
+ */
25
+ interface SkipTagEntry {
26
+ /** Path expression (same syntax as string skip-tag entries). */
27
+ expression: string;
28
+ /**
29
+ * When true, nested same-name open tags are tracked and the skip ends only
30
+ * when the outermost closing tag is found. Default: false.
31
+ */
32
+ nested?: boolean;
33
+ /**
34
+ * Enclosure pairs to skip while scanning for the closing tag.
35
+ * Checked in array order — first open match wins.
36
+ * Defaults to `[]` (plain first-match, no enclosure awareness).
37
+ */
38
+ skipEnclosures?: Enclosure[];
39
+ }
40
+
41
+ interface SkipOptions {
42
+ /** Skip XML declaration `<?xml ... ?>` from output. Default: false */
43
+ declaration?: boolean;
44
+ /** Skip processing instructions (other than declaration) from output. Default: false */
45
+ pi?: boolean;
46
+ /** Skip all attributes from output. Default: true */
47
+ attributes?: boolean;
48
+ /** Exclude CDATA sections entirely from output. Default: false */
49
+ cdata?: boolean;
50
+ /** Exclude comments entirely from output. Default: false */
51
+ comment?: boolean;
52
+ /**
53
+ * Strip namespace prefixes from tag and attribute names.
54
+ * E.g. `ns:tag` → `tag`, `xmlns:*` attributes are dropped.
55
+ * Default: false
56
+ */
57
+ nsPrefix?: boolean;
58
+ /**
59
+ * Tag paths whose entire subtree is silently dropped from output.
60
+ * The parser advances past the closing tag using the same raw-collection
61
+ * mechanism as stop nodes, then discards the content without calling
62
+ * any output builder methods.
63
+ *
64
+ * Each entry is either:
65
+ * - A plain string path expression — equivalent to `{ expression, nested: false, skipEnclosures: [] }`.
66
+ * The very first `</tagName>` ends collection.
67
+ * - A `SkipTagEntry` object with optional `nested` and `skipEnclosures`.
68
+ *
69
+ * Supports path-expression-matcher syntax. Default: []
70
+ *
71
+ * @example
72
+ * import { xmlEnclosures } from 'flex-xml-parser';
73
+ *
74
+ * skip: {
75
+ * tags: [
76
+ * "..secret",
77
+ * { expression: "root.internal", nested: true, skipEnclosures: [...xmlEnclosures] },
78
+ * ]
79
+ * }
80
+ */
81
+ tags?: Array<string | SkipTagEntry>;
82
+ }
83
+
84
+ interface NameForOptions {
85
+ /**
86
+ * Property name for mixed text content when a tag contains both text and child elements.
87
+ * Default: '#text'
88
+ */
89
+ text?: string;
90
+ /**
91
+ * Property name for CDATA sections.
92
+ * Empty string (default) merges CDATA content into the tag's text value.
93
+ */
94
+ cdata?: string;
95
+ /**
96
+ * Property name for XML comments.
97
+ * Empty string (default) omits comments from output.
98
+ * Set e.g. '#comment' to capture them.
99
+ */
100
+ comment?: string;
101
+ }
102
+
103
+ interface AttributeOptions {
104
+ /** Allow boolean (valueless) attributes — treated as `true`. Default: false */
105
+ booleanType?: boolean;
106
+ /** Group all attributes under this property name. Empty string = inline with tag. Default: '' */
107
+ groupBy?: string;
108
+ /** Prefix prepended to attribute names in output. Default: '@_' */
109
+ prefix?: string;
110
+ /** Suffix appended to attribute names in output. Default: '' */
111
+ suffix?: string;
112
+ }
113
+
114
+ /**
115
+ * An open/close pair that defines a region the stop-node processor should skip
116
+ * when scanning for the closing tag. Anything between `open` and `close` is
117
+ * treated as opaque text — closing-tag detection and depth tracking are
118
+ * suspended until `close` is found.
119
+ *
120
+ * @example
121
+ * { open: '<!--', close: '-->' } // XML comment
122
+ * { open: '"', close: '"' } // double-quoted string
123
+ */
124
+ interface Enclosure {
125
+ open: string;
126
+ close: string;
127
+ }
128
+
129
+ /**
130
+ * Object form of a stop-node entry — allows per-node control of which
131
+ * enclosures the processor should skip when scanning for the closing tag.
132
+ *
133
+ * ```ts
134
+ * import { xmlEnclosures, quoteEnclosures } from 'flex-xml-parser';
135
+ *
136
+ * const parser = new XMLParser({
137
+ * tags: {
138
+ * stopNodes: [
139
+ * "..script", // plain — no enclosures
140
+ * { expression: "body..pre", skipEnclosures: [...xmlEnclosures] },
141
+ * { expression: "head..style", skipEnclosures: [...xmlEnclosures, ...quoteEnclosures] },
142
+ * ]
143
+ * }
144
+ * });
145
+ * ```
146
+ */
147
+ interface StopNodeEntry {
148
+ /** Path expression (same syntax as string stop-node entries). */
149
+ expression: string;
150
+ /**
151
+ * When true, nested same-name open tags are tracked and the stop node ends
152
+ * only when the outermost closing tag is found. Default: false.
153
+ */
154
+ nested?: boolean;
155
+ /**
156
+ * Enclosure pairs to skip while scanning for the closing tag.
157
+ * Checked in array order — first open match wins.
158
+ * Defaults to `[]` (plain first-match, no depth tracking).
159
+ */
160
+ skipEnclosures: Enclosure[];
161
+ }
162
+
163
+ interface TagOptions {
164
+ /** Tags that never have a closing tag (e.g. ['br', 'img', 'hr']). Default: [] */
165
+ unpaired?: string[];
166
+ /**
167
+ * Tag paths whose content is captured raw without further XML parsing.
168
+ *
169
+ * Each entry is either:
170
+ * - A plain string path expression — equivalent to `{ expression, skipEnclosures: [] }`.
171
+ * The very first `</tagName>` ends collection (no depth tracking, no enclosure skipping).
172
+ * - A `StopNodeEntry` object with an explicit `skipEnclosures` array.
173
+ * When `skipEnclosures` is non-empty, depth tracking is enabled and anything
174
+ * between an enclosure's open/close markers is skipped (so false closing tags
175
+ * inside comments, CDATA, string literals, etc. are ignored).
176
+ *
177
+ * Supports path-expression-matcher syntax. Default: []
178
+ *
179
+ * @example
180
+ * import { xmlEnclosures, quoteEnclosures } from 'flex-xml-parser';
181
+ *
182
+ * stopNodes: [
183
+ * "..script", // plain
184
+ * { expression: "body..pre", skipEnclosures: [...xmlEnclosures] },
185
+ * { expression: "head..style", skipEnclosures: [...xmlEnclosures, ...quoteEnclosures] },
186
+ * ]
187
+ */
188
+ stopNodes?: Array<string | StopNodeEntry>;
189
+ }
190
+
191
+ /**
192
+ * Options for DOCTYPE reading — controls whether entities are collected
193
+ * and enforces read-time security limits.
194
+ */
195
+ interface DoctypeOptions {
196
+ /**
197
+ * Whether to collect entities declared in the DOCTYPE internal subset and
198
+ * forward them to the output builder for replacement.
199
+ * The DOCTYPE block is always read to consume it; this flag controls forwarding.
200
+ */
201
+ enabled?: boolean;
202
+
203
+ /**
204
+ * Max number of entities that may be declared in a DOCTYPE internal subset.
205
+ * Enforced by DocTypeReader at declaration time.
206
+ * Default: 100
207
+ */
208
+ maxEntityCount?: number;
209
+
210
+ /**
211
+ * Max bytes per entity definition value in DOCTYPE.
212
+ * Enforced by DocTypeReader at declaration time.
213
+ * Default: 10000
214
+ */
215
+ maxEntitySize?: number;
216
+ }
217
+
218
+ // ─── Error handling ────────────────────────────────────────────────────────────
219
+
220
+ /**
221
+ * All error codes thrown by the parser.
222
+ * Use with `instanceof ParseError` and `err.code === ErrorCode.XXX` for
223
+ * precise error handling without string-matching against messages.
224
+ */
225
+ declare const ErrorCode: {
226
+ // Input type errors
227
+ readonly INVALID_INPUT: 'INVALID_INPUT';
228
+ readonly INVALID_STREAM: 'INVALID_STREAM';
229
+
230
+ // Streaming / feed API
231
+ readonly ALREADY_STREAMING: 'ALREADY_STREAMING';
232
+ readonly NOT_STREAMING: 'NOT_STREAMING';
233
+ readonly DATA_MUST_BE_STRING: 'DATA_MUST_BE_STRING';
234
+
235
+ // Tag structure
236
+ readonly UNEXPECTED_END: 'UNEXPECTED_END';
237
+ readonly UNEXPECTED_CLOSE_TAG: 'UNEXPECTED_CLOSE_TAG';
238
+ readonly MISMATCHED_CLOSE_TAG: 'MISMATCHED_CLOSE_TAG';
239
+ readonly UNEXPECTED_TRAILING_DATA: 'UNEXPECTED_TRAILING_DATA';
240
+ readonly INVALID_TAG: 'INVALID_TAG';
241
+ readonly UNCLOSED_QUOTE: 'UNCLOSED_QUOTE';
242
+
243
+ // Namespace
244
+ readonly MULTIPLE_NAMESPACES: 'MULTIPLE_NAMESPACES';
245
+
246
+ // Security
247
+ readonly SECURITY_PROTOTYPE_POLLUTION: 'SECURITY_PROTOTYPE_POLLUTION';
248
+ readonly SECURITY_RESERVED_OPTION: 'SECURITY_RESERVED_OPTION';
249
+ readonly SECURITY_RESTRICTED_NAME: 'SECURITY_RESTRICTED_NAME';
250
+
251
+ // Limits (DoS prevention)
252
+ readonly LIMIT_MAX_NESTED_TAGS: 'LIMIT_MAX_NESTED_TAGS';
253
+ readonly LIMIT_MAX_ATTRIBUTES: 'LIMIT_MAX_ATTRIBUTES';
254
+
255
+ // Entity limits
256
+ readonly ENTITY_MAX_COUNT: 'ENTITY_MAX_COUNT';
257
+ readonly ENTITY_MAX_SIZE: 'ENTITY_MAX_SIZE';
258
+ readonly ENTITY_MAX_EXPANSIONS: 'ENTITY_MAX_EXPANSIONS';
259
+ readonly ENTITY_MAX_EXPANDED_LENGTH: 'ENTITY_MAX_EXPANDED_LENGTH';
260
+
261
+ // Entity registration
262
+ readonly ENTITY_INVALID_KEY: 'ENTITY_INVALID_KEY';
263
+ readonly ENTITY_INVALID_VALUE: 'ENTITY_INVALID_VALUE';
264
+ };
265
+
266
+ type ErrorCodeValue = typeof ErrorCode[keyof typeof ErrorCode];
267
+
268
+ /**
269
+ * Structured error class thrown by all parser error paths.
270
+ *
271
+ * Always catch with `instanceof ParseError` to distinguish library errors
272
+ * from unexpected runtime errors:
273
+ *
274
+ * ```ts
275
+ * try {
276
+ * parser.parse(xml);
277
+ * } catch (e) {
278
+ * if (e instanceof ParseError) {
279
+ * console.error(e.code, e.line, e.col, e.message);
280
+ * } else {
281
+ * throw e; // unexpected runtime error
282
+ * }
283
+ * }
284
+ * ```
285
+ */
286
+ declare class ParseError extends Error {
287
+ readonly name: 'ParseError';
288
+
289
+ /** Machine-readable error code. Always one of the `ErrorCode` values. */
290
+ readonly code: ErrorCodeValue;
291
+
292
+ /**
293
+ * 1-based line number where the error occurred.
294
+ * `undefined` when position information is not available for this error type.
295
+ */
296
+ readonly line: number | undefined;
297
+
298
+ /**
299
+ * 1-based column where the error occurred.
300
+ * `undefined` when position information is not available for this error type.
301
+ */
302
+ readonly col: number | undefined;
303
+
304
+ /**
305
+ * 0-based character offset from the start of the document.
306
+ * `undefined` when position information is not available for this error type.
307
+ */
308
+ readonly index: number | undefined;
309
+
310
+ constructor(
311
+ message: string,
312
+ code: ErrorCodeValue,
313
+ position?: { line?: number; col?: number; index?: number }
314
+ );
315
+
316
+ /** Returns a formatted string: `ParseError [CODE] at line N, col M: message` */
317
+ toString(): string;
318
+ }
319
+
320
+ // ─── Limits ────────────────────────────────────────────────────────────────────
321
+
322
+ /**
323
+ * Structural limits that guard against resource-exhaustion and DoS attacks.
324
+ * All properties default to `null` (no limit enforced).
325
+ *
326
+ * Errors thrown when limits are exceeded are always `ParseError` instances
327
+ * with codes `LIMIT_MAX_NESTED_TAGS` or `LIMIT_MAX_ATTRIBUTES` respectively,
328
+ * and carry `line`, `col`, and `index` position information.
329
+ */
330
+ interface LimitsOptions {
331
+ /**
332
+ * Maximum tag nesting depth.
333
+ *
334
+ * Throws `ParseError` with code `LIMIT_MAX_NESTED_TAGS` when a tag would
335
+ * open at a depth greater than this value.
336
+ *
337
+ * Prevents stack-overflow attacks via pathologically deep XML such as
338
+ * `<a><a><a>...</a></a></a>` (1 million levels deep).
339
+ *
340
+ * Must be a positive integer (`>= 1`) or `null`.
341
+ * Default: `null` (unlimited)
342
+ *
343
+ * @example
344
+ * // Reject XML deeper than 100 tags
345
+ * new XMLParser({ limits: { maxNestedTags: 100 } });
346
+ */
347
+ maxNestedTags?: number | null;
348
+
349
+ /**
350
+ * Maximum number of attributes allowed on a single tag.
351
+ *
352
+ * Throws `ParseError` with code `LIMIT_MAX_ATTRIBUTES` when a tag has
353
+ * more attributes than this value. Only enforced when `skip.attributes`
354
+ * is `false` (attributes are being parsed).
355
+ *
356
+ * Prevents attacks that use thousands of attributes to exhaust memory or
357
+ * CPU during attribute parsing.
358
+ *
359
+ * Must be a non-negative integer (`>= 0`) or `null`.
360
+ * `0` means no attributes are permitted on any tag.
361
+ * Default: `null` (unlimited)
362
+ *
363
+ * @example
364
+ * // Reject any tag with more than 50 attributes
365
+ * new XMLParser({ skip: { attributes: false }, limits: { maxAttributesPerTag: 50 } });
366
+ */
367
+ maxAttributesPerTag?: number | null;
368
+ }
369
+
370
+ /**
371
+ * A value parser transforms a value in the parsing chain.
372
+ * Receives the current value and an optional context object.
373
+ */
374
+ interface ValueParser {
375
+ /**
376
+ * @param val Current value (string initially; may already be typed if earlier parsers ran)
377
+ * @param context { tagName, isAttribute, attrName? }
378
+ */
379
+ parse(val: any, context?: { tagName: string; isAttribute: boolean; attrName?: string }): any;
380
+ }
381
+
382
+ /**
383
+ * Buffer options for the feed()/end() and parseStream() input APIs.
384
+ * Passed as `feedable` inside XMLParser options.
385
+ */
386
+ interface FeedableOptions {
387
+ /**
388
+ * Maximum number of characters allowed in the buffer at any one time.
389
+ * Prevents memory exhaustion when data is fed faster than it is consumed.
390
+ * Default: 10485760 (10 MB)
391
+ */
392
+ maxBufferSize?: number;
393
+
394
+ /**
395
+ * When true (default), already-processed characters are automatically
396
+ * discarded from the buffer once the processed portion exceeds
397
+ * flushThreshold. Keeps memory usage flat for large documents.
398
+ * Default: true
399
+ */
400
+ autoFlush?: boolean;
401
+
402
+ /**
403
+ * Number of processed characters that triggers an automatic flush.
404
+ * Lower values free memory sooner at the cost of more string-slice
405
+ * operations. Default: 1024 (1 KB)
406
+ */
407
+ flushThreshold?: number;
408
+ }
409
+
410
+ interface X2jOptions {
411
+ // --- node-type controls ---
412
+ /** Fine-grained control over which node types appear in output */
413
+ skip?: SkipOptions;
414
+
415
+ // --- property name mapping ---
416
+ /** Property names used for special nodes in output */
417
+ nameFor?: NameForOptions;
418
+
419
+ // --- attribute controls ---
420
+ /** Attribute parsing and representation options */
421
+ attributes?: AttributeOptions;
422
+
423
+ // --- tag controls ---
424
+ /** Tag parsing options including stop nodes and value parser chain */
425
+ tags?: TagOptions;
426
+
427
+ // --- DOCTYPE parsing ---
428
+ /**
429
+ * Controls whether DOCTYPE entities are collected and read-time security limits.
430
+ * Once collected will be passed to Output builder to take any decision
431
+ */
432
+ doctypeOptions?: DoctypeOptions;
433
+
434
+ // --- security ---
435
+ /** Throw when a tag/attribute name collides with a nameFor.* or attributes.groupBy value. Default: false */
436
+ strictReservedNames?: boolean;
437
+ /** Custom handler for dangerous (non-critical) property names. Default: prefix with '__' */
438
+ onDangerousProperty?: (name: string) => string;
439
+
440
+ // --- filtering (path-expression-matcher) ---
441
+ select?: string[];
442
+ only?: string[];
443
+
444
+ // --- limits (DoS prevention) ---
445
+ /**
446
+ * Structural limits that guard against resource-exhaustion attacks.
447
+ * All properties default to `null` (no limit enforced).
448
+ *
449
+ * ```ts
450
+ * new XMLParser({
451
+ * limits: {
452
+ * maxNestedTags: 100, // reject XML deeper than 100 levels
453
+ * maxAttributesPerTag: 50, // reject any tag with > 50 attributes
454
+ * }
455
+ * });
456
+ * ```
457
+ */
458
+ limits?: LimitsOptions | null;
459
+
460
+ // --- feedable (feed/end and parseStream buffer options) ---
461
+ /**
462
+ * Buffer behaviour for the FeedableSource (feed/end API) and StreamSource
463
+ * (parseStream API). All properties have sensible defaults and only need
464
+ * to be set when processing very large documents or operating under tight
465
+ * memory constraints.
466
+ */
467
+ feedable?: FeedableOptions;
468
+
469
+ // --- output builder ---
470
+ /** Pluggable output builder instance. Default: CompactObjBuilder */
471
+ OutputBuilder?: OutputBuilderFactory | null;
472
+
473
+ /**
474
+ * Callback fired by `NodeTreeBuilder` and `CompactObjBuilder` whenever a stop node
475
+ * is fully collected, before the raw content is added to the output tree.
476
+ *
477
+ * Receive the tag detail, the raw unparsed content, and a read-only path
478
+ * matcher. Useful for side-channel analysis (e.g. extracting script content
479
+ * from HTML) without having to post-process the output tree.
480
+ *
481
+ * The callback is informational — return value is ignored. To suppress the
482
+ * node from output, use a custom OutputBuilder subclass instead.
483
+ *
484
+ * @param tagDetail - `{ name, line, col, index }` of the stop-node opening tag.
485
+ * @param rawContent - Raw text content between the opening and closing tags.
486
+ * @param matcher - Read-only path matcher positioned at the stop node.
487
+ *
488
+ * @example
489
+ * const scripts: string[] = [];
490
+ * const parser = new XMLParser({
491
+ * tags: { stopNodes: ["..script"] },
492
+ * onStopNode(tagDetail, rawContent, matcher) {
493
+ * scripts.push(rawContent);
494
+ * }
495
+ * });
496
+ */
497
+ onStopNode?: (
498
+ tagDetail: { name: string; line: number; col: number; index: number },
499
+ rawContent: string,
500
+ matcher: any,
501
+ ) => void;
502
+ }
503
+
504
+ interface OutputBuilderFactory {
505
+ getInstance(parserOptions: X2jOptions): OutputBuilderInstance;
506
+ registerValueParser(name: string, parser: ValueParser): void;
507
+ }
508
+
509
+ interface OutputBuilderInstance {
510
+ addElement(tag: { name: string }, matcher: any): void;
511
+ closeElement(matcher: any): void;
512
+ addValue(text: string, matcher: any): void;
513
+ addAttribute(name: string, value: any): void;
514
+ addComment(text: string): void;
515
+ addLiteral(text: string): void;
516
+ addDeclaration(): void;
517
+ addInstruction(name: string): void;
518
+ getOutput(): any;
519
+ registeredValParsers: Record<string, ValueParser>;
520
+ /**
521
+ * Optional hook called by the parser when a stop node is fully collected.
522
+ * Implement this in custom OutputBuilder classes to handle stop-node content.
523
+ * `NodeTreeBuilder` and `CompactObjBuilder` implement it and delegate to the
524
+ * `options.onStopNode` callback when supplied.
525
+ */
526
+ onStopNode?(
527
+ tagDetail: { name: string; line: number; col: number; index: number },
528
+ rawContent: string,
529
+ matcher: any,
530
+ ): void;
531
+ }
532
+
533
+ default class XMLParser {
534
+ /**
535
+ * Create a new XMLParser.
536
+ * @throws {ParseError} with code `INVALID_INPUT` or `SECURITY_RESERVED_OPTION`
537
+ * if any option value is invalid or contains a reserved property name.
538
+ */
539
+ constructor(options?: X2jOptions);
540
+
541
+ /**
542
+ * Parse an XML string or Buffer to a JavaScript object.
543
+ * @throws {ParseError} on any well-formedness or limit violation.
544
+ */
545
+ parse(xmlData: string | Buffer): any;
546
+
547
+ /**
548
+ * Parse a Uint8Array / byte array to a JavaScript object.
549
+ * @throws {ParseError} on any well-formedness or limit violation.
550
+ */
551
+ parseBytesArr(xmlData: Uint8Array | ArrayBufferView): any;
552
+
553
+ /**
554
+ * Parse an XML Node.js Readable stream and return a Promise that resolves
555
+ * with the parsed JS object.
556
+ *
557
+ * Chunks are processed incrementally as they arrive — already-consumed input
558
+ * is freed immediately, so memory stays proportional to the largest single
559
+ * token rather than the total document size.
560
+ *
561
+ * @throws {ParseError} with code `INVALID_STREAM` if the argument is not a
562
+ * Node.js Readable stream.
563
+ */
564
+ parseStream(readable: NodeJS.ReadableStream): Promise<any>;
565
+
566
+ /**
567
+ * Feed an XML data chunk for incremental parsing.
568
+ * Call `end()` when all chunks have been fed.
569
+ * @throws {ParseError} with code `DATA_MUST_BE_STRING` if data is not a string or Buffer.
570
+ */
571
+ feed(data: string | Buffer): this;
572
+
573
+ /**
574
+ * Signal end of input and return the parsed result.
575
+ * @throws {ParseError} with code `NOT_STREAMING` if called before any `feed()`.
576
+ * @throws {ParseError} on any well-formedness or limit violation in the accumulated input.
577
+ */
578
+ end(): any;
579
+
580
+ /**
581
+ * Return structural errors collected during the last parse call.
582
+ * Only populated when `autoClose.collectErrors` is `true`.
583
+ * Each entry: `{ type, tag, expected, line, col, index }`
584
+ */
585
+ getParseErrors(): Array<{
586
+ type: 'unclosed-eof' | 'mismatched-close' | 'phantom-close' | 'partial-tag';
587
+ tag: string;
588
+ expected?: string;
589
+ line?: number;
590
+ col?: number;
591
+ index?: number;
592
+ }>;
593
+
594
+ /**
595
+ * Returns `true` if the last parse call was terminated early by `exitIf`.
596
+ * Returns `false` when `exitIf` never fired or the feature is not configured.
597
+ */
598
+ wasExited: boolean;
599
+ }
600
+
601
+ { XMLParser };
602
+
603
+ class CompactObjBuilder implements OutputBuilderFactory {
604
+ constructor(options?: Partial<X2jOptions>);
605
+ getInstance(parserOptions: X2jOptions): OutputBuilderInstance;
606
+ registerValueParser(name: string, parser: ValueParser): void;
607
+ }
608
+
609
+ // ─── Stop-node utilities ───────────────────────────────────────────────────────
610
+
611
+ /**
612
+ * XML structural enclosures — comments, CDATA sections, processing instructions.
613
+ *
614
+ * Use in `skipEnclosures` to prevent false closing-tag matches inside these
615
+ * XML constructs:
616
+ *
617
+ * ```ts
618
+ * { expression: "body..pre", skipEnclosures: [...xmlEnclosures] }
619
+ * ```
620
+ */
621
+ declare const xmlEnclosures: ReadonlyArray<Enclosure>;
622
+
623
+ /**
624
+ * String-literal enclosures — single-quote, double-quote, and template literals.
625
+ *
626
+ * Use in `skipEnclosures` for stop nodes that contain JS or CSS source code
627
+ * where closing tags might appear inside string literals:
628
+ *
629
+ * ```ts
630
+ * { expression: "head..style", skipEnclosures: [...xmlEnclosures, ...quoteEnclosures] }
631
+ * ```
632
+ */
633
+ declare const quoteEnclosures: ReadonlyArray<Enclosure>;
634
+
635
+ declare namespace fxp {
636
+ export {
637
+ XMLParser,
638
+ ErrorCode,
639
+ xmlEnclosures,
640
+ ReplaceEntitiesValueParser,
641
+ ParseError,
642
+ ElementType,
643
+ BaseOutputBuilder,
644
+ booleanParserExt,
645
+ joinParser,
646
+ quoteEnclosures,
647
+ DoctypeOptions
648
+ }
649
+ }
650
+
651
+
652
+ export = fxp;