1 |
|
2 |
|
3 |
|
4 | function isNumber$1(code) {
|
5 | return code > 47 && code < 58;
|
6 | }
|
7 |
|
8 |
|
9 |
|
10 | function isAlpha$1(code, from, to) {
|
11 | from = from || 65;
|
12 | to = to || 90;
|
13 | code &= ~32;
|
14 | return code >= from && code <= to;
|
15 | }
|
16 | function isAlphaNumericWord(code) {
|
17 | return isNumber$1(code) || isAlphaWord(code);
|
18 | }
|
19 | function isAlphaWord(code) {
|
20 | return code === 95 || isAlpha$1(code);
|
21 | }
|
22 |
|
23 |
|
24 |
|
25 | function isUmlaut(code) {
|
26 | return code === 196
|
27 | || code == 214
|
28 | || code === 220
|
29 | || code === 228
|
30 | || code === 246
|
31 | || code === 252;
|
32 | }
|
33 |
|
34 |
|
35 |
|
36 |
|
37 | function isWhiteSpace$3(code) {
|
38 | return code === 32
|
39 | || code === 9
|
40 | || code === 160;
|
41 | }
|
42 |
|
43 |
|
44 |
|
45 | function isSpace(code) {
|
46 | return isWhiteSpace$3(code)
|
47 | || code === 10
|
48 | || code === 13;
|
49 | }
|
50 |
|
51 |
|
52 |
|
53 | function isQuote$2(code) {
|
54 | return code === 39 || code === 34 ;
|
55 | }
|
56 |
|
57 |
|
58 |
|
59 |
|
60 | class Scanner {
|
61 | constructor(str, start, end) {
|
62 | if (end == null && typeof str === 'string') {
|
63 | end = str.length;
|
64 | }
|
65 | this.string = str;
|
66 | this.pos = this.start = start || 0;
|
67 | this.end = end || 0;
|
68 | }
|
69 | |
70 |
|
71 |
|
72 | eof() {
|
73 | return this.pos >= this.end;
|
74 | }
|
75 | |
76 |
|
77 |
|
78 |
|
79 |
|
80 | limit(start, end) {
|
81 | return new Scanner(this.string, start, end);
|
82 | }
|
83 | |
84 |
|
85 |
|
86 |
|
87 | peek() {
|
88 | return this.string.charCodeAt(this.pos);
|
89 | }
|
90 | |
91 |
|
92 |
|
93 |
|
94 | next() {
|
95 | if (this.pos < this.string.length) {
|
96 | return this.string.charCodeAt(this.pos++);
|
97 | }
|
98 | }
|
99 | |
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 | eat(match) {
|
106 | const ch = this.peek();
|
107 | const ok = typeof match === 'function' ? match(ch) : ch === match;
|
108 | if (ok) {
|
109 | this.next();
|
110 | }
|
111 | return ok;
|
112 | }
|
113 | |
114 |
|
115 |
|
116 |
|
117 | eatWhile(match) {
|
118 | const start = this.pos;
|
119 | while (!this.eof() && this.eat(match)) { }
|
120 | return this.pos !== start;
|
121 | }
|
122 | |
123 |
|
124 |
|
125 |
|
126 | backUp(n) {
|
127 | this.pos -= (n || 1);
|
128 | }
|
129 | |
130 |
|
131 |
|
132 |
|
133 | current() {
|
134 | return this.substring(this.start, this.pos);
|
135 | }
|
136 | |
137 |
|
138 |
|
139 | substring(start, end) {
|
140 | return this.string.slice(start, end);
|
141 | }
|
142 | |
143 |
|
144 |
|
145 | error(message, pos = this.pos) {
|
146 | return new ScannerError(`${message} at ${pos + 1}`, pos, this.string);
|
147 | }
|
148 | }
|
149 | class ScannerError extends Error {
|
150 | constructor(message, pos, str) {
|
151 | super(message);
|
152 | this.pos = pos;
|
153 | this.string = str;
|
154 | }
|
155 | }
|
156 |
|
157 | function tokenScanner$1(tokens) {
|
158 | return {
|
159 | tokens,
|
160 | start: 0,
|
161 | pos: 0,
|
162 | size: tokens.length
|
163 | };
|
164 | }
|
165 | function peek$3(scanner) {
|
166 | return scanner.tokens[scanner.pos];
|
167 | }
|
168 | function next(scanner) {
|
169 | return scanner.tokens[scanner.pos++];
|
170 | }
|
171 | function slice(scanner, from = scanner.start, to = scanner.pos) {
|
172 | return scanner.tokens.slice(from, to);
|
173 | }
|
174 | function readable$1(scanner) {
|
175 | return scanner.pos < scanner.size;
|
176 | }
|
177 | function consume$2(scanner, test) {
|
178 | const token = peek$3(scanner);
|
179 | if (token && test(token)) {
|
180 | scanner.pos++;
|
181 | return true;
|
182 | }
|
183 | return false;
|
184 | }
|
185 | function error$1(scanner, message, token = peek$3(scanner)) {
|
186 | if (token && token.start != null) {
|
187 | message += ` at ${token.start}`;
|
188 | }
|
189 | const err = new Error(message);
|
190 | err['pos'] = token && token.start;
|
191 | return err;
|
192 | }
|
193 |
|
194 | function abbreviation(abbr, options = {}) {
|
195 | const scanner = tokenScanner$1(abbr);
|
196 | const result = statements(scanner, options);
|
197 | if (readable$1(scanner)) {
|
198 | throw error$1(scanner, 'Unexpected character');
|
199 | }
|
200 | return result;
|
201 | }
|
202 | function statements(scanner, options) {
|
203 | const result = {
|
204 | type: 'TokenGroup',
|
205 | elements: []
|
206 | };
|
207 | let ctx = result;
|
208 | let node;
|
209 | const stack = [];
|
210 | while (readable$1(scanner)) {
|
211 | if (node = element$2(scanner, options) || group(scanner, options)) {
|
212 | ctx.elements.push(node);
|
213 | if (consume$2(scanner, isChildOperator)) {
|
214 | stack.push(ctx);
|
215 | ctx = node;
|
216 | }
|
217 | else if (consume$2(scanner, isSiblingOperator$1)) {
|
218 | continue;
|
219 | }
|
220 | else if (consume$2(scanner, isClimbOperator)) {
|
221 | do {
|
222 | if (stack.length) {
|
223 | ctx = stack.pop();
|
224 | }
|
225 | } while (consume$2(scanner, isClimbOperator));
|
226 | }
|
227 | }
|
228 | else {
|
229 | break;
|
230 | }
|
231 | }
|
232 | return result;
|
233 | }
|
234 |
|
235 |
|
236 |
|
237 | function group(scanner, options) {
|
238 | if (consume$2(scanner, isGroupStart)) {
|
239 | const result = statements(scanner, options);
|
240 | const token = next(scanner);
|
241 | if (isBracket$2(token, 'group', false)) {
|
242 | result.repeat = repeater$1(scanner);
|
243 | }
|
244 | return result;
|
245 | }
|
246 | }
|
247 |
|
248 |
|
249 |
|
250 | function element$2(scanner, options) {
|
251 | let attr;
|
252 | const elem = {
|
253 | type: 'TokenElement',
|
254 | name: void 0,
|
255 | attributes: void 0,
|
256 | value: void 0,
|
257 | repeat: void 0,
|
258 | selfClose: false,
|
259 | elements: []
|
260 | };
|
261 | if (elementName(scanner, options)) {
|
262 | elem.name = slice(scanner);
|
263 | }
|
264 | while (readable$1(scanner)) {
|
265 | scanner.start = scanner.pos;
|
266 | if (!elem.repeat && !isEmpty(elem) && consume$2(scanner, isRepeater)) {
|
267 | elem.repeat = scanner.tokens[scanner.pos - 1];
|
268 | }
|
269 | else if (!elem.value && text(scanner)) {
|
270 | elem.value = getText(scanner);
|
271 | }
|
272 | else if (attr = shortAttribute(scanner, 'id', options) || shortAttribute(scanner, 'class', options) || attributeSet(scanner)) {
|
273 | if (!elem.attributes) {
|
274 | elem.attributes = Array.isArray(attr) ? attr.slice() : [attr];
|
275 | }
|
276 | else {
|
277 | elem.attributes = elem.attributes.concat(attr);
|
278 | }
|
279 | }
|
280 | else {
|
281 | if (!isEmpty(elem) && consume$2(scanner, isCloseOperator)) {
|
282 | elem.selfClose = true;
|
283 | if (!elem.repeat && consume$2(scanner, isRepeater)) {
|
284 | elem.repeat = scanner.tokens[scanner.pos - 1];
|
285 | }
|
286 | }
|
287 | break;
|
288 | }
|
289 | }
|
290 | return !isEmpty(elem) ? elem : void 0;
|
291 | }
|
292 |
|
293 |
|
294 |
|
295 | function attributeSet(scanner) {
|
296 | if (consume$2(scanner, isAttributeSetStart)) {
|
297 | const attributes = [];
|
298 | let attr;
|
299 | while (readable$1(scanner)) {
|
300 | if (attr = attribute(scanner)) {
|
301 | attributes.push(attr);
|
302 | }
|
303 | else if (consume$2(scanner, isAttributeSetEnd)) {
|
304 | break;
|
305 | }
|
306 | else if (!consume$2(scanner, isWhiteSpace$2)) {
|
307 | throw error$1(scanner, `Unexpected "${peek$3(scanner).type}" token`);
|
308 | }
|
309 | }
|
310 | return attributes;
|
311 | }
|
312 | }
|
313 |
|
314 |
|
315 |
|
316 | function shortAttribute(scanner, type, options) {
|
317 | if (isOperator$1(peek$3(scanner), type)) {
|
318 | scanner.pos++;
|
319 |
|
320 | let count = 1;
|
321 | while (isOperator$1(peek$3(scanner), type)) {
|
322 | scanner.pos++;
|
323 | count++;
|
324 | }
|
325 | const attr = {
|
326 | name: [createLiteral$1(type)]
|
327 | };
|
328 | if (count > 1) {
|
329 | attr.multiple = true;
|
330 | }
|
331 |
|
332 | if (options.jsx && text(scanner)) {
|
333 | attr.value = getText(scanner);
|
334 | attr.expression = true;
|
335 | }
|
336 | else {
|
337 | attr.value = literal$1$1(scanner) ? slice(scanner) : void 0;
|
338 | }
|
339 | return attr;
|
340 | }
|
341 | }
|
342 |
|
343 |
|
344 |
|
345 | function attribute(scanner) {
|
346 | if (quoted(scanner)) {
|
347 |
|
348 | return {
|
349 | value: slice(scanner)
|
350 | };
|
351 | }
|
352 | if (literal$1$1(scanner, true)) {
|
353 | const name = slice(scanner);
|
354 | let value;
|
355 | if (consume$2(scanner, isEquals)) {
|
356 | if (quoted(scanner) || literal$1$1(scanner, true)) {
|
357 | value = slice(scanner);
|
358 | }
|
359 | }
|
360 | return { name, value };
|
361 | }
|
362 | }
|
363 | function repeater$1(scanner) {
|
364 | return isRepeater(peek$3(scanner))
|
365 | ? scanner.tokens[scanner.pos++]
|
366 | : void 0;
|
367 | }
|
368 |
|
369 |
|
370 |
|
371 | function quoted(scanner) {
|
372 | const start = scanner.pos;
|
373 | const quote = peek$3(scanner);
|
374 | if (isQuote$1(quote)) {
|
375 | scanner.pos++;
|
376 | while (readable$1(scanner)) {
|
377 | if (isQuote$1(next(scanner), quote.single)) {
|
378 | scanner.start = start;
|
379 | return true;
|
380 | }
|
381 | }
|
382 | throw error$1(scanner, 'Unclosed quote', quote);
|
383 | }
|
384 | return false;
|
385 | }
|
386 |
|
387 |
|
388 |
|
389 | function literal$1$1(scanner, allowBrackets) {
|
390 | const start = scanner.pos;
|
391 | const brackets = {
|
392 | attribute: 0,
|
393 | expression: 0,
|
394 | group: 0
|
395 | };
|
396 | while (readable$1(scanner)) {
|
397 | const token = peek$3(scanner);
|
398 | if (brackets.expression) {
|
399 |
|
400 | if (isBracket$2(token, 'expression')) {
|
401 | brackets[token.context] += token.open ? 1 : -1;
|
402 | }
|
403 | }
|
404 | else if (isQuote$1(token) || isOperator$1(token) || isWhiteSpace$2(token) || isRepeater(token)) {
|
405 | break;
|
406 | }
|
407 | else if (isBracket$2(token)) {
|
408 | if (!allowBrackets) {
|
409 | break;
|
410 | }
|
411 | if (token.open) {
|
412 | brackets[token.context]++;
|
413 | }
|
414 | else if (!brackets[token.context]) {
|
415 |
|
416 |
|
417 | break;
|
418 | }
|
419 | else {
|
420 | brackets[token.context]--;
|
421 | }
|
422 | }
|
423 | scanner.pos++;
|
424 | }
|
425 | if (start !== scanner.pos) {
|
426 | scanner.start = start;
|
427 | return true;
|
428 | }
|
429 | return false;
|
430 | }
|
431 |
|
432 |
|
433 |
|
434 | function elementName(scanner, options) {
|
435 | const start = scanner.pos;
|
436 | if (options.jsx && consume$2(scanner, isCapitalizedLiteral)) {
|
437 |
|
438 |
|
439 | while (readable$1(scanner)) {
|
440 | const { pos } = scanner;
|
441 | if (!consume$2(scanner, isClassNameOperator) || !consume$2(scanner, isCapitalizedLiteral)) {
|
442 | scanner.pos = pos;
|
443 | break;
|
444 | }
|
445 | }
|
446 | }
|
447 | while (readable$1(scanner) && consume$2(scanner, isElementName$1)) {
|
448 |
|
449 | }
|
450 | if (scanner.pos !== start) {
|
451 | scanner.start = start;
|
452 | return true;
|
453 | }
|
454 | return false;
|
455 | }
|
456 |
|
457 |
|
458 |
|
459 | function text(scanner) {
|
460 | const start = scanner.pos;
|
461 | if (consume$2(scanner, isTextStart)) {
|
462 | let brackets = 0;
|
463 | while (readable$1(scanner)) {
|
464 | const token = next(scanner);
|
465 | if (isBracket$2(token, 'expression')) {
|
466 | if (token.open) {
|
467 | brackets++;
|
468 | }
|
469 | else if (!brackets) {
|
470 | break;
|
471 | }
|
472 | else {
|
473 | brackets--;
|
474 | }
|
475 | }
|
476 | }
|
477 | scanner.start = start;
|
478 | return true;
|
479 | }
|
480 | return false;
|
481 | }
|
482 | function getText(scanner) {
|
483 | let from = scanner.start;
|
484 | let to = scanner.pos;
|
485 | if (isBracket$2(scanner.tokens[from], 'expression', true)) {
|
486 | from++;
|
487 | }
|
488 | if (isBracket$2(scanner.tokens[to - 1], 'expression', false)) {
|
489 | to--;
|
490 | }
|
491 | return slice(scanner, from, to);
|
492 | }
|
493 | function isBracket$2(token, context, isOpen) {
|
494 | return Boolean(token && token.type === 'Bracket'
|
495 | && (!context || token.context === context)
|
496 | && (isOpen == null || token.open === isOpen));
|
497 | }
|
498 | function isOperator$1(token, type) {
|
499 | return Boolean(token && token.type === 'Operator' && (!type || token.operator === type));
|
500 | }
|
501 | function isQuote$1(token, isSingle) {
|
502 | return Boolean(token && token.type === 'Quote' && (isSingle == null || token.single === isSingle));
|
503 | }
|
504 | function isWhiteSpace$2(token) {
|
505 | return Boolean(token && token.type === 'WhiteSpace');
|
506 | }
|
507 | function isEquals(token) {
|
508 | return isOperator$1(token, 'equal');
|
509 | }
|
510 | function isRepeater(token) {
|
511 | return Boolean(token && token.type === 'Repeater');
|
512 | }
|
513 | function isLiteral$2(token) {
|
514 | return token.type === 'Literal';
|
515 | }
|
516 | function isCapitalizedLiteral(token) {
|
517 | if (isLiteral$2(token)) {
|
518 | const ch = token.value.charCodeAt(0);
|
519 | return ch >= 65 && ch <= 90;
|
520 | }
|
521 | return false;
|
522 | }
|
523 | function isElementName$1(token) {
|
524 | return token.type === 'Literal' || token.type === 'RepeaterNumber' || token.type === 'RepeaterPlaceholder';
|
525 | }
|
526 | function isClassNameOperator(token) {
|
527 | return isOperator$1(token, 'class');
|
528 | }
|
529 | function isAttributeSetStart(token) {
|
530 | return isBracket$2(token, 'attribute', true);
|
531 | }
|
532 | function isAttributeSetEnd(token) {
|
533 | return isBracket$2(token, 'attribute', false);
|
534 | }
|
535 | function isTextStart(token) {
|
536 | return isBracket$2(token, 'expression', true);
|
537 | }
|
538 | function isGroupStart(token) {
|
539 | return isBracket$2(token, 'group', true);
|
540 | }
|
541 | function createLiteral$1(value) {
|
542 | return { type: 'Literal', value };
|
543 | }
|
544 | function isEmpty(elem) {
|
545 | return !elem.name && !elem.value && !elem.attributes;
|
546 | }
|
547 | function isChildOperator(token) {
|
548 | return isOperator$1(token, 'child');
|
549 | }
|
550 | function isSiblingOperator$1(token) {
|
551 | return isOperator$1(token, 'sibling');
|
552 | }
|
553 | function isClimbOperator(token) {
|
554 | return isOperator$1(token, 'climb');
|
555 | }
|
556 | function isCloseOperator(token) {
|
557 | return isOperator$1(token, 'close');
|
558 | }
|
559 |
|
560 | var Chars$3;
|
561 | (function (Chars) {
|
562 |
|
563 | Chars[Chars["CurlyBracketOpen"] = 123] = "CurlyBracketOpen";
|
564 |
|
565 | Chars[Chars["CurlyBracketClose"] = 125] = "CurlyBracketClose";
|
566 |
|
567 | Chars[Chars["Escape"] = 92] = "Escape";
|
568 |
|
569 | Chars[Chars["Equals"] = 61] = "Equals";
|
570 |
|
571 | Chars[Chars["SquareBracketOpen"] = 91] = "SquareBracketOpen";
|
572 |
|
573 | Chars[Chars["SquareBracketClose"] = 93] = "SquareBracketClose";
|
574 |
|
575 | Chars[Chars["Asterisk"] = 42] = "Asterisk";
|
576 |
|
577 | Chars[Chars["Hash"] = 35] = "Hash";
|
578 |
|
579 | Chars[Chars["Dollar"] = 36] = "Dollar";
|
580 |
|
581 | Chars[Chars["Dash"] = 45] = "Dash";
|
582 |
|
583 | Chars[Chars["Dot"] = 46] = "Dot";
|
584 |
|
585 | Chars[Chars["Slash"] = 47] = "Slash";
|
586 |
|
587 | Chars[Chars["Colon"] = 58] = "Colon";
|
588 |
|
589 | Chars[Chars["Excl"] = 33] = "Excl";
|
590 |
|
591 | Chars[Chars["At"] = 64] = "At";
|
592 |
|
593 | Chars[Chars["Underscore"] = 95] = "Underscore";
|
594 |
|
595 | Chars[Chars["RoundBracketOpen"] = 40] = "RoundBracketOpen";
|
596 |
|
597 | Chars[Chars["RoundBracketClose"] = 41] = "RoundBracketClose";
|
598 |
|
599 | Chars[Chars["Sibling"] = 43] = "Sibling";
|
600 |
|
601 | Chars[Chars["Child"] = 62] = "Child";
|
602 |
|
603 | Chars[Chars["Climb"] = 94] = "Climb";
|
604 |
|
605 | Chars[Chars["SingleQuote"] = 39] = "SingleQuote";
|
606 |
|
607 | Chars[Chars["DoubleQuote"] = 34] = "DoubleQuote";
|
608 | })(Chars$3 || (Chars$3 = {}));
|
609 |
|
610 |
|
611 |
|
612 | function escaped(scanner) {
|
613 | if (scanner.eat(Chars$3.Escape)) {
|
614 | scanner.start = scanner.pos;
|
615 | if (!scanner.eof()) {
|
616 | scanner.pos++;
|
617 | }
|
618 | return true;
|
619 | }
|
620 | return false;
|
621 | }
|
622 |
|
623 | function tokenize$1(source) {
|
624 | const scanner = new Scanner(source);
|
625 | const result = [];
|
626 | const ctx = {
|
627 | group: 0,
|
628 | attribute: 0,
|
629 | expression: 0,
|
630 | quote: 0
|
631 | };
|
632 | let ch = 0;
|
633 | let token;
|
634 | while (!scanner.eof()) {
|
635 | ch = scanner.peek();
|
636 | token = getToken$1(scanner, ctx);
|
637 | if (token) {
|
638 | result.push(token);
|
639 | if (token.type === 'Quote') {
|
640 | ctx.quote = ch === ctx.quote ? 0 : ch;
|
641 | }
|
642 | else if (token.type === 'Bracket') {
|
643 | ctx[token.context] += token.open ? 1 : -1;
|
644 | }
|
645 | }
|
646 | else {
|
647 | throw scanner.error('Unexpected character');
|
648 | }
|
649 | }
|
650 | return result;
|
651 | }
|
652 |
|
653 |
|
654 |
|
655 | function getToken$1(scanner, ctx) {
|
656 | return field$2(scanner, ctx)
|
657 | || repeaterPlaceholder(scanner)
|
658 | || repeaterNumber(scanner)
|
659 | || repeater(scanner)
|
660 | || whiteSpace$1(scanner)
|
661 | || literal$2(scanner, ctx)
|
662 | || operator$1(scanner)
|
663 | || quote(scanner)
|
664 | || bracket$1(scanner);
|
665 | }
|
666 |
|
667 |
|
668 |
|
669 | function literal$2(scanner, ctx) {
|
670 | const start = scanner.pos;
|
671 | const expressionStart = ctx.expression;
|
672 | let value = '';
|
673 | while (!scanner.eof()) {
|
674 |
|
675 | if (escaped(scanner)) {
|
676 | value += scanner.current();
|
677 | continue;
|
678 | }
|
679 | const ch = scanner.peek();
|
680 | if (ch === Chars$3.Slash && !ctx.quote && !ctx.expression && !ctx.attribute) {
|
681 |
|
682 | const prev = scanner.string.charCodeAt(scanner.pos - 1);
|
683 | const next = scanner.string.charCodeAt(scanner.pos + 1);
|
684 | if (isNumber$1(prev) && isNumber$1(next)) {
|
685 | value += scanner.string[scanner.pos++];
|
686 | continue;
|
687 | }
|
688 | }
|
689 | if (ch === ctx.quote || ch === Chars$3.Dollar || isAllowedOperator(ch, ctx)) {
|
690 |
|
691 |
|
692 |
|
693 | break;
|
694 | }
|
695 | if (expressionStart) {
|
696 |
|
697 | if (ch === Chars$3.CurlyBracketOpen) {
|
698 | ctx.expression++;
|
699 | }
|
700 | else if (ch === Chars$3.CurlyBracketClose) {
|
701 | if (ctx.expression > expressionStart) {
|
702 | ctx.expression--;
|
703 | }
|
704 | else {
|
705 | break;
|
706 | }
|
707 | }
|
708 | }
|
709 | else if (!ctx.quote) {
|
710 |
|
711 | if (!ctx.attribute && !isElementName(ch)) {
|
712 | break;
|
713 | }
|
714 | if (isAllowedSpace(ch, ctx) || isAllowedRepeater(ch, ctx) || isQuote$2(ch) || bracketType(ch)) {
|
715 |
|
716 | break;
|
717 | }
|
718 | }
|
719 | value += scanner.string[scanner.pos++];
|
720 | }
|
721 | if (start !== scanner.pos) {
|
722 | scanner.start = start;
|
723 | return {
|
724 | type: 'Literal',
|
725 | value,
|
726 | start,
|
727 | end: scanner.pos
|
728 | };
|
729 | }
|
730 | }
|
731 |
|
732 |
|
733 |
|
734 | function whiteSpace$1(scanner) {
|
735 | const start = scanner.pos;
|
736 | if (scanner.eatWhile(isSpace)) {
|
737 | return {
|
738 | type: 'WhiteSpace',
|
739 | start,
|
740 | end: scanner.pos,
|
741 | value: scanner.substring(start, scanner.pos)
|
742 | };
|
743 | }
|
744 | }
|
745 |
|
746 |
|
747 |
|
748 | function quote(scanner) {
|
749 | const ch = scanner.peek();
|
750 | if (isQuote$2(ch)) {
|
751 | return {
|
752 | type: 'Quote',
|
753 | single: ch === Chars$3.SingleQuote,
|
754 | start: scanner.pos++,
|
755 | end: scanner.pos
|
756 | };
|
757 | }
|
758 | }
|
759 |
|
760 |
|
761 |
|
762 | function bracket$1(scanner) {
|
763 | const ch = scanner.peek();
|
764 | const context = bracketType(ch);
|
765 | if (context) {
|
766 | return {
|
767 | type: 'Bracket',
|
768 | open: isOpenBracket$2(ch),
|
769 | context,
|
770 | start: scanner.pos++,
|
771 | end: scanner.pos
|
772 | };
|
773 | }
|
774 | }
|
775 |
|
776 |
|
777 |
|
778 | function operator$1(scanner) {
|
779 | const op = operatorType$1(scanner.peek());
|
780 | if (op) {
|
781 | return {
|
782 | type: 'Operator',
|
783 | operator: op,
|
784 | start: scanner.pos++,
|
785 | end: scanner.pos
|
786 | };
|
787 | }
|
788 | }
|
789 |
|
790 |
|
791 |
|
792 |
|
793 | function repeater(scanner) {
|
794 | const start = scanner.pos;
|
795 | if (scanner.eat(Chars$3.Asterisk)) {
|
796 | scanner.start = scanner.pos;
|
797 | let count = 1;
|
798 | let implicit = false;
|
799 | if (scanner.eatWhile(isNumber$1)) {
|
800 | count = Number(scanner.current());
|
801 | }
|
802 | else {
|
803 | implicit = true;
|
804 | }
|
805 | return {
|
806 | type: 'Repeater',
|
807 | count,
|
808 | value: 0,
|
809 | implicit,
|
810 | start,
|
811 | end: scanner.pos
|
812 | };
|
813 | }
|
814 | }
|
815 |
|
816 |
|
817 |
|
818 | function repeaterPlaceholder(scanner) {
|
819 | const start = scanner.pos;
|
820 | if (scanner.eat(Chars$3.Dollar) && scanner.eat(Chars$3.Hash)) {
|
821 | return {
|
822 | type: 'RepeaterPlaceholder',
|
823 | value: void 0,
|
824 | start,
|
825 | end: scanner.pos
|
826 | };
|
827 | }
|
828 | scanner.pos = start;
|
829 | }
|
830 |
|
831 |
|
832 |
|
833 | function repeaterNumber(scanner) {
|
834 | const start = scanner.pos;
|
835 | if (scanner.eatWhile(Chars$3.Dollar)) {
|
836 | const size = scanner.pos - start;
|
837 | let reverse = false;
|
838 | let base = 1;
|
839 | let parent = 0;
|
840 | if (scanner.eat(Chars$3.At)) {
|
841 |
|
842 | while (scanner.eat(Chars$3.Climb)) {
|
843 | parent++;
|
844 | }
|
845 | reverse = scanner.eat(Chars$3.Dash);
|
846 | scanner.start = scanner.pos;
|
847 | if (scanner.eatWhile(isNumber$1)) {
|
848 | base = Number(scanner.current());
|
849 | }
|
850 | }
|
851 | scanner.start = start;
|
852 | return {
|
853 | type: 'RepeaterNumber',
|
854 | size,
|
855 | reverse,
|
856 | base,
|
857 | parent,
|
858 | start,
|
859 | end: scanner.pos
|
860 | };
|
861 | }
|
862 | }
|
863 | function field$2(scanner, ctx) {
|
864 | const start = scanner.pos;
|
865 |
|
866 | if ((ctx.expression || ctx.attribute) && scanner.eat(Chars$3.Dollar) && scanner.eat(Chars$3.CurlyBracketOpen)) {
|
867 | scanner.start = scanner.pos;
|
868 | let index;
|
869 | let name = '';
|
870 | if (scanner.eatWhile(isNumber$1)) {
|
871 |
|
872 | index = Number(scanner.current());
|
873 | name = scanner.eat(Chars$3.Colon) ? consumePlaceholder$2(scanner) : '';
|
874 | }
|
875 | else if (isAlpha$1(scanner.peek())) {
|
876 |
|
877 | name = consumePlaceholder$2(scanner);
|
878 | }
|
879 | if (scanner.eat(Chars$3.CurlyBracketClose)) {
|
880 | return {
|
881 | type: 'Field',
|
882 | index, name,
|
883 | start,
|
884 | end: scanner.pos
|
885 | };
|
886 | }
|
887 | throw scanner.error('Expecting }');
|
888 | }
|
889 |
|
890 |
|
891 | scanner.pos = start;
|
892 | }
|
893 |
|
894 |
|
895 |
|
896 | function consumePlaceholder$2(stream) {
|
897 | const stack = [];
|
898 | stream.start = stream.pos;
|
899 | while (!stream.eof()) {
|
900 | if (stream.eat(Chars$3.CurlyBracketOpen)) {
|
901 | stack.push(stream.pos);
|
902 | }
|
903 | else if (stream.eat(Chars$3.CurlyBracketClose)) {
|
904 | if (!stack.length) {
|
905 | stream.pos--;
|
906 | break;
|
907 | }
|
908 | stack.pop();
|
909 | }
|
910 | else {
|
911 | stream.pos++;
|
912 | }
|
913 | }
|
914 | if (stack.length) {
|
915 | stream.pos = stack.pop();
|
916 | throw stream.error(`Expecting }`);
|
917 | }
|
918 | return stream.current();
|
919 | }
|
920 |
|
921 |
|
922 |
|
923 | function isAllowedOperator(ch, ctx) {
|
924 | const op = operatorType$1(ch);
|
925 | if (!op || ctx.quote || ctx.expression) {
|
926 |
|
927 | return false;
|
928 | }
|
929 |
|
930 | return !ctx.attribute || op === 'equal';
|
931 | }
|
932 |
|
933 |
|
934 |
|
935 |
|
936 | function isAllowedSpace(ch, ctx) {
|
937 | return isSpace(ch) && !ctx.expression;
|
938 | }
|
939 |
|
940 |
|
941 |
|
942 | function isAllowedRepeater(ch, ctx) {
|
943 | return ch === Chars$3.Asterisk && !ctx.attribute && !ctx.expression;
|
944 | }
|
945 |
|
946 |
|
947 |
|
948 | function bracketType(ch) {
|
949 | if (ch === Chars$3.RoundBracketOpen || ch === Chars$3.RoundBracketClose) {
|
950 | return 'group';
|
951 | }
|
952 | if (ch === Chars$3.SquareBracketOpen || ch === Chars$3.SquareBracketClose) {
|
953 | return 'attribute';
|
954 | }
|
955 | if (ch === Chars$3.CurlyBracketOpen || ch === Chars$3.CurlyBracketClose) {
|
956 | return 'expression';
|
957 | }
|
958 | }
|
959 |
|
960 |
|
961 |
|
962 | function operatorType$1(ch) {
|
963 | return (ch === Chars$3.Child && 'child')
|
964 | || (ch === Chars$3.Sibling && 'sibling')
|
965 | || (ch === Chars$3.Climb && 'climb')
|
966 | || (ch === Chars$3.Dot && 'class')
|
967 | || (ch === Chars$3.Hash && 'id')
|
968 | || (ch === Chars$3.Slash && 'close')
|
969 | || (ch === Chars$3.Equals && 'equal')
|
970 | || void 0;
|
971 | }
|
972 |
|
973 |
|
974 |
|
975 | function isOpenBracket$2(ch) {
|
976 | return ch === Chars$3.CurlyBracketOpen
|
977 | || ch === Chars$3.SquareBracketOpen
|
978 | || ch === Chars$3.RoundBracketOpen;
|
979 | }
|
980 |
|
981 |
|
982 |
|
983 | function isElementName(ch) {
|
984 | return isAlphaNumericWord(ch)
|
985 | || isUmlaut(ch)
|
986 | || ch === Chars$3.Dash
|
987 | || ch === Chars$3.Colon
|
988 | || ch === Chars$3.Excl;
|
989 | }
|
990 |
|
991 | const operators = {
|
992 | child: '>',
|
993 | class: '.',
|
994 | climb: '^',
|
995 | id: '#',
|
996 | equal: '=',
|
997 | close: '/',
|
998 | sibling: '+'
|
999 | };
|
1000 | const tokenVisitor = {
|
1001 | Literal(token) {
|
1002 | return token.value;
|
1003 | },
|
1004 | Quote(token) {
|
1005 | return token.single ? '\'' : '"';
|
1006 | },
|
1007 | Bracket(token) {
|
1008 | if (token.context === 'attribute') {
|
1009 | return token.open ? '[' : ']';
|
1010 | }
|
1011 | else if (token.context === 'expression') {
|
1012 | return token.open ? '{' : '}';
|
1013 | }
|
1014 | else {
|
1015 | return token.open ? '(' : '}';
|
1016 | }
|
1017 | },
|
1018 | Operator(token) {
|
1019 | return operators[token.operator];
|
1020 | },
|
1021 | Field(token, state) {
|
1022 | if (token.index != null) {
|
1023 |
|
1024 | return token.name
|
1025 | ? `\${${token.index}:${token.name}}`
|
1026 | : `\${${token.index}`;
|
1027 | }
|
1028 | else if (token.name) {
|
1029 |
|
1030 | return state.getVariable(token.name);
|
1031 | }
|
1032 | return '';
|
1033 | },
|
1034 | RepeaterPlaceholder(token, state) {
|
1035 |
|
1036 | let repeater;
|
1037 | for (let i = state.repeaters.length - 1; i >= 0; i--) {
|
1038 | if (state.repeaters[i].implicit) {
|
1039 | repeater = state.repeaters[i];
|
1040 | break;
|
1041 | }
|
1042 | }
|
1043 | state.inserted = true;
|
1044 | return state.getText(repeater && repeater.value);
|
1045 | },
|
1046 | RepeaterNumber(token, state) {
|
1047 | let value = 1;
|
1048 | const lastIx = state.repeaters.length - 1;
|
1049 |
|
1050 | const repeater = state.repeaters[lastIx];
|
1051 | if (repeater) {
|
1052 | value = token.reverse
|
1053 | ? token.base + repeater.count - repeater.value - 1
|
1054 | : token.base + repeater.value;
|
1055 | if (token.parent) {
|
1056 | const parentIx = Math.max(0, lastIx - token.parent);
|
1057 | if (parentIx !== lastIx) {
|
1058 | const parentRepeater = state.repeaters[parentIx];
|
1059 | value += repeater.count * parentRepeater.value;
|
1060 | }
|
1061 | }
|
1062 | }
|
1063 | let result = String(value);
|
1064 | while (result.length < token.size) {
|
1065 | result = '0' + result;
|
1066 | }
|
1067 | return result;
|
1068 | },
|
1069 | WhiteSpace(token) {
|
1070 | return token.value;
|
1071 | }
|
1072 | };
|
1073 |
|
1074 |
|
1075 |
|
1076 | function stringify$1(token, state) {
|
1077 | if (!tokenVisitor[token.type]) {
|
1078 | throw new Error(`Unknown token ${token.type}`);
|
1079 | }
|
1080 | return tokenVisitor[token.type](token, state);
|
1081 | }
|
1082 |
|
1083 | const urlRegex = /^((https?:|ftp:|file:)?\/\/|(www|ftp)\.)[^ ]*$/;
|
1084 | const emailRegex = /^[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,5}$/;
|
1085 |
|
1086 |
|
1087 |
|
1088 |
|
1089 | function convert(abbr, options = {}) {
|
1090 | let textInserted = false;
|
1091 | let cleanText;
|
1092 | if (options.text) {
|
1093 | if (Array.isArray(options.text)) {
|
1094 | cleanText = options.text.filter(s => s.trim());
|
1095 | }
|
1096 | else {
|
1097 | cleanText = options.text;
|
1098 | }
|
1099 | }
|
1100 | const result = {
|
1101 | type: 'Abbreviation',
|
1102 | children: convertGroup(abbr, {
|
1103 | inserted: false,
|
1104 | repeaters: [],
|
1105 | text: options.text,
|
1106 | cleanText,
|
1107 | repeatGuard: options.maxRepeat || Number.POSITIVE_INFINITY,
|
1108 | getText(pos) {
|
1109 | var _a;
|
1110 | textInserted = true;
|
1111 | let value;
|
1112 | if (Array.isArray(options.text)) {
|
1113 | if (pos !== undefined && pos >= 0 && pos < cleanText.length) {
|
1114 | return cleanText[pos];
|
1115 | }
|
1116 | value = pos !== undefined ? options.text[pos] : options.text.join('\n');
|
1117 | }
|
1118 | else {
|
1119 | value = (_a = options.text) !== null && _a !== void 0 ? _a : '';
|
1120 | }
|
1121 | return value;
|
1122 | },
|
1123 | getVariable(name) {
|
1124 | const varValue = options.variables && options.variables[name];
|
1125 | return varValue != null ? varValue : name;
|
1126 | }
|
1127 | })
|
1128 | };
|
1129 | if (options.text != null && !textInserted) {
|
1130 |
|
1131 |
|
1132 | const deepest = deepestNode(last$1(result.children));
|
1133 | if (deepest) {
|
1134 | const text = Array.isArray(options.text) ? options.text.join('\n') : options.text;
|
1135 | insertText(deepest, text);
|
1136 | if (deepest.name === 'a' && options.href) {
|
1137 |
|
1138 | insertHref(deepest, text);
|
1139 | }
|
1140 | }
|
1141 | }
|
1142 | return result;
|
1143 | }
|
1144 |
|
1145 |
|
1146 |
|
1147 | function convertStatement(node, state) {
|
1148 | let result = [];
|
1149 | if (node.repeat) {
|
1150 |
|
1151 |
|
1152 | const original = node.repeat;
|
1153 | const repeat = Object.assign({}, original);
|
1154 | repeat.count = repeat.implicit && Array.isArray(state.text)
|
1155 | ? state.cleanText.length
|
1156 | : (repeat.count || 1);
|
1157 | let items;
|
1158 | state.repeaters.push(repeat);
|
1159 | for (let i = 0; i < repeat.count; i++) {
|
1160 | repeat.value = i;
|
1161 | node.repeat = repeat;
|
1162 | items = isGroup(node)
|
1163 | ? convertGroup(node, state)
|
1164 | : convertElement(node, state);
|
1165 | if (repeat.implicit && !state.inserted) {
|
1166 |
|
1167 |
|
1168 | const target = last$1(items);
|
1169 | const deepest = target && deepestNode(target);
|
1170 | if (deepest) {
|
1171 | insertText(deepest, state.getText(repeat.value));
|
1172 | }
|
1173 | }
|
1174 | result = result.concat(items);
|
1175 |
|
1176 |
|
1177 | if (--state.repeatGuard <= 0) {
|
1178 | break;
|
1179 | }
|
1180 | }
|
1181 | state.repeaters.pop();
|
1182 | node.repeat = original;
|
1183 | if (repeat.implicit) {
|
1184 | state.inserted = true;
|
1185 | }
|
1186 | }
|
1187 | else {
|
1188 | result = result.concat(isGroup(node) ? convertGroup(node, state) : convertElement(node, state));
|
1189 | }
|
1190 | return result;
|
1191 | }
|
1192 | function convertElement(node, state) {
|
1193 | let children = [];
|
1194 | const elem = {
|
1195 | type: 'AbbreviationNode',
|
1196 | name: node.name && stringifyName(node.name, state),
|
1197 | value: node.value && stringifyValue$1(node.value, state),
|
1198 | attributes: void 0,
|
1199 | children,
|
1200 | repeat: node.repeat && Object.assign({}, node.repeat),
|
1201 | selfClosing: node.selfClose,
|
1202 | };
|
1203 | let result = [elem];
|
1204 | for (const child of node.elements) {
|
1205 | children = children.concat(convertStatement(child, state));
|
1206 | }
|
1207 | if (node.attributes) {
|
1208 | elem.attributes = [];
|
1209 | for (const attr of node.attributes) {
|
1210 | elem.attributes.push(convertAttribute(attr, state));
|
1211 | }
|
1212 | }
|
1213 |
|
1214 |
|
1215 | if (!elem.name && !elem.attributes && elem.value && !elem.value.some(isField$1)) {
|
1216 |
|
1217 |
|
1218 | result = result.concat(children);
|
1219 | }
|
1220 | else {
|
1221 | elem.children = children;
|
1222 | }
|
1223 | return result;
|
1224 | }
|
1225 | function convertGroup(node, state) {
|
1226 | let result = [];
|
1227 | for (const child of node.elements) {
|
1228 | result = result.concat(convertStatement(child, state));
|
1229 | }
|
1230 | if (node.repeat) {
|
1231 | result = attachRepeater(result, node.repeat);
|
1232 | }
|
1233 | return result;
|
1234 | }
|
1235 | function convertAttribute(node, state) {
|
1236 | let implied = false;
|
1237 | let isBoolean = false;
|
1238 | let valueType = node.expression ? 'expression' : 'raw';
|
1239 | let value;
|
1240 | const name = node.name && stringifyName(node.name, state);
|
1241 | if (name && name[0] === '!') {
|
1242 | implied = true;
|
1243 | }
|
1244 | if (name && name[name.length - 1] === '.') {
|
1245 | isBoolean = true;
|
1246 | }
|
1247 | if (node.value) {
|
1248 | const tokens = node.value.slice();
|
1249 | if (isQuote$1(tokens[0])) {
|
1250 |
|
1251 |
|
1252 | const quote = tokens.shift();
|
1253 | if (tokens.length && last$1(tokens).type === quote.type) {
|
1254 | tokens.pop();
|
1255 | }
|
1256 | valueType = quote.single ? 'singleQuote' : 'doubleQuote';
|
1257 | }
|
1258 | else if (isBracket$2(tokens[0], 'expression', true)) {
|
1259 |
|
1260 | valueType = 'expression';
|
1261 | tokens.shift();
|
1262 | if (isBracket$2(last$1(tokens), 'expression', false)) {
|
1263 | tokens.pop();
|
1264 | }
|
1265 | }
|
1266 | value = stringifyValue$1(tokens, state);
|
1267 | }
|
1268 | return {
|
1269 | name: isBoolean || implied
|
1270 | ? name.slice(implied ? 1 : 0, isBoolean ? -1 : void 0)
|
1271 | : name,
|
1272 | value,
|
1273 | boolean: isBoolean,
|
1274 | implied,
|
1275 | valueType,
|
1276 | multiple: node.multiple
|
1277 | };
|
1278 | }
|
1279 |
|
1280 |
|
1281 |
|
1282 | function stringifyName(tokens, state) {
|
1283 | let str = '';
|
1284 | for (let i = 0; i < tokens.length; i++) {
|
1285 | str += stringify$1(tokens[i], state);
|
1286 | }
|
1287 | return str;
|
1288 | }
|
1289 |
|
1290 |
|
1291 |
|
1292 | function stringifyValue$1(tokens, state) {
|
1293 | const result = [];
|
1294 | let str = '';
|
1295 | for (let i = 0, token; i < tokens.length; i++) {
|
1296 | token = tokens[i];
|
1297 | if (isField$1(token)) {
|
1298 |
|
1299 |
|
1300 |
|
1301 | if (str) {
|
1302 | result.push(str);
|
1303 | str = '';
|
1304 | }
|
1305 | result.push(token);
|
1306 | }
|
1307 | else {
|
1308 | str += stringify$1(token, state);
|
1309 | }
|
1310 | }
|
1311 | if (str) {
|
1312 | result.push(str);
|
1313 | }
|
1314 | return result;
|
1315 | }
|
1316 | function isGroup(node) {
|
1317 | return node.type === 'TokenGroup';
|
1318 | }
|
1319 | function isField$1(token) {
|
1320 | return typeof token === 'object' && token.type === 'Field' && token.index != null;
|
1321 | }
|
1322 | function last$1(arr) {
|
1323 | return arr[arr.length - 1];
|
1324 | }
|
1325 | function deepestNode(node) {
|
1326 | return node.children.length ? deepestNode(last$1(node.children)) : node;
|
1327 | }
|
1328 | function insertText(node, text) {
|
1329 | if (node.value) {
|
1330 | const lastToken = last$1(node.value);
|
1331 | if (typeof lastToken === 'string') {
|
1332 | node.value[node.value.length - 1] += text;
|
1333 | }
|
1334 | else {
|
1335 | node.value.push(text);
|
1336 | }
|
1337 | }
|
1338 | else {
|
1339 | node.value = [text];
|
1340 | }
|
1341 | }
|
1342 | function insertHref(node, text) {
|
1343 | var _a;
|
1344 | let href = '';
|
1345 | if (urlRegex.test(text)) {
|
1346 | href = text;
|
1347 | if (!/\w+:/.test(href) && !href.startsWith('//')) {
|
1348 | href = `http://${href}`;
|
1349 | }
|
1350 | }
|
1351 | else if (emailRegex.test(text)) {
|
1352 | href = `mailto:${text}`;
|
1353 | }
|
1354 | const hrefAttribute = (_a = node.attributes) === null || _a === void 0 ? void 0 : _a.find(attr => attr.name === 'href');
|
1355 | if (!hrefAttribute) {
|
1356 | if (!node.attributes) {
|
1357 | node.attributes = [];
|
1358 | }
|
1359 | node.attributes.push({ name: 'href', value: [href], valueType: 'doubleQuote' });
|
1360 | }
|
1361 | else if (!hrefAttribute.value) {
|
1362 | hrefAttribute.value = [href];
|
1363 | }
|
1364 | }
|
1365 | function attachRepeater(items, repeater) {
|
1366 | for (const item of items) {
|
1367 | if (!item.repeat) {
|
1368 | item.repeat = Object.assign({}, repeater);
|
1369 | }
|
1370 | }
|
1371 | return items;
|
1372 | }
|
1373 |
|
1374 |
|
1375 |
|
1376 |
|
1377 | function parseAbbreviation(abbr, options) {
|
1378 | try {
|
1379 | const tokens = typeof abbr === 'string' ? tokenize$1(abbr) : abbr;
|
1380 | return convert(abbreviation(tokens, options), options);
|
1381 | }
|
1382 | catch (err) {
|
1383 | if (err instanceof ScannerError && typeof abbr === 'string') {
|
1384 | err.message += `\n${abbr}\n${'-'.repeat(err.pos)}^`;
|
1385 | }
|
1386 | throw err;
|
1387 | }
|
1388 | }
|
1389 |
|
1390 | var OperatorType;
|
1391 | (function (OperatorType) {
|
1392 | OperatorType["Sibling"] = "+";
|
1393 | OperatorType["Important"] = "!";
|
1394 | OperatorType["ArgumentDelimiter"] = ",";
|
1395 | OperatorType["ValueDelimiter"] = "-";
|
1396 | OperatorType["PropertyDelimiter"] = ":";
|
1397 | })(OperatorType || (OperatorType = {}));
|
1398 |
|
1399 | var Chars$2;
|
1400 | (function (Chars) {
|
1401 |
|
1402 | Chars[Chars["Hash"] = 35] = "Hash";
|
1403 |
|
1404 | Chars[Chars["Dollar"] = 36] = "Dollar";
|
1405 |
|
1406 | Chars[Chars["Dash"] = 45] = "Dash";
|
1407 |
|
1408 | Chars[Chars["Dot"] = 46] = "Dot";
|
1409 |
|
1410 | Chars[Chars["Colon"] = 58] = "Colon";
|
1411 |
|
1412 | Chars[Chars["Comma"] = 44] = "Comma";
|
1413 |
|
1414 | Chars[Chars["Excl"] = 33] = "Excl";
|
1415 |
|
1416 | Chars[Chars["At"] = 64] = "At";
|
1417 |
|
1418 | Chars[Chars["Percent"] = 37] = "Percent";
|
1419 |
|
1420 | Chars[Chars["Underscore"] = 95] = "Underscore";
|
1421 |
|
1422 | Chars[Chars["RoundBracketOpen"] = 40] = "RoundBracketOpen";
|
1423 |
|
1424 | Chars[Chars["RoundBracketClose"] = 41] = "RoundBracketClose";
|
1425 |
|
1426 | Chars[Chars["CurlyBracketOpen"] = 123] = "CurlyBracketOpen";
|
1427 |
|
1428 | Chars[Chars["CurlyBracketClose"] = 125] = "CurlyBracketClose";
|
1429 |
|
1430 | Chars[Chars["Sibling"] = 43] = "Sibling";
|
1431 |
|
1432 | Chars[Chars["SingleQuote"] = 39] = "SingleQuote";
|
1433 |
|
1434 | Chars[Chars["DoubleQuote"] = 34] = "DoubleQuote";
|
1435 |
|
1436 | Chars[Chars["Transparent"] = 116] = "Transparent";
|
1437 |
|
1438 | Chars[Chars["Slash"] = 47] = "Slash";
|
1439 | })(Chars$2 || (Chars$2 = {}));
|
1440 |
|
1441 | function tokenize(abbr, isValue) {
|
1442 | let brackets = 0;
|
1443 | let token;
|
1444 | const scanner = new Scanner(abbr);
|
1445 | const tokens = [];
|
1446 | while (!scanner.eof()) {
|
1447 | token = getToken(scanner, brackets === 0 && !isValue);
|
1448 | if (!token) {
|
1449 | throw scanner.error('Unexpected character');
|
1450 | }
|
1451 | if (token.type === 'Bracket') {
|
1452 | if (!brackets && token.open) {
|
1453 | mergeTokens(scanner, tokens);
|
1454 | }
|
1455 | brackets += token.open ? 1 : -1;
|
1456 | if (brackets < 0) {
|
1457 | throw scanner.error('Unexpected bracket', token.start);
|
1458 | }
|
1459 | }
|
1460 | tokens.push(token);
|
1461 |
|
1462 |
|
1463 | if (shouldConsumeDashAfter(token) && (token = operator(scanner))) {
|
1464 | tokens.push(token);
|
1465 | }
|
1466 | }
|
1467 | return tokens;
|
1468 | }
|
1469 |
|
1470 |
|
1471 |
|
1472 | function getToken(scanner, short) {
|
1473 | return field$1(scanner)
|
1474 | || customProperty(scanner)
|
1475 | || numberValue(scanner)
|
1476 | || colorValue(scanner)
|
1477 | || stringValue(scanner)
|
1478 | || bracket(scanner)
|
1479 | || operator(scanner)
|
1480 | || whiteSpace(scanner)
|
1481 | || literal$1(scanner, short);
|
1482 | }
|
1483 | function field$1(scanner) {
|
1484 | const start = scanner.pos;
|
1485 | if (scanner.eat(Chars$2.Dollar) && scanner.eat(Chars$2.CurlyBracketOpen)) {
|
1486 | scanner.start = scanner.pos;
|
1487 | let index;
|
1488 | let name = '';
|
1489 | if (scanner.eatWhile(isNumber$1)) {
|
1490 |
|
1491 | index = Number(scanner.current());
|
1492 | name = scanner.eat(Chars$2.Colon) ? consumePlaceholder$1(scanner) : '';
|
1493 | }
|
1494 | else if (isAlpha$1(scanner.peek())) {
|
1495 |
|
1496 | name = consumePlaceholder$1(scanner);
|
1497 | }
|
1498 | if (scanner.eat(Chars$2.CurlyBracketClose)) {
|
1499 | return {
|
1500 | type: 'Field',
|
1501 | index, name,
|
1502 | start,
|
1503 | end: scanner.pos
|
1504 | };
|
1505 | }
|
1506 | throw scanner.error('Expecting }');
|
1507 | }
|
1508 |
|
1509 |
|
1510 | scanner.pos = start;
|
1511 | }
|
1512 |
|
1513 |
|
1514 |
|
1515 | function consumePlaceholder$1(stream) {
|
1516 | const stack = [];
|
1517 | stream.start = stream.pos;
|
1518 | while (!stream.eof()) {
|
1519 | if (stream.eat(Chars$2.CurlyBracketOpen)) {
|
1520 | stack.push(stream.pos);
|
1521 | }
|
1522 | else if (stream.eat(Chars$2.CurlyBracketClose)) {
|
1523 | if (!stack.length) {
|
1524 | stream.pos--;
|
1525 | break;
|
1526 | }
|
1527 | stack.pop();
|
1528 | }
|
1529 | else {
|
1530 | stream.pos++;
|
1531 | }
|
1532 | }
|
1533 | if (stack.length) {
|
1534 | stream.pos = stack.pop();
|
1535 | throw stream.error(`Expecting }`);
|
1536 | }
|
1537 | return stream.current();
|
1538 | }
|
1539 |
|
1540 |
|
1541 |
|
1542 |
|
1543 |
|
1544 |
|
1545 |
|
1546 | function literal$1(scanner, short) {
|
1547 | const start = scanner.pos;
|
1548 | if (scanner.eat(isIdentPrefix)) {
|
1549 |
|
1550 |
|
1551 |
|
1552 | scanner.eatWhile(start ? isKeyword : isLiteral$1);
|
1553 | }
|
1554 | else if (scanner.eat(isAlphaWord)) {
|
1555 | scanner.eatWhile(short ? isLiteral$1 : isKeyword);
|
1556 | }
|
1557 | else {
|
1558 |
|
1559 | scanner.eat(Chars$2.Dot);
|
1560 | scanner.eatWhile(isLiteral$1);
|
1561 | }
|
1562 | if (start !== scanner.pos) {
|
1563 | scanner.start = start;
|
1564 | return createLiteral(scanner, scanner.start = start);
|
1565 | }
|
1566 | }
|
1567 | function createLiteral(scanner, start = scanner.start, end = scanner.pos) {
|
1568 | return {
|
1569 | type: 'Literal',
|
1570 | value: scanner.substring(start, end),
|
1571 | start,
|
1572 | end
|
1573 | };
|
1574 | }
|
1575 |
|
1576 |
|
1577 |
|
1578 |
|
1579 | function numberValue(scanner) {
|
1580 | const start = scanner.pos;
|
1581 | if (consumeNumber(scanner)) {
|
1582 | scanner.start = start;
|
1583 | const rawValue = scanner.current();
|
1584 |
|
1585 | scanner.start = scanner.pos;
|
1586 | scanner.eat(Chars$2.Percent) || scanner.eatWhile(isAlphaWord);
|
1587 | return {
|
1588 | type: 'NumberValue',
|
1589 | value: Number(rawValue),
|
1590 | rawValue,
|
1591 | unit: scanner.current(),
|
1592 | start,
|
1593 | end: scanner.pos
|
1594 | };
|
1595 | }
|
1596 | }
|
1597 |
|
1598 |
|
1599 |
|
1600 | function stringValue(scanner) {
|
1601 | const ch = scanner.peek();
|
1602 | const start = scanner.pos;
|
1603 | let finished = false;
|
1604 | if (isQuote$2(ch)) {
|
1605 | scanner.pos++;
|
1606 | while (!scanner.eof()) {
|
1607 |
|
1608 | if (scanner.eat(ch)) {
|
1609 | finished = true;
|
1610 | break;
|
1611 | }
|
1612 | else {
|
1613 | scanner.pos++;
|
1614 | }
|
1615 | }
|
1616 | scanner.start = start;
|
1617 | return {
|
1618 | type: 'StringValue',
|
1619 | value: scanner.substring(start + 1, scanner.pos - (finished ? 1 : 0)),
|
1620 | quote: ch === Chars$2.SingleQuote ? 'single' : 'double',
|
1621 | start,
|
1622 | end: scanner.pos
|
1623 | };
|
1624 | }
|
1625 | }
|
1626 |
|
1627 |
|
1628 |
|
1629 | function colorValue(scanner) {
|
1630 |
|
1631 |
|
1632 |
|
1633 |
|
1634 |
|
1635 | const start = scanner.pos;
|
1636 | if (scanner.eat(Chars$2.Hash)) {
|
1637 | const valueStart = scanner.pos;
|
1638 | let color = '';
|
1639 | let alpha = '';
|
1640 | if (scanner.eatWhile(isHex)) {
|
1641 | color = scanner.substring(valueStart, scanner.pos);
|
1642 | alpha = colorAlpha(scanner);
|
1643 | }
|
1644 | else if (scanner.eat(Chars$2.Transparent)) {
|
1645 | color = '0';
|
1646 | alpha = colorAlpha(scanner) || '0';
|
1647 | }
|
1648 | else {
|
1649 | alpha = colorAlpha(scanner);
|
1650 | }
|
1651 | if (color || alpha || scanner.eof()) {
|
1652 | const { r, g, b, a } = parseColor(color, alpha);
|
1653 | return {
|
1654 | type: 'ColorValue',
|
1655 | r, g, b, a,
|
1656 | raw: scanner.substring(start + 1, scanner.pos),
|
1657 | start,
|
1658 | end: scanner.pos
|
1659 | };
|
1660 | }
|
1661 | else {
|
1662 |
|
1663 | return createLiteral(scanner, start);
|
1664 | }
|
1665 | }
|
1666 | scanner.pos = start;
|
1667 | }
|
1668 |
|
1669 |
|
1670 |
|
1671 | function colorAlpha(scanner) {
|
1672 | const start = scanner.pos;
|
1673 | if (scanner.eat(Chars$2.Dot)) {
|
1674 | scanner.start = start;
|
1675 | if (scanner.eatWhile(isNumber$1)) {
|
1676 | return scanner.current();
|
1677 | }
|
1678 | return '1';
|
1679 | }
|
1680 | return '';
|
1681 | }
|
1682 |
|
1683 |
|
1684 |
|
1685 | function whiteSpace(scanner) {
|
1686 | const start = scanner.pos;
|
1687 | if (scanner.eatWhile(isSpace)) {
|
1688 | return {
|
1689 | type: 'WhiteSpace',
|
1690 | start,
|
1691 | end: scanner.pos
|
1692 | };
|
1693 | }
|
1694 | }
|
1695 |
|
1696 |
|
1697 |
|
1698 | function customProperty(scanner) {
|
1699 | const start = scanner.pos;
|
1700 | if (scanner.eat(Chars$2.Dash) && scanner.eat(Chars$2.Dash)) {
|
1701 | scanner.start = start;
|
1702 | scanner.eatWhile(isKeyword);
|
1703 | return {
|
1704 | type: 'CustomProperty',
|
1705 | value: scanner.current(),
|
1706 | start,
|
1707 | end: scanner.pos
|
1708 | };
|
1709 | }
|
1710 | scanner.pos = start;
|
1711 | }
|
1712 |
|
1713 |
|
1714 |
|
1715 | function bracket(scanner) {
|
1716 | const ch = scanner.peek();
|
1717 | if (isBracket$1(ch)) {
|
1718 | return {
|
1719 | type: 'Bracket',
|
1720 | open: ch === Chars$2.RoundBracketOpen,
|
1721 | start: scanner.pos++,
|
1722 | end: scanner.pos
|
1723 | };
|
1724 | }
|
1725 | }
|
1726 |
|
1727 |
|
1728 |
|
1729 | function operator(scanner) {
|
1730 | const op = operatorType(scanner.peek());
|
1731 | if (op) {
|
1732 | return {
|
1733 | type: 'Operator',
|
1734 | operator: op,
|
1735 | start: scanner.pos++,
|
1736 | end: scanner.pos
|
1737 | };
|
1738 | }
|
1739 | }
|
1740 |
|
1741 |
|
1742 |
|
1743 |
|
1744 | function consumeNumber(stream) {
|
1745 | const start = stream.pos;
|
1746 | stream.eat(Chars$2.Dash);
|
1747 | const afterNegative = stream.pos;
|
1748 | const hasDecimal = stream.eatWhile(isNumber$1);
|
1749 | const prevPos = stream.pos;
|
1750 | if (stream.eat(Chars$2.Dot)) {
|
1751 |
|
1752 |
|
1753 | const hasFloat = stream.eatWhile(isNumber$1);
|
1754 | if (!hasDecimal && !hasFloat) {
|
1755 |
|
1756 | stream.pos = prevPos;
|
1757 | }
|
1758 | }
|
1759 |
|
1760 | if (stream.pos === afterNegative) {
|
1761 | stream.pos = start;
|
1762 | }
|
1763 | return stream.pos !== start;
|
1764 | }
|
1765 | function isIdentPrefix(code) {
|
1766 | return code === Chars$2.At || code === Chars$2.Dollar;
|
1767 | }
|
1768 |
|
1769 |
|
1770 |
|
1771 | function operatorType(ch) {
|
1772 | return (ch === Chars$2.Sibling && OperatorType.Sibling)
|
1773 | || (ch === Chars$2.Excl && OperatorType.Important)
|
1774 | || (ch === Chars$2.Comma && OperatorType.ArgumentDelimiter)
|
1775 | || (ch === Chars$2.Colon && OperatorType.PropertyDelimiter)
|
1776 | || (ch === Chars$2.Dash && OperatorType.ValueDelimiter)
|
1777 | || void 0;
|
1778 | }
|
1779 |
|
1780 |
|
1781 |
|
1782 | function isHex(code) {
|
1783 | return isNumber$1(code) || isAlpha$1(code, 65, 70);
|
1784 | }
|
1785 | function isKeyword(code) {
|
1786 | return isAlphaNumericWord(code) || code === Chars$2.Dash;
|
1787 | }
|
1788 | function isBracket$1(code) {
|
1789 | return code === Chars$2.RoundBracketOpen || code === Chars$2.RoundBracketClose;
|
1790 | }
|
1791 | function isLiteral$1(code) {
|
1792 | return isAlphaWord(code) || code === Chars$2.Percent || code === Chars$2.Slash;
|
1793 | }
|
1794 |
|
1795 |
|
1796 |
|
1797 | function parseColor(value, alpha) {
|
1798 | let r = '0';
|
1799 | let g = '0';
|
1800 | let b = '0';
|
1801 | let a = Number(alpha != null && alpha !== '' ? alpha : 1);
|
1802 | if (value === 't') {
|
1803 | a = 0;
|
1804 | }
|
1805 | else {
|
1806 | switch (value.length) {
|
1807 | case 0:
|
1808 | break;
|
1809 | case 1:
|
1810 | r = g = b = value + value;
|
1811 | break;
|
1812 | case 2:
|
1813 | r = g = b = value;
|
1814 | break;
|
1815 | case 3:
|
1816 | r = value[0] + value[0];
|
1817 | g = value[1] + value[1];
|
1818 | b = value[2] + value[2];
|
1819 | break;
|
1820 | default:
|
1821 | value += value;
|
1822 | r = value.slice(0, 2);
|
1823 | g = value.slice(2, 4);
|
1824 | b = value.slice(4, 6);
|
1825 | }
|
1826 | }
|
1827 | return {
|
1828 | r: parseInt(r, 16),
|
1829 | g: parseInt(g, 16),
|
1830 | b: parseInt(b, 16),
|
1831 | a
|
1832 | };
|
1833 | }
|
1834 |
|
1835 |
|
1836 |
|
1837 |
|
1838 | function shouldConsumeDashAfter(token) {
|
1839 | return token.type === 'ColorValue' || (token.type === 'NumberValue' && !token.unit);
|
1840 | }
|
1841 |
|
1842 |
|
1843 |
|
1844 |
|
1845 |
|
1846 |
|
1847 |
|
1848 |
|
1849 | function mergeTokens(scanner, tokens) {
|
1850 | let start = 0;
|
1851 | let end = 0;
|
1852 | while (tokens.length) {
|
1853 | const token = last(tokens);
|
1854 | if (token.type === 'Literal' || token.type === 'NumberValue') {
|
1855 | start = token.start;
|
1856 | if (!end) {
|
1857 | end = token.end;
|
1858 | }
|
1859 | tokens.pop();
|
1860 | }
|
1861 | else {
|
1862 | break;
|
1863 | }
|
1864 | }
|
1865 | if (start !== end) {
|
1866 | tokens.push(createLiteral(scanner, start, end));
|
1867 | }
|
1868 | }
|
1869 | function last(arr) {
|
1870 | return arr[arr.length - 1];
|
1871 | }
|
1872 |
|
1873 | function tokenScanner(tokens) {
|
1874 | return {
|
1875 | tokens,
|
1876 | start: 0,
|
1877 | pos: 0,
|
1878 | size: tokens.length
|
1879 | };
|
1880 | }
|
1881 | function peek$2(scanner) {
|
1882 | return scanner.tokens[scanner.pos];
|
1883 | }
|
1884 | function readable(scanner) {
|
1885 | return scanner.pos < scanner.size;
|
1886 | }
|
1887 | function consume$1(scanner, test) {
|
1888 | if (test(peek$2(scanner))) {
|
1889 | scanner.pos++;
|
1890 | return true;
|
1891 | }
|
1892 | return false;
|
1893 | }
|
1894 | function error(scanner, message, token = peek$2(scanner)) {
|
1895 | if (token && token.start != null) {
|
1896 | message += ` at ${token.start}`;
|
1897 | }
|
1898 | const err = new Error(message);
|
1899 | err['pos'] = token && token.start;
|
1900 | return err;
|
1901 | }
|
1902 |
|
1903 | function parser(tokens, options = {}) {
|
1904 | const scanner = tokenScanner(tokens);
|
1905 | const result = [];
|
1906 | let property;
|
1907 | while (readable(scanner)) {
|
1908 | if (property = consumeProperty(scanner, options)) {
|
1909 | result.push(property);
|
1910 | }
|
1911 | else if (!consume$1(scanner, isSiblingOperator)) {
|
1912 | throw error(scanner, 'Unexpected token');
|
1913 | }
|
1914 | }
|
1915 | return result;
|
1916 | }
|
1917 |
|
1918 |
|
1919 |
|
1920 | function consumeProperty(scanner, options) {
|
1921 | let name;
|
1922 | let important = false;
|
1923 | let valueFragment;
|
1924 | const value = [];
|
1925 | const token = peek$2(scanner);
|
1926 | const valueMode = !!options.value;
|
1927 | if (!valueMode && isLiteral(token) && !isFunctionStart(scanner)) {
|
1928 | scanner.pos++;
|
1929 | name = token.value;
|
1930 |
|
1931 | consume$1(scanner, isValueDelimiter);
|
1932 | }
|
1933 |
|
1934 | if (valueMode) {
|
1935 | consume$1(scanner, isWhiteSpace$1);
|
1936 | }
|
1937 | while (readable(scanner)) {
|
1938 | if (consume$1(scanner, isImportant)) {
|
1939 | important = true;
|
1940 | }
|
1941 | else if (valueFragment = consumeValue(scanner, valueMode)) {
|
1942 | value.push(valueFragment);
|
1943 | }
|
1944 | else if (!consume$1(scanner, isFragmentDelimiter)) {
|
1945 | break;
|
1946 | }
|
1947 | }
|
1948 | if (name || value.length || important) {
|
1949 | return { name, value, important };
|
1950 | }
|
1951 | }
|
1952 |
|
1953 |
|
1954 |
|
1955 | function consumeValue(scanner, inArgument) {
|
1956 | const result = [];
|
1957 | let token;
|
1958 | let args;
|
1959 | while (readable(scanner)) {
|
1960 | token = peek$2(scanner);
|
1961 | if (isValue(token)) {
|
1962 | scanner.pos++;
|
1963 | if (isLiteral(token) && (args = consumeArguments(scanner))) {
|
1964 | result.push({
|
1965 | type: 'FunctionCall',
|
1966 | name: token.value,
|
1967 | arguments: args
|
1968 | });
|
1969 | }
|
1970 | else {
|
1971 | result.push(token);
|
1972 | }
|
1973 | }
|
1974 | else if (isValueDelimiter(token) || (inArgument && isWhiteSpace$1(token))) {
|
1975 | scanner.pos++;
|
1976 | }
|
1977 | else {
|
1978 | break;
|
1979 | }
|
1980 | }
|
1981 | return result.length
|
1982 | ? { type: 'CSSValue', value: result }
|
1983 | : void 0;
|
1984 | }
|
1985 | function consumeArguments(scanner) {
|
1986 | const start = scanner.pos;
|
1987 | if (consume$1(scanner, isOpenBracket$1)) {
|
1988 | const args = [];
|
1989 | let value;
|
1990 | while (readable(scanner) && !consume$1(scanner, isCloseBracket$1)) {
|
1991 | if (value = consumeValue(scanner, true)) {
|
1992 | args.push(value);
|
1993 | }
|
1994 | else if (!consume$1(scanner, isWhiteSpace$1) && !consume$1(scanner, isArgumentDelimiter)) {
|
1995 | throw error(scanner, 'Unexpected token');
|
1996 | }
|
1997 | }
|
1998 | scanner.start = start;
|
1999 | return args;
|
2000 | }
|
2001 | }
|
2002 | function isLiteral(token) {
|
2003 | return token && token.type === 'Literal';
|
2004 | }
|
2005 | function isBracket(token, open) {
|
2006 | return token && token.type === 'Bracket' && (open == null || token.open === open);
|
2007 | }
|
2008 | function isOpenBracket$1(token) {
|
2009 | return isBracket(token, true);
|
2010 | }
|
2011 | function isCloseBracket$1(token) {
|
2012 | return isBracket(token, false);
|
2013 | }
|
2014 | function isWhiteSpace$1(token) {
|
2015 | return token && token.type === 'WhiteSpace';
|
2016 | }
|
2017 | function isOperator(token, operator) {
|
2018 | return token && token.type === 'Operator' && (!operator || token.operator === operator);
|
2019 | }
|
2020 | function isSiblingOperator(token) {
|
2021 | return isOperator(token, OperatorType.Sibling);
|
2022 | }
|
2023 | function isArgumentDelimiter(token) {
|
2024 | return isOperator(token, OperatorType.ArgumentDelimiter);
|
2025 | }
|
2026 | function isFragmentDelimiter(token) {
|
2027 | return isArgumentDelimiter(token);
|
2028 | }
|
2029 | function isImportant(token) {
|
2030 | return isOperator(token, OperatorType.Important);
|
2031 | }
|
2032 | function isValue(token) {
|
2033 | return token.type === 'StringValue'
|
2034 | || token.type === 'ColorValue'
|
2035 | || token.type === 'NumberValue'
|
2036 | || token.type === 'Literal'
|
2037 | || token.type === 'Field'
|
2038 | || token.type === 'CustomProperty';
|
2039 | }
|
2040 | function isValueDelimiter(token) {
|
2041 | return isOperator(token, OperatorType.PropertyDelimiter)
|
2042 | || isOperator(token, OperatorType.ValueDelimiter);
|
2043 | }
|
2044 | function isFunctionStart(scanner) {
|
2045 | const t1 = scanner.tokens[scanner.pos];
|
2046 | const t2 = scanner.tokens[scanner.pos + 1];
|
2047 | return t1 && t2 && isLiteral(t1) && t2.type === 'Bracket';
|
2048 | }
|
2049 |
|
2050 |
|
2051 |
|
2052 |
|
2053 | function parse$2(abbr, options) {
|
2054 | try {
|
2055 | const tokens = typeof abbr === 'string' ? tokenize(abbr, options && options.value) : abbr;
|
2056 | return parser(tokens, options);
|
2057 | }
|
2058 | catch (err) {
|
2059 | if (err instanceof ScannerError && typeof abbr === 'string') {
|
2060 | err.message += `\n${abbr}\n${'-'.repeat(err.pos)}^`;
|
2061 | }
|
2062 | throw err;
|
2063 | }
|
2064 | }
|
2065 |
|
2066 |
|
2067 |
|
2068 |
|
2069 |
|
2070 | function mergeAttributes(node, config) {
|
2071 | if (!node.attributes) {
|
2072 | return;
|
2073 | }
|
2074 | const attributes = [];
|
2075 | const lookup = {};
|
2076 | for (const attr of node.attributes) {
|
2077 | if (attr.name) {
|
2078 | const attrName = attr.name;
|
2079 | if (attrName in lookup) {
|
2080 | const prev = lookup[attrName];
|
2081 | if (attrName === 'class') {
|
2082 | prev.value = mergeValue(prev.value, attr.value, ' ');
|
2083 | }
|
2084 | else {
|
2085 | mergeDeclarations(prev, attr, config);
|
2086 | }
|
2087 | }
|
2088 | else {
|
2089 |
|
2090 | attributes.push(lookup[attrName] = Object.assign({}, attr));
|
2091 | }
|
2092 | }
|
2093 | else {
|
2094 | attributes.push(attr);
|
2095 | }
|
2096 | }
|
2097 | node.attributes = attributes;
|
2098 | }
|
2099 |
|
2100 |
|
2101 |
|
2102 | function mergeValue(prev, next, glue) {
|
2103 | if (prev && next) {
|
2104 | if (prev.length && glue) {
|
2105 | append(prev, glue);
|
2106 | }
|
2107 | for (const t of next) {
|
2108 | append(prev, t);
|
2109 | }
|
2110 | return prev;
|
2111 | }
|
2112 | const result = prev || next;
|
2113 | return result && result.slice();
|
2114 | }
|
2115 |
|
2116 |
|
2117 |
|
2118 | function mergeDeclarations(dest, src, config) {
|
2119 | dest.name = src.name;
|
2120 | if (!config.options['output.reverseAttributes']) {
|
2121 | dest.value = src.value;
|
2122 | }
|
2123 |
|
2124 | if (!dest.implied) {
|
2125 | dest.implied = src.implied;
|
2126 | }
|
2127 | if (!dest.boolean) {
|
2128 | dest.boolean = src.boolean;
|
2129 | }
|
2130 | if (dest.valueType !== 'expression') {
|
2131 | dest.valueType = src.valueType;
|
2132 | }
|
2133 | return dest;
|
2134 | }
|
2135 | function append(tokens, value) {
|
2136 | const lastIx = tokens.length - 1;
|
2137 | if (typeof tokens[lastIx] === 'string' && typeof value === 'string') {
|
2138 | tokens[lastIx] += value;
|
2139 | }
|
2140 | else {
|
2141 | tokens.push(value);
|
2142 | }
|
2143 | }
|
2144 |
|
2145 |
|
2146 |
|
2147 |
|
2148 |
|
2149 |
|
2150 |
|
2151 | function walk$1(node, fn, state) {
|
2152 | const ancestors = [node];
|
2153 | const callback = (ctx) => {
|
2154 | fn(ctx, ancestors, state);
|
2155 | ancestors.push(ctx);
|
2156 | ctx.children.forEach(callback);
|
2157 | ancestors.pop();
|
2158 | };
|
2159 | node.children.forEach(callback);
|
2160 | }
|
2161 |
|
2162 |
|
2163 |
|
2164 | function find$1(node, callback) {
|
2165 | for (let i = 0; i < node.children.length; i++) {
|
2166 | const child = node.children[i];
|
2167 | if (callback(child)) {
|
2168 | return child;
|
2169 | }
|
2170 | const result = find$1(child, callback);
|
2171 | if (result) {
|
2172 | return result;
|
2173 | }
|
2174 | }
|
2175 | }
|
2176 |
|
2177 |
|
2178 |
|
2179 | function findDeepest(node) {
|
2180 | let parent;
|
2181 | while (node.children.length) {
|
2182 | parent = node;
|
2183 | node = node.children[node.children.length - 1];
|
2184 | }
|
2185 | return { parent, node };
|
2186 | }
|
2187 | function isNode(node) {
|
2188 | return node.type === 'AbbreviationNode';
|
2189 | }
|
2190 |
|
2191 |
|
2192 |
|
2193 |
|
2194 |
|
2195 |
|
2196 |
|
2197 |
|
2198 |
|
2199 |
|
2200 | function resolveSnippets(abbr, config) {
|
2201 | const stack = [];
|
2202 | const reversed = config.options['output.reverseAttributes'];
|
2203 | const resolve = (child) => {
|
2204 | const snippet = child.name && config.snippets[child.name];
|
2205 |
|
2206 |
|
2207 |
|
2208 |
|
2209 | if (!snippet || stack.includes(snippet)) {
|
2210 | return null;
|
2211 | }
|
2212 | const snippetAbbr = parseAbbreviation(snippet, config);
|
2213 | stack.push(snippet);
|
2214 | walkResolve(snippetAbbr, resolve);
|
2215 | stack.pop();
|
2216 |
|
2217 | for (const topNode of snippetAbbr.children) {
|
2218 | if (child.attributes) {
|
2219 | const from = topNode.attributes || [];
|
2220 | const to = child.attributes || [];
|
2221 | topNode.attributes = reversed ? to.concat(from) : from.concat(to);
|
2222 | }
|
2223 | mergeNodes(child, topNode);
|
2224 | }
|
2225 | return snippetAbbr;
|
2226 | };
|
2227 | walkResolve(abbr, resolve);
|
2228 | return abbr;
|
2229 | }
|
2230 | function walkResolve(node, resolve, config) {
|
2231 | let children = [];
|
2232 | for (const child of node.children) {
|
2233 | const resolved = resolve(child);
|
2234 | if (resolved) {
|
2235 | children = children.concat(resolved.children);
|
2236 | const deepest = findDeepest(resolved);
|
2237 | if (isNode(deepest.node)) {
|
2238 | deepest.node.children = deepest.node.children.concat(walkResolve(child, resolve));
|
2239 | }
|
2240 | }
|
2241 | else {
|
2242 | children.push(child);
|
2243 | child.children = walkResolve(child, resolve);
|
2244 | }
|
2245 | }
|
2246 | return node.children = children;
|
2247 | }
|
2248 |
|
2249 |
|
2250 |
|
2251 | function mergeNodes(from, to) {
|
2252 | if (from.selfClosing) {
|
2253 | to.selfClosing = true;
|
2254 | }
|
2255 | if (from.value != null) {
|
2256 | to.value = from.value;
|
2257 | }
|
2258 | if (from.repeat) {
|
2259 | to.repeat = from.repeat;
|
2260 | }
|
2261 | }
|
2262 |
|
2263 | const expressionStart = '{';
|
2264 | const expressionEnd = '}';
|
2265 | function createOutputStream(options, level = 0) {
|
2266 | return {
|
2267 | options,
|
2268 | value: '',
|
2269 | level,
|
2270 | offset: 0,
|
2271 | line: 0,
|
2272 | column: 0
|
2273 | };
|
2274 | }
|
2275 |
|
2276 |
|
2277 |
|
2278 | function push(stream, text) {
|
2279 | const processText = stream.options['output.text'];
|
2280 | _push(stream, processText(text, stream.offset, stream.line, stream.column));
|
2281 | }
|
2282 |
|
2283 |
|
2284 |
|
2285 | function pushString(stream, value) {
|
2286 |
|
2287 |
|
2288 | const lines = splitByLines$1(value);
|
2289 | for (let i = 0, il = lines.length - 1; i <= il; i++) {
|
2290 | push(stream, lines[i]);
|
2291 | if (i !== il) {
|
2292 | pushNewline(stream, true);
|
2293 | }
|
2294 | }
|
2295 | }
|
2296 |
|
2297 |
|
2298 |
|
2299 | function pushNewline(stream, indent) {
|
2300 | const baseIndent = stream.options['output.baseIndent'];
|
2301 | const newline = stream.options['output.newline'];
|
2302 | push(stream, newline + baseIndent);
|
2303 | stream.line++;
|
2304 | stream.column = baseIndent.length;
|
2305 | if (indent) {
|
2306 | pushIndent(stream, indent === true ? stream.level : indent);
|
2307 | }
|
2308 | }
|
2309 |
|
2310 |
|
2311 |
|
2312 | function pushIndent(stream, size = stream.level) {
|
2313 | const indent = stream.options['output.indent'];
|
2314 | push(stream, indent.repeat(Math.max(size, 0)));
|
2315 | }
|
2316 |
|
2317 |
|
2318 |
|
2319 | function pushField(stream, index, placeholder) {
|
2320 | const field = stream.options['output.field'];
|
2321 |
|
2322 | _push(stream, field(index, placeholder, stream.offset, stream.line, stream.column));
|
2323 | }
|
2324 |
|
2325 |
|
2326 |
|
2327 | function tagName(name, config) {
|
2328 | return strCase(name, config.options['output.tagCase']);
|
2329 | }
|
2330 |
|
2331 |
|
2332 |
|
2333 | function attrName(name, config) {
|
2334 | return strCase(name, config.options['output.attributeCase']);
|
2335 | }
|
2336 |
|
2337 |
|
2338 |
|
2339 | function attrQuote(attr, config, isOpen) {
|
2340 | if (attr.valueType === 'expression') {
|
2341 | return isOpen ? expressionStart : expressionEnd;
|
2342 | }
|
2343 | return config.options['output.attributeQuotes'] === 'single' ? '\'' : '"';
|
2344 | }
|
2345 |
|
2346 |
|
2347 |
|
2348 | function isBooleanAttribute(attr, config) {
|
2349 | return attr.boolean
|
2350 | || config.options['output.booleanAttributes'].includes((attr.name || '').toLowerCase());
|
2351 | }
|
2352 |
|
2353 |
|
2354 |
|
2355 | function selfClose(config) {
|
2356 | switch (config.options['output.selfClosingStyle']) {
|
2357 | case 'xhtml': return ' /';
|
2358 | case 'xml': return '/';
|
2359 | default: return '';
|
2360 | }
|
2361 | }
|
2362 |
|
2363 |
|
2364 |
|
2365 |
|
2366 | function isInline(node, config) {
|
2367 | if (typeof node === 'string') {
|
2368 | return config.options.inlineElements.includes(node.toLowerCase());
|
2369 | }
|
2370 |
|
2371 | return node.name ? isInline(node.name, config) : Boolean(node.value && !node.attributes);
|
2372 | }
|
2373 |
|
2374 |
|
2375 |
|
2376 | function splitByLines$1(text) {
|
2377 | return text.split(/\r\n|\r|\n/g);
|
2378 | }
|
2379 |
|
2380 |
|
2381 |
|
2382 | function _push(stream, text) {
|
2383 | stream.value += text;
|
2384 | stream.offset += text.length;
|
2385 | stream.column += text.length;
|
2386 | }
|
2387 | function strCase(str, type) {
|
2388 | if (type) {
|
2389 | return type === 'upper' ? str.toUpperCase() : str.toLowerCase();
|
2390 | }
|
2391 | return str;
|
2392 | }
|
2393 |
|
2394 | const elementMap = {
|
2395 | p: 'span',
|
2396 | ul: 'li',
|
2397 | ol: 'li',
|
2398 | table: 'tr',
|
2399 | tr: 'td',
|
2400 | tbody: 'tr',
|
2401 | thead: 'tr',
|
2402 | tfoot: 'tr',
|
2403 | colgroup: 'col',
|
2404 | select: 'option',
|
2405 | optgroup: 'option',
|
2406 | audio: 'source',
|
2407 | video: 'source',
|
2408 | object: 'param',
|
2409 | map: 'area'
|
2410 | };
|
2411 | function implicitTag(node, ancestors, config) {
|
2412 | if (!node.name && node.attributes) {
|
2413 | resolveImplicitTag(node, ancestors, config);
|
2414 | }
|
2415 | }
|
2416 | function resolveImplicitTag(node, ancestors, config) {
|
2417 | const parent = getParentElement(ancestors);
|
2418 | const contextName = config.context ? config.context.name : '';
|
2419 | const parentName = lowercase(parent ? parent.name : contextName);
|
2420 | node.name = elementMap[parentName]
|
2421 | || (isInline(parentName, config) ? 'span' : 'div');
|
2422 | }
|
2423 | function lowercase(str) {
|
2424 | return (str || '').toLowerCase();
|
2425 | }
|
2426 |
|
2427 |
|
2428 |
|
2429 | function getParentElement(ancestors) {
|
2430 | for (let i = ancestors.length - 1; i >= 0; i--) {
|
2431 | const elem = ancestors[i];
|
2432 | if (isNode(elem)) {
|
2433 | return elem;
|
2434 | }
|
2435 | }
|
2436 | }
|
2437 |
|
2438 | var latin = {
|
2439 | "common": ["lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipisicing", "elit"],
|
2440 | "words": ["exercitationem", "perferendis", "perspiciatis", "laborum", "eveniet",
|
2441 | "sunt", "iure", "nam", "nobis", "eum", "cum", "officiis", "excepturi",
|
2442 | "odio", "consectetur", "quasi", "aut", "quisquam", "vel", "eligendi",
|
2443 | "itaque", "non", "odit", "tempore", "quaerat", "dignissimos",
|
2444 | "facilis", "neque", "nihil", "expedita", "vitae", "vero", "ipsum",
|
2445 | "nisi", "animi", "cumque", "pariatur", "velit", "modi", "natus",
|
2446 | "iusto", "eaque", "sequi", "illo", "sed", "ex", "et", "voluptatibus",
|
2447 | "tempora", "veritatis", "ratione", "assumenda", "incidunt", "nostrum",
|
2448 | "placeat", "aliquid", "fuga", "provident", "praesentium", "rem",
|
2449 | "necessitatibus", "suscipit", "adipisci", "quidem", "possimus",
|
2450 | "voluptas", "debitis", "sint", "accusantium", "unde", "sapiente",
|
2451 | "voluptate", "qui", "aspernatur", "laudantium", "soluta", "amet",
|
2452 | "quo", "aliquam", "saepe", "culpa", "libero", "ipsa", "dicta",
|
2453 | "reiciendis", "nesciunt", "doloribus", "autem", "impedit", "minima",
|
2454 | "maiores", "repudiandae", "ipsam", "obcaecati", "ullam", "enim",
|
2455 | "totam", "delectus", "ducimus", "quis", "voluptates", "dolores",
|
2456 | "molestiae", "harum", "dolorem", "quia", "voluptatem", "molestias",
|
2457 | "magni", "distinctio", "omnis", "illum", "dolorum", "voluptatum", "ea",
|
2458 | "quas", "quam", "corporis", "quae", "blanditiis", "atque", "deserunt",
|
2459 | "laboriosam", "earum", "consequuntur", "hic", "cupiditate",
|
2460 | "quibusdam", "accusamus", "ut", "rerum", "error", "minus", "eius",
|
2461 | "ab", "ad", "nemo", "fugit", "officia", "at", "in", "id", "quos",
|
2462 | "reprehenderit", "numquam", "iste", "fugiat", "sit", "inventore",
|
2463 | "beatae", "repellendus", "magnam", "recusandae", "quod", "explicabo",
|
2464 | "doloremque", "aperiam", "consequatur", "asperiores", "commodi",
|
2465 | "optio", "dolor", "labore", "temporibus", "repellat", "veniam",
|
2466 | "architecto", "est", "esse", "mollitia", "nulla", "a", "similique",
|
2467 | "eos", "alias", "dolore", "tenetur", "deleniti", "porro", "facere",
|
2468 | "maxime", "corrupti"]
|
2469 | };
|
2470 |
|
2471 | var ru = {
|
2472 | "common": ["далеко-далеко", "за", "словесными", "горами", "в стране", "гласных", "и согласных", "живут", "рыбные", "тексты"],
|
2473 | "words": ["вдали", "от всех", "они", "буквенных", "домах", "на берегу", "семантика",
|
2474 | "большого", "языкового", "океана", "маленький", "ручеек", "даль",
|
2475 | "журчит", "по всей", "обеспечивает", "ее","всеми", "необходимыми",
|
2476 | "правилами", "эта", "парадигматическая", "страна", "которой", "жаренные",
|
2477 | "предложения", "залетают", "прямо", "рот", "даже", "всемогущая",
|
2478 | "пунктуация", "не", "имеет", "власти", "над", "рыбными", "текстами",
|
2479 | "ведущими", "безорфографичный", "образ", "жизни", "однажды", "одна",
|
2480 | "маленькая", "строчка","рыбного", "текста", "имени", "lorem", "ipsum",
|
2481 | "решила", "выйти", "большой", "мир", "грамматики", "великий", "оксмокс",
|
2482 | "предупреждал", "о", "злых", "запятых", "диких", "знаках", "вопроса",
|
2483 | "коварных", "точках", "запятой", "но", "текст", "дал", "сбить",
|
2484 | "себя", "толку", "он", "собрал", "семь", "своих", "заглавных", "букв",
|
2485 | "подпоясал", "инициал", "за", "пояс", "пустился", "дорогу",
|
2486 | "взобравшись", "первую", "вершину", "курсивных", "гор", "бросил",
|
2487 | "последний", "взгляд", "назад", "силуэт", "своего", "родного", "города",
|
2488 | "буквоград", "заголовок", "деревни", "алфавит", "подзаголовок", "своего",
|
2489 | "переулка", "грустный", "реторический", "вопрос", "скатился", "его",
|
2490 | "щеке", "продолжил", "свой", "путь", "дороге", "встретил", "рукопись",
|
2491 | "она", "предупредила", "моей", "все", "переписывается", "несколько",
|
2492 | "раз", "единственное", "что", "меня", "осталось", "это", "приставка",
|
2493 | "возвращайся", "ты", "лучше", "свою", "безопасную", "страну", "послушавшись",
|
2494 | "рукописи", "наш", "продолжил", "свой", "путь", "вскоре", "ему",
|
2495 | "повстречался", "коварный", "составитель", "рекламных", "текстов",
|
2496 | "напоивший", "языком", "речью", "заманивший", "свое", "агентство",
|
2497 | "которое", "использовало", "снова", "снова", "своих", "проектах",
|
2498 | "если", "переписали", "то", "живет", "там", "до", "сих", "пор"]
|
2499 | };
|
2500 |
|
2501 | var sp = {
|
2502 | "common": ["mujer", "uno", "dolor", "más", "de", "poder", "mismo", "si"],
|
2503 | "words": ["ejercicio", "preferencia", "perspicacia", "laboral", "paño",
|
2504 | "suntuoso", "molde", "namibia", "planeador", "mirar", "demás", "oficinista", "excepción",
|
2505 | "odio", "consecuencia", "casi", "auto", "chicharra", "velo", "elixir",
|
2506 | "ataque", "no", "odio", "temporal", "cuórum", "dignísimo",
|
2507 | "facilismo", "letra", "nihilista", "expedición", "alma", "alveolar", "aparte",
|
2508 | "león", "animal", "como", "paria", "belleza", "modo", "natividad",
|
2509 | "justo", "ataque", "séquito", "pillo", "sed", "ex", "y", "voluminoso",
|
2510 | "temporalidad", "verdades", "racional", "asunción", "incidente", "marejada",
|
2511 | "placenta", "amanecer", "fuga", "previsor", "presentación", "lejos",
|
2512 | "necesariamente", "sospechoso", "adiposidad", "quindío", "pócima",
|
2513 | "voluble", "débito", "sintió", "accesorio", "falda", "sapiencia",
|
2514 | "volutas", "queso", "permacultura", "laudo", "soluciones", "entero",
|
2515 | "pan", "litro", "tonelada", "culpa", "libertario", "mosca", "dictado",
|
2516 | "reincidente", "nascimiento", "dolor", "escolar", "impedimento", "mínima",
|
2517 | "mayores", "repugnante", "dulce", "obcecado", "montaña", "enigma",
|
2518 | "total", "deletéreo", "décima", "cábala", "fotografía", "dolores",
|
2519 | "molesto", "olvido", "paciencia", "resiliencia", "voluntad", "molestias",
|
2520 | "magnífico", "distinción", "ovni", "marejada", "cerro", "torre", "y",
|
2521 | "abogada", "manantial", "corporal", "agua", "crepúsculo", "ataque", "desierto",
|
2522 | "laboriosamente", "angustia", "afortunado", "alma", "encefalograma",
|
2523 | "materialidad", "cosas", "o", "renuncia", "error", "menos", "conejo",
|
2524 | "abadía", "analfabeto", "remo", "fugacidad", "oficio", "en", "almácigo", "vos", "pan",
|
2525 | "represión", "números", "triste", "refugiado", "trote", "inventor",
|
2526 | "corchea", "repelente", "magma", "recusado", "patrón", "explícito",
|
2527 | "paloma", "síndrome", "inmune", "autoinmune", "comodidad",
|
2528 | "ley", "vietnamita", "demonio", "tasmania", "repeler", "apéndice",
|
2529 | "arquitecto", "columna", "yugo", "computador", "mula", "a", "propósito",
|
2530 | "fantasía", "alias", "rayo", "tenedor", "deleznable", "ventana", "cara",
|
2531 | "anemia", "corrupto"]
|
2532 | };
|
2533 |
|
2534 | const vocabularies = { ru, sp, latin };
|
2535 | const reLorem = /^lorem([a-z]*)(\d*)(-\d*)?$/i;
|
2536 | function lorem(node, ancestors, config) {
|
2537 | let m;
|
2538 | if (node.name && (m = node.name.match(reLorem))) {
|
2539 | const db = vocabularies[m[1]] || vocabularies.latin;
|
2540 | const minWordCount = m[2] ? Math.max(1, Number(m[2])) : 30;
|
2541 | const maxWordCount = m[3] ? Math.max(minWordCount, Number(m[3].slice(1))) : minWordCount;
|
2542 | const wordCount = rand(minWordCount, maxWordCount);
|
2543 | const repeat = node.repeat || findRepeater(ancestors);
|
2544 | node.name = node.attributes = void 0;
|
2545 | node.value = [paragraph(db, wordCount, !repeat || repeat.value === 0)];
|
2546 | if (node.repeat && ancestors.length > 1) {
|
2547 | resolveImplicitTag(node, ancestors, config);
|
2548 | }
|
2549 | }
|
2550 | }
|
2551 |
|
2552 |
|
2553 |
|
2554 | function rand(from, to) {
|
2555 | return Math.floor(Math.random() * (to - from) + from);
|
2556 | }
|
2557 | function sample(arr, count) {
|
2558 | const len = arr.length;
|
2559 | const iterations = Math.min(len, count);
|
2560 | const result = [];
|
2561 | while (result.length < iterations) {
|
2562 | const str = arr[rand(0, len)];
|
2563 | if (!result.includes(str)) {
|
2564 | result.push(str);
|
2565 | }
|
2566 | }
|
2567 | return result;
|
2568 | }
|
2569 | function choice(val) {
|
2570 | return val[rand(0, val.length - 1)];
|
2571 | }
|
2572 | function sentence(words, end) {
|
2573 | if (words.length) {
|
2574 | words = [capitalize(words[0])].concat(words.slice(1));
|
2575 | }
|
2576 | return words.join(' ') + (end || choice('?!...'));
|
2577 | }
|
2578 | function capitalize(word) {
|
2579 | return word[0].toUpperCase() + word.slice(1);
|
2580 | }
|
2581 |
|
2582 |
|
2583 |
|
2584 |
|
2585 | function insertCommas(words) {
|
2586 | if (words.length < 2) {
|
2587 | return words;
|
2588 | }
|
2589 | words = words.slice();
|
2590 | const len = words.length;
|
2591 | const hasComma = /,$/;
|
2592 | let totalCommas = 0;
|
2593 | if (len > 3 && len <= 6) {
|
2594 | totalCommas = rand(0, 1);
|
2595 | }
|
2596 | else if (len > 6 && len <= 12) {
|
2597 | totalCommas = rand(0, 2);
|
2598 | }
|
2599 | else {
|
2600 | totalCommas = rand(1, 4);
|
2601 | }
|
2602 | for (let i = 0, pos; i < totalCommas; i++) {
|
2603 | pos = rand(0, len - 2);
|
2604 | if (!hasComma.test(words[pos])) {
|
2605 | words[pos] += ',';
|
2606 | }
|
2607 | }
|
2608 | return words;
|
2609 | }
|
2610 |
|
2611 |
|
2612 |
|
2613 |
|
2614 |
|
2615 |
|
2616 | function paragraph(dict, wordCount, startWithCommon) {
|
2617 | const result = [];
|
2618 | let totalWords = 0;
|
2619 | let words;
|
2620 | if (startWithCommon && dict.common) {
|
2621 | words = dict.common.slice(0, wordCount);
|
2622 | totalWords += words.length;
|
2623 | result.push(sentence(insertCommas(words), '.'));
|
2624 | }
|
2625 | while (totalWords < wordCount) {
|
2626 | words = sample(dict.words, Math.min(rand(2, 30), wordCount - totalWords));
|
2627 | totalWords += words.length;
|
2628 | result.push(sentence(insertCommas(words)));
|
2629 | }
|
2630 | return result.join(' ');
|
2631 | }
|
2632 | function findRepeater(ancestors) {
|
2633 | for (let i = ancestors.length - 1; i >= 0; i--) {
|
2634 | const element = ancestors[i];
|
2635 | if (element.type === 'AbbreviationNode' && element.repeat) {
|
2636 | return element.repeat;
|
2637 | }
|
2638 | }
|
2639 | }
|
2640 |
|
2641 |
|
2642 |
|
2643 |
|
2644 |
|
2645 | function xsl(node) {
|
2646 | if (matchesName(node.name) && node.attributes && (node.children.length || node.value)) {
|
2647 | node.attributes = node.attributes.filter(isAllowed);
|
2648 | }
|
2649 | }
|
2650 | function isAllowed(attr) {
|
2651 | return attr.name !== 'select';
|
2652 | }
|
2653 | function matchesName(name) {
|
2654 | return name === 'xsl:variable' || name === 'xsl:with-param';
|
2655 | }
|
2656 |
|
2657 | const reElement = /^(-+)([a-z0-9]+[a-z0-9-]*)/i;
|
2658 | const reModifier = /^(_+)([a-z0-9]+[a-z0-9-_]*)/i;
|
2659 | const blockCandidates1 = (className) => /^[a-z]\-/i.test(className);
|
2660 | const blockCandidates2 = (className) => /^[a-z]/i.test(className);
|
2661 | function bem(node, ancestors, config) {
|
2662 | expandClassNames(node);
|
2663 | expandShortNotation(node, ancestors, config);
|
2664 | }
|
2665 |
|
2666 |
|
2667 |
|
2668 |
|
2669 |
|
2670 | function expandClassNames(node) {
|
2671 | const data = getBEMData(node);
|
2672 | const classNames = [];
|
2673 | for (const cl of data.classNames) {
|
2674 |
|
2675 | const ix = cl.indexOf('_');
|
2676 | if (ix > 0 && !cl.startsWith('-')) {
|
2677 | classNames.push(cl.slice(0, ix));
|
2678 | classNames.push(cl.slice(ix));
|
2679 | }
|
2680 | else {
|
2681 | classNames.push(cl);
|
2682 | }
|
2683 | }
|
2684 | if (classNames.length) {
|
2685 | data.classNames = classNames.filter(uniqueClass);
|
2686 | data.block = findBlockName(data.classNames);
|
2687 | updateClass(node, data.classNames.join(' '));
|
2688 | }
|
2689 | }
|
2690 |
|
2691 |
|
2692 |
|
2693 | function expandShortNotation(node, ancestors, config) {
|
2694 | const data = getBEMData(node);
|
2695 | const classNames = [];
|
2696 | const { options } = config;
|
2697 | const path = ancestors.slice(1).concat(node);
|
2698 | for (let cl of data.classNames) {
|
2699 | let prefix = '';
|
2700 | let m;
|
2701 | const originalClass = cl;
|
2702 |
|
2703 | if (m = cl.match(reElement)) {
|
2704 | prefix = getBlockName(path, m[1].length, config.context) + options['bem.element'] + m[2];
|
2705 | classNames.push(prefix);
|
2706 | cl = cl.slice(m[0].length);
|
2707 | }
|
2708 |
|
2709 | if (m = cl.match(reModifier)) {
|
2710 | if (!prefix) {
|
2711 | prefix = getBlockName(path, m[1].length);
|
2712 | classNames.push(prefix);
|
2713 | }
|
2714 | classNames.push(`${prefix}${options['bem.modifier']}${m[2]}`);
|
2715 | cl = cl.slice(m[0].length);
|
2716 | }
|
2717 | if (cl === originalClass) {
|
2718 |
|
2719 |
|
2720 | classNames.push(originalClass);
|
2721 | }
|
2722 | }
|
2723 | const arrClassNames = classNames.filter(uniqueClass);
|
2724 | if (arrClassNames.length) {
|
2725 | updateClass(node, arrClassNames.join(' '));
|
2726 | }
|
2727 | }
|
2728 |
|
2729 |
|
2730 |
|
2731 | function getBEMData(node) {
|
2732 | if (!node._bem) {
|
2733 | let classValue = '';
|
2734 | if (node.attributes) {
|
2735 | for (const attr of node.attributes) {
|
2736 | if (attr.name === 'class' && attr.value) {
|
2737 | classValue = stringifyValue(attr.value);
|
2738 | break;
|
2739 | }
|
2740 | }
|
2741 | }
|
2742 | node._bem = parseBEM(classValue);
|
2743 | }
|
2744 | return node._bem;
|
2745 | }
|
2746 | function getBEMDataFromContext(context) {
|
2747 | if (!context._bem) {
|
2748 | context._bem = parseBEM(context.attributes && context.attributes.class || '');
|
2749 | }
|
2750 | return context._bem;
|
2751 | }
|
2752 |
|
2753 |
|
2754 |
|
2755 | function parseBEM(classValue) {
|
2756 | const classNames = classValue ? classValue.split(/\s+/) : [];
|
2757 | return {
|
2758 | classNames,
|
2759 | block: findBlockName(classNames)
|
2760 | };
|
2761 | }
|
2762 |
|
2763 |
|
2764 |
|
2765 |
|
2766 | function getBlockName(ancestors, depth = 0, context) {
|
2767 | const maxParentIx = 0;
|
2768 | let parentIx = Math.max(ancestors.length - depth, maxParentIx);
|
2769 | do {
|
2770 | const parent = ancestors[parentIx];
|
2771 | if (parent) {
|
2772 | const data = getBEMData(parent);
|
2773 | if (data.block) {
|
2774 | return data.block;
|
2775 | }
|
2776 | }
|
2777 | } while (maxParentIx < parentIx--);
|
2778 | if (context) {
|
2779 | const data = getBEMDataFromContext(context);
|
2780 | if (data.block) {
|
2781 | return data.block;
|
2782 | }
|
2783 | }
|
2784 | return '';
|
2785 | }
|
2786 | function findBlockName(classNames) {
|
2787 | return find(classNames, blockCandidates1)
|
2788 | || find(classNames, blockCandidates2)
|
2789 | || void 0;
|
2790 | }
|
2791 |
|
2792 |
|
2793 |
|
2794 | function find(classNames, filter) {
|
2795 | for (const cl of classNames) {
|
2796 | if (reElement.test(cl) || reModifier.test(cl)) {
|
2797 | break;
|
2798 | }
|
2799 | if (filter(cl)) {
|
2800 | return cl;
|
2801 | }
|
2802 | }
|
2803 | }
|
2804 | function updateClass(node, value) {
|
2805 | for (const attr of node.attributes) {
|
2806 | if (attr.name === 'class') {
|
2807 | attr.value = [value];
|
2808 | break;
|
2809 | }
|
2810 | }
|
2811 | }
|
2812 | function stringifyValue(value) {
|
2813 | let result = '';
|
2814 | for (const t of value) {
|
2815 | result += typeof t === 'string' ? t : t.name;
|
2816 | }
|
2817 | return result;
|
2818 | }
|
2819 | function uniqueClass(item, ix, arr) {
|
2820 | return !!item && arr.indexOf(item) === ix;
|
2821 | }
|
2822 |
|
2823 |
|
2824 |
|
2825 |
|
2826 |
|
2827 | function label(node) {
|
2828 | if (node.name === 'label') {
|
2829 | const input = find$1(node, n => (n.name === 'input' || n.name === 'textarea'));
|
2830 | if (input) {
|
2831 |
|
2832 | if (node.attributes) {
|
2833 | node.attributes = node.attributes.filter(attr => {
|
2834 | return !(attr.name === 'for' && isEmptyAttribute(attr));
|
2835 | });
|
2836 | }
|
2837 |
|
2838 | if (input.attributes) {
|
2839 | input.attributes = input.attributes.filter(attr => {
|
2840 | return !(attr.name === 'id' && isEmptyAttribute(attr));
|
2841 | });
|
2842 | }
|
2843 | }
|
2844 | }
|
2845 | }
|
2846 | function isEmptyAttribute(attr) {
|
2847 | if (!attr.value) {
|
2848 | return true;
|
2849 | }
|
2850 | if (attr.value.length === 1) {
|
2851 | const token = attr.value[0];
|
2852 | if (token && typeof token !== 'string' && !token.name) {
|
2853 |
|
2854 | return true;
|
2855 | }
|
2856 | }
|
2857 | return false;
|
2858 | }
|
2859 |
|
2860 | function walk(abbr, visitor, state) {
|
2861 | const callback = (ctx, index, items) => {
|
2862 | const { parent, current } = state;
|
2863 | state.parent = current;
|
2864 | state.current = ctx;
|
2865 | visitor(ctx, index, items, state, next);
|
2866 | state.current = current;
|
2867 | state.parent = parent;
|
2868 | };
|
2869 | const next = (node, index, items) => {
|
2870 | state.ancestors.push(state.current);
|
2871 | callback(node, index, items);
|
2872 | state.ancestors.pop();
|
2873 | };
|
2874 | abbr.children.forEach(callback);
|
2875 | }
|
2876 | function createWalkState(config) {
|
2877 | return {
|
2878 |
|
2879 | current: null,
|
2880 | parent: void 0,
|
2881 | ancestors: [],
|
2882 | config,
|
2883 | field: 1,
|
2884 | out: createOutputStream(config.options)
|
2885 | };
|
2886 | }
|
2887 |
|
2888 | const caret = [{ type: 'Field', index: 0, name: '' }];
|
2889 |
|
2890 |
|
2891 |
|
2892 | function isSnippet(node) {
|
2893 | return node ? !node.name && !node.attributes : false;
|
2894 | }
|
2895 |
|
2896 |
|
2897 |
|
2898 |
|
2899 | function isInlineElement(node, config) {
|
2900 | return node ? isInline(node, config) : false;
|
2901 | }
|
2902 |
|
2903 |
|
2904 |
|
2905 | function isField(token) {
|
2906 | return typeof token === 'object' && token.type === 'Field';
|
2907 | }
|
2908 | function pushTokens(tokens, state) {
|
2909 | const { out } = state;
|
2910 | let largestIndex = -1;
|
2911 | for (const t of tokens) {
|
2912 | if (typeof t === 'string') {
|
2913 | pushString(out, t);
|
2914 | }
|
2915 | else {
|
2916 | pushField(out, state.field + t.index, t.name);
|
2917 | if (t.index > largestIndex) {
|
2918 | largestIndex = t.index;
|
2919 | }
|
2920 | }
|
2921 | }
|
2922 | if (largestIndex !== -1) {
|
2923 | state.field += largestIndex + 1;
|
2924 | }
|
2925 | }
|
2926 |
|
2927 |
|
2928 |
|
2929 |
|
2930 | function splitByLines(tokens) {
|
2931 | const result = [];
|
2932 | let line = [];
|
2933 | for (const t of tokens) {
|
2934 | if (typeof t === 'string') {
|
2935 | const lines = t.split(/\r\n?|\n/g);
|
2936 | line.push(lines.shift() || '');
|
2937 | while (lines.length) {
|
2938 | result.push(line);
|
2939 | line = [lines.shift() || ''];
|
2940 | }
|
2941 | }
|
2942 | else {
|
2943 | line.push(t);
|
2944 | }
|
2945 | }
|
2946 | line.length && result.push(line);
|
2947 | return result;
|
2948 | }
|
2949 |
|
2950 |
|
2951 |
|
2952 | function shouldOutputAttribute(attr) {
|
2953 |
|
2954 |
|
2955 | return !attr.implied || attr.valueType !== 'raw' || (!!attr.value && attr.value.length > 0);
|
2956 | }
|
2957 |
|
2958 | var TemplateChars;
|
2959 | (function (TemplateChars) {
|
2960 |
|
2961 | TemplateChars[TemplateChars["Start"] = 91] = "Start";
|
2962 |
|
2963 | TemplateChars[TemplateChars["End"] = 93] = "End";
|
2964 |
|
2965 | TemplateChars[TemplateChars["Underscore"] = 95] = "Underscore";
|
2966 |
|
2967 | TemplateChars[TemplateChars["Dash"] = 45] = "Dash";
|
2968 | })(TemplateChars || (TemplateChars = {}));
|
2969 |
|
2970 |
|
2971 |
|
2972 |
|
2973 |
|
2974 |
|
2975 |
|
2976 |
|
2977 | function template(text) {
|
2978 | const tokens = [];
|
2979 | const scanner = { pos: 0, text };
|
2980 | let placeholder;
|
2981 | let offset = scanner.pos;
|
2982 | let pos = scanner.pos;
|
2983 | while (scanner.pos < scanner.text.length) {
|
2984 | pos = scanner.pos;
|
2985 | if (placeholder = consumePlaceholder(scanner)) {
|
2986 | if (offset !== scanner.pos) {
|
2987 | tokens.push(text.slice(offset, pos));
|
2988 | }
|
2989 | tokens.push(placeholder);
|
2990 | offset = scanner.pos;
|
2991 | }
|
2992 | else {
|
2993 | scanner.pos++;
|
2994 | }
|
2995 | }
|
2996 | if (offset !== scanner.pos) {
|
2997 | tokens.push(text.slice(offset));
|
2998 | }
|
2999 | return tokens;
|
3000 | }
|
3001 |
|
3002 |
|
3003 |
|
3004 | function consumePlaceholder(scanner) {
|
3005 | if (peek$1(scanner) === TemplateChars.Start) {
|
3006 | const start = ++scanner.pos;
|
3007 | let namePos = start;
|
3008 | let afterPos = start;
|
3009 | let stack = 1;
|
3010 | while (scanner.pos < scanner.text.length) {
|
3011 | const code = peek$1(scanner);
|
3012 | if (isTokenStart(code)) {
|
3013 | namePos = scanner.pos;
|
3014 | while (isToken(peek$1(scanner))) {
|
3015 | scanner.pos++;
|
3016 | }
|
3017 | afterPos = scanner.pos;
|
3018 | }
|
3019 | else {
|
3020 | if (code === TemplateChars.Start) {
|
3021 | stack++;
|
3022 | }
|
3023 | else if (code === TemplateChars.End) {
|
3024 | if (--stack === 0) {
|
3025 | return {
|
3026 | before: scanner.text.slice(start, namePos),
|
3027 | after: scanner.text.slice(afterPos, scanner.pos++),
|
3028 | name: scanner.text.slice(namePos, afterPos)
|
3029 | };
|
3030 | }
|
3031 | }
|
3032 | scanner.pos++;
|
3033 | }
|
3034 | }
|
3035 | }
|
3036 | }
|
3037 | function peek$1(scanner, pos = scanner.pos) {
|
3038 | return scanner.text.charCodeAt(pos);
|
3039 | }
|
3040 | function isTokenStart(code) {
|
3041 | return code >= 65 && code <= 90;
|
3042 | }
|
3043 | function isToken(code) {
|
3044 | return isTokenStart(code)
|
3045 | || (code > 47 && code < 58)
|
3046 | || code === TemplateChars.Underscore
|
3047 | || code === TemplateChars.Dash;
|
3048 | }
|
3049 |
|
3050 | function createCommentState(config) {
|
3051 | const { options } = config;
|
3052 | return {
|
3053 | enabled: options['comment.enabled'],
|
3054 | trigger: options['comment.trigger'],
|
3055 | before: options['comment.before'] ? template(options['comment.before']) : void 0,
|
3056 | after: options['comment.after'] ? template(options['comment.after']) : void 0
|
3057 | };
|
3058 | }
|
3059 |
|
3060 |
|
3061 |
|
3062 | function commentNodeBefore(node, state) {
|
3063 | if (shouldComment(node, state) && state.comment.before) {
|
3064 | output(node, state.comment.before, state);
|
3065 | }
|
3066 | }
|
3067 |
|
3068 |
|
3069 |
|
3070 | function commentNodeAfter(node, state) {
|
3071 | if (shouldComment(node, state) && state.comment.after) {
|
3072 | output(node, state.comment.after, state);
|
3073 | }
|
3074 | }
|
3075 |
|
3076 |
|
3077 |
|
3078 | function shouldComment(node, state) {
|
3079 | const { comment } = state;
|
3080 | if (!comment.enabled || !comment.trigger || !node.name || !node.attributes) {
|
3081 | return false;
|
3082 | }
|
3083 | for (const attr of node.attributes) {
|
3084 | if (attr.name && comment.trigger.includes(attr.name)) {
|
3085 | return true;
|
3086 | }
|
3087 | }
|
3088 | return false;
|
3089 | }
|
3090 |
|
3091 |
|
3092 |
|
3093 | function output(node, tokens, state) {
|
3094 | const attrs = {};
|
3095 | const { out } = state;
|
3096 |
|
3097 | for (const attr of node.attributes) {
|
3098 | if (attr.name && attr.value) {
|
3099 | attrs[attr.name.toUpperCase()] = attr.value;
|
3100 | }
|
3101 | }
|
3102 |
|
3103 | for (const token of tokens) {
|
3104 | if (typeof token === 'string') {
|
3105 | pushString(out, token);
|
3106 | }
|
3107 | else if (attrs[token.name]) {
|
3108 | pushString(out, token.before);
|
3109 | pushTokens(attrs[token.name], state);
|
3110 | pushString(out, token.after);
|
3111 | }
|
3112 | }
|
3113 | }
|
3114 |
|
3115 | const htmlTagRegex = /^<([\w\-:]+)[\s>]/;
|
3116 | const reservedKeywords = new Set([
|
3117 | 'for', 'while', 'of', 'async', 'await', 'const', 'let', 'var', 'continue',
|
3118 | 'break', 'debugger', 'do', 'export', 'import', 'in', 'instanceof', 'new', 'return',
|
3119 | 'switch', 'this', 'throw', 'try', 'catch', 'typeof', 'void', 'with', 'yield'
|
3120 | ]);
|
3121 | function html(abbr, config) {
|
3122 | const state = createWalkState(config);
|
3123 | state.comment = createCommentState(config);
|
3124 | walk(abbr, element$1, state);
|
3125 | return state.out.value;
|
3126 | }
|
3127 |
|
3128 |
|
3129 |
|
3130 |
|
3131 |
|
3132 |
|
3133 |
|
3134 | function element$1(node, index, items, state, next) {
|
3135 | const { out, config } = state;
|
3136 | const format = shouldFormat$1(node, index, items, state);
|
3137 |
|
3138 | const level = getIndent(state);
|
3139 | out.level += level;
|
3140 | format && pushNewline(out, true);
|
3141 | if (node.name) {
|
3142 | const name = tagName(node.name, config);
|
3143 | commentNodeBefore(node, state);
|
3144 | pushString(out, `<${name}`);
|
3145 | if (node.attributes) {
|
3146 | for (const attr of node.attributes) {
|
3147 | if (shouldOutputAttribute(attr)) {
|
3148 | pushAttribute(attr, state);
|
3149 | }
|
3150 | }
|
3151 | }
|
3152 | if (node.selfClosing && !node.children.length && !node.value) {
|
3153 | pushString(out, `${selfClose(config)}>`);
|
3154 | }
|
3155 | else {
|
3156 | pushString(out, '>');
|
3157 | if (!pushSnippet(node, state, next)) {
|
3158 | if (node.value) {
|
3159 | const innerFormat = node.value.some(hasNewline) || startsWithBlockTag(node.value, config);
|
3160 | innerFormat && pushNewline(state.out, ++out.level);
|
3161 | pushTokens(node.value, state);
|
3162 | innerFormat && pushNewline(state.out, --out.level);
|
3163 | }
|
3164 | node.children.forEach(next);
|
3165 | if (!node.value && !node.children.length) {
|
3166 | const innerFormat = config.options['output.formatLeafNode']
|
3167 | || config.options['output.formatForce'].includes(node.name);
|
3168 | innerFormat && pushNewline(state.out, ++out.level);
|
3169 | pushTokens(caret, state);
|
3170 | innerFormat && pushNewline(state.out, --out.level);
|
3171 | }
|
3172 | }
|
3173 | pushString(out, `</${name}>`);
|
3174 | commentNodeAfter(node, state);
|
3175 | }
|
3176 | }
|
3177 | else if (!pushSnippet(node, state, next) && node.value) {
|
3178 |
|
3179 | pushTokens(node.value, state);
|
3180 | node.children.forEach(next);
|
3181 | }
|
3182 | if (format && index === items.length - 1 && state.parent) {
|
3183 | const offset = isSnippet(state.parent) ? 0 : 1;
|
3184 | pushNewline(out, out.level - offset);
|
3185 | }
|
3186 | out.level -= level;
|
3187 | }
|
3188 |
|
3189 |
|
3190 |
|
3191 | function pushAttribute(attr, state) {
|
3192 | const { out, config } = state;
|
3193 | if (attr.name) {
|
3194 | const attributes = config.options['markup.attributes'];
|
3195 | const valuePrefix = config.options['markup.valuePrefix'];
|
3196 | let { name, value } = attr;
|
3197 | let lQuote = attrQuote(attr, config, true);
|
3198 | let rQuote = attrQuote(attr, config);
|
3199 | if (attributes) {
|
3200 | name = getMultiValue(name, attributes, attr.multiple) || name;
|
3201 | }
|
3202 | name = attrName(name, config);
|
3203 | if (config.options['jsx.enabled'] && attr.multiple) {
|
3204 | lQuote = expressionStart;
|
3205 | rQuote = expressionEnd;
|
3206 | }
|
3207 | const prefix = valuePrefix
|
3208 | ? getMultiValue(attr.name, valuePrefix, attr.multiple)
|
3209 | : null;
|
3210 | if (prefix && (value === null || value === void 0 ? void 0 : value.length) === 1 && typeof value[0] === 'string') {
|
3211 |
|
3212 | const val = value[0];
|
3213 | value = [isPropKey(val) ? `${prefix}.${val}` : `${prefix}['${val}']`];
|
3214 | if (config.options['jsx.enabled']) {
|
3215 | lQuote = expressionStart;
|
3216 | rQuote = expressionEnd;
|
3217 | }
|
3218 | }
|
3219 | if (isBooleanAttribute(attr, config) && !value) {
|
3220 |
|
3221 |
|
3222 |
|
3223 | if (!config.options['output.compactBoolean']) {
|
3224 | value = [name];
|
3225 | }
|
3226 | }
|
3227 | else if (!value) {
|
3228 | value = caret;
|
3229 | }
|
3230 | pushString(out, ' ' + name);
|
3231 | if (value) {
|
3232 | pushString(out, '=' + lQuote);
|
3233 | pushTokens(value, state);
|
3234 | pushString(out, rQuote);
|
3235 | }
|
3236 | else if (config.options['output.selfClosingStyle'] !== 'html') {
|
3237 | pushString(out, '=' + lQuote + rQuote);
|
3238 | }
|
3239 | }
|
3240 | }
|
3241 | function pushSnippet(node, state, next) {
|
3242 | if (node.value && node.children.length) {
|
3243 |
|
3244 |
|
3245 | const fieldIx = node.value.findIndex(isField);
|
3246 | if (fieldIx !== -1) {
|
3247 | pushTokens(node.value.slice(0, fieldIx), state);
|
3248 | const line = state.out.line;
|
3249 | let pos = fieldIx + 1;
|
3250 | node.children.forEach(next);
|
3251 |
|
3252 | if (state.out.line !== line && typeof node.value[pos] === 'string') {
|
3253 | pushString(state.out, node.value[pos++].trimLeft());
|
3254 | }
|
3255 | pushTokens(node.value.slice(pos), state);
|
3256 | return true;
|
3257 | }
|
3258 | }
|
3259 | return false;
|
3260 | }
|
3261 |
|
3262 |
|
3263 |
|
3264 | function shouldFormat$1(node, index, items, state) {
|
3265 | const { config, parent } = state;
|
3266 | if (!config.options['output.format']) {
|
3267 | return false;
|
3268 | }
|
3269 | if (index === 0 && !parent) {
|
3270 |
|
3271 | return false;
|
3272 | }
|
3273 |
|
3274 | if (parent && isSnippet(parent) && items.length === 1) {
|
3275 | return false;
|
3276 | }
|
3277 | |
3278 |
|
3279 |
|
3280 | if (isSnippet(node)) {
|
3281 |
|
3282 | const format = isSnippet(items[index - 1]) || isSnippet(items[index + 1])
|
3283 |
|
3284 | || node.value.some(hasNewline)
|
3285 |
|
3286 | || (node.value.some(isField) && node.children.length);
|
3287 | if (format) {
|
3288 | return true;
|
3289 | }
|
3290 | }
|
3291 | if (isInline(node, config)) {
|
3292 |
|
3293 | if (index === 0) {
|
3294 |
|
3295 | for (let i = 0; i < items.length; i++) {
|
3296 | if (!isInline(items[i], config)) {
|
3297 | return true;
|
3298 | }
|
3299 | }
|
3300 | }
|
3301 | else if (!isInline(items[index - 1], config)) {
|
3302 |
|
3303 | return true;
|
3304 | }
|
3305 | if (config.options['output.inlineBreak']) {
|
3306 |
|
3307 | let adjacentInline = 1;
|
3308 | let before = index;
|
3309 | let after = index;
|
3310 | while (isInlineElement(items[--before], config)) {
|
3311 | adjacentInline++;
|
3312 | }
|
3313 | while (isInlineElement(items[++after], config)) {
|
3314 | adjacentInline++;
|
3315 | }
|
3316 | if (adjacentInline >= config.options['output.inlineBreak']) {
|
3317 | return true;
|
3318 | }
|
3319 | }
|
3320 |
|
3321 | for (let i = 0, il = node.children.length; i < il; i++) {
|
3322 | if (shouldFormat$1(node.children[i], i, node.children, state)) {
|
3323 | return true;
|
3324 | }
|
3325 | }
|
3326 | return false;
|
3327 | }
|
3328 | return true;
|
3329 | }
|
3330 |
|
3331 |
|
3332 |
|
3333 | function getIndent(state) {
|
3334 | const { config, parent } = state;
|
3335 | if (!parent || isSnippet(parent) || (parent.name && config.options['output.formatSkip'].includes(parent.name))) {
|
3336 | return 0;
|
3337 | }
|
3338 | return 1;
|
3339 | }
|
3340 |
|
3341 |
|
3342 |
|
3343 | function hasNewline(value) {
|
3344 | return typeof value === 'string' && /\r|\n/.test(value);
|
3345 | }
|
3346 |
|
3347 |
|
3348 |
|
3349 | function startsWithBlockTag(value, config) {
|
3350 | if (value.length && typeof value[0] === 'string') {
|
3351 | const matches = htmlTagRegex.exec(value[0]);
|
3352 | if ((matches === null || matches === void 0 ? void 0 : matches.length) && !config.options['inlineElements'].includes(matches[1].toLowerCase())) {
|
3353 | return true;
|
3354 | }
|
3355 | }
|
3356 | return false;
|
3357 | }
|
3358 | function getMultiValue(key, data, multiple) {
|
3359 | return (multiple && data[`${key}*`]) || data[key];
|
3360 | }
|
3361 | function isPropKey(name) {
|
3362 | return !reservedKeywords.has(name) && /^[a-zA-Z_$][\w_$]*$/.test(name);
|
3363 | }
|
3364 |
|
3365 | function indentFormat(abbr, config, options) {
|
3366 | const state = createWalkState(config);
|
3367 | state.options = options || {};
|
3368 | walk(abbr, element, state);
|
3369 | return state.out.value;
|
3370 | }
|
3371 |
|
3372 |
|
3373 |
|
3374 |
|
3375 |
|
3376 |
|
3377 |
|
3378 | function element(node, index, items, state, next) {
|
3379 | const { out, options } = state;
|
3380 | const { primary, secondary } = collectAttributes(node);
|
3381 |
|
3382 | const level = state.parent ? 1 : 0;
|
3383 | out.level += level;
|
3384 |
|
3385 | if (shouldFormat(node, index, items, state)) {
|
3386 | pushNewline(out, true);
|
3387 | }
|
3388 | if (node.name && (node.name !== 'div' || !primary.length)) {
|
3389 | pushString(out, (options.beforeName || '') + node.name + (options.afterName || ''));
|
3390 | }
|
3391 | pushPrimaryAttributes(primary, state);
|
3392 | pushSecondaryAttributes(secondary.filter(shouldOutputAttribute), state);
|
3393 | if (node.selfClosing && !node.value && !node.children.length) {
|
3394 | if (state.options.selfClose) {
|
3395 | pushString(out, state.options.selfClose);
|
3396 | }
|
3397 | }
|
3398 | else {
|
3399 | pushValue(node, state);
|
3400 | node.children.forEach(next);
|
3401 | }
|
3402 | out.level -= level;
|
3403 | }
|
3404 |
|
3405 |
|
3406 |
|
3407 |
|
3408 |
|
3409 | function collectAttributes(node) {
|
3410 | const primary = [];
|
3411 | const secondary = [];
|
3412 | if (node.attributes) {
|
3413 | for (const attr of node.attributes) {
|
3414 | if (isPrimaryAttribute(attr)) {
|
3415 | primary.push(attr);
|
3416 | }
|
3417 | else {
|
3418 | secondary.push(attr);
|
3419 | }
|
3420 | }
|
3421 | }
|
3422 | return { primary, secondary };
|
3423 | }
|
3424 |
|
3425 |
|
3426 |
|
3427 | function pushPrimaryAttributes(attrs, state) {
|
3428 | for (const attr of attrs) {
|
3429 | if (attr.value) {
|
3430 | if (attr.name === 'class') {
|
3431 | pushString(state.out, '.');
|
3432 |
|
3433 | const tokens = attr.value.map(t => typeof t === 'string' ? t.replace(/\s+/g, '.') : t);
|
3434 | pushTokens(tokens, state);
|
3435 | }
|
3436 | else {
|
3437 |
|
3438 | pushString(state.out, '#');
|
3439 | pushTokens(attr.value, state);
|
3440 | }
|
3441 | }
|
3442 | }
|
3443 | }
|
3444 |
|
3445 |
|
3446 |
|
3447 | function pushSecondaryAttributes(attrs, state) {
|
3448 | if (attrs.length) {
|
3449 | const { out, config, options } = state;
|
3450 | options.beforeAttribute && pushString(out, options.beforeAttribute);
|
3451 | for (let i = 0; i < attrs.length; i++) {
|
3452 | const attr = attrs[i];
|
3453 | pushString(out, attrName(attr.name || '', config));
|
3454 | if (isBooleanAttribute(attr, config) && !attr.value) {
|
3455 | if (!config.options['output.compactBoolean'] && options.booleanValue) {
|
3456 | pushString(out, '=' + options.booleanValue);
|
3457 | }
|
3458 | }
|
3459 | else {
|
3460 | pushString(out, '=' + attrQuote(attr, config, true));
|
3461 | pushTokens(attr.value || caret, state);
|
3462 | pushString(out, attrQuote(attr, config));
|
3463 | }
|
3464 | if (i !== attrs.length - 1 && options.glueAttribute) {
|
3465 | pushString(out, options.glueAttribute);
|
3466 | }
|
3467 | }
|
3468 | options.afterAttribute && pushString(out, options.afterAttribute);
|
3469 | }
|
3470 | }
|
3471 |
|
3472 |
|
3473 |
|
3474 | function pushValue(node, state) {
|
3475 |
|
3476 | if (!node.value && node.children.length) {
|
3477 | return;
|
3478 | }
|
3479 | const value = node.value || caret;
|
3480 | const lines = splitByLines(value);
|
3481 | const { out, options } = state;
|
3482 | if (lines.length === 1) {
|
3483 | if (node.name || node.attributes) {
|
3484 | push(out, ' ');
|
3485 | }
|
3486 | pushTokens(value, state);
|
3487 | }
|
3488 | else {
|
3489 |
|
3490 |
|
3491 | const lineLengths = [];
|
3492 | let maxLength = 0;
|
3493 |
|
3494 | for (const line of lines) {
|
3495 | const len = valueLength(line);
|
3496 | lineLengths.push(len);
|
3497 | if (len > maxLength) {
|
3498 | maxLength = len;
|
3499 | }
|
3500 | }
|
3501 |
|
3502 | out.level++;
|
3503 | for (let i = 0; i < lines.length; i++) {
|
3504 | pushNewline(out, true);
|
3505 | options.beforeTextLine && push(out, options.beforeTextLine);
|
3506 | pushTokens(lines[i], state);
|
3507 | if (options.afterTextLine) {
|
3508 | push(out, ' '.repeat(maxLength - lineLengths[i]));
|
3509 | push(out, options.afterTextLine);
|
3510 | }
|
3511 | }
|
3512 | out.level--;
|
3513 | }
|
3514 | }
|
3515 | function isPrimaryAttribute(attr) {
|
3516 | return attr.name === 'class' || attr.name === 'id';
|
3517 | }
|
3518 |
|
3519 |
|
3520 |
|
3521 | function valueLength(tokens) {
|
3522 | let len = 0;
|
3523 | for (const token of tokens) {
|
3524 | len += typeof token === 'string' ? token.length : token.name.length;
|
3525 | }
|
3526 | return len;
|
3527 | }
|
3528 | function shouldFormat(node, index, items, state) {
|
3529 |
|
3530 | if (!state.parent && index === 0) {
|
3531 | return false;
|
3532 | }
|
3533 | return !isSnippet(node);
|
3534 | }
|
3535 |
|
3536 | function haml(abbr, config) {
|
3537 | return indentFormat(abbr, config, {
|
3538 | beforeName: '%',
|
3539 | beforeAttribute: '(',
|
3540 | afterAttribute: ')',
|
3541 | glueAttribute: ' ',
|
3542 | afterTextLine: ' |',
|
3543 | booleanValue: 'true',
|
3544 | selfClose: '/'
|
3545 | });
|
3546 | }
|
3547 |
|
3548 | function slim(abbr, config) {
|
3549 | return indentFormat(abbr, config, {
|
3550 | beforeAttribute: ' ',
|
3551 | glueAttribute: ' ',
|
3552 | beforeTextLine: '| ',
|
3553 | selfClose: '/'
|
3554 | });
|
3555 | }
|
3556 |
|
3557 | function pug(abbr, config) {
|
3558 | return indentFormat(abbr, config, {
|
3559 | beforeAttribute: '(',
|
3560 | afterAttribute: ')',
|
3561 | glueAttribute: ', ',
|
3562 | beforeTextLine: '| ',
|
3563 | selfClose: config.options['output.selfClosingStyle'] === 'xml' ? '/' : ''
|
3564 | });
|
3565 | }
|
3566 |
|
3567 | const formatters = { html, haml, slim, pug };
|
3568 |
|
3569 |
|
3570 |
|
3571 |
|
3572 | function parse$1(abbr, config) {
|
3573 | let oldTextValue;
|
3574 | if (typeof abbr === 'string') {
|
3575 | const parseOpt = Object.assign({}, config);
|
3576 | if (config.options['jsx.enabled']) {
|
3577 | parseOpt.jsx = true;
|
3578 | }
|
3579 | if (config.options['markup.href']) {
|
3580 | parseOpt.href = true;
|
3581 | }
|
3582 | abbr = parseAbbreviation(abbr, parseOpt);
|
3583 |
|
3584 |
|
3585 | oldTextValue = config.text;
|
3586 | config.text = undefined;
|
3587 | }
|
3588 |
|
3589 |
|
3590 |
|
3591 |
|
3592 | abbr = resolveSnippets(abbr, config);
|
3593 | walk$1(abbr, transform, config);
|
3594 | config.text = oldTextValue !== null && oldTextValue !== void 0 ? oldTextValue : config.text;
|
3595 | return abbr;
|
3596 | }
|
3597 |
|
3598 |
|
3599 |
|
3600 | function stringify(abbr, config) {
|
3601 | const formatter = formatters[config.syntax] || html;
|
3602 | return formatter(abbr, config);
|
3603 | }
|
3604 |
|
3605 |
|
3606 |
|
3607 | function transform(node, ancestors, config) {
|
3608 | implicitTag(node, ancestors, config);
|
3609 | mergeAttributes(node, config);
|
3610 | lorem(node, ancestors, config);
|
3611 | if (config.syntax === 'xsl') {
|
3612 | xsl(node);
|
3613 | }
|
3614 | if (config.type === 'markup') {
|
3615 | label(node);
|
3616 | }
|
3617 | if (config.options['bem.enabled']) {
|
3618 | bem(node, ancestors, config);
|
3619 | }
|
3620 | }
|
3621 |
|
3622 | var CSSSnippetType;
|
3623 | (function (CSSSnippetType) {
|
3624 | CSSSnippetType["Raw"] = "Raw";
|
3625 | CSSSnippetType["Property"] = "Property";
|
3626 | })(CSSSnippetType || (CSSSnippetType = {}));
|
3627 | const reProperty = /^([a-z-]+)(?:\s*:\s*([^\n\r;]+?);*)?$/;
|
3628 | const opt = { value: true };
|
3629 |
|
3630 |
|
3631 |
|
3632 | function createSnippet(key, value) {
|
3633 |
|
3634 |
|
3635 |
|
3636 | const m = value.match(reProperty);
|
3637 | if (m) {
|
3638 | const keywords = {};
|
3639 | const parsed = m[2] ? m[2].split('|').map(parseValue) : [];
|
3640 | for (const item of parsed) {
|
3641 | for (const cssVal of item) {
|
3642 | collectKeywords(cssVal, keywords);
|
3643 | }
|
3644 | }
|
3645 | return {
|
3646 | type: CSSSnippetType.Property,
|
3647 | key,
|
3648 | property: m[1],
|
3649 | value: parsed,
|
3650 | keywords,
|
3651 | dependencies: []
|
3652 | };
|
3653 | }
|
3654 | return { type: CSSSnippetType.Raw, key, value };
|
3655 | }
|
3656 |
|
3657 |
|
3658 |
|
3659 |
|
3660 | function nest(snippets) {
|
3661 | snippets = snippets.slice().sort(snippetsSort);
|
3662 | const stack = [];
|
3663 | let prev;
|
3664 |
|
3665 |
|
3666 |
|
3667 | for (const cur of snippets.filter(isProperty)) {
|
3668 |
|
3669 |
|
3670 |
|
3671 | while (stack.length) {
|
3672 | prev = stack[stack.length - 1];
|
3673 | if (cur.property.startsWith(prev.property)
|
3674 | && cur.property.charCodeAt(prev.property.length) === 45 ) {
|
3675 | prev.dependencies.push(cur);
|
3676 | stack.push(cur);
|
3677 | break;
|
3678 | }
|
3679 | stack.pop();
|
3680 | }
|
3681 | if (!stack.length) {
|
3682 | stack.push(cur);
|
3683 | }
|
3684 | }
|
3685 | return snippets;
|
3686 | }
|
3687 |
|
3688 |
|
3689 |
|
3690 | function snippetsSort(a, b) {
|
3691 | if (a.key === b.key) {
|
3692 | return 0;
|
3693 | }
|
3694 | return a.key < b.key ? -1 : 1;
|
3695 | }
|
3696 | function parseValue(value) {
|
3697 | return parse$2(value.trim(), opt)[0].value;
|
3698 | }
|
3699 | function isProperty(snippet) {
|
3700 | return snippet.type === CSSSnippetType.Property;
|
3701 | }
|
3702 | function collectKeywords(cssVal, dest) {
|
3703 | for (const v of cssVal.value) {
|
3704 | if (v.type === 'Literal') {
|
3705 | dest[v.value] = v;
|
3706 | }
|
3707 | else if (v.type === 'FunctionCall') {
|
3708 | dest[v.name] = v;
|
3709 | }
|
3710 | else if (v.type === 'Field') {
|
3711 |
|
3712 | const value = v.name.trim();
|
3713 | if (value) {
|
3714 | dest[value] = { type: 'Literal', value };
|
3715 | }
|
3716 | }
|
3717 | }
|
3718 | }
|
3719 |
|
3720 |
|
3721 |
|
3722 |
|
3723 |
|
3724 |
|
3725 |
|
3726 |
|
3727 |
|
3728 |
|
3729 |
|
3730 | function scoreMatch(str1, str2, partialMatch = false) {
|
3731 | str1 = str1.toLowerCase();
|
3732 | str2 = str2.toLowerCase();
|
3733 | if (str1 === str2) {
|
3734 | return 1;
|
3735 | }
|
3736 |
|
3737 | if (!str1 || !str2 || str1.charCodeAt(0) !== str2.charCodeAt(0)) {
|
3738 | return 0;
|
3739 | }
|
3740 | const str1Len = str1.length;
|
3741 | const str2Len = str2.length;
|
3742 | if (!partialMatch && str1Len > str2Len) {
|
3743 | return 0;
|
3744 | }
|
3745 |
|
3746 |
|
3747 |
|
3748 |
|
3749 |
|
3750 |
|
3751 |
|
3752 |
|
3753 |
|
3754 | const minLength = Math.min(str1Len, str2Len);
|
3755 | const maxLength = Math.max(str1Len, str2Len);
|
3756 | let i = 1;
|
3757 | let j = 1;
|
3758 | let score = maxLength;
|
3759 | let ch1 = 0;
|
3760 | let ch2 = 0;
|
3761 | let found = false;
|
3762 | let acronym = false;
|
3763 | while (i < str1Len) {
|
3764 | ch1 = str1.charCodeAt(i);
|
3765 | found = false;
|
3766 | acronym = false;
|
3767 | while (j < str2Len) {
|
3768 | ch2 = str2.charCodeAt(j);
|
3769 | if (ch1 === ch2) {
|
3770 | found = true;
|
3771 | score += maxLength - (acronym ? i : j);
|
3772 | break;
|
3773 | }
|
3774 |
|
3775 | acronym = ch2 === 45 ;
|
3776 | j++;
|
3777 | }
|
3778 | if (!found) {
|
3779 | if (!partialMatch) {
|
3780 | return 0;
|
3781 | }
|
3782 | break;
|
3783 | }
|
3784 | i++;
|
3785 | }
|
3786 | const matchRatio = i / maxLength;
|
3787 | const delta = maxLength - minLength;
|
3788 | const maxScore = sum(maxLength) - sum(delta);
|
3789 | return (score * matchRatio) / maxScore;
|
3790 | }
|
3791 |
|
3792 |
|
3793 |
|
3794 | function sum(n) {
|
3795 | return n * (n + 1) / 2;
|
3796 | }
|
3797 |
|
3798 | function color(token, shortHex) {
|
3799 | if (!token.r && !token.g && !token.b && !token.a) {
|
3800 | return 'transparent';
|
3801 | }
|
3802 | else if (token.a === 1) {
|
3803 | return asHex(token, shortHex);
|
3804 | }
|
3805 | return asRGB(token);
|
3806 | }
|
3807 |
|
3808 |
|
3809 |
|
3810 |
|
3811 | function asHex(token, short) {
|
3812 | const fn = (short && isShortHex(token.r) && isShortHex(token.g) && isShortHex(token.b))
|
3813 | ? toShortHex : toHex;
|
3814 | return '#' + fn(token.r) + fn(token.g) + fn(token.b);
|
3815 | }
|
3816 |
|
3817 |
|
3818 |
|
3819 | function asRGB(token) {
|
3820 | const values = [token.r, token.g, token.b];
|
3821 | if (token.a !== 1) {
|
3822 | values.push(frac(token.a, 8));
|
3823 | }
|
3824 | return `${values.length === 3 ? 'rgb' : 'rgba'}(${values.join(', ')})`;
|
3825 | }
|
3826 | function frac(num, digits = 4) {
|
3827 | return num.toFixed(digits).replace(/\.?0+$/, '');
|
3828 | }
|
3829 | function isShortHex(hex) {
|
3830 | return !(hex % 17);
|
3831 | }
|
3832 | function toShortHex(num) {
|
3833 | return (num >> 4).toString(16);
|
3834 | }
|
3835 | function toHex(num) {
|
3836 | return pad(num.toString(16), 2);
|
3837 | }
|
3838 | function pad(value, len) {
|
3839 | while (value.length < len) {
|
3840 | value = '0' + value;
|
3841 | }
|
3842 | return value;
|
3843 | }
|
3844 |
|
3845 | const CSSAbbreviationScope = {
|
3846 |
|
3847 | Global: '@@global',
|
3848 |
|
3849 | Section: '@@section',
|
3850 |
|
3851 | Property: '@@property',
|
3852 |
|
3853 | Value: '@@value',
|
3854 | };
|
3855 | function css(abbr, config) {
|
3856 | var _a;
|
3857 | const out = createOutputStream(config.options);
|
3858 | const format = config.options['output.format'];
|
3859 | if (((_a = config.context) === null || _a === void 0 ? void 0 : _a.name) === CSSAbbreviationScope.Section) {
|
3860 |
|
3861 | abbr = abbr.filter(node => node.snippet);
|
3862 | }
|
3863 | for (let i = 0; i < abbr.length; i++) {
|
3864 | if (format && i !== 0) {
|
3865 | pushNewline(out, true);
|
3866 | }
|
3867 | property(abbr[i], out, config);
|
3868 | }
|
3869 | return out.value;
|
3870 | }
|
3871 |
|
3872 |
|
3873 |
|
3874 | function property(node, out, config) {
|
3875 | const isJSON = config.options['stylesheet.json'];
|
3876 | if (node.name) {
|
3877 |
|
3878 | const name = isJSON ? toCamelCase(node.name) : node.name;
|
3879 | pushString(out, name + config.options['stylesheet.between']);
|
3880 | if (node.value.length) {
|
3881 | propertyValue(node, out, config);
|
3882 | }
|
3883 | else {
|
3884 | pushField(out, 0, '');
|
3885 | }
|
3886 | if (isJSON) {
|
3887 |
|
3888 |
|
3889 | push(out, ',');
|
3890 | }
|
3891 | else {
|
3892 | outputImportant(node, out, true);
|
3893 | push(out, config.options['stylesheet.after']);
|
3894 | }
|
3895 | }
|
3896 | else {
|
3897 |
|
3898 | for (const cssVal of node.value) {
|
3899 | for (const v of cssVal.value) {
|
3900 | outputToken(v, out, config);
|
3901 | }
|
3902 | }
|
3903 | outputImportant(node, out, node.value.length > 0);
|
3904 | }
|
3905 | }
|
3906 | function propertyValue(node, out, config) {
|
3907 | const isJSON = config.options['stylesheet.json'];
|
3908 | const num = isJSON ? getSingleNumeric(node) : null;
|
3909 | if (num && (!num.unit || num.unit === 'px')) {
|
3910 |
|
3911 |
|
3912 | push(out, String(num.value));
|
3913 | }
|
3914 | else {
|
3915 | const quote = getQuote(config);
|
3916 | isJSON && push(out, quote);
|
3917 | for (let i = 0; i < node.value.length; i++) {
|
3918 | if (i !== 0) {
|
3919 | push(out, ', ');
|
3920 | }
|
3921 | outputValue(node.value[i], out, config);
|
3922 | }
|
3923 | isJSON && push(out, quote);
|
3924 | }
|
3925 | }
|
3926 | function outputImportant(node, out, separator) {
|
3927 | if (node.important) {
|
3928 | if (separator) {
|
3929 | push(out, ' ');
|
3930 | }
|
3931 | push(out, '!important');
|
3932 | }
|
3933 | }
|
3934 | function outputValue(value, out, config) {
|
3935 | for (let i = 0, prevEnd = -1; i < value.value.length; i++) {
|
3936 | const token = value.value[i];
|
3937 |
|
3938 |
|
3939 | if (i !== 0 && (token.type !== 'Field' || token.start !== prevEnd)) {
|
3940 | push(out, ' ');
|
3941 | }
|
3942 | outputToken(token, out, config);
|
3943 | prevEnd = token['end'];
|
3944 | }
|
3945 | }
|
3946 | function outputToken(token, out, config) {
|
3947 | if (token.type === 'ColorValue') {
|
3948 | push(out, color(token, config.options['stylesheet.shortHex']));
|
3949 | }
|
3950 | else if (token.type === 'Literal' || token.type === 'CustomProperty') {
|
3951 | pushString(out, token.value);
|
3952 | }
|
3953 | else if (token.type === 'NumberValue') {
|
3954 | pushString(out, frac(token.value, 4) + token.unit);
|
3955 | }
|
3956 | else if (token.type === 'StringValue') {
|
3957 | const quote = token.quote === 'double' ? '"' : '\'';
|
3958 | pushString(out, quote + token.value + quote);
|
3959 | }
|
3960 | else if (token.type === 'Field') {
|
3961 | pushField(out, token.index, token.name);
|
3962 | }
|
3963 | else if (token.type === 'FunctionCall') {
|
3964 | push(out, token.name + '(');
|
3965 | for (let i = 0; i < token.arguments.length; i++) {
|
3966 | if (i) {
|
3967 | push(out, ', ');
|
3968 | }
|
3969 | outputValue(token.arguments[i], out, config);
|
3970 | }
|
3971 | push(out, ')');
|
3972 | }
|
3973 | }
|
3974 |
|
3975 |
|
3976 |
|
3977 | function getSingleNumeric(node) {
|
3978 | if (node.value.length === 1) {
|
3979 | const cssVal = node.value[0];
|
3980 | if (cssVal.value.length === 1 && cssVal.value[0].type === 'NumberValue') {
|
3981 | return cssVal.value[0];
|
3982 | }
|
3983 | }
|
3984 | }
|
3985 |
|
3986 |
|
3987 |
|
3988 | function toCamelCase(str) {
|
3989 | return str.replace(/\-(\w)/g, (_, letter) => letter.toUpperCase());
|
3990 | }
|
3991 | function getQuote(config) {
|
3992 | return config.options['stylesheet.jsonDoubleQuotes'] ? '"' : '\'';
|
3993 | }
|
3994 |
|
3995 | const gradientName = 'lg';
|
3996 |
|
3997 |
|
3998 |
|
3999 |
|
4000 | function parse(abbr, config) {
|
4001 | var _a;
|
4002 | const snippets = ((_a = config.cache) === null || _a === void 0 ? void 0 : _a.stylesheetSnippets) || convertSnippets(config.snippets);
|
4003 | if (config.cache) {
|
4004 | config.cache.stylesheetSnippets = snippets;
|
4005 | }
|
4006 | if (typeof abbr === 'string') {
|
4007 | abbr = parse$2(abbr, { value: isValueScope(config) });
|
4008 | }
|
4009 | const filteredSnippets = getSnippetsForScope(snippets, config);
|
4010 | for (const node of abbr) {
|
4011 | resolveNode(node, filteredSnippets, config);
|
4012 | }
|
4013 | return abbr;
|
4014 | }
|
4015 |
|
4016 |
|
4017 |
|
4018 | function convertSnippets(snippets) {
|
4019 | const result = [];
|
4020 | for (const key of Object.keys(snippets)) {
|
4021 | result.push(createSnippet(key, snippets[key]));
|
4022 | }
|
4023 | return nest(result);
|
4024 | }
|
4025 |
|
4026 |
|
4027 |
|
4028 |
|
4029 | function resolveNode(node, snippets, config) {
|
4030 | if (!resolveGradient(node, config)) {
|
4031 | const score = config.options['stylesheet.fuzzySearchMinScore'];
|
4032 | if (isValueScope(config)) {
|
4033 |
|
4034 | const propName = config.context.name;
|
4035 | const snippet = snippets.find(s => s.type === CSSSnippetType.Property && s.property === propName);
|
4036 | resolveValueKeywords(node, config, snippet, score);
|
4037 | node.snippet = snippet;
|
4038 | }
|
4039 | else if (node.name) {
|
4040 | const snippet = findBestMatch(node.name, snippets, score, true);
|
4041 | node.snippet = snippet;
|
4042 | if (snippet) {
|
4043 | if (snippet.type === CSSSnippetType.Property) {
|
4044 | resolveAsProperty(node, snippet, config);
|
4045 | }
|
4046 | else {
|
4047 | resolveAsSnippet(node, snippet);
|
4048 | }
|
4049 | }
|
4050 | }
|
4051 | }
|
4052 | if (node.name || config.context) {
|
4053 |
|
4054 | resolveNumericValue(node, config);
|
4055 | }
|
4056 | return node;
|
4057 | }
|
4058 |
|
4059 |
|
4060 |
|
4061 | function resolveGradient(node, config) {
|
4062 | let gradientFn = null;
|
4063 | const cssVal = node.value.length === 1 ? node.value[0] : null;
|
4064 | if (cssVal && cssVal.value.length === 1) {
|
4065 | const v = cssVal.value[0];
|
4066 | if (v.type === 'FunctionCall' && v.name === gradientName) {
|
4067 | gradientFn = v;
|
4068 | }
|
4069 | }
|
4070 | if (gradientFn || node.name === gradientName) {
|
4071 | if (!gradientFn) {
|
4072 | gradientFn = {
|
4073 | type: 'FunctionCall',
|
4074 | name: 'linear-gradient',
|
4075 | arguments: [cssValue(field(0, ''))]
|
4076 | };
|
4077 | }
|
4078 | else {
|
4079 | gradientFn = Object.assign(Object.assign({}, gradientFn), { name: 'linear-gradient' });
|
4080 | }
|
4081 | if (!config.context) {
|
4082 | node.name = 'background-image';
|
4083 | }
|
4084 | node.value = [cssValue(gradientFn)];
|
4085 | return true;
|
4086 | }
|
4087 | return false;
|
4088 | }
|
4089 |
|
4090 |
|
4091 |
|
4092 | function resolveAsProperty(node, snippet, config) {
|
4093 | const abbr = node.name;
|
4094 |
|
4095 |
|
4096 |
|
4097 |
|
4098 |
|
4099 |
|
4100 | const inlineValue = getUnmatchedPart(abbr, snippet.key);
|
4101 | if (inlineValue) {
|
4102 | if (node.value.length) {
|
4103 |
|
4104 | return node;
|
4105 | }
|
4106 | const kw = resolveKeyword(inlineValue, config, snippet);
|
4107 | if (!kw) {
|
4108 | return node;
|
4109 | }
|
4110 | node.value.push(cssValue(kw));
|
4111 | }
|
4112 | node.name = snippet.property;
|
4113 | if (node.value.length) {
|
4114 |
|
4115 | resolveValueKeywords(node, config, snippet);
|
4116 | }
|
4117 | else if (snippet.value.length) {
|
4118 | const defaultValue = snippet.value[0];
|
4119 |
|
4120 |
|
4121 |
|
4122 | node.value = snippet.value.length === 1 || defaultValue.some(hasField)
|
4123 | ? defaultValue
|
4124 | : defaultValue.map(n => wrapWithField(n, config));
|
4125 | }
|
4126 | return node;
|
4127 | }
|
4128 | function resolveValueKeywords(node, config, snippet, minScore) {
|
4129 | for (const cssVal of node.value) {
|
4130 | const value = [];
|
4131 | for (const token of cssVal.value) {
|
4132 | if (token.type === 'Literal') {
|
4133 | value.push(resolveKeyword(token.value, config, snippet, minScore) || token);
|
4134 | }
|
4135 | else if (token.type === 'FunctionCall') {
|
4136 |
|
4137 |
|
4138 | const match = resolveKeyword(token.name, config, snippet, minScore);
|
4139 | if (match && match.type === 'FunctionCall') {
|
4140 | value.push(Object.assign(Object.assign({}, match), { arguments: token.arguments.concat(match.arguments.slice(token.arguments.length)) }));
|
4141 | }
|
4142 | else {
|
4143 | value.push(token);
|
4144 | }
|
4145 | }
|
4146 | else {
|
4147 | value.push(token);
|
4148 | }
|
4149 | }
|
4150 | cssVal.value = value;
|
4151 | }
|
4152 | }
|
4153 |
|
4154 |
|
4155 |
|
4156 | function resolveAsSnippet(node, snippet) {
|
4157 |
|
4158 |
|
4159 |
|
4160 | let offset = 0;
|
4161 | let m;
|
4162 | const reField = /\$\{(\d+)(:[^}]+)?\}/g;
|
4163 | const inputValue = node.value[0];
|
4164 | const outputValue = [];
|
4165 | while (m = reField.exec(snippet.value)) {
|
4166 | if (offset !== m.index) {
|
4167 | outputValue.push(literal(snippet.value.slice(offset, m.index)));
|
4168 | }
|
4169 | offset = m.index + m[0].length;
|
4170 | if (inputValue && inputValue.value.length) {
|
4171 | outputValue.push(inputValue.value.shift());
|
4172 | }
|
4173 | else {
|
4174 | outputValue.push(field(Number(m[1]), m[2] ? m[2].slice(1) : ''));
|
4175 | }
|
4176 | }
|
4177 | const tail = snippet.value.slice(offset);
|
4178 | if (tail) {
|
4179 | outputValue.push(literal(tail));
|
4180 | }
|
4181 | node.name = void 0;
|
4182 | node.value = [cssValue(...outputValue)];
|
4183 | return node;
|
4184 | }
|
4185 |
|
4186 |
|
4187 |
|
4188 |
|
4189 |
|
4190 |
|
4191 | function findBestMatch(abbr, items, minScore = 0, partialMatch = false) {
|
4192 | let matchedItem = null;
|
4193 | let maxScore = 0;
|
4194 | for (const item of items) {
|
4195 | const score = scoreMatch(abbr, getScoringPart(item), partialMatch);
|
4196 | if (score === 1) {
|
4197 |
|
4198 | return item;
|
4199 | }
|
4200 | if (score && score >= maxScore) {
|
4201 | maxScore = score;
|
4202 | matchedItem = item;
|
4203 | }
|
4204 | }
|
4205 | return maxScore >= minScore ? matchedItem : null;
|
4206 | }
|
4207 | function getScoringPart(item) {
|
4208 | return typeof item === 'string' ? item : item.key;
|
4209 | }
|
4210 |
|
4211 |
|
4212 |
|
4213 |
|
4214 |
|
4215 | function getUnmatchedPart(abbr, str) {
|
4216 | for (let i = 0, lastPos = 0; i < abbr.length; i++) {
|
4217 | lastPos = str.indexOf(abbr[i], lastPos);
|
4218 | if (lastPos === -1) {
|
4219 | return abbr.slice(i);
|
4220 | }
|
4221 | lastPos++;
|
4222 | }
|
4223 | return '';
|
4224 | }
|
4225 |
|
4226 |
|
4227 |
|
4228 |
|
4229 | function resolveKeyword(kw, config, snippet, minScore) {
|
4230 | let ref;
|
4231 | if (snippet) {
|
4232 | if (ref = findBestMatch(kw, Object.keys(snippet.keywords), minScore)) {
|
4233 | return snippet.keywords[ref];
|
4234 | }
|
4235 | for (const dep of snippet.dependencies) {
|
4236 | if (ref = findBestMatch(kw, Object.keys(dep.keywords), minScore)) {
|
4237 | return dep.keywords[ref];
|
4238 | }
|
4239 | }
|
4240 | }
|
4241 | if (ref = findBestMatch(kw, config.options['stylesheet.keywords'], minScore)) {
|
4242 | return literal(ref);
|
4243 | }
|
4244 | return null;
|
4245 | }
|
4246 |
|
4247 |
|
4248 |
|
4249 | function resolveNumericValue(node, config) {
|
4250 | const aliases = config.options['stylesheet.unitAliases'];
|
4251 | const unitless = config.options['stylesheet.unitless'];
|
4252 | for (const v of node.value) {
|
4253 | for (const t of v.value) {
|
4254 | if (t.type === 'NumberValue') {
|
4255 | if (t.unit) {
|
4256 | t.unit = aliases[t.unit] || t.unit;
|
4257 | }
|
4258 | else if (t.value !== 0 && !unitless.includes(node.name)) {
|
4259 | t.unit = t.rawValue.includes('.')
|
4260 | ? config.options['stylesheet.floatUnit']
|
4261 | : config.options['stylesheet.intUnit'];
|
4262 | }
|
4263 | }
|
4264 | }
|
4265 | }
|
4266 | }
|
4267 |
|
4268 |
|
4269 |
|
4270 | function cssValue(...args) {
|
4271 | return {
|
4272 | type: 'CSSValue',
|
4273 | value: args
|
4274 | };
|
4275 | }
|
4276 |
|
4277 |
|
4278 |
|
4279 | function literal(value) {
|
4280 | return { type: 'Literal', value };
|
4281 | }
|
4282 |
|
4283 |
|
4284 |
|
4285 | function field(index, name) {
|
4286 | return { type: 'Field', index, name };
|
4287 | }
|
4288 |
|
4289 |
|
4290 |
|
4291 | function hasField(value) {
|
4292 | for (const v of value.value) {
|
4293 | if (v.type === 'Field' || (v.type === 'FunctionCall' && v.arguments.some(hasField))) {
|
4294 | return true;
|
4295 | }
|
4296 | }
|
4297 | return false;
|
4298 | }
|
4299 |
|
4300 |
|
4301 |
|
4302 | function wrapWithField(node, config, state = { index: 1 }) {
|
4303 | let value = [];
|
4304 | for (const v of node.value) {
|
4305 | switch (v.type) {
|
4306 | case 'ColorValue':
|
4307 | value.push(field(state.index++, color(v, config.options['stylesheet.shortHex'])));
|
4308 | break;
|
4309 | case 'Literal':
|
4310 | value.push(field(state.index++, v.value));
|
4311 | break;
|
4312 | case 'NumberValue':
|
4313 | value.push(field(state.index++, `${v.value}${v.unit}`));
|
4314 | break;
|
4315 | case 'StringValue':
|
4316 | const q = v.quote === 'single' ? '\'' : '"';
|
4317 | value.push(field(state.index++, q + v.value + q));
|
4318 | break;
|
4319 | case 'FunctionCall':
|
4320 | value.push(field(state.index++, v.name), literal('('));
|
4321 | for (let i = 0, il = v.arguments.length; i < il; i++) {
|
4322 | value = value.concat(wrapWithField(v.arguments[i], config, state).value);
|
4323 | if (i !== il - 1) {
|
4324 | value.push(literal(', '));
|
4325 | }
|
4326 | }
|
4327 | value.push(literal(')'));
|
4328 | break;
|
4329 | default:
|
4330 | value.push(v);
|
4331 | }
|
4332 | }
|
4333 | return Object.assign(Object.assign({}, node), { value });
|
4334 | }
|
4335 |
|
4336 |
|
4337 |
|
4338 | function isValueScope(config) {
|
4339 | if (config.context) {
|
4340 | return config.context.name === CSSAbbreviationScope.Value || !config.context.name.startsWith('@@');
|
4341 | }
|
4342 | return false;
|
4343 | }
|
4344 |
|
4345 |
|
4346 |
|
4347 | function getSnippetsForScope(snippets, config) {
|
4348 | if (config.context) {
|
4349 | if (config.context.name === CSSAbbreviationScope.Section) {
|
4350 | return snippets.filter(s => s.type === CSSSnippetType.Raw);
|
4351 | }
|
4352 | if (config.context.name === CSSAbbreviationScope.Property) {
|
4353 | return snippets.filter(s => s.type === CSSSnippetType.Property);
|
4354 | }
|
4355 | }
|
4356 | return snippets;
|
4357 | }
|
4358 |
|
4359 | var markupSnippets = {
|
4360 | "a": "a[href]",
|
4361 | "a:blank": "a[href='http://${0}' target='_blank' rel='noopener noreferrer']",
|
4362 | "a:link": "a[href='http://${0}']",
|
4363 | "a:mail": "a[href='mailto:${0}']",
|
4364 | "a:tel": "a[href='tel:+${0}']",
|
4365 | "abbr": "abbr[title]",
|
4366 | "acr|acronym": "acronym[title]",
|
4367 | "base": "base[href]/",
|
4368 | "basefont": "basefont/",
|
4369 | "br": "br/",
|
4370 | "frame": "frame/",
|
4371 | "hr": "hr/",
|
4372 | "bdo": "bdo[dir]",
|
4373 | "bdo:r": "bdo[dir=rtl]",
|
4374 | "bdo:l": "bdo[dir=ltr]",
|
4375 | "col": "col/",
|
4376 | "link": "link[rel=stylesheet href]/",
|
4377 | "link:css": "link[href='${1:style}.css']",
|
4378 | "link:print": "link[href='${1:print}.css' media=print]",
|
4379 | "link:favicon": "link[rel='shortcut icon' type=image/x-icon href='${1:favicon.ico}']",
|
4380 | "link:mf|link:manifest": "link[rel='manifest' href='${1:manifest.json}']",
|
4381 | "link:touch": "link[rel=apple-touch-icon href='${1:favicon.png}']",
|
4382 | "link:rss": "link[rel=alternate type=application/rss+xml title=RSS href='${1:rss.xml}']",
|
4383 | "link:atom": "link[rel=alternate type=application/atom+xml title=Atom href='${1:atom.xml}']",
|
4384 | "link:im|link:import": "link[rel=import href='${1:component}.html']",
|
4385 | "meta": "meta/",
|
4386 | "meta:utf": "meta[http-equiv=Content-Type content='text/html;charset=UTF-8']",
|
4387 | "meta:vp": "meta[name=viewport content='width=${1:device-width}, initial-scale=${2:1.0}']",
|
4388 | "meta:compat": "meta[http-equiv=X-UA-Compatible content='${1:IE=7}']",
|
4389 | "meta:edge": "meta:compat[content='${1:ie=edge}']",
|
4390 | "meta:redirect": "meta[http-equiv=refresh content='0; url=${1:http://example.com}']",
|
4391 | "meta:refresh": "meta[http-equiv=refresh content='${1:5}']",
|
4392 | "meta:kw": "meta[name=keywords content]",
|
4393 | "meta:desc": "meta[name=description content]",
|
4394 | "style": "style",
|
4395 | "script": "script",
|
4396 | "script:src": "script[src]",
|
4397 | "script:module": "script[type=module src]",
|
4398 | "img": "img[src alt]/",
|
4399 | "img:s|img:srcset": "img[srcset src alt]",
|
4400 | "img:z|img:sizes": "img[sizes srcset src alt]",
|
4401 | "picture": "picture",
|
4402 | "src|source": "source/",
|
4403 | "src:sc|source:src": "source[src type]",
|
4404 | "src:s|source:srcset": "source[srcset]",
|
4405 | "src:t|source:type": "source[srcset type='${1:image/}']",
|
4406 | "src:z|source:sizes": "source[sizes srcset]",
|
4407 | "src:m|source:media": "source[media='(${1:min-width: })' srcset]",
|
4408 | "src:mt|source:media:type": "source:media[type='${2:image/}']",
|
4409 | "src:mz|source:media:sizes": "source:media[sizes srcset]",
|
4410 | "src:zt|source:sizes:type": "source[sizes srcset type='${1:image/}']",
|
4411 | "iframe": "iframe[src frameborder=0]",
|
4412 | "embed": "embed[src type]/",
|
4413 | "object": "object[data type]",
|
4414 | "param": "param[name value]/",
|
4415 | "map": "map[name]",
|
4416 | "area": "area[shape coords href alt]/",
|
4417 | "area:d": "area[shape=default]",
|
4418 | "area:c": "area[shape=circle]",
|
4419 | "area:r": "area[shape=rect]",
|
4420 | "area:p": "area[shape=poly]",
|
4421 | "form": "form[action]",
|
4422 | "form:get": "form[method=get]",
|
4423 | "form:post": "form[method=post]",
|
4424 | "label": "label[for]",
|
4425 | "input": "input[type=${1:text}]/",
|
4426 | "inp": "input[name=${1} id=${1}]",
|
4427 | "input:h|input:hidden": "input[type=hidden name]",
|
4428 | "input:t|input:text": "inp[type=text]",
|
4429 | "input:search": "inp[type=search]",
|
4430 | "input:email": "inp[type=email]",
|
4431 | "input:url": "inp[type=url]",
|
4432 | "input:p|input:password": "inp[type=password]",
|
4433 | "input:datetime": "inp[type=datetime]",
|
4434 | "input:date": "inp[type=date]",
|
4435 | "input:datetime-local": "inp[type=datetime-local]",
|
4436 | "input:month": "inp[type=month]",
|
4437 | "input:week": "inp[type=week]",
|
4438 | "input:time": "inp[type=time]",
|
4439 | "input:tel": "inp[type=tel]",
|
4440 | "input:number": "inp[type=number]",
|
4441 | "input:color": "inp[type=color]",
|
4442 | "input:c|input:checkbox": "inp[type=checkbox]",
|
4443 | "input:r|input:radio": "inp[type=radio]",
|
4444 | "input:range": "inp[type=range]",
|
4445 | "input:f|input:file": "inp[type=file]",
|
4446 | "input:s|input:submit": "input[type=submit value]",
|
4447 | "input:i|input:image": "input[type=image src alt]",
|
4448 | "input:b|input:btn|input:button": "input[type=button value]",
|
4449 | "input:reset": "input:button[type=reset]",
|
4450 | "isindex": "isindex/",
|
4451 | "select": "select[name=${1} id=${1}]",
|
4452 | "select:d|select:disabled": "select[disabled.]",
|
4453 | "opt|option": "option[value]",
|
4454 | "textarea": "textarea[name=${1} id=${1}]",
|
4455 | "tarea:c|textarea:cols":"textarea[name=${1} id=${1} cols=${2:30}]",
|
4456 | "tarea:r|textarea:rows":"textarea[name=${1} id=${1} rows=${3:10}]",
|
4457 | "tarea:cr|textarea:cols:rows":"textarea[name=${1} id=${1} cols=${2:30} rows=${3:10}]",
|
4458 | "marquee": "marquee[behavior direction]",
|
4459 | "menu:c|menu:context": "menu[type=context]",
|
4460 | "menu:t|menu:toolbar": "menu[type=toolbar]",
|
4461 | "video": "video[src]",
|
4462 | "audio": "audio[src]",
|
4463 | "html:xml": "html[xmlns=http://www.w3.org/1999/xhtml]",
|
4464 | "keygen": "keygen/",
|
4465 | "command": "command/",
|
4466 | "btn:s|button:s|button:submit" : "button[type=submit]",
|
4467 | "btn:r|button:r|button:reset" : "button[type=reset]",
|
4468 | "btn:b|button:b|button:button" : "button[type=button]",
|
4469 | "btn:d|button:d|button:disabled" : "button[disabled.]",
|
4470 | "fst:d|fset:d|fieldset:d|fieldset:disabled" : "fieldset[disabled.]",
|
4471 |
|
4472 | "bq": "blockquote",
|
4473 | "fig": "figure",
|
4474 | "figc": "figcaption",
|
4475 | "pic": "picture",
|
4476 | "ifr": "iframe",
|
4477 | "emb": "embed",
|
4478 | "obj": "object",
|
4479 | "cap": "caption",
|
4480 | "colg": "colgroup",
|
4481 | "fst": "fieldset",
|
4482 | "btn": "button",
|
4483 | "optg": "optgroup",
|
4484 | "tarea": "textarea",
|
4485 | "leg": "legend",
|
4486 | "sect": "section",
|
4487 | "art": "article",
|
4488 | "hdr": "header",
|
4489 | "ftr": "footer",
|
4490 | "adr": "address",
|
4491 | "dlg": "dialog",
|
4492 | "str": "strong",
|
4493 | "prog": "progress",
|
4494 | "mn": "main",
|
4495 | "tem": "template",
|
4496 | "fset": "fieldset",
|
4497 | "datal": "datalist",
|
4498 | "kg": "keygen",
|
4499 | "out": "output",
|
4500 | "det": "details",
|
4501 | "sum": "summary",
|
4502 | "cmd": "command",
|
4503 | "data": "data[value]",
|
4504 | "meter": "meter[value]",
|
4505 | "time": "time[datetime]",
|
4506 |
|
4507 | "ri:d|ri:dpr": "img:s",
|
4508 | "ri:v|ri:viewport": "img:z",
|
4509 | "ri:a|ri:art": "pic>src:m+img",
|
4510 | "ri:t|ri:type": "pic>src:t+img",
|
4511 |
|
4512 | "!!!": "{<!DOCTYPE html>}",
|
4513 | "doc": "html[lang=${lang}]>(head>meta[charset=${charset}]+meta:vp+title{${1:Document}})+body",
|
4514 | "!|html:5": "!!!+doc",
|
4515 |
|
4516 | "c": "{<!-- ${0} -->}",
|
4517 | "cc:ie": "{<!--[if IE]>${0}<![endif]-->}",
|
4518 | "cc:noie": "{<!--[if !IE]><!-->${0}<!--<![endif]-->}"
|
4519 | };
|
4520 |
|
4521 | var stylesheetSnippets = {
|
4522 | "@f": "@font-face {\n\tfont-family: ${1};\n\tsrc: url(${2});\n}",
|
4523 | "@ff": "@font-face {\n\tfont-family: '${1:FontName}';\n\tsrc: url('${2:FileName}.eot');\n\tsrc: url('${2:FileName}.eot?#iefix') format('embedded-opentype'),\n\t\t url('${2:FileName}.woff') format('woff'),\n\t\t url('${2:FileName}.ttf') format('truetype'),\n\t\t url('${2:FileName}.svg#${1:FontName}') format('svg');\n\tfont-style: ${3:normal};\n\tfont-weight: ${4:normal};\n}",
|
4524 | "@i|@import": "@import url(${0});",
|
4525 | "@kf": "@keyframes ${1:identifier} {\n\t${2}\n}",
|
4526 | "@m|@media": "@media ${1:screen} {\n\t${0}\n}",
|
4527 | "ac": "align-content:start|end|flex-start|flex-end|center|space-between|space-around|stretch|space-evenly",
|
4528 | "ai": "align-items:start|end|flex-start|flex-end|center|baseline|stretch",
|
4529 | "anim": "animation:${1:name} ${2:duration} ${3:timing-function} ${4:delay} ${5:iteration-count} ${6:direction} ${7:fill-mode}",
|
4530 | "animdel": "animation-delay:time",
|
4531 | "animdir": "animation-direction:normal|reverse|alternate|alternate-reverse",
|
4532 | "animdur": "animation-duration:${1:0}s",
|
4533 | "animfm": "animation-fill-mode:both|forwards|backwards",
|
4534 | "animic": "animation-iteration-count:1|infinite",
|
4535 | "animn": "animation-name",
|
4536 | "animps": "animation-play-state:running|paused",
|
4537 | "animtf": "animation-timing-function:linear|ease|ease-in|ease-out|ease-in-out|cubic-bezier(${1:0.1}, ${2:0.7}, ${3:1.0}, ${3:0.1})",
|
4538 | "ap": "appearance:none",
|
4539 | "as": "align-self:start|end|auto|flex-start|flex-end|center|baseline|stretch",
|
4540 | "b": "bottom",
|
4541 | "bd": "border:${1:1px} ${2:solid} ${3:#000}",
|
4542 | "bdb": "border-bottom:${1:1px} ${2:solid} ${3:#000}",
|
4543 | "bdbc": "border-bottom-color:${1:#000}",
|
4544 | "bdbi": "border-bottom-image:url(${0})",
|
4545 | "bdbk": "border-break:close",
|
4546 | "bdbli": "border-bottom-left-image:url(${0})|continue",
|
4547 | "bdblrs": "border-bottom-left-radius",
|
4548 | "bdbri": "border-bottom-right-image:url(${0})|continue",
|
4549 | "bdbrrs": "border-bottom-right-radius",
|
4550 | "bdbs": "border-bottom-style",
|
4551 | "bdbw": "border-bottom-width",
|
4552 | "bdc": "border-color:${1:#000}",
|
4553 | "bdci": "border-corner-image:url(${0})|continue",
|
4554 | "bdcl": "border-collapse:collapse|separate",
|
4555 | "bdf": "border-fit:repeat|clip|scale|stretch|overwrite|overflow|space",
|
4556 | "bdi": "border-image:url(${0})",
|
4557 | "bdl": "border-left:${1:1px} ${2:solid} ${3:#000}",
|
4558 | "bdlc": "border-left-color:${1:#000}",
|
4559 | "bdlen": "border-length",
|
4560 | "bdli": "border-left-image:url(${0})",
|
4561 | "bdls": "border-left-style",
|
4562 | "bdlw": "border-left-width",
|
4563 | "bdr": "border-right:${1:1px} ${2:solid} ${3:#000}",
|
4564 | "bdrc": "border-right-color:${1:#000}",
|
4565 | "bdri": "border-right-image:url(${0})",
|
4566 | "bdrs": "border-radius",
|
4567 | "bdrst": "border-right-style",
|
4568 | "bdrw": "border-right-width",
|
4569 | "bds": "border-style:none|hidden|dotted|dashed|solid|double|dot-dash|dot-dot-dash|wave|groove|ridge|inset|outset",
|
4570 | "bdsp": "border-spacing",
|
4571 | "bdt": "border-top:${1:1px} ${2:solid} ${3:#000}",
|
4572 | "bdtc": "border-top-color:${1:#000}",
|
4573 | "bdti": "border-top-image:url(${0})",
|
4574 | "bdtli": "border-top-left-image:url(${0})|continue",
|
4575 | "bdtlrs": "border-top-left-radius",
|
4576 | "bdtri": "border-top-right-image:url(${0})|continue",
|
4577 | "bdtrrs": "border-top-right-radius",
|
4578 | "bdts": "border-top-style",
|
4579 | "bdtw": "border-top-width",
|
4580 | "bdw": "border-width",
|
4581 | "bbs": "border-block-start",
|
4582 | "bbe": "border-block-end",
|
4583 | "bis": "border-inline-start",
|
4584 | "bie": "border-inline-end",
|
4585 | "bfv": "backface-visibility:hidden|visible",
|
4586 | "bg": "background:${1:#000}",
|
4587 | "bg:n": "background: none",
|
4588 | "bga": "background-attachment:fixed|scroll",
|
4589 | "bgbk": "background-break:bounding-box|each-box|continuous",
|
4590 | "bgc": "background-color:${1:#fff}",
|
4591 | "bgcp": "background-clip:padding-box|border-box|content-box|no-clip",
|
4592 | "bgi": "background-image:url(${0})",
|
4593 | "bgo": "background-origin:padding-box|border-box|content-box",
|
4594 | "bgp": "background-position:${1:0} ${2:0}",
|
4595 | "bgpx": "background-position-x",
|
4596 | "bgpy": "background-position-y",
|
4597 | "bgr": "background-repeat:no-repeat|repeat-x|repeat-y|space|round",
|
4598 | "bgsz": "background-size:contain|cover",
|
4599 | "bs": "block-size",
|
4600 | "bxsh": "box-shadow:${1:inset }${2:hoff} ${3:voff} ${4:blur} ${5:#000}|none",
|
4601 | "bxsz": "box-sizing:border-box|content-box|border-box",
|
4602 | "c": "color:${1:#000}",
|
4603 | "cr": "color:rgb(${1:0}, ${2:0}, ${3:0})",
|
4604 | "cra": "color:rgba(${1:0}, ${2:0}, ${3:0}, ${4:.5})",
|
4605 | "cl": "clear:both|left|right|none",
|
4606 | "cm": "/* ${0} */",
|
4607 | "cnt": "content:'${0}'|normal|open-quote|no-open-quote|close-quote|no-close-quote|attr(${0})|counter(${0})|counters(${0})",
|
4608 | "coi": "counter-increment",
|
4609 | "colm": "columns",
|
4610 | "colmc": "column-count",
|
4611 | "colmf": "column-fill",
|
4612 | "colmg": "column-gap",
|
4613 | "colmr": "column-rule",
|
4614 | "colmrc": "column-rule-color",
|
4615 | "colmrs": "column-rule-style",
|
4616 | "colmrw": "column-rule-width",
|
4617 | "colms": "column-span",
|
4618 | "colmw": "column-width",
|
4619 | "cor": "counter-reset",
|
4620 | "cp": "clip:auto|rect(${1:top} ${2:right} ${3:bottom} ${4:left})",
|
4621 | "cps": "caption-side:top|bottom",
|
4622 | "cur": "cursor:pointer|auto|default|crosshair|hand|help|move|pointer|text",
|
4623 | "d": "display:block|none|flex|inline-flex|inline|inline-block|grid|inline-grid|subgrid|list-item|run-in|contents|table|inline-table|table-caption|table-column|table-column-group|table-header-group|table-footer-group|table-row|table-row-group|table-cell|ruby|ruby-base|ruby-base-group|ruby-text|ruby-text-group",
|
4624 | "ec": "empty-cells:show|hide",
|
4625 | "f": "font:${1:1em} ${2:sans-serif}",
|
4626 | "fd": "font-display:auto|block|swap|fallback|optional",
|
4627 | "fef": "font-effect:none|engrave|emboss|outline",
|
4628 | "fem": "font-emphasize",
|
4629 | "femp": "font-emphasize-position:before|after",
|
4630 | "fems": "font-emphasize-style:none|accent|dot|circle|disc",
|
4631 | "ff": "font-family:serif|sans-serif|cursive|fantasy|monospace",
|
4632 | "fft": "font-family:\"Times New Roman\", Times, Baskerville, Georgia, serif",
|
4633 | "ffa": "font-family:Arial, \"Helvetica Neue\", Helvetica, sans-serif",
|
4634 | "ffv": "font-family:Verdana, Geneva, sans-serif",
|
4635 | "fl": "float:left|right|none",
|
4636 | "fs": "font-style:italic|normal|oblique",
|
4637 | "fsm": "font-smoothing:antialiased|subpixel-antialiased|none",
|
4638 | "fst": "font-stretch:normal|ultra-condensed|extra-condensed|condensed|semi-condensed|semi-expanded|expanded|extra-expanded|ultra-expanded",
|
4639 | "fv": "font-variant:normal|small-caps",
|
4640 | "fvs": "font-variation-settings:normal|inherit|initial|unset",
|
4641 | "fw": "font-weight:normal|bold|bolder|lighter",
|
4642 | "fx": "flex",
|
4643 | "fxb": "flex-basis:fill|max-content|min-content|fit-content|content",
|
4644 | "fxd": "flex-direction:row|row-reverse|column|column-reverse",
|
4645 | "fxf": "flex-flow",
|
4646 | "fxg": "flex-grow",
|
4647 | "fxsh": "flex-shrink",
|
4648 | "fxw": "flex-wrap:nowrap|wrap|wrap-reverse",
|
4649 | "fsz": "font-size",
|
4650 | "fsza": "font-size-adjust",
|
4651 | "g": "gap",
|
4652 | "gtc": "grid-template-columns:repeat(${0})|minmax()",
|
4653 | "gtr": "grid-template-rows:repeat(${0})|minmax()",
|
4654 | "gta": "grid-template-areas",
|
4655 | "gt": "grid-template",
|
4656 | "gg": "grid-gap",
|
4657 | "gcg": "grid-column-gap",
|
4658 | "grg": "grid-row-gap",
|
4659 | "gac": "grid-auto-columns:auto|minmax()",
|
4660 | "gar": "grid-auto-rows:auto|minmax()",
|
4661 | "gaf": "grid-auto-flow:row|column|dense|inherit|initial|unset",
|
4662 | "gd": "grid",
|
4663 | "gc": "grid-column",
|
4664 | "gcs": "grid-column-start",
|
4665 | "gce": "grid-column-end",
|
4666 | "gr": "grid-row",
|
4667 | "grs": "grid-row-start",
|
4668 | "gre": "grid-row-end",
|
4669 | "ga": "grid-area",
|
4670 | "h": "height",
|
4671 | "is": "inline-size",
|
4672 | "jc": "justify-content:start|end|stretch|flex-start|flex-end|center|space-between|space-around|space-evenly",
|
4673 | "ji": "justify-items:start|end|center|stretch",
|
4674 | "js": "justify-self:start|end|center|stretch",
|
4675 | "l": "left",
|
4676 | "lg": "background-image:linear-gradient(${1})",
|
4677 | "lh": "line-height",
|
4678 | "lis": "list-style",
|
4679 | "lisi": "list-style-image",
|
4680 | "lisp": "list-style-position:inside|outside",
|
4681 | "list": "list-style-type:disc|circle|square|decimal|decimal-leading-zero|lower-roman|upper-roman",
|
4682 | "lts": "letter-spacing:normal",
|
4683 | "m": "margin",
|
4684 | "mah": "max-height",
|
4685 | "mar": "max-resolution",
|
4686 | "maw": "max-width",
|
4687 | "mb": "margin-bottom",
|
4688 | "mih": "min-height",
|
4689 | "mir": "min-resolution",
|
4690 | "miw": "min-width",
|
4691 | "ml": "margin-left",
|
4692 | "mr": "margin-right",
|
4693 | "mt": "margin-top",
|
4694 | "mbs": "margin-block-start",
|
4695 | "mbe": "margin-block-end",
|
4696 | "mis": "margin-inline-start",
|
4697 | "mie": "margin-inline-end",
|
4698 | "ol": "outline",
|
4699 | "olc": "outline-color:${1:#000}|invert",
|
4700 | "olo": "outline-offset",
|
4701 | "ols": "outline-style:none|dotted|dashed|solid|double|groove|ridge|inset|outset",
|
4702 | "olw": "outline-width:thin|medium|thick",
|
4703 | "op|opa": "opacity",
|
4704 | "ord": "order",
|
4705 | "ori": "orientation:landscape|portrait",
|
4706 | "orp": "orphans",
|
4707 | "ov": "overflow:hidden|visible|hidden|scroll|auto",
|
4708 | "ovs": "overflow-style:scrollbar|auto|scrollbar|panner|move|marquee",
|
4709 | "ovx": "overflow-x:hidden|visible|hidden|scroll|auto",
|
4710 | "ovy": "overflow-y:hidden|visible|hidden|scroll|auto",
|
4711 | "p": "padding",
|
4712 | "pb": "padding-bottom",
|
4713 | "pgba": "page-break-after:auto|always|left|right",
|
4714 | "pgbb": "page-break-before:auto|always|left|right",
|
4715 | "pgbi": "page-break-inside:auto|avoid",
|
4716 | "pl": "padding-left",
|
4717 | "pos": "position:relative|absolute|relative|fixed|static",
|
4718 | "pr": "padding-right",
|
4719 | "pt": "padding-top",
|
4720 | "pbs": "padding-block-start",
|
4721 | "pbe": "padding-block-end",
|
4722 | "pis": "padding-inline-start",
|
4723 | "pie": "padding-inline-end",
|
4724 | "spbs": "scroll-padding-block-start",
|
4725 | "spbe": "scroll-padding-block-end",
|
4726 | "spis": "scroll-padding-inline-start",
|
4727 | "spie": "scroll-padding-inline-end",
|
4728 | "q": "quotes",
|
4729 | "qen": "quotes:'\\201C' '\\201D' '\\2018' '\\2019'",
|
4730 | "qru": "quotes:'\\00AB' '\\00BB' '\\201E' '\\201C'",
|
4731 | "r": "right",
|
4732 | "rsz": "resize:none|both|horizontal|vertical",
|
4733 | "t": "top",
|
4734 | "ta": "text-align:left|center|right|justify",
|
4735 | "tal": "text-align-last:left|center|right",
|
4736 | "tbl": "table-layout:fixed",
|
4737 | "td": "text-decoration:none|underline|overline|line-through",
|
4738 | "te": "text-emphasis:none|accent|dot|circle|disc|before|after",
|
4739 | "th": "text-height:auto|font-size|text-size|max-size",
|
4740 | "ti": "text-indent",
|
4741 | "tj": "text-justify:auto|inter-word|inter-ideograph|inter-cluster|distribute|kashida|tibetan",
|
4742 | "to": "text-outline:${1:0} ${2:0} ${3:#000}",
|
4743 | "tov": "text-overflow:ellipsis|clip",
|
4744 | "tr": "text-replace",
|
4745 | "trf": "transform:${1}|skewX(${1:angle})|skewY(${1:angle})|scale(${1:x}, ${2:y})|scaleX(${1:x})|scaleY(${1:y})|scaleZ(${1:z})|scale3d(${1:x}, ${2:y}, ${3:z})|rotate(${1:angle})|rotateX(${1:angle})|rotateY(${1:angle})|rotateZ(${1:angle})|translate(${1:x}, ${2:y})|translateX(${1:x})|translateY(${1:y})|translateZ(${1:z})|translate3d(${1:tx}, ${2:ty}, ${3:tz})",
|
4746 | "trfo": "transform-origin",
|
4747 | "trfs": "transform-style:preserve-3d",
|
4748 | "trs": "transition:${1:prop} ${2:time}",
|
4749 | "trsde": "transition-delay:${1:time}",
|
4750 | "trsdu": "transition-duration:${1:time}",
|
4751 | "trsp": "transition-property:${1:prop}",
|
4752 | "trstf": "transition-timing-function:${1:fn}",
|
4753 | "tsh": "text-shadow:${1:hoff} ${2:voff} ${3:blur} ${4:#000}",
|
4754 | "tt": "text-transform:uppercase|lowercase|capitalize|none",
|
4755 | "tw": "text-wrap:none|normal|unrestricted|suppress",
|
4756 | "us": "user-select:none",
|
4757 | "v": "visibility:hidden|visible|collapse",
|
4758 | "va": "vertical-align:top|super|text-top|middle|baseline|bottom|text-bottom|sub",
|
4759 | "w|wid": "width",
|
4760 | "whs": "white-space:nowrap|pre|pre-wrap|pre-line|normal",
|
4761 | "whsc": "white-space-collapse:normal|keep-all|loose|break-strict|break-all",
|
4762 | "wido": "widows",
|
4763 | "wm": "writing-mode:lr-tb|lr-tb|lr-bt|rl-tb|rl-bt|tb-rl|tb-lr|bt-lr|bt-rl",
|
4764 | "wob": "word-break:normal|keep-all|break-all",
|
4765 | "wos": "word-spacing",
|
4766 | "wow": "word-wrap:none|unrestricted|suppress|break-word|normal",
|
4767 | "z": "z-index",
|
4768 | "zom": "zoom:1"
|
4769 | };
|
4770 |
|
4771 | var xslSnippets = {
|
4772 | "tm|tmatch": "xsl:template[match mode]",
|
4773 | "tn|tname": "xsl:template[name]",
|
4774 | "call": "xsl:call-template[name]",
|
4775 | "ap": "xsl:apply-templates[select mode]",
|
4776 | "api": "xsl:apply-imports",
|
4777 | "imp": "xsl:import[href]",
|
4778 | "inc": "xsl:include[href]",
|
4779 | "ch": "xsl:choose",
|
4780 | "wh|xsl:when": "xsl:when[test]",
|
4781 | "ot": "xsl:otherwise",
|
4782 | "if": "xsl:if[test]",
|
4783 | "par": "xsl:param[name]",
|
4784 | "pare": "xsl:param[name select]",
|
4785 | "var": "xsl:variable[name]",
|
4786 | "vare": "xsl:variable[name select]",
|
4787 | "wp": "xsl:with-param[name select]",
|
4788 | "key": "xsl:key[name match use]",
|
4789 | "elem": "xsl:element[name]",
|
4790 | "attr": "xsl:attribute[name]",
|
4791 | "attrs": "xsl:attribute-set[name]",
|
4792 | "cp": "xsl:copy[select]",
|
4793 | "co": "xsl:copy-of[select]",
|
4794 | "val": "xsl:value-of[select]",
|
4795 | "for|each": "xsl:for-each[select]",
|
4796 | "tex": "xsl:text",
|
4797 | "com": "xsl:comment",
|
4798 | "msg": "xsl:message[terminate=no]",
|
4799 | "fall": "xsl:fallback",
|
4800 | "num": "xsl:number[value]",
|
4801 | "nam": "namespace-alias[stylesheet-prefix result-prefix]",
|
4802 | "pres": "xsl:preserve-space[elements]",
|
4803 | "strip": "xsl:strip-space[elements]",
|
4804 | "proc": "xsl:processing-instruction[name]",
|
4805 | "sort": "xsl:sort[select order]",
|
4806 | "choose": "xsl:choose>xsl:when+xsl:otherwise",
|
4807 | "xsl": "!!!+xsl:stylesheet[version=1.0 xmlns:xsl=http://www.w3.org/1999/XSL/Transform]>{\n|}",
|
4808 | "!!!": "{<?xml version=\"1.0\" encoding=\"UTF-8\"?>}"
|
4809 | };
|
4810 |
|
4811 | var pugSnippets = {
|
4812 | "!!!": "{doctype html}"
|
4813 | };
|
4814 |
|
4815 | var variables = {
|
4816 | "lang": "en",
|
4817 | "locale": "en-US",
|
4818 | "charset": "UTF-8",
|
4819 | "indentation": "\t",
|
4820 | "newline": "\n"
|
4821 | };
|
4822 |
|
4823 |
|
4824 |
|
4825 |
|
4826 | const defaultSyntaxes = {
|
4827 | markup: 'html',
|
4828 | stylesheet: 'css'
|
4829 | };
|
4830 | const defaultOptions$1 = {
|
4831 | 'inlineElements': [
|
4832 | 'a', 'abbr', 'acronym', 'applet', 'b', 'basefont', 'bdo',
|
4833 | 'big', 'br', 'button', 'cite', 'code', 'del', 'dfn', 'em', 'font', 'i',
|
4834 | 'iframe', 'img', 'input', 'ins', 'kbd', 'label', 'map', 'object', 'q',
|
4835 | 's', 'samp', 'select', 'small', 'span', 'strike', 'strong', 'sub', 'sup',
|
4836 | 'textarea', 'tt', 'u', 'var'
|
4837 | ],
|
4838 | 'output.indent': '\t',
|
4839 | 'output.baseIndent': '',
|
4840 | 'output.newline': '\n',
|
4841 | 'output.tagCase': '',
|
4842 | 'output.attributeCase': '',
|
4843 | 'output.attributeQuotes': 'double',
|
4844 | 'output.format': true,
|
4845 | 'output.formatLeafNode': false,
|
4846 | 'output.formatSkip': ['html'],
|
4847 | 'output.formatForce': ['body'],
|
4848 | 'output.inlineBreak': 3,
|
4849 | 'output.compactBoolean': false,
|
4850 | 'output.booleanAttributes': [
|
4851 | 'contenteditable', 'seamless', 'async', 'autofocus',
|
4852 | 'autoplay', 'checked', 'controls', 'defer', 'disabled', 'formnovalidate',
|
4853 | 'hidden', 'ismap', 'loop', 'multiple', 'muted', 'novalidate', 'readonly',
|
4854 | 'required', 'reversed', 'selected', 'typemustmatch'
|
4855 | ],
|
4856 | 'output.reverseAttributes': false,
|
4857 | 'output.selfClosingStyle': 'html',
|
4858 | 'output.field': (index, placeholder) => placeholder,
|
4859 | 'output.text': text => text,
|
4860 | 'markup.href': true,
|
4861 | 'comment.enabled': false,
|
4862 | 'comment.trigger': ['id', 'class'],
|
4863 | 'comment.before': '',
|
4864 | 'comment.after': '\n<!-- /[#ID][.CLASS] -->',
|
4865 | 'bem.enabled': false,
|
4866 | 'bem.element': '__',
|
4867 | 'bem.modifier': '_',
|
4868 | 'jsx.enabled': false,
|
4869 | 'stylesheet.keywords': ['auto', 'inherit', 'unset', 'none'],
|
4870 | 'stylesheet.unitless': ['z-index', 'line-height', 'opacity', 'font-weight', 'zoom', 'flex', 'flex-grow', 'flex-shrink'],
|
4871 | 'stylesheet.shortHex': true,
|
4872 | 'stylesheet.between': ': ',
|
4873 | 'stylesheet.after': ';',
|
4874 | 'stylesheet.intUnit': 'px',
|
4875 | 'stylesheet.floatUnit': 'em',
|
4876 | 'stylesheet.unitAliases': { e: 'em', p: '%', x: 'ex', r: 'rem' },
|
4877 | 'stylesheet.json': false,
|
4878 | 'stylesheet.jsonDoubleQuotes': false,
|
4879 | 'stylesheet.fuzzySearchMinScore': 0
|
4880 | };
|
4881 | const defaultConfig = {
|
4882 | type: 'markup',
|
4883 | syntax: 'html',
|
4884 | variables,
|
4885 | snippets: {},
|
4886 | options: defaultOptions$1
|
4887 | };
|
4888 |
|
4889 |
|
4890 |
|
4891 | const syntaxConfig = {
|
4892 | markup: {
|
4893 | snippets: parseSnippets(markupSnippets),
|
4894 | },
|
4895 | xhtml: {
|
4896 | options: {
|
4897 | 'output.selfClosingStyle': 'xhtml'
|
4898 | }
|
4899 | },
|
4900 | xml: {
|
4901 | options: {
|
4902 | 'output.selfClosingStyle': 'xml'
|
4903 | }
|
4904 | },
|
4905 | xsl: {
|
4906 | snippets: parseSnippets(xslSnippets),
|
4907 | options: {
|
4908 | 'output.selfClosingStyle': 'xml'
|
4909 | }
|
4910 | },
|
4911 | jsx: {
|
4912 | options: {
|
4913 | 'jsx.enabled': true,
|
4914 | 'markup.attributes': {
|
4915 | 'class': 'className',
|
4916 | 'class*': 'styleName',
|
4917 | 'for': 'htmlFor'
|
4918 | },
|
4919 | 'markup.valuePrefix': {
|
4920 | 'class*': 'styles'
|
4921 | }
|
4922 | }
|
4923 | },
|
4924 | vue: {
|
4925 | options: {
|
4926 | 'markup.attributes': {
|
4927 | 'class*': ':class',
|
4928 | }
|
4929 | }
|
4930 | },
|
4931 | svelte: {
|
4932 | options: {
|
4933 | 'jsx.enabled': true
|
4934 | }
|
4935 | },
|
4936 | pug: {
|
4937 | snippets: parseSnippets(pugSnippets)
|
4938 | },
|
4939 | stylesheet: {
|
4940 | snippets: parseSnippets(stylesheetSnippets)
|
4941 | },
|
4942 | sass: {
|
4943 | options: {
|
4944 | 'stylesheet.after': ''
|
4945 | }
|
4946 | },
|
4947 | stylus: {
|
4948 | options: {
|
4949 | 'stylesheet.between': ' ',
|
4950 | 'stylesheet.after': '',
|
4951 | }
|
4952 | }
|
4953 | };
|
4954 |
|
4955 |
|
4956 |
|
4957 |
|
4958 | function parseSnippets(snippets) {
|
4959 | const result = {};
|
4960 | Object.keys(snippets).forEach(k => {
|
4961 | for (const name of k.split('|')) {
|
4962 | result[name] = snippets[k];
|
4963 | }
|
4964 | });
|
4965 | return result;
|
4966 | }
|
4967 | function resolveConfig(config = {}, globals = {}) {
|
4968 | const type = config.type || 'markup';
|
4969 | const syntax = config.syntax || defaultSyntaxes[type];
|
4970 | return Object.assign(Object.assign(Object.assign({}, defaultConfig), config), { type,
|
4971 | syntax, variables: mergedData(type, syntax, 'variables', config, globals), snippets: mergedData(type, syntax, 'snippets', config, globals), options: mergedData(type, syntax, 'options', config, globals) });
|
4972 | }
|
4973 | function mergedData(type, syntax, key, config, globals = {}) {
|
4974 | const typeDefaults = syntaxConfig[type];
|
4975 | const typeOverride = globals[type];
|
4976 | const syntaxDefaults = syntaxConfig[syntax];
|
4977 | const syntaxOverride = globals[syntax];
|
4978 | return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, defaultConfig[key]), (typeDefaults && typeDefaults[key])), (syntaxDefaults && syntaxDefaults[key])), (typeOverride && typeOverride[key])), (syntaxOverride && syntaxOverride[key])), config[key]);
|
4979 | }
|
4980 |
|
4981 |
|
4982 |
|
4983 |
|
4984 | function backwardScanner(text, start = 0) {
|
4985 | return { text, start, pos: text.length };
|
4986 | }
|
4987 |
|
4988 |
|
4989 |
|
4990 | function sol(scanner) {
|
4991 | return scanner.pos === scanner.start;
|
4992 | }
|
4993 |
|
4994 |
|
4995 |
|
4996 | function peek(scanner, offset = 0) {
|
4997 | return scanner.text.charCodeAt(scanner.pos - 1 + offset);
|
4998 | }
|
4999 |
|
5000 |
|
5001 |
|
5002 | function previous(scanner) {
|
5003 | if (!sol(scanner)) {
|
5004 | return scanner.text.charCodeAt(--scanner.pos);
|
5005 | }
|
5006 | }
|
5007 |
|
5008 |
|
5009 |
|
5010 | function consume(scanner, match) {
|
5011 | if (sol(scanner)) {
|
5012 | return false;
|
5013 | }
|
5014 | const ok = typeof match === 'function'
|
5015 | ? match(peek(scanner))
|
5016 | : match === peek(scanner);
|
5017 | if (ok) {
|
5018 | scanner.pos--;
|
5019 | }
|
5020 | return !!ok;
|
5021 | }
|
5022 | function consumeWhile(scanner, match) {
|
5023 | const start = scanner.pos;
|
5024 | while (consume(scanner, match)) {
|
5025 |
|
5026 | }
|
5027 | return scanner.pos < start;
|
5028 | }
|
5029 |
|
5030 | var Chars$1;
|
5031 | (function (Chars) {
|
5032 | Chars[Chars["SingleQuote"] = 39] = "SingleQuote";
|
5033 | Chars[Chars["DoubleQuote"] = 34] = "DoubleQuote";
|
5034 | Chars[Chars["Escape"] = 92] = "Escape";
|
5035 | })(Chars$1 || (Chars$1 = {}));
|
5036 |
|
5037 |
|
5038 |
|
5039 | function isQuote(c) {
|
5040 | return c === Chars$1.SingleQuote || c === Chars$1.DoubleQuote;
|
5041 | }
|
5042 |
|
5043 |
|
5044 |
|
5045 |
|
5046 | function consumeQuoted(scanner) {
|
5047 | const start = scanner.pos;
|
5048 | const quote = previous(scanner);
|
5049 | if (isQuote(quote)) {
|
5050 | while (!sol(scanner)) {
|
5051 | if (previous(scanner) === quote && peek(scanner) !== Chars$1.Escape) {
|
5052 | return true;
|
5053 | }
|
5054 | }
|
5055 | }
|
5056 | scanner.pos = start;
|
5057 | return false;
|
5058 | }
|
5059 |
|
5060 | var Brackets;
|
5061 | (function (Brackets) {
|
5062 | Brackets[Brackets["SquareL"] = 91] = "SquareL";
|
5063 | Brackets[Brackets["SquareR"] = 93] = "SquareR";
|
5064 | Brackets[Brackets["RoundL"] = 40] = "RoundL";
|
5065 | Brackets[Brackets["RoundR"] = 41] = "RoundR";
|
5066 | Brackets[Brackets["CurlyL"] = 123] = "CurlyL";
|
5067 | Brackets[Brackets["CurlyR"] = 125] = "CurlyR";
|
5068 | })(Brackets || (Brackets = {}));
|
5069 | const bracePairs = {
|
5070 | [Brackets.SquareL]: Brackets.SquareR,
|
5071 | [Brackets.RoundL]: Brackets.RoundR,
|
5072 | [Brackets.CurlyL]: Brackets.CurlyR,
|
5073 | };
|
5074 |
|
5075 | var Chars;
|
5076 | (function (Chars) {
|
5077 | Chars[Chars["Tab"] = 9] = "Tab";
|
5078 | Chars[Chars["Space"] = 32] = "Space";
|
5079 |
|
5080 | Chars[Chars["Dash"] = 45] = "Dash";
|
5081 |
|
5082 | Chars[Chars["Slash"] = 47] = "Slash";
|
5083 |
|
5084 | Chars[Chars["Colon"] = 58] = "Colon";
|
5085 |
|
5086 | Chars[Chars["Equals"] = 61] = "Equals";
|
5087 |
|
5088 | Chars[Chars["AngleLeft"] = 60] = "AngleLeft";
|
5089 |
|
5090 | Chars[Chars["AngleRight"] = 62] = "AngleRight";
|
5091 | })(Chars || (Chars = {}));
|
5092 |
|
5093 |
|
5094 |
|
5095 | function isHtml(scanner) {
|
5096 | const start = scanner.pos;
|
5097 | if (!consume(scanner, Chars.AngleRight)) {
|
5098 | return false;
|
5099 | }
|
5100 | let ok = false;
|
5101 | consume(scanner, Chars.Slash);
|
5102 | while (!sol(scanner)) {
|
5103 | consumeWhile(scanner, isWhiteSpace);
|
5104 | if (consumeIdent(scanner)) {
|
5105 |
|
5106 |
|
5107 | if (consume(scanner, Chars.Slash)) {
|
5108 |
|
5109 | ok = consume(scanner, Chars.AngleLeft);
|
5110 | break;
|
5111 | }
|
5112 | else if (consume(scanner, Chars.AngleLeft)) {
|
5113 |
|
5114 | ok = true;
|
5115 | break;
|
5116 | }
|
5117 | else if (consume(scanner, isWhiteSpace)) {
|
5118 |
|
5119 | continue;
|
5120 | }
|
5121 | else if (consume(scanner, Chars.Equals)) {
|
5122 |
|
5123 | if (consumeIdent(scanner)) {
|
5124 | continue;
|
5125 | }
|
5126 | break;
|
5127 | }
|
5128 | else if (consumeAttributeWithUnquotedValue(scanner)) {
|
5129 |
|
5130 | ok = true;
|
5131 | break;
|
5132 | }
|
5133 |
|
5134 | break;
|
5135 | }
|
5136 | if (consumeAttribute(scanner)) {
|
5137 | continue;
|
5138 | }
|
5139 | break;
|
5140 | }
|
5141 | scanner.pos = start;
|
5142 | return ok;
|
5143 | }
|
5144 |
|
5145 |
|
5146 |
|
5147 |
|
5148 | function consumeAttribute(scanner) {
|
5149 | return consumeAttributeWithQuotedValue(scanner) || consumeAttributeWithUnquotedValue(scanner);
|
5150 | }
|
5151 | function consumeAttributeWithQuotedValue(scanner) {
|
5152 | const start = scanner.pos;
|
5153 | if (consumeQuoted(scanner) && consume(scanner, Chars.Equals) && consumeIdent(scanner)) {
|
5154 | return true;
|
5155 | }
|
5156 | scanner.pos = start;
|
5157 | return false;
|
5158 | }
|
5159 | function consumeAttributeWithUnquotedValue(scanner) {
|
5160 | const start = scanner.pos;
|
5161 | const stack = [];
|
5162 | while (!sol(scanner)) {
|
5163 | const ch = peek(scanner);
|
5164 | if (isCloseBracket(ch)) {
|
5165 | stack.push(ch);
|
5166 | }
|
5167 | else if (isOpenBracket(ch)) {
|
5168 | if (stack.pop() !== bracePairs[ch]) {
|
5169 |
|
5170 | break;
|
5171 | }
|
5172 | }
|
5173 | else if (!isUnquotedValue(ch)) {
|
5174 | break;
|
5175 | }
|
5176 | scanner.pos--;
|
5177 | }
|
5178 | if (start !== scanner.pos && consume(scanner, Chars.Equals) && consumeIdent(scanner)) {
|
5179 | return true;
|
5180 | }
|
5181 | scanner.pos = start;
|
5182 | return false;
|
5183 | }
|
5184 |
|
5185 |
|
5186 |
|
5187 | function consumeIdent(scanner) {
|
5188 | return consumeWhile(scanner, isIdent);
|
5189 | }
|
5190 |
|
5191 |
|
5192 |
|
5193 | function isIdent(ch) {
|
5194 | return ch === Chars.Colon || ch === Chars.Dash || isAlpha(ch) || isNumber(ch);
|
5195 | }
|
5196 |
|
5197 |
|
5198 |
|
5199 | function isAlpha(ch) {
|
5200 | ch &= ~32;
|
5201 | return ch >= 65 && ch <= 90;
|
5202 | }
|
5203 |
|
5204 |
|
5205 |
|
5206 | function isNumber(ch) {
|
5207 | return ch > 47 && ch < 58;
|
5208 | }
|
5209 |
|
5210 |
|
5211 |
|
5212 | function isWhiteSpace(ch) {
|
5213 | return ch === Chars.Space || ch === Chars.Tab;
|
5214 | }
|
5215 |
|
5216 |
|
5217 |
|
5218 | function isUnquotedValue(ch) {
|
5219 | return !isNaN(ch) && ch !== Chars.Equals && !isWhiteSpace(ch) && !isQuote(ch);
|
5220 | }
|
5221 | function isOpenBracket(ch) {
|
5222 | return ch === Brackets.CurlyL || ch === Brackets.RoundL || ch === Brackets.SquareL;
|
5223 | }
|
5224 | function isCloseBracket(ch) {
|
5225 | return ch === Brackets.CurlyR || ch === Brackets.RoundR || ch === Brackets.SquareR;
|
5226 | }
|
5227 |
|
5228 | const code = (ch) => ch.charCodeAt(0);
|
5229 | const specialChars = '#.*:$-_!@%^+>/'.split('').map(code);
|
5230 | const defaultOptions = {
|
5231 | type: 'markup',
|
5232 | lookAhead: true,
|
5233 | prefix: ''
|
5234 | };
|
5235 |
|
5236 |
|
5237 |
|
5238 |
|
5239 |
|
5240 |
|
5241 |
|
5242 |
|
5243 |
|
5244 | function extractAbbreviation(line, pos = line.length, options = {}) {
|
5245 |
|
5246 | const opt = Object.assign(Object.assign({}, defaultOptions), options);
|
5247 | pos = Math.min(line.length, Math.max(0, pos == null ? line.length : pos));
|
5248 | if (opt.lookAhead) {
|
5249 | pos = offsetPastAutoClosed(line, pos, opt);
|
5250 | }
|
5251 | let ch;
|
5252 | const start = getStartOffset(line, pos, opt.prefix || '');
|
5253 | if (start === -1) {
|
5254 | return void 0;
|
5255 | }
|
5256 | const scanner = backwardScanner(line, start);
|
5257 | scanner.pos = pos;
|
5258 | const stack = [];
|
5259 | while (!sol(scanner)) {
|
5260 | ch = peek(scanner);
|
5261 | if (stack.includes(Brackets.CurlyR)) {
|
5262 | if (ch === Brackets.CurlyR) {
|
5263 | stack.push(ch);
|
5264 | scanner.pos--;
|
5265 | continue;
|
5266 | }
|
5267 | if (ch !== Brackets.CurlyL) {
|
5268 | scanner.pos--;
|
5269 | continue;
|
5270 | }
|
5271 | }
|
5272 | if (isCloseBrace(ch, opt.type)) {
|
5273 | stack.push(ch);
|
5274 | }
|
5275 | else if (isOpenBrace(ch, opt.type)) {
|
5276 | if (stack.pop() !== bracePairs[ch]) {
|
5277 |
|
5278 | break;
|
5279 | }
|
5280 | }
|
5281 | else if (stack.includes(Brackets.SquareR) || stack.includes(Brackets.CurlyR)) {
|
5282 |
|
5283 | scanner.pos--;
|
5284 | continue;
|
5285 | }
|
5286 | else if (isHtml(scanner) || !isAbbreviation(ch)) {
|
5287 | break;
|
5288 | }
|
5289 | scanner.pos--;
|
5290 | }
|
5291 | if (!stack.length && scanner.pos !== pos) {
|
5292 |
|
5293 |
|
5294 | const abbreviation = line.slice(scanner.pos, pos).replace(/^[*+>^]+/, '');
|
5295 | return {
|
5296 | abbreviation,
|
5297 | location: pos - abbreviation.length,
|
5298 | start: options.prefix
|
5299 | ? start - options.prefix.length
|
5300 | : pos - abbreviation.length,
|
5301 | end: pos
|
5302 | };
|
5303 | }
|
5304 | }
|
5305 |
|
5306 |
|
5307 |
|
5308 |
|
5309 | function offsetPastAutoClosed(line, pos, options) {
|
5310 |
|
5311 | if (isQuote(line.charCodeAt(pos))) {
|
5312 | pos++;
|
5313 | }
|
5314 |
|
5315 | while (isCloseBrace(line.charCodeAt(pos), options.type)) {
|
5316 | pos++;
|
5317 | }
|
5318 | return pos;
|
5319 | }
|
5320 |
|
5321 |
|
5322 |
|
5323 |
|
5324 | function getStartOffset(line, pos, prefix) {
|
5325 | if (!prefix) {
|
5326 | return 0;
|
5327 | }
|
5328 | const scanner = backwardScanner(line);
|
5329 | const compiledPrefix = prefix.split('').map(code);
|
5330 | scanner.pos = pos;
|
5331 | let result;
|
5332 | while (!sol(scanner)) {
|
5333 | if (consumePair(scanner, Brackets.SquareR, Brackets.SquareL) || consumePair(scanner, Brackets.CurlyR, Brackets.CurlyL)) {
|
5334 | continue;
|
5335 | }
|
5336 | result = scanner.pos;
|
5337 | if (consumeArray(scanner, compiledPrefix)) {
|
5338 | return result;
|
5339 | }
|
5340 | scanner.pos--;
|
5341 | }
|
5342 | return -1;
|
5343 | }
|
5344 |
|
5345 |
|
5346 |
|
5347 | function consumePair(scanner, close, open) {
|
5348 | const start = scanner.pos;
|
5349 | if (consume(scanner, close)) {
|
5350 | while (!sol(scanner)) {
|
5351 | if (consume(scanner, open)) {
|
5352 | return true;
|
5353 | }
|
5354 | scanner.pos--;
|
5355 | }
|
5356 | }
|
5357 | scanner.pos = start;
|
5358 | return false;
|
5359 | }
|
5360 |
|
5361 |
|
5362 |
|
5363 | function consumeArray(scanner, arr) {
|
5364 | const start = scanner.pos;
|
5365 | let consumed = false;
|
5366 | for (let i = arr.length - 1; i >= 0 && !sol(scanner); i--) {
|
5367 | if (!consume(scanner, arr[i])) {
|
5368 | break;
|
5369 | }
|
5370 | consumed = i === 0;
|
5371 | }
|
5372 | if (!consumed) {
|
5373 | scanner.pos = start;
|
5374 | }
|
5375 | return consumed;
|
5376 | }
|
5377 | function isAbbreviation(ch) {
|
5378 | return (ch > 64 && ch < 91)
|
5379 | || (ch > 96 && ch < 123)
|
5380 | || (ch > 47 && ch < 58)
|
5381 | || specialChars.includes(ch);
|
5382 | }
|
5383 | function isOpenBrace(ch, syntax) {
|
5384 | return ch === Brackets.RoundL || (syntax === 'markup' && (ch === Brackets.SquareL || ch === Brackets.CurlyL));
|
5385 | }
|
5386 | function isCloseBrace(ch, syntax) {
|
5387 | return ch === Brackets.RoundR || (syntax === 'markup' && (ch === Brackets.SquareR || ch === Brackets.CurlyR));
|
5388 | }
|
5389 |
|
5390 | function expandAbbreviation(abbr, config) {
|
5391 | const resolvedConfig = resolveConfig(config);
|
5392 | return resolvedConfig.type === 'stylesheet'
|
5393 | ? stylesheet(abbr, resolvedConfig)
|
5394 | : markup(abbr, resolvedConfig);
|
5395 | }
|
5396 |
|
5397 |
|
5398 |
|
5399 |
|
5400 |
|
5401 | function markup(abbr, config) {
|
5402 | return stringify(parse$1(abbr, config), config);
|
5403 | }
|
5404 |
|
5405 |
|
5406 |
|
5407 |
|
5408 |
|
5409 | function stylesheet(abbr, config) {
|
5410 | return css(parse(abbr, config), config);
|
5411 | }
|
5412 |
|
5413 | export { CSSAbbreviationScope, expandAbbreviation as default, extractAbbreviation as extract, markup, parseAbbreviation as markupAbbreviation, parse$1 as parseMarkup, parse as parseStylesheet, convertSnippets as parseStylesheetSnippets, resolveConfig, stringify as stringifyMarkup, css as stringifyStylesheet, stylesheet, parse$2 as stylesheetAbbreviation };
|
5414 |
|