blob: 9333729bac9e487c94b7e7b034d16925517e3609 [file] [log] [blame]
Tim van der Lippe706ec962021-06-04 13:24:42 +01001(function (global, factory) {
2 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
3 typeof define === 'function' && define.amd ? define(factory) :
4 (global = global || self, global.csstree = factory());
5}(this, (function () { 'use strict';
6
7 //
8 // list
9 // ┌──────┐
10 // ┌──────────────┼─head │
11 // │ │ tail─┼──────────────┐
12 // │ └──────┘ │
13 // ▼ ▼
14 // item item item item
15 // ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
16 // null ◀──┼─prev │◀───┼─prev │◀───┼─prev │◀───┼─prev │
17 // │ next─┼───▶│ next─┼───▶│ next─┼───▶│ next─┼──▶ null
18 // ├──────┤ ├──────┤ ├──────┤ ├──────┤
19 // │ data │ │ data │ │ data │ │ data │
20 // └──────┘ └──────┘ └──────┘ └──────┘
21 //
22
23 function createItem(data) {
24 return {
25 prev: null,
26 next: null,
27 data: data
28 };
29 }
30
31 function allocateCursor(node, prev, next) {
32 var cursor;
33
34 if (cursors !== null) {
35 cursor = cursors;
36 cursors = cursors.cursor;
37 cursor.prev = prev;
38 cursor.next = next;
39 cursor.cursor = node.cursor;
40 } else {
41 cursor = {
42 prev: prev,
43 next: next,
44 cursor: node.cursor
45 };
46 }
47
48 node.cursor = cursor;
49
50 return cursor;
51 }
52
53 function releaseCursor(node) {
54 var cursor = node.cursor;
55
56 node.cursor = cursor.cursor;
57 cursor.prev = null;
58 cursor.next = null;
59 cursor.cursor = cursors;
60 cursors = cursor;
61 }
62
63 var cursors = null;
64 var List = function() {
65 this.cursor = null;
66 this.head = null;
67 this.tail = null;
68 };
69
70 List.createItem = createItem;
71 List.prototype.createItem = createItem;
72
73 List.prototype.updateCursors = function(prevOld, prevNew, nextOld, nextNew) {
74 var cursor = this.cursor;
75
76 while (cursor !== null) {
77 if (cursor.prev === prevOld) {
78 cursor.prev = prevNew;
79 }
80
81 if (cursor.next === nextOld) {
82 cursor.next = nextNew;
83 }
84
85 cursor = cursor.cursor;
86 }
87 };
88
89 List.prototype.getSize = function() {
90 var size = 0;
91 var cursor = this.head;
92
93 while (cursor) {
94 size++;
95 cursor = cursor.next;
96 }
97
98 return size;
99 };
100
101 List.prototype.fromArray = function(array) {
102 var cursor = null;
103
104 this.head = null;
105
106 for (var i = 0; i < array.length; i++) {
107 var item = createItem(array[i]);
108
109 if (cursor !== null) {
110 cursor.next = item;
111 } else {
112 this.head = item;
113 }
114
115 item.prev = cursor;
116 cursor = item;
117 }
118
119 this.tail = cursor;
120
121 return this;
122 };
123
124 List.prototype.toArray = function() {
125 var cursor = this.head;
126 var result = [];
127
128 while (cursor) {
129 result.push(cursor.data);
130 cursor = cursor.next;
131 }
132
133 return result;
134 };
135
136 List.prototype.toJSON = List.prototype.toArray;
137
138 List.prototype.isEmpty = function() {
139 return this.head === null;
140 };
141
142 List.prototype.first = function() {
143 return this.head && this.head.data;
144 };
145
146 List.prototype.last = function() {
147 return this.tail && this.tail.data;
148 };
149
150 List.prototype.each = function(fn, context) {
151 var item;
152
153 if (context === undefined) {
154 context = this;
155 }
156
157 // push cursor
158 var cursor = allocateCursor(this, null, this.head);
159
160 while (cursor.next !== null) {
161 item = cursor.next;
162 cursor.next = item.next;
163
164 fn.call(context, item.data, item, this);
165 }
166
167 // pop cursor
168 releaseCursor(this);
169 };
170
171 List.prototype.forEach = List.prototype.each;
172
173 List.prototype.eachRight = function(fn, context) {
174 var item;
175
176 if (context === undefined) {
177 context = this;
178 }
179
180 // push cursor
181 var cursor = allocateCursor(this, this.tail, null);
182
183 while (cursor.prev !== null) {
184 item = cursor.prev;
185 cursor.prev = item.prev;
186
187 fn.call(context, item.data, item, this);
188 }
189
190 // pop cursor
191 releaseCursor(this);
192 };
193
194 List.prototype.forEachRight = List.prototype.eachRight;
195
196 List.prototype.reduce = function(fn, initialValue, context) {
197 var item;
198
199 if (context === undefined) {
200 context = this;
201 }
202
203 // push cursor
204 var cursor = allocateCursor(this, null, this.head);
205 var acc = initialValue;
206
207 while (cursor.next !== null) {
208 item = cursor.next;
209 cursor.next = item.next;
210
211 acc = fn.call(context, acc, item.data, item, this);
212 }
213
214 // pop cursor
215 releaseCursor(this);
216
217 return acc;
218 };
219
220 List.prototype.reduceRight = function(fn, initialValue, context) {
221 var item;
222
223 if (context === undefined) {
224 context = this;
225 }
226
227 // push cursor
228 var cursor = allocateCursor(this, this.tail, null);
229 var acc = initialValue;
230
231 while (cursor.prev !== null) {
232 item = cursor.prev;
233 cursor.prev = item.prev;
234
235 acc = fn.call(context, acc, item.data, item, this);
236 }
237
238 // pop cursor
239 releaseCursor(this);
240
241 return acc;
242 };
243
244 List.prototype.nextUntil = function(start, fn, context) {
245 if (start === null) {
246 return;
247 }
248
249 var item;
250
251 if (context === undefined) {
252 context = this;
253 }
254
255 // push cursor
256 var cursor = allocateCursor(this, null, start);
257
258 while (cursor.next !== null) {
259 item = cursor.next;
260 cursor.next = item.next;
261
262 if (fn.call(context, item.data, item, this)) {
263 break;
264 }
265 }
266
267 // pop cursor
268 releaseCursor(this);
269 };
270
271 List.prototype.prevUntil = function(start, fn, context) {
272 if (start === null) {
273 return;
274 }
275
276 var item;
277
278 if (context === undefined) {
279 context = this;
280 }
281
282 // push cursor
283 var cursor = allocateCursor(this, start, null);
284
285 while (cursor.prev !== null) {
286 item = cursor.prev;
287 cursor.prev = item.prev;
288
289 if (fn.call(context, item.data, item, this)) {
290 break;
291 }
292 }
293
294 // pop cursor
295 releaseCursor(this);
296 };
297
298 List.prototype.some = function(fn, context) {
299 var cursor = this.head;
300
301 if (context === undefined) {
302 context = this;
303 }
304
305 while (cursor !== null) {
306 if (fn.call(context, cursor.data, cursor, this)) {
307 return true;
308 }
309
310 cursor = cursor.next;
311 }
312
313 return false;
314 };
315
316 List.prototype.map = function(fn, context) {
317 var result = new List();
318 var cursor = this.head;
319
320 if (context === undefined) {
321 context = this;
322 }
323
324 while (cursor !== null) {
325 result.appendData(fn.call(context, cursor.data, cursor, this));
326 cursor = cursor.next;
327 }
328
329 return result;
330 };
331
332 List.prototype.filter = function(fn, context) {
333 var result = new List();
334 var cursor = this.head;
335
336 if (context === undefined) {
337 context = this;
338 }
339
340 while (cursor !== null) {
341 if (fn.call(context, cursor.data, cursor, this)) {
342 result.appendData(cursor.data);
343 }
344 cursor = cursor.next;
345 }
346
347 return result;
348 };
349
350 List.prototype.clear = function() {
351 this.head = null;
352 this.tail = null;
353 };
354
355 List.prototype.copy = function() {
356 var result = new List();
357 var cursor = this.head;
358
359 while (cursor !== null) {
360 result.insert(createItem(cursor.data));
361 cursor = cursor.next;
362 }
363
364 return result;
365 };
366
367 List.prototype.prepend = function(item) {
368 // head
369 // ^
370 // item
371 this.updateCursors(null, item, this.head, item);
372
373 // insert to the beginning of the list
374 if (this.head !== null) {
375 // new item <- first item
376 this.head.prev = item;
377
378 // new item -> first item
379 item.next = this.head;
380 } else {
381 // if list has no head, then it also has no tail
382 // in this case tail points to the new item
383 this.tail = item;
384 }
385
386 // head always points to new item
387 this.head = item;
388
389 return this;
390 };
391
392 List.prototype.prependData = function(data) {
393 return this.prepend(createItem(data));
394 };
395
396 List.prototype.append = function(item) {
397 return this.insert(item);
398 };
399
400 List.prototype.appendData = function(data) {
401 return this.insert(createItem(data));
402 };
403
404 List.prototype.insert = function(item, before) {
405 if (before !== undefined && before !== null) {
406 // prev before
407 // ^
408 // item
409 this.updateCursors(before.prev, item, before, item);
410
411 if (before.prev === null) {
412 // insert to the beginning of list
413 if (this.head !== before) {
414 throw new Error('before doesn\'t belong to list');
415 }
416
417 // since head points to before therefore list doesn't empty
418 // no need to check tail
419 this.head = item;
420 before.prev = item;
421 item.next = before;
422
423 this.updateCursors(null, item);
424 } else {
425
426 // insert between two items
427 before.prev.next = item;
428 item.prev = before.prev;
429
430 before.prev = item;
431 item.next = before;
432 }
433 } else {
434 // tail
435 // ^
436 // item
437 this.updateCursors(this.tail, item, null, item);
438
439 // insert to the ending of the list
440 if (this.tail !== null) {
441 // last item -> new item
442 this.tail.next = item;
443
444 // last item <- new item
445 item.prev = this.tail;
446 } else {
447 // if list has no tail, then it also has no head
448 // in this case head points to new item
449 this.head = item;
450 }
451
452 // tail always points to new item
453 this.tail = item;
454 }
455
456 return this;
457 };
458
459 List.prototype.insertData = function(data, before) {
460 return this.insert(createItem(data), before);
461 };
462
463 List.prototype.remove = function(item) {
464 // item
465 // ^
466 // prev next
467 this.updateCursors(item, item.prev, item, item.next);
468
469 if (item.prev !== null) {
470 item.prev.next = item.next;
471 } else {
472 if (this.head !== item) {
473 throw new Error('item doesn\'t belong to list');
474 }
475
476 this.head = item.next;
477 }
478
479 if (item.next !== null) {
480 item.next.prev = item.prev;
481 } else {
482 if (this.tail !== item) {
483 throw new Error('item doesn\'t belong to list');
484 }
485
486 this.tail = item.prev;
487 }
488
489 item.prev = null;
490 item.next = null;
491
492 return item;
493 };
494
495 List.prototype.push = function(data) {
496 this.insert(createItem(data));
497 };
498
499 List.prototype.pop = function() {
500 if (this.tail !== null) {
501 return this.remove(this.tail);
502 }
503 };
504
505 List.prototype.unshift = function(data) {
506 this.prepend(createItem(data));
507 };
508
509 List.prototype.shift = function() {
510 if (this.head !== null) {
511 return this.remove(this.head);
512 }
513 };
514
515 List.prototype.prependList = function(list) {
516 return this.insertList(list, this.head);
517 };
518
519 List.prototype.appendList = function(list) {
520 return this.insertList(list);
521 };
522
523 List.prototype.insertList = function(list, before) {
524 // ignore empty lists
525 if (list.head === null) {
526 return this;
527 }
528
529 if (before !== undefined && before !== null) {
530 this.updateCursors(before.prev, list.tail, before, list.head);
531
532 // insert in the middle of dist list
533 if (before.prev !== null) {
534 // before.prev <-> list.head
535 before.prev.next = list.head;
536 list.head.prev = before.prev;
537 } else {
538 this.head = list.head;
539 }
540
541 before.prev = list.tail;
542 list.tail.next = before;
543 } else {
544 this.updateCursors(this.tail, list.tail, null, list.head);
545
546 // insert to end of the list
547 if (this.tail !== null) {
548 // if destination list has a tail, then it also has a head,
549 // but head doesn't change
550
551 // dest tail -> source head
552 this.tail.next = list.head;
553
554 // dest tail <- source head
555 list.head.prev = this.tail;
556 } else {
557 // if list has no a tail, then it also has no a head
558 // in this case points head to new item
559 this.head = list.head;
560 }
561
562 // tail always start point to new item
563 this.tail = list.tail;
564 }
565
566 list.head = null;
567 list.tail = null;
568
569 return this;
570 };
571
572 List.prototype.replace = function(oldItem, newItemOrList) {
573 if ('head' in newItemOrList) {
574 this.insertList(newItemOrList, oldItem);
575 } else {
576 this.insert(newItemOrList, oldItem);
577 }
578
579 this.remove(oldItem);
580 };
581
582 var List_1 = List;
583
584 var createCustomError = function createCustomError(name, message) {
585 // use Object.create(), because some VMs prevent setting line/column otherwise
586 // (iOS Safari 10 even throws an exception)
587 var error = Object.create(SyntaxError.prototype);
588 var errorStack = new Error();
589
590 error.name = name;
591 error.message = message;
592
593 Object.defineProperty(error, 'stack', {
594 get: function() {
595 return (errorStack.stack || '').replace(/^(.+\n){1,3}/, name + ': ' + message + '\n');
596 }
597 });
598
599 return error;
600 };
601
602 var MAX_LINE_LENGTH = 100;
603 var OFFSET_CORRECTION = 60;
604 var TAB_REPLACEMENT = ' ';
605
606 function sourceFragment(error, extraLines) {
607 function processLines(start, end) {
608 return lines.slice(start, end).map(function(line, idx) {
609 var num = String(start + idx + 1);
610
611 while (num.length < maxNumLength) {
612 num = ' ' + num;
613 }
614
615 return num + ' |' + line;
616 }).join('\n');
617 }
618
619 var lines = error.source.split(/\r\n?|\n|\f/);
620 var line = error.line;
621 var column = error.column;
622 var startLine = Math.max(1, line - extraLines) - 1;
623 var endLine = Math.min(line + extraLines, lines.length + 1);
624 var maxNumLength = Math.max(4, String(endLine).length) + 1;
625 var cutLeft = 0;
626
627 // column correction according to replaced tab before column
628 column += (TAB_REPLACEMENT.length - 1) * (lines[line - 1].substr(0, column - 1).match(/\t/g) || []).length;
629
630 if (column > MAX_LINE_LENGTH) {
631 cutLeft = column - OFFSET_CORRECTION + 3;
632 column = OFFSET_CORRECTION - 2;
633 }
634
635 for (var i = startLine; i <= endLine; i++) {
636 if (i >= 0 && i < lines.length) {
637 lines[i] = lines[i].replace(/\t/g, TAB_REPLACEMENT);
638 lines[i] =
639 (cutLeft > 0 && lines[i].length > cutLeft ? '\u2026' : '') +
640 lines[i].substr(cutLeft, MAX_LINE_LENGTH - 2) +
641 (lines[i].length > cutLeft + MAX_LINE_LENGTH - 1 ? '\u2026' : '');
642 }
643 }
644
645 return [
646 processLines(startLine, line),
647 new Array(column + maxNumLength + 2).join('-') + '^',
648 processLines(line, endLine)
649 ].filter(Boolean).join('\n');
650 }
651
652 var SyntaxError$1 = function(message, source, offset, line, column) {
653 var error = createCustomError('SyntaxError', message);
654
655 error.source = source;
656 error.offset = offset;
657 error.line = line;
658 error.column = column;
659
660 error.sourceFragment = function(extraLines) {
661 return sourceFragment(error, isNaN(extraLines) ? 0 : extraLines);
662 };
663 Object.defineProperty(error, 'formattedMessage', {
664 get: function() {
665 return (
666 'Parse error: ' + error.message + '\n' +
667 sourceFragment(error, 2)
668 );
669 }
670 });
671
672 // for backward capability
673 error.parseError = {
674 offset: offset,
675 line: line,
676 column: column
677 };
678
679 return error;
680 };
681
682 var _SyntaxError = SyntaxError$1;
683
684 // CSS Syntax Module Level 3
685 // https://www.w3.org/TR/css-syntax-3/
686 var TYPE = {
687 EOF: 0, // <EOF-token>
688 Ident: 1, // <ident-token>
689 Function: 2, // <function-token>
690 AtKeyword: 3, // <at-keyword-token>
691 Hash: 4, // <hash-token>
692 String: 5, // <string-token>
693 BadString: 6, // <bad-string-token>
694 Url: 7, // <url-token>
695 BadUrl: 8, // <bad-url-token>
696 Delim: 9, // <delim-token>
697 Number: 10, // <number-token>
698 Percentage: 11, // <percentage-token>
699 Dimension: 12, // <dimension-token>
700 WhiteSpace: 13, // <whitespace-token>
701 CDO: 14, // <CDO-token>
702 CDC: 15, // <CDC-token>
703 Colon: 16, // <colon-token> :
704 Semicolon: 17, // <semicolon-token> ;
705 Comma: 18, // <comma-token> ,
706 LeftSquareBracket: 19, // <[-token>
707 RightSquareBracket: 20, // <]-token>
708 LeftParenthesis: 21, // <(-token>
709 RightParenthesis: 22, // <)-token>
710 LeftCurlyBracket: 23, // <{-token>
711 RightCurlyBracket: 24, // <}-token>
712 Comment: 25
713 };
714
715 var NAME = Object.keys(TYPE).reduce(function(result, key) {
716 result[TYPE[key]] = key;
717 return result;
718 }, {});
719
720 var _const = {
721 TYPE: TYPE,
722 NAME: NAME
723 };
724
725 var EOF = 0;
726
727 // https://drafts.csswg.org/css-syntax-3/
728 // § 4.2. Definitions
729
730 // digit
731 // A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9).
732 function isDigit(code) {
733 return code >= 0x0030 && code <= 0x0039;
734 }
735
736 // hex digit
737 // A digit, or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F),
738 // or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f).
739 function isHexDigit(code) {
740 return (
741 isDigit(code) || // 0 .. 9
742 (code >= 0x0041 && code <= 0x0046) || // A .. F
743 (code >= 0x0061 && code <= 0x0066) // a .. f
744 );
745 }
746
747 // uppercase letter
748 // A code point between U+0041 LATIN CAPITAL LETTER A (A) and U+005A LATIN CAPITAL LETTER Z (Z).
749 function isUppercaseLetter(code) {
750 return code >= 0x0041 && code <= 0x005A;
751 }
752
753 // lowercase letter
754 // A code point between U+0061 LATIN SMALL LETTER A (a) and U+007A LATIN SMALL LETTER Z (z).
755 function isLowercaseLetter(code) {
756 return code >= 0x0061 && code <= 0x007A;
757 }
758
759 // letter
760 // An uppercase letter or a lowercase letter.
761 function isLetter(code) {
762 return isUppercaseLetter(code) || isLowercaseLetter(code);
763 }
764
765 // non-ASCII code point
766 // A code point with a value equal to or greater than U+0080 <control>.
767 function isNonAscii(code) {
768 return code >= 0x0080;
769 }
770
771 // name-start code point
772 // A letter, a non-ASCII code point, or U+005F LOW LINE (_).
773 function isNameStart(code) {
774 return isLetter(code) || isNonAscii(code) || code === 0x005F;
775 }
776
777 // name code point
778 // A name-start code point, a digit, or U+002D HYPHEN-MINUS (-).
779 function isName(code) {
780 return isNameStart(code) || isDigit(code) || code === 0x002D;
781 }
782
783 // non-printable code point
784 // A code point between U+0000 NULL and U+0008 BACKSPACE, or U+000B LINE TABULATION,
785 // or a code point between U+000E SHIFT OUT and U+001F INFORMATION SEPARATOR ONE, or U+007F DELETE.
786 function isNonPrintable(code) {
787 return (
788 (code >= 0x0000 && code <= 0x0008) ||
789 (code === 0x000B) ||
790 (code >= 0x000E && code <= 0x001F) ||
791 (code === 0x007F)
792 );
793 }
794
795 // newline
796 // U+000A LINE FEED. Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition,
797 // as they are converted to U+000A LINE FEED during preprocessing.
798 // TODO: we doesn't do a preprocessing, so check a code point for U+000D CARRIAGE RETURN and U+000C FORM FEED
799 function isNewline(code) {
800 return code === 0x000A || code === 0x000D || code === 0x000C;
801 }
802
803 // whitespace
804 // A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE.
805 function isWhiteSpace(code) {
806 return isNewline(code) || code === 0x0020 || code === 0x0009;
807 }
808
809 // § 4.3.8. Check if two code points are a valid escape
810 function isValidEscape(first, second) {
811 // If the first code point is not U+005C REVERSE SOLIDUS (\), return false.
812 if (first !== 0x005C) {
813 return false;
814 }
815
816 // Otherwise, if the second code point is a newline or EOF, return false.
817 if (isNewline(second) || second === EOF) {
818 return false;
819 }
820
821 // Otherwise, return true.
822 return true;
823 }
824
825 // § 4.3.9. Check if three code points would start an identifier
826 function isIdentifierStart(first, second, third) {
827 // Look at the first code point:
828
829 // U+002D HYPHEN-MINUS
830 if (first === 0x002D) {
831 // If the second code point is a name-start code point or a U+002D HYPHEN-MINUS,
832 // or the second and third code points are a valid escape, return true. Otherwise, return false.
833 return (
834 isNameStart(second) ||
835 second === 0x002D ||
836 isValidEscape(second, third)
837 );
838 }
839
840 // name-start code point
841 if (isNameStart(first)) {
842 // Return true.
843 return true;
844 }
845
846 // U+005C REVERSE SOLIDUS (\)
847 if (first === 0x005C) {
848 // If the first and second code points are a valid escape, return true. Otherwise, return false.
849 return isValidEscape(first, second);
850 }
851
852 // anything else
853 // Return false.
854 return false;
855 }
856
857 // § 4.3.10. Check if three code points would start a number
858 function isNumberStart(first, second, third) {
859 // Look at the first code point:
860
861 // U+002B PLUS SIGN (+)
862 // U+002D HYPHEN-MINUS (-)
863 if (first === 0x002B || first === 0x002D) {
864 // If the second code point is a digit, return true.
865 if (isDigit(second)) {
866 return 2;
867 }
868
869 // Otherwise, if the second code point is a U+002E FULL STOP (.)
870 // and the third code point is a digit, return true.
871 // Otherwise, return false.
872 return second === 0x002E && isDigit(third) ? 3 : 0;
873 }
874
875 // U+002E FULL STOP (.)
876 if (first === 0x002E) {
877 // If the second code point is a digit, return true. Otherwise, return false.
878 return isDigit(second) ? 2 : 0;
879 }
880
881 // digit
882 if (isDigit(first)) {
883 // Return true.
884 return 1;
885 }
886
887 // anything else
888 // Return false.
889 return 0;
890 }
891
892 //
893 // Misc
894 //
895
896 // detect BOM (https://en.wikipedia.org/wiki/Byte_order_mark)
897 function isBOM(code) {
898 // UTF-16BE
899 if (code === 0xFEFF) {
900 return 1;
901 }
902
903 // UTF-16LE
904 if (code === 0xFFFE) {
905 return 1;
906 }
907
908 return 0;
909 }
910
911 // Fast code category
912 //
913 // https://drafts.csswg.org/css-syntax/#tokenizer-definitions
914 // > non-ASCII code point
915 // > A code point with a value equal to or greater than U+0080 <control>
916 // > name-start code point
917 // > A letter, a non-ASCII code point, or U+005F LOW LINE (_).
918 // > name code point
919 // > A name-start code point, a digit, or U+002D HYPHEN-MINUS (-)
920 // That means only ASCII code points has a special meaning and we define a maps for 0..127 codes only
921 var CATEGORY = new Array(0x80);
922 charCodeCategory.Eof = 0x80;
923 charCodeCategory.WhiteSpace = 0x82;
924 charCodeCategory.Digit = 0x83;
925 charCodeCategory.NameStart = 0x84;
926 charCodeCategory.NonPrintable = 0x85;
927
928 for (var i = 0; i < CATEGORY.length; i++) {
929 switch (true) {
930 case isWhiteSpace(i):
931 CATEGORY[i] = charCodeCategory.WhiteSpace;
932 break;
933
934 case isDigit(i):
935 CATEGORY[i] = charCodeCategory.Digit;
936 break;
937
938 case isNameStart(i):
939 CATEGORY[i] = charCodeCategory.NameStart;
940 break;
941
942 case isNonPrintable(i):
943 CATEGORY[i] = charCodeCategory.NonPrintable;
944 break;
945
946 default:
947 CATEGORY[i] = i || charCodeCategory.Eof;
948 }
949 }
950
951 function charCodeCategory(code) {
952 return code < 0x80 ? CATEGORY[code] : charCodeCategory.NameStart;
953 }
954 var charCodeDefinitions = {
955 isDigit: isDigit,
956 isHexDigit: isHexDigit,
957 isUppercaseLetter: isUppercaseLetter,
958 isLowercaseLetter: isLowercaseLetter,
959 isLetter: isLetter,
960 isNonAscii: isNonAscii,
961 isNameStart: isNameStart,
962 isName: isName,
963 isNonPrintable: isNonPrintable,
964 isNewline: isNewline,
965 isWhiteSpace: isWhiteSpace,
966 isValidEscape: isValidEscape,
967 isIdentifierStart: isIdentifierStart,
968 isNumberStart: isNumberStart,
969
970 isBOM: isBOM,
971 charCodeCategory: charCodeCategory
972 };
973
974 var isDigit$1 = charCodeDefinitions.isDigit;
975 var isHexDigit$1 = charCodeDefinitions.isHexDigit;
976 var isUppercaseLetter$1 = charCodeDefinitions.isUppercaseLetter;
977 var isName$1 = charCodeDefinitions.isName;
978 var isWhiteSpace$1 = charCodeDefinitions.isWhiteSpace;
979 var isValidEscape$1 = charCodeDefinitions.isValidEscape;
980
981 function getCharCode(source, offset) {
982 return offset < source.length ? source.charCodeAt(offset) : 0;
983 }
984
985 function getNewlineLength(source, offset, code) {
986 if (code === 13 /* \r */ && getCharCode(source, offset + 1) === 10 /* \n */) {
987 return 2;
988 }
989
990 return 1;
991 }
992
993 function cmpChar(testStr, offset, referenceCode) {
994 var code = testStr.charCodeAt(offset);
995
996 // code.toLowerCase() for A..Z
997 if (isUppercaseLetter$1(code)) {
998 code = code | 32;
999 }
1000
1001 return code === referenceCode;
1002 }
1003
1004 function cmpStr(testStr, start, end, referenceStr) {
1005 if (end - start !== referenceStr.length) {
1006 return false;
1007 }
1008
1009 if (start < 0 || end > testStr.length) {
1010 return false;
1011 }
1012
1013 for (var i = start; i < end; i++) {
1014 var testCode = testStr.charCodeAt(i);
1015 var referenceCode = referenceStr.charCodeAt(i - start);
1016
1017 // testCode.toLowerCase() for A..Z
1018 if (isUppercaseLetter$1(testCode)) {
1019 testCode = testCode | 32;
1020 }
1021
1022 if (testCode !== referenceCode) {
1023 return false;
1024 }
1025 }
1026
1027 return true;
1028 }
1029
1030 function findWhiteSpaceStart(source, offset) {
1031 for (; offset >= 0; offset--) {
1032 if (!isWhiteSpace$1(source.charCodeAt(offset))) {
1033 break;
1034 }
1035 }
1036
1037 return offset + 1;
1038 }
1039
1040 function findWhiteSpaceEnd(source, offset) {
1041 for (; offset < source.length; offset++) {
1042 if (!isWhiteSpace$1(source.charCodeAt(offset))) {
1043 break;
1044 }
1045 }
1046
1047 return offset;
1048 }
1049
1050 function findDecimalNumberEnd(source, offset) {
1051 for (; offset < source.length; offset++) {
1052 if (!isDigit$1(source.charCodeAt(offset))) {
1053 break;
1054 }
1055 }
1056
1057 return offset;
1058 }
1059
1060 // § 4.3.7. Consume an escaped code point
1061 function consumeEscaped(source, offset) {
1062 // It assumes that the U+005C REVERSE SOLIDUS (\) has already been consumed and
1063 // that the next input code point has already been verified to be part of a valid escape.
1064 offset += 2;
1065
1066 // hex digit
1067 if (isHexDigit$1(getCharCode(source, offset - 1))) {
1068 // Consume as many hex digits as possible, but no more than 5.
1069 // Note that this means 1-6 hex digits have been consumed in total.
1070 for (var maxOffset = Math.min(source.length, offset + 5); offset < maxOffset; offset++) {
1071 if (!isHexDigit$1(getCharCode(source, offset))) {
1072 break;
1073 }
1074 }
1075
1076 // If the next input code point is whitespace, consume it as well.
1077 var code = getCharCode(source, offset);
1078 if (isWhiteSpace$1(code)) {
1079 offset += getNewlineLength(source, offset, code);
1080 }
1081 }
1082
1083 return offset;
1084 }
1085
1086 // §4.3.11. Consume a name
1087 // Note: This algorithm does not do the verification of the first few code points that are necessary
1088 // to ensure the returned code points would constitute an <ident-token>. If that is the intended use,
1089 // ensure that the stream starts with an identifier before calling this algorithm.
1090 function consumeName(source, offset) {
1091 // Let result initially be an empty string.
1092 // Repeatedly consume the next input code point from the stream:
1093 for (; offset < source.length; offset++) {
1094 var code = source.charCodeAt(offset);
1095
1096 // name code point
1097 if (isName$1(code)) {
1098 // Append the code point to result.
1099 continue;
1100 }
1101
1102 // the stream starts with a valid escape
1103 if (isValidEscape$1(code, getCharCode(source, offset + 1))) {
1104 // Consume an escaped code point. Append the returned code point to result.
1105 offset = consumeEscaped(source, offset) - 1;
1106 continue;
1107 }
1108
1109 // anything else
1110 // Reconsume the current input code point. Return result.
1111 break;
1112 }
1113
1114 return offset;
1115 }
1116
1117 // §4.3.12. Consume a number
1118 function consumeNumber(source, offset) {
1119 var code = source.charCodeAt(offset);
1120
1121 // 2. If the next input code point is U+002B PLUS SIGN (+) or U+002D HYPHEN-MINUS (-),
1122 // consume it and append it to repr.
1123 if (code === 0x002B || code === 0x002D) {
1124 code = source.charCodeAt(offset += 1);
1125 }
1126
1127 // 3. While the next input code point is a digit, consume it and append it to repr.
1128 if (isDigit$1(code)) {
1129 offset = findDecimalNumberEnd(source, offset + 1);
1130 code = source.charCodeAt(offset);
1131 }
1132
1133 // 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then:
1134 if (code === 0x002E && isDigit$1(source.charCodeAt(offset + 1))) {
1135 // 4.1 Consume them.
1136 // 4.2 Append them to repr.
1137 code = source.charCodeAt(offset += 2);
1138
1139 // 4.3 Set type to "number".
1140 // TODO
1141
1142 // 4.4 While the next input code point is a digit, consume it and append it to repr.
1143
1144 offset = findDecimalNumberEnd(source, offset);
1145 }
1146
1147 // 5. If the next 2 or 3 input code points are U+0045 LATIN CAPITAL LETTER E (E)
1148 // or U+0065 LATIN SMALL LETTER E (e), ... , followed by a digit, then:
1149 if (cmpChar(source, offset, 101 /* e */)) {
1150 var sign = 0;
1151 code = source.charCodeAt(offset + 1);
1152
1153 // ... optionally followed by U+002D HYPHEN-MINUS (-) or U+002B PLUS SIGN (+) ...
1154 if (code === 0x002D || code === 0x002B) {
1155 sign = 1;
1156 code = source.charCodeAt(offset + 2);
1157 }
1158
1159 // ... followed by a digit
1160 if (isDigit$1(code)) {
1161 // 5.1 Consume them.
1162 // 5.2 Append them to repr.
1163
1164 // 5.3 Set type to "number".
1165 // TODO
1166
1167 // 5.4 While the next input code point is a digit, consume it and append it to repr.
1168 offset = findDecimalNumberEnd(source, offset + 1 + sign + 1);
1169 }
1170 }
1171
1172 return offset;
1173 }
1174
1175 // § 4.3.14. Consume the remnants of a bad url
1176 // ... its sole use is to consume enough of the input stream to reach a recovery point
1177 // where normal tokenizing can resume.
1178 function consumeBadUrlRemnants(source, offset) {
1179 // Repeatedly consume the next input code point from the stream:
1180 for (; offset < source.length; offset++) {
1181 var code = source.charCodeAt(offset);
1182
1183 // U+0029 RIGHT PARENTHESIS ())
1184 // EOF
1185 if (code === 0x0029) {
1186 // Return.
1187 offset++;
1188 break;
1189 }
1190
1191 if (isValidEscape$1(code, getCharCode(source, offset + 1))) {
1192 // Consume an escaped code point.
1193 // Note: This allows an escaped right parenthesis ("\)") to be encountered
1194 // without ending the <bad-url-token>. This is otherwise identical to
1195 // the "anything else" clause.
1196 offset = consumeEscaped(source, offset);
1197 }
1198 }
1199
1200 return offset;
1201 }
1202
1203 var utils = {
1204 consumeEscaped: consumeEscaped,
1205 consumeName: consumeName,
1206 consumeNumber: consumeNumber,
1207 consumeBadUrlRemnants: consumeBadUrlRemnants,
1208
1209 cmpChar: cmpChar,
1210 cmpStr: cmpStr,
1211
1212 getNewlineLength: getNewlineLength,
1213 findWhiteSpaceStart: findWhiteSpaceStart,
1214 findWhiteSpaceEnd: findWhiteSpaceEnd
1215 };
1216
1217 var TYPE$1 = _const.TYPE;
1218 var NAME$1 = _const.NAME;
1219
1220
1221 var cmpStr$1 = utils.cmpStr;
1222
1223 var EOF$1 = TYPE$1.EOF;
1224 var WHITESPACE = TYPE$1.WhiteSpace;
1225 var COMMENT = TYPE$1.Comment;
1226
1227 var OFFSET_MASK = 0x00FFFFFF;
1228 var TYPE_SHIFT = 24;
1229
1230 var TokenStream = function() {
1231 this.offsetAndType = null;
1232 this.balance = null;
1233
1234 this.reset();
1235 };
1236
1237 TokenStream.prototype = {
1238 reset: function() {
1239 this.eof = false;
1240 this.tokenIndex = -1;
1241 this.tokenType = 0;
1242 this.tokenStart = this.firstCharOffset;
1243 this.tokenEnd = this.firstCharOffset;
1244 },
1245
1246 lookupType: function(offset) {
1247 offset += this.tokenIndex;
1248
1249 if (offset < this.tokenCount) {
1250 return this.offsetAndType[offset] >> TYPE_SHIFT;
1251 }
1252
1253 return EOF$1;
1254 },
1255 lookupOffset: function(offset) {
1256 offset += this.tokenIndex;
1257
1258 if (offset < this.tokenCount) {
1259 return this.offsetAndType[offset - 1] & OFFSET_MASK;
1260 }
1261
1262 return this.source.length;
1263 },
1264 lookupValue: function(offset, referenceStr) {
1265 offset += this.tokenIndex;
1266
1267 if (offset < this.tokenCount) {
1268 return cmpStr$1(
1269 this.source,
1270 this.offsetAndType[offset - 1] & OFFSET_MASK,
1271 this.offsetAndType[offset] & OFFSET_MASK,
1272 referenceStr
1273 );
1274 }
1275
1276 return false;
1277 },
1278 getTokenStart: function(tokenIndex) {
1279 if (tokenIndex === this.tokenIndex) {
1280 return this.tokenStart;
1281 }
1282
1283 if (tokenIndex > 0) {
1284 return tokenIndex < this.tokenCount
1285 ? this.offsetAndType[tokenIndex - 1] & OFFSET_MASK
1286 : this.offsetAndType[this.tokenCount] & OFFSET_MASK;
1287 }
1288
1289 return this.firstCharOffset;
1290 },
1291
1292 // TODO: -> skipUntilBalanced
1293 getRawLength: function(startToken, mode) {
1294 var cursor = startToken;
1295 var balanceEnd;
1296 var offset = this.offsetAndType[Math.max(cursor - 1, 0)] & OFFSET_MASK;
1297 var type;
1298
1299 loop:
1300 for (; cursor < this.tokenCount; cursor++) {
1301 balanceEnd = this.balance[cursor];
1302
1303 // stop scanning on balance edge that points to offset before start token
1304 if (balanceEnd < startToken) {
1305 break loop;
1306 }
1307
1308 type = this.offsetAndType[cursor] >> TYPE_SHIFT;
1309
1310 // check token is stop type
1311 switch (mode(type, this.source, offset)) {
1312 case 1:
1313 break loop;
1314
1315 case 2:
1316 cursor++;
1317 break loop;
1318
1319 default:
1320 // fast forward to the end of balanced block
1321 if (this.balance[balanceEnd] === cursor) {
1322 cursor = balanceEnd;
1323 }
1324
1325 offset = this.offsetAndType[cursor] & OFFSET_MASK;
1326 }
1327 }
1328
1329 return cursor - this.tokenIndex;
1330 },
1331 isBalanceEdge: function(pos) {
1332 return this.balance[this.tokenIndex] < pos;
1333 },
1334 isDelim: function(code, offset) {
1335 if (offset) {
1336 return (
1337 this.lookupType(offset) === TYPE$1.Delim &&
1338 this.source.charCodeAt(this.lookupOffset(offset)) === code
1339 );
1340 }
1341
1342 return (
1343 this.tokenType === TYPE$1.Delim &&
1344 this.source.charCodeAt(this.tokenStart) === code
1345 );
1346 },
1347
1348 getTokenValue: function() {
1349 return this.source.substring(this.tokenStart, this.tokenEnd);
1350 },
1351 getTokenLength: function() {
1352 return this.tokenEnd - this.tokenStart;
1353 },
1354 substrToCursor: function(start) {
1355 return this.source.substring(start, this.tokenStart);
1356 },
1357
1358 skipWS: function() {
1359 for (var i = this.tokenIndex, skipTokenCount = 0; i < this.tokenCount; i++, skipTokenCount++) {
1360 if ((this.offsetAndType[i] >> TYPE_SHIFT) !== WHITESPACE) {
1361 break;
1362 }
1363 }
1364
1365 if (skipTokenCount > 0) {
1366 this.skip(skipTokenCount);
1367 }
1368 },
1369 skipSC: function() {
1370 while (this.tokenType === WHITESPACE || this.tokenType === COMMENT) {
1371 this.next();
1372 }
1373 },
1374 skip: function(tokenCount) {
1375 var next = this.tokenIndex + tokenCount;
1376
1377 if (next < this.tokenCount) {
1378 this.tokenIndex = next;
1379 this.tokenStart = this.offsetAndType[next - 1] & OFFSET_MASK;
1380 next = this.offsetAndType[next];
1381 this.tokenType = next >> TYPE_SHIFT;
1382 this.tokenEnd = next & OFFSET_MASK;
1383 } else {
1384 this.tokenIndex = this.tokenCount;
1385 this.next();
1386 }
1387 },
1388 next: function() {
1389 var next = this.tokenIndex + 1;
1390
1391 if (next < this.tokenCount) {
1392 this.tokenIndex = next;
1393 this.tokenStart = this.tokenEnd;
1394 next = this.offsetAndType[next];
1395 this.tokenType = next >> TYPE_SHIFT;
1396 this.tokenEnd = next & OFFSET_MASK;
1397 } else {
1398 this.tokenIndex = this.tokenCount;
1399 this.eof = true;
1400 this.tokenType = EOF$1;
1401 this.tokenStart = this.tokenEnd = this.source.length;
1402 }
1403 },
1404
1405 forEachToken(fn) {
1406 for (var i = 0, offset = this.firstCharOffset; i < this.tokenCount; i++) {
1407 var start = offset;
1408 var item = this.offsetAndType[i];
1409 var end = item & OFFSET_MASK;
1410 var type = item >> TYPE_SHIFT;
1411
1412 offset = end;
1413
1414 fn(type, start, end, i);
1415 }
1416 },
1417
1418 dump() {
1419 var tokens = new Array(this.tokenCount);
1420
1421 this.forEachToken((type, start, end, index) => {
1422 tokens[index] = {
1423 idx: index,
1424 type: NAME$1[type],
1425 chunk: this.source.substring(start, end),
1426 balance: this.balance[index]
1427 };
1428 });
1429
1430 return tokens;
1431 }
1432 };
1433
1434 var TokenStream_1 = TokenStream;
1435
1436 function noop(value) {
1437 return value;
1438 }
1439
1440 function generateMultiplier(multiplier) {
1441 if (multiplier.min === 0 && multiplier.max === 0) {
1442 return '*';
1443 }
1444
1445 if (multiplier.min === 0 && multiplier.max === 1) {
1446 return '?';
1447 }
1448
1449 if (multiplier.min === 1 && multiplier.max === 0) {
1450 return multiplier.comma ? '#' : '+';
1451 }
1452
1453 if (multiplier.min === 1 && multiplier.max === 1) {
1454 return '';
1455 }
1456
1457 return (
1458 (multiplier.comma ? '#' : '') +
1459 (multiplier.min === multiplier.max
1460 ? '{' + multiplier.min + '}'
1461 : '{' + multiplier.min + ',' + (multiplier.max !== 0 ? multiplier.max : '') + '}'
1462 )
1463 );
1464 }
1465
1466 function generateTypeOpts(node) {
1467 switch (node.type) {
1468 case 'Range':
1469 return (
1470 ' [' +
1471 (node.min === null ? '-∞' : node.min) +
1472 ',' +
1473 (node.max === null ? '∞' : node.max) +
1474 ']'
1475 );
1476
1477 default:
1478 throw new Error('Unknown node type `' + node.type + '`');
1479 }
1480 }
1481
1482 function generateSequence(node, decorate, forceBraces, compact) {
1483 var combinator = node.combinator === ' ' || compact ? node.combinator : ' ' + node.combinator + ' ';
1484 var result = node.terms.map(function(term) {
1485 return generate(term, decorate, forceBraces, compact);
1486 }).join(combinator);
1487
1488 if (node.explicit || forceBraces) {
1489 result = (compact || result[0] === ',' ? '[' : '[ ') + result + (compact ? ']' : ' ]');
1490 }
1491
1492 return result;
1493 }
1494
1495 function generate(node, decorate, forceBraces, compact) {
1496 var result;
1497
1498 switch (node.type) {
1499 case 'Group':
1500 result =
1501 generateSequence(node, decorate, forceBraces, compact) +
1502 (node.disallowEmpty ? '!' : '');
1503 break;
1504
1505 case 'Multiplier':
1506 // return since node is a composition
1507 return (
1508 generate(node.term, decorate, forceBraces, compact) +
1509 decorate(generateMultiplier(node), node)
1510 );
1511
1512 case 'Type':
1513 result = '<' + node.name + (node.opts ? decorate(generateTypeOpts(node.opts), node.opts) : '') + '>';
1514 break;
1515
1516 case 'Property':
1517 result = '<\'' + node.name + '\'>';
1518 break;
1519
1520 case 'Keyword':
1521 result = node.name;
1522 break;
1523
1524 case 'AtKeyword':
1525 result = '@' + node.name;
1526 break;
1527
1528 case 'Function':
1529 result = node.name + '(';
1530 break;
1531
1532 case 'String':
1533 case 'Token':
1534 result = node.value;
1535 break;
1536
1537 case 'Comma':
1538 result = ',';
1539 break;
1540
1541 default:
1542 throw new Error('Unknown node type `' + node.type + '`');
1543 }
1544
1545 return decorate(result, node);
1546 }
1547
1548 var generate_1 = function(node, options) {
1549 var decorate = noop;
1550 var forceBraces = false;
1551 var compact = false;
1552
1553 if (typeof options === 'function') {
1554 decorate = options;
1555 } else if (options) {
1556 forceBraces = Boolean(options.forceBraces);
1557 compact = Boolean(options.compact);
1558 if (typeof options.decorate === 'function') {
1559 decorate = options.decorate;
1560 }
1561 }
1562
1563 return generate(node, decorate, forceBraces, compact);
1564 };
1565
1566 const defaultLoc = { offset: 0, line: 1, column: 1 };
1567
1568 function locateMismatch(matchResult, node) {
1569 const tokens = matchResult.tokens;
1570 const longestMatch = matchResult.longestMatch;
1571 const mismatchNode = longestMatch < tokens.length ? tokens[longestMatch].node || null : null;
1572 const badNode = mismatchNode !== node ? mismatchNode : null;
1573 let mismatchOffset = 0;
1574 let mismatchLength = 0;
1575 let entries = 0;
1576 let css = '';
1577 let start;
1578 let end;
1579
1580 for (let i = 0; i < tokens.length; i++) {
1581 const token = tokens[i].value;
1582
1583 if (i === longestMatch) {
1584 mismatchLength = token.length;
1585 mismatchOffset = css.length;
1586 }
1587
1588 if (badNode !== null && tokens[i].node === badNode) {
1589 if (i <= longestMatch) {
1590 entries++;
1591 } else {
1592 entries = 0;
1593 }
1594 }
1595
1596 css += token;
1597 }
1598
1599 if (longestMatch === tokens.length || entries > 1) { // last
1600 start = fromLoc(badNode || node, 'end') || buildLoc(defaultLoc, css);
1601 end = buildLoc(start);
1602 } else {
1603 start = fromLoc(badNode, 'start') ||
1604 buildLoc(fromLoc(node, 'start') || defaultLoc, css.slice(0, mismatchOffset));
1605 end = fromLoc(badNode, 'end') ||
1606 buildLoc(start, css.substr(mismatchOffset, mismatchLength));
1607 }
1608
1609 return {
1610 css,
1611 mismatchOffset,
1612 mismatchLength,
1613 start,
1614 end
1615 };
1616 }
1617
1618 function fromLoc(node, point) {
1619 const value = node && node.loc && node.loc[point];
1620
1621 if (value) {
1622 return 'line' in value ? buildLoc(value) : value;
1623 }
1624
1625 return null;
1626 }
1627
1628 function buildLoc({ offset, line, column }, extra) {
1629 const loc = {
1630 offset,
1631 line,
1632 column
1633 };
1634
1635 if (extra) {
1636 const lines = extra.split(/\n|\r\n?|\f/);
1637
1638 loc.offset += extra.length;
1639 loc.line += lines.length - 1;
1640 loc.column = lines.length === 1 ? loc.column + extra.length : lines.pop().length + 1;
1641 }
1642
1643 return loc;
1644 }
1645
1646 const SyntaxReferenceError = function(type, referenceName) {
1647 const error = createCustomError(
1648 'SyntaxReferenceError',
1649 type + (referenceName ? ' `' + referenceName + '`' : '')
1650 );
1651
1652 error.reference = referenceName;
1653
1654 return error;
1655 };
1656
1657 const SyntaxMatchError = function(message, syntax, node, matchResult) {
1658 const error = createCustomError('SyntaxMatchError', message);
1659 const {
1660 css,
1661 mismatchOffset,
1662 mismatchLength,
1663 start,
1664 end
1665 } = locateMismatch(matchResult, node);
1666
1667 error.rawMessage = message;
1668 error.syntax = syntax ? generate_1(syntax) : '<generic>';
1669 error.css = css;
1670 error.mismatchOffset = mismatchOffset;
1671 error.mismatchLength = mismatchLength;
1672 error.message = message + '\n' +
1673 ' syntax: ' + error.syntax + '\n' +
1674 ' value: ' + (css || '<empty string>') + '\n' +
1675 ' --------' + new Array(error.mismatchOffset + 1).join('-') + '^';
1676
1677 Object.assign(error, start);
1678 error.loc = {
1679 source: (node && node.loc && node.loc.source) || '<unknown>',
1680 start,
1681 end
1682 };
1683
1684 return error;
1685 };
1686
1687 var error = {
1688 SyntaxReferenceError,
1689 SyntaxMatchError
1690 };
1691
1692 var hasOwnProperty = Object.prototype.hasOwnProperty;
1693 var keywords = Object.create(null);
1694 var properties = Object.create(null);
1695 var HYPHENMINUS = 45; // '-'.charCodeAt()
1696
1697 function isCustomProperty(str, offset) {
1698 offset = offset || 0;
1699
1700 return str.length - offset >= 2 &&
1701 str.charCodeAt(offset) === HYPHENMINUS &&
1702 str.charCodeAt(offset + 1) === HYPHENMINUS;
1703 }
1704
1705 function getVendorPrefix(str, offset) {
1706 offset = offset || 0;
1707
1708 // verdor prefix should be at least 3 chars length
1709 if (str.length - offset >= 3) {
1710 // vendor prefix starts with hyper minus following non-hyper minus
1711 if (str.charCodeAt(offset) === HYPHENMINUS &&
1712 str.charCodeAt(offset + 1) !== HYPHENMINUS) {
1713 // vendor prefix should contain a hyper minus at the ending
1714 var secondDashIndex = str.indexOf('-', offset + 2);
1715
1716 if (secondDashIndex !== -1) {
1717 return str.substring(offset, secondDashIndex + 1);
1718 }
1719 }
1720 }
1721
1722 return '';
1723 }
1724
1725 function getKeywordDescriptor(keyword) {
1726 if (hasOwnProperty.call(keywords, keyword)) {
1727 return keywords[keyword];
1728 }
1729
1730 var name = keyword.toLowerCase();
1731
1732 if (hasOwnProperty.call(keywords, name)) {
1733 return keywords[keyword] = keywords[name];
1734 }
1735
1736 var custom = isCustomProperty(name, 0);
1737 var vendor = !custom ? getVendorPrefix(name, 0) : '';
1738
1739 return keywords[keyword] = Object.freeze({
1740 basename: name.substr(vendor.length),
1741 name: name,
1742 vendor: vendor,
1743 prefix: vendor,
1744 custom: custom
1745 });
1746 }
1747
1748 function getPropertyDescriptor(property) {
1749 if (hasOwnProperty.call(properties, property)) {
1750 return properties[property];
1751 }
1752
1753 var name = property;
1754 var hack = property[0];
1755
1756 if (hack === '/') {
1757 hack = property[1] === '/' ? '//' : '/';
1758 } else if (hack !== '_' &&
1759 hack !== '*' &&
1760 hack !== '$' &&
1761 hack !== '#' &&
1762 hack !== '+' &&
1763 hack !== '&') {
1764 hack = '';
1765 }
1766
1767 var custom = isCustomProperty(name, hack.length);
1768
1769 // re-use result when possible (the same as for lower case)
1770 if (!custom) {
1771 name = name.toLowerCase();
1772 if (hasOwnProperty.call(properties, name)) {
1773 return properties[property] = properties[name];
1774 }
1775 }
1776
1777 var vendor = !custom ? getVendorPrefix(name, hack.length) : '';
1778 var prefix = name.substr(0, hack.length + vendor.length);
1779
1780 return properties[property] = Object.freeze({
1781 basename: name.substr(prefix.length),
1782 name: name.substr(hack.length),
1783 hack: hack,
1784 vendor: vendor,
1785 prefix: prefix,
1786 custom: custom
1787 });
1788 }
1789
1790 var names = {
1791 keyword: getKeywordDescriptor,
1792 property: getPropertyDescriptor,
1793 isCustomProperty: isCustomProperty,
1794 vendorPrefix: getVendorPrefix
1795 };
1796
1797 var MIN_SIZE = 16 * 1024;
1798 var SafeUint32Array = typeof Uint32Array !== 'undefined' ? Uint32Array : Array; // fallback on Array when TypedArray is not supported
1799
1800 var adoptBuffer = function adoptBuffer(buffer, size) {
1801 if (buffer === null || buffer.length < size) {
1802 return new SafeUint32Array(Math.max(size + 1024, MIN_SIZE));
1803 }
1804
1805 return buffer;
1806 };
1807
1808 var TYPE$2 = _const.TYPE;
1809
1810
1811 var isNewline$1 = charCodeDefinitions.isNewline;
1812 var isName$2 = charCodeDefinitions.isName;
1813 var isValidEscape$2 = charCodeDefinitions.isValidEscape;
1814 var isNumberStart$1 = charCodeDefinitions.isNumberStart;
1815 var isIdentifierStart$1 = charCodeDefinitions.isIdentifierStart;
1816 var charCodeCategory$1 = charCodeDefinitions.charCodeCategory;
1817 var isBOM$1 = charCodeDefinitions.isBOM;
1818
1819
1820 var cmpStr$2 = utils.cmpStr;
1821 var getNewlineLength$1 = utils.getNewlineLength;
1822 var findWhiteSpaceEnd$1 = utils.findWhiteSpaceEnd;
1823 var consumeEscaped$1 = utils.consumeEscaped;
1824 var consumeName$1 = utils.consumeName;
1825 var consumeNumber$1 = utils.consumeNumber;
1826 var consumeBadUrlRemnants$1 = utils.consumeBadUrlRemnants;
1827
1828 var OFFSET_MASK$1 = 0x00FFFFFF;
1829 var TYPE_SHIFT$1 = 24;
1830
1831 function tokenize(source, stream) {
1832 function getCharCode(offset) {
1833 return offset < sourceLength ? source.charCodeAt(offset) : 0;
1834 }
1835
1836 // § 4.3.3. Consume a numeric token
1837 function consumeNumericToken() {
1838 // Consume a number and let number be the result.
1839 offset = consumeNumber$1(source, offset);
1840
1841 // If the next 3 input code points would start an identifier, then:
1842 if (isIdentifierStart$1(getCharCode(offset), getCharCode(offset + 1), getCharCode(offset + 2))) {
1843 // Create a <dimension-token> with the same value and type flag as number, and a unit set initially to the empty string.
1844 // Consume a name. Set the <dimension-token>’s unit to the returned value.
1845 // Return the <dimension-token>.
1846 type = TYPE$2.Dimension;
1847 offset = consumeName$1(source, offset);
1848 return;
1849 }
1850
1851 // Otherwise, if the next input code point is U+0025 PERCENTAGE SIGN (%), consume it.
1852 if (getCharCode(offset) === 0x0025) {
1853 // Create a <percentage-token> with the same value as number, and return it.
1854 type = TYPE$2.Percentage;
1855 offset++;
1856 return;
1857 }
1858
1859 // Otherwise, create a <number-token> with the same value and type flag as number, and return it.
1860 type = TYPE$2.Number;
1861 }
1862
1863 // § 4.3.4. Consume an ident-like token
1864 function consumeIdentLikeToken() {
1865 const nameStartOffset = offset;
1866
1867 // Consume a name, and let string be the result.
1868 offset = consumeName$1(source, offset);
1869
1870 // If string’s value is an ASCII case-insensitive match for "url",
1871 // and the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
1872 if (cmpStr$2(source, nameStartOffset, offset, 'url') && getCharCode(offset) === 0x0028) {
1873 // While the next two input code points are whitespace, consume the next input code point.
1874 offset = findWhiteSpaceEnd$1(source, offset + 1);
1875
1876 // If the next one or two input code points are U+0022 QUOTATION MARK ("), U+0027 APOSTROPHE ('),
1877 // or whitespace followed by U+0022 QUOTATION MARK (") or U+0027 APOSTROPHE ('),
1878 // then create a <function-token> with its value set to string and return it.
1879 if (getCharCode(offset) === 0x0022 ||
1880 getCharCode(offset) === 0x0027) {
1881 type = TYPE$2.Function;
1882 offset = nameStartOffset + 4;
1883 return;
1884 }
1885
1886 // Otherwise, consume a url token, and return it.
1887 consumeUrlToken();
1888 return;
1889 }
1890
1891 // Otherwise, if the next input code point is U+0028 LEFT PARENTHESIS ((), consume it.
1892 // Create a <function-token> with its value set to string and return it.
1893 if (getCharCode(offset) === 0x0028) {
1894 type = TYPE$2.Function;
1895 offset++;
1896 return;
1897 }
1898
1899 // Otherwise, create an <ident-token> with its value set to string and return it.
1900 type = TYPE$2.Ident;
1901 }
1902
1903 // § 4.3.5. Consume a string token
1904 function consumeStringToken(endingCodePoint) {
1905 // This algorithm may be called with an ending code point, which denotes the code point
1906 // that ends the string. If an ending code point is not specified,
1907 // the current input code point is used.
1908 if (!endingCodePoint) {
1909 endingCodePoint = getCharCode(offset++);
1910 }
1911
1912 // Initially create a <string-token> with its value set to the empty string.
1913 type = TYPE$2.String;
1914
1915 // Repeatedly consume the next input code point from the stream:
1916 for (; offset < source.length; offset++) {
1917 var code = source.charCodeAt(offset);
1918
1919 switch (charCodeCategory$1(code)) {
1920 // ending code point
1921 case endingCodePoint:
1922 // Return the <string-token>.
1923 offset++;
1924 return;
1925
1926 // EOF
1927 case charCodeCategory$1.Eof:
1928 // This is a parse error. Return the <string-token>.
1929 return;
1930
1931 // newline
1932 case charCodeCategory$1.WhiteSpace:
1933 if (isNewline$1(code)) {
1934 // This is a parse error. Reconsume the current input code point,
1935 // create a <bad-string-token>, and return it.
1936 offset += getNewlineLength$1(source, offset, code);
1937 type = TYPE$2.BadString;
1938 return;
1939 }
1940 break;
1941
1942 // U+005C REVERSE SOLIDUS (\)
1943 case 0x005C:
1944 // If the next input code point is EOF, do nothing.
1945 if (offset === source.length - 1) {
1946 break;
1947 }
1948
1949 var nextCode = getCharCode(offset + 1);
1950
1951 // Otherwise, if the next input code point is a newline, consume it.
1952 if (isNewline$1(nextCode)) {
1953 offset += getNewlineLength$1(source, offset + 1, nextCode);
1954 } else if (isValidEscape$2(code, nextCode)) {
1955 // Otherwise, (the stream starts with a valid escape) consume
1956 // an escaped code point and append the returned code point to
1957 // the <string-token>’s value.
1958 offset = consumeEscaped$1(source, offset) - 1;
1959 }
1960 break;
1961
1962 // anything else
1963 // Append the current input code point to the <string-token>’s value.
1964 }
1965 }
1966 }
1967
1968 // § 4.3.6. Consume a url token
1969 // Note: This algorithm assumes that the initial "url(" has already been consumed.
1970 // This algorithm also assumes that it’s being called to consume an "unquoted" value, like url(foo).
1971 // A quoted value, like url("foo"), is parsed as a <function-token>. Consume an ident-like token
1972 // automatically handles this distinction; this algorithm shouldn’t be called directly otherwise.
1973 function consumeUrlToken() {
1974 // Initially create a <url-token> with its value set to the empty string.
1975 type = TYPE$2.Url;
1976
1977 // Consume as much whitespace as possible.
1978 offset = findWhiteSpaceEnd$1(source, offset);
1979
1980 // Repeatedly consume the next input code point from the stream:
1981 for (; offset < source.length; offset++) {
1982 var code = source.charCodeAt(offset);
1983
1984 switch (charCodeCategory$1(code)) {
1985 // U+0029 RIGHT PARENTHESIS ())
1986 case 0x0029:
1987 // Return the <url-token>.
1988 offset++;
1989 return;
1990
1991 // EOF
1992 case charCodeCategory$1.Eof:
1993 // This is a parse error. Return the <url-token>.
1994 return;
1995
1996 // whitespace
1997 case charCodeCategory$1.WhiteSpace:
1998 // Consume as much whitespace as possible.
1999 offset = findWhiteSpaceEnd$1(source, offset);
2000
2001 // If the next input code point is U+0029 RIGHT PARENTHESIS ()) or EOF,
2002 // consume it and return the <url-token>
2003 // (if EOF was encountered, this is a parse error);
2004 if (getCharCode(offset) === 0x0029 || offset >= source.length) {
2005 if (offset < source.length) {
2006 offset++;
2007 }
2008 return;
2009 }
2010
2011 // otherwise, consume the remnants of a bad url, create a <bad-url-token>,
2012 // and return it.
2013 offset = consumeBadUrlRemnants$1(source, offset);
2014 type = TYPE$2.BadUrl;
2015 return;
2016
2017 // U+0022 QUOTATION MARK (")
2018 // U+0027 APOSTROPHE (')
2019 // U+0028 LEFT PARENTHESIS (()
2020 // non-printable code point
2021 case 0x0022:
2022 case 0x0027:
2023 case 0x0028:
2024 case charCodeCategory$1.NonPrintable:
2025 // This is a parse error. Consume the remnants of a bad url,
2026 // create a <bad-url-token>, and return it.
2027 offset = consumeBadUrlRemnants$1(source, offset);
2028 type = TYPE$2.BadUrl;
2029 return;
2030
2031 // U+005C REVERSE SOLIDUS (\)
2032 case 0x005C:
2033 // If the stream starts with a valid escape, consume an escaped code point and
2034 // append the returned code point to the <url-token>’s value.
2035 if (isValidEscape$2(code, getCharCode(offset + 1))) {
2036 offset = consumeEscaped$1(source, offset) - 1;
2037 break;
2038 }
2039
2040 // Otherwise, this is a parse error. Consume the remnants of a bad url,
2041 // create a <bad-url-token>, and return it.
2042 offset = consumeBadUrlRemnants$1(source, offset);
2043 type = TYPE$2.BadUrl;
2044 return;
2045
2046 // anything else
2047 // Append the current input code point to the <url-token>’s value.
2048 }
2049 }
2050 }
2051
2052 if (!stream) {
2053 stream = new TokenStream_1();
2054 }
2055
2056 // ensure source is a string
2057 source = String(source || '');
2058
2059 var sourceLength = source.length;
2060 var offsetAndType = adoptBuffer(stream.offsetAndType, sourceLength + 1); // +1 because of eof-token
2061 var balance = adoptBuffer(stream.balance, sourceLength + 1);
2062 var tokenCount = 0;
2063 var start = isBOM$1(getCharCode(0));
2064 var offset = start;
2065 var balanceCloseType = 0;
2066 var balanceStart = 0;
2067 var balancePrev = 0;
2068
2069 // https://drafts.csswg.org/css-syntax-3/#consume-token
2070 // § 4.3.1. Consume a token
2071 while (offset < sourceLength) {
2072 var code = source.charCodeAt(offset);
2073 var type = 0;
2074
2075 balance[tokenCount] = sourceLength;
2076
2077 switch (charCodeCategory$1(code)) {
2078 // whitespace
2079 case charCodeCategory$1.WhiteSpace:
2080 // Consume as much whitespace as possible. Return a <whitespace-token>.
2081 type = TYPE$2.WhiteSpace;
2082 offset = findWhiteSpaceEnd$1(source, offset + 1);
2083 break;
2084
2085 // U+0022 QUOTATION MARK (")
2086 case 0x0022:
2087 // Consume a string token and return it.
2088 consumeStringToken();
2089 break;
2090
2091 // U+0023 NUMBER SIGN (#)
2092 case 0x0023:
2093 // If the next input code point is a name code point or the next two input code points are a valid escape, then:
2094 if (isName$2(getCharCode(offset + 1)) || isValidEscape$2(getCharCode(offset + 1), getCharCode(offset + 2))) {
2095 // Create a <hash-token>.
2096 type = TYPE$2.Hash;
2097
2098 // If the next 3 input code points would start an identifier, set the <hash-token>’s type flag to "id".
2099 // if (isIdentifierStart(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
2100 // // TODO: set id flag
2101 // }
2102
2103 // Consume a name, and set the <hash-token>’s value to the returned string.
2104 offset = consumeName$1(source, offset + 1);
2105
2106 // Return the <hash-token>.
2107 } else {
2108 // Otherwise, return a <delim-token> with its value set to the current input code point.
2109 type = TYPE$2.Delim;
2110 offset++;
2111 }
2112
2113 break;
2114
2115 // U+0027 APOSTROPHE (')
2116 case 0x0027:
2117 // Consume a string token and return it.
2118 consumeStringToken();
2119 break;
2120
2121 // U+0028 LEFT PARENTHESIS (()
2122 case 0x0028:
2123 // Return a <(-token>.
2124 type = TYPE$2.LeftParenthesis;
2125 offset++;
2126 break;
2127
2128 // U+0029 RIGHT PARENTHESIS ())
2129 case 0x0029:
2130 // Return a <)-token>.
2131 type = TYPE$2.RightParenthesis;
2132 offset++;
2133 break;
2134
2135 // U+002B PLUS SIGN (+)
2136 case 0x002B:
2137 // If the input stream starts with a number, ...
2138 if (isNumberStart$1(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
2139 // ... reconsume the current input code point, consume a numeric token, and return it.
2140 consumeNumericToken();
2141 } else {
2142 // Otherwise, return a <delim-token> with its value set to the current input code point.
2143 type = TYPE$2.Delim;
2144 offset++;
2145 }
2146 break;
2147
2148 // U+002C COMMA (,)
2149 case 0x002C:
2150 // Return a <comma-token>.
2151 type = TYPE$2.Comma;
2152 offset++;
2153 break;
2154
2155 // U+002D HYPHEN-MINUS (-)
2156 case 0x002D:
2157 // If the input stream starts with a number, reconsume the current input code point, consume a numeric token, and return it.
2158 if (isNumberStart$1(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
2159 consumeNumericToken();
2160 } else {
2161 // Otherwise, if the next 2 input code points are U+002D HYPHEN-MINUS U+003E GREATER-THAN SIGN (->), consume them and return a <CDC-token>.
2162 if (getCharCode(offset + 1) === 0x002D &&
2163 getCharCode(offset + 2) === 0x003E) {
2164 type = TYPE$2.CDC;
2165 offset = offset + 3;
2166 } else {
2167 // Otherwise, if the input stream starts with an identifier, ...
2168 if (isIdentifierStart$1(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
2169 // ... reconsume the current input code point, consume an ident-like token, and return it.
2170 consumeIdentLikeToken();
2171 } else {
2172 // Otherwise, return a <delim-token> with its value set to the current input code point.
2173 type = TYPE$2.Delim;
2174 offset++;
2175 }
2176 }
2177 }
2178 break;
2179
2180 // U+002E FULL STOP (.)
2181 case 0x002E:
2182 // If the input stream starts with a number, ...
2183 if (isNumberStart$1(code, getCharCode(offset + 1), getCharCode(offset + 2))) {
2184 // ... reconsume the current input code point, consume a numeric token, and return it.
2185 consumeNumericToken();
2186 } else {
2187 // Otherwise, return a <delim-token> with its value set to the current input code point.
2188 type = TYPE$2.Delim;
2189 offset++;
2190 }
2191
2192 break;
2193
2194 // U+002F SOLIDUS (/)
2195 case 0x002F:
2196 // If the next two input code point are U+002F SOLIDUS (/) followed by a U+002A ASTERISK (*),
2197 if (getCharCode(offset + 1) === 0x002A) {
2198 // ... consume them and all following code points up to and including the first U+002A ASTERISK (*)
2199 // followed by a U+002F SOLIDUS (/), or up to an EOF code point.
2200 type = TYPE$2.Comment;
2201 offset = source.indexOf('*/', offset + 2) + 2;
2202 if (offset === 1) {
2203 offset = source.length;
2204 }
2205 } else {
2206 type = TYPE$2.Delim;
2207 offset++;
2208 }
2209 break;
2210
2211 // U+003A COLON (:)
2212 case 0x003A:
2213 // Return a <colon-token>.
2214 type = TYPE$2.Colon;
2215 offset++;
2216 break;
2217
2218 // U+003B SEMICOLON (;)
2219 case 0x003B:
2220 // Return a <semicolon-token>.
2221 type = TYPE$2.Semicolon;
2222 offset++;
2223 break;
2224
2225 // U+003C LESS-THAN SIGN (<)
2226 case 0x003C:
2227 // If the next 3 input code points are U+0021 EXCLAMATION MARK U+002D HYPHEN-MINUS U+002D HYPHEN-MINUS (!--), ...
2228 if (getCharCode(offset + 1) === 0x0021 &&
2229 getCharCode(offset + 2) === 0x002D &&
2230 getCharCode(offset + 3) === 0x002D) {
2231 // ... consume them and return a <CDO-token>.
2232 type = TYPE$2.CDO;
2233 offset = offset + 4;
2234 } else {
2235 // Otherwise, return a <delim-token> with its value set to the current input code point.
2236 type = TYPE$2.Delim;
2237 offset++;
2238 }
2239
2240 break;
2241
2242 // U+0040 COMMERCIAL AT (@)
2243 case 0x0040:
2244 // If the next 3 input code points would start an identifier, ...
2245 if (isIdentifierStart$1(getCharCode(offset + 1), getCharCode(offset + 2), getCharCode(offset + 3))) {
2246 // ... consume a name, create an <at-keyword-token> with its value set to the returned value, and return it.
2247 type = TYPE$2.AtKeyword;
2248 offset = consumeName$1(source, offset + 1);
2249 } else {
2250 // Otherwise, return a <delim-token> with its value set to the current input code point.
2251 type = TYPE$2.Delim;
2252 offset++;
2253 }
2254
2255 break;
2256
2257 // U+005B LEFT SQUARE BRACKET ([)
2258 case 0x005B:
2259 // Return a <[-token>.
2260 type = TYPE$2.LeftSquareBracket;
2261 offset++;
2262 break;
2263
2264 // U+005C REVERSE SOLIDUS (\)
2265 case 0x005C:
2266 // If the input stream starts with a valid escape, ...
2267 if (isValidEscape$2(code, getCharCode(offset + 1))) {
2268 // ... reconsume the current input code point, consume an ident-like token, and return it.
2269 consumeIdentLikeToken();
2270 } else {
2271 // Otherwise, this is a parse error. Return a <delim-token> with its value set to the current input code point.
2272 type = TYPE$2.Delim;
2273 offset++;
2274 }
2275 break;
2276
2277 // U+005D RIGHT SQUARE BRACKET (])
2278 case 0x005D:
2279 // Return a <]-token>.
2280 type = TYPE$2.RightSquareBracket;
2281 offset++;
2282 break;
2283
2284 // U+007B LEFT CURLY BRACKET ({)
2285 case 0x007B:
2286 // Return a <{-token>.
2287 type = TYPE$2.LeftCurlyBracket;
2288 offset++;
2289 break;
2290
2291 // U+007D RIGHT CURLY BRACKET (})
2292 case 0x007D:
2293 // Return a <}-token>.
2294 type = TYPE$2.RightCurlyBracket;
2295 offset++;
2296 break;
2297
2298 // digit
2299 case charCodeCategory$1.Digit:
2300 // Reconsume the current input code point, consume a numeric token, and return it.
2301 consumeNumericToken();
2302 break;
2303
2304 // name-start code point
2305 case charCodeCategory$1.NameStart:
2306 // Reconsume the current input code point, consume an ident-like token, and return it.
2307 consumeIdentLikeToken();
2308 break;
2309
2310 // EOF
2311 case charCodeCategory$1.Eof:
2312 // Return an <EOF-token>.
2313 break;
2314
2315 // anything else
2316 default:
2317 // Return a <delim-token> with its value set to the current input code point.
2318 type = TYPE$2.Delim;
2319 offset++;
2320 }
2321
2322 switch (type) {
2323 case balanceCloseType:
2324 balancePrev = balanceStart & OFFSET_MASK$1;
2325 balanceStart = balance[balancePrev];
2326 balanceCloseType = balanceStart >> TYPE_SHIFT$1;
2327 balance[tokenCount] = balancePrev;
2328 balance[balancePrev++] = tokenCount;
2329 for (; balancePrev < tokenCount; balancePrev++) {
2330 if (balance[balancePrev] === sourceLength) {
2331 balance[balancePrev] = tokenCount;
2332 }
2333 }
2334 break;
2335
2336 case TYPE$2.LeftParenthesis:
2337 case TYPE$2.Function:
2338 balance[tokenCount] = balanceStart;
2339 balanceCloseType = TYPE$2.RightParenthesis;
2340 balanceStart = (balanceCloseType << TYPE_SHIFT$1) | tokenCount;
2341 break;
2342
2343 case TYPE$2.LeftSquareBracket:
2344 balance[tokenCount] = balanceStart;
2345 balanceCloseType = TYPE$2.RightSquareBracket;
2346 balanceStart = (balanceCloseType << TYPE_SHIFT$1) | tokenCount;
2347 break;
2348
2349 case TYPE$2.LeftCurlyBracket:
2350 balance[tokenCount] = balanceStart;
2351 balanceCloseType = TYPE$2.RightCurlyBracket;
2352 balanceStart = (balanceCloseType << TYPE_SHIFT$1) | tokenCount;
2353 break;
2354 }
2355
2356 offsetAndType[tokenCount++] = (type << TYPE_SHIFT$1) | offset;
2357 }
2358
2359 // finalize buffers
2360 offsetAndType[tokenCount] = (TYPE$2.EOF << TYPE_SHIFT$1) | offset; // <EOF-token>
2361 balance[tokenCount] = sourceLength;
2362 balance[sourceLength] = sourceLength; // prevents false positive balance match with any token
2363 while (balanceStart !== 0) {
2364 balancePrev = balanceStart & OFFSET_MASK$1;
2365 balanceStart = balance[balancePrev];
2366 balance[balancePrev] = sourceLength;
2367 }
2368
2369 // update stream
2370 stream.source = source;
2371 stream.firstCharOffset = start;
2372 stream.offsetAndType = offsetAndType;
2373 stream.tokenCount = tokenCount;
2374 stream.balance = balance;
2375 stream.reset();
2376 stream.next();
2377
2378 return stream;
2379 }
2380
2381 // extend tokenizer with constants
2382 Object.keys(_const).forEach(function(key) {
2383 tokenize[key] = _const[key];
2384 });
2385
2386 // extend tokenizer with static methods from utils
2387 Object.keys(charCodeDefinitions).forEach(function(key) {
2388 tokenize[key] = charCodeDefinitions[key];
2389 });
2390 Object.keys(utils).forEach(function(key) {
2391 tokenize[key] = utils[key];
2392 });
2393
2394 var tokenizer = tokenize;
2395
2396 var isDigit$2 = tokenizer.isDigit;
2397 var cmpChar$1 = tokenizer.cmpChar;
2398 var TYPE$3 = tokenizer.TYPE;
2399
2400 var DELIM = TYPE$3.Delim;
2401 var WHITESPACE$1 = TYPE$3.WhiteSpace;
2402 var COMMENT$1 = TYPE$3.Comment;
2403 var IDENT = TYPE$3.Ident;
2404 var NUMBER = TYPE$3.Number;
2405 var DIMENSION = TYPE$3.Dimension;
2406 var PLUSSIGN = 0x002B; // U+002B PLUS SIGN (+)
2407 var HYPHENMINUS$1 = 0x002D; // U+002D HYPHEN-MINUS (-)
2408 var N = 0x006E; // U+006E LATIN SMALL LETTER N (n)
2409 var DISALLOW_SIGN = true;
2410 var ALLOW_SIGN = false;
2411
2412 function isDelim(token, code) {
2413 return token !== null && token.type === DELIM && token.value.charCodeAt(0) === code;
2414 }
2415
2416 function skipSC(token, offset, getNextToken) {
2417 while (token !== null && (token.type === WHITESPACE$1 || token.type === COMMENT$1)) {
2418 token = getNextToken(++offset);
2419 }
2420
2421 return offset;
2422 }
2423
2424 function checkInteger(token, valueOffset, disallowSign, offset) {
2425 if (!token) {
2426 return 0;
2427 }
2428
2429 var code = token.value.charCodeAt(valueOffset);
2430
2431 if (code === PLUSSIGN || code === HYPHENMINUS$1) {
2432 if (disallowSign) {
2433 // Number sign is not allowed
2434 return 0;
2435 }
2436 valueOffset++;
2437 }
2438
2439 for (; valueOffset < token.value.length; valueOffset++) {
2440 if (!isDigit$2(token.value.charCodeAt(valueOffset))) {
2441 // Integer is expected
2442 return 0;
2443 }
2444 }
2445
2446 return offset + 1;
2447 }
2448
2449 // ... <signed-integer>
2450 // ... ['+' | '-'] <signless-integer>
2451 function consumeB(token, offset_, getNextToken) {
2452 var sign = false;
2453 var offset = skipSC(token, offset_, getNextToken);
2454
2455 token = getNextToken(offset);
2456
2457 if (token === null) {
2458 return offset_;
2459 }
2460
2461 if (token.type !== NUMBER) {
2462 if (isDelim(token, PLUSSIGN) || isDelim(token, HYPHENMINUS$1)) {
2463 sign = true;
2464 offset = skipSC(getNextToken(++offset), offset, getNextToken);
2465 token = getNextToken(offset);
2466
2467 if (token === null && token.type !== NUMBER) {
2468 return 0;
2469 }
2470 } else {
2471 return offset_;
2472 }
2473 }
2474
2475 if (!sign) {
2476 var code = token.value.charCodeAt(0);
2477 if (code !== PLUSSIGN && code !== HYPHENMINUS$1) {
2478 // Number sign is expected
2479 return 0;
2480 }
2481 }
2482
2483 return checkInteger(token, sign ? 0 : 1, sign, offset);
2484 }
2485
2486 // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
2487 var genericAnPlusB = function anPlusB(token, getNextToken) {
2488 /* eslint-disable brace-style*/
2489 var offset = 0;
2490
2491 if (!token) {
2492 return 0;
2493 }
2494
2495 // <integer>
2496 if (token.type === NUMBER) {
2497 return checkInteger(token, 0, ALLOW_SIGN, offset); // b
2498 }
2499
2500 // -n
2501 // -n <signed-integer>
2502 // -n ['+' | '-'] <signless-integer>
2503 // -n- <signless-integer>
2504 // <dashndashdigit-ident>
2505 else if (token.type === IDENT && token.value.charCodeAt(0) === HYPHENMINUS$1) {
2506 // expect 1st char is N
2507 if (!cmpChar$1(token.value, 1, N)) {
2508 return 0;
2509 }
2510
2511 switch (token.value.length) {
2512 // -n
2513 // -n <signed-integer>
2514 // -n ['+' | '-'] <signless-integer>
2515 case 2:
2516 return consumeB(getNextToken(++offset), offset, getNextToken);
2517
2518 // -n- <signless-integer>
2519 case 3:
2520 if (token.value.charCodeAt(2) !== HYPHENMINUS$1) {
2521 return 0;
2522 }
2523
2524 offset = skipSC(getNextToken(++offset), offset, getNextToken);
2525 token = getNextToken(offset);
2526
2527 return checkInteger(token, 0, DISALLOW_SIGN, offset);
2528
2529 // <dashndashdigit-ident>
2530 default:
2531 if (token.value.charCodeAt(2) !== HYPHENMINUS$1) {
2532 return 0;
2533 }
2534
2535 return checkInteger(token, 3, DISALLOW_SIGN, offset);
2536 }
2537 }
2538
2539 // '+'? n
2540 // '+'? n <signed-integer>
2541 // '+'? n ['+' | '-'] <signless-integer>
2542 // '+'? n- <signless-integer>
2543 // '+'? <ndashdigit-ident>
2544 else if (token.type === IDENT || (isDelim(token, PLUSSIGN) && getNextToken(offset + 1).type === IDENT)) {
2545 // just ignore a plus
2546 if (token.type !== IDENT) {
2547 token = getNextToken(++offset);
2548 }
2549
2550 if (token === null || !cmpChar$1(token.value, 0, N)) {
2551 return 0;
2552 }
2553
2554 switch (token.value.length) {
2555 // '+'? n
2556 // '+'? n <signed-integer>
2557 // '+'? n ['+' | '-'] <signless-integer>
2558 case 1:
2559 return consumeB(getNextToken(++offset), offset, getNextToken);
2560
2561 // '+'? n- <signless-integer>
2562 case 2:
2563 if (token.value.charCodeAt(1) !== HYPHENMINUS$1) {
2564 return 0;
2565 }
2566
2567 offset = skipSC(getNextToken(++offset), offset, getNextToken);
2568 token = getNextToken(offset);
2569
2570 return checkInteger(token, 0, DISALLOW_SIGN, offset);
2571
2572 // '+'? <ndashdigit-ident>
2573 default:
2574 if (token.value.charCodeAt(1) !== HYPHENMINUS$1) {
2575 return 0;
2576 }
2577
2578 return checkInteger(token, 2, DISALLOW_SIGN, offset);
2579 }
2580 }
2581
2582 // <ndashdigit-dimension>
2583 // <ndash-dimension> <signless-integer>
2584 // <n-dimension>
2585 // <n-dimension> <signed-integer>
2586 // <n-dimension> ['+' | '-'] <signless-integer>
2587 else if (token.type === DIMENSION) {
2588 var code = token.value.charCodeAt(0);
2589 var sign = code === PLUSSIGN || code === HYPHENMINUS$1 ? 1 : 0;
2590
2591 for (var i = sign; i < token.value.length; i++) {
2592 if (!isDigit$2(token.value.charCodeAt(i))) {
2593 break;
2594 }
2595 }
2596
2597 if (i === sign) {
2598 // Integer is expected
2599 return 0;
2600 }
2601
2602 if (!cmpChar$1(token.value, i, N)) {
2603 return 0;
2604 }
2605
2606 // <n-dimension>
2607 // <n-dimension> <signed-integer>
2608 // <n-dimension> ['+' | '-'] <signless-integer>
2609 if (i + 1 === token.value.length) {
2610 return consumeB(getNextToken(++offset), offset, getNextToken);
2611 } else {
2612 if (token.value.charCodeAt(i + 1) !== HYPHENMINUS$1) {
2613 return 0;
2614 }
2615
2616 // <ndash-dimension> <signless-integer>
2617 if (i + 2 === token.value.length) {
2618 offset = skipSC(getNextToken(++offset), offset, getNextToken);
2619 token = getNextToken(offset);
2620
2621 return checkInteger(token, 0, DISALLOW_SIGN, offset);
2622 }
2623 // <ndashdigit-dimension>
2624 else {
2625 return checkInteger(token, i + 2, DISALLOW_SIGN, offset);
2626 }
2627 }
2628 }
2629
2630 return 0;
2631 };
2632
2633 var isHexDigit$2 = tokenizer.isHexDigit;
2634 var cmpChar$2 = tokenizer.cmpChar;
2635 var TYPE$4 = tokenizer.TYPE;
2636
2637 var IDENT$1 = TYPE$4.Ident;
2638 var DELIM$1 = TYPE$4.Delim;
2639 var NUMBER$1 = TYPE$4.Number;
2640 var DIMENSION$1 = TYPE$4.Dimension;
2641 var PLUSSIGN$1 = 0x002B; // U+002B PLUS SIGN (+)
2642 var HYPHENMINUS$2 = 0x002D; // U+002D HYPHEN-MINUS (-)
2643 var QUESTIONMARK = 0x003F; // U+003F QUESTION MARK (?)
2644 var U = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
2645
2646 function isDelim$1(token, code) {
2647 return token !== null && token.type === DELIM$1 && token.value.charCodeAt(0) === code;
2648 }
2649
2650 function startsWith(token, code) {
2651 return token.value.charCodeAt(0) === code;
2652 }
2653
2654 function hexSequence(token, offset, allowDash) {
2655 for (var pos = offset, hexlen = 0; pos < token.value.length; pos++) {
2656 var code = token.value.charCodeAt(pos);
2657
2658 if (code === HYPHENMINUS$2 && allowDash && hexlen !== 0) {
2659 if (hexSequence(token, offset + hexlen + 1, false) > 0) {
2660 return 6; // dissallow following question marks
2661 }
2662
2663 return 0; // dash at the ending of a hex sequence is not allowed
2664 }
2665
2666 if (!isHexDigit$2(code)) {
2667 return 0; // not a hex digit
2668 }
2669
2670 if (++hexlen > 6) {
2671 return 0; // too many hex digits
2672 } }
2673
2674 return hexlen;
2675 }
2676
2677 function withQuestionMarkSequence(consumed, length, getNextToken) {
2678 if (!consumed) {
2679 return 0; // nothing consumed
2680 }
2681
2682 while (isDelim$1(getNextToken(length), QUESTIONMARK)) {
2683 if (++consumed > 6) {
2684 return 0; // too many question marks
2685 }
2686
2687 length++;
2688 }
2689
2690 return length;
2691 }
2692
2693 // https://drafts.csswg.org/css-syntax/#urange
2694 // Informally, the <urange> production has three forms:
2695 // U+0001
2696 // Defines a range consisting of a single code point, in this case the code point "1".
2697 // U+0001-00ff
2698 // Defines a range of codepoints between the first and the second value, in this case
2699 // the range between "1" and "ff" (255 in decimal) inclusive.
2700 // U+00??
2701 // Defines a range of codepoints where the "?" characters range over all hex digits,
2702 // in this case defining the same as the value U+0000-00ff.
2703 // In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
2704 //
2705 // <urange> =
2706 // u '+' <ident-token> '?'* |
2707 // u <dimension-token> '?'* |
2708 // u <number-token> '?'* |
2709 // u <number-token> <dimension-token> |
2710 // u <number-token> <number-token> |
2711 // u '+' '?'+
2712 var genericUrange = function urange(token, getNextToken) {
2713 var length = 0;
2714
2715 // should start with `u` or `U`
2716 if (token === null || token.type !== IDENT$1 || !cmpChar$2(token.value, 0, U)) {
2717 return 0;
2718 }
2719
2720 token = getNextToken(++length);
2721 if (token === null) {
2722 return 0;
2723 }
2724
2725 // u '+' <ident-token> '?'*
2726 // u '+' '?'+
2727 if (isDelim$1(token, PLUSSIGN$1)) {
2728 token = getNextToken(++length);
2729 if (token === null) {
2730 return 0;
2731 }
2732
2733 if (token.type === IDENT$1) {
2734 // u '+' <ident-token> '?'*
2735 return withQuestionMarkSequence(hexSequence(token, 0, true), ++length, getNextToken);
2736 }
2737
2738 if (isDelim$1(token, QUESTIONMARK)) {
2739 // u '+' '?'+
2740 return withQuestionMarkSequence(1, ++length, getNextToken);
2741 }
2742
2743 // Hex digit or question mark is expected
2744 return 0;
2745 }
2746
2747 // u <number-token> '?'*
2748 // u <number-token> <dimension-token>
2749 // u <number-token> <number-token>
2750 if (token.type === NUMBER$1) {
2751 if (!startsWith(token, PLUSSIGN$1)) {
2752 return 0;
2753 }
2754
2755 var consumedHexLength = hexSequence(token, 1, true);
2756 if (consumedHexLength === 0) {
2757 return 0;
2758 }
2759
2760 token = getNextToken(++length);
2761 if (token === null) {
2762 // u <number-token> <eof>
2763 return length;
2764 }
2765
2766 if (token.type === DIMENSION$1 || token.type === NUMBER$1) {
2767 // u <number-token> <dimension-token>
2768 // u <number-token> <number-token>
2769 if (!startsWith(token, HYPHENMINUS$2) || !hexSequence(token, 1, false)) {
2770 return 0;
2771 }
2772
2773 return length + 1;
2774 }
2775
2776 // u <number-token> '?'*
2777 return withQuestionMarkSequence(consumedHexLength, length, getNextToken);
2778 }
2779
2780 // u <dimension-token> '?'*
2781 if (token.type === DIMENSION$1) {
2782 if (!startsWith(token, PLUSSIGN$1)) {
2783 return 0;
2784 }
2785
2786 return withQuestionMarkSequence(hexSequence(token, 1, true), ++length, getNextToken);
2787 }
2788
2789 return 0;
2790 };
2791
2792 var isIdentifierStart$2 = tokenizer.isIdentifierStart;
2793 var isHexDigit$3 = tokenizer.isHexDigit;
2794 var isDigit$3 = tokenizer.isDigit;
2795 var cmpStr$3 = tokenizer.cmpStr;
2796 var consumeNumber$2 = tokenizer.consumeNumber;
2797 var TYPE$5 = tokenizer.TYPE;
2798
2799
2800
2801 var cssWideKeywords = ['unset', 'initial', 'inherit'];
2802 var calcFunctionNames = ['calc(', '-moz-calc(', '-webkit-calc('];
2803
2804 // https://www.w3.org/TR/css-values-3/#lengths
2805 var LENGTH = {
2806 // absolute length units
2807 'px': true,
2808 'mm': true,
2809 'cm': true,
2810 'in': true,
2811 'pt': true,
2812 'pc': true,
2813 'q': true,
2814
2815 // relative length units
2816 'em': true,
2817 'ex': true,
2818 'ch': true,
2819 'rem': true,
2820
2821 // viewport-percentage lengths
2822 'vh': true,
2823 'vw': true,
2824 'vmin': true,
2825 'vmax': true,
2826 'vm': true
2827 };
2828
2829 var ANGLE = {
2830 'deg': true,
2831 'grad': true,
2832 'rad': true,
2833 'turn': true
2834 };
2835
2836 var TIME = {
2837 's': true,
2838 'ms': true
2839 };
2840
2841 var FREQUENCY = {
2842 'hz': true,
2843 'khz': true
2844 };
2845
2846 // https://www.w3.org/TR/css-values-3/#resolution (https://drafts.csswg.org/css-values/#resolution)
2847 var RESOLUTION = {
2848 'dpi': true,
2849 'dpcm': true,
2850 'dppx': true,
2851 'x': true // https://github.com/w3c/csswg-drafts/issues/461
2852 };
2853
2854 // https://drafts.csswg.org/css-grid/#fr-unit
2855 var FLEX = {
2856 'fr': true
2857 };
2858
2859 // https://www.w3.org/TR/css3-speech/#mixing-props-voice-volume
2860 var DECIBEL = {
2861 'db': true
2862 };
2863
2864 // https://www.w3.org/TR/css3-speech/#voice-props-voice-pitch
2865 var SEMITONES = {
2866 'st': true
2867 };
2868
2869 // safe char code getter
2870 function charCode(str, index) {
2871 return index < str.length ? str.charCodeAt(index) : 0;
2872 }
2873
2874 function eqStr(actual, expected) {
2875 return cmpStr$3(actual, 0, actual.length, expected);
2876 }
2877
2878 function eqStrAny(actual, expected) {
2879 for (var i = 0; i < expected.length; i++) {
2880 if (eqStr(actual, expected[i])) {
2881 return true;
2882 }
2883 }
2884
2885 return false;
2886 }
2887
2888 // IE postfix hack, i.e. 123\0 or 123px\9
2889 function isPostfixIeHack(str, offset) {
2890 if (offset !== str.length - 2) {
2891 return false;
2892 }
2893
2894 return (
2895 str.charCodeAt(offset) === 0x005C && // U+005C REVERSE SOLIDUS (\)
2896 isDigit$3(str.charCodeAt(offset + 1))
2897 );
2898 }
2899
2900 function outOfRange(opts, value, numEnd) {
2901 if (opts && opts.type === 'Range') {
2902 var num = Number(
2903 numEnd !== undefined && numEnd !== value.length
2904 ? value.substr(0, numEnd)
2905 : value
2906 );
2907
2908 if (isNaN(num)) {
2909 return true;
2910 }
2911
2912 if (opts.min !== null && num < opts.min) {
2913 return true;
2914 }
2915
2916 if (opts.max !== null && num > opts.max) {
2917 return true;
2918 }
2919 }
2920
2921 return false;
2922 }
2923
2924 function consumeFunction(token, getNextToken) {
2925 var startIdx = token.index;
2926 var length = 0;
2927
2928 // balanced token consuming
2929 do {
2930 length++;
2931
2932 if (token.balance <= startIdx) {
2933 break;
2934 }
2935 } while (token = getNextToken(length));
2936
2937 return length;
2938 }
2939
2940 // TODO: implement
2941 // can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed
2942 // https://drafts.csswg.org/css-values/#calc-notation
2943 function calc(next) {
2944 return function(token, getNextToken, opts) {
2945 if (token === null) {
2946 return 0;
2947 }
2948
2949 if (token.type === TYPE$5.Function && eqStrAny(token.value, calcFunctionNames)) {
2950 return consumeFunction(token, getNextToken);
2951 }
2952
2953 return next(token, getNextToken, opts);
2954 };
2955 }
2956
2957 function tokenType(expectedTokenType) {
2958 return function(token) {
2959 if (token === null || token.type !== expectedTokenType) {
2960 return 0;
2961 }
2962
2963 return 1;
2964 };
2965 }
2966
2967 function func(name) {
2968 name = name + '(';
2969
2970 return function(token, getNextToken) {
2971 if (token !== null && eqStr(token.value, name)) {
2972 return consumeFunction(token, getNextToken);
2973 }
2974
2975 return 0;
2976 };
2977 }
2978
2979 // =========================
2980 // Complex types
2981 //
2982
2983 // https://drafts.csswg.org/css-values-4/#custom-idents
2984 // 4.2. Author-defined Identifiers: the <custom-ident> type
2985 // Some properties accept arbitrary author-defined identifiers as a component value.
2986 // This generic data type is denoted by <custom-ident>, and represents any valid CSS identifier
2987 // that would not be misinterpreted as a pre-defined keyword in that property’s value definition.
2988 //
2989 // See also: https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident
2990 function customIdent(token) {
2991 if (token === null || token.type !== TYPE$5.Ident) {
2992 return 0;
2993 }
2994
2995 var name = token.value.toLowerCase();
2996
2997 // The CSS-wide keywords are not valid <custom-ident>s
2998 if (eqStrAny(name, cssWideKeywords)) {
2999 return 0;
3000 }
3001
3002 // The default keyword is reserved and is also not a valid <custom-ident>
3003 if (eqStr(name, 'default')) {
3004 return 0;
3005 }
3006
3007 // TODO: ignore property specific keywords (as described https://developer.mozilla.org/en-US/docs/Web/CSS/custom-ident)
3008 // Specifications using <custom-ident> must specify clearly what other keywords
3009 // are excluded from <custom-ident>, if any—for example by saying that any pre-defined keywords
3010 // in that property’s value definition are excluded. Excluded keywords are excluded
3011 // in all ASCII case permutations.
3012
3013 return 1;
3014 }
3015
3016 // https://drafts.csswg.org/css-variables/#typedef-custom-property-name
3017 // A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo.
3018 // The <custom-property-name> production corresponds to this: it’s defined as any valid identifier
3019 // that starts with two dashes, except -- itself, which is reserved for future use by CSS.
3020 // NOTE: Current implementation treat `--` as a valid name since most (all?) major browsers treat it as valid.
3021 function customPropertyName(token) {
3022 // ... defined as any valid identifier
3023 if (token === null || token.type !== TYPE$5.Ident) {
3024 return 0;
3025 }
3026
3027 // ... that starts with two dashes (U+002D HYPHEN-MINUS)
3028 if (charCode(token.value, 0) !== 0x002D || charCode(token.value, 1) !== 0x002D) {
3029 return 0;
3030 }
3031
3032 return 1;
3033 }
3034
3035 // https://drafts.csswg.org/css-color-4/#hex-notation
3036 // The syntax of a <hex-color> is a <hash-token> token whose value consists of 3, 4, 6, or 8 hexadecimal digits.
3037 // In other words, a hex color is written as a hash character, "#", followed by some number of digits 0-9 or
3038 // letters a-f (the case of the letters doesn’t matter - #00ff00 is identical to #00FF00).
3039 function hexColor(token) {
3040 if (token === null || token.type !== TYPE$5.Hash) {
3041 return 0;
3042 }
3043
3044 var length = token.value.length;
3045
3046 // valid values (length): #rgb (4), #rgba (5), #rrggbb (7), #rrggbbaa (9)
3047 if (length !== 4 && length !== 5 && length !== 7 && length !== 9) {
3048 return 0;
3049 }
3050
3051 for (var i = 1; i < length; i++) {
3052 if (!isHexDigit$3(token.value.charCodeAt(i))) {
3053 return 0;
3054 }
3055 }
3056
3057 return 1;
3058 }
3059
3060 function idSelector(token) {
3061 if (token === null || token.type !== TYPE$5.Hash) {
3062 return 0;
3063 }
3064
3065 if (!isIdentifierStart$2(charCode(token.value, 1), charCode(token.value, 2), charCode(token.value, 3))) {
3066 return 0;
3067 }
3068
3069 return 1;
3070 }
3071
3072 // https://drafts.csswg.org/css-syntax/#any-value
3073 // It represents the entirety of what a valid declaration can have as its value.
3074 function declarationValue(token, getNextToken) {
3075 if (!token) {
3076 return 0;
3077 }
3078
3079 var length = 0;
3080 var level = 0;
3081 var startIdx = token.index;
3082
3083 // The <declaration-value> production matches any sequence of one or more tokens,
3084 // so long as the sequence ...
3085 scan:
3086 do {
3087 switch (token.type) {
3088 // ... does not contain <bad-string-token>, <bad-url-token>,
3089 case TYPE$5.BadString:
3090 case TYPE$5.BadUrl:
3091 break scan;
3092
3093 // ... unmatched <)-token>, <]-token>, or <}-token>,
3094 case TYPE$5.RightCurlyBracket:
3095 case TYPE$5.RightParenthesis:
3096 case TYPE$5.RightSquareBracket:
3097 if (token.balance > token.index || token.balance < startIdx) {
3098 break scan;
3099 }
3100
3101 level--;
3102 break;
3103
3104 // ... or top-level <semicolon-token> tokens
3105 case TYPE$5.Semicolon:
3106 if (level === 0) {
3107 break scan;
3108 }
3109
3110 break;
3111
3112 // ... or <delim-token> tokens with a value of "!"
3113 case TYPE$5.Delim:
3114 if (token.value === '!' && level === 0) {
3115 break scan;
3116 }
3117
3118 break;
3119
3120 case TYPE$5.Function:
3121 case TYPE$5.LeftParenthesis:
3122 case TYPE$5.LeftSquareBracket:
3123 case TYPE$5.LeftCurlyBracket:
3124 level++;
3125 break;
3126 }
3127
3128 length++;
3129
3130 // until balance closing
3131 if (token.balance <= startIdx) {
3132 break;
3133 }
3134 } while (token = getNextToken(length));
3135
3136 return length;
3137 }
3138
3139 // https://drafts.csswg.org/css-syntax/#any-value
3140 // The <any-value> production is identical to <declaration-value>, but also
3141 // allows top-level <semicolon-token> tokens and <delim-token> tokens
3142 // with a value of "!". It represents the entirety of what valid CSS can be in any context.
3143 function anyValue(token, getNextToken) {
3144 if (!token) {
3145 return 0;
3146 }
3147
3148 var startIdx = token.index;
3149 var length = 0;
3150
3151 // The <any-value> production matches any sequence of one or more tokens,
3152 // so long as the sequence ...
3153 scan:
3154 do {
3155 switch (token.type) {
3156 // ... does not contain <bad-string-token>, <bad-url-token>,
3157 case TYPE$5.BadString:
3158 case TYPE$5.BadUrl:
3159 break scan;
3160
3161 // ... unmatched <)-token>, <]-token>, or <}-token>,
3162 case TYPE$5.RightCurlyBracket:
3163 case TYPE$5.RightParenthesis:
3164 case TYPE$5.RightSquareBracket:
3165 if (token.balance > token.index || token.balance < startIdx) {
3166 break scan;
3167 }
3168
3169 break;
3170 }
3171
3172 length++;
3173
3174 // until balance closing
3175 if (token.balance <= startIdx) {
3176 break;
3177 }
3178 } while (token = getNextToken(length));
3179
3180 return length;
3181 }
3182
3183 // =========================
3184 // Dimensions
3185 //
3186
3187 function dimension(type) {
3188 return function(token, getNextToken, opts) {
3189 if (token === null || token.type !== TYPE$5.Dimension) {
3190 return 0;
3191 }
3192
3193 var numberEnd = consumeNumber$2(token.value, 0);
3194
3195 // check unit
3196 if (type !== null) {
3197 // check for IE postfix hack, i.e. 123px\0 or 123px\9
3198 var reverseSolidusOffset = token.value.indexOf('\\', numberEnd);
3199 var unit = reverseSolidusOffset === -1 || !isPostfixIeHack(token.value, reverseSolidusOffset)
3200 ? token.value.substr(numberEnd)
3201 : token.value.substring(numberEnd, reverseSolidusOffset);
3202
3203 if (type.hasOwnProperty(unit.toLowerCase()) === false) {
3204 return 0;
3205 }
3206 }
3207
3208 // check range if specified
3209 if (outOfRange(opts, token.value, numberEnd)) {
3210 return 0;
3211 }
3212
3213 return 1;
3214 };
3215 }
3216
3217 // =========================
3218 // Percentage
3219 //
3220
3221 // §5.5. Percentages: the <percentage> type
3222 // https://drafts.csswg.org/css-values-4/#percentages
3223 function percentage(token, getNextToken, opts) {
3224 // ... corresponds to the <percentage-token> production
3225 if (token === null || token.type !== TYPE$5.Percentage) {
3226 return 0;
3227 }
3228
3229 // check range if specified
3230 if (outOfRange(opts, token.value, token.value.length - 1)) {
3231 return 0;
3232 }
3233
3234 return 1;
3235 }
3236
3237 // =========================
3238 // Numeric
3239 //
3240
3241 // https://drafts.csswg.org/css-values-4/#numbers
3242 // The value <zero> represents a literal number with the value 0. Expressions that merely
3243 // evaluate to a <number> with the value 0 (for example, calc(0)) do not match <zero>;
3244 // only literal <number-token>s do.
3245 function zero(next) {
3246 if (typeof next !== 'function') {
3247 next = function() {
3248 return 0;
3249 };
3250 }
3251
3252 return function(token, getNextToken, opts) {
3253 if (token !== null && token.type === TYPE$5.Number) {
3254 if (Number(token.value) === 0) {
3255 return 1;
3256 }
3257 }
3258
3259 return next(token, getNextToken, opts);
3260 };
3261 }
3262
3263 // § 5.3. Real Numbers: the <number> type
3264 // https://drafts.csswg.org/css-values-4/#numbers
3265 // Number values are denoted by <number>, and represent real numbers, possibly with a fractional component.
3266 // ... It corresponds to the <number-token> production
3267 function number(token, getNextToken, opts) {
3268 if (token === null) {
3269 return 0;
3270 }
3271
3272 var numberEnd = consumeNumber$2(token.value, 0);
3273 var isNumber = numberEnd === token.value.length;
3274 if (!isNumber && !isPostfixIeHack(token.value, numberEnd)) {
3275 return 0;
3276 }
3277
3278 // check range if specified
3279 if (outOfRange(opts, token.value, numberEnd)) {
3280 return 0;
3281 }
3282
3283 return 1;
3284 }
3285
3286 // §5.2. Integers: the <integer> type
3287 // https://drafts.csswg.org/css-values-4/#integers
3288 function integer(token, getNextToken, opts) {
3289 // ... corresponds to a subset of the <number-token> production
3290 if (token === null || token.type !== TYPE$5.Number) {
3291 return 0;
3292 }
3293
3294 // The first digit of an integer may be immediately preceded by `-` or `+` to indicate the integer’s sign.
3295 var i = token.value.charCodeAt(0) === 0x002B || // U+002B PLUS SIGN (+)
3296 token.value.charCodeAt(0) === 0x002D ? 1 : 0; // U+002D HYPHEN-MINUS (-)
3297
3298 // When written literally, an integer is one or more decimal digits 0 through 9 ...
3299 for (; i < token.value.length; i++) {
3300 if (!isDigit$3(token.value.charCodeAt(i))) {
3301 return 0;
3302 }
3303 }
3304
3305 // check range if specified
3306 if (outOfRange(opts, token.value, i)) {
3307 return 0;
3308 }
3309
3310 return 1;
3311 }
3312
3313 var generic = {
3314 // token types
3315 'ident-token': tokenType(TYPE$5.Ident),
3316 'function-token': tokenType(TYPE$5.Function),
3317 'at-keyword-token': tokenType(TYPE$5.AtKeyword),
3318 'hash-token': tokenType(TYPE$5.Hash),
3319 'string-token': tokenType(TYPE$5.String),
3320 'bad-string-token': tokenType(TYPE$5.BadString),
3321 'url-token': tokenType(TYPE$5.Url),
3322 'bad-url-token': tokenType(TYPE$5.BadUrl),
3323 'delim-token': tokenType(TYPE$5.Delim),
3324 'number-token': tokenType(TYPE$5.Number),
3325 'percentage-token': tokenType(TYPE$5.Percentage),
3326 'dimension-token': tokenType(TYPE$5.Dimension),
3327 'whitespace-token': tokenType(TYPE$5.WhiteSpace),
3328 'CDO-token': tokenType(TYPE$5.CDO),
3329 'CDC-token': tokenType(TYPE$5.CDC),
3330 'colon-token': tokenType(TYPE$5.Colon),
3331 'semicolon-token': tokenType(TYPE$5.Semicolon),
3332 'comma-token': tokenType(TYPE$5.Comma),
3333 '[-token': tokenType(TYPE$5.LeftSquareBracket),
3334 ']-token': tokenType(TYPE$5.RightSquareBracket),
3335 '(-token': tokenType(TYPE$5.LeftParenthesis),
3336 ')-token': tokenType(TYPE$5.RightParenthesis),
3337 '{-token': tokenType(TYPE$5.LeftCurlyBracket),
3338 '}-token': tokenType(TYPE$5.RightCurlyBracket),
3339
3340 // token type aliases
3341 'string': tokenType(TYPE$5.String),
3342 'ident': tokenType(TYPE$5.Ident),
3343
3344 // complex types
3345 'custom-ident': customIdent,
3346 'custom-property-name': customPropertyName,
3347 'hex-color': hexColor,
3348 'id-selector': idSelector, // element( <id-selector> )
3349 'an-plus-b': genericAnPlusB,
3350 'urange': genericUrange,
3351 'declaration-value': declarationValue,
3352 'any-value': anyValue,
3353
3354 // dimensions
3355 'dimension': calc(dimension(null)),
3356 'angle': calc(dimension(ANGLE)),
3357 'decibel': calc(dimension(DECIBEL)),
3358 'frequency': calc(dimension(FREQUENCY)),
3359 'flex': calc(dimension(FLEX)),
3360 'length': calc(zero(dimension(LENGTH))),
3361 'resolution': calc(dimension(RESOLUTION)),
3362 'semitones': calc(dimension(SEMITONES)),
3363 'time': calc(dimension(TIME)),
3364
3365 // percentage
3366 'percentage': calc(percentage),
3367
3368 // numeric
3369 'zero': zero(),
3370 'number': calc(number),
3371 'integer': calc(integer),
3372
3373 // old IE stuff
3374 '-ms-legacy-expression': func('expression')
3375 };
3376
3377 var _SyntaxError$1 = function SyntaxError(message, input, offset) {
3378 var error = createCustomError('SyntaxError', message);
3379
3380 error.input = input;
3381 error.offset = offset;
3382 error.rawMessage = message;
3383 error.message = error.rawMessage + '\n' +
3384 ' ' + error.input + '\n' +
3385 '--' + new Array((error.offset || error.input.length) + 1).join('-') + '^';
3386
3387 return error;
3388 };
3389
3390 var TAB = 9;
3391 var N$1 = 10;
3392 var F = 12;
3393 var R = 13;
3394 var SPACE = 32;
3395
3396 var Tokenizer = function(str) {
3397 this.str = str;
3398 this.pos = 0;
3399 };
3400
3401 Tokenizer.prototype = {
3402 charCodeAt: function(pos) {
3403 return pos < this.str.length ? this.str.charCodeAt(pos) : 0;
3404 },
3405 charCode: function() {
3406 return this.charCodeAt(this.pos);
3407 },
3408 nextCharCode: function() {
3409 return this.charCodeAt(this.pos + 1);
3410 },
3411 nextNonWsCode: function(pos) {
3412 return this.charCodeAt(this.findWsEnd(pos));
3413 },
3414 findWsEnd: function(pos) {
3415 for (; pos < this.str.length; pos++) {
3416 var code = this.str.charCodeAt(pos);
3417 if (code !== R && code !== N$1 && code !== F && code !== SPACE && code !== TAB) {
3418 break;
3419 }
3420 }
3421
3422 return pos;
3423 },
3424 substringToPos: function(end) {
3425 return this.str.substring(this.pos, this.pos = end);
3426 },
3427 eat: function(code) {
3428 if (this.charCode() !== code) {
3429 this.error('Expect `' + String.fromCharCode(code) + '`');
3430 }
3431
3432 this.pos++;
3433 },
3434 peek: function() {
3435 return this.pos < this.str.length ? this.str.charAt(this.pos++) : '';
3436 },
3437 error: function(message) {
3438 throw new _SyntaxError$1(message, this.str, this.pos);
3439 }
3440 };
3441
3442 var tokenizer$1 = Tokenizer;
3443
3444 var TAB$1 = 9;
3445 var N$2 = 10;
3446 var F$1 = 12;
3447 var R$1 = 13;
3448 var SPACE$1 = 32;
3449 var EXCLAMATIONMARK = 33; // !
3450 var NUMBERSIGN = 35; // #
3451 var AMPERSAND = 38; // &
3452 var APOSTROPHE = 39; // '
3453 var LEFTPARENTHESIS = 40; // (
3454 var RIGHTPARENTHESIS = 41; // )
3455 var ASTERISK = 42; // *
3456 var PLUSSIGN$2 = 43; // +
3457 var COMMA = 44; // ,
3458 var HYPERMINUS = 45; // -
3459 var LESSTHANSIGN = 60; // <
3460 var GREATERTHANSIGN = 62; // >
3461 var QUESTIONMARK$1 = 63; // ?
3462 var COMMERCIALAT = 64; // @
3463 var LEFTSQUAREBRACKET = 91; // [
3464 var RIGHTSQUAREBRACKET = 93; // ]
3465 var LEFTCURLYBRACKET = 123; // {
3466 var VERTICALLINE = 124; // |
3467 var RIGHTCURLYBRACKET = 125; // }
3468 var INFINITY = 8734; // ∞
3469 var NAME_CHAR = createCharMap(function(ch) {
3470 return /[a-zA-Z0-9\-]/.test(ch);
3471 });
3472 var COMBINATOR_PRECEDENCE = {
3473 ' ': 1,
3474 '&&': 2,
3475 '||': 3,
3476 '|': 4
3477 };
3478
3479 function createCharMap(fn) {
3480 var array = typeof Uint32Array === 'function' ? new Uint32Array(128) : new Array(128);
3481 for (var i = 0; i < 128; i++) {
3482 array[i] = fn(String.fromCharCode(i)) ? 1 : 0;
3483 }
3484 return array;
3485 }
3486
3487 function scanSpaces(tokenizer) {
3488 return tokenizer.substringToPos(
3489 tokenizer.findWsEnd(tokenizer.pos)
3490 );
3491 }
3492
3493 function scanWord(tokenizer) {
3494 var end = tokenizer.pos;
3495
3496 for (; end < tokenizer.str.length; end++) {
3497 var code = tokenizer.str.charCodeAt(end);
3498 if (code >= 128 || NAME_CHAR[code] === 0) {
3499 break;
3500 }
3501 }
3502
3503 if (tokenizer.pos === end) {
3504 tokenizer.error('Expect a keyword');
3505 }
3506
3507 return tokenizer.substringToPos(end);
3508 }
3509
3510 function scanNumber(tokenizer) {
3511 var end = tokenizer.pos;
3512
3513 for (; end < tokenizer.str.length; end++) {
3514 var code = tokenizer.str.charCodeAt(end);
3515 if (code < 48 || code > 57) {
3516 break;
3517 }
3518 }
3519
3520 if (tokenizer.pos === end) {
3521 tokenizer.error('Expect a number');
3522 }
3523
3524 return tokenizer.substringToPos(end);
3525 }
3526
3527 function scanString(tokenizer) {
3528 var end = tokenizer.str.indexOf('\'', tokenizer.pos + 1);
3529
3530 if (end === -1) {
3531 tokenizer.pos = tokenizer.str.length;
3532 tokenizer.error('Expect an apostrophe');
3533 }
3534
3535 return tokenizer.substringToPos(end + 1);
3536 }
3537
3538 function readMultiplierRange(tokenizer) {
3539 var min = null;
3540 var max = null;
3541
3542 tokenizer.eat(LEFTCURLYBRACKET);
3543
3544 min = scanNumber(tokenizer);
3545
3546 if (tokenizer.charCode() === COMMA) {
3547 tokenizer.pos++;
3548 if (tokenizer.charCode() !== RIGHTCURLYBRACKET) {
3549 max = scanNumber(tokenizer);
3550 }
3551 } else {
3552 max = min;
3553 }
3554
3555 tokenizer.eat(RIGHTCURLYBRACKET);
3556
3557 return {
3558 min: Number(min),
3559 max: max ? Number(max) : 0
3560 };
3561 }
3562
3563 function readMultiplier(tokenizer) {
3564 var range = null;
3565 var comma = false;
3566
3567 switch (tokenizer.charCode()) {
3568 case ASTERISK:
3569 tokenizer.pos++;
3570
3571 range = {
3572 min: 0,
3573 max: 0
3574 };
3575
3576 break;
3577
3578 case PLUSSIGN$2:
3579 tokenizer.pos++;
3580
3581 range = {
3582 min: 1,
3583 max: 0
3584 };
3585
3586 break;
3587
3588 case QUESTIONMARK$1:
3589 tokenizer.pos++;
3590
3591 range = {
3592 min: 0,
3593 max: 1
3594 };
3595
3596 break;
3597
3598 case NUMBERSIGN:
3599 tokenizer.pos++;
3600
3601 comma = true;
3602
3603 if (tokenizer.charCode() === LEFTCURLYBRACKET) {
3604 range = readMultiplierRange(tokenizer);
3605 } else {
3606 range = {
3607 min: 1,
3608 max: 0
3609 };
3610 }
3611
3612 break;
3613
3614 case LEFTCURLYBRACKET:
3615 range = readMultiplierRange(tokenizer);
3616 break;
3617
3618 default:
3619 return null;
3620 }
3621
3622 return {
3623 type: 'Multiplier',
3624 comma: comma,
3625 min: range.min,
3626 max: range.max,
3627 term: null
3628 };
3629 }
3630
3631 function maybeMultiplied(tokenizer, node) {
3632 var multiplier = readMultiplier(tokenizer);
3633
3634 if (multiplier !== null) {
3635 multiplier.term = node;
3636 return multiplier;
3637 }
3638
3639 return node;
3640 }
3641
3642 function maybeToken(tokenizer) {
3643 var ch = tokenizer.peek();
3644
3645 if (ch === '') {
3646 return null;
3647 }
3648
3649 return {
3650 type: 'Token',
3651 value: ch
3652 };
3653 }
3654
3655 function readProperty(tokenizer) {
3656 var name;
3657
3658 tokenizer.eat(LESSTHANSIGN);
3659 tokenizer.eat(APOSTROPHE);
3660
3661 name = scanWord(tokenizer);
3662
3663 tokenizer.eat(APOSTROPHE);
3664 tokenizer.eat(GREATERTHANSIGN);
3665
3666 return maybeMultiplied(tokenizer, {
3667 type: 'Property',
3668 name: name
3669 });
3670 }
3671
3672 // https://drafts.csswg.org/css-values-3/#numeric-ranges
3673 // 4.1. Range Restrictions and Range Definition Notation
3674 //
3675 // Range restrictions can be annotated in the numeric type notation using CSS bracketed
3676 // range notation—[min,max]—within the angle brackets, after the identifying keyword,
3677 // indicating a closed range between (and including) min and max.
3678 // For example, <integer [0, 10]> indicates an integer between 0 and 10, inclusive.
3679 function readTypeRange(tokenizer) {
3680 // use null for Infinity to make AST format JSON serializable/deserializable
3681 var min = null; // -Infinity
3682 var max = null; // Infinity
3683 var sign = 1;
3684
3685 tokenizer.eat(LEFTSQUAREBRACKET);
3686
3687 if (tokenizer.charCode() === HYPERMINUS) {
3688 tokenizer.peek();
3689 sign = -1;
3690 }
3691
3692 if (sign == -1 && tokenizer.charCode() === INFINITY) {
3693 tokenizer.peek();
3694 } else {
3695 min = sign * Number(scanNumber(tokenizer));
3696 }
3697
3698 scanSpaces(tokenizer);
3699 tokenizer.eat(COMMA);
3700 scanSpaces(tokenizer);
3701
3702 if (tokenizer.charCode() === INFINITY) {
3703 tokenizer.peek();
3704 } else {
3705 sign = 1;
3706
3707 if (tokenizer.charCode() === HYPERMINUS) {
3708 tokenizer.peek();
3709 sign = -1;
3710 }
3711
3712 max = sign * Number(scanNumber(tokenizer));
3713 }
3714
3715 tokenizer.eat(RIGHTSQUAREBRACKET);
3716
3717 // If no range is indicated, either by using the bracketed range notation
3718 // or in the property description, then [−∞,∞] is assumed.
3719 if (min === null && max === null) {
3720 return null;
3721 }
3722
3723 return {
3724 type: 'Range',
3725 min: min,
3726 max: max
3727 };
3728 }
3729
3730 function readType(tokenizer) {
3731 var name;
3732 var opts = null;
3733
3734 tokenizer.eat(LESSTHANSIGN);
3735 name = scanWord(tokenizer);
3736
3737 if (tokenizer.charCode() === LEFTPARENTHESIS &&
3738 tokenizer.nextCharCode() === RIGHTPARENTHESIS) {
3739 tokenizer.pos += 2;
3740 name += '()';
3741 }
3742
3743 if (tokenizer.charCodeAt(tokenizer.findWsEnd(tokenizer.pos)) === LEFTSQUAREBRACKET) {
3744 scanSpaces(tokenizer);
3745 opts = readTypeRange(tokenizer);
3746 }
3747
3748 tokenizer.eat(GREATERTHANSIGN);
3749
3750 return maybeMultiplied(tokenizer, {
3751 type: 'Type',
3752 name: name,
3753 opts: opts
3754 });
3755 }
3756
3757 function readKeywordOrFunction(tokenizer) {
3758 var name;
3759
3760 name = scanWord(tokenizer);
3761
3762 if (tokenizer.charCode() === LEFTPARENTHESIS) {
3763 tokenizer.pos++;
3764
3765 return {
3766 type: 'Function',
3767 name: name
3768 };
3769 }
3770
3771 return maybeMultiplied(tokenizer, {
3772 type: 'Keyword',
3773 name: name
3774 });
3775 }
3776
3777 function regroupTerms(terms, combinators) {
3778 function createGroup(terms, combinator) {
3779 return {
3780 type: 'Group',
3781 terms: terms,
3782 combinator: combinator,
3783 disallowEmpty: false,
3784 explicit: false
3785 };
3786 }
3787
3788 combinators = Object.keys(combinators).sort(function(a, b) {
3789 return COMBINATOR_PRECEDENCE[a] - COMBINATOR_PRECEDENCE[b];
3790 });
3791
3792 while (combinators.length > 0) {
3793 var combinator = combinators.shift();
3794 for (var i = 0, subgroupStart = 0; i < terms.length; i++) {
3795 var term = terms[i];
3796 if (term.type === 'Combinator') {
3797 if (term.value === combinator) {
3798 if (subgroupStart === -1) {
3799 subgroupStart = i - 1;
3800 }
3801 terms.splice(i, 1);
3802 i--;
3803 } else {
3804 if (subgroupStart !== -1 && i - subgroupStart > 1) {
3805 terms.splice(
3806 subgroupStart,
3807 i - subgroupStart,
3808 createGroup(terms.slice(subgroupStart, i), combinator)
3809 );
3810 i = subgroupStart + 1;
3811 }
3812 subgroupStart = -1;
3813 }
3814 }
3815 }
3816
3817 if (subgroupStart !== -1 && combinators.length) {
3818 terms.splice(
3819 subgroupStart,
3820 i - subgroupStart,
3821 createGroup(terms.slice(subgroupStart, i), combinator)
3822 );
3823 }
3824 }
3825
3826 return combinator;
3827 }
3828
3829 function readImplicitGroup(tokenizer) {
3830 var terms = [];
3831 var combinators = {};
3832 var token;
3833 var prevToken = null;
3834 var prevTokenPos = tokenizer.pos;
3835
3836 while (token = peek(tokenizer)) {
3837 if (token.type !== 'Spaces') {
3838 if (token.type === 'Combinator') {
3839 // check for combinator in group beginning and double combinator sequence
3840 if (prevToken === null || prevToken.type === 'Combinator') {
3841 tokenizer.pos = prevTokenPos;
3842 tokenizer.error('Unexpected combinator');
3843 }
3844
3845 combinators[token.value] = true;
3846 } else if (prevToken !== null && prevToken.type !== 'Combinator') {
3847 combinators[' '] = true; // a b
3848 terms.push({
3849 type: 'Combinator',
3850 value: ' '
3851 });
3852 }
3853
3854 terms.push(token);
3855 prevToken = token;
3856 prevTokenPos = tokenizer.pos;
3857 }
3858 }
3859
3860 // check for combinator in group ending
3861 if (prevToken !== null && prevToken.type === 'Combinator') {
3862 tokenizer.pos -= prevTokenPos;
3863 tokenizer.error('Unexpected combinator');
3864 }
3865
3866 return {
3867 type: 'Group',
3868 terms: terms,
3869 combinator: regroupTerms(terms, combinators) || ' ',
3870 disallowEmpty: false,
3871 explicit: false
3872 };
3873 }
3874
3875 function readGroup(tokenizer) {
3876 var result;
3877
3878 tokenizer.eat(LEFTSQUAREBRACKET);
3879 result = readImplicitGroup(tokenizer);
3880 tokenizer.eat(RIGHTSQUAREBRACKET);
3881
3882 result.explicit = true;
3883
3884 if (tokenizer.charCode() === EXCLAMATIONMARK) {
3885 tokenizer.pos++;
3886 result.disallowEmpty = true;
3887 }
3888
3889 return result;
3890 }
3891
3892 function peek(tokenizer) {
3893 var code = tokenizer.charCode();
3894
3895 if (code < 128 && NAME_CHAR[code] === 1) {
3896 return readKeywordOrFunction(tokenizer);
3897 }
3898
3899 switch (code) {
3900 case RIGHTSQUAREBRACKET:
3901 // don't eat, stop scan a group
3902 break;
3903
3904 case LEFTSQUAREBRACKET:
3905 return maybeMultiplied(tokenizer, readGroup(tokenizer));
3906
3907 case LESSTHANSIGN:
3908 return tokenizer.nextCharCode() === APOSTROPHE
3909 ? readProperty(tokenizer)
3910 : readType(tokenizer);
3911
3912 case VERTICALLINE:
3913 return {
3914 type: 'Combinator',
3915 value: tokenizer.substringToPos(
3916 tokenizer.nextCharCode() === VERTICALLINE
3917 ? tokenizer.pos + 2
3918 : tokenizer.pos + 1
3919 )
3920 };
3921
3922 case AMPERSAND:
3923 tokenizer.pos++;
3924 tokenizer.eat(AMPERSAND);
3925
3926 return {
3927 type: 'Combinator',
3928 value: '&&'
3929 };
3930
3931 case COMMA:
3932 tokenizer.pos++;
3933 return {
3934 type: 'Comma'
3935 };
3936
3937 case APOSTROPHE:
3938 return maybeMultiplied(tokenizer, {
3939 type: 'String',
3940 value: scanString(tokenizer)
3941 });
3942
3943 case SPACE$1:
3944 case TAB$1:
3945 case N$2:
3946 case R$1:
3947 case F$1:
3948 return {
3949 type: 'Spaces',
3950 value: scanSpaces(tokenizer)
3951 };
3952
3953 case COMMERCIALAT:
3954 code = tokenizer.nextCharCode();
3955
3956 if (code < 128 && NAME_CHAR[code] === 1) {
3957 tokenizer.pos++;
3958 return {
3959 type: 'AtKeyword',
3960 name: scanWord(tokenizer)
3961 };
3962 }
3963
3964 return maybeToken(tokenizer);
3965
3966 case ASTERISK:
3967 case PLUSSIGN$2:
3968 case QUESTIONMARK$1:
3969 case NUMBERSIGN:
3970 case EXCLAMATIONMARK:
3971 // prohibited tokens (used as a multiplier start)
3972 break;
3973
3974 case LEFTCURLYBRACKET:
3975 // LEFTCURLYBRACKET is allowed since mdn/data uses it w/o quoting
3976 // check next char isn't a number, because it's likely a disjoined multiplier
3977 code = tokenizer.nextCharCode();
3978
3979 if (code < 48 || code > 57) {
3980 return maybeToken(tokenizer);
3981 }
3982
3983 break;
3984
3985 default:
3986 return maybeToken(tokenizer);
3987 }
3988 }
3989
3990 function parse(source) {
3991 var tokenizer = new tokenizer$1(source);
3992 var result = readImplicitGroup(tokenizer);
3993
3994 if (tokenizer.pos !== source.length) {
3995 tokenizer.error('Unexpected input');
3996 }
3997
3998 // reduce redundant groups with single group term
3999 if (result.terms.length === 1 && result.terms[0].type === 'Group') {
4000 result = result.terms[0];
4001 }
4002
4003 return result;
4004 }
4005
4006 // warm up parse to elimitate code branches that never execute
4007 // fix soft deoptimizations (insufficient type feedback)
4008 parse('[a&&<b>#|<\'c\'>*||e() f{2} /,(% g#{1,2} h{2,})]!');
4009
4010 var parse_1 = parse;
4011
4012 var noop$1 = function() {};
4013
4014 function ensureFunction(value) {
4015 return typeof value === 'function' ? value : noop$1;
4016 }
4017
4018 var walk = function(node, options, context) {
4019 function walk(node) {
4020 enter.call(context, node);
4021
4022 switch (node.type) {
4023 case 'Group':
4024 node.terms.forEach(walk);
4025 break;
4026
4027 case 'Multiplier':
4028 walk(node.term);
4029 break;
4030
4031 case 'Type':
4032 case 'Property':
4033 case 'Keyword':
4034 case 'AtKeyword':
4035 case 'Function':
4036 case 'String':
4037 case 'Token':
4038 case 'Comma':
4039 break;
4040
4041 default:
4042 throw new Error('Unknown type: ' + node.type);
4043 }
4044
4045 leave.call(context, node);
4046 }
4047
4048 var enter = noop$1;
4049 var leave = noop$1;
4050
4051 if (typeof options === 'function') {
4052 enter = options;
4053 } else if (options) {
4054 enter = ensureFunction(options.enter);
4055 leave = ensureFunction(options.leave);
4056 }
4057
4058 if (enter === noop$1 && leave === noop$1) {
4059 throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
4060 }
4061
4062 walk(node);
4063 };
4064
4065 var tokenStream = new TokenStream_1();
4066 var astToTokens = {
4067 decorator: function(handlers) {
4068 var curNode = null;
4069 var prev = { len: 0, node: null };
4070 var nodes = [prev];
4071 var buffer = '';
4072
4073 return {
4074 children: handlers.children,
4075 node: function(node) {
4076 var tmp = curNode;
4077 curNode = node;
4078 handlers.node.call(this, node);
4079 curNode = tmp;
4080 },
4081 chunk: function(chunk) {
4082 buffer += chunk;
4083 if (prev.node !== curNode) {
4084 nodes.push({
4085 len: chunk.length,
4086 node: curNode
4087 });
4088 } else {
4089 prev.len += chunk.length;
4090 }
4091 },
4092 result: function() {
4093 return prepareTokens(buffer, nodes);
4094 }
4095 };
4096 }
4097 };
4098
4099 function prepareTokens(str, nodes) {
4100 var tokens = [];
4101 var nodesOffset = 0;
4102 var nodesIndex = 0;
4103 var currentNode = nodes ? nodes[nodesIndex].node : null;
4104
4105 tokenizer(str, tokenStream);
4106
4107 while (!tokenStream.eof) {
4108 if (nodes) {
4109 while (nodesIndex < nodes.length && nodesOffset + nodes[nodesIndex].len <= tokenStream.tokenStart) {
4110 nodesOffset += nodes[nodesIndex++].len;
4111 currentNode = nodes[nodesIndex].node;
4112 }
4113 }
4114
4115 tokens.push({
4116 type: tokenStream.tokenType,
4117 value: tokenStream.getTokenValue(),
4118 index: tokenStream.tokenIndex, // TODO: remove it, temporary solution
4119 balance: tokenStream.balance[tokenStream.tokenIndex], // TODO: remove it, temporary solution
4120 node: currentNode
4121 });
4122 tokenStream.next();
4123 // console.log({ ...tokens[tokens.length - 1], node: undefined });
4124 }
4125
4126 return tokens;
4127 }
4128
4129 var prepareTokens_1 = function(value, syntax) {
4130 if (typeof value === 'string') {
4131 return prepareTokens(value, null);
4132 }
4133
4134 return syntax.generate(value, astToTokens);
4135 };
4136
4137 var MATCH = { type: 'Match' };
4138 var MISMATCH = { type: 'Mismatch' };
4139 var DISALLOW_EMPTY = { type: 'DisallowEmpty' };
4140 var LEFTPARENTHESIS$1 = 40; // (
4141 var RIGHTPARENTHESIS$1 = 41; // )
4142
4143 function createCondition(match, thenBranch, elseBranch) {
4144 // reduce node count
4145 if (thenBranch === MATCH && elseBranch === MISMATCH) {
4146 return match;
4147 }
4148
4149 if (match === MATCH && thenBranch === MATCH && elseBranch === MATCH) {
4150 return match;
4151 }
4152
4153 if (match.type === 'If' && match.else === MISMATCH && thenBranch === MATCH) {
4154 thenBranch = match.then;
4155 match = match.match;
4156 }
4157
4158 return {
4159 type: 'If',
4160 match: match,
4161 then: thenBranch,
4162 else: elseBranch
4163 };
4164 }
4165
4166 function isFunctionType(name) {
4167 return (
4168 name.length > 2 &&
4169 name.charCodeAt(name.length - 2) === LEFTPARENTHESIS$1 &&
4170 name.charCodeAt(name.length - 1) === RIGHTPARENTHESIS$1
4171 );
4172 }
4173
4174 function isEnumCapatible(term) {
4175 return (
4176 term.type === 'Keyword' ||
4177 term.type === 'AtKeyword' ||
4178 term.type === 'Function' ||
4179 term.type === 'Type' && isFunctionType(term.name)
4180 );
4181 }
4182
4183 function buildGroupMatchGraph(combinator, terms, atLeastOneTermMatched) {
4184 switch (combinator) {
4185 case ' ':
4186 // Juxtaposing components means that all of them must occur, in the given order.
4187 //
4188 // a b c
4189 // =
4190 // match a
4191 // then match b
4192 // then match c
4193 // then MATCH
4194 // else MISMATCH
4195 // else MISMATCH
4196 // else MISMATCH
4197 var result = MATCH;
4198
4199 for (var i = terms.length - 1; i >= 0; i--) {
4200 var term = terms[i];
4201
4202 result = createCondition(
4203 term,
4204 result,
4205 MISMATCH
4206 );
4207 }
4208 return result;
4209
4210 case '|':
4211 // A bar (|) separates two or more alternatives: exactly one of them must occur.
4212 //
4213 // a | b | c
4214 // =
4215 // match a
4216 // then MATCH
4217 // else match b
4218 // then MATCH
4219 // else match c
4220 // then MATCH
4221 // else MISMATCH
4222
4223 var result = MISMATCH;
4224 var map = null;
4225
4226 for (var i = terms.length - 1; i >= 0; i--) {
4227 var term = terms[i];
4228
4229 // reduce sequence of keywords into a Enum
4230 if (isEnumCapatible(term)) {
4231 if (map === null && i > 0 && isEnumCapatible(terms[i - 1])) {
4232 map = Object.create(null);
4233 result = createCondition(
4234 {
4235 type: 'Enum',
4236 map: map
4237 },
4238 MATCH,
4239 result
4240 );
4241 }
4242
4243 if (map !== null) {
4244 var key = (isFunctionType(term.name) ? term.name.slice(0, -1) : term.name).toLowerCase();
4245 if (key in map === false) {
4246 map[key] = term;
4247 continue;
4248 }
4249 }
4250 }
4251
4252 map = null;
4253
4254 // create a new conditonal node
4255 result = createCondition(
4256 term,
4257 MATCH,
4258 result
4259 );
4260 }
4261 return result;
4262
4263 case '&&':
4264 // A double ampersand (&&) separates two or more components,
4265 // all of which must occur, in any order.
4266
4267 // Use MatchOnce for groups with a large number of terms,
4268 // since &&-groups produces at least N!-node trees
4269 if (terms.length > 5) {
4270 return {
4271 type: 'MatchOnce',
4272 terms: terms,
4273 all: true
4274 };
4275 }
4276
4277 // Use a combination tree for groups with small number of terms
4278 //
4279 // a && b && c
4280 // =
4281 // match a
4282 // then [b && c]
4283 // else match b
4284 // then [a && c]
4285 // else match c
4286 // then [a && b]
4287 // else MISMATCH
4288 //
4289 // a && b
4290 // =
4291 // match a
4292 // then match b
4293 // then MATCH
4294 // else MISMATCH
4295 // else match b
4296 // then match a
4297 // then MATCH
4298 // else MISMATCH
4299 // else MISMATCH
4300 var result = MISMATCH;
4301
4302 for (var i = terms.length - 1; i >= 0; i--) {
4303 var term = terms[i];
4304 var thenClause;
4305
4306 if (terms.length > 1) {
4307 thenClause = buildGroupMatchGraph(
4308 combinator,
4309 terms.filter(function(newGroupTerm) {
4310 return newGroupTerm !== term;
4311 }),
4312 false
4313 );
4314 } else {
4315 thenClause = MATCH;
4316 }
4317
4318 result = createCondition(
4319 term,
4320 thenClause,
4321 result
4322 );
4323 }
4324 return result;
4325
4326 case '||':
4327 // A double bar (||) separates two or more options:
4328 // one or more of them must occur, in any order.
4329
4330 // Use MatchOnce for groups with a large number of terms,
4331 // since ||-groups produces at least N!-node trees
4332 if (terms.length > 5) {
4333 return {
4334 type: 'MatchOnce',
4335 terms: terms,
4336 all: false
4337 };
4338 }
4339
4340 // Use a combination tree for groups with small number of terms
4341 //
4342 // a || b || c
4343 // =
4344 // match a
4345 // then [b || c]
4346 // else match b
4347 // then [a || c]
4348 // else match c
4349 // then [a || b]
4350 // else MISMATCH
4351 //
4352 // a || b
4353 // =
4354 // match a
4355 // then match b
4356 // then MATCH
4357 // else MATCH
4358 // else match b
4359 // then match a
4360 // then MATCH
4361 // else MATCH
4362 // else MISMATCH
4363 var result = atLeastOneTermMatched ? MATCH : MISMATCH;
4364
4365 for (var i = terms.length - 1; i >= 0; i--) {
4366 var term = terms[i];
4367 var thenClause;
4368
4369 if (terms.length > 1) {
4370 thenClause = buildGroupMatchGraph(
4371 combinator,
4372 terms.filter(function(newGroupTerm) {
4373 return newGroupTerm !== term;
4374 }),
4375 true
4376 );
4377 } else {
4378 thenClause = MATCH;
4379 }
4380
4381 result = createCondition(
4382 term,
4383 thenClause,
4384 result
4385 );
4386 }
4387 return result;
4388 }
4389 }
4390
4391 function buildMultiplierMatchGraph(node) {
4392 var result = MATCH;
4393 var matchTerm = buildMatchGraph(node.term);
4394
4395 if (node.max === 0) {
4396 // disable repeating of empty match to prevent infinite loop
4397 matchTerm = createCondition(
4398 matchTerm,
4399 DISALLOW_EMPTY,
4400 MISMATCH
4401 );
4402
4403 // an occurrence count is not limited, make a cycle;
4404 // to collect more terms on each following matching mismatch
4405 result = createCondition(
4406 matchTerm,
4407 null, // will be a loop
4408 MISMATCH
4409 );
4410
4411 result.then = createCondition(
4412 MATCH,
4413 MATCH,
4414 result // make a loop
4415 );
4416
4417 if (node.comma) {
4418 result.then.else = createCondition(
4419 { type: 'Comma', syntax: node },
4420 result,
4421 MISMATCH
4422 );
4423 }
4424 } else {
4425 // create a match node chain for [min .. max] interval with optional matches
4426 for (var i = node.min || 1; i <= node.max; i++) {
4427 if (node.comma && result !== MATCH) {
4428 result = createCondition(
4429 { type: 'Comma', syntax: node },
4430 result,
4431 MISMATCH
4432 );
4433 }
4434
4435 result = createCondition(
4436 matchTerm,
4437 createCondition(
4438 MATCH,
4439 MATCH,
4440 result
4441 ),
4442 MISMATCH
4443 );
4444 }
4445 }
4446
4447 if (node.min === 0) {
4448 // allow zero match
4449 result = createCondition(
4450 MATCH,
4451 MATCH,
4452 result
4453 );
4454 } else {
4455 // create a match node chain to collect [0 ... min - 1] required matches
4456 for (var i = 0; i < node.min - 1; i++) {
4457 if (node.comma && result !== MATCH) {
4458 result = createCondition(
4459 { type: 'Comma', syntax: node },
4460 result,
4461 MISMATCH
4462 );
4463 }
4464
4465 result = createCondition(
4466 matchTerm,
4467 result,
4468 MISMATCH
4469 );
4470 }
4471 }
4472
4473 return result;
4474 }
4475
4476 function buildMatchGraph(node) {
4477 if (typeof node === 'function') {
4478 return {
4479 type: 'Generic',
4480 fn: node
4481 };
4482 }
4483
4484 switch (node.type) {
4485 case 'Group':
4486 var result = buildGroupMatchGraph(
4487 node.combinator,
4488 node.terms.map(buildMatchGraph),
4489 false
4490 );
4491
4492 if (node.disallowEmpty) {
4493 result = createCondition(
4494 result,
4495 DISALLOW_EMPTY,
4496 MISMATCH
4497 );
4498 }
4499
4500 return result;
4501
4502 case 'Multiplier':
4503 return buildMultiplierMatchGraph(node);
4504
4505 case 'Type':
4506 case 'Property':
4507 return {
4508 type: node.type,
4509 name: node.name,
4510 syntax: node
4511 };
4512
4513 case 'Keyword':
4514 return {
4515 type: node.type,
4516 name: node.name.toLowerCase(),
4517 syntax: node
4518 };
4519
4520 case 'AtKeyword':
4521 return {
4522 type: node.type,
4523 name: '@' + node.name.toLowerCase(),
4524 syntax: node
4525 };
4526
4527 case 'Function':
4528 return {
4529 type: node.type,
4530 name: node.name.toLowerCase() + '(',
4531 syntax: node
4532 };
4533
4534 case 'String':
4535 // convert a one char length String to a Token
4536 if (node.value.length === 3) {
4537 return {
4538 type: 'Token',
4539 value: node.value.charAt(1),
4540 syntax: node
4541 };
4542 }
4543
4544 // otherwise use it as is
4545 return {
4546 type: node.type,
4547 value: node.value.substr(1, node.value.length - 2).replace(/\\'/g, '\''),
4548 syntax: node
4549 };
4550
4551 case 'Token':
4552 return {
4553 type: node.type,
4554 value: node.value,
4555 syntax: node
4556 };
4557
4558 case 'Comma':
4559 return {
4560 type: node.type,
4561 syntax: node
4562 };
4563
4564 default:
4565 throw new Error('Unknown node type:', node.type);
4566 }
4567 }
4568
4569 var matchGraph = {
4570 MATCH: MATCH,
4571 MISMATCH: MISMATCH,
4572 DISALLOW_EMPTY: DISALLOW_EMPTY,
4573 buildMatchGraph: function(syntaxTree, ref) {
4574 if (typeof syntaxTree === 'string') {
4575 syntaxTree = parse_1(syntaxTree);
4576 }
4577
4578 return {
4579 type: 'MatchGraph',
4580 match: buildMatchGraph(syntaxTree),
4581 syntax: ref || null,
4582 source: syntaxTree
4583 };
4584 }
4585 };
4586
4587 var hasOwnProperty$1 = Object.prototype.hasOwnProperty;
4588
4589 var MATCH$1 = matchGraph.MATCH;
4590 var MISMATCH$1 = matchGraph.MISMATCH;
4591 var DISALLOW_EMPTY$1 = matchGraph.DISALLOW_EMPTY;
4592 var TYPE$6 = _const.TYPE;
4593
4594 var STUB = 0;
4595 var TOKEN = 1;
4596 var OPEN_SYNTAX = 2;
4597 var CLOSE_SYNTAX = 3;
4598
4599 var EXIT_REASON_MATCH = 'Match';
4600 var EXIT_REASON_MISMATCH = 'Mismatch';
4601 var EXIT_REASON_ITERATION_LIMIT = 'Maximum iteration number exceeded (please fill an issue on https://github.com/csstree/csstree/issues)';
4602
4603 var ITERATION_LIMIT = 15000;
4604 var totalIterationCount = 0;
4605
4606 function reverseList(list) {
4607 var prev = null;
4608 var next = null;
4609 var item = list;
4610
4611 while (item !== null) {
4612 next = item.prev;
4613 item.prev = prev;
4614 prev = item;
4615 item = next;
4616 }
4617
4618 return prev;
4619 }
4620
4621 function areStringsEqualCaseInsensitive(testStr, referenceStr) {
4622 if (testStr.length !== referenceStr.length) {
4623 return false;
4624 }
4625
4626 for (var i = 0; i < testStr.length; i++) {
4627 var testCode = testStr.charCodeAt(i);
4628 var referenceCode = referenceStr.charCodeAt(i);
4629
4630 // testCode.toLowerCase() for U+0041 LATIN CAPITAL LETTER A (A) .. U+005A LATIN CAPITAL LETTER Z (Z).
4631 if (testCode >= 0x0041 && testCode <= 0x005A) {
4632 testCode = testCode | 32;
4633 }
4634
4635 if (testCode !== referenceCode) {
4636 return false;
4637 }
4638 }
4639
4640 return true;
4641 }
4642
4643 function isContextEdgeDelim(token) {
4644 if (token.type !== TYPE$6.Delim) {
4645 return false;
4646 }
4647
4648 // Fix matching for unicode-range: U+30??, U+FF00-FF9F
4649 // Probably we need to check out previous match instead
4650 return token.value !== '?';
4651 }
4652
4653 function isCommaContextStart(token) {
4654 if (token === null) {
4655 return true;
4656 }
4657
4658 return (
4659 token.type === TYPE$6.Comma ||
4660 token.type === TYPE$6.Function ||
4661 token.type === TYPE$6.LeftParenthesis ||
4662 token.type === TYPE$6.LeftSquareBracket ||
4663 token.type === TYPE$6.LeftCurlyBracket ||
4664 isContextEdgeDelim(token)
4665 );
4666 }
4667
4668 function isCommaContextEnd(token) {
4669 if (token === null) {
4670 return true;
4671 }
4672
4673 return (
4674 token.type === TYPE$6.RightParenthesis ||
4675 token.type === TYPE$6.RightSquareBracket ||
4676 token.type === TYPE$6.RightCurlyBracket ||
4677 token.type === TYPE$6.Delim
4678 );
4679 }
4680
4681 function internalMatch(tokens, state, syntaxes) {
4682 function moveToNextToken() {
4683 do {
4684 tokenIndex++;
4685 token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
4686 } while (token !== null && (token.type === TYPE$6.WhiteSpace || token.type === TYPE$6.Comment));
4687 }
4688
4689 function getNextToken(offset) {
4690 var nextIndex = tokenIndex + offset;
4691
4692 return nextIndex < tokens.length ? tokens[nextIndex] : null;
4693 }
4694
4695 function stateSnapshotFromSyntax(nextState, prev) {
4696 return {
4697 nextState: nextState,
4698 matchStack: matchStack,
4699 syntaxStack: syntaxStack,
4700 thenStack: thenStack,
4701 tokenIndex: tokenIndex,
4702 prev: prev
4703 };
4704 }
4705
4706 function pushThenStack(nextState) {
4707 thenStack = {
4708 nextState: nextState,
4709 matchStack: matchStack,
4710 syntaxStack: syntaxStack,
4711 prev: thenStack
4712 };
4713 }
4714
4715 function pushElseStack(nextState) {
4716 elseStack = stateSnapshotFromSyntax(nextState, elseStack);
4717 }
4718
4719 function addTokenToMatch() {
4720 matchStack = {
4721 type: TOKEN,
4722 syntax: state.syntax,
4723 token: token,
4724 prev: matchStack
4725 };
4726
4727 moveToNextToken();
4728 syntaxStash = null;
4729
4730 if (tokenIndex > longestMatch) {
4731 longestMatch = tokenIndex;
4732 }
4733 }
4734
4735 function openSyntax() {
4736 syntaxStack = {
4737 syntax: state.syntax,
4738 opts: state.syntax.opts || (syntaxStack !== null && syntaxStack.opts) || null,
4739 prev: syntaxStack
4740 };
4741
4742 matchStack = {
4743 type: OPEN_SYNTAX,
4744 syntax: state.syntax,
4745 token: matchStack.token,
4746 prev: matchStack
4747 };
4748 }
4749
4750 function closeSyntax() {
4751 if (matchStack.type === OPEN_SYNTAX) {
4752 matchStack = matchStack.prev;
4753 } else {
4754 matchStack = {
4755 type: CLOSE_SYNTAX,
4756 syntax: syntaxStack.syntax,
4757 token: matchStack.token,
4758 prev: matchStack
4759 };
4760 }
4761
4762 syntaxStack = syntaxStack.prev;
4763 }
4764
4765 var syntaxStack = null;
4766 var thenStack = null;
4767 var elseStack = null;
4768
4769 // null – stashing allowed, nothing stashed
4770 // false – stashing disabled, nothing stashed
4771 // anithing else – fail stashable syntaxes, some syntax stashed
4772 var syntaxStash = null;
4773
4774 var iterationCount = 0; // count iterations and prevent infinite loop
4775 var exitReason = null;
4776
4777 var token = null;
4778 var tokenIndex = -1;
4779 var longestMatch = 0;
4780 var matchStack = {
4781 type: STUB,
4782 syntax: null,
4783 token: null,
4784 prev: null
4785 };
4786
4787 moveToNextToken();
4788
4789 while (exitReason === null && ++iterationCount < ITERATION_LIMIT) {
4790 // function mapList(list, fn) {
4791 // var result = [];
4792 // while (list) {
4793 // result.unshift(fn(list));
4794 // list = list.prev;
4795 // }
4796 // return result;
4797 // }
4798 // console.log('--\n',
4799 // '#' + iterationCount,
4800 // require('util').inspect({
4801 // match: mapList(matchStack, x => x.type === TOKEN ? x.token && x.token.value : x.syntax ? ({ [OPEN_SYNTAX]: '<', [CLOSE_SYNTAX]: '</' }[x.type] || x.type) + '!' + x.syntax.name : null),
4802 // token: token && token.value,
4803 // tokenIndex,
4804 // syntax: syntax.type + (syntax.id ? ' #' + syntax.id : '')
4805 // }, { depth: null })
4806 // );
4807 switch (state.type) {
4808 case 'Match':
4809 if (thenStack === null) {
4810 // turn to MISMATCH when some tokens left unmatched
4811 if (token !== null) {
4812 // doesn't mismatch if just one token left and it's an IE hack
4813 if (tokenIndex !== tokens.length - 1 || (token.value !== '\\0' && token.value !== '\\9')) {
4814 state = MISMATCH$1;
4815 break;
4816 }
4817 }
4818
4819 // break the main loop, return a result - MATCH
4820 exitReason = EXIT_REASON_MATCH;
4821 break;
4822 }
4823
4824 // go to next syntax (`then` branch)
4825 state = thenStack.nextState;
4826
4827 // check match is not empty
4828 if (state === DISALLOW_EMPTY$1) {
4829 if (thenStack.matchStack === matchStack) {
4830 state = MISMATCH$1;
4831 break;
4832 } else {
4833 state = MATCH$1;
4834 }
4835 }
4836
4837 // close syntax if needed
4838 while (thenStack.syntaxStack !== syntaxStack) {
4839 closeSyntax();
4840 }
4841
4842 // pop stack
4843 thenStack = thenStack.prev;
4844 break;
4845
4846 case 'Mismatch':
4847 // when some syntax is stashed
4848 if (syntaxStash !== null && syntaxStash !== false) {
4849 // there is no else branches or a branch reduce match stack
4850 if (elseStack === null || tokenIndex > elseStack.tokenIndex) {
4851 // restore state from the stash
4852 elseStack = syntaxStash;
4853 syntaxStash = false; // disable stashing
4854 }
4855 } else if (elseStack === null) {
4856 // no else branches -> break the main loop
4857 // return a result - MISMATCH
4858 exitReason = EXIT_REASON_MISMATCH;
4859 break;
4860 }
4861
4862 // go to next syntax (`else` branch)
4863 state = elseStack.nextState;
4864
4865 // restore all the rest stack states
4866 thenStack = elseStack.thenStack;
4867 syntaxStack = elseStack.syntaxStack;
4868 matchStack = elseStack.matchStack;
4869 tokenIndex = elseStack.tokenIndex;
4870 token = tokenIndex < tokens.length ? tokens[tokenIndex] : null;
4871
4872 // pop stack
4873 elseStack = elseStack.prev;
4874 break;
4875
4876 case 'MatchGraph':
4877 state = state.match;
4878 break;
4879
4880 case 'If':
4881 // IMPORTANT: else stack push must go first,
4882 // since it stores the state of thenStack before changes
4883 if (state.else !== MISMATCH$1) {
4884 pushElseStack(state.else);
4885 }
4886
4887 if (state.then !== MATCH$1) {
4888 pushThenStack(state.then);
4889 }
4890
4891 state = state.match;
4892 break;
4893
4894 case 'MatchOnce':
4895 state = {
4896 type: 'MatchOnceBuffer',
4897 syntax: state,
4898 index: 0,
4899 mask: 0
4900 };
4901 break;
4902
4903 case 'MatchOnceBuffer':
4904 var terms = state.syntax.terms;
4905
4906 if (state.index === terms.length) {
4907 // no matches at all or it's required all terms to be matched
4908 if (state.mask === 0 || state.syntax.all) {
4909 state = MISMATCH$1;
4910 break;
4911 }
4912
4913 // a partial match is ok
4914 state = MATCH$1;
4915 break;
4916 }
4917
4918 // all terms are matched
4919 if (state.mask === (1 << terms.length) - 1) {
4920 state = MATCH$1;
4921 break;
4922 }
4923
4924 for (; state.index < terms.length; state.index++) {
4925 var matchFlag = 1 << state.index;
4926
4927 if ((state.mask & matchFlag) === 0) {
4928 // IMPORTANT: else stack push must go first,
4929 // since it stores the state of thenStack before changes
4930 pushElseStack(state);
4931 pushThenStack({
4932 type: 'AddMatchOnce',
4933 syntax: state.syntax,
4934 mask: state.mask | matchFlag
4935 });
4936
4937 // match
4938 state = terms[state.index++];
4939 break;
4940 }
4941 }
4942 break;
4943
4944 case 'AddMatchOnce':
4945 state = {
4946 type: 'MatchOnceBuffer',
4947 syntax: state.syntax,
4948 index: 0,
4949 mask: state.mask
4950 };
4951 break;
4952
4953 case 'Enum':
4954 if (token !== null) {
4955 var name = token.value.toLowerCase();
4956
4957 // drop \0 and \9 hack from keyword name
4958 if (name.indexOf('\\') !== -1) {
4959 name = name.replace(/\\[09].*$/, '');
4960 }
4961
4962 if (hasOwnProperty$1.call(state.map, name)) {
4963 state = state.map[name];
4964 break;
4965 }
4966 }
4967
4968 state = MISMATCH$1;
4969 break;
4970
4971 case 'Generic':
4972 var opts = syntaxStack !== null ? syntaxStack.opts : null;
4973 var lastTokenIndex = tokenIndex + Math.floor(state.fn(token, getNextToken, opts));
4974
4975 if (!isNaN(lastTokenIndex) && lastTokenIndex > tokenIndex) {
4976 while (tokenIndex < lastTokenIndex) {
4977 addTokenToMatch();
4978 }
4979
4980 state = MATCH$1;
4981 } else {
4982 state = MISMATCH$1;
4983 }
4984
4985 break;
4986
4987 case 'Type':
4988 case 'Property':
4989 var syntaxDict = state.type === 'Type' ? 'types' : 'properties';
4990 var dictSyntax = hasOwnProperty$1.call(syntaxes, syntaxDict) ? syntaxes[syntaxDict][state.name] : null;
4991
4992 if (!dictSyntax || !dictSyntax.match) {
4993 throw new Error(
4994 'Bad syntax reference: ' +
4995 (state.type === 'Type'
4996 ? '<' + state.name + '>'
4997 : '<\'' + state.name + '\'>')
4998 );
4999 }
5000
5001 // stash a syntax for types with low priority
5002 if (syntaxStash !== false && token !== null && state.type === 'Type') {
5003 var lowPriorityMatching =
5004 // https://drafts.csswg.org/css-values-4/#custom-idents
5005 // When parsing positionally-ambiguous keywords in a property value, a <custom-ident> production
5006 // can only claim the keyword if no other unfulfilled production can claim it.
5007 (state.name === 'custom-ident' && token.type === TYPE$6.Ident) ||
5008
5009 // https://drafts.csswg.org/css-values-4/#lengths
5010 // ... if a `0` could be parsed as either a <number> or a <length> in a property (such as line-height),
5011 // it must parse as a <number>
5012 (state.name === 'length' && token.value === '0');
5013
5014 if (lowPriorityMatching) {
5015 if (syntaxStash === null) {
5016 syntaxStash = stateSnapshotFromSyntax(state, elseStack);
5017 }
5018
5019 state = MISMATCH$1;
5020 break;
5021 }
5022 }
5023
5024 openSyntax();
5025 state = dictSyntax.match;
5026 break;
5027
5028 case 'Keyword':
5029 var name = state.name;
5030
5031 if (token !== null) {
5032 var keywordName = token.value;
5033
5034 // drop \0 and \9 hack from keyword name
5035 if (keywordName.indexOf('\\') !== -1) {
5036 keywordName = keywordName.replace(/\\[09].*$/, '');
5037 }
5038
5039 if (areStringsEqualCaseInsensitive(keywordName, name)) {
5040 addTokenToMatch();
5041 state = MATCH$1;
5042 break;
5043 }
5044 }
5045
5046 state = MISMATCH$1;
5047 break;
5048
5049 case 'AtKeyword':
5050 case 'Function':
5051 if (token !== null && areStringsEqualCaseInsensitive(token.value, state.name)) {
5052 addTokenToMatch();
5053 state = MATCH$1;
5054 break;
5055 }
5056
5057 state = MISMATCH$1;
5058 break;
5059
5060 case 'Token':
5061 if (token !== null && token.value === state.value) {
5062 addTokenToMatch();
5063 state = MATCH$1;
5064 break;
5065 }
5066
5067 state = MISMATCH$1;
5068 break;
5069
5070 case 'Comma':
5071 if (token !== null && token.type === TYPE$6.Comma) {
5072 if (isCommaContextStart(matchStack.token)) {
5073 state = MISMATCH$1;
5074 } else {
5075 addTokenToMatch();
5076 state = isCommaContextEnd(token) ? MISMATCH$1 : MATCH$1;
5077 }
5078 } else {
5079 state = isCommaContextStart(matchStack.token) || isCommaContextEnd(token) ? MATCH$1 : MISMATCH$1;
5080 }
5081
5082 break;
5083
5084 case 'String':
5085 var string = '';
5086
5087 for (var lastTokenIndex = tokenIndex; lastTokenIndex < tokens.length && string.length < state.value.length; lastTokenIndex++) {
5088 string += tokens[lastTokenIndex].value;
5089 }
5090
5091 if (areStringsEqualCaseInsensitive(string, state.value)) {
5092 while (tokenIndex < lastTokenIndex) {
5093 addTokenToMatch();
5094 }
5095
5096 state = MATCH$1;
5097 } else {
5098 state = MISMATCH$1;
5099 }
5100
5101 break;
5102
5103 default:
5104 throw new Error('Unknown node type: ' + state.type);
5105 }
5106 }
5107
5108 totalIterationCount += iterationCount;
5109
5110 switch (exitReason) {
5111 case null:
5112 console.warn('[csstree-match] BREAK after ' + ITERATION_LIMIT + ' iterations');
5113 exitReason = EXIT_REASON_ITERATION_LIMIT;
5114 matchStack = null;
5115 break;
5116
5117 case EXIT_REASON_MATCH:
5118 while (syntaxStack !== null) {
5119 closeSyntax();
5120 }
5121 break;
5122
5123 default:
5124 matchStack = null;
5125 }
5126
5127 return {
5128 tokens: tokens,
5129 reason: exitReason,
5130 iterations: iterationCount,
5131 match: matchStack,
5132 longestMatch: longestMatch
5133 };
5134 }
5135
5136 function matchAsList(tokens, matchGraph, syntaxes) {
5137 var matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
5138
5139 if (matchResult.match !== null) {
5140 var item = reverseList(matchResult.match).prev;
5141
5142 matchResult.match = [];
5143
5144 while (item !== null) {
5145 switch (item.type) {
5146 case STUB:
5147 break;
5148
5149 case OPEN_SYNTAX:
5150 case CLOSE_SYNTAX:
5151 matchResult.match.push({
5152 type: item.type,
5153 syntax: item.syntax
5154 });
5155 break;
5156
5157 default:
5158 matchResult.match.push({
5159 token: item.token.value,
5160 node: item.token.node
5161 });
5162 break;
5163 }
5164
5165 item = item.prev;
5166 }
5167 }
5168
5169 return matchResult;
5170 }
5171
5172 function matchAsTree(tokens, matchGraph, syntaxes) {
5173 var matchResult = internalMatch(tokens, matchGraph, syntaxes || {});
5174
5175 if (matchResult.match === null) {
5176 return matchResult;
5177 }
5178
5179 var item = matchResult.match;
5180 var host = matchResult.match = {
5181 syntax: matchGraph.syntax || null,
5182 match: []
5183 };
5184 var hostStack = [host];
5185
5186 // revert a list and start with 2nd item since 1st is a stub item
5187 item = reverseList(item).prev;
5188
5189 // build a tree
5190 while (item !== null) {
5191 switch (item.type) {
5192 case OPEN_SYNTAX:
5193 host.match.push(host = {
5194 syntax: item.syntax,
5195 match: []
5196 });
5197 hostStack.push(host);
5198 break;
5199
5200 case CLOSE_SYNTAX:
5201 hostStack.pop();
5202 host = hostStack[hostStack.length - 1];
5203 break;
5204
5205 default:
5206 host.match.push({
5207 syntax: item.syntax || null,
5208 token: item.token.value,
5209 node: item.token.node
5210 });
5211 }
5212
5213 item = item.prev;
5214 }
5215
5216 return matchResult;
5217 }
5218
5219 var match = {
5220 matchAsList: matchAsList,
5221 matchAsTree: matchAsTree,
5222 getTotalIterationCount: function() {
5223 return totalIterationCount;
5224 }
5225 };
5226
5227 function getTrace(node) {
5228 function shouldPutToTrace(syntax) {
5229 if (syntax === null) {
5230 return false;
5231 }
5232
5233 return (
5234 syntax.type === 'Type' ||
5235 syntax.type === 'Property' ||
5236 syntax.type === 'Keyword'
5237 );
5238 }
5239
5240 function hasMatch(matchNode) {
5241 if (Array.isArray(matchNode.match)) {
5242 // use for-loop for better perfomance
5243 for (var i = 0; i < matchNode.match.length; i++) {
5244 if (hasMatch(matchNode.match[i])) {
5245 if (shouldPutToTrace(matchNode.syntax)) {
5246 result.unshift(matchNode.syntax);
5247 }
5248
5249 return true;
5250 }
5251 }
5252 } else if (matchNode.node === node) {
5253 result = shouldPutToTrace(matchNode.syntax)
5254 ? [matchNode.syntax]
5255 : [];
5256
5257 return true;
5258 }
5259
5260 return false;
5261 }
5262
5263 var result = null;
5264
5265 if (this.matched !== null) {
5266 hasMatch(this.matched);
5267 }
5268
5269 return result;
5270 }
5271
5272 function testNode(match, node, fn) {
5273 var trace = getTrace.call(match, node);
5274
5275 if (trace === null) {
5276 return false;
5277 }
5278
5279 return trace.some(fn);
5280 }
5281
5282 function isType(node, type) {
5283 return testNode(this, node, function(matchNode) {
5284 return matchNode.type === 'Type' && matchNode.name === type;
5285 });
5286 }
5287
5288 function isProperty(node, property) {
5289 return testNode(this, node, function(matchNode) {
5290 return matchNode.type === 'Property' && matchNode.name === property;
5291 });
5292 }
5293
5294 function isKeyword(node) {
5295 return testNode(this, node, function(matchNode) {
5296 return matchNode.type === 'Keyword';
5297 });
5298 }
5299
5300 var trace = {
5301 getTrace: getTrace,
5302 isType: isType,
5303 isProperty: isProperty,
5304 isKeyword: isKeyword
5305 };
5306
5307 function getFirstMatchNode(matchNode) {
5308 if ('node' in matchNode) {
5309 return matchNode.node;
5310 }
5311
5312 return getFirstMatchNode(matchNode.match[0]);
5313 }
5314
5315 function getLastMatchNode(matchNode) {
5316 if ('node' in matchNode) {
5317 return matchNode.node;
5318 }
5319
5320 return getLastMatchNode(matchNode.match[matchNode.match.length - 1]);
5321 }
5322
5323 function matchFragments(lexer, ast, match, type, name) {
5324 function findFragments(matchNode) {
5325 if (matchNode.syntax !== null &&
5326 matchNode.syntax.type === type &&
5327 matchNode.syntax.name === name) {
5328 var start = getFirstMatchNode(matchNode);
5329 var end = getLastMatchNode(matchNode);
5330
5331 lexer.syntax.walk(ast, function(node, item, list) {
5332 if (node === start) {
5333 var nodes = new List_1();
5334
5335 do {
5336 nodes.appendData(item.data);
5337
5338 if (item.data === end) {
5339 break;
5340 }
5341
5342 item = item.next;
5343 } while (item !== null);
5344
5345 fragments.push({
5346 parent: list,
5347 nodes: nodes
5348 });
5349 }
5350 });
5351 }
5352
5353 if (Array.isArray(matchNode.match)) {
5354 matchNode.match.forEach(findFragments);
5355 }
5356 }
5357
5358 var fragments = [];
5359
5360 if (match.matched !== null) {
5361 findFragments(match.matched);
5362 }
5363
5364 return fragments;
5365 }
5366
5367 var search = {
5368 matchFragments: matchFragments
5369 };
5370
5371 var hasOwnProperty$2 = Object.prototype.hasOwnProperty;
5372
5373 function isValidNumber(value) {
5374 // Number.isInteger(value) && value >= 0
5375 return (
5376 typeof value === 'number' &&
5377 isFinite(value) &&
5378 Math.floor(value) === value &&
5379 value >= 0
5380 );
5381 }
5382
5383 function isValidLocation(loc) {
5384 return (
5385 Boolean(loc) &&
5386 isValidNumber(loc.offset) &&
5387 isValidNumber(loc.line) &&
5388 isValidNumber(loc.column)
5389 );
5390 }
5391
5392 function createNodeStructureChecker(type, fields) {
5393 return function checkNode(node, warn) {
5394 if (!node || node.constructor !== Object) {
5395 return warn(node, 'Type of node should be an Object');
5396 }
5397
5398 for (var key in node) {
5399 var valid = true;
5400
5401 if (hasOwnProperty$2.call(node, key) === false) {
5402 continue;
5403 }
5404
5405 if (key === 'type') {
5406 if (node.type !== type) {
5407 warn(node, 'Wrong node type `' + node.type + '`, expected `' + type + '`');
5408 }
5409 } else if (key === 'loc') {
5410 if (node.loc === null) {
5411 continue;
5412 } else if (node.loc && node.loc.constructor === Object) {
5413 if (typeof node.loc.source !== 'string') {
5414 key += '.source';
5415 } else if (!isValidLocation(node.loc.start)) {
5416 key += '.start';
5417 } else if (!isValidLocation(node.loc.end)) {
5418 key += '.end';
5419 } else {
5420 continue;
5421 }
5422 }
5423
5424 valid = false;
5425 } else if (fields.hasOwnProperty(key)) {
5426 for (var i = 0, valid = false; !valid && i < fields[key].length; i++) {
5427 var fieldType = fields[key][i];
5428
5429 switch (fieldType) {
5430 case String:
5431 valid = typeof node[key] === 'string';
5432 break;
5433
5434 case Boolean:
5435 valid = typeof node[key] === 'boolean';
5436 break;
5437
5438 case null:
5439 valid = node[key] === null;
5440 break;
5441
5442 default:
5443 if (typeof fieldType === 'string') {
5444 valid = node[key] && node[key].type === fieldType;
5445 } else if (Array.isArray(fieldType)) {
5446 valid = node[key] instanceof List_1;
5447 }
5448 }
5449 }
5450 } else {
5451 warn(node, 'Unknown field `' + key + '` for ' + type + ' node type');
5452 }
5453
5454 if (!valid) {
5455 warn(node, 'Bad value for `' + type + '.' + key + '`');
5456 }
5457 }
5458
5459 for (var key in fields) {
5460 if (hasOwnProperty$2.call(fields, key) &&
5461 hasOwnProperty$2.call(node, key) === false) {
5462 warn(node, 'Field `' + type + '.' + key + '` is missed');
5463 }
5464 }
5465 };
5466 }
5467
5468 function processStructure(name, nodeType) {
5469 var structure = nodeType.structure;
5470 var fields = {
5471 type: String,
5472 loc: true
5473 };
5474 var docs = {
5475 type: '"' + name + '"'
5476 };
5477
5478 for (var key in structure) {
5479 if (hasOwnProperty$2.call(structure, key) === false) {
5480 continue;
5481 }
5482
5483 var docsTypes = [];
5484 var fieldTypes = fields[key] = Array.isArray(structure[key])
5485 ? structure[key].slice()
5486 : [structure[key]];
5487
5488 for (var i = 0; i < fieldTypes.length; i++) {
5489 var fieldType = fieldTypes[i];
5490 if (fieldType === String || fieldType === Boolean) {
5491 docsTypes.push(fieldType.name);
5492 } else if (fieldType === null) {
5493 docsTypes.push('null');
5494 } else if (typeof fieldType === 'string') {
5495 docsTypes.push('<' + fieldType + '>');
5496 } else if (Array.isArray(fieldType)) {
5497 docsTypes.push('List'); // TODO: use type enum
5498 } else {
5499 throw new Error('Wrong value `' + fieldType + '` in `' + name + '.' + key + '` structure definition');
5500 }
5501 }
5502
5503 docs[key] = docsTypes.join(' | ');
5504 }
5505
5506 return {
5507 docs: docs,
5508 check: createNodeStructureChecker(name, fields)
5509 };
5510 }
5511
5512 var structure = {
5513 getStructureFromConfig: function(config) {
5514 var structure = {};
5515
5516 if (config.node) {
5517 for (var name in config.node) {
5518 if (hasOwnProperty$2.call(config.node, name)) {
5519 var nodeType = config.node[name];
5520
5521 if (nodeType.structure) {
5522 structure[name] = processStructure(name, nodeType);
5523 } else {
5524 throw new Error('Missed `structure` field in `' + name + '` node type definition');
5525 }
5526 }
5527 }
5528 }
5529
5530 return structure;
5531 }
5532 };
5533
5534 var SyntaxReferenceError$1 = error.SyntaxReferenceError;
5535 var SyntaxMatchError$1 = error.SyntaxMatchError;
5536
5537
5538
5539
5540
5541
5542 var buildMatchGraph$1 = matchGraph.buildMatchGraph;
5543 var matchAsTree$1 = match.matchAsTree;
5544
5545
5546 var getStructureFromConfig = structure.getStructureFromConfig;
5547 var cssWideKeywords$1 = buildMatchGraph$1('inherit | initial | unset');
5548 var cssWideKeywordsWithExpression = buildMatchGraph$1('inherit | initial | unset | <-ms-legacy-expression>');
5549
5550 function dumpMapSyntax(map, compact, syntaxAsAst) {
5551 var result = {};
5552
5553 for (var name in map) {
5554 if (map[name].syntax) {
5555 result[name] = syntaxAsAst
5556 ? map[name].syntax
5557 : generate_1(map[name].syntax, { compact: compact });
5558 }
5559 }
5560
5561 return result;
5562 }
5563
5564 function dumpAtruleMapSyntax(map, compact, syntaxAsAst) {
5565 const result = {};
5566
5567 for (const [name, atrule] of Object.entries(map)) {
5568 result[name] = {
5569 prelude: atrule.prelude && (
5570 syntaxAsAst
5571 ? atrule.prelude.syntax
5572 : generate_1(atrule.prelude.syntax, { compact })
5573 ),
5574 descriptors: atrule.descriptors && dumpMapSyntax(atrule.descriptors, compact, syntaxAsAst)
5575 };
5576 }
5577
5578 return result;
5579 }
5580
5581 function valueHasVar(tokens) {
5582 for (var i = 0; i < tokens.length; i++) {
5583 if (tokens[i].value.toLowerCase() === 'var(') {
5584 return true;
5585 }
5586 }
5587
5588 return false;
5589 }
5590
5591 function buildMatchResult(match, error, iterations) {
5592 return {
5593 matched: match,
5594 iterations: iterations,
5595 error: error,
5596 getTrace: trace.getTrace,
5597 isType: trace.isType,
5598 isProperty: trace.isProperty,
5599 isKeyword: trace.isKeyword
5600 };
5601 }
5602
5603 function matchSyntax(lexer, syntax, value, useCommon) {
5604 var tokens = prepareTokens_1(value, lexer.syntax);
5605 var result;
5606
5607 if (valueHasVar(tokens)) {
5608 return buildMatchResult(null, new Error('Matching for a tree with var() is not supported'));
5609 }
5610
5611 if (useCommon) {
5612 result = matchAsTree$1(tokens, lexer.valueCommonSyntax, lexer);
5613 }
5614
5615 if (!useCommon || !result.match) {
5616 result = matchAsTree$1(tokens, syntax.match, lexer);
5617 if (!result.match) {
5618 return buildMatchResult(
5619 null,
5620 new SyntaxMatchError$1(result.reason, syntax.syntax, value, result),
5621 result.iterations
5622 );
5623 }
5624 }
5625
5626 return buildMatchResult(result.match, null, result.iterations);
5627 }
5628
5629 var Lexer = function(config, syntax, structure) {
5630 this.valueCommonSyntax = cssWideKeywords$1;
5631 this.syntax = syntax;
5632 this.generic = false;
5633 this.atrules = {};
5634 this.properties = {};
5635 this.types = {};
5636 this.structure = structure || getStructureFromConfig(config);
5637
5638 if (config) {
5639 if (config.types) {
5640 for (var name in config.types) {
5641 this.addType_(name, config.types[name]);
5642 }
5643 }
5644
5645 if (config.generic) {
5646 this.generic = true;
5647 for (var name in generic) {
5648 this.addType_(name, generic[name]);
5649 }
5650 }
5651
5652 if (config.atrules) {
5653 for (var name in config.atrules) {
5654 this.addAtrule_(name, config.atrules[name]);
5655 }
5656 }
5657
5658 if (config.properties) {
5659 for (var name in config.properties) {
5660 this.addProperty_(name, config.properties[name]);
5661 }
5662 }
5663 }
5664 };
5665
5666 Lexer.prototype = {
5667 structure: {},
5668 checkStructure: function(ast) {
5669 function collectWarning(node, message) {
5670 warns.push({
5671 node: node,
5672 message: message
5673 });
5674 }
5675
5676 var structure = this.structure;
5677 var warns = [];
5678
5679 this.syntax.walk(ast, function(node) {
5680 if (structure.hasOwnProperty(node.type)) {
5681 structure[node.type].check(node, collectWarning);
5682 } else {
5683 collectWarning(node, 'Unknown node type `' + node.type + '`');
5684 }
5685 });
5686
5687 return warns.length ? warns : false;
5688 },
5689
5690 createDescriptor: function(syntax, type, name, parent = null) {
5691 var ref = {
5692 type: type,
5693 name: name
5694 };
5695 var descriptor = {
5696 type: type,
5697 name: name,
5698 parent: parent,
5699 syntax: null,
5700 match: null
5701 };
5702
5703 if (typeof syntax === 'function') {
5704 descriptor.match = buildMatchGraph$1(syntax, ref);
5705 } else {
5706 if (typeof syntax === 'string') {
5707 // lazy parsing on first access
5708 Object.defineProperty(descriptor, 'syntax', {
5709 get: function() {
5710 Object.defineProperty(descriptor, 'syntax', {
5711 value: parse_1(syntax)
5712 });
5713
5714 return descriptor.syntax;
5715 }
5716 });
5717 } else {
5718 descriptor.syntax = syntax;
5719 }
5720
5721 // lazy graph build on first access
5722 Object.defineProperty(descriptor, 'match', {
5723 get: function() {
5724 Object.defineProperty(descriptor, 'match', {
5725 value: buildMatchGraph$1(descriptor.syntax, ref)
5726 });
5727
5728 return descriptor.match;
5729 }
5730 });
5731 }
5732
5733 return descriptor;
5734 },
5735 addAtrule_: function(name, syntax) {
5736 if (!syntax) {
5737 return;
5738 }
5739
5740 this.atrules[name] = {
5741 type: 'Atrule',
5742 name: name,
5743 prelude: syntax.prelude ? this.createDescriptor(syntax.prelude, 'AtrulePrelude', name) : null,
5744 descriptors: syntax.descriptors
5745 ? Object.keys(syntax.descriptors).reduce((res, descName) => {
5746 res[descName] = this.createDescriptor(syntax.descriptors[descName], 'AtruleDescriptor', descName, name);
5747 return res;
5748 }, {})
5749 : null
5750 };
5751 },
5752 addProperty_: function(name, syntax) {
5753 if (!syntax) {
5754 return;
5755 }
5756
5757 this.properties[name] = this.createDescriptor(syntax, 'Property', name);
5758 },
5759 addType_: function(name, syntax) {
5760 if (!syntax) {
5761 return;
5762 }
5763
5764 this.types[name] = this.createDescriptor(syntax, 'Type', name);
5765
5766 if (syntax === generic['-ms-legacy-expression']) {
5767 this.valueCommonSyntax = cssWideKeywordsWithExpression;
5768 }
5769 },
5770
5771 checkAtruleName: function(atruleName) {
5772 if (!this.getAtrule(atruleName)) {
5773 return new SyntaxReferenceError$1('Unknown at-rule', '@' + atruleName);
5774 }
5775 },
5776 checkAtrulePrelude: function(atruleName, prelude) {
5777 let error = this.checkAtruleName(atruleName);
5778
5779 if (error) {
5780 return error;
5781 }
5782
5783 var atrule = this.getAtrule(atruleName);
5784
5785 if (!atrule.prelude && prelude) {
5786 return new SyntaxError('At-rule `@' + atruleName + '` should not contain a prelude');
5787 }
5788
5789 if (atrule.prelude && !prelude) {
5790 return new SyntaxError('At-rule `@' + atruleName + '` should contain a prelude');
5791 }
5792 },
5793 checkAtruleDescriptorName: function(atruleName, descriptorName) {
5794 let error = this.checkAtruleName(atruleName);
5795
5796 if (error) {
5797 return error;
5798 }
5799
5800 var atrule = this.getAtrule(atruleName);
5801 var descriptor = names.keyword(descriptorName);
5802
5803 if (!atrule.descriptors) {
5804 return new SyntaxError('At-rule `@' + atruleName + '` has no known descriptors');
5805 }
5806
5807 if (!atrule.descriptors[descriptor.name] &&
5808 !atrule.descriptors[descriptor.basename]) {
5809 return new SyntaxReferenceError$1('Unknown at-rule descriptor', descriptorName);
5810 }
5811 },
5812 checkPropertyName: function(propertyName) {
5813 var property = names.property(propertyName);
5814
5815 // don't match syntax for a custom property
5816 if (property.custom) {
5817 return new Error('Lexer matching doesn\'t applicable for custom properties');
5818 }
5819
5820 if (!this.getProperty(propertyName)) {
5821 return new SyntaxReferenceError$1('Unknown property', propertyName);
5822 }
5823 },
5824
5825 matchAtrulePrelude: function(atruleName, prelude) {
5826 var error = this.checkAtrulePrelude(atruleName, prelude);
5827
5828 if (error) {
5829 return buildMatchResult(null, error);
5830 }
5831
5832 if (!prelude) {
5833 return buildMatchResult(null, null);
5834 }
5835
5836 return matchSyntax(this, this.getAtrule(atruleName).prelude, prelude, false);
5837 },
5838 matchAtruleDescriptor: function(atruleName, descriptorName, value) {
5839 var error = this.checkAtruleDescriptorName(atruleName, descriptorName);
5840
5841 if (error) {
5842 return buildMatchResult(null, error);
5843 }
5844
5845 var atrule = this.getAtrule(atruleName);
5846 var descriptor = names.keyword(descriptorName);
5847
5848 return matchSyntax(this, atrule.descriptors[descriptor.name] || atrule.descriptors[descriptor.basename], value, false);
5849 },
5850 matchDeclaration: function(node) {
5851 if (node.type !== 'Declaration') {
5852 return buildMatchResult(null, new Error('Not a Declaration node'));
5853 }
5854
5855 return this.matchProperty(node.property, node.value);
5856 },
5857 matchProperty: function(propertyName, value) {
5858 var error = this.checkPropertyName(propertyName);
5859
5860 if (error) {
5861 return buildMatchResult(null, error);
5862 }
5863
5864 return matchSyntax(this, this.getProperty(propertyName), value, true);
5865 },
5866 matchType: function(typeName, value) {
5867 var typeSyntax = this.getType(typeName);
5868
5869 if (!typeSyntax) {
5870 return buildMatchResult(null, new SyntaxReferenceError$1('Unknown type', typeName));
5871 }
5872
5873 return matchSyntax(this, typeSyntax, value, false);
5874 },
5875 match: function(syntax, value) {
5876 if (typeof syntax !== 'string' && (!syntax || !syntax.type)) {
5877 return buildMatchResult(null, new SyntaxReferenceError$1('Bad syntax'));
5878 }
5879
5880 if (typeof syntax === 'string' || !syntax.match) {
5881 syntax = this.createDescriptor(syntax, 'Type', 'anonymous');
5882 }
5883
5884 return matchSyntax(this, syntax, value, false);
5885 },
5886
5887 findValueFragments: function(propertyName, value, type, name) {
5888 return search.matchFragments(this, value, this.matchProperty(propertyName, value), type, name);
5889 },
5890 findDeclarationValueFragments: function(declaration, type, name) {
5891 return search.matchFragments(this, declaration.value, this.matchDeclaration(declaration), type, name);
5892 },
5893 findAllFragments: function(ast, type, name) {
5894 var result = [];
5895
5896 this.syntax.walk(ast, {
5897 visit: 'Declaration',
5898 enter: function(declaration) {
5899 result.push.apply(result, this.findDeclarationValueFragments(declaration, type, name));
5900 }.bind(this)
5901 });
5902
5903 return result;
5904 },
5905
5906 getAtrule: function(atruleName, fallbackBasename = true) {
5907 var atrule = names.keyword(atruleName);
5908 var atruleEntry = atrule.vendor && fallbackBasename
5909 ? this.atrules[atrule.name] || this.atrules[atrule.basename]
5910 : this.atrules[atrule.name];
5911
5912 return atruleEntry || null;
5913 },
5914 getAtrulePrelude: function(atruleName, fallbackBasename = true) {
5915 const atrule = this.getAtrule(atruleName, fallbackBasename);
5916
5917 return atrule && atrule.prelude || null;
5918 },
5919 getAtruleDescriptor: function(atruleName, name) {
5920 return this.atrules.hasOwnProperty(atruleName) && this.atrules.declarators
5921 ? this.atrules[atruleName].declarators[name] || null
5922 : null;
5923 },
5924 getProperty: function(propertyName, fallbackBasename = true) {
5925 var property = names.property(propertyName);
5926 var propertyEntry = property.vendor && fallbackBasename
5927 ? this.properties[property.name] || this.properties[property.basename]
5928 : this.properties[property.name];
5929
5930 return propertyEntry || null;
5931 },
5932 getType: function(name) {
5933 return this.types.hasOwnProperty(name) ? this.types[name] : null;
5934 },
5935
5936 validate: function() {
5937 function validate(syntax, name, broken, descriptor) {
5938 if (broken.hasOwnProperty(name)) {
5939 return broken[name];
5940 }
5941
5942 broken[name] = false;
5943 if (descriptor.syntax !== null) {
5944 walk(descriptor.syntax, function(node) {
5945 if (node.type !== 'Type' && node.type !== 'Property') {
5946 return;
5947 }
5948
5949 var map = node.type === 'Type' ? syntax.types : syntax.properties;
5950 var brokenMap = node.type === 'Type' ? brokenTypes : brokenProperties;
5951
5952 if (!map.hasOwnProperty(node.name) || validate(syntax, node.name, brokenMap, map[node.name])) {
5953 broken[name] = true;
5954 }
5955 }, this);
5956 }
5957 }
5958
5959 var brokenTypes = {};
5960 var brokenProperties = {};
5961
5962 for (var key in this.types) {
5963 validate(this, key, brokenTypes, this.types[key]);
5964 }
5965
5966 for (var key in this.properties) {
5967 validate(this, key, brokenProperties, this.properties[key]);
5968 }
5969
5970 brokenTypes = Object.keys(brokenTypes).filter(function(name) {
5971 return brokenTypes[name];
5972 });
5973 brokenProperties = Object.keys(brokenProperties).filter(function(name) {
5974 return brokenProperties[name];
5975 });
5976
5977 if (brokenTypes.length || brokenProperties.length) {
5978 return {
5979 types: brokenTypes,
5980 properties: brokenProperties
5981 };
5982 }
5983
5984 return null;
5985 },
5986 dump: function(syntaxAsAst, pretty) {
5987 return {
5988 generic: this.generic,
5989 types: dumpMapSyntax(this.types, !pretty, syntaxAsAst),
5990 properties: dumpMapSyntax(this.properties, !pretty, syntaxAsAst),
5991 atrules: dumpAtruleMapSyntax(this.atrules, !pretty, syntaxAsAst)
5992 };
5993 },
5994 toString: function() {
5995 return JSON.stringify(this.dump());
5996 }
5997 };
5998
5999 var Lexer_1 = Lexer;
6000
6001 var definitionSyntax = {
6002 SyntaxError: _SyntaxError$1,
6003 parse: parse_1,
6004 generate: generate_1,
6005 walk: walk
6006 };
6007
6008 var isBOM$2 = tokenizer.isBOM;
6009
6010 var N$3 = 10;
6011 var F$2 = 12;
6012 var R$2 = 13;
6013
6014 function computeLinesAndColumns(host, source) {
6015 var sourceLength = source.length;
6016 var lines = adoptBuffer(host.lines, sourceLength); // +1
6017 var line = host.startLine;
6018 var columns = adoptBuffer(host.columns, sourceLength);
6019 var column = host.startColumn;
6020 var startOffset = source.length > 0 ? isBOM$2(source.charCodeAt(0)) : 0;
6021
6022 for (var i = startOffset; i < sourceLength; i++) { // -1
6023 var code = source.charCodeAt(i);
6024
6025 lines[i] = line;
6026 columns[i] = column++;
6027
6028 if (code === N$3 || code === R$2 || code === F$2) {
6029 if (code === R$2 && i + 1 < sourceLength && source.charCodeAt(i + 1) === N$3) {
6030 i++;
6031 lines[i] = line;
6032 columns[i] = column;
6033 }
6034
6035 line++;
6036 column = 1;
6037 }
6038 }
6039
6040 lines[i] = line;
6041 columns[i] = column;
6042
6043 host.lines = lines;
6044 host.columns = columns;
6045 }
6046
6047 var OffsetToLocation = function() {
6048 this.lines = null;
6049 this.columns = null;
6050 this.linesAndColumnsComputed = false;
6051 };
6052
6053 OffsetToLocation.prototype = {
6054 setSource: function(source, startOffset, startLine, startColumn) {
6055 this.source = source;
6056 this.startOffset = typeof startOffset === 'undefined' ? 0 : startOffset;
6057 this.startLine = typeof startLine === 'undefined' ? 1 : startLine;
6058 this.startColumn = typeof startColumn === 'undefined' ? 1 : startColumn;
6059 this.linesAndColumnsComputed = false;
6060 },
6061
6062 ensureLinesAndColumnsComputed: function() {
6063 if (!this.linesAndColumnsComputed) {
6064 computeLinesAndColumns(this, this.source);
6065 this.linesAndColumnsComputed = true;
6066 }
6067 },
6068 getLocation: function(offset, filename) {
6069 this.ensureLinesAndColumnsComputed();
6070
6071 return {
6072 source: filename,
6073 offset: this.startOffset + offset,
6074 line: this.lines[offset],
6075 column: this.columns[offset]
6076 };
6077 },
6078 getLocationRange: function(start, end, filename) {
6079 this.ensureLinesAndColumnsComputed();
6080
6081 return {
6082 source: filename,
6083 start: {
6084 offset: this.startOffset + start,
6085 line: this.lines[start],
6086 column: this.columns[start]
6087 },
6088 end: {
6089 offset: this.startOffset + end,
6090 line: this.lines[end],
6091 column: this.columns[end]
6092 }
6093 };
6094 }
6095 };
6096
6097 var OffsetToLocation_1 = OffsetToLocation;
6098
6099 var TYPE$7 = tokenizer.TYPE;
6100 var WHITESPACE$2 = TYPE$7.WhiteSpace;
6101 var COMMENT$2 = TYPE$7.Comment;
6102
6103 var sequence = function readSequence(recognizer) {
6104 var children = this.createList();
6105 var child = null;
6106 var context = {
6107 recognizer: recognizer,
6108 space: null,
6109 ignoreWS: false,
6110 ignoreWSAfter: false
6111 };
6112
6113 this.scanner.skipSC();
6114
6115 while (!this.scanner.eof) {
6116 switch (this.scanner.tokenType) {
6117 case COMMENT$2:
6118 this.scanner.next();
6119 continue;
6120
6121 case WHITESPACE$2:
6122 if (context.ignoreWS) {
6123 this.scanner.next();
6124 } else {
6125 context.space = this.WhiteSpace();
6126 }
6127 continue;
6128 }
6129
6130 child = recognizer.getNode.call(this, context);
6131
6132 if (child === undefined) {
6133 break;
6134 }
6135
6136 if (context.space !== null) {
6137 children.push(context.space);
6138 context.space = null;
6139 }
6140
6141 children.push(child);
6142
6143 if (context.ignoreWSAfter) {
6144 context.ignoreWSAfter = false;
6145 context.ignoreWS = true;
6146 } else {
6147 context.ignoreWS = false;
6148 }
6149 }
6150
6151 return children;
6152 };
6153
6154 var { findWhiteSpaceStart: findWhiteSpaceStart$1, cmpStr: cmpStr$4 } = utils;
6155
6156 var noop$2 = function() {};
6157
6158 var TYPE$8 = _const.TYPE;
6159 var NAME$2 = _const.NAME;
6160 var WHITESPACE$3 = TYPE$8.WhiteSpace;
6161 var COMMENT$3 = TYPE$8.Comment;
6162 var IDENT$2 = TYPE$8.Ident;
6163 var FUNCTION = TYPE$8.Function;
6164 var URL = TYPE$8.Url;
6165 var HASH = TYPE$8.Hash;
6166 var PERCENTAGE = TYPE$8.Percentage;
6167 var NUMBER$2 = TYPE$8.Number;
6168 var NUMBERSIGN$1 = 0x0023; // U+0023 NUMBER SIGN (#)
6169 var NULL = 0;
6170
6171 function createParseContext(name) {
6172 return function() {
6173 return this[name]();
6174 };
6175 }
6176
6177 function processConfig(config) {
6178 var parserConfig = {
6179 context: {},
6180 scope: {},
6181 atrule: {},
6182 pseudo: {}
6183 };
6184
6185 if (config.parseContext) {
6186 for (var name in config.parseContext) {
6187 switch (typeof config.parseContext[name]) {
6188 case 'function':
6189 parserConfig.context[name] = config.parseContext[name];
6190 break;
6191
6192 case 'string':
6193 parserConfig.context[name] = createParseContext(config.parseContext[name]);
6194 break;
6195 }
6196 }
6197 }
6198
6199 if (config.scope) {
6200 for (var name in config.scope) {
6201 parserConfig.scope[name] = config.scope[name];
6202 }
6203 }
6204
6205 if (config.atrule) {
6206 for (var name in config.atrule) {
6207 var atrule = config.atrule[name];
6208
6209 if (atrule.parse) {
6210 parserConfig.atrule[name] = atrule.parse;
6211 }
6212 }
6213 }
6214
6215 if (config.pseudo) {
6216 for (var name in config.pseudo) {
6217 var pseudo = config.pseudo[name];
6218
6219 if (pseudo.parse) {
6220 parserConfig.pseudo[name] = pseudo.parse;
6221 }
6222 }
6223 }
6224
6225 if (config.node) {
6226 for (var name in config.node) {
6227 parserConfig[name] = config.node[name].parse;
6228 }
6229 }
6230
6231 return parserConfig;
6232 }
6233
6234 var create = function createParser(config) {
6235 var parser = {
6236 scanner: new TokenStream_1(),
6237 locationMap: new OffsetToLocation_1(),
6238
6239 filename: '<unknown>',
6240 needPositions: false,
6241 onParseError: noop$2,
6242 onParseErrorThrow: false,
6243 parseAtrulePrelude: true,
6244 parseRulePrelude: true,
6245 parseValue: true,
6246 parseCustomProperty: false,
6247
6248 readSequence: sequence,
6249
6250 createList: function() {
6251 return new List_1();
6252 },
6253 createSingleNodeList: function(node) {
6254 return new List_1().appendData(node);
6255 },
6256 getFirstListNode: function(list) {
6257 return list && list.first();
6258 },
6259 getLastListNode: function(list) {
6260 return list.last();
6261 },
6262
6263 parseWithFallback: function(consumer, fallback) {
6264 var startToken = this.scanner.tokenIndex;
6265
6266 try {
6267 return consumer.call(this);
6268 } catch (e) {
6269 if (this.onParseErrorThrow) {
6270 throw e;
6271 }
6272
6273 var fallbackNode = fallback.call(this, startToken);
6274
6275 this.onParseErrorThrow = true;
6276 this.onParseError(e, fallbackNode);
6277 this.onParseErrorThrow = false;
6278
6279 return fallbackNode;
6280 }
6281 },
6282
6283 lookupNonWSType: function(offset) {
6284 do {
6285 var type = this.scanner.lookupType(offset++);
6286 if (type !== WHITESPACE$3) {
6287 return type;
6288 }
6289 } while (type !== NULL);
6290
6291 return NULL;
6292 },
6293
6294 eat: function(tokenType) {
6295 if (this.scanner.tokenType !== tokenType) {
6296 var offset = this.scanner.tokenStart;
6297 var message = NAME$2[tokenType] + ' is expected';
6298
6299 // tweak message and offset
6300 switch (tokenType) {
6301 case IDENT$2:
6302 // when identifier is expected but there is a function or url
6303 if (this.scanner.tokenType === FUNCTION || this.scanner.tokenType === URL) {
6304 offset = this.scanner.tokenEnd - 1;
6305 message = 'Identifier is expected but function found';
6306 } else {
6307 message = 'Identifier is expected';
6308 }
6309 break;
6310
6311 case HASH:
6312 if (this.scanner.isDelim(NUMBERSIGN$1)) {
6313 this.scanner.next();
6314 offset++;
6315 message = 'Name is expected';
6316 }
6317 break;
6318
6319 case PERCENTAGE:
6320 if (this.scanner.tokenType === NUMBER$2) {
6321 offset = this.scanner.tokenEnd;
6322 message = 'Percent sign is expected';
6323 }
6324 break;
6325
6326 default:
6327 // when test type is part of another token show error for current position + 1
6328 // e.g. eat(HYPHENMINUS) will fail on "-foo", but pointing on "-" is odd
6329 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) === tokenType) {
6330 offset = offset + 1;
6331 }
6332 }
6333
6334 this.error(message, offset);
6335 }
6336
6337 this.scanner.next();
6338 },
6339
6340 consume: function(tokenType) {
6341 var value = this.scanner.getTokenValue();
6342
6343 this.eat(tokenType);
6344
6345 return value;
6346 },
6347 consumeFunctionName: function() {
6348 var name = this.scanner.source.substring(this.scanner.tokenStart, this.scanner.tokenEnd - 1);
6349
6350 this.eat(FUNCTION);
6351
6352 return name;
6353 },
6354
6355 getLocation: function(start, end) {
6356 if (this.needPositions) {
6357 return this.locationMap.getLocationRange(
6358 start,
6359 end,
6360 this.filename
6361 );
6362 }
6363
6364 return null;
6365 },
6366 getLocationFromList: function(list) {
6367 if (this.needPositions) {
6368 var head = this.getFirstListNode(list);
6369 var tail = this.getLastListNode(list);
6370 return this.locationMap.getLocationRange(
6371 head !== null ? head.loc.start.offset - this.locationMap.startOffset : this.scanner.tokenStart,
6372 tail !== null ? tail.loc.end.offset - this.locationMap.startOffset : this.scanner.tokenStart,
6373 this.filename
6374 );
6375 }
6376
6377 return null;
6378 },
6379
6380 error: function(message, offset) {
6381 var location = typeof offset !== 'undefined' && offset < this.scanner.source.length
6382 ? this.locationMap.getLocation(offset)
6383 : this.scanner.eof
6384 ? this.locationMap.getLocation(findWhiteSpaceStart$1(this.scanner.source, this.scanner.source.length - 1))
6385 : this.locationMap.getLocation(this.scanner.tokenStart);
6386
6387 throw new _SyntaxError(
6388 message || 'Unexpected input',
6389 this.scanner.source,
6390 location.offset,
6391 location.line,
6392 location.column
6393 );
6394 }
6395 };
6396
6397 config = processConfig(config || {});
6398 for (var key in config) {
6399 parser[key] = config[key];
6400 }
6401
6402 return function(source, options) {
6403 options = options || {};
6404
6405 var context = options.context || 'default';
6406 var onComment = options.onComment;
6407 var ast;
6408
6409 tokenizer(source, parser.scanner);
6410 parser.locationMap.setSource(
6411 source,
6412 options.offset,
6413 options.line,
6414 options.column
6415 );
6416
6417 parser.filename = options.filename || '<unknown>';
6418 parser.needPositions = Boolean(options.positions);
6419 parser.onParseError = typeof options.onParseError === 'function' ? options.onParseError : noop$2;
6420 parser.onParseErrorThrow = false;
6421 parser.parseAtrulePrelude = 'parseAtrulePrelude' in options ? Boolean(options.parseAtrulePrelude) : true;
6422 parser.parseRulePrelude = 'parseRulePrelude' in options ? Boolean(options.parseRulePrelude) : true;
6423 parser.parseValue = 'parseValue' in options ? Boolean(options.parseValue) : true;
6424 parser.parseCustomProperty = 'parseCustomProperty' in options ? Boolean(options.parseCustomProperty) : false;
6425
6426 if (!parser.context.hasOwnProperty(context)) {
6427 throw new Error('Unknown context `' + context + '`');
6428 }
6429
6430 if (typeof onComment === 'function') {
6431 parser.scanner.forEachToken((type, start, end) => {
6432 if (type === COMMENT$3) {
6433 const loc = parser.getLocation(start, end);
6434 const value = cmpStr$4(source, end - 2, end, '*/')
6435 ? source.slice(start + 2, end - 2)
6436 : source.slice(start + 2, end);
6437
6438 onComment(value, loc);
6439 }
6440 });
6441 }
6442
6443 ast = parser.context[context].call(parser, options);
6444
6445 if (!parser.scanner.eof) {
6446 parser.error();
6447 }
6448
6449 return ast;
6450 };
6451 };
6452
6453 /* -*- Mode: js; js-indent-level: 2; -*- */
6454 /*
6455 * Copyright 2011 Mozilla Foundation and contributors
6456 * Licensed under the New BSD license. See LICENSE or:
6457 * http://opensource.org/licenses/BSD-3-Clause
6458 */
6459
6460 var intToCharMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'.split('');
6461
6462 /**
6463 * Encode an integer in the range of 0 to 63 to a single base 64 digit.
6464 */
6465 var encode = function (number) {
6466 if (0 <= number && number < intToCharMap.length) {
6467 return intToCharMap[number];
6468 }
6469 throw new TypeError("Must be between 0 and 63: " + number);
6470 };
6471
6472 /**
6473 * Decode a single base 64 character code digit to an integer. Returns -1 on
6474 * failure.
6475 */
6476 var decode = function (charCode) {
6477 var bigA = 65; // 'A'
6478 var bigZ = 90; // 'Z'
6479
6480 var littleA = 97; // 'a'
6481 var littleZ = 122; // 'z'
6482
6483 var zero = 48; // '0'
6484 var nine = 57; // '9'
6485
6486 var plus = 43; // '+'
6487 var slash = 47; // '/'
6488
6489 var littleOffset = 26;
6490 var numberOffset = 52;
6491
6492 // 0 - 25: ABCDEFGHIJKLMNOPQRSTUVWXYZ
6493 if (bigA <= charCode && charCode <= bigZ) {
6494 return (charCode - bigA);
6495 }
6496
6497 // 26 - 51: abcdefghijklmnopqrstuvwxyz
6498 if (littleA <= charCode && charCode <= littleZ) {
6499 return (charCode - littleA + littleOffset);
6500 }
6501
6502 // 52 - 61: 0123456789
6503 if (zero <= charCode && charCode <= nine) {
6504 return (charCode - zero + numberOffset);
6505 }
6506
6507 // 62: +
6508 if (charCode == plus) {
6509 return 62;
6510 }
6511
6512 // 63: /
6513 if (charCode == slash) {
6514 return 63;
6515 }
6516
6517 // Invalid base64 digit.
6518 return -1;
6519 };
6520
6521 var base64 = {
6522 encode: encode,
6523 decode: decode
6524 };
6525
6526 /* -*- Mode: js; js-indent-level: 2; -*- */
6527 /*
6528 * Copyright 2011 Mozilla Foundation and contributors
6529 * Licensed under the New BSD license. See LICENSE or:
6530 * http://opensource.org/licenses/BSD-3-Clause
6531 *
6532 * Based on the Base 64 VLQ implementation in Closure Compiler:
6533 * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java
6534 *
6535 * Copyright 2011 The Closure Compiler Authors. All rights reserved.
6536 * Redistribution and use in source and binary forms, with or without
6537 * modification, are permitted provided that the following conditions are
6538 * met:
6539 *
6540 * * Redistributions of source code must retain the above copyright
6541 * notice, this list of conditions and the following disclaimer.
6542 * * Redistributions in binary form must reproduce the above
6543 * copyright notice, this list of conditions and the following
6544 * disclaimer in the documentation and/or other materials provided
6545 * with the distribution.
6546 * * Neither the name of Google Inc. nor the names of its
6547 * contributors may be used to endorse or promote products derived
6548 * from this software without specific prior written permission.
6549 *
6550 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
6551 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
6552 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
6553 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
6554 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
6555 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
6556 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
6557 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
6558 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
6559 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
6560 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
6561 */
6562
6563
6564
6565 // A single base 64 digit can contain 6 bits of data. For the base 64 variable
6566 // length quantities we use in the source map spec, the first bit is the sign,
6567 // the next four bits are the actual value, and the 6th bit is the
6568 // continuation bit. The continuation bit tells us whether there are more
6569 // digits in this value following this digit.
6570 //
6571 // Continuation
6572 // | Sign
6573 // | |
6574 // V V
6575 // 101011
6576
6577 var VLQ_BASE_SHIFT = 5;
6578
6579 // binary: 100000
6580 var VLQ_BASE = 1 << VLQ_BASE_SHIFT;
6581
6582 // binary: 011111
6583 var VLQ_BASE_MASK = VLQ_BASE - 1;
6584
6585 // binary: 100000
6586 var VLQ_CONTINUATION_BIT = VLQ_BASE;
6587
6588 /**
6589 * Converts from a two-complement value to a value where the sign bit is
6590 * placed in the least significant bit. For example, as decimals:
6591 * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary)
6592 * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary)
6593 */
6594 function toVLQSigned(aValue) {
6595 return aValue < 0
6596 ? ((-aValue) << 1) + 1
6597 : (aValue << 1) + 0;
6598 }
6599
6600 /**
6601 * Converts to a two-complement value from a value where the sign bit is
6602 * placed in the least significant bit. For example, as decimals:
6603 * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1
6604 * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2
6605 */
6606 function fromVLQSigned(aValue) {
6607 var isNegative = (aValue & 1) === 1;
6608 var shifted = aValue >> 1;
6609 return isNegative
6610 ? -shifted
6611 : shifted;
6612 }
6613
6614 /**
6615 * Returns the base 64 VLQ encoded value.
6616 */
6617 var encode$1 = function base64VLQ_encode(aValue) {
6618 var encoded = "";
6619 var digit;
6620
6621 var vlq = toVLQSigned(aValue);
6622
6623 do {
6624 digit = vlq & VLQ_BASE_MASK;
6625 vlq >>>= VLQ_BASE_SHIFT;
6626 if (vlq > 0) {
6627 // There are still more digits in this value, so we must make sure the
6628 // continuation bit is marked.
6629 digit |= VLQ_CONTINUATION_BIT;
6630 }
6631 encoded += base64.encode(digit);
6632 } while (vlq > 0);
6633
6634 return encoded;
6635 };
6636
6637 /**
6638 * Decodes the next base 64 VLQ value from the given string and returns the
6639 * value and the rest of the string via the out parameter.
6640 */
6641 var decode$1 = function base64VLQ_decode(aStr, aIndex, aOutParam) {
6642 var strLen = aStr.length;
6643 var result = 0;
6644 var shift = 0;
6645 var continuation, digit;
6646
6647 do {
6648 if (aIndex >= strLen) {
6649 throw new Error("Expected more digits in base 64 VLQ value.");
6650 }
6651
6652 digit = base64.decode(aStr.charCodeAt(aIndex++));
6653 if (digit === -1) {
6654 throw new Error("Invalid base64 digit: " + aStr.charAt(aIndex - 1));
6655 }
6656
6657 continuation = !!(digit & VLQ_CONTINUATION_BIT);
6658 digit &= VLQ_BASE_MASK;
6659 result = result + (digit << shift);
6660 shift += VLQ_BASE_SHIFT;
6661 } while (continuation);
6662
6663 aOutParam.value = fromVLQSigned(result);
6664 aOutParam.rest = aIndex;
6665 };
6666
6667 var base64Vlq = {
6668 encode: encode$1,
6669 decode: decode$1
6670 };
6671
6672 function createCommonjsModule(fn, module) {
6673 return module = { exports: {} }, fn(module, module.exports), module.exports;
6674 }
6675
6676 function getCjsExportFromNamespace (n) {
6677 return n && n['default'] || n;
6678 }
6679
6680 var util = createCommonjsModule(function (module, exports) {
6681 /* -*- Mode: js; js-indent-level: 2; -*- */
6682 /*
6683 * Copyright 2011 Mozilla Foundation and contributors
6684 * Licensed under the New BSD license. See LICENSE or:
6685 * http://opensource.org/licenses/BSD-3-Clause
6686 */
6687
6688 /**
6689 * This is a helper function for getting values from parameter/options
6690 * objects.
6691 *
6692 * @param args The object we are extracting values from
6693 * @param name The name of the property we are getting.
6694 * @param defaultValue An optional value to return if the property is missing
6695 * from the object. If this is not specified and the property is missing, an
6696 * error will be thrown.
6697 */
6698 function getArg(aArgs, aName, aDefaultValue) {
6699 if (aName in aArgs) {
6700 return aArgs[aName];
6701 } else if (arguments.length === 3) {
6702 return aDefaultValue;
6703 } else {
6704 throw new Error('"' + aName + '" is a required argument.');
6705 }
6706 }
6707 exports.getArg = getArg;
6708
6709 var urlRegexp = /^(?:([\w+\-.]+):)?\/\/(?:(\w+:\w+)@)?([\w.-]*)(?::(\d+))?(.*)$/;
6710 var dataUrlRegexp = /^data:.+\,.+$/;
6711
6712 function urlParse(aUrl) {
6713 var match = aUrl.match(urlRegexp);
6714 if (!match) {
6715 return null;
6716 }
6717 return {
6718 scheme: match[1],
6719 auth: match[2],
6720 host: match[3],
6721 port: match[4],
6722 path: match[5]
6723 };
6724 }
6725 exports.urlParse = urlParse;
6726
6727 function urlGenerate(aParsedUrl) {
6728 var url = '';
6729 if (aParsedUrl.scheme) {
6730 url += aParsedUrl.scheme + ':';
6731 }
6732 url += '//';
6733 if (aParsedUrl.auth) {
6734 url += aParsedUrl.auth + '@';
6735 }
6736 if (aParsedUrl.host) {
6737 url += aParsedUrl.host;
6738 }
6739 if (aParsedUrl.port) {
6740 url += ":" + aParsedUrl.port;
6741 }
6742 if (aParsedUrl.path) {
6743 url += aParsedUrl.path;
6744 }
6745 return url;
6746 }
6747 exports.urlGenerate = urlGenerate;
6748
6749 /**
6750 * Normalizes a path, or the path portion of a URL:
6751 *
6752 * - Replaces consecutive slashes with one slash.
6753 * - Removes unnecessary '.' parts.
6754 * - Removes unnecessary '<dir>/..' parts.
6755 *
6756 * Based on code in the Node.js 'path' core module.
6757 *
6758 * @param aPath The path or url to normalize.
6759 */
6760 function normalize(aPath) {
6761 var path = aPath;
6762 var url = urlParse(aPath);
6763 if (url) {
6764 if (!url.path) {
6765 return aPath;
6766 }
6767 path = url.path;
6768 }
6769 var isAbsolute = exports.isAbsolute(path);
6770
6771 var parts = path.split(/\/+/);
6772 for (var part, up = 0, i = parts.length - 1; i >= 0; i--) {
6773 part = parts[i];
6774 if (part === '.') {
6775 parts.splice(i, 1);
6776 } else if (part === '..') {
6777 up++;
6778 } else if (up > 0) {
6779 if (part === '') {
6780 // The first part is blank if the path is absolute. Trying to go
6781 // above the root is a no-op. Therefore we can remove all '..' parts
6782 // directly after the root.
6783 parts.splice(i + 1, up);
6784 up = 0;
6785 } else {
6786 parts.splice(i, 2);
6787 up--;
6788 }
6789 }
6790 }
6791 path = parts.join('/');
6792
6793 if (path === '') {
6794 path = isAbsolute ? '/' : '.';
6795 }
6796
6797 if (url) {
6798 url.path = path;
6799 return urlGenerate(url);
6800 }
6801 return path;
6802 }
6803 exports.normalize = normalize;
6804
6805 /**
6806 * Joins two paths/URLs.
6807 *
6808 * @param aRoot The root path or URL.
6809 * @param aPath The path or URL to be joined with the root.
6810 *
6811 * - If aPath is a URL or a data URI, aPath is returned, unless aPath is a
6812 * scheme-relative URL: Then the scheme of aRoot, if any, is prepended
6813 * first.
6814 * - Otherwise aPath is a path. If aRoot is a URL, then its path portion
6815 * is updated with the result and aRoot is returned. Otherwise the result
6816 * is returned.
6817 * - If aPath is absolute, the result is aPath.
6818 * - Otherwise the two paths are joined with a slash.
6819 * - Joining for example 'http://' and 'www.example.com' is also supported.
6820 */
6821 function join(aRoot, aPath) {
6822 if (aRoot === "") {
6823 aRoot = ".";
6824 }
6825 if (aPath === "") {
6826 aPath = ".";
6827 }
6828 var aPathUrl = urlParse(aPath);
6829 var aRootUrl = urlParse(aRoot);
6830 if (aRootUrl) {
6831 aRoot = aRootUrl.path || '/';
6832 }
6833
6834 // `join(foo, '//www.example.org')`
6835 if (aPathUrl && !aPathUrl.scheme) {
6836 if (aRootUrl) {
6837 aPathUrl.scheme = aRootUrl.scheme;
6838 }
6839 return urlGenerate(aPathUrl);
6840 }
6841
6842 if (aPathUrl || aPath.match(dataUrlRegexp)) {
6843 return aPath;
6844 }
6845
6846 // `join('http://', 'www.example.com')`
6847 if (aRootUrl && !aRootUrl.host && !aRootUrl.path) {
6848 aRootUrl.host = aPath;
6849 return urlGenerate(aRootUrl);
6850 }
6851
6852 var joined = aPath.charAt(0) === '/'
6853 ? aPath
6854 : normalize(aRoot.replace(/\/+$/, '') + '/' + aPath);
6855
6856 if (aRootUrl) {
6857 aRootUrl.path = joined;
6858 return urlGenerate(aRootUrl);
6859 }
6860 return joined;
6861 }
6862 exports.join = join;
6863
6864 exports.isAbsolute = function (aPath) {
6865 return aPath.charAt(0) === '/' || urlRegexp.test(aPath);
6866 };
6867
6868 /**
6869 * Make a path relative to a URL or another path.
6870 *
6871 * @param aRoot The root path or URL.
6872 * @param aPath The path or URL to be made relative to aRoot.
6873 */
6874 function relative(aRoot, aPath) {
6875 if (aRoot === "") {
6876 aRoot = ".";
6877 }
6878
6879 aRoot = aRoot.replace(/\/$/, '');
6880
6881 // It is possible for the path to be above the root. In this case, simply
6882 // checking whether the root is a prefix of the path won't work. Instead, we
6883 // need to remove components from the root one by one, until either we find
6884 // a prefix that fits, or we run out of components to remove.
6885 var level = 0;
6886 while (aPath.indexOf(aRoot + '/') !== 0) {
6887 var index = aRoot.lastIndexOf("/");
6888 if (index < 0) {
6889 return aPath;
6890 }
6891
6892 // If the only part of the root that is left is the scheme (i.e. http://,
6893 // file:///, etc.), one or more slashes (/), or simply nothing at all, we
6894 // have exhausted all components, so the path is not relative to the root.
6895 aRoot = aRoot.slice(0, index);
6896 if (aRoot.match(/^([^\/]+:\/)?\/*$/)) {
6897 return aPath;
6898 }
6899
6900 ++level;
6901 }
6902
6903 // Make sure we add a "../" for each component we removed from the root.
6904 return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
6905 }
6906 exports.relative = relative;
6907
6908 var supportsNullProto = (function () {
6909 var obj = Object.create(null);
6910 return !('__proto__' in obj);
6911 }());
6912
6913 function identity (s) {
6914 return s;
6915 }
6916
6917 /**
6918 * Because behavior goes wacky when you set `__proto__` on objects, we
6919 * have to prefix all the strings in our set with an arbitrary character.
6920 *
6921 * See https://github.com/mozilla/source-map/pull/31 and
6922 * https://github.com/mozilla/source-map/issues/30
6923 *
6924 * @param String aStr
6925 */
6926 function toSetString(aStr) {
6927 if (isProtoString(aStr)) {
6928 return '$' + aStr;
6929 }
6930
6931 return aStr;
6932 }
6933 exports.toSetString = supportsNullProto ? identity : toSetString;
6934
6935 function fromSetString(aStr) {
6936 if (isProtoString(aStr)) {
6937 return aStr.slice(1);
6938 }
6939
6940 return aStr;
6941 }
6942 exports.fromSetString = supportsNullProto ? identity : fromSetString;
6943
6944 function isProtoString(s) {
6945 if (!s) {
6946 return false;
6947 }
6948
6949 var length = s.length;
6950
6951 if (length < 9 /* "__proto__".length */) {
6952 return false;
6953 }
6954
6955 if (s.charCodeAt(length - 1) !== 95 /* '_' */ ||
6956 s.charCodeAt(length - 2) !== 95 /* '_' */ ||
6957 s.charCodeAt(length - 3) !== 111 /* 'o' */ ||
6958 s.charCodeAt(length - 4) !== 116 /* 't' */ ||
6959 s.charCodeAt(length - 5) !== 111 /* 'o' */ ||
6960 s.charCodeAt(length - 6) !== 114 /* 'r' */ ||
6961 s.charCodeAt(length - 7) !== 112 /* 'p' */ ||
6962 s.charCodeAt(length - 8) !== 95 /* '_' */ ||
6963 s.charCodeAt(length - 9) !== 95 /* '_' */) {
6964 return false;
6965 }
6966
6967 for (var i = length - 10; i >= 0; i--) {
6968 if (s.charCodeAt(i) !== 36 /* '$' */) {
6969 return false;
6970 }
6971 }
6972
6973 return true;
6974 }
6975
6976 /**
6977 * Comparator between two mappings where the original positions are compared.
6978 *
6979 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
6980 * mappings with the same original source/line/column, but different generated
6981 * line and column the same. Useful when searching for a mapping with a
6982 * stubbed out mapping.
6983 */
6984 function compareByOriginalPositions(mappingA, mappingB, onlyCompareOriginal) {
6985 var cmp = strcmp(mappingA.source, mappingB.source);
6986 if (cmp !== 0) {
6987 return cmp;
6988 }
6989
6990 cmp = mappingA.originalLine - mappingB.originalLine;
6991 if (cmp !== 0) {
6992 return cmp;
6993 }
6994
6995 cmp = mappingA.originalColumn - mappingB.originalColumn;
6996 if (cmp !== 0 || onlyCompareOriginal) {
6997 return cmp;
6998 }
6999
7000 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
7001 if (cmp !== 0) {
7002 return cmp;
7003 }
7004
7005 cmp = mappingA.generatedLine - mappingB.generatedLine;
7006 if (cmp !== 0) {
7007 return cmp;
7008 }
7009
7010 return strcmp(mappingA.name, mappingB.name);
7011 }
7012 exports.compareByOriginalPositions = compareByOriginalPositions;
7013
7014 /**
7015 * Comparator between two mappings with deflated source and name indices where
7016 * the generated positions are compared.
7017 *
7018 * Optionally pass in `true` as `onlyCompareGenerated` to consider two
7019 * mappings with the same generated line and column, but different
7020 * source/name/original line and column the same. Useful when searching for a
7021 * mapping with a stubbed out mapping.
7022 */
7023 function compareByGeneratedPositionsDeflated(mappingA, mappingB, onlyCompareGenerated) {
7024 var cmp = mappingA.generatedLine - mappingB.generatedLine;
7025 if (cmp !== 0) {
7026 return cmp;
7027 }
7028
7029 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
7030 if (cmp !== 0 || onlyCompareGenerated) {
7031 return cmp;
7032 }
7033
7034 cmp = strcmp(mappingA.source, mappingB.source);
7035 if (cmp !== 0) {
7036 return cmp;
7037 }
7038
7039 cmp = mappingA.originalLine - mappingB.originalLine;
7040 if (cmp !== 0) {
7041 return cmp;
7042 }
7043
7044 cmp = mappingA.originalColumn - mappingB.originalColumn;
7045 if (cmp !== 0) {
7046 return cmp;
7047 }
7048
7049 return strcmp(mappingA.name, mappingB.name);
7050 }
7051 exports.compareByGeneratedPositionsDeflated = compareByGeneratedPositionsDeflated;
7052
7053 function strcmp(aStr1, aStr2) {
7054 if (aStr1 === aStr2) {
7055 return 0;
7056 }
7057
7058 if (aStr1 === null) {
7059 return 1; // aStr2 !== null
7060 }
7061
7062 if (aStr2 === null) {
7063 return -1; // aStr1 !== null
7064 }
7065
7066 if (aStr1 > aStr2) {
7067 return 1;
7068 }
7069
7070 return -1;
7071 }
7072
7073 /**
7074 * Comparator between two mappings with inflated source and name strings where
7075 * the generated positions are compared.
7076 */
7077 function compareByGeneratedPositionsInflated(mappingA, mappingB) {
7078 var cmp = mappingA.generatedLine - mappingB.generatedLine;
7079 if (cmp !== 0) {
7080 return cmp;
7081 }
7082
7083 cmp = mappingA.generatedColumn - mappingB.generatedColumn;
7084 if (cmp !== 0) {
7085 return cmp;
7086 }
7087
7088 cmp = strcmp(mappingA.source, mappingB.source);
7089 if (cmp !== 0) {
7090 return cmp;
7091 }
7092
7093 cmp = mappingA.originalLine - mappingB.originalLine;
7094 if (cmp !== 0) {
7095 return cmp;
7096 }
7097
7098 cmp = mappingA.originalColumn - mappingB.originalColumn;
7099 if (cmp !== 0) {
7100 return cmp;
7101 }
7102
7103 return strcmp(mappingA.name, mappingB.name);
7104 }
7105 exports.compareByGeneratedPositionsInflated = compareByGeneratedPositionsInflated;
7106
7107 /**
7108 * Strip any JSON XSSI avoidance prefix from the string (as documented
7109 * in the source maps specification), and then parse the string as
7110 * JSON.
7111 */
7112 function parseSourceMapInput(str) {
7113 return JSON.parse(str.replace(/^\)]}'[^\n]*\n/, ''));
7114 }
7115 exports.parseSourceMapInput = parseSourceMapInput;
7116
7117 /**
7118 * Compute the URL of a source given the the source root, the source's
7119 * URL, and the source map's URL.
7120 */
7121 function computeSourceURL(sourceRoot, sourceURL, sourceMapURL) {
7122 sourceURL = sourceURL || '';
7123
7124 if (sourceRoot) {
7125 // This follows what Chrome does.
7126 if (sourceRoot[sourceRoot.length - 1] !== '/' && sourceURL[0] !== '/') {
7127 sourceRoot += '/';
7128 }
7129 // The spec says:
7130 // Line 4: An optional source root, useful for relocating source
7131 // files on a server or removing repeated values in the
7132 // “sources” entry. This value is prepended to the individual
7133 // entries in the “source” field.
7134 sourceURL = sourceRoot + sourceURL;
7135 }
7136
7137 // Historically, SourceMapConsumer did not take the sourceMapURL as
7138 // a parameter. This mode is still somewhat supported, which is why
7139 // this code block is conditional. However, it's preferable to pass
7140 // the source map URL to SourceMapConsumer, so that this function
7141 // can implement the source URL resolution algorithm as outlined in
7142 // the spec. This block is basically the equivalent of:
7143 // new URL(sourceURL, sourceMapURL).toString()
7144 // ... except it avoids using URL, which wasn't available in the
7145 // older releases of node still supported by this library.
7146 //
7147 // The spec says:
7148 // If the sources are not absolute URLs after prepending of the
7149 // “sourceRoot”, the sources are resolved relative to the
7150 // SourceMap (like resolving script src in a html document).
7151 if (sourceMapURL) {
7152 var parsed = urlParse(sourceMapURL);
7153 if (!parsed) {
7154 throw new Error("sourceMapURL could not be parsed");
7155 }
7156 if (parsed.path) {
7157 // Strip the last path component, but keep the "/".
7158 var index = parsed.path.lastIndexOf('/');
7159 if (index >= 0) {
7160 parsed.path = parsed.path.substring(0, index + 1);
7161 }
7162 }
7163 sourceURL = join(urlGenerate(parsed), sourceURL);
7164 }
7165
7166 return normalize(sourceURL);
7167 }
7168 exports.computeSourceURL = computeSourceURL;
7169 });
7170 var util_1 = util.getArg;
7171 var util_2 = util.urlParse;
7172 var util_3 = util.urlGenerate;
7173 var util_4 = util.normalize;
7174 var util_5 = util.join;
7175 var util_6 = util.isAbsolute;
7176 var util_7 = util.relative;
7177 var util_8 = util.toSetString;
7178 var util_9 = util.fromSetString;
7179 var util_10 = util.compareByOriginalPositions;
7180 var util_11 = util.compareByGeneratedPositionsDeflated;
7181 var util_12 = util.compareByGeneratedPositionsInflated;
7182 var util_13 = util.parseSourceMapInput;
7183 var util_14 = util.computeSourceURL;
7184
7185 /* -*- Mode: js; js-indent-level: 2; -*- */
7186 /*
7187 * Copyright 2011 Mozilla Foundation and contributors
7188 * Licensed under the New BSD license. See LICENSE or:
7189 * http://opensource.org/licenses/BSD-3-Clause
7190 */
7191
7192
7193 var has = Object.prototype.hasOwnProperty;
7194 var hasNativeMap = typeof Map !== "undefined";
7195
7196 /**
7197 * A data structure which is a combination of an array and a set. Adding a new
7198 * member is O(1), testing for membership is O(1), and finding the index of an
7199 * element is O(1). Removing elements from the set is not supported. Only
7200 * strings are supported for membership.
7201 */
7202 function ArraySet() {
7203 this._array = [];
7204 this._set = hasNativeMap ? new Map() : Object.create(null);
7205 }
7206
7207 /**
7208 * Static method for creating ArraySet instances from an existing array.
7209 */
7210 ArraySet.fromArray = function ArraySet_fromArray(aArray, aAllowDuplicates) {
7211 var set = new ArraySet();
7212 for (var i = 0, len = aArray.length; i < len; i++) {
7213 set.add(aArray[i], aAllowDuplicates);
7214 }
7215 return set;
7216 };
7217
7218 /**
7219 * Return how many unique items are in this ArraySet. If duplicates have been
7220 * added, than those do not count towards the size.
7221 *
7222 * @returns Number
7223 */
7224 ArraySet.prototype.size = function ArraySet_size() {
7225 return hasNativeMap ? this._set.size : Object.getOwnPropertyNames(this._set).length;
7226 };
7227
7228 /**
7229 * Add the given string to this set.
7230 *
7231 * @param String aStr
7232 */
7233 ArraySet.prototype.add = function ArraySet_add(aStr, aAllowDuplicates) {
7234 var sStr = hasNativeMap ? aStr : util.toSetString(aStr);
7235 var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);
7236 var idx = this._array.length;
7237 if (!isDuplicate || aAllowDuplicates) {
7238 this._array.push(aStr);
7239 }
7240 if (!isDuplicate) {
7241 if (hasNativeMap) {
7242 this._set.set(aStr, idx);
7243 } else {
7244 this._set[sStr] = idx;
7245 }
7246 }
7247 };
7248
7249 /**
7250 * Is the given string a member of this set?
7251 *
7252 * @param String aStr
7253 */
7254 ArraySet.prototype.has = function ArraySet_has(aStr) {
7255 if (hasNativeMap) {
7256 return this._set.has(aStr);
7257 } else {
7258 var sStr = util.toSetString(aStr);
7259 return has.call(this._set, sStr);
7260 }
7261 };
7262
7263 /**
7264 * What is the index of the given string in the array?
7265 *
7266 * @param String aStr
7267 */
7268 ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) {
7269 if (hasNativeMap) {
7270 var idx = this._set.get(aStr);
7271 if (idx >= 0) {
7272 return idx;
7273 }
7274 } else {
7275 var sStr = util.toSetString(aStr);
7276 if (has.call(this._set, sStr)) {
7277 return this._set[sStr];
7278 }
7279 }
7280
7281 throw new Error('"' + aStr + '" is not in the set.');
7282 };
7283
7284 /**
7285 * What is the element at the given index?
7286 *
7287 * @param Number aIdx
7288 */
7289 ArraySet.prototype.at = function ArraySet_at(aIdx) {
7290 if (aIdx >= 0 && aIdx < this._array.length) {
7291 return this._array[aIdx];
7292 }
7293 throw new Error('No element indexed by ' + aIdx);
7294 };
7295
7296 /**
7297 * Returns the array representation of this set (which has the proper indices
7298 * indicated by indexOf). Note that this is a copy of the internal array used
7299 * for storing the members so that no one can mess with internal state.
7300 */
7301 ArraySet.prototype.toArray = function ArraySet_toArray() {
7302 return this._array.slice();
7303 };
7304
7305 var ArraySet_1 = ArraySet;
7306
7307 var arraySet = {
7308 ArraySet: ArraySet_1
7309 };
7310
7311 /* -*- Mode: js; js-indent-level: 2; -*- */
7312 /*
7313 * Copyright 2014 Mozilla Foundation and contributors
7314 * Licensed under the New BSD license. See LICENSE or:
7315 * http://opensource.org/licenses/BSD-3-Clause
7316 */
7317
7318
7319
7320 /**
7321 * Determine whether mappingB is after mappingA with respect to generated
7322 * position.
7323 */
7324 function generatedPositionAfter(mappingA, mappingB) {
7325 // Optimized for most common case
7326 var lineA = mappingA.generatedLine;
7327 var lineB = mappingB.generatedLine;
7328 var columnA = mappingA.generatedColumn;
7329 var columnB = mappingB.generatedColumn;
7330 return lineB > lineA || lineB == lineA && columnB >= columnA ||
7331 util.compareByGeneratedPositionsInflated(mappingA, mappingB) <= 0;
7332 }
7333
7334 /**
7335 * A data structure to provide a sorted view of accumulated mappings in a
7336 * performance conscious manner. It trades a neglibable overhead in general
7337 * case for a large speedup in case of mappings being added in order.
7338 */
7339 function MappingList() {
7340 this._array = [];
7341 this._sorted = true;
7342 // Serves as infimum
7343 this._last = {generatedLine: -1, generatedColumn: 0};
7344 }
7345
7346 /**
7347 * Iterate through internal items. This method takes the same arguments that
7348 * `Array.prototype.forEach` takes.
7349 *
7350 * NOTE: The order of the mappings is NOT guaranteed.
7351 */
7352 MappingList.prototype.unsortedForEach =
7353 function MappingList_forEach(aCallback, aThisArg) {
7354 this._array.forEach(aCallback, aThisArg);
7355 };
7356
7357 /**
7358 * Add the given source mapping.
7359 *
7360 * @param Object aMapping
7361 */
7362 MappingList.prototype.add = function MappingList_add(aMapping) {
7363 if (generatedPositionAfter(this._last, aMapping)) {
7364 this._last = aMapping;
7365 this._array.push(aMapping);
7366 } else {
7367 this._sorted = false;
7368 this._array.push(aMapping);
7369 }
7370 };
7371
7372 /**
7373 * Returns the flat, sorted array of mappings. The mappings are sorted by
7374 * generated position.
7375 *
7376 * WARNING: This method returns internal data without copying, for
7377 * performance. The return value must NOT be mutated, and should be treated as
7378 * an immutable borrow. If you want to take ownership, you must make your own
7379 * copy.
7380 */
7381 MappingList.prototype.toArray = function MappingList_toArray() {
7382 if (!this._sorted) {
7383 this._array.sort(util.compareByGeneratedPositionsInflated);
7384 this._sorted = true;
7385 }
7386 return this._array;
7387 };
7388
7389 var MappingList_1 = MappingList;
7390
7391 var mappingList = {
7392 MappingList: MappingList_1
7393 };
7394
7395 /* -*- Mode: js; js-indent-level: 2; -*- */
7396 /*
7397 * Copyright 2011 Mozilla Foundation and contributors
7398 * Licensed under the New BSD license. See LICENSE or:
7399 * http://opensource.org/licenses/BSD-3-Clause
7400 */
7401
7402
7403
7404 var ArraySet$1 = arraySet.ArraySet;
7405 var MappingList$1 = mappingList.MappingList;
7406
7407 /**
7408 * An instance of the SourceMapGenerator represents a source map which is
7409 * being built incrementally. You may pass an object with the following
7410 * properties:
7411 *
7412 * - file: The filename of the generated source.
7413 * - sourceRoot: A root for all relative URLs in this source map.
7414 */
7415 function SourceMapGenerator(aArgs) {
7416 if (!aArgs) {
7417 aArgs = {};
7418 }
7419 this._file = util.getArg(aArgs, 'file', null);
7420 this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null);
7421 this._skipValidation = util.getArg(aArgs, 'skipValidation', false);
7422 this._sources = new ArraySet$1();
7423 this._names = new ArraySet$1();
7424 this._mappings = new MappingList$1();
7425 this._sourcesContents = null;
7426 }
7427
7428 SourceMapGenerator.prototype._version = 3;
7429
7430 /**
7431 * Creates a new SourceMapGenerator based on a SourceMapConsumer
7432 *
7433 * @param aSourceMapConsumer The SourceMap.
7434 */
7435 SourceMapGenerator.fromSourceMap =
7436 function SourceMapGenerator_fromSourceMap(aSourceMapConsumer) {
7437 var sourceRoot = aSourceMapConsumer.sourceRoot;
7438 var generator = new SourceMapGenerator({
7439 file: aSourceMapConsumer.file,
7440 sourceRoot: sourceRoot
7441 });
7442 aSourceMapConsumer.eachMapping(function (mapping) {
7443 var newMapping = {
7444 generated: {
7445 line: mapping.generatedLine,
7446 column: mapping.generatedColumn
7447 }
7448 };
7449
7450 if (mapping.source != null) {
7451 newMapping.source = mapping.source;
7452 if (sourceRoot != null) {
7453 newMapping.source = util.relative(sourceRoot, newMapping.source);
7454 }
7455
7456 newMapping.original = {
7457 line: mapping.originalLine,
7458 column: mapping.originalColumn
7459 };
7460
7461 if (mapping.name != null) {
7462 newMapping.name = mapping.name;
7463 }
7464 }
7465
7466 generator.addMapping(newMapping);
7467 });
7468 aSourceMapConsumer.sources.forEach(function (sourceFile) {
7469 var sourceRelative = sourceFile;
7470 if (sourceRoot !== null) {
7471 sourceRelative = util.relative(sourceRoot, sourceFile);
7472 }
7473
7474 if (!generator._sources.has(sourceRelative)) {
7475 generator._sources.add(sourceRelative);
7476 }
7477
7478 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
7479 if (content != null) {
7480 generator.setSourceContent(sourceFile, content);
7481 }
7482 });
7483 return generator;
7484 };
7485
7486 /**
7487 * Add a single mapping from original source line and column to the generated
7488 * source's line and column for this source map being created. The mapping
7489 * object should have the following properties:
7490 *
7491 * - generated: An object with the generated line and column positions.
7492 * - original: An object with the original line and column positions.
7493 * - source: The original source file (relative to the sourceRoot).
7494 * - name: An optional original token name for this mapping.
7495 */
7496 SourceMapGenerator.prototype.addMapping =
7497 function SourceMapGenerator_addMapping(aArgs) {
7498 var generated = util.getArg(aArgs, 'generated');
7499 var original = util.getArg(aArgs, 'original', null);
7500 var source = util.getArg(aArgs, 'source', null);
7501 var name = util.getArg(aArgs, 'name', null);
7502
7503 if (!this._skipValidation) {
7504 this._validateMapping(generated, original, source, name);
7505 }
7506
7507 if (source != null) {
7508 source = String(source);
7509 if (!this._sources.has(source)) {
7510 this._sources.add(source);
7511 }
7512 }
7513
7514 if (name != null) {
7515 name = String(name);
7516 if (!this._names.has(name)) {
7517 this._names.add(name);
7518 }
7519 }
7520
7521 this._mappings.add({
7522 generatedLine: generated.line,
7523 generatedColumn: generated.column,
7524 originalLine: original != null && original.line,
7525 originalColumn: original != null && original.column,
7526 source: source,
7527 name: name
7528 });
7529 };
7530
7531 /**
7532 * Set the source content for a source file.
7533 */
7534 SourceMapGenerator.prototype.setSourceContent =
7535 function SourceMapGenerator_setSourceContent(aSourceFile, aSourceContent) {
7536 var source = aSourceFile;
7537 if (this._sourceRoot != null) {
7538 source = util.relative(this._sourceRoot, source);
7539 }
7540
7541 if (aSourceContent != null) {
7542 // Add the source content to the _sourcesContents map.
7543 // Create a new _sourcesContents map if the property is null.
7544 if (!this._sourcesContents) {
7545 this._sourcesContents = Object.create(null);
7546 }
7547 this._sourcesContents[util.toSetString(source)] = aSourceContent;
7548 } else if (this._sourcesContents) {
7549 // Remove the source file from the _sourcesContents map.
7550 // If the _sourcesContents map is empty, set the property to null.
7551 delete this._sourcesContents[util.toSetString(source)];
7552 if (Object.keys(this._sourcesContents).length === 0) {
7553 this._sourcesContents = null;
7554 }
7555 }
7556 };
7557
7558 /**
7559 * Applies the mappings of a sub-source-map for a specific source file to the
7560 * source map being generated. Each mapping to the supplied source file is
7561 * rewritten using the supplied source map. Note: The resolution for the
7562 * resulting mappings is the minimium of this map and the supplied map.
7563 *
7564 * @param aSourceMapConsumer The source map to be applied.
7565 * @param aSourceFile Optional. The filename of the source file.
7566 * If omitted, SourceMapConsumer's file property will be used.
7567 * @param aSourceMapPath Optional. The dirname of the path to the source map
7568 * to be applied. If relative, it is relative to the SourceMapConsumer.
7569 * This parameter is needed when the two source maps aren't in the same
7570 * directory, and the source map to be applied contains relative source
7571 * paths. If so, those relative source paths need to be rewritten
7572 * relative to the SourceMapGenerator.
7573 */
7574 SourceMapGenerator.prototype.applySourceMap =
7575 function SourceMapGenerator_applySourceMap(aSourceMapConsumer, aSourceFile, aSourceMapPath) {
7576 var sourceFile = aSourceFile;
7577 // If aSourceFile is omitted, we will use the file property of the SourceMap
7578 if (aSourceFile == null) {
7579 if (aSourceMapConsumer.file == null) {
7580 throw new Error(
7581 'SourceMapGenerator.prototype.applySourceMap requires either an explicit source file, ' +
7582 'or the source map\'s "file" property. Both were omitted.'
7583 );
7584 }
7585 sourceFile = aSourceMapConsumer.file;
7586 }
7587 var sourceRoot = this._sourceRoot;
7588 // Make "sourceFile" relative if an absolute Url is passed.
7589 if (sourceRoot != null) {
7590 sourceFile = util.relative(sourceRoot, sourceFile);
7591 }
7592 // Applying the SourceMap can add and remove items from the sources and
7593 // the names array.
7594 var newSources = new ArraySet$1();
7595 var newNames = new ArraySet$1();
7596
7597 // Find mappings for the "sourceFile"
7598 this._mappings.unsortedForEach(function (mapping) {
7599 if (mapping.source === sourceFile && mapping.originalLine != null) {
7600 // Check if it can be mapped by the source map, then update the mapping.
7601 var original = aSourceMapConsumer.originalPositionFor({
7602 line: mapping.originalLine,
7603 column: mapping.originalColumn
7604 });
7605 if (original.source != null) {
7606 // Copy mapping
7607 mapping.source = original.source;
7608 if (aSourceMapPath != null) {
7609 mapping.source = util.join(aSourceMapPath, mapping.source);
7610 }
7611 if (sourceRoot != null) {
7612 mapping.source = util.relative(sourceRoot, mapping.source);
7613 }
7614 mapping.originalLine = original.line;
7615 mapping.originalColumn = original.column;
7616 if (original.name != null) {
7617 mapping.name = original.name;
7618 }
7619 }
7620 }
7621
7622 var source = mapping.source;
7623 if (source != null && !newSources.has(source)) {
7624 newSources.add(source);
7625 }
7626
7627 var name = mapping.name;
7628 if (name != null && !newNames.has(name)) {
7629 newNames.add(name);
7630 }
7631
7632 }, this);
7633 this._sources = newSources;
7634 this._names = newNames;
7635
7636 // Copy sourcesContents of applied map.
7637 aSourceMapConsumer.sources.forEach(function (sourceFile) {
7638 var content = aSourceMapConsumer.sourceContentFor(sourceFile);
7639 if (content != null) {
7640 if (aSourceMapPath != null) {
7641 sourceFile = util.join(aSourceMapPath, sourceFile);
7642 }
7643 if (sourceRoot != null) {
7644 sourceFile = util.relative(sourceRoot, sourceFile);
7645 }
7646 this.setSourceContent(sourceFile, content);
7647 }
7648 }, this);
7649 };
7650
7651 /**
7652 * A mapping can have one of the three levels of data:
7653 *
7654 * 1. Just the generated position.
7655 * 2. The Generated position, original position, and original source.
7656 * 3. Generated and original position, original source, as well as a name
7657 * token.
7658 *
7659 * To maintain consistency, we validate that any new mapping being added falls
7660 * in to one of these categories.
7661 */
7662 SourceMapGenerator.prototype._validateMapping =
7663 function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource,
7664 aName) {
7665 // When aOriginal is truthy but has empty values for .line and .column,
7666 // it is most likely a programmer error. In this case we throw a very
7667 // specific error message to try to guide them the right way.
7668 // For example: https://github.com/Polymer/polymer-bundler/pull/519
7669 if (aOriginal && typeof aOriginal.line !== 'number' && typeof aOriginal.column !== 'number') {
7670 throw new Error(
7671 'original.line and original.column are not numbers -- you probably meant to omit ' +
7672 'the original mapping entirely and only map the generated position. If so, pass ' +
7673 'null for the original mapping instead of an object with empty or null values.'
7674 );
7675 }
7676
7677 if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
7678 && aGenerated.line > 0 && aGenerated.column >= 0
7679 && !aOriginal && !aSource && !aName) {
7680 // Case 1.
7681 return;
7682 }
7683 else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated
7684 && aOriginal && 'line' in aOriginal && 'column' in aOriginal
7685 && aGenerated.line > 0 && aGenerated.column >= 0
7686 && aOriginal.line > 0 && aOriginal.column >= 0
7687 && aSource) {
7688 // Cases 2 and 3.
7689 return;
7690 }
7691 else {
7692 throw new Error('Invalid mapping: ' + JSON.stringify({
7693 generated: aGenerated,
7694 source: aSource,
7695 original: aOriginal,
7696 name: aName
7697 }));
7698 }
7699 };
7700
7701 /**
7702 * Serialize the accumulated mappings in to the stream of base 64 VLQs
7703 * specified by the source map format.
7704 */
7705 SourceMapGenerator.prototype._serializeMappings =
7706 function SourceMapGenerator_serializeMappings() {
7707 var previousGeneratedColumn = 0;
7708 var previousGeneratedLine = 1;
7709 var previousOriginalColumn = 0;
7710 var previousOriginalLine = 0;
7711 var previousName = 0;
7712 var previousSource = 0;
7713 var result = '';
7714 var next;
7715 var mapping;
7716 var nameIdx;
7717 var sourceIdx;
7718
7719 var mappings = this._mappings.toArray();
7720 for (var i = 0, len = mappings.length; i < len; i++) {
7721 mapping = mappings[i];
7722 next = '';
7723
7724 if (mapping.generatedLine !== previousGeneratedLine) {
7725 previousGeneratedColumn = 0;
7726 while (mapping.generatedLine !== previousGeneratedLine) {
7727 next += ';';
7728 previousGeneratedLine++;
7729 }
7730 }
7731 else {
7732 if (i > 0) {
7733 if (!util.compareByGeneratedPositionsInflated(mapping, mappings[i - 1])) {
7734 continue;
7735 }
7736 next += ',';
7737 }
7738 }
7739
7740 next += base64Vlq.encode(mapping.generatedColumn
7741 - previousGeneratedColumn);
7742 previousGeneratedColumn = mapping.generatedColumn;
7743
7744 if (mapping.source != null) {
7745 sourceIdx = this._sources.indexOf(mapping.source);
7746 next += base64Vlq.encode(sourceIdx - previousSource);
7747 previousSource = sourceIdx;
7748
7749 // lines are stored 0-based in SourceMap spec version 3
7750 next += base64Vlq.encode(mapping.originalLine - 1
7751 - previousOriginalLine);
7752 previousOriginalLine = mapping.originalLine - 1;
7753
7754 next += base64Vlq.encode(mapping.originalColumn
7755 - previousOriginalColumn);
7756 previousOriginalColumn = mapping.originalColumn;
7757
7758 if (mapping.name != null) {
7759 nameIdx = this._names.indexOf(mapping.name);
7760 next += base64Vlq.encode(nameIdx - previousName);
7761 previousName = nameIdx;
7762 }
7763 }
7764
7765 result += next;
7766 }
7767
7768 return result;
7769 };
7770
7771 SourceMapGenerator.prototype._generateSourcesContent =
7772 function SourceMapGenerator_generateSourcesContent(aSources, aSourceRoot) {
7773 return aSources.map(function (source) {
7774 if (!this._sourcesContents) {
7775 return null;
7776 }
7777 if (aSourceRoot != null) {
7778 source = util.relative(aSourceRoot, source);
7779 }
7780 var key = util.toSetString(source);
7781 return Object.prototype.hasOwnProperty.call(this._sourcesContents, key)
7782 ? this._sourcesContents[key]
7783 : null;
7784 }, this);
7785 };
7786
7787 /**
7788 * Externalize the source map.
7789 */
7790 SourceMapGenerator.prototype.toJSON =
7791 function SourceMapGenerator_toJSON() {
7792 var map = {
7793 version: this._version,
7794 sources: this._sources.toArray(),
7795 names: this._names.toArray(),
7796 mappings: this._serializeMappings()
7797 };
7798 if (this._file != null) {
7799 map.file = this._file;
7800 }
7801 if (this._sourceRoot != null) {
7802 map.sourceRoot = this._sourceRoot;
7803 }
7804 if (this._sourcesContents) {
7805 map.sourcesContent = this._generateSourcesContent(map.sources, map.sourceRoot);
7806 }
7807
7808 return map;
7809 };
7810
7811 /**
7812 * Render the source map being generated to a string.
7813 */
7814 SourceMapGenerator.prototype.toString =
7815 function SourceMapGenerator_toString() {
7816 return JSON.stringify(this.toJSON());
7817 };
7818
7819 var SourceMapGenerator_1 = SourceMapGenerator;
7820
7821 var sourceMapGenerator = {
7822 SourceMapGenerator: SourceMapGenerator_1
7823 };
7824
7825 var SourceMapGenerator$1 = sourceMapGenerator.SourceMapGenerator;
7826 var trackNodes = {
7827 Atrule: true,
7828 Selector: true,
7829 Declaration: true
7830 };
7831
7832 var sourceMap = function generateSourceMap(handlers) {
7833 var map = new SourceMapGenerator$1();
7834 var line = 1;
7835 var column = 0;
7836 var generated = {
7837 line: 1,
7838 column: 0
7839 };
7840 var original = {
7841 line: 0, // should be zero to add first mapping
7842 column: 0
7843 };
7844 var sourceMappingActive = false;
7845 var activatedGenerated = {
7846 line: 1,
7847 column: 0
7848 };
7849 var activatedMapping = {
7850 generated: activatedGenerated
7851 };
7852
7853 var handlersNode = handlers.node;
7854 handlers.node = function(node) {
7855 if (node.loc && node.loc.start && trackNodes.hasOwnProperty(node.type)) {
7856 var nodeLine = node.loc.start.line;
7857 var nodeColumn = node.loc.start.column - 1;
7858
7859 if (original.line !== nodeLine ||
7860 original.column !== nodeColumn) {
7861 original.line = nodeLine;
7862 original.column = nodeColumn;
7863
7864 generated.line = line;
7865 generated.column = column;
7866
7867 if (sourceMappingActive) {
7868 sourceMappingActive = false;
7869 if (generated.line !== activatedGenerated.line ||
7870 generated.column !== activatedGenerated.column) {
7871 map.addMapping(activatedMapping);
7872 }
7873 }
7874
7875 sourceMappingActive = true;
7876 map.addMapping({
7877 source: node.loc.source,
7878 original: original,
7879 generated: generated
7880 });
7881 }
7882 }
7883
7884 handlersNode.call(this, node);
7885
7886 if (sourceMappingActive && trackNodes.hasOwnProperty(node.type)) {
7887 activatedGenerated.line = line;
7888 activatedGenerated.column = column;
7889 }
7890 };
7891
7892 var handlersChunk = handlers.chunk;
7893 handlers.chunk = function(chunk) {
7894 for (var i = 0; i < chunk.length; i++) {
7895 if (chunk.charCodeAt(i) === 10) { // \n
7896 line++;
7897 column = 0;
7898 } else {
7899 column++;
7900 }
7901 }
7902
7903 handlersChunk(chunk);
7904 };
7905
7906 var handlersResult = handlers.result;
7907 handlers.result = function() {
7908 if (sourceMappingActive) {
7909 map.addMapping(activatedMapping);
7910 }
7911
7912 return {
7913 css: handlersResult(),
7914 map: map
7915 };
7916 };
7917
7918 return handlers;
7919 };
7920
7921 var hasOwnProperty$3 = Object.prototype.hasOwnProperty;
7922
7923 function processChildren(node, delimeter) {
7924 var list = node.children;
7925 var prev = null;
7926
7927 if (typeof delimeter !== 'function') {
7928 list.forEach(this.node, this);
7929 } else {
7930 list.forEach(function(node) {
7931 if (prev !== null) {
7932 delimeter.call(this, prev);
7933 }
7934
7935 this.node(node);
7936 prev = node;
7937 }, this);
7938 }
7939 }
7940
7941 var create$1 = function createGenerator(config) {
7942 function processNode(node) {
7943 if (hasOwnProperty$3.call(types, node.type)) {
7944 types[node.type].call(this, node);
7945 } else {
7946 throw new Error('Unknown node type: ' + node.type);
7947 }
7948 }
7949
7950 var types = {};
7951
7952 if (config.node) {
7953 for (var name in config.node) {
7954 types[name] = config.node[name].generate;
7955 }
7956 }
7957
7958 return function(node, options) {
7959 var buffer = '';
7960 var handlers = {
7961 children: processChildren,
7962 node: processNode,
7963 chunk: function(chunk) {
7964 buffer += chunk;
7965 },
7966 result: function() {
7967 return buffer;
7968 }
7969 };
7970
7971 if (options) {
7972 if (typeof options.decorator === 'function') {
7973 handlers = options.decorator(handlers);
7974 }
7975
7976 if (options.sourceMap) {
7977 handlers = sourceMap(handlers);
7978 }
7979 }
7980
7981 handlers.node(node);
7982
7983 return handlers.result();
7984 };
7985 };
7986
7987 var create$2 = function createConvertors(walk) {
7988 return {
7989 fromPlainObject: function(ast) {
7990 walk(ast, {
7991 enter: function(node) {
7992 if (node.children && node.children instanceof List_1 === false) {
7993 node.children = new List_1().fromArray(node.children);
7994 }
7995 }
7996 });
7997
7998 return ast;
7999 },
8000 toPlainObject: function(ast) {
8001 walk(ast, {
8002 leave: function(node) {
8003 if (node.children && node.children instanceof List_1) {
8004 node.children = node.children.toArray();
8005 }
8006 }
8007 });
8008
8009 return ast;
8010 }
8011 };
8012 };
8013
8014 var hasOwnProperty$4 = Object.prototype.hasOwnProperty;
8015 var noop$3 = function() {};
8016
8017 function ensureFunction$1(value) {
8018 return typeof value === 'function' ? value : noop$3;
8019 }
8020
8021 function invokeForType(fn, type) {
8022 return function(node, item, list) {
8023 if (node.type === type) {
8024 fn.call(this, node, item, list);
8025 }
8026 };
8027 }
8028
8029 function getWalkersFromStructure(name, nodeType) {
8030 var structure = nodeType.structure;
8031 var walkers = [];
8032
8033 for (var key in structure) {
8034 if (hasOwnProperty$4.call(structure, key) === false) {
8035 continue;
8036 }
8037
8038 var fieldTypes = structure[key];
8039 var walker = {
8040 name: key,
8041 type: false,
8042 nullable: false
8043 };
8044
8045 if (!Array.isArray(structure[key])) {
8046 fieldTypes = [structure[key]];
8047 }
8048
8049 for (var i = 0; i < fieldTypes.length; i++) {
8050 var fieldType = fieldTypes[i];
8051 if (fieldType === null) {
8052 walker.nullable = true;
8053 } else if (typeof fieldType === 'string') {
8054 walker.type = 'node';
8055 } else if (Array.isArray(fieldType)) {
8056 walker.type = 'list';
8057 }
8058 }
8059
8060 if (walker.type) {
8061 walkers.push(walker);
8062 }
8063 }
8064
8065 if (walkers.length) {
8066 return {
8067 context: nodeType.walkContext,
8068 fields: walkers
8069 };
8070 }
8071
8072 return null;
8073 }
8074
8075 function getTypesFromConfig(config) {
8076 var types = {};
8077
8078 for (var name in config.node) {
8079 if (hasOwnProperty$4.call(config.node, name)) {
8080 var nodeType = config.node[name];
8081
8082 if (!nodeType.structure) {
8083 throw new Error('Missed `structure` field in `' + name + '` node type definition');
8084 }
8085
8086 types[name] = getWalkersFromStructure(name, nodeType);
8087 }
8088 }
8089
8090 return types;
8091 }
8092
8093 function createTypeIterator(config, reverse) {
8094 var fields = config.fields.slice();
8095 var contextName = config.context;
8096 var useContext = typeof contextName === 'string';
8097
8098 if (reverse) {
8099 fields.reverse();
8100 }
8101
8102 return function(node, context, walk, walkReducer) {
8103 var prevContextValue;
8104
8105 if (useContext) {
8106 prevContextValue = context[contextName];
8107 context[contextName] = node;
8108 }
8109
8110 for (var i = 0; i < fields.length; i++) {
8111 var field = fields[i];
8112 var ref = node[field.name];
8113
8114 if (!field.nullable || ref) {
8115 if (field.type === 'list') {
8116 var breakWalk = reverse
8117 ? ref.reduceRight(walkReducer, false)
8118 : ref.reduce(walkReducer, false);
8119
8120 if (breakWalk) {
8121 return true;
8122 }
8123 } else if (walk(ref)) {
8124 return true;
8125 }
8126 }
8127 }
8128
8129 if (useContext) {
8130 context[contextName] = prevContextValue;
8131 }
8132 };
8133 }
8134
8135 function createFastTraveralMap(iterators) {
8136 return {
8137 Atrule: {
8138 StyleSheet: iterators.StyleSheet,
8139 Atrule: iterators.Atrule,
8140 Rule: iterators.Rule,
8141 Block: iterators.Block
8142 },
8143 Rule: {
8144 StyleSheet: iterators.StyleSheet,
8145 Atrule: iterators.Atrule,
8146 Rule: iterators.Rule,
8147 Block: iterators.Block
8148 },
8149 Declaration: {
8150 StyleSheet: iterators.StyleSheet,
8151 Atrule: iterators.Atrule,
8152 Rule: iterators.Rule,
8153 Block: iterators.Block,
8154 DeclarationList: iterators.DeclarationList
8155 }
8156 };
8157 }
8158
8159 var create$3 = function createWalker(config) {
8160 var types = getTypesFromConfig(config);
8161 var iteratorsNatural = {};
8162 var iteratorsReverse = {};
8163 var breakWalk = Symbol('break-walk');
8164 var skipNode = Symbol('skip-node');
8165
8166 for (var name in types) {
8167 if (hasOwnProperty$4.call(types, name) && types[name] !== null) {
8168 iteratorsNatural[name] = createTypeIterator(types[name], false);
8169 iteratorsReverse[name] = createTypeIterator(types[name], true);
8170 }
8171 }
8172
8173 var fastTraversalIteratorsNatural = createFastTraveralMap(iteratorsNatural);
8174 var fastTraversalIteratorsReverse = createFastTraveralMap(iteratorsReverse);
8175
8176 var walk = function(root, options) {
8177 function walkNode(node, item, list) {
8178 var enterRet = enter.call(context, node, item, list);
8179
8180 if (enterRet === breakWalk) {
8181 debugger;
8182 return true;
8183 }
8184
8185 if (enterRet === skipNode) {
8186 return false;
8187 }
8188
8189 if (iterators.hasOwnProperty(node.type)) {
8190 if (iterators[node.type](node, context, walkNode, walkReducer)) {
8191 return true;
8192 }
8193 }
8194
8195 if (leave.call(context, node, item, list) === breakWalk) {
8196 return true;
8197 }
8198
8199 return false;
8200 }
8201
8202 var walkReducer = (ret, data, item, list) => ret || walkNode(data, item, list);
8203 var enter = noop$3;
8204 var leave = noop$3;
8205 var iterators = iteratorsNatural;
8206 var context = {
8207 break: breakWalk,
8208 skip: skipNode,
8209
8210 root: root,
8211 stylesheet: null,
8212 atrule: null,
8213 atrulePrelude: null,
8214 rule: null,
8215 selector: null,
8216 block: null,
8217 declaration: null,
8218 function: null
8219 };
8220
8221 if (typeof options === 'function') {
8222 enter = options;
8223 } else if (options) {
8224 enter = ensureFunction$1(options.enter);
8225 leave = ensureFunction$1(options.leave);
8226
8227 if (options.reverse) {
8228 iterators = iteratorsReverse;
8229 }
8230
8231 if (options.visit) {
8232 if (fastTraversalIteratorsNatural.hasOwnProperty(options.visit)) {
8233 iterators = options.reverse
8234 ? fastTraversalIteratorsReverse[options.visit]
8235 : fastTraversalIteratorsNatural[options.visit];
8236 } else if (!types.hasOwnProperty(options.visit)) {
8237 throw new Error('Bad value `' + options.visit + '` for `visit` option (should be: ' + Object.keys(types).join(', ') + ')');
8238 }
8239
8240 enter = invokeForType(enter, options.visit);
8241 leave = invokeForType(leave, options.visit);
8242 }
8243 }
8244
8245 if (enter === noop$3 && leave === noop$3) {
8246 throw new Error('Neither `enter` nor `leave` walker handler is set or both aren\'t a function');
8247 }
8248
8249 walkNode(root);
8250 };
8251
8252 walk.break = breakWalk;
8253 walk.skip = skipNode;
8254
8255 walk.find = function(ast, fn) {
8256 var found = null;
8257
8258 walk(ast, function(node, item, list) {
8259 if (fn.call(this, node, item, list)) {
8260 found = node;
8261 return breakWalk;
8262 }
8263 });
8264
8265 return found;
8266 };
8267
8268 walk.findLast = function(ast, fn) {
8269 var found = null;
8270
8271 walk(ast, {
8272 reverse: true,
8273 enter: function(node, item, list) {
8274 if (fn.call(this, node, item, list)) {
8275 found = node;
8276 return breakWalk;
8277 }
8278 }
8279 });
8280
8281 return found;
8282 };
8283
8284 walk.findAll = function(ast, fn) {
8285 var found = [];
8286
8287 walk(ast, function(node, item, list) {
8288 if (fn.call(this, node, item, list)) {
8289 found.push(node);
8290 }
8291 });
8292
8293 return found;
8294 };
8295
8296 return walk;
8297 };
8298
8299 var clone = function clone(node) {
8300 var result = {};
8301
8302 for (var key in node) {
8303 var value = node[key];
8304
8305 if (value) {
8306 if (Array.isArray(value) || value instanceof List_1) {
8307 value = value.map(clone);
8308 } else if (value.constructor === Object) {
8309 value = clone(value);
8310 }
8311 }
8312
8313 result[key] = value;
8314 }
8315
8316 return result;
8317 };
8318
8319 const hasOwnProperty$5 = Object.prototype.hasOwnProperty;
8320 const shape = {
8321 generic: true,
8322 types: appendOrAssign,
8323 atrules: {
8324 prelude: appendOrAssignOrNull,
8325 descriptors: appendOrAssignOrNull
8326 },
8327 properties: appendOrAssign,
8328 parseContext: assign,
8329 scope: deepAssign,
8330 atrule: ['parse'],
8331 pseudo: ['parse'],
8332 node: ['name', 'structure', 'parse', 'generate', 'walkContext']
8333 };
8334
8335 function isObject(value) {
8336 return value && value.constructor === Object;
8337 }
8338
8339 function copy(value) {
8340 return isObject(value)
8341 ? Object.assign({}, value)
8342 : value;
8343 }
8344
8345 function assign(dest, src) {
8346 return Object.assign(dest, src);
8347 }
8348
8349 function deepAssign(dest, src) {
8350 for (const key in src) {
8351 if (hasOwnProperty$5.call(src, key)) {
8352 if (isObject(dest[key])) {
8353 deepAssign(dest[key], copy(src[key]));
8354 } else {
8355 dest[key] = copy(src[key]);
8356 }
8357 }
8358 }
8359
8360 return dest;
8361 }
8362
8363 function append(a, b) {
8364 if (typeof b === 'string' && /^\s*\|/.test(b)) {
8365 return typeof a === 'string'
8366 ? a + b
8367 : b.replace(/^\s*\|\s*/, '');
8368 }
8369
8370 return b || null;
8371 }
8372
8373 function appendOrAssign(a, b) {
8374 if (typeof b === 'string') {
8375 return append(a, b);
8376 }
8377
8378 const result = Object.assign({}, a);
8379 for (let key in b) {
8380 if (hasOwnProperty$5.call(b, key)) {
8381 result[key] = append(hasOwnProperty$5.call(a, key) ? a[key] : undefined, b[key]);
8382 }
8383 }
8384
8385 return result;
8386 }
8387
8388 function appendOrAssignOrNull(a, b) {
8389 const result = appendOrAssign(a, b);
8390
8391 return !isObject(result) || Object.keys(result).length
8392 ? result
8393 : null;
8394 }
8395
8396 function mix(dest, src, shape) {
8397 for (const key in shape) {
8398 if (hasOwnProperty$5.call(shape, key) === false) {
8399 continue;
8400 }
8401
8402 if (shape[key] === true) {
8403 if (key in src) {
8404 if (hasOwnProperty$5.call(src, key)) {
8405 dest[key] = copy(src[key]);
8406 }
8407 }
8408 } else if (shape[key]) {
8409 if (typeof shape[key] === 'function') {
8410 const fn = shape[key];
8411 dest[key] = fn({}, dest[key]);
8412 dest[key] = fn(dest[key] || {}, src[key]);
8413 } else if (isObject(shape[key])) {
8414 const result = {};
8415
8416 for (let name in dest[key]) {
8417 result[name] = mix({}, dest[key][name], shape[key]);
8418 }
8419
8420 for (let name in src[key]) {
8421 result[name] = mix(result[name] || {}, src[key][name], shape[key]);
8422 }
8423
8424 dest[key] = result;
8425 } else if (Array.isArray(shape[key])) {
8426 const res = {};
8427 const innerShape = shape[key].reduce(function(s, k) {
8428 s[k] = true;
8429 return s;
8430 }, {});
8431
8432 for (const [name, value] of Object.entries(dest[key] || {})) {
8433 res[name] = {};
8434 if (value) {
8435 mix(res[name], value, innerShape);
8436 }
8437 }
8438
8439 for (const name in src[key]) {
8440 if (hasOwnProperty$5.call(src[key], name)) {
8441 if (!res[name]) {
8442 res[name] = {};
8443 }
8444
8445 if (src[key] && src[key][name]) {
8446 mix(res[name], src[key][name], innerShape);
8447 }
8448 }
8449 }
8450
8451 dest[key] = res;
8452 }
8453 }
8454 }
8455 return dest;
8456 }
8457
8458 var mix_1 = (dest, src) => mix(dest, src, shape);
8459
8460 function createSyntax(config) {
8461 var parse = create(config);
8462 var walk = create$3(config);
8463 var generate = create$1(config);
8464 var convert = create$2(walk);
8465
8466 var syntax = {
8467 List: List_1,
8468 SyntaxError: _SyntaxError,
8469 TokenStream: TokenStream_1,
8470 Lexer: Lexer_1,
8471
8472 vendorPrefix: names.vendorPrefix,
8473 keyword: names.keyword,
8474 property: names.property,
8475 isCustomProperty: names.isCustomProperty,
8476
8477 definitionSyntax: definitionSyntax,
8478 lexer: null,
8479 createLexer: function(config) {
8480 return new Lexer_1(config, syntax, syntax.lexer.structure);
8481 },
8482
8483 tokenize: tokenizer,
8484 parse: parse,
8485 walk: walk,
8486 generate: generate,
8487
8488 find: walk.find,
8489 findLast: walk.findLast,
8490 findAll: walk.findAll,
8491
8492 clone: clone,
8493 fromPlainObject: convert.fromPlainObject,
8494 toPlainObject: convert.toPlainObject,
8495
8496 createSyntax: function(config) {
8497 return createSyntax(mix_1({}, config));
8498 },
8499 fork: function(extension) {
8500 var base = mix_1({}, config); // copy of config
8501 return createSyntax(
8502 typeof extension === 'function'
8503 ? extension(base, Object.assign)
8504 : mix_1(base, extension)
8505 );
8506 }
8507 };
8508
8509 syntax.lexer = new Lexer_1({
8510 generic: true,
8511 types: config.types,
8512 atrules: config.atrules,
8513 properties: config.properties,
8514 node: config.node
8515 }, syntax);
8516
8517 return syntax;
8518 }
8519 var create_1 = function(config) {
8520 return createSyntax(mix_1({}, config));
8521 };
8522
8523 var create$4 = {
8524 create: create_1
8525 };
8526
8527 var data = {
8528 "generic": true,
8529 "types": {
8530 "absolute-size": "xx-small|x-small|small|medium|large|x-large|xx-large|xxx-large",
8531 "alpha-value": "<number>|<percentage>",
8532 "angle-percentage": "<angle>|<percentage>",
8533 "angular-color-hint": "<angle-percentage>",
8534 "angular-color-stop": "<color>&&<color-stop-angle>?",
8535 "angular-color-stop-list": "[<angular-color-stop> [, <angular-color-hint>]?]# , <angular-color-stop>",
8536 "animateable-feature": "scroll-position|contents|<custom-ident>",
8537 "attachment": "scroll|fixed|local",
8538 "attr()": "attr( <attr-name> <type-or-unit>? [, <attr-fallback>]? )",
8539 "attr-matcher": "['~'|'|'|'^'|'$'|'*']? '='",
8540 "attr-modifier": "i|s",
8541 "attribute-selector": "'[' <wq-name> ']'|'[' <wq-name> <attr-matcher> [<string-token>|<ident-token>] <attr-modifier>? ']'",
8542 "auto-repeat": "repeat( [auto-fill|auto-fit] , [<line-names>? <fixed-size>]+ <line-names>? )",
8543 "auto-track-list": "[<line-names>? [<fixed-size>|<fixed-repeat>]]* <line-names>? <auto-repeat> [<line-names>? [<fixed-size>|<fixed-repeat>]]* <line-names>?",
8544 "baseline-position": "[first|last]? baseline",
8545 "basic-shape": "<inset()>|<circle()>|<ellipse()>|<polygon()>|<path()>",
8546 "bg-image": "none|<image>",
8547 "bg-layer": "<bg-image>||<bg-position> [/ <bg-size>]?||<repeat-style>||<attachment>||<box>||<box>",
8548 "bg-position": "[[left|center|right|top|bottom|<length-percentage>]|[left|center|right|<length-percentage>] [top|center|bottom|<length-percentage>]|[center|[left|right] <length-percentage>?]&&[center|[top|bottom] <length-percentage>?]]",
8549 "bg-size": "[<length-percentage>|auto]{1,2}|cover|contain",
8550 "blur()": "blur( <length> )",
8551 "blend-mode": "normal|multiply|screen|overlay|darken|lighten|color-dodge|color-burn|hard-light|soft-light|difference|exclusion|hue|saturation|color|luminosity",
8552 "box": "border-box|padding-box|content-box",
8553 "brightness()": "brightness( <number-percentage> )",
8554 "calc()": "calc( <calc-sum> )",
8555 "calc-sum": "<calc-product> [['+'|'-'] <calc-product>]*",
8556 "calc-product": "<calc-value> ['*' <calc-value>|'/' <number>]*",
8557 "calc-value": "<number>|<dimension>|<percentage>|( <calc-sum> )",
8558 "cf-final-image": "<image>|<color>",
8559 "cf-mixing-image": "<percentage>?&&<image>",
8560 "circle()": "circle( [<shape-radius>]? [at <position>]? )",
8561 "clamp()": "clamp( <calc-sum>#{3} )",
8562 "class-selector": "'.' <ident-token>",
8563 "clip-source": "<url>",
8564 "color": "<rgb()>|<rgba()>|<hsl()>|<hsla()>|<hex-color>|<named-color>|currentcolor|<deprecated-system-color>",
8565 "color-stop": "<color-stop-length>|<color-stop-angle>",
8566 "color-stop-angle": "<angle-percentage>{1,2}",
8567 "color-stop-length": "<length-percentage>{1,2}",
8568 "color-stop-list": "[<linear-color-stop> [, <linear-color-hint>]?]# , <linear-color-stop>",
8569 "combinator": "'>'|'+'|'~'|['||']",
8570 "common-lig-values": "[common-ligatures|no-common-ligatures]",
8571 "compat-auto": "searchfield|textarea|push-button|slider-horizontal|checkbox|radio|square-button|menulist|listbox|meter|progress-bar|button",
8572 "composite-style": "clear|copy|source-over|source-in|source-out|source-atop|destination-over|destination-in|destination-out|destination-atop|xor",
8573 "compositing-operator": "add|subtract|intersect|exclude",
8574 "compound-selector": "[<type-selector>? <subclass-selector>* [<pseudo-element-selector> <pseudo-class-selector>*]*]!",
8575 "compound-selector-list": "<compound-selector>#",
8576 "complex-selector": "<compound-selector> [<combinator>? <compound-selector>]*",
8577 "complex-selector-list": "<complex-selector>#",
8578 "conic-gradient()": "conic-gradient( [from <angle>]? [at <position>]? , <angular-color-stop-list> )",
8579 "contextual-alt-values": "[contextual|no-contextual]",
8580 "content-distribution": "space-between|space-around|space-evenly|stretch",
8581 "content-list": "[<string>|contents|<image>|<quote>|<target>|<leader()>|<attr()>|counter( <ident> , <'list-style-type'>? )]+",
8582 "content-position": "center|start|end|flex-start|flex-end",
8583 "content-replacement": "<image>",
8584 "contrast()": "contrast( [<number-percentage>] )",
8585 "counter()": "counter( <custom-ident> , <counter-style>? )",
8586 "counter-style": "<counter-style-name>|symbols( )",
8587 "counter-style-name": "<custom-ident>",
8588 "counters()": "counters( <custom-ident> , <string> , <counter-style>? )",
8589 "cross-fade()": "cross-fade( <cf-mixing-image> , <cf-final-image>? )",
8590 "cubic-bezier-timing-function": "ease|ease-in|ease-out|ease-in-out|cubic-bezier( <number [0,1]> , <number> , <number [0,1]> , <number> )",
8591 "deprecated-system-color": "ActiveBorder|ActiveCaption|AppWorkspace|Background|ButtonFace|ButtonHighlight|ButtonShadow|ButtonText|CaptionText|GrayText|Highlight|HighlightText|InactiveBorder|InactiveCaption|InactiveCaptionText|InfoBackground|InfoText|Menu|MenuText|Scrollbar|ThreeDDarkShadow|ThreeDFace|ThreeDHighlight|ThreeDLightShadow|ThreeDShadow|Window|WindowFrame|WindowText",
8592 "discretionary-lig-values": "[discretionary-ligatures|no-discretionary-ligatures]",
8593 "display-box": "contents|none",
8594 "display-inside": "flow|flow-root|table|flex|grid|ruby",
8595 "display-internal": "table-row-group|table-header-group|table-footer-group|table-row|table-cell|table-column-group|table-column|table-caption|ruby-base|ruby-text|ruby-base-container|ruby-text-container",
8596 "display-legacy": "inline-block|inline-list-item|inline-table|inline-flex|inline-grid",
8597 "display-listitem": "<display-outside>?&&[flow|flow-root]?&&list-item",
8598 "display-outside": "block|inline|run-in",
8599 "drop-shadow()": "drop-shadow( <length>{2,3} <color>? )",
8600 "east-asian-variant-values": "[jis78|jis83|jis90|jis04|simplified|traditional]",
8601 "east-asian-width-values": "[full-width|proportional-width]",
8602 "element()": "element( <custom-ident> , [first|start|last|first-except]? )|element( <id-selector> )",
8603 "ellipse()": "ellipse( [<shape-radius>{2}]? [at <position>]? )",
8604 "ending-shape": "circle|ellipse",
8605 "env()": "env( <custom-ident> , <declaration-value>? )",
8606 "explicit-track-list": "[<line-names>? <track-size>]+ <line-names>?",
8607 "family-name": "<string>|<custom-ident>+",
8608 "feature-tag-value": "<string> [<integer>|on|off]?",
8609 "feature-type": "@stylistic|@historical-forms|@styleset|@character-variant|@swash|@ornaments|@annotation",
8610 "feature-value-block": "<feature-type> '{' <feature-value-declaration-list> '}'",
8611 "feature-value-block-list": "<feature-value-block>+",
8612 "feature-value-declaration": "<custom-ident> : <integer>+ ;",
8613 "feature-value-declaration-list": "<feature-value-declaration>",
8614 "feature-value-name": "<custom-ident>",
8615 "fill-rule": "nonzero|evenodd",
8616 "filter-function": "<blur()>|<brightness()>|<contrast()>|<drop-shadow()>|<grayscale()>|<hue-rotate()>|<invert()>|<opacity()>|<saturate()>|<sepia()>",
8617 "filter-function-list": "[<filter-function>|<url>]+",
8618 "final-bg-layer": "<'background-color'>||<bg-image>||<bg-position> [/ <bg-size>]?||<repeat-style>||<attachment>||<box>||<box>",
8619 "fit-content()": "fit-content( [<length>|<percentage>] )",
8620 "fixed-breadth": "<length-percentage>",
8621 "fixed-repeat": "repeat( [<positive-integer>] , [<line-names>? <fixed-size>]+ <line-names>? )",
8622 "fixed-size": "<fixed-breadth>|minmax( <fixed-breadth> , <track-breadth> )|minmax( <inflexible-breadth> , <fixed-breadth> )",
8623 "font-stretch-absolute": "normal|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded|<percentage>",
8624 "font-variant-css21": "[normal|small-caps]",
8625 "font-weight-absolute": "normal|bold|<number [1,1000]>",
8626 "frequency-percentage": "<frequency>|<percentage>",
8627 "general-enclosed": "[<function-token> <any-value> )]|( <ident> <any-value> )",
8628 "generic-family": "serif|sans-serif|cursive|fantasy|monospace|-apple-system",
8629 "generic-name": "serif|sans-serif|cursive|fantasy|monospace",
8630 "geometry-box": "<shape-box>|fill-box|stroke-box|view-box",
8631 "gradient": "<linear-gradient()>|<repeating-linear-gradient()>|<radial-gradient()>|<repeating-radial-gradient()>|<conic-gradient()>|<-legacy-gradient>",
8632 "grayscale()": "grayscale( <number-percentage> )",
8633 "grid-line": "auto|<custom-ident>|[<integer>&&<custom-ident>?]|[span&&[<integer>||<custom-ident>]]",
8634 "historical-lig-values": "[historical-ligatures|no-historical-ligatures]",
8635 "hsl()": "hsl( <hue> <percentage> <percentage> [/ <alpha-value>]? )|hsl( <hue> , <percentage> , <percentage> , <alpha-value>? )",
8636 "hsla()": "hsla( <hue> <percentage> <percentage> [/ <alpha-value>]? )|hsla( <hue> , <percentage> , <percentage> , <alpha-value>? )",
8637 "hue": "<number>|<angle>",
8638 "hue-rotate()": "hue-rotate( <angle> )",
8639 "image": "<url>|<image()>|<image-set()>|<element()>|<paint()>|<cross-fade()>|<gradient>",
8640 "image()": "image( <image-tags>? [<image-src>? , <color>?]! )",
8641 "image-set()": "image-set( <image-set-option># )",
8642 "image-set-option": "[<image>|<string>] <resolution>",
8643 "image-src": "<url>|<string>",
8644 "image-tags": "ltr|rtl",
8645 "inflexible-breadth": "<length>|<percentage>|min-content|max-content|auto",
8646 "inset()": "inset( <length-percentage>{1,4} [round <'border-radius'>]? )",
8647 "invert()": "invert( <number-percentage> )",
8648 "keyframes-name": "<custom-ident>|<string>",
8649 "keyframe-block": "<keyframe-selector># { <declaration-list> }",
8650 "keyframe-block-list": "<keyframe-block>+",
8651 "keyframe-selector": "from|to|<percentage>",
8652 "leader()": "leader( <leader-type> )",
8653 "leader-type": "dotted|solid|space|<string>",
8654 "length-percentage": "<length>|<percentage>",
8655 "line-names": "'[' <custom-ident>* ']'",
8656 "line-name-list": "[<line-names>|<name-repeat>]+",
8657 "line-style": "none|hidden|dotted|dashed|solid|double|groove|ridge|inset|outset",
8658 "line-width": "<length>|thin|medium|thick",
8659 "linear-color-hint": "<length-percentage>",
8660 "linear-color-stop": "<color> <color-stop-length>?",
8661 "linear-gradient()": "linear-gradient( [<angle>|to <side-or-corner>]? , <color-stop-list> )",
8662 "mask-layer": "<mask-reference>||<position> [/ <bg-size>]?||<repeat-style>||<geometry-box>||[<geometry-box>|no-clip]||<compositing-operator>||<masking-mode>",
8663 "mask-position": "[<length-percentage>|left|center|right] [<length-percentage>|top|center|bottom]?",
8664 "mask-reference": "none|<image>|<mask-source>",
8665 "mask-source": "<url>",
8666 "masking-mode": "alpha|luminance|match-source",
8667 "matrix()": "matrix( <number>#{6} )",
8668 "matrix3d()": "matrix3d( <number>#{16} )",
8669 "max()": "max( <calc-sum># )",
8670 "media-and": "<media-in-parens> [and <media-in-parens>]+",
8671 "media-condition": "<media-not>|<media-and>|<media-or>|<media-in-parens>",
8672 "media-condition-without-or": "<media-not>|<media-and>|<media-in-parens>",
8673 "media-feature": "( [<mf-plain>|<mf-boolean>|<mf-range>] )",
8674 "media-in-parens": "( <media-condition> )|<media-feature>|<general-enclosed>",
8675 "media-not": "not <media-in-parens>",
8676 "media-or": "<media-in-parens> [or <media-in-parens>]+",
8677 "media-query": "<media-condition>|[not|only]? <media-type> [and <media-condition-without-or>]?",
8678 "media-query-list": "<media-query>#",
8679 "media-type": "<ident>",
8680 "mf-boolean": "<mf-name>",
8681 "mf-name": "<ident>",
8682 "mf-plain": "<mf-name> : <mf-value>",
8683 "mf-range": "<mf-name> ['<'|'>']? '='? <mf-value>|<mf-value> ['<'|'>']? '='? <mf-name>|<mf-value> '<' '='? <mf-name> '<' '='? <mf-value>|<mf-value> '>' '='? <mf-name> '>' '='? <mf-value>",
8684 "mf-value": "<number>|<dimension>|<ident>|<ratio>",
8685 "min()": "min( <calc-sum># )",
8686 "minmax()": "minmax( [<length>|<percentage>|min-content|max-content|auto] , [<length>|<percentage>|<flex>|min-content|max-content|auto] )",
8687 "named-color": "transparent|aliceblue|antiquewhite|aqua|aquamarine|azure|beige|bisque|black|blanchedalmond|blue|blueviolet|brown|burlywood|cadetblue|chartreuse|chocolate|coral|cornflowerblue|cornsilk|crimson|cyan|darkblue|darkcyan|darkgoldenrod|darkgray|darkgreen|darkgrey|darkkhaki|darkmagenta|darkolivegreen|darkorange|darkorchid|darkred|darksalmon|darkseagreen|darkslateblue|darkslategray|darkslategrey|darkturquoise|darkviolet|deeppink|deepskyblue|dimgray|dimgrey|dodgerblue|firebrick|floralwhite|forestgreen|fuchsia|gainsboro|ghostwhite|gold|goldenrod|gray|green|greenyellow|grey|honeydew|hotpink|indianred|indigo|ivory|khaki|lavender|lavenderblush|lawngreen|lemonchiffon|lightblue|lightcoral|lightcyan|lightgoldenrodyellow|lightgray|lightgreen|lightgrey|lightpink|lightsalmon|lightseagreen|lightskyblue|lightslategray|lightslategrey|lightsteelblue|lightyellow|lime|limegreen|linen|magenta|maroon|mediumaquamarine|mediumblue|mediumorchid|mediumpurple|mediumseagreen|mediumslateblue|mediumspringgreen|mediumturquoise|mediumvioletred|midnightblue|mintcream|mistyrose|moccasin|navajowhite|navy|oldlace|olive|olivedrab|orange|orangered|orchid|palegoldenrod|palegreen|paleturquoise|palevioletred|papayawhip|peachpuff|peru|pink|plum|powderblue|purple|rebeccapurple|red|rosybrown|royalblue|saddlebrown|salmon|sandybrown|seagreen|seashell|sienna|silver|skyblue|slateblue|slategray|slategrey|snow|springgreen|steelblue|tan|teal|thistle|tomato|turquoise|violet|wheat|white|whitesmoke|yellow|yellowgreen|<-non-standard-color>",
8688 "namespace-prefix": "<ident>",
8689 "ns-prefix": "[<ident-token>|'*']? '|'",
8690 "number-percentage": "<number>|<percentage>",
8691 "numeric-figure-values": "[lining-nums|oldstyle-nums]",
8692 "numeric-fraction-values": "[diagonal-fractions|stacked-fractions]",
8693 "numeric-spacing-values": "[proportional-nums|tabular-nums]",
8694 "nth": "<an-plus-b>|even|odd",
8695 "opacity()": "opacity( [<number-percentage>] )",
8696 "overflow-position": "unsafe|safe",
8697 "outline-radius": "<length>|<percentage>",
8698 "page-body": "<declaration>? [; <page-body>]?|<page-margin-box> <page-body>",
8699 "page-margin-box": "<page-margin-box-type> '{' <declaration-list> '}'",
8700 "page-margin-box-type": "@top-left-corner|@top-left|@top-center|@top-right|@top-right-corner|@bottom-left-corner|@bottom-left|@bottom-center|@bottom-right|@bottom-right-corner|@left-top|@left-middle|@left-bottom|@right-top|@right-middle|@right-bottom",
8701 "page-selector-list": "[<page-selector>#]?",
8702 "page-selector": "<pseudo-page>+|<ident> <pseudo-page>*",
8703 "path()": "path( [<fill-rule> ,]? <string> )",
8704 "paint()": "paint( <ident> , <declaration-value>? )",
8705 "perspective()": "perspective( <length> )",
8706 "polygon()": "polygon( <fill-rule>? , [<length-percentage> <length-percentage>]# )",
8707 "position": "[[left|center|right]||[top|center|bottom]|[left|center|right|<length-percentage>] [top|center|bottom|<length-percentage>]?|[[left|right] <length-percentage>]&&[[top|bottom] <length-percentage>]]",
8708 "pseudo-class-selector": "':' <ident-token>|':' <function-token> <any-value> ')'",
8709 "pseudo-element-selector": "':' <pseudo-class-selector>",
8710 "pseudo-page": ": [left|right|first|blank]",
8711 "quote": "open-quote|close-quote|no-open-quote|no-close-quote",
8712 "radial-gradient()": "radial-gradient( [<ending-shape>||<size>]? [at <position>]? , <color-stop-list> )",
8713 "relative-selector": "<combinator>? <complex-selector>",
8714 "relative-selector-list": "<relative-selector>#",
8715 "relative-size": "larger|smaller",
8716 "repeat-style": "repeat-x|repeat-y|[repeat|space|round|no-repeat]{1,2}",
8717 "repeating-linear-gradient()": "repeating-linear-gradient( [<angle>|to <side-or-corner>]? , <color-stop-list> )",
8718 "repeating-radial-gradient()": "repeating-radial-gradient( [<ending-shape>||<size>]? [at <position>]? , <color-stop-list> )",
8719 "rgb()": "rgb( <percentage>{3} [/ <alpha-value>]? )|rgb( <number>{3} [/ <alpha-value>]? )|rgb( <percentage>#{3} , <alpha-value>? )|rgb( <number>#{3} , <alpha-value>? )",
8720 "rgba()": "rgba( <percentage>{3} [/ <alpha-value>]? )|rgba( <number>{3} [/ <alpha-value>]? )|rgba( <percentage>#{3} , <alpha-value>? )|rgba( <number>#{3} , <alpha-value>? )",
8721 "rotate()": "rotate( [<angle>|<zero>] )",
8722 "rotate3d()": "rotate3d( <number> , <number> , <number> , [<angle>|<zero>] )",
8723 "rotateX()": "rotateX( [<angle>|<zero>] )",
8724 "rotateY()": "rotateY( [<angle>|<zero>] )",
8725 "rotateZ()": "rotateZ( [<angle>|<zero>] )",
8726 "saturate()": "saturate( <number-percentage> )",
8727 "scale()": "scale( <number> , <number>? )",
8728 "scale3d()": "scale3d( <number> , <number> , <number> )",
8729 "scaleX()": "scaleX( <number> )",
8730 "scaleY()": "scaleY( <number> )",
8731 "scaleZ()": "scaleZ( <number> )",
8732 "self-position": "center|start|end|self-start|self-end|flex-start|flex-end",
8733 "shape-radius": "<length-percentage>|closest-side|farthest-side",
8734 "skew()": "skew( [<angle>|<zero>] , [<angle>|<zero>]? )",
8735 "skewX()": "skewX( [<angle>|<zero>] )",
8736 "skewY()": "skewY( [<angle>|<zero>] )",
8737 "sepia()": "sepia( <number-percentage> )",
8738 "shadow": "inset?&&<length>{2,4}&&<color>?",
8739 "shadow-t": "[<length>{2,3}&&<color>?]",
8740 "shape": "rect( <top> , <right> , <bottom> , <left> )|rect( <top> <right> <bottom> <left> )",
8741 "shape-box": "<box>|margin-box",
8742 "side-or-corner": "[left|right]||[top|bottom]",
8743 "single-animation": "<time>||<timing-function>||<time>||<single-animation-iteration-count>||<single-animation-direction>||<single-animation-fill-mode>||<single-animation-play-state>||[none|<keyframes-name>]",
8744 "single-animation-direction": "normal|reverse|alternate|alternate-reverse",
8745 "single-animation-fill-mode": "none|forwards|backwards|both",
8746 "single-animation-iteration-count": "infinite|<number>",
8747 "single-animation-play-state": "running|paused",
8748 "single-transition": "[none|<single-transition-property>]||<time>||<timing-function>||<time>",
8749 "single-transition-property": "all|<custom-ident>",
8750 "size": "closest-side|farthest-side|closest-corner|farthest-corner|<length>|<length-percentage>{2}",
8751 "step-position": "jump-start|jump-end|jump-none|jump-both|start|end",
8752 "step-timing-function": "step-start|step-end|steps( <integer> [, <step-position>]? )",
8753 "subclass-selector": "<id-selector>|<class-selector>|<attribute-selector>|<pseudo-class-selector>",
8754 "supports-condition": "not <supports-in-parens>|<supports-in-parens> [and <supports-in-parens>]*|<supports-in-parens> [or <supports-in-parens>]*",
8755 "supports-in-parens": "( <supports-condition> )|<supports-feature>|<general-enclosed>",
8756 "supports-feature": "<supports-decl>|<supports-selector-fn>",
8757 "supports-decl": "( <declaration> )",
8758 "supports-selector-fn": "selector( <complex-selector> )",
8759 "symbol": "<string>|<image>|<custom-ident>",
8760 "target": "<target-counter()>|<target-counters()>|<target-text()>",
8761 "target-counter()": "target-counter( [<string>|<url>] , <custom-ident> , <counter-style>? )",
8762 "target-counters()": "target-counters( [<string>|<url>] , <custom-ident> , <string> , <counter-style>? )",
8763 "target-text()": "target-text( [<string>|<url>] , [content|before|after|first-letter]? )",
8764 "time-percentage": "<time>|<percentage>",
8765 "timing-function": "linear|<cubic-bezier-timing-function>|<step-timing-function>",
8766 "track-breadth": "<length-percentage>|<flex>|min-content|max-content|auto",
8767 "track-list": "[<line-names>? [<track-size>|<track-repeat>]]+ <line-names>?",
8768 "track-repeat": "repeat( [<positive-integer>] , [<line-names>? <track-size>]+ <line-names>? )",
8769 "track-size": "<track-breadth>|minmax( <inflexible-breadth> , <track-breadth> )|fit-content( [<length>|<percentage>] )",
8770 "transform-function": "<matrix()>|<translate()>|<translateX()>|<translateY()>|<scale()>|<scaleX()>|<scaleY()>|<rotate()>|<skew()>|<skewX()>|<skewY()>|<matrix3d()>|<translate3d()>|<translateZ()>|<scale3d()>|<scaleZ()>|<rotate3d()>|<rotateX()>|<rotateY()>|<rotateZ()>|<perspective()>",
8771 "transform-list": "<transform-function>+",
8772 "translate()": "translate( <length-percentage> , <length-percentage>? )",
8773 "translate3d()": "translate3d( <length-percentage> , <length-percentage> , <length> )",
8774 "translateX()": "translateX( <length-percentage> )",
8775 "translateY()": "translateY( <length-percentage> )",
8776 "translateZ()": "translateZ( <length> )",
8777 "type-or-unit": "string|color|url|integer|number|length|angle|time|frequency|cap|ch|em|ex|ic|lh|rlh|rem|vb|vi|vw|vh|vmin|vmax|mm|Q|cm|in|pt|pc|px|deg|grad|rad|turn|ms|s|Hz|kHz|%",
8778 "type-selector": "<wq-name>|<ns-prefix>? '*'",
8779 "var()": "var( <custom-property-name> , <declaration-value>? )",
8780 "viewport-length": "auto|<length-percentage>",
8781 "wq-name": "<ns-prefix>? <ident-token>",
8782 "-legacy-gradient": "<-webkit-gradient()>|<-legacy-linear-gradient>|<-legacy-repeating-linear-gradient>|<-legacy-radial-gradient>|<-legacy-repeating-radial-gradient>",
8783 "-legacy-linear-gradient": "-moz-linear-gradient( <-legacy-linear-gradient-arguments> )|-webkit-linear-gradient( <-legacy-linear-gradient-arguments> )|-o-linear-gradient( <-legacy-linear-gradient-arguments> )",
8784 "-legacy-repeating-linear-gradient": "-moz-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )|-webkit-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )|-o-repeating-linear-gradient( <-legacy-linear-gradient-arguments> )",
8785 "-legacy-linear-gradient-arguments": "[<angle>|<side-or-corner>]? , <color-stop-list>",
8786 "-legacy-radial-gradient": "-moz-radial-gradient( <-legacy-radial-gradient-arguments> )|-webkit-radial-gradient( <-legacy-radial-gradient-arguments> )|-o-radial-gradient( <-legacy-radial-gradient-arguments> )",
8787 "-legacy-repeating-radial-gradient": "-moz-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )|-webkit-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )|-o-repeating-radial-gradient( <-legacy-radial-gradient-arguments> )",
8788 "-legacy-radial-gradient-arguments": "[<position> ,]? [[[<-legacy-radial-gradient-shape>||<-legacy-radial-gradient-size>]|[<length>|<percentage>]{2}] ,]? <color-stop-list>",
8789 "-legacy-radial-gradient-size": "closest-side|closest-corner|farthest-side|farthest-corner|contain|cover",
8790 "-legacy-radial-gradient-shape": "circle|ellipse",
8791 "-non-standard-font": "-apple-system-body|-apple-system-headline|-apple-system-subheadline|-apple-system-caption1|-apple-system-caption2|-apple-system-footnote|-apple-system-short-body|-apple-system-short-headline|-apple-system-short-subheadline|-apple-system-short-caption1|-apple-system-short-footnote|-apple-system-tall-body",
8792 "-non-standard-color": "-moz-ButtonDefault|-moz-ButtonHoverFace|-moz-ButtonHoverText|-moz-CellHighlight|-moz-CellHighlightText|-moz-Combobox|-moz-ComboboxText|-moz-Dialog|-moz-DialogText|-moz-dragtargetzone|-moz-EvenTreeRow|-moz-Field|-moz-FieldText|-moz-html-CellHighlight|-moz-html-CellHighlightText|-moz-mac-accentdarkestshadow|-moz-mac-accentdarkshadow|-moz-mac-accentface|-moz-mac-accentlightesthighlight|-moz-mac-accentlightshadow|-moz-mac-accentregularhighlight|-moz-mac-accentregularshadow|-moz-mac-chrome-active|-moz-mac-chrome-inactive|-moz-mac-focusring|-moz-mac-menuselect|-moz-mac-menushadow|-moz-mac-menutextselect|-moz-MenuHover|-moz-MenuHoverText|-moz-MenuBarText|-moz-MenuBarHoverText|-moz-nativehyperlinktext|-moz-OddTreeRow|-moz-win-communicationstext|-moz-win-mediatext|-moz-activehyperlinktext|-moz-default-background-color|-moz-default-color|-moz-hyperlinktext|-moz-visitedhyperlinktext|-webkit-activelink|-webkit-focus-ring-color|-webkit-link|-webkit-text",
8793 "-non-standard-image-rendering": "optimize-contrast|-moz-crisp-edges|-o-crisp-edges|-webkit-optimize-contrast",
8794 "-non-standard-overflow": "-moz-scrollbars-none|-moz-scrollbars-horizontal|-moz-scrollbars-vertical|-moz-hidden-unscrollable",
8795 "-non-standard-width": "fill-available|min-intrinsic|intrinsic|-moz-available|-moz-fit-content|-moz-min-content|-moz-max-content|-webkit-min-content|-webkit-max-content",
8796 "-webkit-gradient()": "-webkit-gradient( <-webkit-gradient-type> , <-webkit-gradient-point> [, <-webkit-gradient-point>|, <-webkit-gradient-radius> , <-webkit-gradient-point>] [, <-webkit-gradient-radius>]? [, <-webkit-gradient-color-stop>]* )",
8797 "-webkit-gradient-color-stop": "from( <color> )|color-stop( [<number-zero-one>|<percentage>] , <color> )|to( <color> )",
8798 "-webkit-gradient-point": "[left|center|right|<length-percentage>] [top|center|bottom|<length-percentage>]",
8799 "-webkit-gradient-radius": "<length>|<percentage>",
8800 "-webkit-gradient-type": "linear|radial",
8801 "-webkit-mask-box-repeat": "repeat|stretch|round",
8802 "-webkit-mask-clip-style": "border|border-box|padding|padding-box|content|content-box|text",
8803 "-ms-filter-function-list": "<-ms-filter-function>+",
8804 "-ms-filter-function": "<-ms-filter-function-progid>|<-ms-filter-function-legacy>",
8805 "-ms-filter-function-progid": "'progid:' [<ident-token> '.']* [<ident-token>|<function-token> <any-value>? )]",
8806 "-ms-filter-function-legacy": "<ident-token>|<function-token> <any-value>? )",
8807 "-ms-filter": "<string>",
8808 "age": "child|young|old",
8809 "attr-name": "<wq-name>",
8810 "attr-fallback": "<any-value>",
8811 "border-radius": "<length-percentage>{1,2}",
8812 "bottom": "<length>|auto",
8813 "generic-voice": "[<age>? <gender> <integer>?]",
8814 "gender": "male|female|neutral",
8815 "left": "<length>|auto",
8816 "mask-image": "<mask-reference>#",
8817 "name-repeat": "repeat( [<positive-integer>|auto-fill] , <line-names>+ )",
8818 "paint": "none|<color>|<url> [none|<color>]?|context-fill|context-stroke",
8819 "page-size": "A5|A4|A3|B5|B4|JIS-B5|JIS-B4|letter|legal|ledger",
8820 "ratio": "<integer> / <integer>",
8821 "right": "<length>|auto",
8822 "svg-length": "<percentage>|<length>|<number>",
8823 "svg-writing-mode": "lr-tb|rl-tb|tb-rl|lr|rl|tb",
8824 "top": "<length>|auto",
8825 "track-group": "'(' [<string>* <track-minmax> <string>*]+ ')' ['[' <positive-integer> ']']?|<track-minmax>",
8826 "track-list-v0": "[<string>* <track-group> <string>*]+|none",
8827 "track-minmax": "minmax( <track-breadth> , <track-breadth> )|auto|<track-breadth>|fit-content",
8828 "x": "<number>",
8829 "y": "<number>",
8830 "declaration": "<ident-token> : <declaration-value>? ['!' important]?",
8831 "declaration-list": "[<declaration>? ';']* <declaration>?",
8832 "url": "url( <string> <url-modifier>* )|<url-token>",
8833 "url-modifier": "<ident>|<function-token> <any-value> )",
8834 "number-zero-one": "<number [0,1]>",
8835 "number-one-or-greater": "<number [1,∞]>",
8836 "positive-integer": "<integer [0,∞]>",
8837 "-non-standard-display": "-ms-inline-flexbox|-ms-grid|-ms-inline-grid|-webkit-flex|-webkit-inline-flex|-webkit-box|-webkit-inline-box|-moz-inline-stack|-moz-box|-moz-inline-box"
8838 },
8839 "properties": {
8840 "--*": "<declaration-value>",
8841 "-ms-accelerator": "false|true",
8842 "-ms-block-progression": "tb|rl|bt|lr",
8843 "-ms-content-zoom-chaining": "none|chained",
8844 "-ms-content-zooming": "none|zoom",
8845 "-ms-content-zoom-limit": "<'-ms-content-zoom-limit-min'> <'-ms-content-zoom-limit-max'>",
8846 "-ms-content-zoom-limit-max": "<percentage>",
8847 "-ms-content-zoom-limit-min": "<percentage>",
8848 "-ms-content-zoom-snap": "<'-ms-content-zoom-snap-type'>||<'-ms-content-zoom-snap-points'>",
8849 "-ms-content-zoom-snap-points": "snapInterval( <percentage> , <percentage> )|snapList( <percentage># )",
8850 "-ms-content-zoom-snap-type": "none|proximity|mandatory",
8851 "-ms-filter": "<string>",
8852 "-ms-flow-from": "[none|<custom-ident>]#",
8853 "-ms-flow-into": "[none|<custom-ident>]#",
8854 "-ms-grid-columns": "none|<track-list>|<auto-track-list>",
8855 "-ms-grid-rows": "none|<track-list>|<auto-track-list>",
8856 "-ms-high-contrast-adjust": "auto|none",
8857 "-ms-hyphenate-limit-chars": "auto|<integer>{1,3}",
8858 "-ms-hyphenate-limit-lines": "no-limit|<integer>",
8859 "-ms-hyphenate-limit-zone": "<percentage>|<length>",
8860 "-ms-ime-align": "auto|after",
8861 "-ms-overflow-style": "auto|none|scrollbar|-ms-autohiding-scrollbar",
8862 "-ms-scrollbar-3dlight-color": "<color>",
8863 "-ms-scrollbar-arrow-color": "<color>",
8864 "-ms-scrollbar-base-color": "<color>",
8865 "-ms-scrollbar-darkshadow-color": "<color>",
8866 "-ms-scrollbar-face-color": "<color>",
8867 "-ms-scrollbar-highlight-color": "<color>",
8868 "-ms-scrollbar-shadow-color": "<color>",
8869 "-ms-scrollbar-track-color": "<color>",
8870 "-ms-scroll-chaining": "chained|none",
8871 "-ms-scroll-limit": "<'-ms-scroll-limit-x-min'> <'-ms-scroll-limit-y-min'> <'-ms-scroll-limit-x-max'> <'-ms-scroll-limit-y-max'>",
8872 "-ms-scroll-limit-x-max": "auto|<length>",
8873 "-ms-scroll-limit-x-min": "<length>",
8874 "-ms-scroll-limit-y-max": "auto|<length>",
8875 "-ms-scroll-limit-y-min": "<length>",
8876 "-ms-scroll-rails": "none|railed",
8877 "-ms-scroll-snap-points-x": "snapInterval( <length-percentage> , <length-percentage> )|snapList( <length-percentage># )",
8878 "-ms-scroll-snap-points-y": "snapInterval( <length-percentage> , <length-percentage> )|snapList( <length-percentage># )",
8879 "-ms-scroll-snap-type": "none|proximity|mandatory",
8880 "-ms-scroll-snap-x": "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-x'>",
8881 "-ms-scroll-snap-y": "<'-ms-scroll-snap-type'> <'-ms-scroll-snap-points-y'>",
8882 "-ms-scroll-translation": "none|vertical-to-horizontal",
8883 "-ms-text-autospace": "none|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space",
8884 "-ms-touch-select": "grippers|none",
8885 "-ms-user-select": "none|element|text",
8886 "-ms-wrap-flow": "auto|both|start|end|maximum|clear",
8887 "-ms-wrap-margin": "<length>",
8888 "-ms-wrap-through": "wrap|none",
8889 "-moz-appearance": "none|button|button-arrow-down|button-arrow-next|button-arrow-previous|button-arrow-up|button-bevel|button-focus|caret|checkbox|checkbox-container|checkbox-label|checkmenuitem|dualbutton|groupbox|listbox|listitem|menuarrow|menubar|menucheckbox|menuimage|menuitem|menuitemtext|menulist|menulist-button|menulist-text|menulist-textfield|menupopup|menuradio|menuseparator|meterbar|meterchunk|progressbar|progressbar-vertical|progresschunk|progresschunk-vertical|radio|radio-container|radio-label|radiomenuitem|range|range-thumb|resizer|resizerpanel|scale-horizontal|scalethumbend|scalethumb-horizontal|scalethumbstart|scalethumbtick|scalethumb-vertical|scale-vertical|scrollbarbutton-down|scrollbarbutton-left|scrollbarbutton-right|scrollbarbutton-up|scrollbarthumb-horizontal|scrollbarthumb-vertical|scrollbartrack-horizontal|scrollbartrack-vertical|searchfield|separator|sheet|spinner|spinner-downbutton|spinner-textfield|spinner-upbutton|splitter|statusbar|statusbarpanel|tab|tabpanel|tabpanels|tab-scroll-arrow-back|tab-scroll-arrow-forward|textfield|textfield-multiline|toolbar|toolbarbutton|toolbarbutton-dropdown|toolbargripper|toolbox|tooltip|treeheader|treeheadercell|treeheadersortarrow|treeitem|treeline|treetwisty|treetwistyopen|treeview|-moz-mac-unified-toolbar|-moz-win-borderless-glass|-moz-win-browsertabbar-toolbox|-moz-win-communicationstext|-moz-win-communications-toolbox|-moz-win-exclude-glass|-moz-win-glass|-moz-win-mediatext|-moz-win-media-toolbox|-moz-window-button-box|-moz-window-button-box-maximized|-moz-window-button-close|-moz-window-button-maximize|-moz-window-button-minimize|-moz-window-button-restore|-moz-window-frame-bottom|-moz-window-frame-left|-moz-window-frame-right|-moz-window-titlebar|-moz-window-titlebar-maximized",
8890 "-moz-binding": "<url>|none",
8891 "-moz-border-bottom-colors": "<color>+|none",
8892 "-moz-border-left-colors": "<color>+|none",
8893 "-moz-border-right-colors": "<color>+|none",
8894 "-moz-border-top-colors": "<color>+|none",
8895 "-moz-context-properties": "none|[fill|fill-opacity|stroke|stroke-opacity]#",
8896 "-moz-float-edge": "border-box|content-box|margin-box|padding-box",
8897 "-moz-force-broken-image-icon": "<integer [0,1]>",
8898 "-moz-image-region": "<shape>|auto",
8899 "-moz-orient": "inline|block|horizontal|vertical",
8900 "-moz-outline-radius": "<outline-radius>{1,4} [/ <outline-radius>{1,4}]?",
8901 "-moz-outline-radius-bottomleft": "<outline-radius>",
8902 "-moz-outline-radius-bottomright": "<outline-radius>",
8903 "-moz-outline-radius-topleft": "<outline-radius>",
8904 "-moz-outline-radius-topright": "<outline-radius>",
8905 "-moz-stack-sizing": "ignore|stretch-to-fit",
8906 "-moz-text-blink": "none|blink",
8907 "-moz-user-focus": "ignore|normal|select-after|select-before|select-menu|select-same|select-all|none",
8908 "-moz-user-input": "auto|none|enabled|disabled",
8909 "-moz-user-modify": "read-only|read-write|write-only",
8910 "-moz-window-dragging": "drag|no-drag",
8911 "-moz-window-shadow": "default|menu|tooltip|sheet|none",
8912 "-webkit-appearance": "none|button|button-bevel|caps-lock-indicator|caret|checkbox|default-button|inner-spin-button|listbox|listitem|media-controls-background|media-controls-fullscreen-background|media-current-time-display|media-enter-fullscreen-button|media-exit-fullscreen-button|media-fullscreen-button|media-mute-button|media-overlay-play-button|media-play-button|media-seek-back-button|media-seek-forward-button|media-slider|media-sliderthumb|media-time-remaining-display|media-toggle-closed-captions-button|media-volume-slider|media-volume-slider-container|media-volume-sliderthumb|menulist|menulist-button|menulist-text|menulist-textfield|meter|progress-bar|progress-bar-value|push-button|radio|scrollbarbutton-down|scrollbarbutton-left|scrollbarbutton-right|scrollbarbutton-up|scrollbargripper-horizontal|scrollbargripper-vertical|scrollbarthumb-horizontal|scrollbarthumb-vertical|scrollbartrack-horizontal|scrollbartrack-vertical|searchfield|searchfield-cancel-button|searchfield-decoration|searchfield-results-button|searchfield-results-decoration|slider-horizontal|slider-vertical|sliderthumb-horizontal|sliderthumb-vertical|square-button|textarea|textfield|-apple-pay-button",
8913 "-webkit-border-before": "<'border-width'>||<'border-style'>||<'color'>",
8914 "-webkit-border-before-color": "<'color'>",
8915 "-webkit-border-before-style": "<'border-style'>",
8916 "-webkit-border-before-width": "<'border-width'>",
8917 "-webkit-box-reflect": "[above|below|right|left]? <length>? <image>?",
8918 "-webkit-line-clamp": "none|<integer>",
8919 "-webkit-mask": "[<mask-reference>||<position> [/ <bg-size>]?||<repeat-style>||[<box>|border|padding|content|text]||[<box>|border|padding|content]]#",
8920 "-webkit-mask-attachment": "<attachment>#",
8921 "-webkit-mask-clip": "[<box>|border|padding|content|text]#",
8922 "-webkit-mask-composite": "<composite-style>#",
8923 "-webkit-mask-image": "<mask-reference>#",
8924 "-webkit-mask-origin": "[<box>|border|padding|content]#",
8925 "-webkit-mask-position": "<position>#",
8926 "-webkit-mask-position-x": "[<length-percentage>|left|center|right]#",
8927 "-webkit-mask-position-y": "[<length-percentage>|top|center|bottom]#",
8928 "-webkit-mask-repeat": "<repeat-style>#",
8929 "-webkit-mask-repeat-x": "repeat|no-repeat|space|round",
8930 "-webkit-mask-repeat-y": "repeat|no-repeat|space|round",
8931 "-webkit-mask-size": "<bg-size>#",
8932 "-webkit-overflow-scrolling": "auto|touch",
8933 "-webkit-tap-highlight-color": "<color>",
8934 "-webkit-text-fill-color": "<color>",
8935 "-webkit-text-stroke": "<length>||<color>",
8936 "-webkit-text-stroke-color": "<color>",
8937 "-webkit-text-stroke-width": "<length>",
8938 "-webkit-touch-callout": "default|none",
8939 "-webkit-user-modify": "read-only|read-write|read-write-plaintext-only",
8940 "align-content": "normal|<baseline-position>|<content-distribution>|<overflow-position>? <content-position>",
8941 "align-items": "normal|stretch|<baseline-position>|[<overflow-position>? <self-position>]",
8942 "align-self": "auto|normal|stretch|<baseline-position>|<overflow-position>? <self-position>",
8943 "align-tracks": "[normal|<baseline-position>|<content-distribution>|<overflow-position>? <content-position>]#",
8944 "all": "initial|inherit|unset|revert",
8945 "animation": "<single-animation>#",
8946 "animation-delay": "<time>#",
8947 "animation-direction": "<single-animation-direction>#",
8948 "animation-duration": "<time>#",
8949 "animation-fill-mode": "<single-animation-fill-mode>#",
8950 "animation-iteration-count": "<single-animation-iteration-count>#",
8951 "animation-name": "[none|<keyframes-name>]#",
8952 "animation-play-state": "<single-animation-play-state>#",
8953 "animation-timing-function": "<timing-function>#",
8954 "appearance": "none|auto|textfield|menulist-button|<compat-auto>",
8955 "aspect-ratio": "auto|<ratio>",
8956 "azimuth": "<angle>|[[left-side|far-left|left|center-left|center|center-right|right|far-right|right-side]||behind]|leftwards|rightwards",
8957 "backdrop-filter": "none|<filter-function-list>",
8958 "backface-visibility": "visible|hidden",
8959 "background": "[<bg-layer> ,]* <final-bg-layer>",
8960 "background-attachment": "<attachment>#",
8961 "background-blend-mode": "<blend-mode>#",
8962 "background-clip": "<box>#",
8963 "background-color": "<color>",
8964 "background-image": "<bg-image>#",
8965 "background-origin": "<box>#",
8966 "background-position": "<bg-position>#",
8967 "background-position-x": "[center|[[left|right|x-start|x-end]? <length-percentage>?]!]#",
8968 "background-position-y": "[center|[[top|bottom|y-start|y-end]? <length-percentage>?]!]#",
8969 "background-repeat": "<repeat-style>#",
8970 "background-size": "<bg-size>#",
8971 "block-overflow": "clip|ellipsis|<string>",
8972 "block-size": "<'width'>",
8973 "border": "<line-width>||<line-style>||<color>",
8974 "border-block": "<'border-top-width'>||<'border-top-style'>||<'color'>",
8975 "border-block-color": "<'border-top-color'>{1,2}",
8976 "border-block-style": "<'border-top-style'>",
8977 "border-block-width": "<'border-top-width'>",
8978 "border-block-end": "<'border-top-width'>||<'border-top-style'>||<'color'>",
8979 "border-block-end-color": "<'border-top-color'>",
8980 "border-block-end-style": "<'border-top-style'>",
8981 "border-block-end-width": "<'border-top-width'>",
8982 "border-block-start": "<'border-top-width'>||<'border-top-style'>||<'color'>",
8983 "border-block-start-color": "<'border-top-color'>",
8984 "border-block-start-style": "<'border-top-style'>",
8985 "border-block-start-width": "<'border-top-width'>",
8986 "border-bottom": "<line-width>||<line-style>||<color>",
8987 "border-bottom-color": "<'border-top-color'>",
8988 "border-bottom-left-radius": "<length-percentage>{1,2}",
8989 "border-bottom-right-radius": "<length-percentage>{1,2}",
8990 "border-bottom-style": "<line-style>",
8991 "border-bottom-width": "<line-width>",
8992 "border-collapse": "collapse|separate",
8993 "border-color": "<color>{1,4}",
8994 "border-end-end-radius": "<length-percentage>{1,2}",
8995 "border-end-start-radius": "<length-percentage>{1,2}",
8996 "border-image": "<'border-image-source'>||<'border-image-slice'> [/ <'border-image-width'>|/ <'border-image-width'>? / <'border-image-outset'>]?||<'border-image-repeat'>",
8997 "border-image-outset": "[<length>|<number>]{1,4}",
8998 "border-image-repeat": "[stretch|repeat|round|space]{1,2}",
8999 "border-image-slice": "<number-percentage>{1,4}&&fill?",
9000 "border-image-source": "none|<image>",
9001 "border-image-width": "[<length-percentage>|<number>|auto]{1,4}",
9002 "border-inline": "<'border-top-width'>||<'border-top-style'>||<'color'>",
9003 "border-inline-end": "<'border-top-width'>||<'border-top-style'>||<'color'>",
9004 "border-inline-color": "<'border-top-color'>{1,2}",
9005 "border-inline-style": "<'border-top-style'>",
9006 "border-inline-width": "<'border-top-width'>",
9007 "border-inline-end-color": "<'border-top-color'>",
9008 "border-inline-end-style": "<'border-top-style'>",
9009 "border-inline-end-width": "<'border-top-width'>",
9010 "border-inline-start": "<'border-top-width'>||<'border-top-style'>||<'color'>",
9011 "border-inline-start-color": "<'border-top-color'>",
9012 "border-inline-start-style": "<'border-top-style'>",
9013 "border-inline-start-width": "<'border-top-width'>",
9014 "border-left": "<line-width>||<line-style>||<color>",
9015 "border-left-color": "<color>",
9016 "border-left-style": "<line-style>",
9017 "border-left-width": "<line-width>",
9018 "border-radius": "<length-percentage>{1,4} [/ <length-percentage>{1,4}]?",
9019 "border-right": "<line-width>||<line-style>||<color>",
9020 "border-right-color": "<color>",
9021 "border-right-style": "<line-style>",
9022 "border-right-width": "<line-width>",
9023 "border-spacing": "<length> <length>?",
9024 "border-start-end-radius": "<length-percentage>{1,2}",
9025 "border-start-start-radius": "<length-percentage>{1,2}",
9026 "border-style": "<line-style>{1,4}",
9027 "border-top": "<line-width>||<line-style>||<color>",
9028 "border-top-color": "<color>",
9029 "border-top-left-radius": "<length-percentage>{1,2}",
9030 "border-top-right-radius": "<length-percentage>{1,2}",
9031 "border-top-style": "<line-style>",
9032 "border-top-width": "<line-width>",
9033 "border-width": "<line-width>{1,4}",
9034 "bottom": "<length>|<percentage>|auto",
9035 "box-align": "start|center|end|baseline|stretch",
9036 "box-decoration-break": "slice|clone",
9037 "box-direction": "normal|reverse|inherit",
9038 "box-flex": "<number>",
9039 "box-flex-group": "<integer>",
9040 "box-lines": "single|multiple",
9041 "box-ordinal-group": "<integer>",
9042 "box-orient": "horizontal|vertical|inline-axis|block-axis|inherit",
9043 "box-pack": "start|center|end|justify",
9044 "box-shadow": "none|<shadow>#",
9045 "box-sizing": "content-box|border-box",
9046 "break-after": "auto|avoid|always|all|avoid-page|page|left|right|recto|verso|avoid-column|column|avoid-region|region",
9047 "break-before": "auto|avoid|always|all|avoid-page|page|left|right|recto|verso|avoid-column|column|avoid-region|region",
9048 "break-inside": "auto|avoid|avoid-page|avoid-column|avoid-region",
9049 "caption-side": "top|bottom|block-start|block-end|inline-start|inline-end",
9050 "caret-color": "auto|<color>",
9051 "clear": "none|left|right|both|inline-start|inline-end",
9052 "clip": "<shape>|auto",
9053 "clip-path": "<clip-source>|[<basic-shape>||<geometry-box>]|none",
9054 "color": "<color>",
9055 "color-adjust": "economy|exact",
9056 "column-count": "<integer>|auto",
9057 "column-fill": "auto|balance|balance-all",
9058 "column-gap": "normal|<length-percentage>",
9059 "column-rule": "<'column-rule-width'>||<'column-rule-style'>||<'column-rule-color'>",
9060 "column-rule-color": "<color>",
9061 "column-rule-style": "<'border-style'>",
9062 "column-rule-width": "<'border-width'>",
9063 "column-span": "none|all",
9064 "column-width": "<length>|auto",
9065 "columns": "<'column-width'>||<'column-count'>",
9066 "contain": "none|strict|content|[size||layout||style||paint]",
9067 "content": "normal|none|[<content-replacement>|<content-list>] [/ <string>]?",
9068 "counter-increment": "[<custom-ident> <integer>?]+|none",
9069 "counter-reset": "[<custom-ident> <integer>?]+|none",
9070 "counter-set": "[<custom-ident> <integer>?]+|none",
9071 "cursor": "[[<url> [<x> <y>]? ,]* [auto|default|none|context-menu|help|pointer|progress|wait|cell|crosshair|text|vertical-text|alias|copy|move|no-drop|not-allowed|e-resize|n-resize|ne-resize|nw-resize|s-resize|se-resize|sw-resize|w-resize|ew-resize|ns-resize|nesw-resize|nwse-resize|col-resize|row-resize|all-scroll|zoom-in|zoom-out|grab|grabbing|hand|-webkit-grab|-webkit-grabbing|-webkit-zoom-in|-webkit-zoom-out|-moz-grab|-moz-grabbing|-moz-zoom-in|-moz-zoom-out]]",
9072 "direction": "ltr|rtl",
9073 "display": "[<display-outside>||<display-inside>]|<display-listitem>|<display-internal>|<display-box>|<display-legacy>|<-non-standard-display>",
9074 "empty-cells": "show|hide",
9075 "filter": "none|<filter-function-list>|<-ms-filter-function-list>",
9076 "flex": "none|[<'flex-grow'> <'flex-shrink'>?||<'flex-basis'>]",
9077 "flex-basis": "content|<'width'>",
9078 "flex-direction": "row|row-reverse|column|column-reverse",
9079 "flex-flow": "<'flex-direction'>||<'flex-wrap'>",
9080 "flex-grow": "<number>",
9081 "flex-shrink": "<number>",
9082 "flex-wrap": "nowrap|wrap|wrap-reverse",
9083 "float": "left|right|none|inline-start|inline-end",
9084 "font": "[[<'font-style'>||<font-variant-css21>||<'font-weight'>||<'font-stretch'>]? <'font-size'> [/ <'line-height'>]? <'font-family'>]|caption|icon|menu|message-box|small-caption|status-bar",
9085 "font-family": "[<family-name>|<generic-family>]#",
9086 "font-feature-settings": "normal|<feature-tag-value>#",
9087 "font-kerning": "auto|normal|none",
9088 "font-language-override": "normal|<string>",
9089 "font-optical-sizing": "auto|none",
9090 "font-variation-settings": "normal|[<string> <number>]#",
9091 "font-size": "<absolute-size>|<relative-size>|<length-percentage>",
9092 "font-size-adjust": "none|<number>",
9093 "font-smooth": "auto|never|always|<absolute-size>|<length>",
9094 "font-stretch": "<font-stretch-absolute>",
9095 "font-style": "normal|italic|oblique <angle>?",
9096 "font-synthesis": "none|[weight||style]",
9097 "font-variant": "normal|none|[<common-lig-values>||<discretionary-lig-values>||<historical-lig-values>||<contextual-alt-values>||stylistic( <feature-value-name> )||historical-forms||styleset( <feature-value-name># )||character-variant( <feature-value-name># )||swash( <feature-value-name> )||ornaments( <feature-value-name> )||annotation( <feature-value-name> )||[small-caps|all-small-caps|petite-caps|all-petite-caps|unicase|titling-caps]||<numeric-figure-values>||<numeric-spacing-values>||<numeric-fraction-values>||ordinal||slashed-zero||<east-asian-variant-values>||<east-asian-width-values>||ruby]",
9098 "font-variant-alternates": "normal|[stylistic( <feature-value-name> )||historical-forms||styleset( <feature-value-name># )||character-variant( <feature-value-name># )||swash( <feature-value-name> )||ornaments( <feature-value-name> )||annotation( <feature-value-name> )]",
9099 "font-variant-caps": "normal|small-caps|all-small-caps|petite-caps|all-petite-caps|unicase|titling-caps",
9100 "font-variant-east-asian": "normal|[<east-asian-variant-values>||<east-asian-width-values>||ruby]",
9101 "font-variant-ligatures": "normal|none|[<common-lig-values>||<discretionary-lig-values>||<historical-lig-values>||<contextual-alt-values>]",
9102 "font-variant-numeric": "normal|[<numeric-figure-values>||<numeric-spacing-values>||<numeric-fraction-values>||ordinal||slashed-zero]",
9103 "font-variant-position": "normal|sub|super",
9104 "font-weight": "<font-weight-absolute>|bolder|lighter",
9105 "gap": "<'row-gap'> <'column-gap'>?",
9106 "grid": "<'grid-template'>|<'grid-template-rows'> / [auto-flow&&dense?] <'grid-auto-columns'>?|[auto-flow&&dense?] <'grid-auto-rows'>? / <'grid-template-columns'>",
9107 "grid-area": "<grid-line> [/ <grid-line>]{0,3}",
9108 "grid-auto-columns": "<track-size>+",
9109 "grid-auto-flow": "[row|column]||dense",
9110 "grid-auto-rows": "<track-size>+",
9111 "grid-column": "<grid-line> [/ <grid-line>]?",
9112 "grid-column-end": "<grid-line>",
9113 "grid-column-gap": "<length-percentage>",
9114 "grid-column-start": "<grid-line>",
9115 "grid-gap": "<'grid-row-gap'> <'grid-column-gap'>?",
9116 "grid-row": "<grid-line> [/ <grid-line>]?",
9117 "grid-row-end": "<grid-line>",
9118 "grid-row-gap": "<length-percentage>",
9119 "grid-row-start": "<grid-line>",
9120 "grid-template": "none|[<'grid-template-rows'> / <'grid-template-columns'>]|[<line-names>? <string> <track-size>? <line-names>?]+ [/ <explicit-track-list>]?",
9121 "grid-template-areas": "none|<string>+",
9122 "grid-template-columns": "none|<track-list>|<auto-track-list>|subgrid <line-name-list>?",
9123 "grid-template-rows": "none|<track-list>|<auto-track-list>|subgrid <line-name-list>?",
9124 "hanging-punctuation": "none|[first||[force-end|allow-end]||last]",
9125 "height": "auto|<length>|<percentage>|min-content|max-content|fit-content( <length-percentage> )",
9126 "hyphens": "none|manual|auto",
9127 "image-orientation": "from-image|<angle>|[<angle>? flip]",
9128 "image-rendering": "auto|crisp-edges|pixelated|optimizeSpeed|optimizeQuality|<-non-standard-image-rendering>",
9129 "image-resolution": "[from-image||<resolution>]&&snap?",
9130 "ime-mode": "auto|normal|active|inactive|disabled",
9131 "initial-letter": "normal|[<number> <integer>?]",
9132 "initial-letter-align": "[auto|alphabetic|hanging|ideographic]",
9133 "inline-size": "<'width'>",
9134 "inset": "<'top'>{1,4}",
9135 "inset-block": "<'top'>{1,2}",
9136 "inset-block-end": "<'top'>",
9137 "inset-block-start": "<'top'>",
9138 "inset-inline": "<'top'>{1,2}",
9139 "inset-inline-end": "<'top'>",
9140 "inset-inline-start": "<'top'>",
9141 "isolation": "auto|isolate",
9142 "justify-content": "normal|<content-distribution>|<overflow-position>? [<content-position>|left|right]",
9143 "justify-items": "normal|stretch|<baseline-position>|<overflow-position>? [<self-position>|left|right]|legacy|legacy&&[left|right|center]",
9144 "justify-self": "auto|normal|stretch|<baseline-position>|<overflow-position>? [<self-position>|left|right]",
9145 "justify-tracks": "[normal|<content-distribution>|<overflow-position>? [<content-position>|left|right]]#",
9146 "left": "<length>|<percentage>|auto",
9147 "letter-spacing": "normal|<length-percentage>",
9148 "line-break": "auto|loose|normal|strict|anywhere",
9149 "line-clamp": "none|<integer>",
9150 "line-height": "normal|<number>|<length>|<percentage>",
9151 "line-height-step": "<length>",
9152 "list-style": "<'list-style-type'>||<'list-style-position'>||<'list-style-image'>",
9153 "list-style-image": "<url>|none",
9154 "list-style-position": "inside|outside",
9155 "list-style-type": "<counter-style>|<string>|none",
9156 "margin": "[<length>|<percentage>|auto]{1,4}",
9157 "margin-block": "<'margin-left'>{1,2}",
9158 "margin-block-end": "<'margin-left'>",
9159 "margin-block-start": "<'margin-left'>",
9160 "margin-bottom": "<length>|<percentage>|auto",
9161 "margin-inline": "<'margin-left'>{1,2}",
9162 "margin-inline-end": "<'margin-left'>",
9163 "margin-inline-start": "<'margin-left'>",
9164 "margin-left": "<length>|<percentage>|auto",
9165 "margin-right": "<length>|<percentage>|auto",
9166 "margin-top": "<length>|<percentage>|auto",
9167 "margin-trim": "none|in-flow|all",
9168 "mask": "<mask-layer>#",
9169 "mask-border": "<'mask-border-source'>||<'mask-border-slice'> [/ <'mask-border-width'>? [/ <'mask-border-outset'>]?]?||<'mask-border-repeat'>||<'mask-border-mode'>",
9170 "mask-border-mode": "luminance|alpha",
9171 "mask-border-outset": "[<length>|<number>]{1,4}",
9172 "mask-border-repeat": "[stretch|repeat|round|space]{1,2}",
9173 "mask-border-slice": "<number-percentage>{1,4} fill?",
9174 "mask-border-source": "none|<image>",
9175 "mask-border-width": "[<length-percentage>|<number>|auto]{1,4}",
9176 "mask-clip": "[<geometry-box>|no-clip]#",
9177 "mask-composite": "<compositing-operator>#",
9178 "mask-image": "<mask-reference>#",
9179 "mask-mode": "<masking-mode>#",
9180 "mask-origin": "<geometry-box>#",
9181 "mask-position": "<position>#",
9182 "mask-repeat": "<repeat-style>#",
9183 "mask-size": "<bg-size>#",
9184 "mask-type": "luminance|alpha",
9185 "masonry-auto-flow": "[pack|next]||[definite-first|ordered]",
9186 "math-style": "normal|compact",
9187 "max-block-size": "<'max-width'>",
9188 "max-height": "none|<length-percentage>|min-content|max-content|fit-content( <length-percentage> )",
9189 "max-inline-size": "<'max-width'>",
9190 "max-lines": "none|<integer>",
9191 "max-width": "none|<length-percentage>|min-content|max-content|fit-content( <length-percentage> )|<-non-standard-width>",
9192 "min-block-size": "<'min-width'>",
9193 "min-height": "auto|<length>|<percentage>|min-content|max-content|fit-content( <length-percentage> )",
9194 "min-inline-size": "<'min-width'>",
9195 "min-width": "auto|<length-percentage>|min-content|max-content|fit-content( <length-percentage> )|<-non-standard-width>",
9196 "mix-blend-mode": "<blend-mode>",
9197 "object-fit": "fill|contain|cover|none|scale-down",
9198 "object-position": "<position>",
9199 "offset": "[<'offset-position'>? [<'offset-path'> [<'offset-distance'>||<'offset-rotate'>]?]?]! [/ <'offset-anchor'>]?",
9200 "offset-anchor": "auto|<position>",
9201 "offset-distance": "<length-percentage>",
9202 "offset-path": "none|ray( [<angle>&&<size>&&contain?] )|<path()>|<url>|[<basic-shape>||<geometry-box>]",
9203 "offset-position": "auto|<position>",
9204 "offset-rotate": "[auto|reverse]||<angle>",
9205 "opacity": "<alpha-value>",
9206 "order": "<integer>",
9207 "orphans": "<integer>",
9208 "outline": "[<'outline-color'>||<'outline-style'>||<'outline-width'>]",
9209 "outline-color": "<color>|invert",
9210 "outline-offset": "<length>",
9211 "outline-style": "auto|<'border-style'>",
9212 "outline-width": "<line-width>",
9213 "overflow": "[visible|hidden|clip|scroll|auto]{1,2}|<-non-standard-overflow>",
9214 "overflow-anchor": "auto|none",
9215 "overflow-block": "visible|hidden|clip|scroll|auto",
9216 "overflow-clip-box": "padding-box|content-box",
9217 "overflow-inline": "visible|hidden|clip|scroll|auto",
9218 "overflow-wrap": "normal|break-word|anywhere",
9219 "overflow-x": "visible|hidden|clip|scroll|auto",
9220 "overflow-y": "visible|hidden|clip|scroll|auto",
9221 "overscroll-behavior": "[contain|none|auto]{1,2}",
9222 "overscroll-behavior-block": "contain|none|auto",
9223 "overscroll-behavior-inline": "contain|none|auto",
9224 "overscroll-behavior-x": "contain|none|auto",
9225 "overscroll-behavior-y": "contain|none|auto",
9226 "padding": "[<length>|<percentage>]{1,4}",
9227 "padding-block": "<'padding-left'>{1,2}",
9228 "padding-block-end": "<'padding-left'>",
9229 "padding-block-start": "<'padding-left'>",
9230 "padding-bottom": "<length>|<percentage>",
9231 "padding-inline": "<'padding-left'>{1,2}",
9232 "padding-inline-end": "<'padding-left'>",
9233 "padding-inline-start": "<'padding-left'>",
9234 "padding-left": "<length>|<percentage>",
9235 "padding-right": "<length>|<percentage>",
9236 "padding-top": "<length>|<percentage>",
9237 "page-break-after": "auto|always|avoid|left|right|recto|verso",
9238 "page-break-before": "auto|always|avoid|left|right|recto|verso",
9239 "page-break-inside": "auto|avoid",
9240 "paint-order": "normal|[fill||stroke||markers]",
9241 "perspective": "none|<length>",
9242 "perspective-origin": "<position>",
9243 "place-content": "<'align-content'> <'justify-content'>?",
9244 "place-items": "<'align-items'> <'justify-items'>?",
9245 "place-self": "<'align-self'> <'justify-self'>?",
9246 "pointer-events": "auto|none|visiblePainted|visibleFill|visibleStroke|visible|painted|fill|stroke|all|inherit",
9247 "position": "static|relative|absolute|sticky|fixed|-webkit-sticky",
9248 "quotes": "none|auto|[<string> <string>]+",
9249 "resize": "none|both|horizontal|vertical|block|inline",
9250 "right": "<length>|<percentage>|auto",
9251 "rotate": "none|<angle>|[x|y|z|<number>{3}]&&<angle>",
9252 "row-gap": "normal|<length-percentage>",
9253 "ruby-align": "start|center|space-between|space-around",
9254 "ruby-merge": "separate|collapse|auto",
9255 "ruby-position": "over|under|inter-character",
9256 "scale": "none|<number>{1,3}",
9257 "scrollbar-color": "auto|dark|light|<color>{2}",
9258 "scrollbar-gutter": "auto|[stable|always]&&both?&&force?",
9259 "scrollbar-width": "auto|thin|none",
9260 "scroll-behavior": "auto|smooth",
9261 "scroll-margin": "<length>{1,4}",
9262 "scroll-margin-block": "<length>{1,2}",
9263 "scroll-margin-block-start": "<length>",
9264 "scroll-margin-block-end": "<length>",
9265 "scroll-margin-bottom": "<length>",
9266 "scroll-margin-inline": "<length>{1,2}",
9267 "scroll-margin-inline-start": "<length>",
9268 "scroll-margin-inline-end": "<length>",
9269 "scroll-margin-left": "<length>",
9270 "scroll-margin-right": "<length>",
9271 "scroll-margin-top": "<length>",
9272 "scroll-padding": "[auto|<length-percentage>]{1,4}",
9273 "scroll-padding-block": "[auto|<length-percentage>]{1,2}",
9274 "scroll-padding-block-start": "auto|<length-percentage>",
9275 "scroll-padding-block-end": "auto|<length-percentage>",
9276 "scroll-padding-bottom": "auto|<length-percentage>",
9277 "scroll-padding-inline": "[auto|<length-percentage>]{1,2}",
9278 "scroll-padding-inline-start": "auto|<length-percentage>",
9279 "scroll-padding-inline-end": "auto|<length-percentage>",
9280 "scroll-padding-left": "auto|<length-percentage>",
9281 "scroll-padding-right": "auto|<length-percentage>",
9282 "scroll-padding-top": "auto|<length-percentage>",
9283 "scroll-snap-align": "[none|start|end|center]{1,2}",
9284 "scroll-snap-coordinate": "none|<position>#",
9285 "scroll-snap-destination": "<position>",
9286 "scroll-snap-points-x": "none|repeat( <length-percentage> )",
9287 "scroll-snap-points-y": "none|repeat( <length-percentage> )",
9288 "scroll-snap-stop": "normal|always",
9289 "scroll-snap-type": "none|[x|y|block|inline|both] [mandatory|proximity]?",
9290 "scroll-snap-type-x": "none|mandatory|proximity",
9291 "scroll-snap-type-y": "none|mandatory|proximity",
9292 "shape-image-threshold": "<alpha-value>",
9293 "shape-margin": "<length-percentage>",
9294 "shape-outside": "none|<shape-box>||<basic-shape>|<image>",
9295 "tab-size": "<integer>|<length>",
9296 "table-layout": "auto|fixed",
9297 "text-align": "start|end|left|right|center|justify|match-parent",
9298 "text-align-last": "auto|start|end|left|right|center|justify",
9299 "text-combine-upright": "none|all|[digits <integer>?]",
9300 "text-decoration": "<'text-decoration-line'>||<'text-decoration-style'>||<'text-decoration-color'>||<'text-decoration-thickness'>",
9301 "text-decoration-color": "<color>",
9302 "text-decoration-line": "none|[underline||overline||line-through||blink]|spelling-error|grammar-error",
9303 "text-decoration-skip": "none|[objects||[spaces|[leading-spaces||trailing-spaces]]||edges||box-decoration]",
9304 "text-decoration-skip-ink": "auto|all|none",
9305 "text-decoration-style": "solid|double|dotted|dashed|wavy",
9306 "text-decoration-thickness": "auto|from-font|<length>|<percentage>",
9307 "text-emphasis": "<'text-emphasis-style'>||<'text-emphasis-color'>",
9308 "text-emphasis-color": "<color>",
9309 "text-emphasis-position": "[over|under]&&[right|left]",
9310 "text-emphasis-style": "none|[[filled|open]||[dot|circle|double-circle|triangle|sesame]]|<string>",
9311 "text-indent": "<length-percentage>&&hanging?&&each-line?",
9312 "text-justify": "auto|inter-character|inter-word|none",
9313 "text-orientation": "mixed|upright|sideways",
9314 "text-overflow": "[clip|ellipsis|<string>]{1,2}",
9315 "text-rendering": "auto|optimizeSpeed|optimizeLegibility|geometricPrecision",
9316 "text-shadow": "none|<shadow-t>#",
9317 "text-size-adjust": "none|auto|<percentage>",
9318 "text-transform": "none|capitalize|uppercase|lowercase|full-width|full-size-kana",
9319 "text-underline-offset": "auto|<length>|<percentage>",
9320 "text-underline-position": "auto|from-font|[under||[left|right]]",
9321 "top": "<length>|<percentage>|auto",
9322 "touch-action": "auto|none|[[pan-x|pan-left|pan-right]||[pan-y|pan-up|pan-down]||pinch-zoom]|manipulation",
9323 "transform": "none|<transform-list>",
9324 "transform-box": "content-box|border-box|fill-box|stroke-box|view-box",
9325 "transform-origin": "[<length-percentage>|left|center|right|top|bottom]|[[<length-percentage>|left|center|right]&&[<length-percentage>|top|center|bottom]] <length>?",
9326 "transform-style": "flat|preserve-3d",
9327 "transition": "<single-transition>#",
9328 "transition-delay": "<time>#",
9329 "transition-duration": "<time>#",
9330 "transition-property": "none|<single-transition-property>#",
9331 "transition-timing-function": "<timing-function>#",
9332 "translate": "none|<length-percentage> [<length-percentage> <length>?]?",
9333 "unicode-bidi": "normal|embed|isolate|bidi-override|isolate-override|plaintext|-moz-isolate|-moz-isolate-override|-moz-plaintext|-webkit-isolate|-webkit-isolate-override|-webkit-plaintext",
9334 "user-select": "auto|text|none|contain|all",
9335 "vertical-align": "baseline|sub|super|text-top|text-bottom|middle|top|bottom|<percentage>|<length>",
9336 "visibility": "visible|hidden|collapse",
9337 "white-space": "normal|pre|nowrap|pre-wrap|pre-line|break-spaces",
9338 "widows": "<integer>",
9339 "width": "auto|<length>|<percentage>|min-content|max-content|fit-content( <length-percentage> )|fit-content|-moz-fit-content|-webkit-fit-content",
9340 "will-change": "auto|<animateable-feature>#",
9341 "word-break": "normal|break-all|keep-all|break-word",
9342 "word-spacing": "normal|<length-percentage>",
9343 "word-wrap": "normal|break-word",
9344 "writing-mode": "horizontal-tb|vertical-rl|vertical-lr|sideways-rl|sideways-lr|<svg-writing-mode>",
9345 "z-index": "auto|<integer>",
9346 "zoom": "normal|reset|<number>|<percentage>",
9347 "-moz-background-clip": "padding|border",
9348 "-moz-border-radius-bottomleft": "<'border-bottom-left-radius'>",
9349 "-moz-border-radius-bottomright": "<'border-bottom-right-radius'>",
9350 "-moz-border-radius-topleft": "<'border-top-left-radius'>",
9351 "-moz-border-radius-topright": "<'border-bottom-right-radius'>",
9352 "-moz-control-character-visibility": "visible|hidden",
9353 "-moz-osx-font-smoothing": "auto|grayscale",
9354 "-moz-user-select": "none|text|all|-moz-none",
9355 "-ms-flex-align": "start|end|center|baseline|stretch",
9356 "-ms-flex-item-align": "auto|start|end|center|baseline|stretch",
9357 "-ms-flex-line-pack": "start|end|center|justify|distribute|stretch",
9358 "-ms-flex-negative": "<'flex-shrink'>",
9359 "-ms-flex-pack": "start|end|center|justify|distribute",
9360 "-ms-flex-order": "<integer>",
9361 "-ms-flex-positive": "<'flex-grow'>",
9362 "-ms-flex-preferred-size": "<'flex-basis'>",
9363 "-ms-interpolation-mode": "nearest-neighbor|bicubic",
9364 "-ms-grid-column-align": "start|end|center|stretch",
9365 "-ms-grid-row-align": "start|end|center|stretch",
9366 "-ms-hyphenate-limit-last": "none|always|column|page|spread",
9367 "-webkit-background-clip": "[<box>|border|padding|content|text]#",
9368 "-webkit-column-break-after": "always|auto|avoid",
9369 "-webkit-column-break-before": "always|auto|avoid",
9370 "-webkit-column-break-inside": "always|auto|avoid",
9371 "-webkit-font-smoothing": "auto|none|antialiased|subpixel-antialiased",
9372 "-webkit-mask-box-image": "[<url>|<gradient>|none] [<length-percentage>{4} <-webkit-mask-box-repeat>{2}]?",
9373 "-webkit-print-color-adjust": "economy|exact",
9374 "-webkit-text-security": "none|circle|disc|square",
9375 "-webkit-user-drag": "none|element|auto",
9376 "-webkit-user-select": "auto|none|text|all",
9377 "alignment-baseline": "auto|baseline|before-edge|text-before-edge|middle|central|after-edge|text-after-edge|ideographic|alphabetic|hanging|mathematical",
9378 "baseline-shift": "baseline|sub|super|<svg-length>",
9379 "behavior": "<url>+",
9380 "clip-rule": "nonzero|evenodd",
9381 "cue": "<'cue-before'> <'cue-after'>?",
9382 "cue-after": "<url> <decibel>?|none",
9383 "cue-before": "<url> <decibel>?|none",
9384 "dominant-baseline": "auto|use-script|no-change|reset-size|ideographic|alphabetic|hanging|mathematical|central|middle|text-after-edge|text-before-edge",
9385 "fill": "<paint>",
9386 "fill-opacity": "<number-zero-one>",
9387 "fill-rule": "nonzero|evenodd",
9388 "glyph-orientation-horizontal": "<angle>",
9389 "glyph-orientation-vertical": "<angle>",
9390 "kerning": "auto|<svg-length>",
9391 "marker": "none|<url>",
9392 "marker-end": "none|<url>",
9393 "marker-mid": "none|<url>",
9394 "marker-start": "none|<url>",
9395 "pause": "<'pause-before'> <'pause-after'>?",
9396 "pause-after": "<time>|none|x-weak|weak|medium|strong|x-strong",
9397 "pause-before": "<time>|none|x-weak|weak|medium|strong|x-strong",
9398 "rest": "<'rest-before'> <'rest-after'>?",
9399 "rest-after": "<time>|none|x-weak|weak|medium|strong|x-strong",
9400 "rest-before": "<time>|none|x-weak|weak|medium|strong|x-strong",
9401 "shape-rendering": "auto|optimizeSpeed|crispEdges|geometricPrecision",
9402 "src": "[<url> [format( <string># )]?|local( <family-name> )]#",
9403 "speak": "auto|none|normal",
9404 "speak-as": "normal|spell-out||digits||[literal-punctuation|no-punctuation]",
9405 "stroke": "<paint>",
9406 "stroke-dasharray": "none|[<svg-length>+]#",
9407 "stroke-dashoffset": "<svg-length>",
9408 "stroke-linecap": "butt|round|square",
9409 "stroke-linejoin": "miter|round|bevel",
9410 "stroke-miterlimit": "<number-one-or-greater>",
9411 "stroke-opacity": "<number-zero-one>",
9412 "stroke-width": "<svg-length>",
9413 "text-anchor": "start|middle|end",
9414 "unicode-range": "<urange>#",
9415 "voice-balance": "<number>|left|center|right|leftwards|rightwards",
9416 "voice-duration": "auto|<time>",
9417 "voice-family": "[[<family-name>|<generic-voice>] ,]* [<family-name>|<generic-voice>]|preserve",
9418 "voice-pitch": "<frequency>&&absolute|[[x-low|low|medium|high|x-high]||[<frequency>|<semitones>|<percentage>]]",
9419 "voice-range": "<frequency>&&absolute|[[x-low|low|medium|high|x-high]||[<frequency>|<semitones>|<percentage>]]",
9420 "voice-rate": "[normal|x-slow|slow|medium|fast|x-fast]||<percentage>",
9421 "voice-stress": "normal|strong|moderate|none|reduced",
9422 "voice-volume": "silent|[[x-soft|soft|medium|loud|x-loud]||<decibel>]"
9423 },
9424 "atrules": {
9425 "charset": {
9426 "prelude": "<string>",
9427 "descriptors": null
9428 },
9429 "counter-style": {
9430 "prelude": "<counter-style-name>",
9431 "descriptors": {
9432 "additive-symbols": "[<integer>&&<symbol>]#",
9433 "fallback": "<counter-style-name>",
9434 "negative": "<symbol> <symbol>?",
9435 "pad": "<integer>&&<symbol>",
9436 "prefix": "<symbol>",
9437 "range": "[[<integer>|infinite]{2}]#|auto",
9438 "speak-as": "auto|bullets|numbers|words|spell-out|<counter-style-name>",
9439 "suffix": "<symbol>",
9440 "symbols": "<symbol>+",
9441 "system": "cyclic|numeric|alphabetic|symbolic|additive|[fixed <integer>?]|[extends <counter-style-name>]"
9442 }
9443 },
9444 "document": {
9445 "prelude": "[<url>|url-prefix( <string> )|domain( <string> )|media-document( <string> )|regexp( <string> )]#",
9446 "descriptors": null
9447 },
9448 "font-face": {
9449 "prelude": null,
9450 "descriptors": {
9451 "font-display": "[auto|block|swap|fallback|optional]",
9452 "font-family": "<family-name>",
9453 "font-feature-settings": "normal|<feature-tag-value>#",
9454 "font-variation-settings": "normal|[<string> <number>]#",
9455 "font-stretch": "<font-stretch-absolute>{1,2}",
9456 "font-style": "normal|italic|oblique <angle>{0,2}",
9457 "font-weight": "<font-weight-absolute>{1,2}",
9458 "font-variant": "normal|none|[<common-lig-values>||<discretionary-lig-values>||<historical-lig-values>||<contextual-alt-values>||stylistic( <feature-value-name> )||historical-forms||styleset( <feature-value-name># )||character-variant( <feature-value-name># )||swash( <feature-value-name> )||ornaments( <feature-value-name> )||annotation( <feature-value-name> )||[small-caps|all-small-caps|petite-caps|all-petite-caps|unicase|titling-caps]||<numeric-figure-values>||<numeric-spacing-values>||<numeric-fraction-values>||ordinal||slashed-zero||<east-asian-variant-values>||<east-asian-width-values>||ruby]",
9459 "src": "[<url> [format( <string># )]?|local( <family-name> )]#",
9460 "unicode-range": "<urange>#"
9461 }
9462 },
9463 "font-feature-values": {
9464 "prelude": "<family-name>#",
9465 "descriptors": null
9466 },
9467 "import": {
9468 "prelude": "[<string>|<url>] [<media-query-list>]?",
9469 "descriptors": null
9470 },
9471 "keyframes": {
9472 "prelude": "<keyframes-name>",
9473 "descriptors": null
9474 },
9475 "media": {
9476 "prelude": "<media-query-list>",
9477 "descriptors": null
9478 },
9479 "namespace": {
9480 "prelude": "<namespace-prefix>? [<string>|<url>]",
9481 "descriptors": null
9482 },
9483 "page": {
9484 "prelude": "<page-selector-list>",
9485 "descriptors": {
9486 "bleed": "auto|<length>",
9487 "marks": "none|[crop||cross]",
9488 "size": "<length>{1,2}|auto|[<page-size>||[portrait|landscape]]"
9489 }
9490 },
9491 "property": {
9492 "prelude": "<custom-property-name>",
9493 "descriptors": {
9494 "syntax": "<string>",
9495 "inherits": "true|false",
9496 "initial-value": "<string>"
9497 }
9498 },
9499 "supports": {
9500 "prelude": "<supports-condition>",
9501 "descriptors": null
9502 },
9503 "viewport": {
9504 "prelude": null,
9505 "descriptors": {
9506 "height": "<viewport-length>{1,2}",
9507 "max-height": "<viewport-length>",
9508 "max-width": "<viewport-length>",
9509 "max-zoom": "auto|<number>|<percentage>",
9510 "min-height": "<viewport-length>",
9511 "min-width": "<viewport-length>",
9512 "min-zoom": "auto|<number>|<percentage>",
9513 "orientation": "auto|portrait|landscape",
9514 "user-zoom": "zoom|fixed",
9515 "viewport-fit": "auto|contain|cover",
9516 "width": "<viewport-length>{1,2}",
9517 "zoom": "auto|<number>|<percentage>"
9518 }
9519 }
9520 }
9521 };
9522
9523 var cmpChar$3 = tokenizer.cmpChar;
9524 var isDigit$4 = tokenizer.isDigit;
9525 var TYPE$9 = tokenizer.TYPE;
9526
9527 var WHITESPACE$4 = TYPE$9.WhiteSpace;
9528 var COMMENT$4 = TYPE$9.Comment;
9529 var IDENT$3 = TYPE$9.Ident;
9530 var NUMBER$3 = TYPE$9.Number;
9531 var DIMENSION$2 = TYPE$9.Dimension;
9532 var PLUSSIGN$3 = 0x002B; // U+002B PLUS SIGN (+)
9533 var HYPHENMINUS$3 = 0x002D; // U+002D HYPHEN-MINUS (-)
9534 var N$4 = 0x006E; // U+006E LATIN SMALL LETTER N (n)
9535 var DISALLOW_SIGN$1 = true;
9536 var ALLOW_SIGN$1 = false;
9537
9538 function checkInteger$1(offset, disallowSign) {
9539 var pos = this.scanner.tokenStart + offset;
9540 var code = this.scanner.source.charCodeAt(pos);
9541
9542 if (code === PLUSSIGN$3 || code === HYPHENMINUS$3) {
9543 if (disallowSign) {
9544 this.error('Number sign is not allowed');
9545 }
9546 pos++;
9547 }
9548
9549 for (; pos < this.scanner.tokenEnd; pos++) {
9550 if (!isDigit$4(this.scanner.source.charCodeAt(pos))) {
9551 this.error('Integer is expected', pos);
9552 }
9553 }
9554 }
9555
9556 function checkTokenIsInteger(disallowSign) {
9557 return checkInteger$1.call(this, 0, disallowSign);
9558 }
9559
9560 function expectCharCode(offset, code) {
9561 if (!cmpChar$3(this.scanner.source, this.scanner.tokenStart + offset, code)) {
9562 var msg = '';
9563
9564 switch (code) {
9565 case N$4:
9566 msg = 'N is expected';
9567 break;
9568 case HYPHENMINUS$3:
9569 msg = 'HyphenMinus is expected';
9570 break;
9571 }
9572
9573 this.error(msg, this.scanner.tokenStart + offset);
9574 }
9575 }
9576
9577 // ... <signed-integer>
9578 // ... ['+' | '-'] <signless-integer>
9579 function consumeB$1() {
9580 var offset = 0;
9581 var sign = 0;
9582 var type = this.scanner.tokenType;
9583
9584 while (type === WHITESPACE$4 || type === COMMENT$4) {
9585 type = this.scanner.lookupType(++offset);
9586 }
9587
9588 if (type !== NUMBER$3) {
9589 if (this.scanner.isDelim(PLUSSIGN$3, offset) ||
9590 this.scanner.isDelim(HYPHENMINUS$3, offset)) {
9591 sign = this.scanner.isDelim(PLUSSIGN$3, offset) ? PLUSSIGN$3 : HYPHENMINUS$3;
9592
9593 do {
9594 type = this.scanner.lookupType(++offset);
9595 } while (type === WHITESPACE$4 || type === COMMENT$4);
9596
9597 if (type !== NUMBER$3) {
9598 this.scanner.skip(offset);
9599 checkTokenIsInteger.call(this, DISALLOW_SIGN$1);
9600 }
9601 } else {
9602 return null;
9603 }
9604 }
9605
9606 if (offset > 0) {
9607 this.scanner.skip(offset);
9608 }
9609
9610 if (sign === 0) {
9611 type = this.scanner.source.charCodeAt(this.scanner.tokenStart);
9612 if (type !== PLUSSIGN$3 && type !== HYPHENMINUS$3) {
9613 this.error('Number sign is expected');
9614 }
9615 }
9616
9617 checkTokenIsInteger.call(this, sign !== 0);
9618 return sign === HYPHENMINUS$3 ? '-' + this.consume(NUMBER$3) : this.consume(NUMBER$3);
9619 }
9620
9621 // An+B microsyntax https://www.w3.org/TR/css-syntax-3/#anb
9622 var AnPlusB = {
9623 name: 'AnPlusB',
9624 structure: {
9625 a: [String, null],
9626 b: [String, null]
9627 },
9628 parse: function() {
9629 /* eslint-disable brace-style*/
9630 var start = this.scanner.tokenStart;
9631 var a = null;
9632 var b = null;
9633
9634 // <integer>
9635 if (this.scanner.tokenType === NUMBER$3) {
9636 checkTokenIsInteger.call(this, ALLOW_SIGN$1);
9637 b = this.consume(NUMBER$3);
9638 }
9639
9640 // -n
9641 // -n <signed-integer>
9642 // -n ['+' | '-'] <signless-integer>
9643 // -n- <signless-integer>
9644 // <dashndashdigit-ident>
9645 else if (this.scanner.tokenType === IDENT$3 && cmpChar$3(this.scanner.source, this.scanner.tokenStart, HYPHENMINUS$3)) {
9646 a = '-1';
9647
9648 expectCharCode.call(this, 1, N$4);
9649
9650 switch (this.scanner.getTokenLength()) {
9651 // -n
9652 // -n <signed-integer>
9653 // -n ['+' | '-'] <signless-integer>
9654 case 2:
9655 this.scanner.next();
9656 b = consumeB$1.call(this);
9657 break;
9658
9659 // -n- <signless-integer>
9660 case 3:
9661 expectCharCode.call(this, 2, HYPHENMINUS$3);
9662
9663 this.scanner.next();
9664 this.scanner.skipSC();
9665
9666 checkTokenIsInteger.call(this, DISALLOW_SIGN$1);
9667
9668 b = '-' + this.consume(NUMBER$3);
9669 break;
9670
9671 // <dashndashdigit-ident>
9672 default:
9673 expectCharCode.call(this, 2, HYPHENMINUS$3);
9674 checkInteger$1.call(this, 3, DISALLOW_SIGN$1);
9675 this.scanner.next();
9676
9677 b = this.scanner.substrToCursor(start + 2);
9678 }
9679 }
9680
9681 // '+'? n
9682 // '+'? n <signed-integer>
9683 // '+'? n ['+' | '-'] <signless-integer>
9684 // '+'? n- <signless-integer>
9685 // '+'? <ndashdigit-ident>
9686 else if (this.scanner.tokenType === IDENT$3 || (this.scanner.isDelim(PLUSSIGN$3) && this.scanner.lookupType(1) === IDENT$3)) {
9687 var sign = 0;
9688 a = '1';
9689
9690 // just ignore a plus
9691 if (this.scanner.isDelim(PLUSSIGN$3)) {
9692 sign = 1;
9693 this.scanner.next();
9694 }
9695
9696 expectCharCode.call(this, 0, N$4);
9697
9698 switch (this.scanner.getTokenLength()) {
9699 // '+'? n
9700 // '+'? n <signed-integer>
9701 // '+'? n ['+' | '-'] <signless-integer>
9702 case 1:
9703 this.scanner.next();
9704 b = consumeB$1.call(this);
9705 break;
9706
9707 // '+'? n- <signless-integer>
9708 case 2:
9709 expectCharCode.call(this, 1, HYPHENMINUS$3);
9710
9711 this.scanner.next();
9712 this.scanner.skipSC();
9713
9714 checkTokenIsInteger.call(this, DISALLOW_SIGN$1);
9715
9716 b = '-' + this.consume(NUMBER$3);
9717 break;
9718
9719 // '+'? <ndashdigit-ident>
9720 default:
9721 expectCharCode.call(this, 1, HYPHENMINUS$3);
9722 checkInteger$1.call(this, 2, DISALLOW_SIGN$1);
9723 this.scanner.next();
9724
9725 b = this.scanner.substrToCursor(start + sign + 1);
9726 }
9727 }
9728
9729 // <ndashdigit-dimension>
9730 // <ndash-dimension> <signless-integer>
9731 // <n-dimension>
9732 // <n-dimension> <signed-integer>
9733 // <n-dimension> ['+' | '-'] <signless-integer>
9734 else if (this.scanner.tokenType === DIMENSION$2) {
9735 var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
9736 var sign = code === PLUSSIGN$3 || code === HYPHENMINUS$3;
9737
9738 for (var i = this.scanner.tokenStart + sign; i < this.scanner.tokenEnd; i++) {
9739 if (!isDigit$4(this.scanner.source.charCodeAt(i))) {
9740 break;
9741 }
9742 }
9743
9744 if (i === this.scanner.tokenStart + sign) {
9745 this.error('Integer is expected', this.scanner.tokenStart + sign);
9746 }
9747
9748 expectCharCode.call(this, i - this.scanner.tokenStart, N$4);
9749 a = this.scanner.source.substring(start, i);
9750
9751 // <n-dimension>
9752 // <n-dimension> <signed-integer>
9753 // <n-dimension> ['+' | '-'] <signless-integer>
9754 if (i + 1 === this.scanner.tokenEnd) {
9755 this.scanner.next();
9756 b = consumeB$1.call(this);
9757 } else {
9758 expectCharCode.call(this, i - this.scanner.tokenStart + 1, HYPHENMINUS$3);
9759
9760 // <ndash-dimension> <signless-integer>
9761 if (i + 2 === this.scanner.tokenEnd) {
9762 this.scanner.next();
9763 this.scanner.skipSC();
9764 checkTokenIsInteger.call(this, DISALLOW_SIGN$1);
9765 b = '-' + this.consume(NUMBER$3);
9766 }
9767 // <ndashdigit-dimension>
9768 else {
9769 checkInteger$1.call(this, i - this.scanner.tokenStart + 2, DISALLOW_SIGN$1);
9770 this.scanner.next();
9771 b = this.scanner.substrToCursor(i + 1);
9772 }
9773 }
9774 } else {
9775 this.error();
9776 }
9777
9778 if (a !== null && a.charCodeAt(0) === PLUSSIGN$3) {
9779 a = a.substr(1);
9780 }
9781
9782 if (b !== null && b.charCodeAt(0) === PLUSSIGN$3) {
9783 b = b.substr(1);
9784 }
9785
9786 return {
9787 type: 'AnPlusB',
9788 loc: this.getLocation(start, this.scanner.tokenStart),
9789 a: a,
9790 b: b
9791 };
9792 },
9793 generate: function(node) {
9794 var a = node.a !== null && node.a !== undefined;
9795 var b = node.b !== null && node.b !== undefined;
9796
9797 if (a) {
9798 this.chunk(
9799 node.a === '+1' ? '+n' : // eslint-disable-line operator-linebreak, indent
9800 node.a === '1' ? 'n' : // eslint-disable-line operator-linebreak, indent
9801 node.a === '-1' ? '-n' : // eslint-disable-line operator-linebreak, indent
9802 node.a + 'n' // eslint-disable-line operator-linebreak, indent
9803 );
9804
9805 if (b) {
9806 b = String(node.b);
9807 if (b.charAt(0) === '-' || b.charAt(0) === '+') {
9808 this.chunk(b.charAt(0));
9809 this.chunk(b.substr(1));
9810 } else {
9811 this.chunk('+');
9812 this.chunk(b);
9813 }
9814 }
9815 } else {
9816 this.chunk(String(node.b));
9817 }
9818 }
9819 };
9820
9821 var TYPE$a = tokenizer.TYPE;
9822
9823 var WhiteSpace = TYPE$a.WhiteSpace;
9824 var Semicolon = TYPE$a.Semicolon;
9825 var LeftCurlyBracket = TYPE$a.LeftCurlyBracket;
9826 var Delim = TYPE$a.Delim;
9827 var EXCLAMATIONMARK$1 = 0x0021; // U+0021 EXCLAMATION MARK (!)
9828
9829 function getOffsetExcludeWS() {
9830 if (this.scanner.tokenIndex > 0) {
9831 if (this.scanner.lookupType(-1) === WhiteSpace) {
9832 return this.scanner.tokenIndex > 1
9833 ? this.scanner.getTokenStart(this.scanner.tokenIndex - 1)
9834 : this.scanner.firstCharOffset;
9835 }
9836 }
9837
9838 return this.scanner.tokenStart;
9839 }
9840
9841 // 0, 0, false
9842 function balanceEnd() {
9843 return 0;
9844 }
9845
9846 // LEFTCURLYBRACKET, 0, false
9847 function leftCurlyBracket(tokenType) {
9848 return tokenType === LeftCurlyBracket ? 1 : 0;
9849 }
9850
9851 // LEFTCURLYBRACKET, SEMICOLON, false
9852 function leftCurlyBracketOrSemicolon(tokenType) {
9853 return tokenType === LeftCurlyBracket || tokenType === Semicolon ? 1 : 0;
9854 }
9855
9856 // EXCLAMATIONMARK, SEMICOLON, false
9857 function exclamationMarkOrSemicolon(tokenType, source, offset) {
9858 if (tokenType === Delim && source.charCodeAt(offset) === EXCLAMATIONMARK$1) {
9859 return 1;
9860 }
9861
9862 return tokenType === Semicolon ? 1 : 0;
9863 }
9864
9865 // 0, SEMICOLON, true
9866 function semicolonIncluded(tokenType) {
9867 return tokenType === Semicolon ? 2 : 0;
9868 }
9869
9870 var Raw = {
9871 name: 'Raw',
9872 structure: {
9873 value: String
9874 },
9875 parse: function(startToken, mode, excludeWhiteSpace) {
9876 var startOffset = this.scanner.getTokenStart(startToken);
9877 var endOffset;
9878
9879 this.scanner.skip(
9880 this.scanner.getRawLength(startToken, mode || balanceEnd)
9881 );
9882
9883 if (excludeWhiteSpace && this.scanner.tokenStart > startOffset) {
9884 endOffset = getOffsetExcludeWS.call(this);
9885 } else {
9886 endOffset = this.scanner.tokenStart;
9887 }
9888
9889 return {
9890 type: 'Raw',
9891 loc: this.getLocation(startOffset, endOffset),
9892 value: this.scanner.source.substring(startOffset, endOffset)
9893 };
9894 },
9895 generate: function(node) {
9896 this.chunk(node.value);
9897 },
9898
9899 mode: {
9900 default: balanceEnd,
9901 leftCurlyBracket: leftCurlyBracket,
9902 leftCurlyBracketOrSemicolon: leftCurlyBracketOrSemicolon,
9903 exclamationMarkOrSemicolon: exclamationMarkOrSemicolon,
9904 semicolonIncluded: semicolonIncluded
9905 }
9906 };
9907
9908 var TYPE$b = tokenizer.TYPE;
9909 var rawMode = Raw.mode;
9910
9911 var ATKEYWORD = TYPE$b.AtKeyword;
9912 var SEMICOLON = TYPE$b.Semicolon;
9913 var LEFTCURLYBRACKET$1 = TYPE$b.LeftCurlyBracket;
9914 var RIGHTCURLYBRACKET$1 = TYPE$b.RightCurlyBracket;
9915
9916 function consumeRaw(startToken) {
9917 return this.Raw(startToken, rawMode.leftCurlyBracketOrSemicolon, true);
9918 }
9919
9920 function isDeclarationBlockAtrule() {
9921 for (var offset = 1, type; type = this.scanner.lookupType(offset); offset++) {
9922 if (type === RIGHTCURLYBRACKET$1) {
9923 return true;
9924 }
9925
9926 if (type === LEFTCURLYBRACKET$1 ||
9927 type === ATKEYWORD) {
9928 return false;
9929 }
9930 }
9931
9932 return false;
9933 }
9934
9935 var Atrule = {
9936 name: 'Atrule',
9937 structure: {
9938 name: String,
9939 prelude: ['AtrulePrelude', 'Raw', null],
9940 block: ['Block', null]
9941 },
9942 parse: function() {
9943 var start = this.scanner.tokenStart;
9944 var name;
9945 var nameLowerCase;
9946 var prelude = null;
9947 var block = null;
9948
9949 this.eat(ATKEYWORD);
9950
9951 name = this.scanner.substrToCursor(start + 1);
9952 nameLowerCase = name.toLowerCase();
9953 this.scanner.skipSC();
9954
9955 // parse prelude
9956 if (this.scanner.eof === false &&
9957 this.scanner.tokenType !== LEFTCURLYBRACKET$1 &&
9958 this.scanner.tokenType !== SEMICOLON) {
9959 if (this.parseAtrulePrelude) {
9960 prelude = this.parseWithFallback(this.AtrulePrelude.bind(this, name), consumeRaw);
9961
9962 // turn empty AtrulePrelude into null
9963 if (prelude.type === 'AtrulePrelude' && prelude.children.head === null) {
9964 prelude = null;
9965 }
9966 } else {
9967 prelude = consumeRaw.call(this, this.scanner.tokenIndex);
9968 }
9969
9970 this.scanner.skipSC();
9971 }
9972
9973 switch (this.scanner.tokenType) {
9974 case SEMICOLON:
9975 this.scanner.next();
9976 break;
9977
9978 case LEFTCURLYBRACKET$1:
9979 if (this.atrule.hasOwnProperty(nameLowerCase) &&
9980 typeof this.atrule[nameLowerCase].block === 'function') {
9981 block = this.atrule[nameLowerCase].block.call(this);
9982 } else {
9983 // TODO: should consume block content as Raw?
9984 block = this.Block(isDeclarationBlockAtrule.call(this));
9985 }
9986
9987 break;
9988 }
9989
9990 return {
9991 type: 'Atrule',
9992 loc: this.getLocation(start, this.scanner.tokenStart),
9993 name: name,
9994 prelude: prelude,
9995 block: block
9996 };
9997 },
9998 generate: function(node) {
9999 this.chunk('@');
10000 this.chunk(node.name);
10001
10002 if (node.prelude !== null) {
10003 this.chunk(' ');
10004 this.node(node.prelude);
10005 }
10006
10007 if (node.block) {
10008 this.node(node.block);
10009 } else {
10010 this.chunk(';');
10011 }
10012 },
10013 walkContext: 'atrule'
10014 };
10015
10016 var TYPE$c = tokenizer.TYPE;
10017
10018 var SEMICOLON$1 = TYPE$c.Semicolon;
10019 var LEFTCURLYBRACKET$2 = TYPE$c.LeftCurlyBracket;
10020
10021 var AtrulePrelude = {
10022 name: 'AtrulePrelude',
10023 structure: {
10024 children: [[]]
10025 },
10026 parse: function(name) {
10027 var children = null;
10028
10029 if (name !== null) {
10030 name = name.toLowerCase();
10031 }
10032
10033 this.scanner.skipSC();
10034
10035 if (this.atrule.hasOwnProperty(name) &&
10036 typeof this.atrule[name].prelude === 'function') {
10037 // custom consumer
10038 children = this.atrule[name].prelude.call(this);
10039 } else {
10040 // default consumer
10041 children = this.readSequence(this.scope.AtrulePrelude);
10042 }
10043
10044 this.scanner.skipSC();
10045
10046 if (this.scanner.eof !== true &&
10047 this.scanner.tokenType !== LEFTCURLYBRACKET$2 &&
10048 this.scanner.tokenType !== SEMICOLON$1) {
10049 this.error('Semicolon or block is expected');
10050 }
10051
10052 if (children === null) {
10053 children = this.createList();
10054 }
10055
10056 return {
10057 type: 'AtrulePrelude',
10058 loc: this.getLocationFromList(children),
10059 children: children
10060 };
10061 },
10062 generate: function(node) {
10063 this.children(node);
10064 },
10065 walkContext: 'atrulePrelude'
10066 };
10067
10068 var TYPE$d = tokenizer.TYPE;
10069
10070 var IDENT$4 = TYPE$d.Ident;
10071 var STRING = TYPE$d.String;
10072 var COLON = TYPE$d.Colon;
10073 var LEFTSQUAREBRACKET$1 = TYPE$d.LeftSquareBracket;
10074 var RIGHTSQUAREBRACKET$1 = TYPE$d.RightSquareBracket;
10075 var DOLLARSIGN = 0x0024; // U+0024 DOLLAR SIGN ($)
10076 var ASTERISK$1 = 0x002A; // U+002A ASTERISK (*)
10077 var EQUALSSIGN = 0x003D; // U+003D EQUALS SIGN (=)
10078 var CIRCUMFLEXACCENT = 0x005E; // U+005E (^)
10079 var VERTICALLINE$1 = 0x007C; // U+007C VERTICAL LINE (|)
10080 var TILDE = 0x007E; // U+007E TILDE (~)
10081
10082 function getAttributeName() {
10083 if (this.scanner.eof) {
10084 this.error('Unexpected end of input');
10085 }
10086
10087 var start = this.scanner.tokenStart;
10088 var expectIdent = false;
10089 var checkColon = true;
10090
10091 if (this.scanner.isDelim(ASTERISK$1)) {
10092 expectIdent = true;
10093 checkColon = false;
10094 this.scanner.next();
10095 } else if (!this.scanner.isDelim(VERTICALLINE$1)) {
10096 this.eat(IDENT$4);
10097 }
10098
10099 if (this.scanner.isDelim(VERTICALLINE$1)) {
10100 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 1) !== EQUALSSIGN) {
10101 this.scanner.next();
10102 this.eat(IDENT$4);
10103 } else if (expectIdent) {
10104 this.error('Identifier is expected', this.scanner.tokenEnd);
10105 }
10106 } else if (expectIdent) {
10107 this.error('Vertical line is expected');
10108 }
10109
10110 if (checkColon && this.scanner.tokenType === COLON) {
10111 this.scanner.next();
10112 this.eat(IDENT$4);
10113 }
10114
10115 return {
10116 type: 'Identifier',
10117 loc: this.getLocation(start, this.scanner.tokenStart),
10118 name: this.scanner.substrToCursor(start)
10119 };
10120 }
10121
10122 function getOperator() {
10123 var start = this.scanner.tokenStart;
10124 var code = this.scanner.source.charCodeAt(start);
10125
10126 if (code !== EQUALSSIGN && // =
10127 code !== TILDE && // ~=
10128 code !== CIRCUMFLEXACCENT && // ^=
10129 code !== DOLLARSIGN && // $=
10130 code !== ASTERISK$1 && // *=
10131 code !== VERTICALLINE$1 // |=
10132 ) {
10133 this.error('Attribute selector (=, ~=, ^=, $=, *=, |=) is expected');
10134 }
10135
10136 this.scanner.next();
10137
10138 if (code !== EQUALSSIGN) {
10139 if (!this.scanner.isDelim(EQUALSSIGN)) {
10140 this.error('Equal sign is expected');
10141 }
10142
10143 this.scanner.next();
10144 }
10145
10146 return this.scanner.substrToCursor(start);
10147 }
10148
10149 // '[' <wq-name> ']'
10150 // '[' <wq-name> <attr-matcher> [ <string-token> | <ident-token> ] <attr-modifier>? ']'
10151 var AttributeSelector = {
10152 name: 'AttributeSelector',
10153 structure: {
10154 name: 'Identifier',
10155 matcher: [String, null],
10156 value: ['String', 'Identifier', null],
10157 flags: [String, null]
10158 },
10159 parse: function() {
10160 var start = this.scanner.tokenStart;
10161 var name;
10162 var matcher = null;
10163 var value = null;
10164 var flags = null;
10165
10166 this.eat(LEFTSQUAREBRACKET$1);
10167 this.scanner.skipSC();
10168
10169 name = getAttributeName.call(this);
10170 this.scanner.skipSC();
10171
10172 if (this.scanner.tokenType !== RIGHTSQUAREBRACKET$1) {
10173 // avoid case `[name i]`
10174 if (this.scanner.tokenType !== IDENT$4) {
10175 matcher = getOperator.call(this);
10176
10177 this.scanner.skipSC();
10178
10179 value = this.scanner.tokenType === STRING
10180 ? this.String()
10181 : this.Identifier();
10182
10183 this.scanner.skipSC();
10184 }
10185
10186 // attribute flags
10187 if (this.scanner.tokenType === IDENT$4) {
10188 flags = this.scanner.getTokenValue();
10189 this.scanner.next();
10190
10191 this.scanner.skipSC();
10192 }
10193 }
10194
10195 this.eat(RIGHTSQUAREBRACKET$1);
10196
10197 return {
10198 type: 'AttributeSelector',
10199 loc: this.getLocation(start, this.scanner.tokenStart),
10200 name: name,
10201 matcher: matcher,
10202 value: value,
10203 flags: flags
10204 };
10205 },
10206 generate: function(node) {
10207 var flagsPrefix = ' ';
10208
10209 this.chunk('[');
10210 this.node(node.name);
10211
10212 if (node.matcher !== null) {
10213 this.chunk(node.matcher);
10214
10215 if (node.value !== null) {
10216 this.node(node.value);
10217
10218 // space between string and flags is not required
10219 if (node.value.type === 'String') {
10220 flagsPrefix = '';
10221 }
10222 }
10223 }
10224
10225 if (node.flags !== null) {
10226 this.chunk(flagsPrefix);
10227 this.chunk(node.flags);
10228 }
10229
10230 this.chunk(']');
10231 }
10232 };
10233
10234 var TYPE$e = tokenizer.TYPE;
10235 var rawMode$1 = Raw.mode;
10236
10237 var WHITESPACE$5 = TYPE$e.WhiteSpace;
10238 var COMMENT$5 = TYPE$e.Comment;
10239 var SEMICOLON$2 = TYPE$e.Semicolon;
10240 var ATKEYWORD$1 = TYPE$e.AtKeyword;
10241 var LEFTCURLYBRACKET$3 = TYPE$e.LeftCurlyBracket;
10242 var RIGHTCURLYBRACKET$2 = TYPE$e.RightCurlyBracket;
10243
10244 function consumeRaw$1(startToken) {
10245 return this.Raw(startToken, null, true);
10246 }
10247 function consumeRule() {
10248 return this.parseWithFallback(this.Rule, consumeRaw$1);
10249 }
10250 function consumeRawDeclaration(startToken) {
10251 return this.Raw(startToken, rawMode$1.semicolonIncluded, true);
10252 }
10253 function consumeDeclaration() {
10254 if (this.scanner.tokenType === SEMICOLON$2) {
10255 return consumeRawDeclaration.call(this, this.scanner.tokenIndex);
10256 }
10257
10258 var node = this.parseWithFallback(this.Declaration, consumeRawDeclaration);
10259
10260 if (this.scanner.tokenType === SEMICOLON$2) {
10261 this.scanner.next();
10262 }
10263
10264 return node;
10265 }
10266
10267 var Block = {
10268 name: 'Block',
10269 structure: {
10270 children: [[
10271 'Atrule',
10272 'Rule',
10273 'Declaration'
10274 ]]
10275 },
10276 parse: function(isDeclaration) {
10277 var consumer = isDeclaration ? consumeDeclaration : consumeRule;
10278
10279 var start = this.scanner.tokenStart;
10280 var children = this.createList();
10281
10282 this.eat(LEFTCURLYBRACKET$3);
10283
10284 scan:
10285 while (!this.scanner.eof) {
10286 switch (this.scanner.tokenType) {
10287 case RIGHTCURLYBRACKET$2:
10288 break scan;
10289
10290 case WHITESPACE$5:
10291 case COMMENT$5:
10292 this.scanner.next();
10293 break;
10294
10295 case ATKEYWORD$1:
10296 children.push(this.parseWithFallback(this.Atrule, consumeRaw$1));
10297 break;
10298
10299 default:
10300 children.push(consumer.call(this));
10301 }
10302 }
10303
10304 if (!this.scanner.eof) {
10305 this.eat(RIGHTCURLYBRACKET$2);
10306 }
10307
10308 return {
10309 type: 'Block',
10310 loc: this.getLocation(start, this.scanner.tokenStart),
10311 children: children
10312 };
10313 },
10314 generate: function(node) {
10315 this.chunk('{');
10316 this.children(node, function(prev) {
10317 if (prev.type === 'Declaration') {
10318 this.chunk(';');
10319 }
10320 });
10321 this.chunk('}');
10322 },
10323 walkContext: 'block'
10324 };
10325
10326 var TYPE$f = tokenizer.TYPE;
10327
10328 var LEFTSQUAREBRACKET$2 = TYPE$f.LeftSquareBracket;
10329 var RIGHTSQUAREBRACKET$2 = TYPE$f.RightSquareBracket;
10330
10331 var Brackets = {
10332 name: 'Brackets',
10333 structure: {
10334 children: [[]]
10335 },
10336 parse: function(readSequence, recognizer) {
10337 var start = this.scanner.tokenStart;
10338 var children = null;
10339
10340 this.eat(LEFTSQUAREBRACKET$2);
10341
10342 children = readSequence.call(this, recognizer);
10343
10344 if (!this.scanner.eof) {
10345 this.eat(RIGHTSQUAREBRACKET$2);
10346 }
10347
10348 return {
10349 type: 'Brackets',
10350 loc: this.getLocation(start, this.scanner.tokenStart),
10351 children: children
10352 };
10353 },
10354 generate: function(node) {
10355 this.chunk('[');
10356 this.children(node);
10357 this.chunk(']');
10358 }
10359 };
10360
10361 var CDC = tokenizer.TYPE.CDC;
10362
10363 var CDC_1 = {
10364 name: 'CDC',
10365 structure: [],
10366 parse: function() {
10367 var start = this.scanner.tokenStart;
10368
10369 this.eat(CDC); // -->
10370
10371 return {
10372 type: 'CDC',
10373 loc: this.getLocation(start, this.scanner.tokenStart)
10374 };
10375 },
10376 generate: function() {
10377 this.chunk('-->');
10378 }
10379 };
10380
10381 var CDO = tokenizer.TYPE.CDO;
10382
10383 var CDO_1 = {
10384 name: 'CDO',
10385 structure: [],
10386 parse: function() {
10387 var start = this.scanner.tokenStart;
10388
10389 this.eat(CDO); // <!--
10390
10391 return {
10392 type: 'CDO',
10393 loc: this.getLocation(start, this.scanner.tokenStart)
10394 };
10395 },
10396 generate: function() {
10397 this.chunk('<!--');
10398 }
10399 };
10400
10401 var TYPE$g = tokenizer.TYPE;
10402
10403 var IDENT$5 = TYPE$g.Ident;
10404 var FULLSTOP = 0x002E; // U+002E FULL STOP (.)
10405
10406 // '.' ident
10407 var ClassSelector = {
10408 name: 'ClassSelector',
10409 structure: {
10410 name: String
10411 },
10412 parse: function() {
10413 if (!this.scanner.isDelim(FULLSTOP)) {
10414 this.error('Full stop is expected');
10415 }
10416
10417 this.scanner.next();
10418
10419 return {
10420 type: 'ClassSelector',
10421 loc: this.getLocation(this.scanner.tokenStart - 1, this.scanner.tokenEnd),
10422 name: this.consume(IDENT$5)
10423 };
10424 },
10425 generate: function(node) {
10426 this.chunk('.');
10427 this.chunk(node.name);
10428 }
10429 };
10430
10431 var TYPE$h = tokenizer.TYPE;
10432
10433 var IDENT$6 = TYPE$h.Ident;
10434 var PLUSSIGN$4 = 0x002B; // U+002B PLUS SIGN (+)
10435 var SOLIDUS = 0x002F; // U+002F SOLIDUS (/)
10436 var GREATERTHANSIGN$1 = 0x003E; // U+003E GREATER-THAN SIGN (>)
10437 var TILDE$1 = 0x007E; // U+007E TILDE (~)
10438
10439 // + | > | ~ | /deep/
10440 var Combinator = {
10441 name: 'Combinator',
10442 structure: {
10443 name: String
10444 },
10445 parse: function() {
10446 var start = this.scanner.tokenStart;
10447 var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
10448
10449 switch (code) {
10450 case GREATERTHANSIGN$1:
10451 case PLUSSIGN$4:
10452 case TILDE$1:
10453 this.scanner.next();
10454 break;
10455
10456 case SOLIDUS:
10457 this.scanner.next();
10458
10459 if (this.scanner.tokenType !== IDENT$6 || this.scanner.lookupValue(0, 'deep') === false) {
10460 this.error('Identifier `deep` is expected');
10461 }
10462
10463 this.scanner.next();
10464
10465 if (!this.scanner.isDelim(SOLIDUS)) {
10466 this.error('Solidus is expected');
10467 }
10468
10469 this.scanner.next();
10470 break;
10471
10472 default:
10473 this.error('Combinator is expected');
10474 }
10475
10476 return {
10477 type: 'Combinator',
10478 loc: this.getLocation(start, this.scanner.tokenStart),
10479 name: this.scanner.substrToCursor(start)
10480 };
10481 },
10482 generate: function(node) {
10483 this.chunk(node.name);
10484 }
10485 };
10486
10487 var TYPE$i = tokenizer.TYPE;
10488
10489 var COMMENT$6 = TYPE$i.Comment;
10490 var ASTERISK$2 = 0x002A; // U+002A ASTERISK (*)
10491 var SOLIDUS$1 = 0x002F; // U+002F SOLIDUS (/)
10492
10493 // '/*' .* '*/'
10494 var Comment = {
10495 name: 'Comment',
10496 structure: {
10497 value: String
10498 },
10499 parse: function() {
10500 var start = this.scanner.tokenStart;
10501 var end = this.scanner.tokenEnd;
10502
10503 this.eat(COMMENT$6);
10504
10505 if ((end - start + 2) >= 2 &&
10506 this.scanner.source.charCodeAt(end - 2) === ASTERISK$2 &&
10507 this.scanner.source.charCodeAt(end - 1) === SOLIDUS$1) {
10508 end -= 2;
10509 }
10510
10511 return {
10512 type: 'Comment',
10513 loc: this.getLocation(start, this.scanner.tokenStart),
10514 value: this.scanner.source.substring(start + 2, end)
10515 };
10516 },
10517 generate: function(node) {
10518 this.chunk('/*');
10519 this.chunk(node.value);
10520 this.chunk('*/');
10521 }
10522 };
10523
10524 var isCustomProperty$1 = names.isCustomProperty;
10525 var TYPE$j = tokenizer.TYPE;
10526 var rawMode$2 = Raw.mode;
10527
10528 var IDENT$7 = TYPE$j.Ident;
10529 var HASH$1 = TYPE$j.Hash;
10530 var COLON$1 = TYPE$j.Colon;
10531 var SEMICOLON$3 = TYPE$j.Semicolon;
10532 var DELIM$2 = TYPE$j.Delim;
10533 var WHITESPACE$6 = TYPE$j.WhiteSpace;
10534 var EXCLAMATIONMARK$2 = 0x0021; // U+0021 EXCLAMATION MARK (!)
10535 var NUMBERSIGN$2 = 0x0023; // U+0023 NUMBER SIGN (#)
10536 var DOLLARSIGN$1 = 0x0024; // U+0024 DOLLAR SIGN ($)
10537 var AMPERSAND$1 = 0x0026; // U+0026 ANPERSAND (&)
10538 var ASTERISK$3 = 0x002A; // U+002A ASTERISK (*)
10539 var PLUSSIGN$5 = 0x002B; // U+002B PLUS SIGN (+)
10540 var SOLIDUS$2 = 0x002F; // U+002F SOLIDUS (/)
10541
10542 function consumeValueRaw(startToken) {
10543 return this.Raw(startToken, rawMode$2.exclamationMarkOrSemicolon, true);
10544 }
10545
10546 function consumeCustomPropertyRaw(startToken) {
10547 return this.Raw(startToken, rawMode$2.exclamationMarkOrSemicolon, false);
10548 }
10549
10550 function consumeValue() {
10551 var startValueToken = this.scanner.tokenIndex;
10552 var value = this.Value();
10553
10554 if (value.type !== 'Raw' &&
10555 this.scanner.eof === false &&
10556 this.scanner.tokenType !== SEMICOLON$3 &&
10557 this.scanner.isDelim(EXCLAMATIONMARK$2) === false &&
10558 this.scanner.isBalanceEdge(startValueToken) === false) {
10559 this.error();
10560 }
10561
10562 return value;
10563 }
10564
10565 var Declaration = {
10566 name: 'Declaration',
10567 structure: {
10568 important: [Boolean, String],
10569 property: String,
10570 value: ['Value', 'Raw']
10571 },
10572 parse: function() {
10573 var start = this.scanner.tokenStart;
10574 var startToken = this.scanner.tokenIndex;
10575 var property = readProperty$1.call(this);
10576 var customProperty = isCustomProperty$1(property);
10577 var parseValue = customProperty ? this.parseCustomProperty : this.parseValue;
10578 var consumeRaw = customProperty ? consumeCustomPropertyRaw : consumeValueRaw;
10579 var important = false;
10580 var value;
10581
10582 this.scanner.skipSC();
10583 this.eat(COLON$1);
10584
10585 const valueStart = this.scanner.tokenIndex;
10586
10587 if (!customProperty) {
10588 this.scanner.skipSC();
10589 }
10590
10591 if (parseValue) {
10592 value = this.parseWithFallback(consumeValue, consumeRaw);
10593 } else {
10594 value = consumeRaw.call(this, this.scanner.tokenIndex);
10595 }
10596
10597 if (customProperty && value.type === 'Value' && value.children.isEmpty()) {
10598 for (let offset = valueStart - this.scanner.tokenIndex; offset <= 0; offset++) {
10599 if (this.scanner.lookupType(offset) === WHITESPACE$6) {
10600 value.children.appendData({
10601 type: 'WhiteSpace',
10602 loc: null,
10603 value: ' '
10604 });
10605 break;
10606 }
10607 }
10608 }
10609
10610 if (this.scanner.isDelim(EXCLAMATIONMARK$2)) {
10611 important = getImportant.call(this);
10612 this.scanner.skipSC();
10613 }
10614
10615 // Do not include semicolon to range per spec
10616 // https://drafts.csswg.org/css-syntax/#declaration-diagram
10617
10618 if (this.scanner.eof === false &&
10619 this.scanner.tokenType !== SEMICOLON$3 &&
10620 this.scanner.isBalanceEdge(startToken) === false) {
10621 this.error();
10622 }
10623
10624 return {
10625 type: 'Declaration',
10626 loc: this.getLocation(start, this.scanner.tokenStart),
10627 important: important,
10628 property: property,
10629 value: value
10630 };
10631 },
10632 generate: function(node) {
10633 this.chunk(node.property);
10634 this.chunk(':');
10635 this.node(node.value);
10636
10637 if (node.important) {
10638 this.chunk(node.important === true ? '!important' : '!' + node.important);
10639 }
10640 },
10641 walkContext: 'declaration'
10642 };
10643
10644 function readProperty$1() {
10645 var start = this.scanner.tokenStart;
10646
10647 // hacks
10648 if (this.scanner.tokenType === DELIM$2) {
10649 switch (this.scanner.source.charCodeAt(this.scanner.tokenStart)) {
10650 case ASTERISK$3:
10651 case DOLLARSIGN$1:
10652 case PLUSSIGN$5:
10653 case NUMBERSIGN$2:
10654 case AMPERSAND$1:
10655 this.scanner.next();
10656 break;
10657
10658 // TODO: not sure we should support this hack
10659 case SOLIDUS$2:
10660 this.scanner.next();
10661 if (this.scanner.isDelim(SOLIDUS$2)) {
10662 this.scanner.next();
10663 }
10664 break;
10665 }
10666 }
10667
10668 if (this.scanner.tokenType === HASH$1) {
10669 this.eat(HASH$1);
10670 } else {
10671 this.eat(IDENT$7);
10672 }
10673
10674 return this.scanner.substrToCursor(start);
10675 }
10676
10677 // ! ws* important
10678 function getImportant() {
10679 this.eat(DELIM$2);
10680 this.scanner.skipSC();
10681
10682 var important = this.consume(IDENT$7);
10683
10684 // store original value in case it differ from `important`
10685 // for better original source restoring and hacks like `!ie` support
10686 return important === 'important' ? true : important;
10687 }
10688
10689 var TYPE$k = tokenizer.TYPE;
10690 var rawMode$3 = Raw.mode;
10691
10692 var WHITESPACE$7 = TYPE$k.WhiteSpace;
10693 var COMMENT$7 = TYPE$k.Comment;
10694 var SEMICOLON$4 = TYPE$k.Semicolon;
10695
10696 function consumeRaw$2(startToken) {
10697 return this.Raw(startToken, rawMode$3.semicolonIncluded, true);
10698 }
10699
10700 var DeclarationList = {
10701 name: 'DeclarationList',
10702 structure: {
10703 children: [[
10704 'Declaration'
10705 ]]
10706 },
10707 parse: function() {
10708 var children = this.createList();
10709
10710
10711 while (!this.scanner.eof) {
10712 switch (this.scanner.tokenType) {
10713 case WHITESPACE$7:
10714 case COMMENT$7:
10715 case SEMICOLON$4:
10716 this.scanner.next();
10717 break;
10718
10719 default:
10720 children.push(this.parseWithFallback(this.Declaration, consumeRaw$2));
10721 }
10722 }
10723
10724 return {
10725 type: 'DeclarationList',
10726 loc: this.getLocationFromList(children),
10727 children: children
10728 };
10729 },
10730 generate: function(node) {
10731 this.children(node, function(prev) {
10732 if (prev.type === 'Declaration') {
10733 this.chunk(';');
10734 }
10735 });
10736 }
10737 };
10738
10739 var consumeNumber$3 = utils.consumeNumber;
10740 var TYPE$l = tokenizer.TYPE;
10741
10742 var DIMENSION$3 = TYPE$l.Dimension;
10743
10744 var Dimension = {
10745 name: 'Dimension',
10746 structure: {
10747 value: String,
10748 unit: String
10749 },
10750 parse: function() {
10751 var start = this.scanner.tokenStart;
10752 var numberEnd = consumeNumber$3(this.scanner.source, start);
10753
10754 this.eat(DIMENSION$3);
10755
10756 return {
10757 type: 'Dimension',
10758 loc: this.getLocation(start, this.scanner.tokenStart),
10759 value: this.scanner.source.substring(start, numberEnd),
10760 unit: this.scanner.source.substring(numberEnd, this.scanner.tokenStart)
10761 };
10762 },
10763 generate: function(node) {
10764 this.chunk(node.value);
10765 this.chunk(node.unit);
10766 }
10767 };
10768
10769 var TYPE$m = tokenizer.TYPE;
10770
10771 var RIGHTPARENTHESIS$2 = TYPE$m.RightParenthesis;
10772
10773 // <function-token> <sequence> )
10774 var _Function = {
10775 name: 'Function',
10776 structure: {
10777 name: String,
10778 children: [[]]
10779 },
10780 parse: function(readSequence, recognizer) {
10781 var start = this.scanner.tokenStart;
10782 var name = this.consumeFunctionName();
10783 var nameLowerCase = name.toLowerCase();
10784 var children;
10785
10786 children = recognizer.hasOwnProperty(nameLowerCase)
10787 ? recognizer[nameLowerCase].call(this, recognizer)
10788 : readSequence.call(this, recognizer);
10789
10790 if (!this.scanner.eof) {
10791 this.eat(RIGHTPARENTHESIS$2);
10792 }
10793
10794 return {
10795 type: 'Function',
10796 loc: this.getLocation(start, this.scanner.tokenStart),
10797 name: name,
10798 children: children
10799 };
10800 },
10801 generate: function(node) {
10802 this.chunk(node.name);
10803 this.chunk('(');
10804 this.children(node);
10805 this.chunk(')');
10806 },
10807 walkContext: 'function'
10808 };
10809
10810 var TYPE$n = tokenizer.TYPE;
10811
10812 var HASH$2 = TYPE$n.Hash;
10813
10814 // '#' ident
10815 var Hash = {
10816 name: 'Hash',
10817 structure: {
10818 value: String
10819 },
10820 parse: function() {
10821 var start = this.scanner.tokenStart;
10822
10823 this.eat(HASH$2);
10824
10825 return {
10826 type: 'Hash',
10827 loc: this.getLocation(start, this.scanner.tokenStart),
10828 value: this.scanner.substrToCursor(start + 1)
10829 };
10830 },
10831 generate: function(node) {
10832 this.chunk('#');
10833 this.chunk(node.value);
10834 }
10835 };
10836
10837 var TYPE$o = tokenizer.TYPE;
10838
10839 var IDENT$8 = TYPE$o.Ident;
10840
10841 var Identifier = {
10842 name: 'Identifier',
10843 structure: {
10844 name: String
10845 },
10846 parse: function() {
10847 return {
10848 type: 'Identifier',
10849 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
10850 name: this.consume(IDENT$8)
10851 };
10852 },
10853 generate: function(node) {
10854 this.chunk(node.name);
10855 }
10856 };
10857
10858 var TYPE$p = tokenizer.TYPE;
10859
10860 var HASH$3 = TYPE$p.Hash;
10861
10862 // <hash-token>
10863 var IdSelector = {
10864 name: 'IdSelector',
10865 structure: {
10866 name: String
10867 },
10868 parse: function() {
10869 var start = this.scanner.tokenStart;
10870
10871 // TODO: check value is an ident
10872 this.eat(HASH$3);
10873
10874 return {
10875 type: 'IdSelector',
10876 loc: this.getLocation(start, this.scanner.tokenStart),
10877 name: this.scanner.substrToCursor(start + 1)
10878 };
10879 },
10880 generate: function(node) {
10881 this.chunk('#');
10882 this.chunk(node.name);
10883 }
10884 };
10885
10886 var TYPE$q = tokenizer.TYPE;
10887
10888 var IDENT$9 = TYPE$q.Ident;
10889 var NUMBER$4 = TYPE$q.Number;
10890 var DIMENSION$4 = TYPE$q.Dimension;
10891 var LEFTPARENTHESIS$2 = TYPE$q.LeftParenthesis;
10892 var RIGHTPARENTHESIS$3 = TYPE$q.RightParenthesis;
10893 var COLON$2 = TYPE$q.Colon;
10894 var DELIM$3 = TYPE$q.Delim;
10895
10896 var MediaFeature = {
10897 name: 'MediaFeature',
10898 structure: {
10899 name: String,
10900 value: ['Identifier', 'Number', 'Dimension', 'Ratio', null]
10901 },
10902 parse: function() {
10903 var start = this.scanner.tokenStart;
10904 var name;
10905 var value = null;
10906
10907 this.eat(LEFTPARENTHESIS$2);
10908 this.scanner.skipSC();
10909
10910 name = this.consume(IDENT$9);
10911 this.scanner.skipSC();
10912
10913 if (this.scanner.tokenType !== RIGHTPARENTHESIS$3) {
10914 this.eat(COLON$2);
10915 this.scanner.skipSC();
10916
10917 switch (this.scanner.tokenType) {
10918 case NUMBER$4:
10919 if (this.lookupNonWSType(1) === DELIM$3) {
10920 value = this.Ratio();
10921 } else {
10922 value = this.Number();
10923 }
10924
10925 break;
10926
10927 case DIMENSION$4:
10928 value = this.Dimension();
10929 break;
10930
10931 case IDENT$9:
10932 value = this.Identifier();
10933
10934 break;
10935
10936 default:
10937 this.error('Number, dimension, ratio or identifier is expected');
10938 }
10939
10940 this.scanner.skipSC();
10941 }
10942
10943 this.eat(RIGHTPARENTHESIS$3);
10944
10945 return {
10946 type: 'MediaFeature',
10947 loc: this.getLocation(start, this.scanner.tokenStart),
10948 name: name,
10949 value: value
10950 };
10951 },
10952 generate: function(node) {
10953 this.chunk('(');
10954 this.chunk(node.name);
10955 if (node.value !== null) {
10956 this.chunk(':');
10957 this.node(node.value);
10958 }
10959 this.chunk(')');
10960 }
10961 };
10962
10963 var TYPE$r = tokenizer.TYPE;
10964
10965 var WHITESPACE$8 = TYPE$r.WhiteSpace;
10966 var COMMENT$8 = TYPE$r.Comment;
10967 var IDENT$a = TYPE$r.Ident;
10968 var LEFTPARENTHESIS$3 = TYPE$r.LeftParenthesis;
10969
10970 var MediaQuery = {
10971 name: 'MediaQuery',
10972 structure: {
10973 children: [[
10974 'Identifier',
10975 'MediaFeature',
10976 'WhiteSpace'
10977 ]]
10978 },
10979 parse: function() {
10980 this.scanner.skipSC();
10981
10982 var children = this.createList();
10983 var child = null;
10984 var space = null;
10985
10986 scan:
10987 while (!this.scanner.eof) {
10988 switch (this.scanner.tokenType) {
10989 case COMMENT$8:
10990 this.scanner.next();
10991 continue;
10992
10993 case WHITESPACE$8:
10994 space = this.WhiteSpace();
10995 continue;
10996
10997 case IDENT$a:
10998 child = this.Identifier();
10999 break;
11000
11001 case LEFTPARENTHESIS$3:
11002 child = this.MediaFeature();
11003 break;
11004
11005 default:
11006 break scan;
11007 }
11008
11009 if (space !== null) {
11010 children.push(space);
11011 space = null;
11012 }
11013
11014 children.push(child);
11015 }
11016
11017 if (child === null) {
11018 this.error('Identifier or parenthesis is expected');
11019 }
11020
11021 return {
11022 type: 'MediaQuery',
11023 loc: this.getLocationFromList(children),
11024 children: children
11025 };
11026 },
11027 generate: function(node) {
11028 this.children(node);
11029 }
11030 };
11031
11032 var COMMA$1 = tokenizer.TYPE.Comma;
11033
11034 var MediaQueryList = {
11035 name: 'MediaQueryList',
11036 structure: {
11037 children: [[
11038 'MediaQuery'
11039 ]]
11040 },
11041 parse: function(relative) {
11042 var children = this.createList();
11043
11044 this.scanner.skipSC();
11045
11046 while (!this.scanner.eof) {
11047 children.push(this.MediaQuery(relative));
11048
11049 if (this.scanner.tokenType !== COMMA$1) {
11050 break;
11051 }
11052
11053 this.scanner.next();
11054 }
11055
11056 return {
11057 type: 'MediaQueryList',
11058 loc: this.getLocationFromList(children),
11059 children: children
11060 };
11061 },
11062 generate: function(node) {
11063 this.children(node, function() {
11064 this.chunk(',');
11065 });
11066 }
11067 };
11068
11069 var Nth = {
11070 name: 'Nth',
11071 structure: {
11072 nth: ['AnPlusB', 'Identifier'],
11073 selector: ['SelectorList', null]
11074 },
11075 parse: function(allowOfClause) {
11076 this.scanner.skipSC();
11077
11078 var start = this.scanner.tokenStart;
11079 var end = start;
11080 var selector = null;
11081 var query;
11082
11083 if (this.scanner.lookupValue(0, 'odd') || this.scanner.lookupValue(0, 'even')) {
11084 query = this.Identifier();
11085 } else {
11086 query = this.AnPlusB();
11087 }
11088
11089 this.scanner.skipSC();
11090
11091 if (allowOfClause && this.scanner.lookupValue(0, 'of')) {
11092 this.scanner.next();
11093
11094 selector = this.SelectorList();
11095
11096 if (this.needPositions) {
11097 end = this.getLastListNode(selector.children).loc.end.offset;
11098 }
11099 } else {
11100 if (this.needPositions) {
11101 end = query.loc.end.offset;
11102 }
11103 }
11104
11105 return {
11106 type: 'Nth',
11107 loc: this.getLocation(start, end),
11108 nth: query,
11109 selector: selector
11110 };
11111 },
11112 generate: function(node) {
11113 this.node(node.nth);
11114 if (node.selector !== null) {
11115 this.chunk(' of ');
11116 this.node(node.selector);
11117 }
11118 }
11119 };
11120
11121 var NUMBER$5 = tokenizer.TYPE.Number;
11122
11123 var _Number = {
11124 name: 'Number',
11125 structure: {
11126 value: String
11127 },
11128 parse: function() {
11129 return {
11130 type: 'Number',
11131 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11132 value: this.consume(NUMBER$5)
11133 };
11134 },
11135 generate: function(node) {
11136 this.chunk(node.value);
11137 }
11138 };
11139
11140 // '/' | '*' | ',' | ':' | '+' | '-'
11141 var Operator = {
11142 name: 'Operator',
11143 structure: {
11144 value: String
11145 },
11146 parse: function() {
11147 var start = this.scanner.tokenStart;
11148
11149 this.scanner.next();
11150
11151 return {
11152 type: 'Operator',
11153 loc: this.getLocation(start, this.scanner.tokenStart),
11154 value: this.scanner.substrToCursor(start)
11155 };
11156 },
11157 generate: function(node) {
11158 this.chunk(node.value);
11159 }
11160 };
11161
11162 var TYPE$s = tokenizer.TYPE;
11163
11164 var LEFTPARENTHESIS$4 = TYPE$s.LeftParenthesis;
11165 var RIGHTPARENTHESIS$4 = TYPE$s.RightParenthesis;
11166
11167 var Parentheses = {
11168 name: 'Parentheses',
11169 structure: {
11170 children: [[]]
11171 },
11172 parse: function(readSequence, recognizer) {
11173 var start = this.scanner.tokenStart;
11174 var children = null;
11175
11176 this.eat(LEFTPARENTHESIS$4);
11177
11178 children = readSequence.call(this, recognizer);
11179
11180 if (!this.scanner.eof) {
11181 this.eat(RIGHTPARENTHESIS$4);
11182 }
11183
11184 return {
11185 type: 'Parentheses',
11186 loc: this.getLocation(start, this.scanner.tokenStart),
11187 children: children
11188 };
11189 },
11190 generate: function(node) {
11191 this.chunk('(');
11192 this.children(node);
11193 this.chunk(')');
11194 }
11195 };
11196
11197 var consumeNumber$4 = utils.consumeNumber;
11198 var TYPE$t = tokenizer.TYPE;
11199
11200 var PERCENTAGE$1 = TYPE$t.Percentage;
11201
11202 var Percentage = {
11203 name: 'Percentage',
11204 structure: {
11205 value: String
11206 },
11207 parse: function() {
11208 var start = this.scanner.tokenStart;
11209 var numberEnd = consumeNumber$4(this.scanner.source, start);
11210
11211 this.eat(PERCENTAGE$1);
11212
11213 return {
11214 type: 'Percentage',
11215 loc: this.getLocation(start, this.scanner.tokenStart),
11216 value: this.scanner.source.substring(start, numberEnd)
11217 };
11218 },
11219 generate: function(node) {
11220 this.chunk(node.value);
11221 this.chunk('%');
11222 }
11223 };
11224
11225 var TYPE$u = tokenizer.TYPE;
11226
11227 var IDENT$b = TYPE$u.Ident;
11228 var FUNCTION$1 = TYPE$u.Function;
11229 var COLON$3 = TYPE$u.Colon;
11230 var RIGHTPARENTHESIS$5 = TYPE$u.RightParenthesis;
11231
11232 // : [ <ident> | <function-token> <any-value>? ) ]
11233 var PseudoClassSelector = {
11234 name: 'PseudoClassSelector',
11235 structure: {
11236 name: String,
11237 children: [['Raw'], null]
11238 },
11239 parse: function() {
11240 var start = this.scanner.tokenStart;
11241 var children = null;
11242 var name;
11243 var nameLowerCase;
11244
11245 this.eat(COLON$3);
11246
11247 if (this.scanner.tokenType === FUNCTION$1) {
11248 name = this.consumeFunctionName();
11249 nameLowerCase = name.toLowerCase();
11250
11251 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11252 this.scanner.skipSC();
11253 children = this.pseudo[nameLowerCase].call(this);
11254 this.scanner.skipSC();
11255 } else {
11256 children = this.createList();
11257 children.push(
11258 this.Raw(this.scanner.tokenIndex, null, false)
11259 );
11260 }
11261
11262 this.eat(RIGHTPARENTHESIS$5);
11263 } else {
11264 name = this.consume(IDENT$b);
11265 }
11266
11267 return {
11268 type: 'PseudoClassSelector',
11269 loc: this.getLocation(start, this.scanner.tokenStart),
11270 name: name,
11271 children: children
11272 };
11273 },
11274 generate: function(node) {
11275 this.chunk(':');
11276 this.chunk(node.name);
11277
11278 if (node.children !== null) {
11279 this.chunk('(');
11280 this.children(node);
11281 this.chunk(')');
11282 }
11283 },
11284 walkContext: 'function'
11285 };
11286
11287 var TYPE$v = tokenizer.TYPE;
11288
11289 var IDENT$c = TYPE$v.Ident;
11290 var FUNCTION$2 = TYPE$v.Function;
11291 var COLON$4 = TYPE$v.Colon;
11292 var RIGHTPARENTHESIS$6 = TYPE$v.RightParenthesis;
11293
11294 // :: [ <ident> | <function-token> <any-value>? ) ]
11295 var PseudoElementSelector = {
11296 name: 'PseudoElementSelector',
11297 structure: {
11298 name: String,
11299 children: [['Raw'], null]
11300 },
11301 parse: function() {
11302 var start = this.scanner.tokenStart;
11303 var children = null;
11304 var name;
11305 var nameLowerCase;
11306
11307 this.eat(COLON$4);
11308 this.eat(COLON$4);
11309
11310 if (this.scanner.tokenType === FUNCTION$2) {
11311 name = this.consumeFunctionName();
11312 nameLowerCase = name.toLowerCase();
11313
11314 if (this.pseudo.hasOwnProperty(nameLowerCase)) {
11315 this.scanner.skipSC();
11316 children = this.pseudo[nameLowerCase].call(this);
11317 this.scanner.skipSC();
11318 } else {
11319 children = this.createList();
11320 children.push(
11321 this.Raw(this.scanner.tokenIndex, null, false)
11322 );
11323 }
11324
11325 this.eat(RIGHTPARENTHESIS$6);
11326 } else {
11327 name = this.consume(IDENT$c);
11328 }
11329
11330 return {
11331 type: 'PseudoElementSelector',
11332 loc: this.getLocation(start, this.scanner.tokenStart),
11333 name: name,
11334 children: children
11335 };
11336 },
11337 generate: function(node) {
11338 this.chunk('::');
11339 this.chunk(node.name);
11340
11341 if (node.children !== null) {
11342 this.chunk('(');
11343 this.children(node);
11344 this.chunk(')');
11345 }
11346 },
11347 walkContext: 'function'
11348 };
11349
11350 var isDigit$5 = tokenizer.isDigit;
11351 var TYPE$w = tokenizer.TYPE;
11352
11353 var NUMBER$6 = TYPE$w.Number;
11354 var DELIM$4 = TYPE$w.Delim;
11355 var SOLIDUS$3 = 0x002F; // U+002F SOLIDUS (/)
11356 var FULLSTOP$1 = 0x002E; // U+002E FULL STOP (.)
11357
11358 // Terms of <ratio> should be a positive numbers (not zero or negative)
11359 // (see https://drafts.csswg.org/mediaqueries-3/#values)
11360 // However, -o-min-device-pixel-ratio takes fractional values as a ratio's term
11361 // and this is using by various sites. Therefore we relax checking on parse
11362 // to test a term is unsigned number without an exponent part.
11363 // Additional checking may be applied on lexer validation.
11364 function consumeNumber$5() {
11365 this.scanner.skipWS();
11366
11367 var value = this.consume(NUMBER$6);
11368
11369 for (var i = 0; i < value.length; i++) {
11370 var code = value.charCodeAt(i);
11371 if (!isDigit$5(code) && code !== FULLSTOP$1) {
11372 this.error('Unsigned number is expected', this.scanner.tokenStart - value.length + i);
11373 }
11374 }
11375
11376 if (Number(value) === 0) {
11377 this.error('Zero number is not allowed', this.scanner.tokenStart - value.length);
11378 }
11379
11380 return value;
11381 }
11382
11383 // <positive-integer> S* '/' S* <positive-integer>
11384 var Ratio = {
11385 name: 'Ratio',
11386 structure: {
11387 left: String,
11388 right: String
11389 },
11390 parse: function() {
11391 var start = this.scanner.tokenStart;
11392 var left = consumeNumber$5.call(this);
11393 var right;
11394
11395 this.scanner.skipWS();
11396
11397 if (!this.scanner.isDelim(SOLIDUS$3)) {
11398 this.error('Solidus is expected');
11399 }
11400 this.eat(DELIM$4);
11401 right = consumeNumber$5.call(this);
11402
11403 return {
11404 type: 'Ratio',
11405 loc: this.getLocation(start, this.scanner.tokenStart),
11406 left: left,
11407 right: right
11408 };
11409 },
11410 generate: function(node) {
11411 this.chunk(node.left);
11412 this.chunk('/');
11413 this.chunk(node.right);
11414 }
11415 };
11416
11417 var TYPE$x = tokenizer.TYPE;
11418 var rawMode$4 = Raw.mode;
11419
11420 var LEFTCURLYBRACKET$4 = TYPE$x.LeftCurlyBracket;
11421
11422 function consumeRaw$3(startToken) {
11423 return this.Raw(startToken, rawMode$4.leftCurlyBracket, true);
11424 }
11425
11426 function consumePrelude() {
11427 var prelude = this.SelectorList();
11428
11429 if (prelude.type !== 'Raw' &&
11430 this.scanner.eof === false &&
11431 this.scanner.tokenType !== LEFTCURLYBRACKET$4) {
11432 this.error();
11433 }
11434
11435 return prelude;
11436 }
11437
11438 var Rule = {
11439 name: 'Rule',
11440 structure: {
11441 prelude: ['SelectorList', 'Raw'],
11442 block: ['Block']
11443 },
11444 parse: function() {
11445 var startToken = this.scanner.tokenIndex;
11446 var startOffset = this.scanner.tokenStart;
11447 var prelude;
11448 var block;
11449
11450 if (this.parseRulePrelude) {
11451 prelude = this.parseWithFallback(consumePrelude, consumeRaw$3);
11452 } else {
11453 prelude = consumeRaw$3.call(this, startToken);
11454 }
11455
11456 block = this.Block(true);
11457
11458 return {
11459 type: 'Rule',
11460 loc: this.getLocation(startOffset, this.scanner.tokenStart),
11461 prelude: prelude,
11462 block: block
11463 };
11464 },
11465 generate: function(node) {
11466 this.node(node.prelude);
11467 this.node(node.block);
11468 },
11469 walkContext: 'rule'
11470 };
11471
11472 var Selector = {
11473 name: 'Selector',
11474 structure: {
11475 children: [[
11476 'TypeSelector',
11477 'IdSelector',
11478 'ClassSelector',
11479 'AttributeSelector',
11480 'PseudoClassSelector',
11481 'PseudoElementSelector',
11482 'Combinator',
11483 'WhiteSpace'
11484 ]]
11485 },
11486 parse: function() {
11487 var children = this.readSequence(this.scope.Selector);
11488
11489 // nothing were consumed
11490 if (this.getFirstListNode(children) === null) {
11491 this.error('Selector is expected');
11492 }
11493
11494 return {
11495 type: 'Selector',
11496 loc: this.getLocationFromList(children),
11497 children: children
11498 };
11499 },
11500 generate: function(node) {
11501 this.children(node);
11502 }
11503 };
11504
11505 var TYPE$y = tokenizer.TYPE;
11506
11507 var COMMA$2 = TYPE$y.Comma;
11508
11509 var SelectorList = {
11510 name: 'SelectorList',
11511 structure: {
11512 children: [[
11513 'Selector',
11514 'Raw'
11515 ]]
11516 },
11517 parse: function() {
11518 var children = this.createList();
11519
11520 while (!this.scanner.eof) {
11521 children.push(this.Selector());
11522
11523 if (this.scanner.tokenType === COMMA$2) {
11524 this.scanner.next();
11525 continue;
11526 }
11527
11528 break;
11529 }
11530
11531 return {
11532 type: 'SelectorList',
11533 loc: this.getLocationFromList(children),
11534 children: children
11535 };
11536 },
11537 generate: function(node) {
11538 this.children(node, function() {
11539 this.chunk(',');
11540 });
11541 },
11542 walkContext: 'selector'
11543 };
11544
11545 var STRING$1 = tokenizer.TYPE.String;
11546
11547 var _String = {
11548 name: 'String',
11549 structure: {
11550 value: String
11551 },
11552 parse: function() {
11553 return {
11554 type: 'String',
11555 loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11556 value: this.consume(STRING$1)
11557 };
11558 },
11559 generate: function(node) {
11560 this.chunk(node.value);
11561 }
11562 };
11563
11564 var TYPE$z = tokenizer.TYPE;
11565
11566 var WHITESPACE$9 = TYPE$z.WhiteSpace;
11567 var COMMENT$9 = TYPE$z.Comment;
11568 var ATKEYWORD$2 = TYPE$z.AtKeyword;
11569 var CDO$1 = TYPE$z.CDO;
11570 var CDC$1 = TYPE$z.CDC;
11571 var EXCLAMATIONMARK$3 = 0x0021; // U+0021 EXCLAMATION MARK (!)
11572
11573 function consumeRaw$4(startToken) {
11574 return this.Raw(startToken, null, false);
11575 }
11576
11577 var StyleSheet = {
11578 name: 'StyleSheet',
11579 structure: {
11580 children: [[
11581 'Comment',
11582 'CDO',
11583 'CDC',
11584 'Atrule',
11585 'Rule',
11586 'Raw'
11587 ]]
11588 },
11589 parse: function() {
11590 var start = this.scanner.tokenStart;
11591 var children = this.createList();
11592 var child;
11593
11594
11595 while (!this.scanner.eof) {
11596 switch (this.scanner.tokenType) {
11597 case WHITESPACE$9:
11598 this.scanner.next();
11599 continue;
11600
11601 case COMMENT$9:
11602 // ignore comments except exclamation comments (i.e. /*! .. */) on top level
11603 if (this.scanner.source.charCodeAt(this.scanner.tokenStart + 2) !== EXCLAMATIONMARK$3) {
11604 this.scanner.next();
11605 continue;
11606 }
11607
11608 child = this.Comment();
11609 break;
11610
11611 case CDO$1: // <!--
11612 child = this.CDO();
11613 break;
11614
11615 case CDC$1: // -->
11616 child = this.CDC();
11617 break;
11618
11619 // CSS Syntax Module Level 3
11620 // §2.2 Error handling
11621 // At the "top level" of a stylesheet, an <at-keyword-token> starts an at-rule.
11622 case ATKEYWORD$2:
11623 child = this.parseWithFallback(this.Atrule, consumeRaw$4);
11624 break;
11625
11626 // Anything else starts a qualified rule ...
11627 default:
11628 child = this.parseWithFallback(this.Rule, consumeRaw$4);
11629 }
11630
11631 children.push(child);
11632 }
11633
11634 return {
11635 type: 'StyleSheet',
11636 loc: this.getLocation(start, this.scanner.tokenStart),
11637 children: children
11638 };
11639 },
11640 generate: function(node) {
11641 this.children(node);
11642 },
11643 walkContext: 'stylesheet'
11644 };
11645
11646 var TYPE$A = tokenizer.TYPE;
11647
11648 var IDENT$d = TYPE$A.Ident;
11649 var ASTERISK$4 = 0x002A; // U+002A ASTERISK (*)
11650 var VERTICALLINE$2 = 0x007C; // U+007C VERTICAL LINE (|)
11651
11652 function eatIdentifierOrAsterisk() {
11653 if (this.scanner.tokenType !== IDENT$d &&
11654 this.scanner.isDelim(ASTERISK$4) === false) {
11655 this.error('Identifier or asterisk is expected');
11656 }
11657
11658 this.scanner.next();
11659 }
11660
11661 // ident
11662 // ident|ident
11663 // ident|*
11664 // *
11665 // *|ident
11666 // *|*
11667 // |ident
11668 // |*
11669 var TypeSelector = {
11670 name: 'TypeSelector',
11671 structure: {
11672 name: String
11673 },
11674 parse: function() {
11675 var start = this.scanner.tokenStart;
11676
11677 if (this.scanner.isDelim(VERTICALLINE$2)) {
11678 this.scanner.next();
11679 eatIdentifierOrAsterisk.call(this);
11680 } else {
11681 eatIdentifierOrAsterisk.call(this);
11682
11683 if (this.scanner.isDelim(VERTICALLINE$2)) {
11684 this.scanner.next();
11685 eatIdentifierOrAsterisk.call(this);
11686 }
11687 }
11688
11689 return {
11690 type: 'TypeSelector',
11691 loc: this.getLocation(start, this.scanner.tokenStart),
11692 name: this.scanner.substrToCursor(start)
11693 };
11694 },
11695 generate: function(node) {
11696 this.chunk(node.name);
11697 }
11698 };
11699
11700 var isHexDigit$4 = tokenizer.isHexDigit;
11701 var cmpChar$4 = tokenizer.cmpChar;
11702 var TYPE$B = tokenizer.TYPE;
11703 var NAME$3 = tokenizer.NAME;
11704
11705 var IDENT$e = TYPE$B.Ident;
11706 var NUMBER$7 = TYPE$B.Number;
11707 var DIMENSION$5 = TYPE$B.Dimension;
11708 var PLUSSIGN$6 = 0x002B; // U+002B PLUS SIGN (+)
11709 var HYPHENMINUS$4 = 0x002D; // U+002D HYPHEN-MINUS (-)
11710 var QUESTIONMARK$2 = 0x003F; // U+003F QUESTION MARK (?)
11711 var U$1 = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
11712
11713 function eatHexSequence(offset, allowDash) {
11714 for (var pos = this.scanner.tokenStart + offset, len = 0; pos < this.scanner.tokenEnd; pos++) {
11715 var code = this.scanner.source.charCodeAt(pos);
11716
11717 if (code === HYPHENMINUS$4 && allowDash && len !== 0) {
11718 if (eatHexSequence.call(this, offset + len + 1, false) === 0) {
11719 this.error();
11720 }
11721
11722 return -1;
11723 }
11724
11725 if (!isHexDigit$4(code)) {
11726 this.error(
11727 allowDash && len !== 0
11728 ? 'HyphenMinus' + (len < 6 ? ' or hex digit' : '') + ' is expected'
11729 : (len < 6 ? 'Hex digit is expected' : 'Unexpected input'),
11730 pos
11731 );
11732 }
11733
11734 if (++len > 6) {
11735 this.error('Too many hex digits', pos);
11736 } }
11737
11738 this.scanner.next();
11739 return len;
11740 }
11741
11742 function eatQuestionMarkSequence(max) {
11743 var count = 0;
11744
11745 while (this.scanner.isDelim(QUESTIONMARK$2)) {
11746 if (++count > max) {
11747 this.error('Too many question marks');
11748 }
11749
11750 this.scanner.next();
11751 }
11752 }
11753
11754 function startsWith$1(code) {
11755 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) !== code) {
11756 this.error(NAME$3[code] + ' is expected');
11757 }
11758 }
11759
11760 // https://drafts.csswg.org/css-syntax/#urange
11761 // Informally, the <urange> production has three forms:
11762 // U+0001
11763 // Defines a range consisting of a single code point, in this case the code point "1".
11764 // U+0001-00ff
11765 // Defines a range of codepoints between the first and the second value, in this case
11766 // the range between "1" and "ff" (255 in decimal) inclusive.
11767 // U+00??
11768 // Defines a range of codepoints where the "?" characters range over all hex digits,
11769 // in this case defining the same as the value U+0000-00ff.
11770 // In each form, a maximum of 6 digits is allowed for each hexadecimal number (if you treat "?" as a hexadecimal digit).
11771 //
11772 // <urange> =
11773 // u '+' <ident-token> '?'* |
11774 // u <dimension-token> '?'* |
11775 // u <number-token> '?'* |
11776 // u <number-token> <dimension-token> |
11777 // u <number-token> <number-token> |
11778 // u '+' '?'+
11779 function scanUnicodeRange() {
11780 var hexLength = 0;
11781
11782 // u '+' <ident-token> '?'*
11783 // u '+' '?'+
11784 if (this.scanner.isDelim(PLUSSIGN$6)) {
11785 this.scanner.next();
11786
11787 if (this.scanner.tokenType === IDENT$e) {
11788 hexLength = eatHexSequence.call(this, 0, true);
11789 if (hexLength > 0) {
11790 eatQuestionMarkSequence.call(this, 6 - hexLength);
11791 }
11792 return;
11793 }
11794
11795 if (this.scanner.isDelim(QUESTIONMARK$2)) {
11796 this.scanner.next();
11797 eatQuestionMarkSequence.call(this, 5);
11798 return;
11799 }
11800
11801 this.error('Hex digit or question mark is expected');
11802 return;
11803 }
11804
11805 // u <number-token> '?'*
11806 // u <number-token> <dimension-token>
11807 // u <number-token> <number-token>
11808 if (this.scanner.tokenType === NUMBER$7) {
11809 startsWith$1.call(this, PLUSSIGN$6);
11810 hexLength = eatHexSequence.call(this, 1, true);
11811
11812 if (this.scanner.isDelim(QUESTIONMARK$2)) {
11813 eatQuestionMarkSequence.call(this, 6 - hexLength);
11814 return;
11815 }
11816
11817 if (this.scanner.tokenType === DIMENSION$5 ||
11818 this.scanner.tokenType === NUMBER$7) {
11819 startsWith$1.call(this, HYPHENMINUS$4);
11820 eatHexSequence.call(this, 1, false);
11821 return;
11822 }
11823
11824 return;
11825 }
11826
11827 // u <dimension-token> '?'*
11828 if (this.scanner.tokenType === DIMENSION$5) {
11829 startsWith$1.call(this, PLUSSIGN$6);
11830 hexLength = eatHexSequence.call(this, 1, true);
11831
11832 if (hexLength > 0) {
11833 eatQuestionMarkSequence.call(this, 6 - hexLength);
11834 }
11835
11836 return;
11837 }
11838
11839 this.error();
11840 }
11841
11842 var UnicodeRange = {
11843 name: 'UnicodeRange',
11844 structure: {
11845 value: String
11846 },
11847 parse: function() {
11848 var start = this.scanner.tokenStart;
11849
11850 // U or u
11851 if (!cmpChar$4(this.scanner.source, start, U$1)) {
11852 this.error('U is expected');
11853 }
11854
11855 if (!cmpChar$4(this.scanner.source, start + 1, PLUSSIGN$6)) {
11856 this.error('Plus sign is expected');
11857 }
11858
11859 this.scanner.next();
11860 scanUnicodeRange.call(this);
11861
11862 return {
11863 type: 'UnicodeRange',
11864 loc: this.getLocation(start, this.scanner.tokenStart),
11865 value: this.scanner.substrToCursor(start)
11866 };
11867 },
11868 generate: function(node) {
11869 this.chunk(node.value);
11870 }
11871 };
11872
11873 var isWhiteSpace$2 = tokenizer.isWhiteSpace;
11874 var cmpStr$5 = tokenizer.cmpStr;
11875 var TYPE$C = tokenizer.TYPE;
11876
11877 var FUNCTION$3 = TYPE$C.Function;
11878 var URL$1 = TYPE$C.Url;
11879 var RIGHTPARENTHESIS$7 = TYPE$C.RightParenthesis;
11880
11881 // <url-token> | <function-token> <string> )
11882 var Url = {
11883 name: 'Url',
11884 structure: {
11885 value: ['String', 'Raw']
11886 },
11887 parse: function() {
11888 var start = this.scanner.tokenStart;
11889 var value;
11890
11891 switch (this.scanner.tokenType) {
11892 case URL$1:
11893 var rawStart = start + 4;
11894 var rawEnd = this.scanner.tokenEnd - 1;
11895
11896 while (rawStart < rawEnd && isWhiteSpace$2(this.scanner.source.charCodeAt(rawStart))) {
11897 rawStart++;
11898 }
11899
11900 while (rawStart < rawEnd && isWhiteSpace$2(this.scanner.source.charCodeAt(rawEnd - 1))) {
11901 rawEnd--;
11902 }
11903
11904 value = {
11905 type: 'Raw',
11906 loc: this.getLocation(rawStart, rawEnd),
11907 value: this.scanner.source.substring(rawStart, rawEnd)
11908 };
11909
11910 this.eat(URL$1);
11911 break;
11912
11913 case FUNCTION$3:
11914 if (!cmpStr$5(this.scanner.source, this.scanner.tokenStart, this.scanner.tokenEnd, 'url(')) {
11915 this.error('Function name must be `url`');
11916 }
11917
11918 this.eat(FUNCTION$3);
11919 this.scanner.skipSC();
11920 value = this.String();
11921 this.scanner.skipSC();
11922 this.eat(RIGHTPARENTHESIS$7);
11923 break;
11924
11925 default:
11926 this.error('Url or Function is expected');
11927 }
11928
11929 return {
11930 type: 'Url',
11931 loc: this.getLocation(start, this.scanner.tokenStart),
11932 value: value
11933 };
11934 },
11935 generate: function(node) {
11936 this.chunk('url');
11937 this.chunk('(');
11938 this.node(node.value);
11939 this.chunk(')');
11940 }
11941 };
11942
11943 var Value = {
11944 name: 'Value',
11945 structure: {
11946 children: [[]]
11947 },
11948 parse: function() {
11949 var start = this.scanner.tokenStart;
11950 var children = this.readSequence(this.scope.Value);
11951
11952 return {
11953 type: 'Value',
11954 loc: this.getLocation(start, this.scanner.tokenStart),
11955 children: children
11956 };
11957 },
11958 generate: function(node) {
11959 this.children(node);
11960 }
11961 };
11962
11963 var WHITESPACE$a = tokenizer.TYPE.WhiteSpace;
11964 var SPACE$2 = Object.freeze({
11965 type: 'WhiteSpace',
11966 loc: null,
11967 value: ' '
11968 });
11969
11970 var WhiteSpace$1 = {
11971 name: 'WhiteSpace',
11972 structure: {
11973 value: String
11974 },
11975 parse: function() {
11976 this.eat(WHITESPACE$a);
11977 return SPACE$2;
11978
11979 // return {
11980 // type: 'WhiteSpace',
11981 // loc: this.getLocation(this.scanner.tokenStart, this.scanner.tokenEnd),
11982 // value: this.consume(WHITESPACE)
11983 // };
11984 },
11985 generate: function(node) {
11986 this.chunk(node.value);
11987 }
11988 };
11989
11990 var node = {
11991 AnPlusB: AnPlusB,
11992 Atrule: Atrule,
11993 AtrulePrelude: AtrulePrelude,
11994 AttributeSelector: AttributeSelector,
11995 Block: Block,
11996 Brackets: Brackets,
11997 CDC: CDC_1,
11998 CDO: CDO_1,
11999 ClassSelector: ClassSelector,
12000 Combinator: Combinator,
12001 Comment: Comment,
12002 Declaration: Declaration,
12003 DeclarationList: DeclarationList,
12004 Dimension: Dimension,
12005 Function: _Function,
12006 Hash: Hash,
12007 Identifier: Identifier,
12008 IdSelector: IdSelector,
12009 MediaFeature: MediaFeature,
12010 MediaQuery: MediaQuery,
12011 MediaQueryList: MediaQueryList,
12012 Nth: Nth,
12013 Number: _Number,
12014 Operator: Operator,
12015 Parentheses: Parentheses,
12016 Percentage: Percentage,
12017 PseudoClassSelector: PseudoClassSelector,
12018 PseudoElementSelector: PseudoElementSelector,
12019 Ratio: Ratio,
12020 Raw: Raw,
12021 Rule: Rule,
12022 Selector: Selector,
12023 SelectorList: SelectorList,
12024 String: _String,
12025 StyleSheet: StyleSheet,
12026 TypeSelector: TypeSelector,
12027 UnicodeRange: UnicodeRange,
12028 Url: Url,
12029 Value: Value,
12030 WhiteSpace: WhiteSpace$1
12031 };
12032
12033 var lexer = {
12034 generic: true,
12035 types: data.types,
12036 atrules: data.atrules,
12037 properties: data.properties,
12038 node: node
12039 };
12040
12041 var cmpChar$5 = tokenizer.cmpChar;
12042 var cmpStr$6 = tokenizer.cmpStr;
12043 var TYPE$D = tokenizer.TYPE;
12044
12045 var IDENT$f = TYPE$D.Ident;
12046 var STRING$2 = TYPE$D.String;
12047 var NUMBER$8 = TYPE$D.Number;
12048 var FUNCTION$4 = TYPE$D.Function;
12049 var URL$2 = TYPE$D.Url;
12050 var HASH$4 = TYPE$D.Hash;
12051 var DIMENSION$6 = TYPE$D.Dimension;
12052 var PERCENTAGE$2 = TYPE$D.Percentage;
12053 var LEFTPARENTHESIS$5 = TYPE$D.LeftParenthesis;
12054 var LEFTSQUAREBRACKET$3 = TYPE$D.LeftSquareBracket;
12055 var COMMA$3 = TYPE$D.Comma;
12056 var DELIM$5 = TYPE$D.Delim;
12057 var NUMBERSIGN$3 = 0x0023; // U+0023 NUMBER SIGN (#)
12058 var ASTERISK$5 = 0x002A; // U+002A ASTERISK (*)
12059 var PLUSSIGN$7 = 0x002B; // U+002B PLUS SIGN (+)
12060 var HYPHENMINUS$5 = 0x002D; // U+002D HYPHEN-MINUS (-)
12061 var SOLIDUS$4 = 0x002F; // U+002F SOLIDUS (/)
12062 var U$2 = 0x0075; // U+0075 LATIN SMALL LETTER U (u)
12063
12064 var _default = function defaultRecognizer(context) {
12065 switch (this.scanner.tokenType) {
12066 case HASH$4:
12067 return this.Hash();
12068
12069 case COMMA$3:
12070 context.space = null;
12071 context.ignoreWSAfter = true;
12072 return this.Operator();
12073
12074 case LEFTPARENTHESIS$5:
12075 return this.Parentheses(this.readSequence, context.recognizer);
12076
12077 case LEFTSQUAREBRACKET$3:
12078 return this.Brackets(this.readSequence, context.recognizer);
12079
12080 case STRING$2:
12081 return this.String();
12082
12083 case DIMENSION$6:
12084 return this.Dimension();
12085
12086 case PERCENTAGE$2:
12087 return this.Percentage();
12088
12089 case NUMBER$8:
12090 return this.Number();
12091
12092 case FUNCTION$4:
12093 return cmpStr$6(this.scanner.source, this.scanner.tokenStart, this.scanner.tokenEnd, 'url(')
12094 ? this.Url()
12095 : this.Function(this.readSequence, context.recognizer);
12096
12097 case URL$2:
12098 return this.Url();
12099
12100 case IDENT$f:
12101 // check for unicode range, it should start with u+ or U+
12102 if (cmpChar$5(this.scanner.source, this.scanner.tokenStart, U$2) &&
12103 cmpChar$5(this.scanner.source, this.scanner.tokenStart + 1, PLUSSIGN$7)) {
12104 return this.UnicodeRange();
12105 } else {
12106 return this.Identifier();
12107 }
12108
12109 case DELIM$5:
12110 var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
12111
12112 if (code === SOLIDUS$4 ||
12113 code === ASTERISK$5 ||
12114 code === PLUSSIGN$7 ||
12115 code === HYPHENMINUS$5) {
12116 return this.Operator(); // TODO: replace with Delim
12117 }
12118
12119 // TODO: produce a node with Delim node type
12120
12121 if (code === NUMBERSIGN$3) {
12122 this.error('Hex or identifier is expected', this.scanner.tokenStart + 1);
12123 }
12124
12125 break;
12126 }
12127 };
12128
12129 var atrulePrelude = {
12130 getNode: _default
12131 };
12132
12133 var TYPE$E = tokenizer.TYPE;
12134
12135 var DELIM$6 = TYPE$E.Delim;
12136 var IDENT$g = TYPE$E.Ident;
12137 var DIMENSION$7 = TYPE$E.Dimension;
12138 var PERCENTAGE$3 = TYPE$E.Percentage;
12139 var NUMBER$9 = TYPE$E.Number;
12140 var HASH$5 = TYPE$E.Hash;
12141 var COLON$5 = TYPE$E.Colon;
12142 var LEFTSQUAREBRACKET$4 = TYPE$E.LeftSquareBracket;
12143 var NUMBERSIGN$4 = 0x0023; // U+0023 NUMBER SIGN (#)
12144 var ASTERISK$6 = 0x002A; // U+002A ASTERISK (*)
12145 var PLUSSIGN$8 = 0x002B; // U+002B PLUS SIGN (+)
12146 var SOLIDUS$5 = 0x002F; // U+002F SOLIDUS (/)
12147 var FULLSTOP$2 = 0x002E; // U+002E FULL STOP (.)
12148 var GREATERTHANSIGN$2 = 0x003E; // U+003E GREATER-THAN SIGN (>)
12149 var VERTICALLINE$3 = 0x007C; // U+007C VERTICAL LINE (|)
12150 var TILDE$2 = 0x007E; // U+007E TILDE (~)
12151
12152 function getNode(context) {
12153 switch (this.scanner.tokenType) {
12154 case LEFTSQUAREBRACKET$4:
12155 return this.AttributeSelector();
12156
12157 case HASH$5:
12158 return this.IdSelector();
12159
12160 case COLON$5:
12161 if (this.scanner.lookupType(1) === COLON$5) {
12162 return this.PseudoElementSelector();
12163 } else {
12164 return this.PseudoClassSelector();
12165 }
12166
12167 case IDENT$g:
12168 return this.TypeSelector();
12169
12170 case NUMBER$9:
12171 case PERCENTAGE$3:
12172 return this.Percentage();
12173
12174 case DIMENSION$7:
12175 // throws when .123ident
12176 if (this.scanner.source.charCodeAt(this.scanner.tokenStart) === FULLSTOP$2) {
12177 this.error('Identifier is expected', this.scanner.tokenStart + 1);
12178 }
12179 break;
12180
12181 case DELIM$6:
12182 var code = this.scanner.source.charCodeAt(this.scanner.tokenStart);
12183
12184 switch (code) {
12185 case PLUSSIGN$8:
12186 case GREATERTHANSIGN$2:
12187 case TILDE$2:
12188 context.space = null;
12189 context.ignoreWSAfter = true;
12190 return this.Combinator();
12191
12192 case SOLIDUS$5: // /deep/
12193 return this.Combinator();
12194
12195 case FULLSTOP$2:
12196 return this.ClassSelector();
12197
12198 case ASTERISK$6:
12199 case VERTICALLINE$3:
12200 return this.TypeSelector();
12201
12202 case NUMBERSIGN$4:
12203 return this.IdSelector();
12204 }
12205
12206 break;
12207 }
12208 }
12209 var selector = {
12210 getNode: getNode
12211 };
12212
12213 // legacy IE function
12214 // expression( <any-value> )
12215 var expression = function() {
12216 return this.createSingleNodeList(
12217 this.Raw(this.scanner.tokenIndex, null, false)
12218 );
12219 };
12220
12221 var TYPE$F = tokenizer.TYPE;
12222 var rawMode$5 = Raw.mode;
12223
12224 var COMMA$4 = TYPE$F.Comma;
12225 var WHITESPACE$b = TYPE$F.WhiteSpace;
12226
12227 // var( <ident> , <value>? )
12228 var _var = function() {
12229 var children = this.createList();
12230
12231 this.scanner.skipSC();
12232
12233 // NOTE: Don't check more than a first argument is an ident, rest checks are for lexer
12234 children.push(this.Identifier());
12235
12236 this.scanner.skipSC();
12237
12238 if (this.scanner.tokenType === COMMA$4) {
12239 children.push(this.Operator());
12240
12241 const startIndex = this.scanner.tokenIndex;
12242 const value = this.parseCustomProperty
12243 ? this.Value(null)
12244 : this.Raw(this.scanner.tokenIndex, rawMode$5.exclamationMarkOrSemicolon, false);
12245
12246 if (value.type === 'Value' && value.children.isEmpty()) {
12247 for (let offset = startIndex - this.scanner.tokenIndex; offset <= 0; offset++) {
12248 if (this.scanner.lookupType(offset) === WHITESPACE$b) {
12249 value.children.appendData({
12250 type: 'WhiteSpace',
12251 loc: null,
12252 value: ' '
12253 });
12254 break;
12255 }
12256 }
12257 }
12258
12259 children.push(value);
12260 }
12261
12262 return children;
12263 };
12264
12265 var value = {
12266 getNode: _default,
12267 'expression': expression,
12268 'var': _var
12269 };
12270
12271 var scope = {
12272 AtrulePrelude: atrulePrelude,
12273 Selector: selector,
12274 Value: value
12275 };
12276
12277 var fontFace = {
12278 parse: {
12279 prelude: null,
12280 block: function() {
12281 return this.Block(true);
12282 }
12283 }
12284 };
12285
12286 var TYPE$G = tokenizer.TYPE;
12287
12288 var STRING$3 = TYPE$G.String;
12289 var IDENT$h = TYPE$G.Ident;
12290 var URL$3 = TYPE$G.Url;
12291 var FUNCTION$5 = TYPE$G.Function;
12292 var LEFTPARENTHESIS$6 = TYPE$G.LeftParenthesis;
12293
12294 var _import = {
12295 parse: {
12296 prelude: function() {
12297 var children = this.createList();
12298
12299 this.scanner.skipSC();
12300
12301 switch (this.scanner.tokenType) {
12302 case STRING$3:
12303 children.push(this.String());
12304 break;
12305
12306 case URL$3:
12307 case FUNCTION$5:
12308 children.push(this.Url());
12309 break;
12310
12311 default:
12312 this.error('String or url() is expected');
12313 }
12314
12315 if (this.lookupNonWSType(0) === IDENT$h ||
12316 this.lookupNonWSType(0) === LEFTPARENTHESIS$6) {
12317 children.push(this.WhiteSpace());
12318 children.push(this.MediaQueryList());
12319 }
12320
12321 return children;
12322 },
12323 block: null
12324 }
12325 };
12326
12327 var media = {
12328 parse: {
12329 prelude: function() {
12330 return this.createSingleNodeList(
12331 this.MediaQueryList()
12332 );
12333 },
12334 block: function() {
12335 return this.Block(false);
12336 }
12337 }
12338 };
12339
12340 var page = {
12341 parse: {
12342 prelude: function() {
12343 return this.createSingleNodeList(
12344 this.SelectorList()
12345 );
12346 },
12347 block: function() {
12348 return this.Block(true);
12349 }
12350 }
12351 };
12352
12353 var TYPE$H = tokenizer.TYPE;
12354
12355 var WHITESPACE$c = TYPE$H.WhiteSpace;
12356 var COMMENT$a = TYPE$H.Comment;
12357 var IDENT$i = TYPE$H.Ident;
12358 var FUNCTION$6 = TYPE$H.Function;
12359 var COLON$6 = TYPE$H.Colon;
12360 var LEFTPARENTHESIS$7 = TYPE$H.LeftParenthesis;
12361
12362 function consumeRaw$5() {
12363 return this.createSingleNodeList(
12364 this.Raw(this.scanner.tokenIndex, null, false)
12365 );
12366 }
12367
12368 function parentheses() {
12369 this.scanner.skipSC();
12370
12371 if (this.scanner.tokenType === IDENT$i &&
12372 this.lookupNonWSType(1) === COLON$6) {
12373 return this.createSingleNodeList(
12374 this.Declaration()
12375 );
12376 }
12377
12378 return readSequence.call(this);
12379 }
12380
12381 function readSequence() {
12382 var children = this.createList();
12383 var space = null;
12384 var child;
12385
12386 this.scanner.skipSC();
12387
12388 scan:
12389 while (!this.scanner.eof) {
12390 switch (this.scanner.tokenType) {
12391 case WHITESPACE$c:
12392 space = this.WhiteSpace();
12393 continue;
12394
12395 case COMMENT$a:
12396 this.scanner.next();
12397 continue;
12398
12399 case FUNCTION$6:
12400 child = this.Function(consumeRaw$5, this.scope.AtrulePrelude);
12401 break;
12402
12403 case IDENT$i:
12404 child = this.Identifier();
12405 break;
12406
12407 case LEFTPARENTHESIS$7:
12408 child = this.Parentheses(parentheses, this.scope.AtrulePrelude);
12409 break;
12410
12411 default:
12412 break scan;
12413 }
12414
12415 if (space !== null) {
12416 children.push(space);
12417 space = null;
12418 }
12419
12420 children.push(child);
12421 }
12422
12423 return children;
12424 }
12425
12426 var supports = {
12427 parse: {
12428 prelude: function() {
12429 var children = readSequence.call(this);
12430
12431 if (this.getFirstListNode(children) === null) {
12432 this.error('Condition is expected');
12433 }
12434
12435 return children;
12436 },
12437 block: function() {
12438 return this.Block(false);
12439 }
12440 }
12441 };
12442
12443 var atrule = {
12444 'font-face': fontFace,
12445 'import': _import,
12446 'media': media,
12447 'page': page,
12448 'supports': supports
12449 };
12450
12451 var dir = {
12452 parse: function() {
12453 return this.createSingleNodeList(
12454 this.Identifier()
12455 );
12456 }
12457 };
12458
12459 var has$1 = {
12460 parse: function() {
12461 return this.createSingleNodeList(
12462 this.SelectorList()
12463 );
12464 }
12465 };
12466
12467 var lang = {
12468 parse: function() {
12469 return this.createSingleNodeList(
12470 this.Identifier()
12471 );
12472 }
12473 };
12474
12475 var selectorList = {
12476 parse: function selectorList() {
12477 return this.createSingleNodeList(
12478 this.SelectorList()
12479 );
12480 }
12481 };
12482
12483 var matches = selectorList;
12484
12485 var not = selectorList;
12486
12487 var ALLOW_OF_CLAUSE = true;
12488
12489 var nthWithOfClause = {
12490 parse: function nthWithOfClause() {
12491 return this.createSingleNodeList(
12492 this.Nth(ALLOW_OF_CLAUSE)
12493 );
12494 }
12495 };
12496
12497 var nthChild = nthWithOfClause;
12498
12499 var nthLastChild = nthWithOfClause;
12500
12501 var DISALLOW_OF_CLAUSE = false;
12502
12503 var nth = {
12504 parse: function nth() {
12505 return this.createSingleNodeList(
12506 this.Nth(DISALLOW_OF_CLAUSE)
12507 );
12508 }
12509 };
12510
12511 var nthLastOfType = nth;
12512
12513 var nthOfType = nth;
12514
12515 var slotted = {
12516 parse: function compoundSelector() {
12517 return this.createSingleNodeList(
12518 this.Selector()
12519 );
12520 }
12521 };
12522
12523 var pseudo = {
12524 'dir': dir,
12525 'has': has$1,
12526 'lang': lang,
12527 'matches': matches,
12528 'not': not,
12529 'nth-child': nthChild,
12530 'nth-last-child': nthLastChild,
12531 'nth-last-of-type': nthLastOfType,
12532 'nth-of-type': nthOfType,
12533 'slotted': slotted
12534 };
12535
12536 var parser = {
12537 parseContext: {
12538 default: 'StyleSheet',
12539 stylesheet: 'StyleSheet',
12540 atrule: 'Atrule',
12541 atrulePrelude: function(options) {
12542 return this.AtrulePrelude(options.atrule ? String(options.atrule) : null);
12543 },
12544 mediaQueryList: 'MediaQueryList',
12545 mediaQuery: 'MediaQuery',
12546 rule: 'Rule',
12547 selectorList: 'SelectorList',
12548 selector: 'Selector',
12549 block: function() {
12550 return this.Block(true);
12551 },
12552 declarationList: 'DeclarationList',
12553 declaration: 'Declaration',
12554 value: 'Value'
12555 },
12556 scope: scope,
12557 atrule: atrule,
12558 pseudo: pseudo,
12559 node: node
12560 };
12561
12562 var walker = {
12563 node: node
12564 };
12565
12566 var version = "1.1.3";
12567 var _package = {
12568 version: version
12569 };
12570
12571 var _package$1 = /*#__PURE__*/Object.freeze({
12572 __proto__: null,
12573 version: version,
12574 'default': _package
12575 });
12576
12577 var require$$4 = getCjsExportFromNamespace(_package$1);
12578
12579 function merge() {
12580 var dest = {};
12581
12582 for (var i = 0; i < arguments.length; i++) {
12583 var src = arguments[i];
12584 for (var key in src) {
12585 dest[key] = src[key];
12586 }
12587 }
12588
12589 return dest;
12590 }
12591
12592 var syntax = create$4.create(
12593 merge(
12594 lexer,
12595 parser,
12596 walker
12597 )
12598 );
12599 var version$1 = require$$4.version;
12600 syntax.version = version$1;
12601
12602 var lib = syntax;
12603
12604 return lib;
12605
12606})));