read-excel-file 9.3.1 → 9.3.2

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.
@@ -0,0 +1,1091 @@
1
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
2
+ export default function Parser_(options) {
3
+ return Parser(options);
4
+
5
+ // `decode.js` file contents
6
+
7
+ var fromCharCode = String.fromCharCode;
8
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
9
+ var ENTITY_PATTERN = /&#(\d+);|&#x([0-9a-f]+);|&(\w+);/ig;
10
+ var ENTITY_MAPPING = {
11
+ 'amp': '&',
12
+ 'apos': '\'',
13
+ 'gt': '>',
14
+ 'lt': '<',
15
+ 'quot': '"'
16
+ };
17
+
18
+ // map UPPERCASE variants of supported special chars
19
+ Object.keys(ENTITY_MAPPING).forEach(function (k) {
20
+ ENTITY_MAPPING[k.toUpperCase()] = ENTITY_MAPPING[k];
21
+ });
22
+ function replaceEntities(_, d, x, z) {
23
+ // reserved names, i.e. &nbsp;
24
+ if (z) {
25
+ if (hasOwnProperty.call(ENTITY_MAPPING, z)) {
26
+ return ENTITY_MAPPING[z];
27
+ } else {
28
+ // fall back to original value
29
+ return '&' + z + ';';
30
+ }
31
+ }
32
+
33
+ // decimal encoded char
34
+ if (d) {
35
+ return fromCharCode(d);
36
+ }
37
+
38
+ // hex encoded char
39
+ return fromCharCode(parseInt(x, 16));
40
+ }
41
+
42
+ /**
43
+ * A basic entity decoder that can decode a minimal
44
+ * sub-set of reserved names (&amp;) as well as
45
+ * hex (&#xaaf;) and decimal (&#1231;) encoded characters.
46
+ *
47
+ * @param {string} s
48
+ *
49
+ * @return {string} decoded string
50
+ */
51
+ function decodeEntities(s) {
52
+ if (s.length > 3 && s.indexOf('&') !== -1) {
53
+ return s.replace(ENTITY_PATTERN, replaceEntities);
54
+ }
55
+ return s;
56
+ }
57
+
58
+ // `parser.js` file contents
59
+
60
+ var NON_WHITESPACE_OUTSIDE_ROOT_NODE = 'non-whitespace outside of root node';
61
+ function error(msg) {
62
+ return new Error(msg);
63
+ }
64
+ function missingNamespaceForPrefix(prefix) {
65
+ return 'missing namespace for prefix <' + prefix + '>';
66
+ }
67
+ function getter(getFn) {
68
+ return {
69
+ 'get': getFn,
70
+ 'enumerable': true
71
+ };
72
+ }
73
+ function cloneNsMatrix(nsMatrix) {
74
+ var clone = {},
75
+ key;
76
+ for (key in nsMatrix) {
77
+ clone[key] = nsMatrix[key];
78
+ }
79
+ return clone;
80
+ }
81
+
82
+ // per-matrix element name cache; stored under a symbol so it is
83
+ // invisible to the `for (key in nsMatrix)` clone above and gets
84
+ // collected together with the matrix it belongs to
85
+ var NAME_CACHE = Symbol('nameCache');
86
+ function uriPrefix(prefix) {
87
+ return prefix + '$uri';
88
+ }
89
+ function buildNsMatrix(nsUriToPrefix) {
90
+ var nsMatrix = {},
91
+ uri,
92
+ prefix;
93
+ for (uri in nsUriToPrefix) {
94
+ prefix = nsUriToPrefix[uri];
95
+ nsMatrix[prefix] = prefix;
96
+ nsMatrix[uriPrefix(prefix)] = uri;
97
+ }
98
+ return nsMatrix;
99
+ }
100
+ function noopGetContext() {
101
+ return {
102
+ line: 0,
103
+ column: 0
104
+ };
105
+ }
106
+ function throwFunc(err) {
107
+ throw err;
108
+ }
109
+
110
+ /**
111
+ * Creates a new parser with the given options.
112
+ *
113
+ * @constructor
114
+ *
115
+ * @param {!Object<string, ?>=} options
116
+ */
117
+ function Parser(options) {
118
+ if (!this) {
119
+ return new Parser(options);
120
+ }
121
+ var proxy = options && options['proxy'];
122
+ var onText,
123
+ onOpenTag,
124
+ onCloseTag,
125
+ onCDATA,
126
+ onError = throwFunc,
127
+ onWarning,
128
+ onComment,
129
+ onQuestion,
130
+ onAttention;
131
+ var getContext = noopGetContext;
132
+
133
+ /**
134
+ * Are we currently consuming a chunked stream of XML,
135
+ * i.e. is a `write` call in progress that may be followed
136
+ * by more chunks?
137
+ *
138
+ * @type {boolean}
139
+ */
140
+ var streaming = false;
141
+
142
+ /**
143
+ * Did we already encounter the root tag?
144
+ *
145
+ * Persisted across `write` calls so we can detect a missing
146
+ * start tag once the stream ends.
147
+ *
148
+ * @type {boolean}
149
+ */
150
+ var rootTagFound = false;
151
+
152
+ /**
153
+ * Not yet parsed remainder of the previously written chunk,
154
+ * i.e. an incomplete token that awaits more input.
155
+ *
156
+ * @type {string}
157
+ */
158
+ var leftoverXml = '';
159
+
160
+ /**
161
+ * Do we need to parse the current elements attributes for namespaces?
162
+ *
163
+ * @type {boolean}
164
+ */
165
+ var maybeNS = false;
166
+
167
+ /**
168
+ * Do we process namespaces at all?
169
+ *
170
+ * @type {boolean}
171
+ */
172
+ var isNamespace = false;
173
+
174
+ /**
175
+ * The caught error returned on parse end
176
+ *
177
+ * @type {Error}
178
+ */
179
+ var returnError = null;
180
+
181
+ /**
182
+ * Should we stop parsing?
183
+ *
184
+ * @type {boolean}
185
+ */
186
+ var parseStop = false;
187
+
188
+ /**
189
+ * Namespace + node state shared across (streamed) parse runs.
190
+ */
191
+ var nsMatrixStack, nsMatrix, nodeStack;
192
+
193
+ /**
194
+ * A map of { uri: prefix } used by the parser.
195
+ *
196
+ * This map will ensure we can normalize prefixes during processing;
197
+ * for each uri, only one prefix will be exposed to the handlers.
198
+ *
199
+ * @type {!Object<string, string>}}
200
+ */
201
+ var nsUriToPrefix;
202
+
203
+ /**
204
+ * Handle parse error.
205
+ *
206
+ * @param {string|Error} err
207
+ */
208
+ function handleError(err) {
209
+ if (!(err instanceof Error)) {
210
+ err = error(err);
211
+ }
212
+ returnError = err;
213
+ onError(err, getContext);
214
+ }
215
+
216
+ /**
217
+ * Handle parse error.
218
+ *
219
+ * @param {string|Error} err
220
+ */
221
+ function handleWarning(err) {
222
+ if (!onWarning) {
223
+ return;
224
+ }
225
+ if (!(err instanceof Error)) {
226
+ err = error(err);
227
+ }
228
+ onWarning(err, getContext);
229
+ }
230
+
231
+ /**
232
+ * Register parse listener.
233
+ *
234
+ * @param {string} name
235
+ * @param {Function} cb
236
+ *
237
+ * @return {Parser}
238
+ */
239
+ this['on'] = function (name, cb) {
240
+ if (typeof cb !== 'function') {
241
+ throw error('required args <name, cb>');
242
+ }
243
+ switch (name) {
244
+ case 'openTag':
245
+ onOpenTag = cb;
246
+ break;
247
+ case 'text':
248
+ onText = cb;
249
+ break;
250
+ case 'closeTag':
251
+ onCloseTag = cb;
252
+ break;
253
+ case 'error':
254
+ onError = cb;
255
+ break;
256
+ case 'warn':
257
+ onWarning = cb;
258
+ break;
259
+ case 'cdata':
260
+ onCDATA = cb;
261
+ break;
262
+ case 'attention':
263
+ onAttention = cb;
264
+ break;
265
+ // <!XXXXX zzzz="eeee">
266
+ case 'question':
267
+ onQuestion = cb;
268
+ break;
269
+ // <? .... ?>
270
+ case 'comment':
271
+ onComment = cb;
272
+ break;
273
+ default:
274
+ throw error('unsupported event: ' + name);
275
+ }
276
+ return this;
277
+ };
278
+
279
+ /**
280
+ * Set the namespace to prefix mapping.
281
+ *
282
+ * @example
283
+ *
284
+ * parser.ns({
285
+ * 'http://foo': 'foo',
286
+ * 'http://bar': 'bar'
287
+ * });
288
+ *
289
+ * @param {!Object<string, string>} nsMap
290
+ *
291
+ * @return {Parser}
292
+ */
293
+ this['ns'] = function (nsMap) {
294
+ if (typeof nsMap === 'undefined') {
295
+ nsMap = {};
296
+ }
297
+ if (_typeof(nsMap) !== 'object') {
298
+ throw error('required args <nsMap={}>');
299
+ }
300
+ var _nsUriToPrefix = {},
301
+ k;
302
+ for (k in nsMap) {
303
+ _nsUriToPrefix[k] = nsMap[k];
304
+ }
305
+ isNamespace = true;
306
+ nsUriToPrefix = _nsUriToPrefix;
307
+ return this;
308
+ };
309
+
310
+ /**
311
+ * Reset the parser state before a (streamed) parse run.
312
+ */
313
+ function resetState() {
314
+ nsMatrixStack = isNamespace ? [] : null;
315
+ nsMatrix = isNamespace ? buildNsMatrix(nsUriToPrefix) : null;
316
+ nodeStack = [];
317
+ getContext = noopGetContext;
318
+ parseStop = false;
319
+ returnError = null;
320
+ rootTagFound = false;
321
+ leftoverXml = '';
322
+ }
323
+
324
+ /**
325
+ * Parse a complete xml string.
326
+ *
327
+ * @param {string} xml
328
+ *
329
+ * @return {Error} returnError, if not thrown
330
+ */
331
+ this['parse'] = function (xml) {
332
+ if (typeof xml !== 'string') {
333
+ throw error('required args <xml=string>');
334
+ }
335
+ if (streaming) {
336
+ throw error('parse during stream; call end() first');
337
+ }
338
+ resetState();
339
+ parse(xml);
340
+ getContext = noopGetContext;
341
+ parseStop = false;
342
+ return returnError;
343
+ };
344
+
345
+ /**
346
+ * Write the next chunk of a streamed xml string.
347
+ *
348
+ * Parse events are emitted for all complete tokens; an
349
+ * incomplete trailing token is buffered until the next
350
+ * `write` or, ultimately, reported as an error on `end`.
351
+ *
352
+ * @param {string} xml
353
+ *
354
+ * @return {Parser} self
355
+ */
356
+ this['write'] = function (xml) {
357
+ if (typeof xml !== 'string') {
358
+ throw error('required args <xml=string>');
359
+ }
360
+ if (!streaming) {
361
+ resetState();
362
+ streaming = true;
363
+ }
364
+ if (!returnError) {
365
+ leftoverXml = parse(leftoverXml + xml, true) || '';
366
+ }
367
+ return this;
368
+ };
369
+
370
+ /**
371
+ * Finish parsing a streamed xml string, i.e. signal that
372
+ * no more chunks will be written.
373
+ *
374
+ * @return {Error} returnError, if not thrown
375
+ */
376
+ this['end'] = function () {
377
+ if (!streaming) {
378
+ resetState();
379
+ }
380
+
381
+ // flush the buffered remainder, now treating an incomplete
382
+ // trailing token as a hard error
383
+ streaming = false;
384
+ if (!returnError) {
385
+ parse(leftoverXml);
386
+ }
387
+ leftoverXml = '';
388
+ getContext = noopGetContext;
389
+ parseStop = false;
390
+ return returnError;
391
+ };
392
+
393
+ /**
394
+ * Stop parsing.
395
+ */
396
+ this['stop'] = function () {
397
+ parseStop = true;
398
+ };
399
+
400
+ /**
401
+ * Parse string, invoking configured listeners on element.
402
+ *
403
+ * Namespace and node stack state is shared across (streamed)
404
+ * invocations via the enclosing parser scope.
405
+ *
406
+ * Internal note: while `streaming`, an incomplete trailing token
407
+ * is not treated as an error but returned so `write` can buffer it
408
+ * and prepend it to the next chunk. This buffered remainder is an
409
+ * implementation detail of the streaming buffer, not a public API;
410
+ * outside of that case the return value is `undefined`.
411
+ *
412
+ * @param {string} xml
413
+ * @param {boolean} streaming
414
+ *
415
+ * @return {string|undefined} buffered remainder, streaming internal use only
416
+ */
417
+ function parse(xml) {
418
+ var streaming = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
419
+ var elNameCache = null,
420
+ elNameCacheMatrix = null;
421
+ var _nsMatrix,
422
+ anonymousNsCount = 0,
423
+ tagStart = false,
424
+ tagEnd = false,
425
+ i = 0,
426
+ j = 0,
427
+ x,
428
+ y,
429
+ q,
430
+ w,
431
+ v,
432
+ xmlns,
433
+ elementName,
434
+ _elementName,
435
+ elementProxy;
436
+ var attrsString = '',
437
+ attrsStart = 0,
438
+ cachedAttrs // false = parsed with errors, null = needs parsing
439
+ ;
440
+
441
+ /**
442
+ * Normalize a namespaced attribute name against the current
443
+ * namespace matrix.
444
+ *
445
+ * @param {string} name
446
+ * @param {string|boolean} defaultAlias
447
+ *
448
+ * @return {string|null} normalized name, or `null` when the prefix
449
+ * has no namespace (a warning is emitted)
450
+ */
451
+ function normalizeAttrName(name, defaultAlias) {
452
+ var w = name.indexOf(':');
453
+ if (w === -1) {
454
+ return name;
455
+ }
456
+
457
+ // normalize ns attribute name
458
+ var nsName = nsMatrix[name.substring(0, w)];
459
+ if (!nsName) {
460
+ handleWarning(missingNamespaceForPrefix(name.substring(0, w)));
461
+ return null;
462
+ }
463
+ return defaultAlias === nsName ? name.substr(w + 1) : nsName + name.substr(w);
464
+ }
465
+
466
+ /**
467
+ * Parse attributes on demand and returns the parsed attributes.
468
+ *
469
+ * Return semantics: (1) `false` on attribute parse error,
470
+ * (2) object hash on extracted attrs.
471
+ *
472
+ * @return {boolean|Object}
473
+ */
474
+ function getAttrs() {
475
+ if (cachedAttrs !== null) {
476
+ return cachedAttrs;
477
+ }
478
+ var nsUri,
479
+ nsUriPrefix,
480
+ defaultAlias = isNamespace && nsMatrix['xmlns'],
481
+ attrList = isNamespace && maybeNS ? [] : null,
482
+ i = attrsStart,
483
+ s = attrsString,
484
+ l = s.length,
485
+ hasNewMatrix,
486
+ newalias,
487
+ value,
488
+ alias,
489
+ name,
490
+ attrs = {},
491
+ seenAttrs = new Set(),
492
+ skipAttr,
493
+ w,
494
+ j;
495
+ parseAttr: for (; i < l; i++) {
496
+ skipAttr = false;
497
+ w = s.charCodeAt(i);
498
+ if (w === 32 || w < 14 && w > 8) {
499
+ // WHITESPACE={ \f\n\r\t\v}
500
+ continue;
501
+ }
502
+
503
+ // wait for non whitespace character
504
+ if (w < 65 || w > 122 || w > 90 && w < 97) {
505
+ if (w !== 95 && w !== 58) {
506
+ // char 95"_" 58":"
507
+ handleWarning('illegal first char attribute name');
508
+ skipAttr = true;
509
+ }
510
+ }
511
+
512
+ // parse attribute name
513
+ for (j = i + 1; j < l; j++) {
514
+ w = s.charCodeAt(j);
515
+ if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 46 ||
516
+ // '.'
517
+ w === 45 ||
518
+ // '-'
519
+ w === 95 // '_'
520
+ ) {
521
+ continue;
522
+ }
523
+
524
+ // unexpected whitespace
525
+ if (w === 32 || w < 14 && w > 8) {
526
+ // WHITESPACE
527
+ handleWarning('missing attribute value');
528
+ i = j;
529
+ continue parseAttr;
530
+ }
531
+
532
+ // expected "="
533
+ if (w === 61) {
534
+ // "=" == 61
535
+ break;
536
+ }
537
+ handleWarning('illegal attribute name char');
538
+ skipAttr = true;
539
+ }
540
+ name = s.substring(i, j);
541
+ if (name === 'xmlns:xmlns') {
542
+ handleWarning('illegal declaration of xmlns');
543
+ skipAttr = true;
544
+ }
545
+ w = s.charCodeAt(j + 1);
546
+ if (w === 34) {
547
+ // '"'
548
+ j = s.indexOf('"', i = j + 2);
549
+ if (j === -1) {
550
+ j = s.indexOf('\'', i);
551
+ if (j !== -1) {
552
+ handleWarning('attribute value quote missmatch');
553
+ skipAttr = true;
554
+ }
555
+ }
556
+ } else if (w === 39) {
557
+ // "'"
558
+ j = s.indexOf('\'', i = j + 2);
559
+ if (j === -1) {
560
+ j = s.indexOf('"', i);
561
+ if (j !== -1) {
562
+ handleWarning('attribute value quote missmatch');
563
+ skipAttr = true;
564
+ }
565
+ }
566
+ } else {
567
+ handleWarning('missing attribute value quotes');
568
+ skipAttr = true;
569
+
570
+ // skip to next space
571
+ for (j = j + 1; j < l; j++) {
572
+ w = s.charCodeAt(j + 1);
573
+ if (w === 32 || w < 14 && w > 8) {
574
+ // WHITESPACE
575
+ break;
576
+ }
577
+ }
578
+ }
579
+ if (j === -1) {
580
+ handleWarning('missing closing quotes');
581
+ j = l;
582
+ skipAttr = true;
583
+ }
584
+ if (!skipAttr) {
585
+ value = s.substring(i, j);
586
+ }
587
+ i = j;
588
+
589
+ // ensure SPACE follows attribute
590
+ // skip illegal content otherwise
591
+ // example a="b"c
592
+ for (; j + 1 < l; j++) {
593
+ w = s.charCodeAt(j + 1);
594
+ if (w === 32 || w < 14 && w > 8) {
595
+ // WHITESPACE
596
+ break;
597
+ }
598
+
599
+ // FIRST ILLEGAL CHAR
600
+ if (i === j) {
601
+ handleWarning('illegal character after attribute end');
602
+ skipAttr = true;
603
+ }
604
+ }
605
+
606
+ // advance cursor to next attribute
607
+ i = j + 1;
608
+ if (skipAttr) {
609
+ continue parseAttr;
610
+ }
611
+
612
+ // check attribute re-declaration
613
+ if (seenAttrs.has(name)) {
614
+ handleWarning('attribute <' + name + '> already defined');
615
+ continue;
616
+ }
617
+ seenAttrs.add(name);
618
+ if (!isNamespace) {
619
+ attrs[name] = value;
620
+ continue;
621
+ }
622
+
623
+ // try to extract namespace information
624
+ if (maybeNS) {
625
+ newalias = name === 'xmlns' ? 'xmlns' : name.charCodeAt(0) === 120 && name.substr(0, 6) === 'xmlns:' ? name.substr(6) : null;
626
+
627
+ // handle xmlns(:alias) assignment
628
+ if (newalias !== null) {
629
+ nsUri = decodeEntities(value);
630
+ nsUriPrefix = uriPrefix(newalias);
631
+ alias = nsUriToPrefix[nsUri];
632
+ if (!alias) {
633
+ // no prefix defined or prefix collision
634
+ if (newalias === 'xmlns' || nsUriPrefix in nsMatrix && nsMatrix[nsUriPrefix] !== nsUri) {
635
+ // alocate free ns prefix
636
+ do {
637
+ alias = 'ns' + anonymousNsCount++;
638
+ } while (typeof nsMatrix[alias] !== 'undefined');
639
+ } else {
640
+ alias = newalias;
641
+ }
642
+ nsUriToPrefix[nsUri] = alias;
643
+ }
644
+ if (nsMatrix[newalias] !== alias) {
645
+ if (!hasNewMatrix) {
646
+ nsMatrix = cloneNsMatrix(nsMatrix);
647
+ hasNewMatrix = true;
648
+ }
649
+ nsMatrix[newalias] = alias;
650
+ if (newalias === 'xmlns') {
651
+ nsMatrix[uriPrefix(alias)] = nsUri;
652
+ defaultAlias = alias;
653
+ }
654
+ nsMatrix[nsUriPrefix] = nsUri;
655
+ }
656
+
657
+ // expose xmlns(:asd)="..." in attributes
658
+ attrs[name] = value;
659
+ continue;
660
+ }
661
+
662
+ // collect attributes until all namespace
663
+ // declarations are processed
664
+ attrList.push(name, value);
665
+ continue;
666
+ } /** end if (maybeNs) */
667
+
668
+ // handle attributes on element without
669
+ // namespace declarations
670
+ name = normalizeAttrName(name, defaultAlias);
671
+ if (name === null) {
672
+ continue;
673
+ }
674
+ attrs[name] = value;
675
+ }
676
+
677
+ // handle deferred, possibly namespaced attributes
678
+ if (maybeNS) {
679
+ // normalize captured attributes
680
+ for (i = 0, l = attrList.length; i < l; i++) {
681
+ name = normalizeAttrName(attrList[i++], defaultAlias);
682
+ value = attrList[i];
683
+ if (name === null) {
684
+ continue;
685
+ }
686
+ attrs[name] = value;
687
+ }
688
+
689
+ // end: normalize captured attributes
690
+ }
691
+
692
+ return cachedAttrs = attrs;
693
+ }
694
+
695
+ /**
696
+ * Extract the parse context { line, column, part }
697
+ * from the current parser position.
698
+ *
699
+ * @return {Object} parse context
700
+ */
701
+ function getParseContext() {
702
+ var splitsRe = /(\r\n|\r|\n)/g;
703
+ var line = 0;
704
+ var column = 0;
705
+ var startOfLine = 0;
706
+ var endOfLine = j;
707
+ var match;
708
+ var data;
709
+ while (i >= startOfLine) {
710
+ match = splitsRe.exec(xml);
711
+ if (!match) {
712
+ break;
713
+ }
714
+
715
+ // end of line = (break idx + break chars)
716
+ endOfLine = match[0].length + match.index;
717
+ if (endOfLine > i) {
718
+ break;
719
+ }
720
+
721
+ // advance to next line
722
+ line += 1;
723
+ startOfLine = endOfLine;
724
+ }
725
+
726
+ // EOF errors
727
+ if (i == -1) {
728
+ column = endOfLine;
729
+ data = xml.substring(j);
730
+ } else
731
+ // start errors
732
+ if (j === 0) {
733
+ data = xml.substring(j, i);
734
+ }
735
+
736
+ // other errors
737
+ else {
738
+ column = i - startOfLine;
739
+ data = j == -1 ? xml.substring(i) : xml.substring(i, j + 1);
740
+ }
741
+ return {
742
+ 'data': data,
743
+ 'line': line,
744
+ 'column': column
745
+ };
746
+ }
747
+ getContext = getParseContext;
748
+ if (proxy) {
749
+ elementProxy = Object.create({}, {
750
+ 'name': getter(function () {
751
+ return elementName;
752
+ }),
753
+ 'originalName': getter(function () {
754
+ return _elementName;
755
+ }),
756
+ 'attrs': getter(getAttrs),
757
+ 'ns': getter(function () {
758
+ return nsMatrix;
759
+ })
760
+ });
761
+ }
762
+
763
+ // actual parse logic
764
+ while (j !== -1) {
765
+ if (xml.charCodeAt(j) === 60) {
766
+ // "<"
767
+ i = j;
768
+ } else {
769
+ i = xml.indexOf('<', j);
770
+ }
771
+
772
+ // no (more) tags found
773
+ if (i === -1) {
774
+ // buffer the remainder for the next chunk
775
+ if (streaming) {
776
+ return xml.substring(j);
777
+ }
778
+ if (nodeStack.length) {
779
+ return handleError('unexpected end of file');
780
+ }
781
+ if (!rootTagFound) {
782
+ return handleError('missing start tag');
783
+ }
784
+ if (j < xml.length) {
785
+ if (xml.substring(j).trim()) {
786
+ handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
787
+ }
788
+ }
789
+ return;
790
+ }
791
+
792
+ // remember that we saw the root tag
793
+ if (!rootTagFound) {
794
+ rootTagFound = true;
795
+ }
796
+
797
+ // parse text
798
+ if (j !== i) {
799
+ if (nodeStack.length) {
800
+ if (onText) {
801
+ onText(xml.substring(j, i), decodeEntities, getContext);
802
+ if (parseStop) {
803
+ return;
804
+ }
805
+ }
806
+ } else {
807
+ if (xml.substring(j, i).trim()) {
808
+ handleWarning(NON_WHITESPACE_OUTSIDE_ROOT_NODE);
809
+ if (parseStop) {
810
+ return;
811
+ }
812
+ }
813
+ }
814
+ }
815
+ w = xml.charCodeAt(i + 1);
816
+
817
+ // parse comments + CDATA
818
+ if (w === 33) {
819
+ // "!"
820
+ q = xml.charCodeAt(i + 2);
821
+
822
+ // CDATA section
823
+ if (q === 91 && xml.substr(i + 3, 6) === 'CDATA[') {
824
+ // 91 == "["
825
+ j = xml.indexOf(']]>', i);
826
+ if (j === -1) {
827
+ if (streaming) {
828
+ return xml.substring(i);
829
+ }
830
+ return handleError('unclosed cdata');
831
+ }
832
+ if (onCDATA) {
833
+ onCDATA(xml.substring(i + 9, j), getContext);
834
+ if (parseStop) {
835
+ return;
836
+ }
837
+ }
838
+ j += 3;
839
+ continue;
840
+ }
841
+
842
+ // comment
843
+ if (q === 45 && xml.charCodeAt(i + 3) === 45) {
844
+ // 45 == "-"
845
+ j = xml.indexOf('-->', i);
846
+ if (j === -1) {
847
+ if (streaming) {
848
+ return xml.substring(i);
849
+ }
850
+ return handleError('unclosed comment');
851
+ }
852
+ if (onComment) {
853
+ onComment(xml.substring(i + 4, j), decodeEntities, getContext);
854
+ if (parseStop) {
855
+ return;
856
+ }
857
+ }
858
+ j += 3;
859
+ continue;
860
+ }
861
+ }
862
+
863
+ // parse question <? ... ?>
864
+ if (w === 63) {
865
+ // "?"
866
+ j = xml.indexOf('?>', i);
867
+ if (j === -1) {
868
+ if (streaming) {
869
+ return xml.substring(i);
870
+ }
871
+ return handleError('unclosed question');
872
+ }
873
+ if (onQuestion) {
874
+ onQuestion(xml.substring(i, j + 2), getContext);
875
+ if (parseStop) {
876
+ return;
877
+ }
878
+ }
879
+ j += 2;
880
+ continue;
881
+ }
882
+
883
+ // find matching closing tag for attention or standard tags
884
+ // for that we must skip through attribute values
885
+ // (enclosed in single or double quotes)
886
+ for (x = i + 1;; x++) {
887
+ v = xml.charCodeAt(x);
888
+ if (isNaN(v)) {
889
+ if (streaming) {
890
+ return xml.substring(i);
891
+ }
892
+ j = -1;
893
+ return handleError('unclosed tag');
894
+ }
895
+
896
+ // [10] AttValue ::= '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'"
897
+ // skips the quoted string
898
+ // (double quotes) does not appear in a literal enclosed by (double quotes)
899
+ // (single quote) does not appear in a literal enclosed by (single quote)
900
+ if (v === 34) {
901
+ // '"'
902
+ q = xml.indexOf('"', x + 1);
903
+ x = q !== -1 ? q : x;
904
+ } else if (v === 39) {
905
+ // "'"
906
+ q = xml.indexOf("'", x + 1);
907
+ x = q !== -1 ? q : x;
908
+ } else if (v === 62) {
909
+ // '>'
910
+ j = x;
911
+ break;
912
+ }
913
+ }
914
+
915
+ // parse attention <! ...>
916
+ // previously comment and CDATA have already been parsed
917
+ if (w === 33) {
918
+ // "!"
919
+
920
+ if (onAttention) {
921
+ onAttention(xml.substring(i, j + 1), decodeEntities, getContext);
922
+ if (parseStop) {
923
+ return;
924
+ }
925
+ }
926
+ j += 1;
927
+ continue;
928
+ }
929
+
930
+ // don't process attributes;
931
+ // there are none
932
+ cachedAttrs = {};
933
+
934
+ // if (xml.charCodeAt(i+1) === 47) { // </...
935
+ if (w === 47) {
936
+ // </...
937
+ tagStart = false;
938
+ tagEnd = true;
939
+ if (!nodeStack.length) {
940
+ return handleError('missing open tag');
941
+ }
942
+
943
+ // verify open <-> close tag match
944
+ x = elementName = nodeStack.pop();
945
+ q = i + 2 + x.length;
946
+ if (xml.substring(i + 2, q) !== x) {
947
+ return handleError('closing tag mismatch');
948
+ }
949
+
950
+ // verify chars in close tag
951
+ for (; q < j; q++) {
952
+ w = xml.charCodeAt(q);
953
+ if (w === 32 || w > 8 && w < 14) {
954
+ // \f\n\r\t\v space
955
+ continue;
956
+ }
957
+ return handleError('close tag');
958
+ }
959
+ } else {
960
+ if (xml.charCodeAt(j - 1) === 47) {
961
+ // .../>
962
+ x = elementName = xml.substring(i + 1, j - 1);
963
+ tagStart = true;
964
+ tagEnd = true;
965
+ } else {
966
+ x = elementName = xml.substring(i + 1, j);
967
+ tagStart = true;
968
+ tagEnd = false;
969
+ }
970
+ if (!(w > 96 && w < 123 || w > 64 && w < 91 || w === 95 || w === 58)) {
971
+ // char 95"_" 58":"
972
+ return handleError('illegal first char nodeName');
973
+ }
974
+ for (q = 1, y = x.length; q < y; q++) {
975
+ w = x.charCodeAt(q);
976
+ if (w > 96 && w < 123 || w > 64 && w < 91 || w > 47 && w < 59 || w === 45 || w === 95 || w == 46) {
977
+ continue;
978
+ }
979
+ if (w === 32 || w < 14 && w > 8) {
980
+ // \f\n\r\t\v space
981
+ elementName = x.substring(0, q);
982
+
983
+ // maybe there are attributes
984
+ cachedAttrs = null;
985
+ break;
986
+ }
987
+ return handleError('invalid nodeName');
988
+ }
989
+ if (!tagEnd) {
990
+ nodeStack.push(elementName);
991
+ }
992
+ }
993
+ if (isNamespace) {
994
+ _nsMatrix = nsMatrix;
995
+ if (tagStart) {
996
+ // remember old namespace
997
+ // unless we're self-closing
998
+ if (!tagEnd) {
999
+ nsMatrixStack.push(_nsMatrix);
1000
+ }
1001
+ if (cachedAttrs === null) {
1002
+ // quick check, whether there may be namespace
1003
+ // declarations on the node; if that is the case
1004
+ // we need to eagerly parse the node attributes
1005
+ if (maybeNS = x.indexOf('xmlns', q) !== -1) {
1006
+ attrsStart = q;
1007
+ attrsString = x;
1008
+ getAttrs();
1009
+ maybeNS = false;
1010
+ }
1011
+ }
1012
+ }
1013
+ _elementName = elementName;
1014
+
1015
+ // memoize normalized names per namespace matrix; tag names
1016
+ // typically repeat heavily and the matrix rarely changes.
1017
+ if (elNameCacheMatrix !== nsMatrix) {
1018
+ elNameCache = nsMatrix[NAME_CACHE];
1019
+ if (elNameCache === undefined) {
1020
+ elNameCache = nsMatrix[NAME_CACHE] = {};
1021
+ }
1022
+ elNameCacheMatrix = nsMatrix;
1023
+ }
1024
+ var _cachedName = elNameCache[elementName];
1025
+ if (_cachedName !== undefined) {
1026
+ elementName = _cachedName;
1027
+ } else {
1028
+ w = elementName.indexOf(':');
1029
+ if (w !== -1) {
1030
+ xmlns = nsMatrix[elementName.substring(0, w)];
1031
+
1032
+ // prefix given; namespace must exist
1033
+ if (!xmlns) {
1034
+ return handleError('missing namespace on <' + _elementName + '>');
1035
+ }
1036
+ elementName = elementName.substr(w + 1);
1037
+ } else {
1038
+ xmlns = nsMatrix['xmlns'];
1039
+
1040
+ // if no default namespace is defined,
1041
+ // we'll import the element as anonymous.
1042
+ //
1043
+ // it is up to users to correct that to the document defined
1044
+ // targetNamespace, or whatever their undersanding of the
1045
+ // XML spec mandates.
1046
+ }
1047
+
1048
+ // adjust namespace prefixs as configured
1049
+ if (xmlns) {
1050
+ elementName = xmlns + ':' + elementName;
1051
+ }
1052
+ elNameCache[_elementName] = elementName;
1053
+ }
1054
+ }
1055
+ if (tagStart) {
1056
+ attrsStart = q;
1057
+ attrsString = x;
1058
+ if (onOpenTag) {
1059
+ if (proxy) {
1060
+ onOpenTag(elementProxy, decodeEntities, tagEnd, getContext);
1061
+ } else {
1062
+ onOpenTag(elementName, getAttrs, decodeEntities, tagEnd, getContext);
1063
+ }
1064
+ if (parseStop) {
1065
+ return;
1066
+ }
1067
+ }
1068
+ }
1069
+ if (tagEnd) {
1070
+ if (onCloseTag) {
1071
+ onCloseTag(proxy ? elementProxy : elementName, decodeEntities, tagStart, getContext);
1072
+ if (parseStop) {
1073
+ return;
1074
+ }
1075
+ }
1076
+
1077
+ // restore old namespace
1078
+ if (isNamespace) {
1079
+ if (!tagStart) {
1080
+ nsMatrix = nsMatrixStack.pop();
1081
+ } else {
1082
+ nsMatrix = _nsMatrix;
1083
+ }
1084
+ }
1085
+ }
1086
+ j += 1;
1087
+ }
1088
+ } /** end parse */
1089
+ }
1090
+ }
1091
+ //# sourceMappingURL=parser.js.map