@rgrove/parse-xml 3.0.0 → 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/LICENSE +1 -1
- package/README.md +72 -97
- package/dist/browser.js +774 -0
- package/dist/browser.js.map +7 -0
- package/dist/global.min.js +10 -0
- package/dist/global.min.js.map +7 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +50 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/Parser.d.ts +218 -0
- package/dist/lib/Parser.d.ts.map +1 -0
- package/dist/lib/Parser.js +638 -0
- package/dist/lib/Parser.js.map +1 -0
- package/dist/lib/StringScanner.d.ts +97 -0
- package/dist/lib/StringScanner.d.ts.map +1 -0
- package/dist/lib/StringScanner.js +210 -0
- package/dist/lib/StringScanner.js.map +1 -0
- package/dist/lib/XmlCdata.d.ts +8 -0
- package/dist/lib/XmlCdata.d.ts.map +1 -0
- package/dist/lib/XmlCdata.js +15 -0
- package/dist/lib/XmlCdata.js.map +1 -0
- package/dist/lib/XmlComment.d.ts +16 -0
- package/dist/lib/XmlComment.d.ts.map +1 -0
- package/dist/lib/XmlComment.js +23 -0
- package/dist/lib/XmlComment.js.map +1 -0
- package/dist/lib/XmlDocument.d.ts +29 -0
- package/dist/lib/XmlDocument.d.ts.map +1 -0
- package/dist/lib/XmlDocument.js +47 -0
- package/dist/lib/XmlDocument.js.map +1 -0
- package/dist/lib/XmlElement.d.ts +40 -0
- package/dist/lib/XmlElement.d.ts.map +1 -0
- package/dist/lib/XmlElement.js +51 -0
- package/dist/lib/XmlElement.js.map +1 -0
- package/dist/lib/XmlNode.d.ts +74 -0
- package/dist/lib/XmlNode.d.ts.map +1 -0
- package/dist/lib/XmlNode.js +96 -0
- package/dist/lib/XmlNode.js.map +1 -0
- package/dist/lib/XmlProcessingInstruction.d.ts +22 -0
- package/dist/lib/XmlProcessingInstruction.d.ts.map +1 -0
- package/dist/lib/XmlProcessingInstruction.js +25 -0
- package/dist/lib/XmlProcessingInstruction.js.map +1 -0
- package/dist/lib/XmlText.d.ts +16 -0
- package/dist/lib/XmlText.d.ts.map +1 -0
- package/dist/lib/XmlText.js +23 -0
- package/dist/lib/XmlText.js.map +1 -0
- package/dist/lib/syntax.d.ts +69 -0
- package/dist/lib/syntax.d.ts.map +1 -0
- package/dist/lib/syntax.js +133 -0
- package/dist/lib/syntax.js.map +1 -0
- package/dist/lib/types.d.ts +5 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/types.js +3 -0
- package/dist/lib/types.js.map +1 -0
- package/package.json +30 -22
- package/src/index.ts +30 -0
- package/src/lib/Parser.ts +819 -0
- package/src/lib/StringScanner.ts +254 -0
- package/src/lib/XmlCdata.ts +11 -0
- package/src/lib/XmlComment.ts +26 -0
- package/src/lib/XmlDocument.ts +57 -0
- package/src/lib/XmlElement.ts +81 -0
- package/src/lib/XmlNode.ts +107 -0
- package/src/lib/XmlProcessingInstruction.ts +35 -0
- package/src/lib/XmlText.ts +26 -0
- package/src/lib/syntax.ts +136 -0
- package/src/lib/types.ts +2 -0
- package/CHANGELOG.md +0 -162
- package/dist/types/index.d.ts +0 -68
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/lib/Parser.d.ts +0 -234
- package/dist/types/lib/Parser.d.ts.map +0 -1
- package/dist/types/lib/StringScanner.d.ts +0 -139
- package/dist/types/lib/StringScanner.d.ts.map +0 -1
- package/dist/types/lib/XmlCdata.d.ts +0 -11
- package/dist/types/lib/XmlCdata.d.ts.map +0 -1
- package/dist/types/lib/XmlComment.d.ts +0 -21
- package/dist/types/lib/XmlComment.d.ts.map +0 -1
- package/dist/types/lib/XmlDocument.d.ts +0 -42
- package/dist/types/lib/XmlDocument.d.ts.map +0 -1
- package/dist/types/lib/XmlElement.d.ts +0 -62
- package/dist/types/lib/XmlElement.d.ts.map +0 -1
- package/dist/types/lib/XmlNode.d.ts +0 -78
- package/dist/types/lib/XmlNode.d.ts.map +0 -1
- package/dist/types/lib/XmlProcessingInstruction.d.ts +0 -30
- package/dist/types/lib/XmlProcessingInstruction.d.ts.map +0 -1
- package/dist/types/lib/XmlText.d.ts +0 -21
- package/dist/types/lib/XmlText.d.ts.map +0 -1
- package/dist/types/lib/syntax.d.ts +0 -59
- package/dist/types/lib/syntax.d.ts.map +0 -1
- package/dist/umd/parse-xml.min.js +0 -2
- package/dist/umd/parse-xml.min.js.map +0 -1
- package/src/index.js +0 -67
- package/src/lib/Parser.js +0 -812
- package/src/lib/StringScanner.js +0 -312
- package/src/lib/XmlCdata.js +0 -17
- package/src/lib/XmlComment.js +0 -37
- package/src/lib/XmlDocument.js +0 -69
- package/src/lib/XmlElement.js +0 -101
- package/src/lib/XmlNode.js +0 -152
- package/src/lib/XmlProcessingInstruction.js +0 -48
- package/src/lib/XmlText.js +0 -37
- package/src/lib/syntax.js +0 -153
package/src/lib/StringScanner.js
DELETED
|
@@ -1,312 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const emptyString = '';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
@private
|
|
7
|
-
*/
|
|
8
|
-
class StringScanner {
|
|
9
|
-
/**
|
|
10
|
-
@param {string} string
|
|
11
|
-
*/
|
|
12
|
-
constructor(string) {
|
|
13
|
-
/** @type {string[]} */
|
|
14
|
-
this.chars = [ ...string ];
|
|
15
|
-
|
|
16
|
-
/** @type {number} */
|
|
17
|
-
this.charCount = this.chars.length;
|
|
18
|
-
|
|
19
|
-
/** @type {number} */
|
|
20
|
-
this.charIndex = 0;
|
|
21
|
-
|
|
22
|
-
/** @type {number[]} */
|
|
23
|
-
this.charsToBytes = new Array(this.charCount);
|
|
24
|
-
|
|
25
|
-
/** @type {boolean} */
|
|
26
|
-
this.multiByteMode = false;
|
|
27
|
-
|
|
28
|
-
/** @type {string} */
|
|
29
|
-
this.string = string;
|
|
30
|
-
|
|
31
|
-
let { chars, charCount, charsToBytes } = this;
|
|
32
|
-
|
|
33
|
-
if (charCount === string.length) {
|
|
34
|
-
// There are no multibyte characters in the input string, so char indexes
|
|
35
|
-
// and byte indexes are the same.
|
|
36
|
-
for (let i = 0; i < charCount; ++i) {
|
|
37
|
-
charsToBytes[i] = i;
|
|
38
|
-
}
|
|
39
|
-
} else {
|
|
40
|
-
// Create a mapping of character indexes to byte indexes. When the string
|
|
41
|
-
// contains multibyte characters, a byte index may not necessarily align
|
|
42
|
-
// with a character index.
|
|
43
|
-
for (let byteIndex = 0, charIndex = 0; charIndex < charCount; ++charIndex) {
|
|
44
|
-
charsToBytes[charIndex] = byteIndex;
|
|
45
|
-
byteIndex += chars[charIndex].length;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
this.multiByteMode = true;
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
Whether the current character index is at the end of the input string.
|
|
54
|
-
|
|
55
|
-
@type {boolean}
|
|
56
|
-
*/
|
|
57
|
-
get isEnd() {
|
|
58
|
-
return this.charIndex >= this.charCount;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// -- Protected Methods ------------------------------------------------------
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
Returns the number of characters in the given _string_, which may differ from
|
|
65
|
-
the byte length if the string contains multibyte characters.
|
|
66
|
-
|
|
67
|
-
@param {string} string
|
|
68
|
-
@returns {number}
|
|
69
|
-
*/
|
|
70
|
-
_charLength(string) {
|
|
71
|
-
let { length } = string;
|
|
72
|
-
|
|
73
|
-
if (length < 2 || !this.multiByteMode) {
|
|
74
|
-
return length;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// We could get the char length with `[ ...string ].length`, but that's
|
|
78
|
-
// actually slower than this approach, which replaces surrogate pairs with
|
|
79
|
-
// single-byte characters.
|
|
80
|
-
return string.replace(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g, '_').length;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// -- Public Methods ---------------------------------------------------------
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
Advances the scanner by the given number of characters, stopping if the end of
|
|
87
|
-
the string is reached.
|
|
88
|
-
|
|
89
|
-
@param {number} [count]
|
|
90
|
-
*/
|
|
91
|
-
advance(count = 1) {
|
|
92
|
-
this.charIndex = Math.min(this.charCount, this.charIndex + count);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
Consumes and returns the given number of characters if possible, advancing the
|
|
97
|
-
scanner and stopping if the end of the string is reached.
|
|
98
|
-
|
|
99
|
-
If no characters could be consumed, an empty string will be returned.
|
|
100
|
-
|
|
101
|
-
@param {number} [count]
|
|
102
|
-
@returns {string}
|
|
103
|
-
*/
|
|
104
|
-
consume(count = 1) {
|
|
105
|
-
let chars = this.peek(count);
|
|
106
|
-
this.advance(count);
|
|
107
|
-
return chars;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
Consumes a match for the given sticky regex, advances the scanner, updates the
|
|
112
|
-
`lastIndex` property of the regex, and returns the matching string.
|
|
113
|
-
|
|
114
|
-
The regex must have a sticky flag ("y") so that its `lastIndex` prop can be
|
|
115
|
-
used to anchor the match at the current scanner position.
|
|
116
|
-
|
|
117
|
-
Returns the consumed string, or an empty string if nothing was consumed.
|
|
118
|
-
|
|
119
|
-
@param {RegExp} regex
|
|
120
|
-
@returns {string}
|
|
121
|
-
*/
|
|
122
|
-
consumeMatch(regex) {
|
|
123
|
-
if (!regex.sticky) {
|
|
124
|
-
throw new Error('`regex` must have a sticky flag ("y")');
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
regex.lastIndex = this.charsToBytes[this.charIndex];
|
|
128
|
-
|
|
129
|
-
let result = regex.exec(this.string);
|
|
130
|
-
|
|
131
|
-
if (result === null) {
|
|
132
|
-
return emptyString;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
let match = result[0];
|
|
136
|
-
this.advance(this._charLength(match));
|
|
137
|
-
return match;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
Consumes and returns all characters for which the given function returns a
|
|
142
|
-
truthy value, stopping on the first falsy return value or if the end of the
|
|
143
|
-
input is reached.
|
|
144
|
-
|
|
145
|
-
@param {(char: string) => boolean} fn
|
|
146
|
-
@returns {string}
|
|
147
|
-
*/
|
|
148
|
-
consumeMatchFn(fn) {
|
|
149
|
-
let startIndex = this.charIndex;
|
|
150
|
-
|
|
151
|
-
while (!this.isEnd && fn(this.peek())) {
|
|
152
|
-
this.advance();
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return this.charIndex > startIndex
|
|
156
|
-
? this.string.slice(this.charsToBytes[startIndex], this.charsToBytes[this.charIndex])
|
|
157
|
-
: emptyString;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
Consumes the given string if it exists at the current character index, and
|
|
162
|
-
advances the scanner.
|
|
163
|
-
|
|
164
|
-
If the given string doesn't exist at the current character index, an empty
|
|
165
|
-
string will be returned and the scanner will not be advanced.
|
|
166
|
-
|
|
167
|
-
@param {string} stringToConsume
|
|
168
|
-
@returns {string}
|
|
169
|
-
*/
|
|
170
|
-
consumeString(stringToConsume) {
|
|
171
|
-
if (this.consumeStringFast(stringToConsume)) {
|
|
172
|
-
return stringToConsume;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
if (!this.multiByteMode) {
|
|
176
|
-
return emptyString;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
let { length } = stringToConsume;
|
|
180
|
-
let charLengthToMatch = this._charLength(stringToConsume);
|
|
181
|
-
|
|
182
|
-
if (charLengthToMatch !== length
|
|
183
|
-
&& stringToConsume === this.peek(charLengthToMatch)) {
|
|
184
|
-
|
|
185
|
-
this.advance(charLengthToMatch);
|
|
186
|
-
return stringToConsume;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return emptyString;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Does the same thing as `consumeString()`, but doesn't support consuming
|
|
194
|
-
* multibyte characters. This can be much faster if you only need to match
|
|
195
|
-
* single byte characters.
|
|
196
|
-
*
|
|
197
|
-
* @param {string} stringToConsume
|
|
198
|
-
* @returns {string}
|
|
199
|
-
*/
|
|
200
|
-
consumeStringFast(stringToConsume) {
|
|
201
|
-
if (this.peek() === stringToConsume[0]) {
|
|
202
|
-
let { length } = stringToConsume;
|
|
203
|
-
|
|
204
|
-
if (length === 1) {
|
|
205
|
-
this.advance();
|
|
206
|
-
return stringToConsume;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
if (this.peek(length) === stringToConsume) {
|
|
210
|
-
this.advance(length);
|
|
211
|
-
return stringToConsume;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
return emptyString;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
Consumes characters until the given global regex is matched, advancing the
|
|
220
|
-
scanner up to (but not beyond) the beginning of the match and updating the
|
|
221
|
-
`lastIndex` property of the regex.
|
|
222
|
-
|
|
223
|
-
The regex must have a global flag ("g") so that its `lastIndex` prop can be
|
|
224
|
-
used to begin the search at the current scanner position.
|
|
225
|
-
|
|
226
|
-
Returns the consumed string, or an empty string if nothing was consumed.
|
|
227
|
-
|
|
228
|
-
@param {RegExp} regex
|
|
229
|
-
@returns {string}
|
|
230
|
-
*/
|
|
231
|
-
consumeUntilMatch(regex) {
|
|
232
|
-
if (!regex.global) {
|
|
233
|
-
throw new Error('`regex` must have a global flag ("g")');
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
let byteIndex = this.charsToBytes[this.charIndex];
|
|
237
|
-
regex.lastIndex = byteIndex;
|
|
238
|
-
|
|
239
|
-
let match = regex.exec(this.string);
|
|
240
|
-
|
|
241
|
-
if (match === null || match.index === byteIndex) {
|
|
242
|
-
return emptyString;
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
let result = this.string.slice(byteIndex, match.index);
|
|
246
|
-
this.advance(this._charLength(result));
|
|
247
|
-
return result;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/**
|
|
251
|
-
Consumes characters until the given string is found, advancing the scanner up
|
|
252
|
-
to (but not beyond) that point.
|
|
253
|
-
|
|
254
|
-
Returns the consumed string, or an empty string if nothing was consumed.
|
|
255
|
-
|
|
256
|
-
@param {string} searchString
|
|
257
|
-
@returns {string}
|
|
258
|
-
*/
|
|
259
|
-
consumeUntilString(searchString) {
|
|
260
|
-
let { charIndex, charsToBytes, string } = this;
|
|
261
|
-
let byteIndex = charsToBytes[charIndex];
|
|
262
|
-
let matchByteIndex = string.indexOf(searchString, byteIndex);
|
|
263
|
-
|
|
264
|
-
if (matchByteIndex <= 0) {
|
|
265
|
-
return emptyString;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
let result = string.slice(byteIndex, matchByteIndex);
|
|
269
|
-
this.advance(this._charLength(result));
|
|
270
|
-
return result;
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
Returns the given number of characters starting at the current character
|
|
275
|
-
index, without advancing the scanner and without exceeding the end of the
|
|
276
|
-
input string.
|
|
277
|
-
|
|
278
|
-
@param {number} [count]
|
|
279
|
-
@returns {string}
|
|
280
|
-
*/
|
|
281
|
-
peek(count = 1) {
|
|
282
|
-
// Inlining this comparison instead of checking `this.isEnd` improves perf
|
|
283
|
-
// slightly since `peek()` is called so frequently.
|
|
284
|
-
if (this.charIndex >= this.charCount) {
|
|
285
|
-
return emptyString;
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
if (count === 1) {
|
|
289
|
-
return this.chars[this.charIndex];
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
let { charsToBytes, charIndex } = this;
|
|
293
|
-
return this.string.slice(charsToBytes[charIndex], charsToBytes[charIndex + count]);
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
Resets the scanner position to the given character _index_, or to the start of
|
|
298
|
-
the input string if no index is given.
|
|
299
|
-
|
|
300
|
-
If _index_ is negative, the scanner position will be moved backward by that
|
|
301
|
-
many characters, stopping if the beginning of the string is reached.
|
|
302
|
-
|
|
303
|
-
@param {number} [index]
|
|
304
|
-
*/
|
|
305
|
-
reset(index = 0) {
|
|
306
|
-
this.charIndex = index >= 0
|
|
307
|
-
? Math.min(this.charCount, index)
|
|
308
|
-
: Math.max(0, this.charIndex + index);
|
|
309
|
-
}
|
|
310
|
-
}
|
|
311
|
-
|
|
312
|
-
module.exports = StringScanner;
|
package/src/lib/XmlCdata.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const XmlNode = require('./XmlNode');
|
|
4
|
-
const XmlText = require('./XmlText');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
A CDATA section within an XML document.
|
|
8
|
-
|
|
9
|
-
@public
|
|
10
|
-
*/
|
|
11
|
-
class XmlCdata extends XmlText {
|
|
12
|
-
get type() {
|
|
13
|
-
return XmlNode.TYPE_CDATA;
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
module.exports = XmlCdata;
|
package/src/lib/XmlComment.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const XmlNode = require('./XmlNode');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
A comment within an XML document.
|
|
7
|
-
|
|
8
|
-
@public
|
|
9
|
-
*/
|
|
10
|
-
class XmlComment extends XmlNode {
|
|
11
|
-
/**
|
|
12
|
-
@param {string} [content]
|
|
13
|
-
*/
|
|
14
|
-
constructor(content = '') {
|
|
15
|
-
super();
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
Content of this comment.
|
|
19
|
-
|
|
20
|
-
@type {string}
|
|
21
|
-
@public
|
|
22
|
-
*/
|
|
23
|
-
this.content = content;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
get type() {
|
|
27
|
-
return XmlNode.TYPE_COMMENT;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
toJSON() {
|
|
31
|
-
return Object.assign(XmlNode.prototype.toJSON.call(this), {
|
|
32
|
-
content: this.content
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
module.exports = XmlComment;
|
package/src/lib/XmlDocument.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const XmlElement = require('./XmlElement');
|
|
4
|
-
const XmlNode = require('./XmlNode');
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
Represents an XML document. All elements within the document are descendants of
|
|
8
|
-
this node.
|
|
9
|
-
|
|
10
|
-
@public
|
|
11
|
-
*/
|
|
12
|
-
class XmlDocument extends XmlNode {
|
|
13
|
-
/**
|
|
14
|
-
@param {Array<XmlComment|XmlElement|XmlProcessingInstruction>} [children]
|
|
15
|
-
*/
|
|
16
|
-
constructor(children = []) {
|
|
17
|
-
super();
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
Child nodes of this document.
|
|
21
|
-
|
|
22
|
-
@type {Array<XmlComment|XmlElement|XmlProcessingInstruction>}
|
|
23
|
-
@public
|
|
24
|
-
*/
|
|
25
|
-
this.children = children;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
get document() {
|
|
29
|
-
return this;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
Root element of this document, or `null` if this document is empty.
|
|
34
|
-
|
|
35
|
-
@type {XmlElement?}
|
|
36
|
-
@public
|
|
37
|
-
*/
|
|
38
|
-
get root() {
|
|
39
|
-
// @ts-ignore
|
|
40
|
-
return this.children.find((child) => child instanceof XmlElement) || null;
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
Text content of this document and all its descendants.
|
|
45
|
-
|
|
46
|
-
@type {string}
|
|
47
|
-
@public
|
|
48
|
-
*/
|
|
49
|
-
get text() {
|
|
50
|
-
return this.children
|
|
51
|
-
.map(child => 'text' in child ? child.text : '')
|
|
52
|
-
.join('');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
get type() {
|
|
56
|
-
return XmlNode.TYPE_DOCUMENT;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
toJSON() {
|
|
60
|
-
return Object.assign(XmlNode.prototype.toJSON.call(this), {
|
|
61
|
-
children: this.children.map(child => child.toJSON()),
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
module.exports = XmlDocument;
|
|
67
|
-
|
|
68
|
-
/** @typedef {import('./XmlComment')} XmlComment */
|
|
69
|
-
/** @typedef {import('./XmlProcessingInstruction')} XmlProcessingInstruction */
|
package/src/lib/XmlElement.js
DELETED
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const XmlNode = require('./XmlNode');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
Element in an XML document.
|
|
7
|
-
|
|
8
|
-
@public
|
|
9
|
-
*/
|
|
10
|
-
class XmlElement extends XmlNode {
|
|
11
|
-
/**
|
|
12
|
-
@param {string} name
|
|
13
|
-
@param {{[attrName: string]: string}} [attributes]
|
|
14
|
-
@param {Array<XmlCdata|XmlComment|XmlElement|XmlProcessingInstruction|XmlText>} [children]
|
|
15
|
-
*/
|
|
16
|
-
constructor(name, attributes = Object.create(null), children = []) {
|
|
17
|
-
super();
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
Name of this element.
|
|
21
|
-
|
|
22
|
-
@type {string}
|
|
23
|
-
@public
|
|
24
|
-
*/
|
|
25
|
-
this.name = name;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
Attributes on this element.
|
|
29
|
-
|
|
30
|
-
@type {{[attrName: string]: string}}
|
|
31
|
-
@public
|
|
32
|
-
*/
|
|
33
|
-
this.attributes = attributes;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
Child nodes of this element.
|
|
37
|
-
|
|
38
|
-
@type {Array<XmlCdata|XmlComment|XmlElement|XmlProcessingInstruction|XmlText>}
|
|
39
|
-
@public
|
|
40
|
-
*/
|
|
41
|
-
this.children = children;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
Whether this node is empty (meaning it has no children).
|
|
46
|
-
|
|
47
|
-
@type {boolean}
|
|
48
|
-
@public
|
|
49
|
-
*/
|
|
50
|
-
get isEmpty() {
|
|
51
|
-
return this.children.length === 0;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** @type {boolean} */
|
|
55
|
-
get preserveWhitespace() {
|
|
56
|
-
/** @type {XmlNode?} */
|
|
57
|
-
let node = this;
|
|
58
|
-
|
|
59
|
-
while (node instanceof XmlElement) {
|
|
60
|
-
if ('xml:space' in node.attributes) {
|
|
61
|
-
return node.attributes['xml:space'] === 'preserve';
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
node = node.parent;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return false;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
Text content of this element and all its descendants.
|
|
72
|
-
|
|
73
|
-
@type {string}
|
|
74
|
-
@public
|
|
75
|
-
*/
|
|
76
|
-
get text() {
|
|
77
|
-
return this.children
|
|
78
|
-
.map(child => 'text' in child ? child.text : '')
|
|
79
|
-
.join('');
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
get type() {
|
|
83
|
-
return XmlNode.TYPE_ELEMENT;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** @returns {{[key: string]: any}} */
|
|
87
|
-
toJSON() {
|
|
88
|
-
return Object.assign(XmlNode.prototype.toJSON.call(this), {
|
|
89
|
-
name: this.name,
|
|
90
|
-
attributes: this.attributes,
|
|
91
|
-
children: this.children.map(child => child.toJSON()),
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
module.exports = XmlElement;
|
|
97
|
-
|
|
98
|
-
/** @typedef {import('./XmlCdata')} XmlCdata */
|
|
99
|
-
/** @typedef {import('./XmlComment')} XmlComment */
|
|
100
|
-
/** @typedef {import('./XmlProcessingInstruction')} XmlProcessingInstruction */
|
|
101
|
-
/** @typedef {import('./XmlText')} XmlText */
|
package/src/lib/XmlNode.js
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
Base interface for a node in an XML document.
|
|
5
|
-
|
|
6
|
-
@public
|
|
7
|
-
*/
|
|
8
|
-
class XmlNode {
|
|
9
|
-
constructor() {
|
|
10
|
-
/**
|
|
11
|
-
Parent node of this node, or `null` if this node has no parent.
|
|
12
|
-
|
|
13
|
-
@type {XmlDocument|XmlElement|null}
|
|
14
|
-
@public
|
|
15
|
-
*/
|
|
16
|
-
this.parent = null;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
Document that contains this node, or `null` if this node is not associated
|
|
21
|
-
with a document.
|
|
22
|
-
|
|
23
|
-
@type {XmlDocument?}
|
|
24
|
-
@public
|
|
25
|
-
*/
|
|
26
|
-
get document() {
|
|
27
|
-
return this.parent
|
|
28
|
-
? this.parent.document
|
|
29
|
-
: null;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
Whether this node is the root node of the document.
|
|
34
|
-
|
|
35
|
-
@returns {boolean}
|
|
36
|
-
@public
|
|
37
|
-
*/
|
|
38
|
-
get isRootNode() {
|
|
39
|
-
return this.parent
|
|
40
|
-
? this.parent === this.document
|
|
41
|
-
: false;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
Whether whitespace should be preserved in the content of this element and
|
|
46
|
-
its children.
|
|
47
|
-
|
|
48
|
-
This is influenced by the value of the special `xml:space` attribute, and
|
|
49
|
-
will be `true` for any node whose `xml:space` attribute is set to
|
|
50
|
-
"preserve". If a node has no such attribute, it will inherit the value of
|
|
51
|
-
the nearest ancestor that does (if any).
|
|
52
|
-
|
|
53
|
-
@type {boolean}
|
|
54
|
-
@see https://www.w3.org/TR/2008/REC-xml-20081126/#sec-white-space
|
|
55
|
-
@public
|
|
56
|
-
*/
|
|
57
|
-
get preserveWhitespace() {
|
|
58
|
-
return Boolean(this.parent && this.parent.preserveWhitespace);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/**
|
|
62
|
-
Type of this node.
|
|
63
|
-
|
|
64
|
-
The value of this property is a string that matches one of the static `TYPE_*`
|
|
65
|
-
properties on the `XmlNode` class (e.g. `TYPE_ELEMENT`, `TYPE_TEXT`, etc.).
|
|
66
|
-
|
|
67
|
-
The `XmlNode` class itself is a base class and doesn't have its own type name.
|
|
68
|
-
|
|
69
|
-
@type {string}
|
|
70
|
-
@public
|
|
71
|
-
*/
|
|
72
|
-
get type() {
|
|
73
|
-
return '';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
Returns a JSON-serializable object representing this node, minus properties
|
|
78
|
-
that could result in circular references.
|
|
79
|
-
|
|
80
|
-
@returns {{[key: string]: any}}
|
|
81
|
-
@public
|
|
82
|
-
*/
|
|
83
|
-
toJSON() {
|
|
84
|
-
/** @type {{[key: string]: any}} */
|
|
85
|
-
let json = {
|
|
86
|
-
type: this.type
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
if (this.isRootNode) {
|
|
90
|
-
json.isRootNode = true;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
if (this.preserveWhitespace) {
|
|
94
|
-
json.preserveWhitespace = true;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return json;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
Type value for an `XmlCdata` node.
|
|
103
|
-
|
|
104
|
-
@type {string}
|
|
105
|
-
@public
|
|
106
|
-
*/
|
|
107
|
-
XmlNode.TYPE_CDATA = 'cdata';
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
Type value for an `XmlComment` node.
|
|
111
|
-
|
|
112
|
-
@type {string}
|
|
113
|
-
@public
|
|
114
|
-
*/
|
|
115
|
-
XmlNode.TYPE_COMMENT = 'comment';
|
|
116
|
-
|
|
117
|
-
/**
|
|
118
|
-
Type value for an `XmlDocument` node.
|
|
119
|
-
|
|
120
|
-
@type {string}
|
|
121
|
-
@public
|
|
122
|
-
*/
|
|
123
|
-
XmlNode.TYPE_DOCUMENT = 'document';
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
Type value for an `XmlElement` node.
|
|
127
|
-
|
|
128
|
-
@type {string}
|
|
129
|
-
@public
|
|
130
|
-
*/
|
|
131
|
-
XmlNode.TYPE_ELEMENT = 'element';
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
Type value for an `XmlProcessingInstruction` node.
|
|
135
|
-
|
|
136
|
-
@type {string}
|
|
137
|
-
@public
|
|
138
|
-
*/
|
|
139
|
-
XmlNode.TYPE_PROCESSING_INSTRUCTION = 'pi';
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
Type value for an `XmlText` node.
|
|
143
|
-
|
|
144
|
-
@type {string}
|
|
145
|
-
@public
|
|
146
|
-
*/
|
|
147
|
-
XmlNode.TYPE_TEXT = 'text';
|
|
148
|
-
|
|
149
|
-
module.exports = XmlNode;
|
|
150
|
-
|
|
151
|
-
/** @typedef {import('./XmlDocument')} XmlDocument */
|
|
152
|
-
/** @typedef {import('./XmlElement')} XmlElement */
|