@btc-embedded/cdk-extensions 0.23.4 → 0.23.5
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/.jsii +5 -5
- package/CHANGELOG.md +7 -0
- package/assets/cli/catnip.js +154 -166
- package/lib/constructs/EventPipe.js +1 -1
- package/lib/constructs/ExportedService.js +1 -1
- package/lib/constructs/S3Bucket.js +1 -1
- package/lib/constructs/SecureRestApi.js +1 -1
- package/lib/constructs/SecureRestApiV2.js +1 -1
- package/lib/constructs/api-keys/ApiKeyClientAuthorization.js +1 -1
- package/lib/constructs/api-keys/ApiKeyManagement.js +1 -1
- package/lib/constructs/api-keys/ApiKeyPreTokenHandler.js +1 -1
- package/lib/constructs/api-keys/ApiKeyStore.js +1 -1
- package/lib/extensions/ApiGatewayExtension.js +1 -1
- package/lib/extensions/ApplicationContainer.js +1 -1
- package/lib/extensions/ApplicationLoadBalancerExtension.js +1 -1
- package/lib/extensions/ApplicationLoadBalancerExtensionV2.js +1 -1
- package/lib/extensions/CloudMapExtension.js +1 -1
- package/lib/extensions/DeactivatableServiceExtension.js +1 -1
- package/lib/extensions/DeploymentConfigExtension.js +1 -1
- package/lib/extensions/DocumentDbAccessExtension.js +1 -1
- package/lib/extensions/DomainEventMessagingExtension.js +1 -1
- package/lib/extensions/EfsMountExtension.js +1 -1
- package/lib/extensions/ExtraContainerExtension.js +1 -1
- package/lib/extensions/HTTPApiExtension.js +1 -1
- package/lib/extensions/LogExtension.js +1 -1
- package/lib/extensions/ModifyContainerDefinitionExtension.js +1 -1
- package/lib/extensions/ModifyTaskDefinitionExtension.js +1 -1
- package/lib/extensions/OpenIdExtension.js +1 -1
- package/lib/extensions/OpenTelemetryExtension.js +1 -1
- package/lib/extensions/PostgresDbAccessExtension.js +1 -1
- package/lib/extensions/SharedVolumeExtension.js +1 -1
- package/lib/extensions/TcpKeepAliveExtension.js +1 -1
- package/lib/platform/ApiGateway.js +1 -1
- package/lib/platform/ApiGatewayVpcLink.js +2 -2
- package/lib/platform/ApplicationLoadBalancer.js +1 -1
- package/lib/platform/ApplicationLoadBalancerV2.d.ts +1 -0
- package/lib/platform/ApplicationLoadBalancerV2.js +10 -3
- package/lib/platform/AuroraPostgresDB.js +2 -2
- package/lib/platform/BTCLogGroup.js +1 -1
- package/lib/platform/CognitoUserPool.js +2 -2
- package/lib/platform/DefaultUserPoolClients.js +1 -1
- package/lib/platform/DocumentDB.js +2 -2
- package/lib/platform/EcsCluster.js +1 -1
- package/lib/platform/EfsFileSystem.js +1 -1
- package/lib/platform/HostedZone.js +1 -1
- package/lib/platform/PrivateDnsNamespace.js +1 -1
- package/lib/platform/ResourceServer.js +1 -1
- package/lib/platform/Vpc.js +1 -1
- package/lib/platform/VpcV2.js +1 -1
- package/lib/stacks/ApplicationStack.js +1 -1
- package/lib/utils/BasePlatformStackResolver.js +1 -1
- package/lib/utils/StackParameter.js +1 -1
- package/node_modules/@nodable/entities/README.md +41 -0
- package/node_modules/@nodable/entities/package.json +54 -0
- package/node_modules/@nodable/entities/src/EntityDecoder.js +543 -0
- package/node_modules/@nodable/entities/src/EntityEncoder.js +194 -0
- package/node_modules/@nodable/entities/src/entities.js +1177 -0
- package/node_modules/@nodable/entities/src/entityTries.js +49 -0
- package/node_modules/@nodable/entities/src/index.d.ts +264 -0
- package/node_modules/@nodable/entities/src/index.js +29 -0
- package/node_modules/fast-xml-builder/CHANGELOG.md +40 -0
- package/node_modules/fast-xml-builder/LICENSE +21 -0
- package/node_modules/fast-xml-builder/README.md +74 -0
- package/node_modules/fast-xml-builder/lib/fxb.cjs +1 -0
- package/node_modules/fast-xml-builder/lib/fxb.d.cts +270 -0
- package/node_modules/fast-xml-builder/lib/fxb.min.js +2 -0
- package/node_modules/fast-xml-builder/lib/fxb.min.js.map +1 -0
- package/node_modules/fast-xml-builder/package.json +81 -0
- package/node_modules/fast-xml-builder/src/fxb.d.ts +270 -0
- package/node_modules/fast-xml-builder/src/fxb.js +599 -0
- package/node_modules/fast-xml-builder/src/ignoreAttributes.js +18 -0
- package/node_modules/fast-xml-builder/src/orderedJs2Xml.js +359 -0
- package/node_modules/fast-xml-builder/src/util.js +16 -0
- package/node_modules/fast-xml-parser/CHANGELOG.md +165 -0
- package/node_modules/fast-xml-parser/README.md +21 -44
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.cjs +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.d.cts +343 -31
- package/node_modules/fast-xml-parser/lib/fxp.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxp.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxparser.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxparser.min.js.map +1 -1
- package/node_modules/fast-xml-parser/lib/fxvalidator.min.js +1 -1
- package/node_modules/fast-xml-parser/lib/fxvalidator.min.js.map +1 -1
- package/node_modules/fast-xml-parser/package.json +13 -8
- package/node_modules/fast-xml-parser/src/fxp.d.ts +335 -30
- package/node_modules/fast-xml-parser/src/fxp.js +1 -1
- package/node_modules/fast-xml-parser/src/util.js +18 -25
- package/node_modules/fast-xml-parser/src/v6/EntitiesParser.js +89 -87
- package/node_modules/fast-xml-parser/src/v6/OptionsBuilder.js +10 -10
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/BaseOutputBuilder.js +23 -23
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsArrBuilder.js +29 -29
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsMinArrBuilder.js +1 -1
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/JsObjBuilder.js +39 -39
- package/node_modules/fast-xml-parser/src/v6/OutputBuilders/ParserOptionsBuilder.js +21 -21
- package/node_modules/fast-xml-parser/src/v6/XMLParser.js +22 -22
- package/node_modules/fast-xml-parser/src/v6/valueParsers/EntitiesParser.js +85 -85
- package/node_modules/fast-xml-parser/src/validator.js +34 -34
- package/node_modules/fast-xml-parser/src/xmlbuilder/json2xml.js +5 -284
- package/node_modules/fast-xml-parser/src/xmlparser/DocTypeReader.js +335 -293
- package/node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js +160 -43
- package/node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js +540 -308
- package/node_modules/fast-xml-parser/src/xmlparser/XMLParser.js +26 -26
- package/node_modules/fast-xml-parser/src/xmlparser/node2json.js +99 -41
- package/node_modules/fast-xml-parser/src/xmlparser/xmlNode.js +10 -10
- package/node_modules/path-expression-matcher/LICENSE +21 -0
- package/node_modules/path-expression-matcher/README.md +872 -0
- package/node_modules/path-expression-matcher/lib/pem.cjs +1 -0
- package/node_modules/path-expression-matcher/lib/pem.d.cts +634 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js +2 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js.map +1 -0
- package/node_modules/path-expression-matcher/package.json +78 -0
- package/node_modules/path-expression-matcher/src/Expression.js +232 -0
- package/node_modules/path-expression-matcher/src/ExpressionSet.js +209 -0
- package/node_modules/path-expression-matcher/src/Matcher.js +570 -0
- package/node_modules/path-expression-matcher/src/index.d.ts +523 -0
- package/node_modules/path-expression-matcher/src/index.js +29 -0
- package/node_modules/strnum/CHANGELOG.md +12 -2
- package/node_modules/strnum/README.md +1 -0
- package/node_modules/strnum/package.json +5 -4
- package/node_modules/strnum/strnum.js +99 -65
- package/node_modules/xml-naming/README.md +189 -0
- package/node_modules/xml-naming/package.json +54 -0
- package/node_modules/xml-naming/src/index.d.ts +74 -0
- package/node_modules/xml-naming/src/index.js +270 -0
- package/package.json +3 -2
- package/renovate.json5 +1 -0
- package/node_modules/fast-xml-parser/src/xmlbuilder/orderedJs2Xml.js +0 -134
- package/node_modules/strnum/.github/SECURITY.md +0 -5
- package/node_modules/strnum/.vscode/launch.json +0 -25
- package/node_modules/strnum/algo.stflow +0 -84
- package/node_modules/strnum/strnum.test.js +0 -173
- package/node_modules/strnum/test.js +0 -9
- /package/node_modules/{fast-xml-parser/src/xmlbuilder → fast-xml-builder/src}/prettifyJs2Xml.js +0 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// entityTries.js
|
|
2
|
+
// Builds integer-keyed tries so the decoder never allocates a string object
|
|
3
|
+
// during lookup — every key is a plain charCode number.
|
|
4
|
+
//
|
|
5
|
+
// trie1: Map<code0, entity>
|
|
6
|
+
// trie2: Map<code0, Map<code1, entity>>
|
|
7
|
+
// trie3: Map<code0, Map<code1, Map<code2, entity>>>
|
|
8
|
+
|
|
9
|
+
import { ALL_ENTITIES } from './entities.js';
|
|
10
|
+
|
|
11
|
+
// Reverse map: character sequence → "&name;"
|
|
12
|
+
const CHAR_TO_ENTITY = new Map();
|
|
13
|
+
for (const [name, chars] of Object.entries(ALL_ENTITIES)) {
|
|
14
|
+
CHAR_TO_ENTITY.set(chars, `&${name};`);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export const trie1 = new Map(); // code0 → entity string
|
|
18
|
+
export const trie2 = new Map(); // code0 → Map → entity string
|
|
19
|
+
export const trie3 = new Map(); // code0 → Map → Map → entity string
|
|
20
|
+
|
|
21
|
+
for (const [chars, entity] of CHAR_TO_ENTITY) {
|
|
22
|
+
const len = chars.length;
|
|
23
|
+
|
|
24
|
+
if (len === 1) {
|
|
25
|
+
const c0 = chars.charCodeAt(0);
|
|
26
|
+
// Keep shortest match only if no longer match already claimed this code
|
|
27
|
+
// (longer matches are inserted in the same pass so we just overwrite —
|
|
28
|
+
// trie1 is only consulted after trie2/trie3 both miss, so no conflict)
|
|
29
|
+
trie1.set(c0, entity);
|
|
30
|
+
|
|
31
|
+
} else if (len === 2) {
|
|
32
|
+
const c0 = chars.charCodeAt(0);
|
|
33
|
+
const c1 = chars.charCodeAt(1);
|
|
34
|
+
let inner = trie2.get(c0);
|
|
35
|
+
if (inner === undefined) { inner = new Map(); trie2.set(c0, inner); }
|
|
36
|
+
inner.set(c1, entity);
|
|
37
|
+
|
|
38
|
+
} else if (len === 3) {
|
|
39
|
+
const c0 = chars.charCodeAt(0);
|
|
40
|
+
const c1 = chars.charCodeAt(1);
|
|
41
|
+
const c2 = chars.charCodeAt(2);
|
|
42
|
+
let mid = trie3.get(c0);
|
|
43
|
+
if (mid === undefined) { mid = new Map(); trie3.set(c0, mid); }
|
|
44
|
+
let inner = mid.get(c1);
|
|
45
|
+
if (inner === undefined) { inner = new Map(); mid.set(c1, inner); }
|
|
46
|
+
inner.set(c2, entity);
|
|
47
|
+
}
|
|
48
|
+
// HTML5 has no named entity whose character sequence is longer than 3 chars
|
|
49
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// @nodable/entities — TypeScript declarations
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
/** A function-based entity replacement value (used for numeric refs). */
|
|
6
|
+
export type EntityValFn = (match: string, captured: string, ...rest: unknown[]) => string;
|
|
7
|
+
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
// Encoder options
|
|
10
|
+
// ---------------------------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
export interface EntityEncoderOptions {
|
|
13
|
+
/**
|
|
14
|
+
* Whether to encode XML unsafe characters: `&`, `<`, `>`, `"`, `'`.
|
|
15
|
+
* @default true
|
|
16
|
+
*/
|
|
17
|
+
encodeXmlSafe?: boolean;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Whether to encode non‑ASCII characters (e.g. `é` → `é`) using the
|
|
21
|
+
* built‑in named entity trie.
|
|
22
|
+
* @default true
|
|
23
|
+
*/
|
|
24
|
+
encodeAllNamed?: boolean;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Maximum number of replacements performed **cumulatively** across all
|
|
28
|
+
* `encode()` calls. `0` means unlimited.
|
|
29
|
+
*
|
|
30
|
+
* Use `reset()` to reset the internal counter.
|
|
31
|
+
* @default 0
|
|
32
|
+
*/
|
|
33
|
+
maxReplacements?: number;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
// EntityEncoder class
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* High‑performance encoder that replaces characters with XML/HTML entities.
|
|
42
|
+
*
|
|
43
|
+
* - Escapes XML unsafe characters (`&`, `<`, `>`, `"`, `'`) when `encodeXmlSafe` is true.
|
|
44
|
+
* - Replaces non‑ASCII characters (e.g. `é`, `©`) with named entities using
|
|
45
|
+
* a compact trie‑based lookup when `encodeAllNamed` is true.
|
|
46
|
+
* - Supports a cumulative replacement limit (`maxReplacements`) that persists
|
|
47
|
+
* across multiple `encode()` calls until `reset()` is called.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* const encoder = new EntityEncoder({ encodeXmlSafe: true, encodeAllNamed: true });
|
|
51
|
+
* encoder.encode('<foo>'); // "<foo>"
|
|
52
|
+
* encoder.encode('© 2025'); // "© 2025"
|
|
53
|
+
*
|
|
54
|
+
* // With limit
|
|
55
|
+
* const limited = new EntityEncoder({ maxReplacements: 2 });
|
|
56
|
+
* limited.encode('<>&'); // "<>&" (third replacement omitted)
|
|
57
|
+
* limited.reset(); // reset counter
|
|
58
|
+
*/
|
|
59
|
+
export class EntityEncoder {
|
|
60
|
+
constructor(options?: EntityEncoderOptions);
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Encode a string by replacing XML‑unsafe characters and (optionally)
|
|
64
|
+
* non‑ASCII characters with named entities.
|
|
65
|
+
*
|
|
66
|
+
* If `maxReplacements` is set and the cumulative limit has been reached,
|
|
67
|
+
* the input string is returned unchanged.
|
|
68
|
+
*
|
|
69
|
+
* @returns Encoded string (may be identical to input if no replacements needed
|
|
70
|
+
* or the limit has been exhausted).
|
|
71
|
+
*/
|
|
72
|
+
encode(str: string): string;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Reset the internal replacement counter.
|
|
76
|
+
* Does **not** change `encodeXmlSafe`, `encodeAllNamed`, or `maxReplacements`.
|
|
77
|
+
*/
|
|
78
|
+
reset(): void;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ---------------------------------------------------------------------------
|
|
82
|
+
// Constructor options for EntityDecoder (existing)
|
|
83
|
+
// ---------------------------------------------------------------------------
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Controls which entity categories count toward the expansion limits.
|
|
87
|
+
*
|
|
88
|
+
* - `'external'` — only untrusted / injected entities (default)
|
|
89
|
+
* - `'base'` — only built‑in XML entities + user‑supplied `namedEntities`
|
|
90
|
+
* - `'all'` — all entities regardless of tier
|
|
91
|
+
* - `string[]` — explicit combination, e.g. `['external', 'base']`
|
|
92
|
+
*/
|
|
93
|
+
export type ApplyLimitsTo = 'external' | 'base' | 'all' | Array<'external' | 'base'>;
|
|
94
|
+
|
|
95
|
+
export interface EntityDecoderLimitOptions {
|
|
96
|
+
/**
|
|
97
|
+
* Maximum number of entity references expanded **per document**.
|
|
98
|
+
* `0` means unlimited.
|
|
99
|
+
* @default 0
|
|
100
|
+
*/
|
|
101
|
+
maxTotalExpansions?: number;
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Maximum number of characters **added** by entity expansion per document.
|
|
105
|
+
* `0` means unlimited.
|
|
106
|
+
* @default 0
|
|
107
|
+
*/
|
|
108
|
+
maxExpandedLength?: number;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Which entity tiers count toward the expansion limits.
|
|
112
|
+
*
|
|
113
|
+
* - `'external'` (default) – only input/runtime + persistent external entities
|
|
114
|
+
* - `'base'` – only built‑in XML + `namedEntities`
|
|
115
|
+
* - `'all'` – every entity regardless of tier
|
|
116
|
+
* - `string[]` – explicit combination, e.g. `['external', 'base']`
|
|
117
|
+
*
|
|
118
|
+
* @default 'external'
|
|
119
|
+
*/
|
|
120
|
+
applyLimitsTo?: ApplyLimitsTo;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export interface EntityDecoderNCROptions {
|
|
124
|
+
/**
|
|
125
|
+
* XML version used for NCR classification.
|
|
126
|
+
* @default 1.0
|
|
127
|
+
*/
|
|
128
|
+
xmlVersion?: 1.0 | 1.1;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Base action for all numeric references.
|
|
132
|
+
* @default 'allow'
|
|
133
|
+
*/
|
|
134
|
+
onNCR?: 'allow' | 'leave' | 'remove' | 'throw';
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Action for null NCR (U+0000).
|
|
138
|
+
* @default 'remove'
|
|
139
|
+
*/
|
|
140
|
+
nullNCR?: 'remove' | 'throw';
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export interface EntityDecoderOptions {
|
|
144
|
+
/**
|
|
145
|
+
* Extra named entities merged into the **base map** (trusted, counts as `'base'` tier).
|
|
146
|
+
* These are combined with the built‑in XML entities (`lt`, `gt`, `quot`, `apos`).
|
|
147
|
+
* Values containing `&` are silently skipped to prevent recursive expansion.
|
|
148
|
+
*
|
|
149
|
+
* @default null
|
|
150
|
+
*/
|
|
151
|
+
namedEntities?: Record<string, string | { regex: RegExp; val: string | EntityValFn }> | null;
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Hook called once on the fully decoded string (after all replacements).
|
|
156
|
+
*
|
|
157
|
+
* - Receives `(resolved, original)` and **must return a string**.
|
|
158
|
+
* - To reject expansion, return `original`.
|
|
159
|
+
* - To sanitize, return a cleaned version of `resolved`.
|
|
160
|
+
*
|
|
161
|
+
* @example
|
|
162
|
+
* postCheck: (resolved, original) =>
|
|
163
|
+
* /<[a-z]/i.test(resolved) ? original : resolved
|
|
164
|
+
*/
|
|
165
|
+
postCheck?: ((resolved: string, original: string) => string) | null;
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Whether numeric character references (`&#NNN;`, `&#xHH;`) are allowed.
|
|
169
|
+
* @default true
|
|
170
|
+
*/
|
|
171
|
+
numericAllowed?: boolean;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Array of entity names or numeric references to leave unexpanded.
|
|
175
|
+
* @default []
|
|
176
|
+
*/
|
|
177
|
+
leave?: string[];
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Array of entity names or numeric references to remove.
|
|
181
|
+
* @default []
|
|
182
|
+
*/
|
|
183
|
+
remove?: string[];
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Security limits for entity expansion.
|
|
187
|
+
*/
|
|
188
|
+
limit?: EntityDecoderLimitOptions;
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Numeric Character Reference (NCR) policy.
|
|
192
|
+
*/
|
|
193
|
+
ncr?: EntityDecoderNCROptions;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// ---------------------------------------------------------------------------
|
|
197
|
+
// EntityDecoder class (default export)
|
|
198
|
+
// ---------------------------------------------------------------------------
|
|
199
|
+
|
|
200
|
+
/**
|
|
201
|
+
* Single‑pass, zero‑regex entity decoder for XML/HTML content.
|
|
202
|
+
*
|
|
203
|
+
* ## Entity lookup priority (highest → lowest)
|
|
204
|
+
* 1. **input / runtime** – injected via `addInputEntities()` (DOCTYPE per document)
|
|
205
|
+
* 2. **persistent external** – set via `setExternalEntities()` / `addExternalEntity()`
|
|
206
|
+
* 3. **base map** – built‑in XML entities + user‑supplied `namedEntities`
|
|
207
|
+
*
|
|
208
|
+
* Numeric references (`&#NNN;`, `&#xHH;`) are resolved directly and count as the `'base'` tier.
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* const decoder = new EntityDecoder({
|
|
212
|
+
* namedEntities: COMMON_HTML,
|
|
213
|
+
* maxTotalExpansions: 100
|
|
214
|
+
* });
|
|
215
|
+
* decoder.setExternalEntities({ brand: 'Acme' });
|
|
216
|
+
*
|
|
217
|
+
* decoder.addInputEntities({ version: '1.0' });
|
|
218
|
+
* decoder.decode('&brand; v&version; <'); // 'Acme v1.0 <'
|
|
219
|
+
*
|
|
220
|
+
* decoder.reset(); // clears input entities + counters, keeps external entities
|
|
221
|
+
*/
|
|
222
|
+
export default class EntityDecoder {
|
|
223
|
+
constructor(options?: EntityDecoderOptions);
|
|
224
|
+
|
|
225
|
+
setExternalEntities(
|
|
226
|
+
map: Record<string, string | { regex: RegExp; val: string | EntityValFn }>
|
|
227
|
+
): void;
|
|
228
|
+
|
|
229
|
+
addExternalEntity(key: string, value: string): void;
|
|
230
|
+
|
|
231
|
+
addInputEntities(
|
|
232
|
+
map: Record<
|
|
233
|
+
string,
|
|
234
|
+
| string
|
|
235
|
+
| { regx: RegExp; val: string | EntityValFn }
|
|
236
|
+
| { regex: RegExp; val: string | EntityValFn }
|
|
237
|
+
>
|
|
238
|
+
): void;
|
|
239
|
+
|
|
240
|
+
reset(): this;
|
|
241
|
+
|
|
242
|
+
decode(str: string): string;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// ---------------------------------------------------------------------------
|
|
246
|
+
// Named entity group exports (for use with `namedEntities` option)
|
|
247
|
+
// ---------------------------------------------------------------------------
|
|
248
|
+
|
|
249
|
+
export const COMMON_HTML: Record<string, string>;
|
|
250
|
+
export const ALL_ENTITIES: Record<string, string>;
|
|
251
|
+
export const XML: Record<string, string>;
|
|
252
|
+
export const BASIC_LATIN: Record<string, string>;
|
|
253
|
+
export const LATIN_ACCENTS: Record<string, string>;
|
|
254
|
+
export const LATIN_EXTENDED: Record<string, string>;
|
|
255
|
+
export const GREEK: Record<string, string>;
|
|
256
|
+
export const CYRILLIC: Record<string, string>;
|
|
257
|
+
export const MATH: Record<string, string>;
|
|
258
|
+
export const MATH_ADVANCED: Record<string, string>;
|
|
259
|
+
export const ARROWS: Record<string, string>;
|
|
260
|
+
export const SHAPES: Record<string, string>;
|
|
261
|
+
export const PUNCTUATION: Record<string, string>;
|
|
262
|
+
export const CURRENCY: Record<string, string>;
|
|
263
|
+
export const FRACTIONS: Record<string, string>;
|
|
264
|
+
export const MISC_SYMBOLS: Record<string, string>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @nodable/entities
|
|
3
|
+
*
|
|
4
|
+
* Standalone, zero-dependency XML/HTML entity replacement.
|
|
5
|
+
*
|
|
6
|
+
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { default as EntityDecoder } from './EntityDecoder.js';
|
|
10
|
+
export {
|
|
11
|
+
COMMON_HTML,
|
|
12
|
+
XML,
|
|
13
|
+
ALL_ENTITIES,
|
|
14
|
+
ARROWS,
|
|
15
|
+
BASIC_LATIN,
|
|
16
|
+
CURRENCY,
|
|
17
|
+
MATH,
|
|
18
|
+
MATH_ADVANCED,
|
|
19
|
+
CYRILLIC,
|
|
20
|
+
FRACTIONS,
|
|
21
|
+
GREEK,
|
|
22
|
+
LATIN_ACCENTS,
|
|
23
|
+
LATIN_EXTENDED,
|
|
24
|
+
MISC_SYMBOLS,
|
|
25
|
+
PUNCTUATION,
|
|
26
|
+
SHAPES,
|
|
27
|
+
} from './entities.js';
|
|
28
|
+
|
|
29
|
+
export { default as EntityEncoder } from './EntityEncoder.js';
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
**1.2.0** (2026-05-08)
|
|
5
|
+
- Add support for `sanitizeName` option
|
|
6
|
+
- Support xml-naming for validating and sanitizing tag and attribute names
|
|
7
|
+
|
|
8
|
+
**1.1.9** (2026-05-06)
|
|
9
|
+
- fix: format output for preserve order when indent by is set to empty string
|
|
10
|
+
|
|
11
|
+
**1.1.8** (2026-05-05)
|
|
12
|
+
- fix: skip text property for PI tags
|
|
13
|
+
- improve typings
|
|
14
|
+
|
|
15
|
+
**1.1.7** (2026--05-04)
|
|
16
|
+
- fix security issues when attribute value contains quotes
|
|
17
|
+
|
|
18
|
+
**1.1.6** (2026--05-04)
|
|
19
|
+
- fix security issues related to comment
|
|
20
|
+
- skip comment with null value
|
|
21
|
+
|
|
22
|
+
**1.1.5** (2026-04-17)
|
|
23
|
+
- fix security issues related to comment and cdata
|
|
24
|
+
|
|
25
|
+
**1.1.4** (2026-03-16)
|
|
26
|
+
- support maxNestedTags option
|
|
27
|
+
|
|
28
|
+
**1.1.3** (2026-03-13)
|
|
29
|
+
- declare Matcher & Expression as unknown so user is not forced to install path-expression-matcher
|
|
30
|
+
|
|
31
|
+
**1.1.2** (2026-03-11)
|
|
32
|
+
- fix typings
|
|
33
|
+
|
|
34
|
+
**1.1.1** (2026-03-11)
|
|
35
|
+
- upgrade path-expression-matcher to 1.1.3
|
|
36
|
+
|
|
37
|
+
**1.1.0** (2026-03-10)
|
|
38
|
+
|
|
39
|
+
- Integrate [path-expression-matcher](https://github.com/NaturalIntelligence/path-expression-matcher)
|
|
40
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Natural Intelligence
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# fast-xml-builder
|
|
2
|
+
Build XML from JSON
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
XML Builder was part of [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) for years. But considering that any bug in the parser may false-alarm users who are only using the builder, we have decided to split it into a separate package.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install fast-xml-builder
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```javascript
|
|
16
|
+
import XMLBuilder from 'fast-xml-builder';
|
|
17
|
+
|
|
18
|
+
const builder = new XMLBuilder();
|
|
19
|
+
const xml = builder.build({ name: 'value' });
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
fast-xml-builder fully supports the response generated by fast-xml-parser. You can use options like `preserveOrder`, `ignoreAttributes`, `attributeNamePrefix`, `textNodeName`, `cdataPropName`, `commentPropName`, `format`, `indentBy`, `suppressEmptyNode`, `suppressUnpairedNode`, `stopNodes`, `oneListGroup`, `maxNestedTags`, and many more.
|
|
23
|
+
|
|
24
|
+
## Default Options
|
|
25
|
+
|
|
26
|
+
```js
|
|
27
|
+
{
|
|
28
|
+
attributeNamePrefix: '@_',
|
|
29
|
+
attributesGroupName: false,
|
|
30
|
+
textNodeName: '#text',
|
|
31
|
+
ignoreAttributes: true,
|
|
32
|
+
cdataPropName: false,
|
|
33
|
+
commentPropName: false,
|
|
34
|
+
format: false,
|
|
35
|
+
indentBy: ' ',
|
|
36
|
+
suppressEmptyNode: false,
|
|
37
|
+
suppressUnpairedNode: true,
|
|
38
|
+
suppressBooleanAttributes: true,
|
|
39
|
+
preserveOrder: false,
|
|
40
|
+
processEntities: true,
|
|
41
|
+
unpairedTags: [],
|
|
42
|
+
stopNodes: [],
|
|
43
|
+
oneListGroup: false,
|
|
44
|
+
maxNestedTags: 100,
|
|
45
|
+
jPath: true,
|
|
46
|
+
tagValueProcessor: (key, val) => val,
|
|
47
|
+
attributeValueProcessor: (attrName, val) => val,
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Options Reference
|
|
52
|
+
|
|
53
|
+
Check [Options reference](docs/Builder_v1.md) for more detail and examples.
|
|
54
|
+
|
|
55
|
+
- **arrayNodeName**: When building XML from an array, set `arrayNodeName` to wrap each element in a tag name.
|
|
56
|
+
- **attributeNamePrefix**: Prefix used to identify attribute properties in the JS object. Default: `'@_'`.
|
|
57
|
+
- **attributesGroupName**: Group name for attributes in the JS object. When set, all attributes are expected to be nested under this key. Not supported with `preserveOrder: true`.
|
|
58
|
+
- **attributeValueProcessor**: Customize how attribute values are serialized. Receives the attribute name and value.
|
|
59
|
+
- **cdataPropName**: Property name that identifies CDATA content. Values under this key are wrapped in `<![CDATA[...]]>`.
|
|
60
|
+
- **commentPropName**: Property name that identifies comment content. Values under this key are rendered as `<!-- ... -->`.
|
|
61
|
+
- **format**: By default, output is a single-line XML string. Set `format: true` for human-readable, indented output.
|
|
62
|
+
- **ignoreAttributes**: By default (`true`), attributes are skipped. Set to `false` to include them. Also supports selective ignoring via an array of strings, array of regular expressions, or a callback function.
|
|
63
|
+
- **indentBy**: String used for each level of indentation. Default: `' '` (two spaces). Only applies when `format: true`.
|
|
64
|
+
- **maxNestedTags**: Limits the maximum depth of nested tags. An error is thrown if this depth is exceeded. Default: `100`.
|
|
65
|
+
- **oneListGroup**: Groups all repeated child tags under a single parent tag.
|
|
66
|
+
- **preserveOrder**: When a JS object was produced by XMLParser with `preserveOrder: true`, pass the same option to XMLBuilder to reconstruct the original XML correctly.
|
|
67
|
+
- **processEntities**: When `true` (default), special characters in text and attribute values are replaced with XML entities (`&`, `<`, etc.). Set to `false` for a performance boost when you know your content has no entities. Note: quotes in attribute values are always escaped regardless of this setting.
|
|
68
|
+
- **stopNodes**: Tags listed here are treated as raw content containers — their text content is written as-is without entity encoding. Accepts an array of tag name strings or `Expression` instances from `path-expression-matcher`. The old `*.tagName` wildcard syntax is still accepted and automatically converted to the equivalent `..tagName` deep-wildcard syntax.
|
|
69
|
+
- **suppressBooleanAttributes**: When `true` (default), attributes with the value `true` are rendered without the value (e.g. `<tag attr>` instead of `<tag attr="true">`).
|
|
70
|
+
- **suppressEmptyNode**: When `true`, tags with no text value are rendered as self-closing (`<tag/>`).
|
|
71
|
+
- **suppressUnpairedNode**: When `true` (default), unpaired tags are rendered without a closing slash (`<br>`). When `false`, they are rendered as `<br/>`.
|
|
72
|
+
- **tagValueProcessor**: Customize how tag text values are serialized. Receives the tag name and value.
|
|
73
|
+
- **textNodeName**: Property name representing the text content of a tag in the JS object. Default: `'#text'`.
|
|
74
|
+
- **unpairedTags**: List of tag names that have no matching closing tag (e.g. `<br>` in HTML).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(()=>{"use strict";var t={d:(e,i)=>{for(var s in i)t.o(i,s)&&!t.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:i[s]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{default:()=>w});class i{constructor(t,e={},i){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this.data=i,this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let i=0,s="";for(;i<t.length;)t[i]===this.separator?i+1<t.length&&t[i+1]===this.separator?(s.trim()&&(e.push(this._parseSegment(s.trim())),s=""),e.push({type:"deep-wildcard"}),i+=2):(s.trim()&&e.push(this._parseSegment(s.trim())),s="",i++):(s+=t[i],i++);return s.trim()&&e.push(this._parseSegment(s.trim())),e}_parseSegment(t){const e={type:"tag"};let i=null,s=t;const n=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(n&&(s=n[1]+n[3],n[2])){const t=n[2].slice(1,-1);t&&(i=t)}let r,o,a=s;if(s.includes("::")){const e=s.indexOf("::");if(r=s.substring(0,e).trim(),a=s.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let h=null;if(a.includes(":")){const t=a.lastIndexOf(":"),e=a.substring(0,t).trim(),i=a.substring(t+1).trim();["first","last","odd","even"].includes(i)||/^nth\(\d+\)$/.test(i)?(o=e,h=i):o=a}else o=a;if(!o)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=o,r&&(e.namespace=r),i)if(i.includes("=")){const t=i.indexOf("=");e.attrName=i.substring(0,t).trim(),e.attrValue=i.substring(t+1).trim()}else e.attrName=i.trim();if(h){const t=h.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=h}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}class s{constructor(t){this._matcher=t}get separator(){return this._matcher.separator}getCurrentTag(){const t=this._matcher.path;return t.length>0?t[t.length-1].tag:void 0}getCurrentNamespace(){const t=this._matcher.path;return t.length>0?t[t.length-1].namespace:void 0}getAttrValue(t){const e=this._matcher.path;if(0!==e.length)return e[e.length-1].values?.[t]}hasAttr(t){const e=this._matcher.path;if(0===e.length)return!1;const i=e[e.length-1];return void 0!==i.values&&t in i.values}getPosition(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].position??0}getCounter(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this._matcher.path.length}toString(t,e=!0){return this._matcher.toString(t,e)}toArray(){return this._matcher.path.map(t=>t.tag)}matches(t){return this._matcher.matches(t)}matchesAny(t){return t.matchesAny(this._matcher)}}class n{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[],this._pathStringCache=null,this._view=new s(this)}push(t,e=null,i=null){this._pathStringCache=null,this.path.length>0&&(this.path[this.path.length-1].values=void 0);const s=this.path.length;this.siblingStacks[s]||(this.siblingStacks[s]=new Map);const n=this.siblingStacks[s],r=i?`${i}:${t}`:t,o=n.get(r)||0;let a=0;for(const t of n.values())a+=t;n.set(r,o+1);const h={tag:t,position:a,counter:o};null!=i&&(h.namespace=i),null!=e&&(h.values=e),this.path.push(h)}pop(){if(0===this.path.length)return;this._pathStringCache=null;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0!==this.path.length)return this.path[this.path.length-1].values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const i=t||this.separator;if(i===this.separator&&!0===e){if(null!==this._pathStringCache)return this._pathStringCache;const t=this.path.map(t=>t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(i);return this._pathStringCache=t,t}return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(i)}toArray(){return this.path.map(t=>t.tag)}reset(){this._pathStringCache=null,this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++)if(!this._matchSegment(t[e],this.path[e],e===this.path.length-1))return!1;return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,i=t.length-1;for(;i>=0&&e>=0;){const s=t[i];if("deep-wildcard"===s.type){if(i--,i<0)return!0;const s=t[i];let n=!1;for(let t=e;t>=0;t--)if(this._matchSegment(s,this.path[t],t===this.path.length-1)){e=t-1,i--,n=!0;break}if(!n)return!1}else{if(!this._matchSegment(s,this.path[e],e===this.path.length-1))return!1;e--,i--}}return i<0}_matchSegment(t,e,i){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!i)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue&&String(e.values[t.attrName])!==String(t.attrValue))return!1}if(void 0!==t.position){if(!i)return!1;const s=e.counter??0;if("first"===t.position&&0!==s)return!1;if("odd"===t.position&&s%2!=1)return!1;if("even"===t.position&&s%2!=0)return!1;if("nth"===t.position&&s!==t.positionValue)return!1}return!0}matchesAny(t){return t.matchesAny(this)}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this._pathStringCache=null,this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return this._view}}function r(t){return String(t).replace(/--/g,"- -").replace(/--/g,"- -").replace(/-$/,"- ")}function o(t){return String(t).replace(/\]\]>/g,"]]]]><![CDATA[>")}function a(t){return String(t).replace(/"/g,""").replace(/'/g,"'")}const h=":A-Za-z_À-ÖØ-öø-˿Ͱ-ͽͿ-҆҈--⁰-Ⰰ-、-豈-﷏ﷰ-�",p=":A-Za-z_À-˿Ͱ-ͽͿ-҆҈--⁰-Ⰰ-、-豈-﷏ﷰ-�𐀀-",u=p+"\\-\\.\\d·̀-ͯ҇‿-⁀",l=(t,e,i="")=>{const s=`[${t.replace(":","")}][${e.replace(":","")}]*`;return{name:new RegExp(`^[${t}][${e}]*$`,i),ncName:new RegExp(`^${s}$`,i),qName:new RegExp(`^${s}(?::${s})?$`,i),nmToken:new RegExp(`^[${e}]+$`,i),nmTokens:new RegExp(`^[${e}]+(?:\\s+[${e}]+)*$`,i)}},c=l(h,h+"\\-\\.\\d·̀-ͯ‿-⁀"),g=l(p,u,"u"),d=(t,{xmlVersion:e="1.0"}={})=>((t="1.0")=>"1.1"===t?g:c)(e).qName.test(t);function f(t,e,i,s,n){return i.sanitizeName?d(t,{xmlVersion:n})?t:i.sanitizeName(t,{isAttribute:e,matcher:s.readOnly()}):t}function m(t,e){let s="";e.format&&(s="\n");const r=[];if(e.stopNodes&&Array.isArray(e.stopNodes))for(let t=0;t<e.stopNodes.length;t++){const s=e.stopNodes[t];"string"==typeof s?r.push(new i(s)):s instanceof i&&r.push(s)}const o=function(t,e){if(!Array.isArray(t)||0===t.length)return"1.0";const i=t[0];if("?xml"===A(i)){const t=i[":@"];if(t){const i=e.attributeNamePrefix+"version";if(t[i])return t[i]}}return"1.0"}(t,e);return N(t,e,s,new n,r,o)}function N(t,e,i,s,n,a){let h="",p=!1;if(e.maxNestedTags&&s.getDepth()>e.maxNestedTags)throw new Error("Maximum nested tags exceeded");if(!Array.isArray(t)){if(null!=t){let i=t.toString();return i=S(i,e),i}return""}for(let u=0;u<t.length;u++){const l=t[u],c=A(l);if(void 0===c)continue;const g=c===e.textNodeName||c===e.cdataPropName||c===e.commentPropName||"?"===c[0]?c:f(c,!1,e,s,a),d=b(l[":@"],e);s.push(g,d);const m=P(s,n);if(g===e.textNodeName){let t=l[c];m||(t=e.tagValueProcessor(g,t),t=S(t,e)),p&&(h+=i),h+=t,p=!1,s.pop();continue}if(g===e.cdataPropName){p&&(h+=i),h+=`<![CDATA[${o(l[c][0][e.textNodeName])}]]>`,p=!1,s.pop();continue}if(g===e.commentPropName){h+=i+`\x3c!--${r(l[c][0][e.textNodeName])}--\x3e`,p=!0,s.pop();continue}if("?"===g[0]){h+=("?xml"===g?"":i)+`<${g}${$(l[":@"],e,m,s,a)}?>`,p=!0,s.pop();continue}let y=i;""!==y&&(y+=e.indentBy);const v=i+`<${g}${$(l[":@"],e,m,s,a)}`;let w;w=m?x(l[c],e):N(l[c],e,y,s,n,a),-1!==e.unpairedTags.indexOf(g)?e.suppressUnpairedNode?h+=v+">":h+=v+"/>":w&&0!==w.length||!e.suppressEmptyNode?w&&w.endsWith(">")?h+=v+`>${w}${i}</${g}>`:(h+=v+">",w&&""!==i&&(w.includes("/>")||w.includes("</"))?h+=i+e.indentBy+w+i:h+=w,h+=`</${g}>`):h+=v+"/>",p=!0,s.pop()}return h}function b(t,e){if(!t||e.ignoreAttributes)return null;const i={};let s=!1;for(let n in t)Object.prototype.hasOwnProperty.call(t,n)&&(i[n.startsWith(e.attributeNamePrefix)?n.substr(e.attributeNamePrefix.length):n]=a(t[n]),s=!0);return s?i:null}function x(t,e){if(!Array.isArray(t))return null!=t?t.toString():"";let i="";for(let s=0;s<t.length;s++){const n=t[s],r=A(n);if(r===e.textNodeName)i+=n[r];else if(r===e.cdataPropName)i+=n[r][0][e.textNodeName];else if(r===e.commentPropName)i+=n[r][0][e.textNodeName];else{if(r&&"?"===r[0])continue;if(r){const t=y(n[":@"],e),s=x(n[r],e);s&&0!==s.length?i+=`<${r}${t}>${s}</${r}>`:i+=`<${r}${t}/>`}}}return i}function y(t,e){let i="";if(t&&!e.ignoreAttributes)for(let s in t){if(!Object.prototype.hasOwnProperty.call(t,s))continue;let n=t[s];!0===n&&e.suppressBooleanAttributes?i+=` ${s.substr(e.attributeNamePrefix.length)}`:i+=` ${s.substr(e.attributeNamePrefix.length)}="${a(n)}"`}return i}function A(t){const e=Object.keys(t);for(let i=0;i<e.length;i++){const s=e[i];if(Object.prototype.hasOwnProperty.call(t,s)&&":@"!==s)return s}}function $(t,e,i,s,n){let r="";if(t&&!e.ignoreAttributes)for(let o in t){if(!Object.prototype.hasOwnProperty.call(t,o))continue;const h=o.substr(e.attributeNamePrefix.length),p=i?h:f(h,!0,e,s,n);let u;i?u=t[o]:(u=e.attributeValueProcessor(o,t[o]),u=S(u,e)),!0===u&&e.suppressBooleanAttributes?r+=` ${p}`:r+=` ${p}="${a(u)}"`}return r}function P(t,e){if(!e||0===e.length)return!1;for(let i=0;i<e.length;i++)if(t.matches(e[i]))return!0;return!1}function S(t,e){if(t&&t.length>0&&e.processEntities)for(let i=0;i<e.entities.length;i++){const s=e.entities[i];t=t.replace(s.regex,s.val)}return t}const v={attributeNamePrefix:"@_",attributesGroupName:!1,textNodeName:"#text",ignoreAttributes:!0,cdataPropName:!1,format:!1,indentBy:" ",suppressEmptyNode:!1,suppressUnpairedNode:!0,suppressBooleanAttributes:!0,tagValueProcessor:function(t,e){return e},attributeValueProcessor:function(t,e){return e},preserveOrder:!1,commentPropName:!1,unpairedTags:[],entities:[{regex:new RegExp("&","g"),val:"&"},{regex:new RegExp(">","g"),val:">"},{regex:new RegExp("<","g"),val:"<"},{regex:new RegExp("'","g"),val:"'"},{regex:new RegExp('"',"g"),val:"""}],processEntities:!0,stopNodes:[],oneListGroup:!1,maxNestedTags:100,jPath:!0,sanitizeName:!1};function w(t){if(this.options=Object.assign({},v,t),this.options.stopNodes&&Array.isArray(this.options.stopNodes)&&(this.options.stopNodes=this.options.stopNodes.map(t=>"string"==typeof t&&t.startsWith("*.")?".."+t.substring(2):t)),this.stopNodeExpressions=[],this.options.stopNodes&&Array.isArray(this.options.stopNodes))for(let t=0;t<this.options.stopNodes.length;t++){const e=this.options.stopNodes[t];"string"==typeof e?this.stopNodeExpressions.push(new i(e)):e instanceof i&&this.stopNodeExpressions.push(e)}var e;!0===this.options.ignoreAttributes||this.options.attributesGroupName?this.isAttribute=function(){return!1}:(this.ignoreAttributesFn="function"==typeof(e=this.options.ignoreAttributes)?e:Array.isArray(e)?t=>{for(const i of e){if("string"==typeof i&&t===i)return!0;if(i instanceof RegExp&&i.test(t))return!0}}:()=>!1,this.attrPrefixLen=this.options.attributeNamePrefix.length,this.isAttribute=C),this.processTextOrObjNode=O,this.options.format?(this.indentate=_,this.tagEndChar=">\n",this.newLine="\n"):(this.indentate=function(){return""},this.tagEndChar=">",this.newLine="")}function E(t,e,i,s,n){return i.sanitizeName?d(t,{xmlVersion:n})?t:i.sanitizeName(t,{isAttribute:e,matcher:s.readOnly()}):t}function O(t,e,i,s,n){const r=this.extractAttributes(t);if(s.push(e,r),this.checkStopNode(s)){const n=this.buildRawContent(t),r=this.buildAttributesForStopNode(t);return s.pop(),this.buildObjectNode(n,e,r,i)}const o=this.j2x(t,i+1,s,n);return s.pop(),"?"===e[0]?this.buildTextValNode("",e,o.attrStr,i,s):void 0!==t[this.options.textNodeName]&&1===Object.keys(t).length?this.buildTextValNode(t[this.options.textNodeName],e,o.attrStr,i,s):this.buildObjectNode(o.val,e,o.attrStr,i)}function _(t){return this.options.indentBy.repeat(t)}function C(t){return!(!t.startsWith(this.options.attributeNamePrefix)||t===this.options.textNodeName)&&t.substr(this.attrPrefixLen)}w.prototype.build=function(t){if(this.options.preserveOrder)return m(t,this.options);{Array.isArray(t)&&this.options.arrayNodeName&&this.options.arrayNodeName.length>1&&(t={[this.options.arrayNodeName]:t});const e=new n,i=function(t,e){const i=t["?xml"];if(i&&"object"==typeof i){if(e.attributesGroupName&&i[e.attributesGroupName]){const t=i[e.attributesGroupName][e.attributeNamePrefix+"version"];if(t)return t}const t=i[e.attributeNamePrefix+"version"];if(t)return t}return"1.0"}(t,this.options);return this.j2x(t,0,e,i).val}},w.prototype.j2x=function(t,e,i,s){let n="",r="";if(this.options.maxNestedTags&&i.getDepth()>=this.options.maxNestedTags)throw new Error("Maximum nested tags exceeded");const o=this.options.jPath?i.toString():i,a=this.checkStopNode(i);for(let h in t){if(!Object.prototype.hasOwnProperty.call(t,h))continue;const p=h===this.options.textNodeName||h===this.options.cdataPropName||h===this.options.commentPropName||this.options.attributesGroupName&&h===this.options.attributesGroupName||this.isAttribute(h)||"?"===h[0]?h:E(h,!1,this.options,i,s);if(void 0===t[h])this.isAttribute(h)&&(r+="");else if(null===t[h])this.isAttribute(h)||p===this.options.cdataPropName||p===this.options.commentPropName?r+="":"?"===p[0]?r+=this.indentate(e)+"<"+p+"?"+this.tagEndChar:r+=this.indentate(e)+"<"+p+"/"+this.tagEndChar;else if(t[h]instanceof Date)r+=this.buildTextValNode(t[h],p,"",e,i);else if("object"!=typeof t[h]){const u=this.isAttribute(h);if(u&&!this.ignoreAttributesFn(u,o)){const e=E(u,!0,this.options,i,s);n+=this.buildAttrPairStr(e,""+t[h],a)}else if(!u)if(h===this.options.textNodeName){let e=this.options.tagValueProcessor(h,""+t[h]);r+=this.replaceEntitiesValue(e)}else{i.push(p);const s=this.checkStopNode(i);if(i.pop(),s){const i=""+t[h];r+=""===i?this.indentate(e)+"<"+p+this.closeTag(p)+this.tagEndChar:this.indentate(e)+"<"+p+">"+i+"</"+p+this.tagEndChar}else r+=this.buildTextValNode(t[h],p,"",e,i)}}else if(Array.isArray(t[h])){const n=t[h].length;let o="",a="";for(let u=0;u<n;u++){const n=t[h][u];if(void 0===n);else if(null===n)"?"===p[0]?r+=this.indentate(e)+"<"+p+"?"+this.tagEndChar:r+=this.indentate(e)+"<"+p+"/"+this.tagEndChar;else if("object"==typeof n)if(this.options.oneListGroup){i.push(p);const t=this.j2x(n,e+1,i,s);i.pop(),o+=t.val,this.options.attributesGroupName&&n.hasOwnProperty(this.options.attributesGroupName)&&(a+=t.attrStr)}else o+=this.processTextOrObjNode(n,p,e,i,s);else if(this.options.oneListGroup){let t=this.options.tagValueProcessor(p,n);t=this.replaceEntitiesValue(t),o+=t}else{i.push(p);const t=this.checkStopNode(i);if(i.pop(),t){const t=""+n;o+=""===t?this.indentate(e)+"<"+p+this.closeTag(p)+this.tagEndChar:this.indentate(e)+"<"+p+">"+t+"</"+p+this.tagEndChar}else o+=this.buildTextValNode(n,p,"",e,i)}}this.options.oneListGroup&&(o=this.buildObjectNode(o,p,a,e)),r+=o}else if(this.options.attributesGroupName&&h===this.options.attributesGroupName){const e=Object.keys(t[h]),r=e.length;for(let o=0;o<r;o++){const r=E(e[o],!0,this.options,i,s);n+=this.buildAttrPairStr(r,""+t[h][e[o]],a)}}else r+=this.processTextOrObjNode(t[h],p,e,i,s)}return{attrStr:n,val:r}},w.prototype.buildAttrPairStr=function(t,e,i){return i||(e=this.options.attributeValueProcessor(t,""+e),e=this.replaceEntitiesValue(e)),this.options.suppressBooleanAttributes&&"true"===e?" "+t:" "+t+'="'+a(e)+'"'},w.prototype.extractAttributes=function(t){if(!t||"object"!=typeof t)return null;const e={};let i=!1;if(this.options.attributesGroupName&&t[this.options.attributesGroupName]){const s=t[this.options.attributesGroupName];for(let t in s)Object.prototype.hasOwnProperty.call(s,t)&&(e[t.startsWith(this.options.attributeNamePrefix)?t.substring(this.options.attributeNamePrefix.length):t]=a(s[t]),i=!0)}else for(let s in t){if(!Object.prototype.hasOwnProperty.call(t,s))continue;const n=this.isAttribute(s);n&&(e[n]=a(t[s]),i=!0)}return i?e:null},w.prototype.buildRawContent=function(t){if("string"==typeof t)return t;if("object"!=typeof t||null===t)return String(t);if(void 0!==t[this.options.textNodeName])return t[this.options.textNodeName];let e="";for(let i in t){if(!Object.prototype.hasOwnProperty.call(t,i))continue;if(this.isAttribute(i))continue;if(this.options.attributesGroupName&&i===this.options.attributesGroupName)continue;const s=t[i];if(i===this.options.textNodeName)e+=s;else if(Array.isArray(s)){for(let t of s)if("string"==typeof t||"number"==typeof t)e+=`<${i}>${t}</${i}>`;else if("object"==typeof t&&null!==t){const s=this.buildRawContent(t),n=this.buildAttributesForStopNode(t);e+=""===s?`<${i}${n}/>`:`<${i}${n}>${s}</${i}>`}}else if("object"==typeof s&&null!==s){const t=this.buildRawContent(s),n=this.buildAttributesForStopNode(s);e+=""===t?`<${i}${n}/>`:`<${i}${n}>${t}</${i}>`}else e+=`<${i}>${s}</${i}>`}return e},w.prototype.buildAttributesForStopNode=function(t){if(!t||"object"!=typeof t)return"";let e="";if(this.options.attributesGroupName&&t[this.options.attributesGroupName]){const i=t[this.options.attributesGroupName];for(let t in i){if(!Object.prototype.hasOwnProperty.call(i,t))continue;const s=t.startsWith(this.options.attributeNamePrefix)?t.substring(this.options.attributeNamePrefix.length):t,n=i[t];!0===n&&this.options.suppressBooleanAttributes?e+=" "+s:e+=" "+s+'="'+n+'"'}}else for(let i in t){if(!Object.prototype.hasOwnProperty.call(t,i))continue;const s=this.isAttribute(i);if(s){const n=t[i];!0===n&&this.options.suppressBooleanAttributes?e+=" "+s:e+=" "+s+'="'+n+'"'}}return e},w.prototype.buildObjectNode=function(t,e,i,s){if(""===t)return"?"===e[0]?this.indentate(s)+"<"+e+i+"?"+this.tagEndChar:this.indentate(s)+"<"+e+i+this.closeTag(e)+this.tagEndChar;if("?"===e[0])return this.indentate(s)+"<"+e+i+"?"+this.tagEndChar;{let n="</"+e+this.tagEndChar,r="";return"?"===e[0]&&(r="?",n=""),!i&&""!==i||-1!==t.indexOf("<")?!1!==this.options.commentPropName&&e===this.options.commentPropName&&0===r.length?this.indentate(s)+`\x3c!--${t}--\x3e`+this.newLine:this.indentate(s)+"<"+e+i+r+this.tagEndChar+t+this.indentate(s)+n:this.indentate(s)+"<"+e+i+r+">"+t+n}},w.prototype.closeTag=function(t){let e="";return-1!==this.options.unpairedTags.indexOf(t)?this.options.suppressUnpairedNode||(e="/"):e=this.options.suppressEmptyNode?"/":`></${t}`,e},w.prototype.checkStopNode=function(t){if(!this.stopNodeExpressions||0===this.stopNodeExpressions.length)return!1;for(let e=0;e<this.stopNodeExpressions.length;e++)if(t.matches(this.stopNodeExpressions[e]))return!0;return!1},w.prototype.buildTextValNode=function(t,e,i,s,n){if(!1!==this.options.cdataPropName&&e===this.options.cdataPropName){const e=o(t);return this.indentate(s)+`<![CDATA[${e}]]>`+this.newLine}if(!1!==this.options.commentPropName&&e===this.options.commentPropName){const e=r(t);return this.indentate(s)+`\x3c!--${e}--\x3e`+this.newLine}if("?"===e[0])return this.indentate(s)+"<"+e+i+"?"+this.tagEndChar;{let n=this.options.tagValueProcessor(e,t);return n=this.replaceEntitiesValue(n),""===n?this.indentate(s)+"<"+e+i+this.closeTag(e)+this.tagEndChar:this.indentate(s)+"<"+e+i+">"+n+"</"+e+this.tagEndChar}},w.prototype.replaceEntitiesValue=function(t){if(t&&t.length>0&&this.options.processEntities)for(let e=0;e<this.options.entities.length;e++){const i=this.options.entities[e];t=t.replace(i.regex,i.val)}return t},module.exports=e})();
|