@rgrove/parse-xml 2.0.4 → 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.
Files changed (73) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +84 -337
  3. package/dist/browser.js +774 -0
  4. package/dist/browser.js.map +7 -0
  5. package/dist/global.min.js +10 -0
  6. package/dist/global.min.js.map +7 -0
  7. package/dist/index.d.ts +24 -0
  8. package/dist/index.d.ts.map +1 -0
  9. package/dist/index.js +50 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/lib/Parser.d.ts +218 -0
  12. package/dist/lib/Parser.d.ts.map +1 -0
  13. package/dist/lib/Parser.js +638 -0
  14. package/dist/lib/Parser.js.map +1 -0
  15. package/dist/lib/StringScanner.d.ts +97 -0
  16. package/dist/lib/StringScanner.d.ts.map +1 -0
  17. package/dist/lib/StringScanner.js +210 -0
  18. package/dist/lib/StringScanner.js.map +1 -0
  19. package/dist/lib/XmlCdata.d.ts +8 -0
  20. package/dist/lib/XmlCdata.d.ts.map +1 -0
  21. package/dist/lib/XmlCdata.js +15 -0
  22. package/dist/lib/XmlCdata.js.map +1 -0
  23. package/dist/lib/XmlComment.d.ts +16 -0
  24. package/dist/lib/XmlComment.d.ts.map +1 -0
  25. package/dist/lib/XmlComment.js +23 -0
  26. package/dist/lib/XmlComment.js.map +1 -0
  27. package/dist/lib/XmlDocument.d.ts +29 -0
  28. package/dist/lib/XmlDocument.d.ts.map +1 -0
  29. package/dist/lib/XmlDocument.js +47 -0
  30. package/dist/lib/XmlDocument.js.map +1 -0
  31. package/dist/lib/XmlElement.d.ts +40 -0
  32. package/dist/lib/XmlElement.d.ts.map +1 -0
  33. package/dist/lib/XmlElement.js +51 -0
  34. package/dist/lib/XmlElement.js.map +1 -0
  35. package/dist/lib/XmlNode.d.ts +74 -0
  36. package/dist/lib/XmlNode.d.ts.map +1 -0
  37. package/dist/lib/XmlNode.js +96 -0
  38. package/dist/lib/XmlNode.js.map +1 -0
  39. package/dist/lib/XmlProcessingInstruction.d.ts +22 -0
  40. package/dist/lib/XmlProcessingInstruction.d.ts.map +1 -0
  41. package/dist/lib/XmlProcessingInstruction.js +25 -0
  42. package/dist/lib/XmlProcessingInstruction.js.map +1 -0
  43. package/dist/lib/XmlText.d.ts +16 -0
  44. package/dist/lib/XmlText.d.ts.map +1 -0
  45. package/dist/lib/XmlText.js +23 -0
  46. package/dist/lib/XmlText.js.map +1 -0
  47. package/dist/lib/syntax.d.ts +69 -0
  48. package/dist/lib/syntax.d.ts.map +1 -0
  49. package/dist/lib/syntax.js +133 -0
  50. package/dist/lib/syntax.js.map +1 -0
  51. package/dist/lib/types.d.ts +5 -0
  52. package/dist/lib/types.d.ts.map +1 -0
  53. package/dist/lib/types.js +3 -0
  54. package/dist/lib/types.js.map +1 -0
  55. package/package.json +36 -22
  56. package/src/index.ts +30 -0
  57. package/src/lib/Parser.ts +819 -0
  58. package/src/lib/StringScanner.ts +254 -0
  59. package/src/lib/XmlCdata.ts +11 -0
  60. package/src/lib/XmlComment.ts +26 -0
  61. package/src/lib/XmlDocument.ts +57 -0
  62. package/src/lib/XmlElement.ts +81 -0
  63. package/src/lib/XmlNode.ts +107 -0
  64. package/src/lib/XmlProcessingInstruction.ts +35 -0
  65. package/src/lib/XmlText.ts +26 -0
  66. package/src/lib/syntax.ts +136 -0
  67. package/src/lib/types.ts +2 -0
  68. package/CHANGELOG.md +0 -89
  69. package/dist/commonjs/index.js +0 -434
  70. package/dist/commonjs/lib/syntax.js +0 -262
  71. package/dist/umd/parse-xml.min.js +0 -1
  72. package/src/index.js +0 -451
  73. package/src/lib/syntax.js +0 -263
package/src/index.js DELETED
@@ -1,451 +0,0 @@
1
- 'use strict';
2
-
3
- const emptyArray = Object.freeze([]);
4
- const emptyObject = Object.freeze(Object.create(null));
5
-
6
- const namedEntities = Object.freeze({
7
- '&': '&',
8
- ''': "'",
9
- '>': '>',
10
- '&lt;': '<',
11
- '&quot;': '"'
12
- });
13
-
14
- const NODE_TYPE_CDATA = 'cdata';
15
- const NODE_TYPE_COMMENT = 'comment';
16
- const NODE_TYPE_DOCUMENT = 'document';
17
- const NODE_TYPE_ELEMENT = 'element';
18
- const NODE_TYPE_TEXT = 'text';
19
-
20
- let Syntax;
21
-
22
- module.exports = function parseXml(xml, options = emptyObject) {
23
- if (Syntax === void 0) {
24
- // Lazy require to defer regex parsing until first use.
25
- Syntax = require('./lib/syntax');
26
- }
27
-
28
- if (xml[0] === '\uFEFF') {
29
- // Strip byte order mark.
30
- xml = xml.slice(1);
31
- }
32
-
33
- xml = xml.replace(/\r\n?/g, '\n'); // Normalize CRLF and CR to LF.
34
-
35
- let doc = {
36
- type: NODE_TYPE_DOCUMENT,
37
- children: [],
38
- parent: null,
39
- toJSON: nodeToJson
40
- };
41
-
42
- let state = {
43
- length: xml.length,
44
- options,
45
- parent: doc,
46
- pos: 0,
47
- prevPos: 0,
48
- xml
49
- };
50
-
51
- state.replaceReference = replaceReference.bind(state);
52
-
53
- consumeProlog(state);
54
-
55
- if (!consumeElement(state)) {
56
- error(state, 'Root element is missing or invalid');
57
- }
58
-
59
- while (consumeMisc(state)) {} // eslint-disable-line no-empty
60
-
61
- if (!isEof(state)) {
62
- error(state, `Extra content at the end of the document`);
63
- }
64
-
65
- return doc;
66
- };
67
-
68
- // -- Private Functions --------------------------------------------------------
69
- function addNode(state, node) {
70
- node.parent = state.parent;
71
- node.toJSON = nodeToJson;
72
-
73
- state.parent.children.push(node);
74
- }
75
-
76
- function addText(state, text) {
77
- let { children } = state.parent;
78
- let prevNode = children[children.length - 1];
79
-
80
- if (prevNode !== void 0 && prevNode.type === NODE_TYPE_TEXT) {
81
- // The previous node is a text node, so we can append to it and avoid
82
- // creating another node.
83
- prevNode.text += text;
84
- } else {
85
- addNode(state, {
86
- type: NODE_TYPE_TEXT,
87
- text
88
- });
89
- }
90
- }
91
-
92
- // Each `consume*` function takes the current state as an argument and returns
93
- // `true` if `state.pos` was advanced (meaning some XML was consumed) or `false`
94
- // if nothing was consumed.
95
-
96
- function consumeCDSect(state) {
97
- let [ match, text ] = scan(state, Syntax.Anchored.CDSect);
98
-
99
- if (match === void 0) {
100
- return false;
101
- }
102
-
103
- if (state.options.preserveCdata) {
104
- addNode(state, {
105
- type: NODE_TYPE_CDATA,
106
- text
107
- });
108
- } else {
109
- addText(state, text);
110
- }
111
-
112
- return true;
113
- }
114
-
115
- function consumeCharData(state) {
116
- let [ text ] = scan(state, Syntax.Anchored.CharData);
117
-
118
- if (text === void 0) {
119
- return false;
120
- }
121
-
122
- let cdataCloseIndex = text.indexOf(']]>');
123
-
124
- if (cdataCloseIndex !== -1) {
125
- state.pos = state.prevPos + cdataCloseIndex;
126
- error(state, 'Element content may not contain the CDATA section close delimiter `]]>`');
127
- }
128
-
129
- // Note: XML 1.0 5th ed. says `CharData` is "any string of characters which
130
- // does not contain the start-delimiter of any markup and does not include the
131
- // CDATA-section-close delimiter", but the conformance test suite and
132
- // well-established parsers like libxml seem to restrict `CharData` to
133
- // characters that match the `Char` symbol, so that's what I've done here.
134
- if (!Syntax.CharOnly.test(text)) {
135
- state.pos = state.prevPos + text.search(new RegExp(`(?!${Syntax.Char.source})`));
136
- error(state, 'Element content contains an invalid character');
137
- }
138
-
139
- addText(state, text);
140
- return true;
141
- }
142
-
143
- function consumeComment(state) {
144
- let [ , content ] = scan(state, Syntax.Anchored.Comment);
145
-
146
- if (content === void 0) {
147
- return false;
148
- }
149
-
150
- if (state.options.preserveComments) {
151
- addNode(state, {
152
- type: NODE_TYPE_COMMENT,
153
- content: content.trim()
154
- });
155
- }
156
-
157
- return true;
158
- }
159
-
160
- function consumeDoctypeDecl(state) {
161
- return scan(state, Syntax.Anchored.doctypedecl).length > 0;
162
- }
163
-
164
- function consumeElement(state) {
165
- let [ tag, name, attrs ] = scan(state, Syntax.Anchored.EmptyElemTag);
166
- let isEmpty = tag !== void 0;
167
-
168
- if (!isEmpty) {
169
- [ tag, name, attrs ] = scan(state, Syntax.Anchored.STag);
170
-
171
- if (tag === void 0) {
172
- return false;
173
- }
174
- }
175
-
176
- let { parent } = state;
177
- let parsedAttrs = parseAttrs(state, attrs);
178
-
179
- let node = {
180
- type: NODE_TYPE_ELEMENT,
181
- name,
182
- attributes: parsedAttrs,
183
- children: []
184
- };
185
-
186
- let xmlSpace = parsedAttrs['xml:space'];
187
-
188
- if (xmlSpace === 'preserve'
189
- || (xmlSpace !== 'default' && parent.preserveWhitespace)) {
190
-
191
- node.preserveWhitespace = true;
192
- }
193
-
194
- if (!isEmpty) {
195
- state.parent = node;
196
-
197
- consumeCharData(state);
198
-
199
- while (
200
- consumeElement(state)
201
- || consumeReference(state)
202
- || consumeCDSect(state)
203
- || consumePI(state)
204
- || consumeComment(state)
205
- ) {
206
- consumeCharData(state);
207
- }
208
-
209
- let [ , endName ] = scan(state, Syntax.Anchored.ETag);
210
-
211
- if (endName !== name) {
212
- state.pos = state.prevPos;
213
- error(state, `Missing end tag for element ${name}`);
214
- }
215
-
216
- state.parent = parent;
217
- }
218
-
219
- addNode(state, node);
220
- return true;
221
- }
222
-
223
- function consumeMisc(state) {
224
- return consumeComment(state)
225
- || consumePI(state)
226
- || consumeWhitespace(state);
227
- }
228
-
229
- function consumePI(state) {
230
- let [ match, target ] = scan(state, Syntax.Anchored.PI);
231
-
232
- if (match === void 0) {
233
- return false;
234
- }
235
-
236
- if (target.toLowerCase() === 'xml') {
237
- state.pos = state.prevPos;
238
- error(state, 'XML declaration is only allowed at the start of the document');
239
- }
240
-
241
- return true;
242
- }
243
-
244
- function consumeProlog(state) {
245
- let { pos } = state;
246
-
247
- scan(state, Syntax.Anchored.XMLDecl);
248
-
249
- while (consumeMisc(state)) {} // eslint-disable-line no-empty
250
-
251
- if (consumeDoctypeDecl(state)) {
252
- while (consumeMisc(state)) {} // eslint-disable-line no-empty
253
- }
254
-
255
- return state.pos > pos;
256
- }
257
-
258
- function consumeReference(state) {
259
- let [ ref ] = scan(state, Syntax.Anchored.Reference);
260
-
261
- if (ref === void 0) {
262
- return false;
263
- }
264
-
265
- addText(state, state.replaceReference(ref));
266
- return true;
267
- }
268
-
269
- function consumeWhitespace(state) {
270
- return scan(state, Syntax.Anchored.S).length > 0;
271
- }
272
-
273
- function error(state, message) {
274
- let { pos, xml } = state;
275
- let column = 1;
276
- let excerpt = '';
277
- let line = 1;
278
-
279
- // Find the line and column where the error occurred.
280
- for (let i = 0; i < pos; ++i) {
281
- let char = xml[i];
282
-
283
- if (char === '\n') {
284
- column = 1;
285
- excerpt = '';
286
- line += 1;
287
- } else {
288
- column += 1;
289
- excerpt += char;
290
- }
291
- }
292
-
293
- let eol = xml.indexOf('\n', pos);
294
-
295
- excerpt += eol === -1
296
- ? xml.slice(pos)
297
- : xml.slice(pos, eol);
298
-
299
- let excerptStart = 0;
300
-
301
- // Keep the excerpt below 50 chars, but always keep the error position in
302
- // view.
303
- if (excerpt.length > 50) {
304
- if (column < 40) {
305
- excerpt = excerpt.slice(0, 50);
306
- } else {
307
- excerptStart = column - 20;
308
- excerpt = excerpt.slice(excerptStart, column + 30);
309
- }
310
- }
311
-
312
- let err = new Error(
313
- `${message} (line ${line}, column ${column})\n`
314
- + ` ${excerpt}\n`
315
- + ' '.repeat(column - excerptStart + 1) + '^\n'
316
- );
317
-
318
- err.column = column;
319
- err.excerpt = excerpt;
320
- err.line = line;
321
- err.pos = pos;
322
-
323
- throw err;
324
- }
325
-
326
- function isEof(state) {
327
- return state.pos >= state.length - 1;
328
- }
329
-
330
- function nodeToJson() {
331
- let json = Object.assign(Object.create(null), this); // eslint-disable-line no-invalid-this
332
- delete json.parent;
333
- return json;
334
- }
335
-
336
- function normalizeAttrValue(state, value) {
337
- return value
338
- .replace(/[\x20\t\r\n]/g, ' ')
339
- .replace(Syntax.Global.Reference, state.replaceReference);
340
- }
341
-
342
- function parseAttrs(state, attrs) {
343
- let parsedAttrs = Object.create(null);
344
-
345
- if (!attrs) {
346
- return parsedAttrs;
347
- }
348
-
349
- let attrPairs = attrs
350
- .match(Syntax.Global.Attribute)
351
- .sort();
352
-
353
- for (let i = 0, len = attrPairs.length; i < len; ++i) {
354
- let attrPair = attrPairs[i];
355
- let eqMatch = attrPair.match(Syntax.Eq);
356
- let name = attrPair.slice(0, eqMatch.index);
357
- let value = attrPair.slice(eqMatch.index + eqMatch[0].length);
358
-
359
- if (name in parsedAttrs) {
360
- state.pos = state.prevPos;
361
- error(state, `Attribute \`${name}\` redefined`);
362
- }
363
-
364
- value = normalizeAttrValue(state, value.slice(1, -1));
365
-
366
- if (name === 'xml:space') {
367
- if (value !== 'default' && value !== 'preserve') {
368
- state.pos = state.prevPos;
369
- error(state, `Value of the \`xml:space\` attribute must be "default" or "preserve"`);
370
- }
371
- }
372
-
373
- parsedAttrs[name] = value;
374
- }
375
-
376
- return parsedAttrs;
377
- }
378
-
379
- function replaceReference(ref) {
380
- let state = this; // eslint-disable-line no-invalid-this
381
-
382
- if (ref[ref.length - 1] !== ';') {
383
- error(state, `Invalid reference: \`${ref}\``);
384
- }
385
-
386
- if (ref[1] === '#') {
387
- // This is a character entity.
388
- let codePoint;
389
-
390
- if (ref[2] === 'x') {
391
- codePoint = parseInt(ref.slice(3, -1), 16);
392
- } else {
393
- codePoint = parseInt(ref.slice(2, -1), 10);
394
- }
395
-
396
- if (isNaN(codePoint)) {
397
- state.pos = state.prevPos;
398
- error(state, `Invalid character entity \`${ref}\``);
399
- }
400
-
401
- let char = String.fromCodePoint(codePoint);
402
-
403
- if (!Syntax.Char.test(char)) {
404
- state.pos = state.prevPos;
405
- error(state, `Invalid character entity \`${ref}\``);
406
- }
407
-
408
- return char;
409
- }
410
-
411
- // This is a named entity.
412
- let value = namedEntities[ref];
413
-
414
- if (value !== void 0) {
415
- return value;
416
- }
417
-
418
- if (state.options.resolveUndefinedEntity) {
419
- let resolvedValue = state.options.resolveUndefinedEntity(ref);
420
-
421
- if (resolvedValue !== null && resolvedValue !== void 0) {
422
- return resolvedValue;
423
- }
424
- }
425
-
426
- if (state.options.ignoreUndefinedEntities) {
427
- return ref;
428
- }
429
-
430
- state.pos = state.prevPos;
431
- error(state, `Named entity isn't defined: \`${ref}\``);
432
- }
433
-
434
- function scan(state, regex) {
435
- let { pos, xml } = state;
436
-
437
- let xmlToScan = pos > 0
438
- ? xml.slice(pos)
439
- : xml;
440
-
441
- let matches = xmlToScan.match(regex);
442
-
443
- if (matches === null) {
444
- return emptyArray;
445
- }
446
-
447
- state.prevPos = state.pos;
448
- state.pos += matches[0].length;
449
-
450
- return matches;
451
- }
package/src/lib/syntax.js DELETED
@@ -1,263 +0,0 @@
1
- 'use strict';
2
-
3
- // To improve readability, the regular expression patterns in this file are
4
- // written as tagged template literals. The `regex` tag function strips literal
5
- // whitespace characters and line comments beginning with `//` and returns a
6
- // RegExp instance.
7
- //
8
- // Escape sequences are preserved as-is in the resulting regex, so
9
- // double-escaping isn't necessary. A pattern may embed another pattern using
10
- // `${}` interpolation.
11
-
12
- // -- Common Symbols -----------------------------------------------------------
13
- exports.Char = regex`
14
- (?:
15
- [
16
- \t
17
- \n
18
- \r
19
- \x20-\uD7FF
20
- \uE000-\uFFFD
21
- ]
22
-
23
- |
24
-
25
- [\uD800-\uDBFF][\uDC00-\uDFFF]
26
- )
27
- `;
28
-
29
- // Partial implementation.
30
- //
31
- // To be compliant, the matched text must result in an error if it contains the
32
- // string `]]>`, but that can't be easily represented here so we do it in the
33
- // parser.
34
- exports.CharData = regex`
35
- [^<&]+
36
- `;
37
-
38
- exports.NameStartChar = regex`
39
- (?:
40
- [
41
- :
42
- A-Z
43
- _
44
- a-z
45
- \xC0-\xD6
46
- \xD8-\xF6
47
- \xF8-\u02FF
48
- \u0370-\u037D
49
- \u037F-\u1FFF
50
- \u200C-\u200D
51
- \u2070-\u218F
52
- \u2C00-\u2FEF
53
- \u3001-\uD7FF
54
- \uF900-\uFDCF
55
- \uFDF0-\uFFFD
56
- ]
57
-
58
- |
59
-
60
- [\uD800-\uDB7F][\uDC00-\uDFFF]
61
- )
62
- `;
63
-
64
- exports.NameChar = regex`
65
- (?:
66
- ${exports.NameStartChar}
67
-
68
- |
69
-
70
- [
71
- .
72
- 0-9
73
- \xB7
74
- \u0300-\u036F
75
- \u203F-\u2040
76
- -
77
- ]
78
- )
79
- `;
80
-
81
- exports.Name = regex`
82
- ${exports.NameStartChar}
83
- (?:${exports.NameChar})*
84
- `;
85
-
86
- // Loose implementation. The entity will be validated in the `replaceReference`
87
- // function.
88
- exports.Reference = regex`
89
- &[^\s&;]*;?
90
- `;
91
-
92
- exports.S = regex`
93
- [\x20\t\r\n]+
94
- `;
95
-
96
- // -- Attributes ---------------------------------------------------------------
97
- exports.Eq = regex`
98
- (?:${exports.S})?
99
- =
100
- (?:${exports.S})?
101
- `;
102
-
103
- exports.Attribute = regex`
104
- ${exports.Name}
105
- ${exports.Eq}
106
-
107
- (?:
108
- "(?:
109
- [^<"]
110
- )*"
111
-
112
- |
113
-
114
- '(?:
115
- [^<']
116
- )*'
117
- )
118
- `;
119
-
120
- // -- Elements -----------------------------------------------------------------
121
- exports.CDSect = regex`
122
- <!\[CDATA\[
123
- // Group 1: CData text content (optional)
124
- (
125
- (?:${exports.Char})*?
126
- )
127
- \]\]>
128
- `;
129
-
130
- exports.EmptyElemTag = regex`
131
- <
132
- // Group 1: Element name
133
- (${exports.Name})
134
-
135
- // Group 2: Attributes (optional)
136
- (
137
- (?:
138
- ${exports.S}
139
- ${exports.Attribute}
140
- )*
141
- )
142
-
143
- (?:${exports.S})?
144
- />
145
- `;
146
-
147
- exports.ETag = regex`
148
- </
149
- // Group 1: End tag name
150
- (${exports.Name})
151
- (?:${exports.S})?
152
- >
153
- `;
154
-
155
- exports.STag = regex`
156
- <
157
- // Group 1: Start tag name
158
- (${exports.Name})
159
-
160
- // Group 2: Attributes (optional)
161
- (
162
- (?:
163
- ${exports.S}
164
- ${exports.Attribute}
165
- )*
166
- )
167
-
168
- (?:${exports.S})?
169
- >
170
- `;
171
-
172
- // -- Misc ---------------------------------------------------------------------
173
-
174
- // Special pattern that matches an entire string consisting only of `Char`
175
- // characters.
176
- exports.CharOnly = regex`
177
- ^(?:${exports.Char})*$
178
- `;
179
-
180
- exports.Comment = regex`
181
- <!--
182
- // Group 1: Comment text (optional)
183
- (
184
- (?:
185
- (?!-) ${exports.Char}
186
- | - (?!-) ${exports.Char}
187
- )*
188
- )
189
- -->
190
- `;
191
-
192
- // Loose implementation since doctype declarations are discarded.
193
- //
194
- // It's not possible to fully parse a doctype declaration with a regex, but
195
- // since we just discard them we can skip parsing the fiddly inner bits and use
196
- // a regex to speed things up.
197
- exports.doctypedecl = regex`
198
- <!DOCTYPE
199
- ${exports.S}
200
-
201
- [^[>]*
202
-
203
- (?:
204
- \[ [\s\S]+? \]
205
- (?:${exports.S})?
206
- )?
207
- >
208
- `;
209
-
210
- // Loose implementation since processing instructions are discarded.
211
- exports.PI = regex`
212
- <\?
213
- // Group 1: PITarget
214
- (
215
- ${exports.Name}
216
- )
217
-
218
- (?:
219
- ${exports.S}
220
- (?:${exports.Char})*?
221
- )?
222
- \?>
223
- `;
224
-
225
- // Loose implementation since XML declarations are discarded.
226
- exports.XMLDecl = regex`
227
- <\?xml
228
- ${exports.S}
229
- [\s\S]+?
230
- \?>
231
- `;
232
-
233
- // -- Helpers ------------------------------------------------------------------
234
- exports.Anchored = {};
235
- exports.Global = {};
236
-
237
- // Create anchored and global variations of each pattern.
238
- Object.keys(exports).forEach(name => {
239
- if (name !== 'Anchored' && name !== 'CharOnly' && name !== 'Global') {
240
- let pattern = exports[name];
241
-
242
- exports.Anchored[name] = new RegExp('^' + pattern.source);
243
- exports.Global[name] = new RegExp(pattern.source, 'g');
244
- }
245
- });
246
-
247
- function regex(strings, ...embeddedPatterns) {
248
- let { length, raw } = strings;
249
- let lastIndex = length - 1;
250
- let pattern = '';
251
-
252
- for (let i = 0; i < length; ++i) {
253
- pattern += raw[i]
254
- .replace(/(^|[^\\])\/\/.*$/gm, '$1') // remove end-of-line comments
255
- .replace(/\s+/g, ''); // remove all whitespace
256
-
257
- if (i < lastIndex) {
258
- pattern += embeddedPatterns[i].source;
259
- }
260
- }
261
-
262
- return new RegExp(pattern);
263
- }