@depup/fast-xml-parser 5.5.11-depup.1 → 5.10.1-depup.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/CHANGELOG.md +79 -0
- package/README.md +3 -3
- package/changes.json +4 -4
- package/lib/fxbuilder.min.js +1 -1
- package/lib/fxbuilder.min.js.map +1 -1
- package/lib/fxp.cjs +1 -1
- package/lib/fxp.d.cts +40 -11
- package/lib/fxp.min.js +1 -1
- package/lib/fxp.min.js.map +1 -1
- package/lib/fxparser.min.js +1 -1
- package/lib/fxparser.min.js.map +1 -1
- package/package.json +14 -14
- package/src/fxp.d.ts +50 -17
- package/src/xmlparser/DocTypeReader.js +16 -15
- package/src/xmlparser/OptionsBuilder.js +13 -8
- package/src/xmlparser/OrderedObjParser.js +59 -132
- package/src/xmlparser/XMLParser.js +2 -2
- package/src/xmlparser/node2json.js +4 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@depup/fast-xml-parser",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.10.1-depup.0",
|
|
4
4
|
"description": "Validate XML, Parse XML, Build XML without C/C++ based libraries (with updated dependencies)",
|
|
5
5
|
"main": "./lib/fxp.cjs",
|
|
6
6
|
"type": "module",
|
|
@@ -23,13 +23,11 @@
|
|
|
23
23
|
"test": "c8 --reporter=lcov --reporter=text jasmine spec/*spec.js",
|
|
24
24
|
"test-types": "tsc --noEmit spec/typings/typings-test.ts",
|
|
25
25
|
"unit": "jasmine",
|
|
26
|
-
"coverage": "nyc report --reporter html --reporter text -t .nyc_output --report-dir .nyc_output/summary",
|
|
27
26
|
"perf": "node ./benchmark/perfTest3.js",
|
|
28
27
|
"lint": "eslint src/**/*.js spec/**/*.js benchmark/**/*.js",
|
|
29
28
|
"bundle": "webpack --config webpack.cjs.config.js",
|
|
30
29
|
"prettier": "prettier --write src/**/*.js",
|
|
31
|
-
"
|
|
32
|
-
"publish-please": "publish-please"
|
|
30
|
+
"preversion": "npm test"
|
|
33
31
|
},
|
|
34
32
|
"bin": {
|
|
35
33
|
"fxparser": "src/cli/cli.js"
|
|
@@ -75,14 +73,13 @@
|
|
|
75
73
|
"@babel/plugin-transform-runtime": "^7.13.10",
|
|
76
74
|
"@babel/preset-env": "^7.13.10",
|
|
77
75
|
"@babel/register": "^7.13.8",
|
|
76
|
+
"@byspec/xml": "^0.1.0",
|
|
78
77
|
"@types/node": "20",
|
|
79
78
|
"babel-loader": "^8.2.2",
|
|
80
79
|
"c8": "^10.1.3",
|
|
81
80
|
"eslint": "^8.3.0",
|
|
82
|
-
"he": "^1.2.0",
|
|
83
81
|
"jasmine": "^5.6.0",
|
|
84
82
|
"prettier": "^3.5.1",
|
|
85
|
-
"publish-please": "^5.5.2",
|
|
86
83
|
"typescript": "5",
|
|
87
84
|
"webpack": "^5.64.4",
|
|
88
85
|
"webpack-cli": "^4.9.1"
|
|
@@ -94,21 +91,24 @@
|
|
|
94
91
|
}
|
|
95
92
|
],
|
|
96
93
|
"dependencies": {
|
|
97
|
-
"
|
|
98
|
-
"
|
|
99
|
-
"
|
|
94
|
+
"@nodable/entities": "^3.0.0",
|
|
95
|
+
"fast-xml-builder": "^1.3.0",
|
|
96
|
+
"is-unsafe": "^2.0.0",
|
|
97
|
+
"path-expression-matcher": "^1.6.2",
|
|
98
|
+
"strnum": "^2.4.1",
|
|
99
|
+
"xml-naming": "^0.3.0"
|
|
100
100
|
},
|
|
101
101
|
"depup": {
|
|
102
102
|
"changes": {
|
|
103
|
-
"
|
|
104
|
-
"from": "^1.
|
|
105
|
-
"to": "^1.
|
|
103
|
+
"fast-xml-builder": {
|
|
104
|
+
"from": "^1.2.0",
|
|
105
|
+
"to": "^1.3.0"
|
|
106
106
|
}
|
|
107
107
|
},
|
|
108
108
|
"depsUpdated": 1,
|
|
109
109
|
"originalPackage": "fast-xml-parser",
|
|
110
|
-
"originalVersion": "5.
|
|
111
|
-
"processedAt": "2026-
|
|
110
|
+
"originalVersion": "5.10.1",
|
|
111
|
+
"processedAt": "2026-07-21T16:14:33.562Z",
|
|
112
112
|
"smokeTest": "passed"
|
|
113
113
|
}
|
|
114
114
|
}
|
package/src/fxp.d.ts
CHANGED
|
@@ -66,20 +66,23 @@ export class Expression {
|
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
// ---------------------------------------------------------------------------
|
|
69
|
-
//
|
|
69
|
+
// MatcherView
|
|
70
70
|
// ---------------------------------------------------------------------------
|
|
71
71
|
|
|
72
72
|
/**
|
|
73
|
-
* A live read-only view of a Matcher instance
|
|
73
|
+
* A lightweight, live read-only view of a Matcher instance.
|
|
74
74
|
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
*
|
|
75
|
+
* Returned by `Matcher.readOnly()`. The same instance is reused across every
|
|
76
|
+
* callback invocation — no allocation overhead per call. Reads directly from
|
|
77
|
+
* the parent Matcher's internal state so it always reflects the current parser
|
|
78
|
+
* position with no copying or freezing.
|
|
79
|
+
*
|
|
80
|
+
* Mutation methods (`push`, `pop`, `reset`, `updateCurrent`, `restore`) are
|
|
81
|
+
* simply absent — misuse is caught at compile time by TypeScript.
|
|
79
82
|
*
|
|
80
83
|
* This is the type received by all FXP user callbacks when `jPath: false`.
|
|
81
84
|
*/
|
|
82
|
-
export
|
|
85
|
+
export class MatcherView {
|
|
83
86
|
readonly separator: string;
|
|
84
87
|
|
|
85
88
|
/** Check if current path matches an Expression. */
|
|
@@ -111,14 +114,14 @@ export interface ReadonlyMatcher {
|
|
|
111
114
|
|
|
112
115
|
/** Current path as an array of tag names. */
|
|
113
116
|
toArray(): string[];
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* Create a snapshot of the current state.
|
|
117
|
-
* The snapshot can be passed to the real Matcher.restore if needed.
|
|
118
|
-
*/
|
|
119
|
-
snapshot(): MatcherSnapshot;
|
|
120
117
|
}
|
|
121
118
|
|
|
119
|
+
/**
|
|
120
|
+
* @deprecated Use {@link MatcherView} instead.
|
|
121
|
+
* Alias kept for backward compatibility.
|
|
122
|
+
*/
|
|
123
|
+
export type ReadonlyMatcher = MatcherView;
|
|
124
|
+
|
|
122
125
|
/** Internal node structure — exposed via snapshot only. */
|
|
123
126
|
export interface PathNode {
|
|
124
127
|
tag: string;
|
|
@@ -141,8 +144,8 @@ export interface MatcherSnapshot {
|
|
|
141
144
|
**********************************************************************/
|
|
142
145
|
|
|
143
146
|
// jPath: true → string
|
|
144
|
-
// jPath: false →
|
|
145
|
-
type JPathOrMatcher = string |
|
|
147
|
+
// jPath: false → MatcherView
|
|
148
|
+
type JPathOrMatcher = string | MatcherView;
|
|
146
149
|
type JPathOrExpression = string | Expression;
|
|
147
150
|
|
|
148
151
|
export type ProcessEntitiesOptions = {
|
|
@@ -208,6 +211,14 @@ export type ProcessEntitiesOptions = {
|
|
|
208
211
|
tagFilter?: ((tagName: string, jPathOrMatcher: JPathOrMatcher) => boolean) | null;
|
|
209
212
|
};
|
|
210
213
|
|
|
214
|
+
export type EntityDecoderOptions = {
|
|
215
|
+
setExternalEntities: (entities: Record<string, string>) => void;
|
|
216
|
+
addInputEntities: (entities: Record<string, string>) => void;
|
|
217
|
+
reset: () => void;
|
|
218
|
+
decode: (text: string) => string;
|
|
219
|
+
setXmlVersion: (version: string) => void;
|
|
220
|
+
}
|
|
221
|
+
|
|
211
222
|
export type X2jOptions = {
|
|
212
223
|
/**
|
|
213
224
|
* Preserve the order of tags in resulting JS object
|
|
@@ -394,9 +405,14 @@ export type X2jOptions = {
|
|
|
394
405
|
* Whether to process HTML entities
|
|
395
406
|
*
|
|
396
407
|
* Defaults to `false`
|
|
408
|
+
* @deprecated Use `entityDecoder` instead
|
|
397
409
|
*/
|
|
398
410
|
htmlEntities?: boolean;
|
|
399
411
|
|
|
412
|
+
/**
|
|
413
|
+
* Custom entity decoder
|
|
414
|
+
*/
|
|
415
|
+
entityDecoder?: EntityDecoderOptions;
|
|
400
416
|
/**
|
|
401
417
|
* Whether to ignore the declaration tag from output
|
|
402
418
|
*
|
|
@@ -487,7 +503,9 @@ export type strnumOptions = {
|
|
|
487
503
|
hex: boolean;
|
|
488
504
|
leadingZeros: boolean,
|
|
489
505
|
skipLike?: RegExp,
|
|
490
|
-
eNotation?: boolean
|
|
506
|
+
eNotation?: boolean,
|
|
507
|
+
infinity?: string,
|
|
508
|
+
unicode?: boolean
|
|
491
509
|
}
|
|
492
510
|
|
|
493
511
|
export type validationOptions = {
|
|
@@ -680,11 +698,19 @@ export type ValidationError = {
|
|
|
680
698
|
|
|
681
699
|
export class XMLParser {
|
|
682
700
|
constructor(options?: X2jOptions);
|
|
683
|
-
|
|
701
|
+
|
|
702
|
+
parse(xmlData: string | Uint8Array): any;
|
|
703
|
+
/**
|
|
704
|
+
* @deprecated The `validationOptions` parameter is deprecated.
|
|
705
|
+
* Use the `fast-xml-validator` package instead for XML validation.
|
|
706
|
+
* @see https://www.npmjs.com/package/fast-xml-validator
|
|
707
|
+
*/
|
|
708
|
+
parse(xmlData: string | Uint8Array, validationOptions: validationOptions | boolean): any;
|
|
684
709
|
/**
|
|
685
710
|
* Add Entity which is not by default supported by this library
|
|
686
711
|
* @param entityIdentifier {string} Eg: 'ent' for &ent;
|
|
687
712
|
* @param entityValue {string} Eg: '\r'
|
|
713
|
+
* @deprecated Use `entityDecoder` instead
|
|
688
714
|
*/
|
|
689
715
|
addEntity(entityIdentifier: string, entityValue: string): void;
|
|
690
716
|
|
|
@@ -701,9 +727,16 @@ export class XMLParser {
|
|
|
701
727
|
static getMetaDataSymbol(): Symbol;
|
|
702
728
|
}
|
|
703
729
|
|
|
730
|
+
/**
|
|
731
|
+
* @deprecated Use fast-xml-validator instead
|
|
732
|
+
* @see https://www.npmjs.com/package/fast-xml-validator
|
|
733
|
+
*/
|
|
704
734
|
export class XMLValidator {
|
|
705
735
|
static validate(xmlData: string, options?: validationOptions): true | ValidationError;
|
|
706
736
|
}
|
|
737
|
+
/**
|
|
738
|
+
* @deprecated Use npm package 'fast-xml-builder' instead
|
|
739
|
+
*/
|
|
707
740
|
export class XMLBuilder {
|
|
708
741
|
constructor(options?: XmlBuilderOptions);
|
|
709
742
|
build(jObj: any): string;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
-
import { isName } from '
|
|
1
|
+
import { qName as isName } from 'xml-naming';
|
|
2
2
|
|
|
3
3
|
export default class DocTypeReader {
|
|
4
|
-
constructor(options) {
|
|
4
|
+
constructor(options, xmlVersion) {
|
|
5
5
|
this.suppressValidationErr = !options;
|
|
6
6
|
this.options = options;
|
|
7
|
+
this.xmlVersion = xmlVersion || 1.0;
|
|
7
8
|
}
|
|
8
9
|
|
|
10
|
+
setXmlVersion(xmlVersion = 1.0) {
|
|
11
|
+
this.xmlVersion = xmlVersion;
|
|
12
|
+
}
|
|
9
13
|
readDocType(xmlData, i) {
|
|
10
14
|
const entities = Object.create(null);
|
|
11
15
|
let entityCount = 0;
|
|
@@ -35,11 +39,8 @@ export default class DocTypeReader {
|
|
|
35
39
|
);
|
|
36
40
|
}
|
|
37
41
|
//const escaped = entityName.replace(/[.\-+*:]/g, '\\.');
|
|
38
|
-
const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
39
|
-
entities[entityName] =
|
|
40
|
-
regx: RegExp(`&${escaped};`, "g"),
|
|
41
|
-
val: val
|
|
42
|
-
};
|
|
42
|
+
//const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
43
|
+
entities[entityName] = val;
|
|
43
44
|
entityCount++;
|
|
44
45
|
}
|
|
45
46
|
}
|
|
@@ -106,7 +107,7 @@ export default class DocTypeReader {
|
|
|
106
107
|
}
|
|
107
108
|
let entityName = xmlData.substring(startIndex, i);
|
|
108
109
|
|
|
109
|
-
validateEntityName(entityName);
|
|
110
|
+
validateEntityName(entityName, { xmlVersion: this.xmlVersion });
|
|
110
111
|
|
|
111
112
|
// Skip whitespace after entity name
|
|
112
113
|
i = skipWhitespace(xmlData, i);
|
|
@@ -149,7 +150,7 @@ export default class DocTypeReader {
|
|
|
149
150
|
}
|
|
150
151
|
let notationName = xmlData.substring(startIndex, i);
|
|
151
152
|
|
|
152
|
-
!this.suppressValidationErr && validateEntityName(notationName);
|
|
153
|
+
!this.suppressValidationErr && validateEntityName(notationName, { xmlVersion: this.xmlVersion });
|
|
153
154
|
|
|
154
155
|
// Skip whitespace after notation name
|
|
155
156
|
i = skipWhitespace(xmlData, i);
|
|
@@ -229,7 +230,7 @@ export default class DocTypeReader {
|
|
|
229
230
|
let elementName = xmlData.substring(startIndex, i);
|
|
230
231
|
|
|
231
232
|
// Validate element name
|
|
232
|
-
if (!this.suppressValidationErr && !isName(elementName)) {
|
|
233
|
+
if (!this.suppressValidationErr && !isName(elementName, { xmlVersion: this.xmlVersion })) {
|
|
233
234
|
throw new Error(`Invalid element name: "${elementName}"`);
|
|
234
235
|
}
|
|
235
236
|
|
|
@@ -276,7 +277,7 @@ export default class DocTypeReader {
|
|
|
276
277
|
let elementName = xmlData.substring(startIndex, i);
|
|
277
278
|
|
|
278
279
|
// Validate element name
|
|
279
|
-
validateEntityName(elementName)
|
|
280
|
+
validateEntityName(elementName, { xmlVersion: this.xmlVersion })
|
|
280
281
|
|
|
281
282
|
// Skip whitespace after element name
|
|
282
283
|
i = skipWhitespace(xmlData, i);
|
|
@@ -289,7 +290,7 @@ export default class DocTypeReader {
|
|
|
289
290
|
let attributeName = xmlData.substring(startIndex, i);
|
|
290
291
|
|
|
291
292
|
// Validate attribute name
|
|
292
|
-
if (!validateEntityName(attributeName)) {
|
|
293
|
+
if (!validateEntityName(attributeName, { xmlVersion: this.xmlVersion })) {
|
|
293
294
|
throw new Error(`Invalid attribute name: "${attributeName}"`);
|
|
294
295
|
}
|
|
295
296
|
|
|
@@ -324,7 +325,7 @@ export default class DocTypeReader {
|
|
|
324
325
|
|
|
325
326
|
// Validate notation name
|
|
326
327
|
notation = notation.trim();
|
|
327
|
-
if (!validateEntityName(notation)) {
|
|
328
|
+
if (!validateEntityName(notation, { xmlVersion: this.xmlVersion })) {
|
|
328
329
|
throw new Error(`Invalid notation name: "${notation}"`);
|
|
329
330
|
}
|
|
330
331
|
|
|
@@ -402,8 +403,8 @@ function hasSeq(data, seq, i) {
|
|
|
402
403
|
return true;
|
|
403
404
|
}
|
|
404
405
|
|
|
405
|
-
function validateEntityName(name) {
|
|
406
|
-
if (isName(name))
|
|
406
|
+
function validateEntityName(name, xmlVersion) {
|
|
407
|
+
if (isName(name, { xmlVersion: xmlVersion }))
|
|
407
408
|
return name;
|
|
408
409
|
else
|
|
409
410
|
throw new Error(`Invalid entity name ${name}`);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DANGEROUS_PROPERTY_NAMES, criticalProperties } from "../util.js";
|
|
2
|
+
import { COMMON_HTML, CURRENCY } from '@nodable/entities';
|
|
2
3
|
|
|
3
4
|
const defaultOnDangerousProperty = (name) => {
|
|
4
5
|
if (DANGEROUS_PROPERTY_NAMES.includes(name)) {
|
|
@@ -24,7 +25,8 @@ export const defaultOptions = {
|
|
|
24
25
|
numberParseOptions: {
|
|
25
26
|
hex: true,
|
|
26
27
|
leadingZeros: true,
|
|
27
|
-
eNotation: true
|
|
28
|
+
eNotation: true,
|
|
29
|
+
unicode: false
|
|
28
30
|
},
|
|
29
31
|
tagValueProcessor: function (tagName, val) {
|
|
30
32
|
return val;
|
|
@@ -39,6 +41,7 @@ export const defaultOptions = {
|
|
|
39
41
|
unpairedTags: [],
|
|
40
42
|
processEntities: true,
|
|
41
43
|
htmlEntities: false,
|
|
44
|
+
entityDecoder: null,
|
|
42
45
|
ignoreDeclaration: false,
|
|
43
46
|
ignorePiTags: false,
|
|
44
47
|
transformTagName: false,
|
|
@@ -85,18 +88,19 @@ function validatePropertyName(propertyName, optionName) {
|
|
|
85
88
|
* @param {boolean|object} value
|
|
86
89
|
* @returns {object} Always returns normalized object
|
|
87
90
|
*/
|
|
88
|
-
function normalizeProcessEntities(value) {
|
|
91
|
+
function normalizeProcessEntities(value, htmlEntities) {
|
|
89
92
|
// Boolean backward compatibility
|
|
90
93
|
if (typeof value === 'boolean') {
|
|
91
94
|
return {
|
|
92
95
|
enabled: value, // true or false
|
|
93
96
|
maxEntitySize: 10000,
|
|
94
|
-
maxExpansionDepth:
|
|
95
|
-
maxTotalExpansions:
|
|
97
|
+
maxExpansionDepth: 10000,
|
|
98
|
+
maxTotalExpansions: Infinity,
|
|
96
99
|
maxExpandedLength: 100000,
|
|
97
|
-
maxEntityCount:
|
|
100
|
+
maxEntityCount: 1000,
|
|
98
101
|
allowedTags: null,
|
|
99
|
-
tagFilter: null
|
|
102
|
+
tagFilter: null,
|
|
103
|
+
appliesTo: "all",
|
|
100
104
|
};
|
|
101
105
|
}
|
|
102
106
|
|
|
@@ -110,7 +114,8 @@ function normalizeProcessEntities(value) {
|
|
|
110
114
|
maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),
|
|
111
115
|
maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),
|
|
112
116
|
allowedTags: value.allowedTags ?? null,
|
|
113
|
-
tagFilter: value.tagFilter ?? null
|
|
117
|
+
tagFilter: value.tagFilter ?? null,
|
|
118
|
+
appliesTo: value.appliesTo ?? "all",
|
|
114
119
|
};
|
|
115
120
|
}
|
|
116
121
|
|
|
@@ -141,7 +146,7 @@ export const buildOptions = function (options) {
|
|
|
141
146
|
}
|
|
142
147
|
|
|
143
148
|
// Always normalize processEntities for backward compatibility and validation
|
|
144
|
-
built.processEntities = normalizeProcessEntities(built.processEntities);
|
|
149
|
+
built.processEntities = normalizeProcessEntities(built.processEntities, built.htmlEntities);
|
|
145
150
|
built.unpairedTagsSet = new Set(built.unpairedTags);
|
|
146
151
|
// Convert old-style stopNodes for backward compatibility
|
|
147
152
|
if (built.stopNodes && Array.isArray(built.stopNodes)) {
|