1 | import { parse as convertToCSSWhatSelector } from 'css-what';
|
2 | import '../../globals';
|
3 | import { isCssVariable } from '../core/properties';
|
4 | import { isNullOrUndefined } from '../../utils/types';
|
5 | import { checkIfMediaQueryMatches } from '../../media-query-list';
|
6 | export const MEDIA_QUERY_SEPARATOR = '&&';
|
7 | var Combinator;
|
8 | (function (Combinator) {
|
9 | Combinator["descendant"] = " ";
|
10 | Combinator["child"] = ">";
|
11 | Combinator["adjacent"] = "+";
|
12 | Combinator["sibling"] = "~";
|
13 |
|
14 | Combinator["parent"] = "<";
|
15 | Combinator["column-combinator"] = "||";
|
16 | })(Combinator || (Combinator = {}));
|
17 | var AttributeSelectorOperator;
|
18 | (function (AttributeSelectorOperator) {
|
19 | AttributeSelectorOperator["exists"] = "";
|
20 | AttributeSelectorOperator["equals"] = "=";
|
21 | AttributeSelectorOperator["start"] = "^=";
|
22 | AttributeSelectorOperator["end"] = "$=";
|
23 | AttributeSelectorOperator["any"] = "*=";
|
24 | AttributeSelectorOperator["element"] = "~=";
|
25 | AttributeSelectorOperator["hyphen"] = "|=";
|
26 | })(AttributeSelectorOperator || (AttributeSelectorOperator = {}));
|
27 | var Match;
|
28 | (function (Match) {
|
29 | |
30 |
|
31 |
|
32 | Match.Dynamic = true;
|
33 | |
34 |
|
35 |
|
36 | Match.Static = false;
|
37 | })(Match || (Match = {}));
|
38 | function eachNodePreviousGeneralSibling(node, callback) {
|
39 | if (!node.parent || !node.parent.getChildIndex || !node.parent.getChildAt || !node.parent.getChildrenCount) {
|
40 | return;
|
41 | }
|
42 | const nodeIndex = node.parent.getChildIndex(node);
|
43 | if (nodeIndex === 0) {
|
44 | return;
|
45 | }
|
46 | const count = node.parent.getChildrenCount();
|
47 | let retVal = true;
|
48 | for (let i = nodeIndex - 1; i >= 0 && retVal; i--) {
|
49 | const sibling = node.parent.getChildAt(i);
|
50 | retVal = callback(sibling);
|
51 | }
|
52 | }
|
53 | function getNodePreviousDirectSibling(node) {
|
54 | if (!node.parent || !node.parent.getChildIndex || !node.parent.getChildAt) {
|
55 | return null;
|
56 | }
|
57 | const nodeIndex = node.parent.getChildIndex(node);
|
58 | if (nodeIndex === 0) {
|
59 | return null;
|
60 | }
|
61 | return node.parent.getChildAt(nodeIndex - 1);
|
62 | }
|
63 | function SelectorProperties(specificity, rarity, dynamic = false) {
|
64 | return (cls) => {
|
65 | cls.prototype.specificity = specificity;
|
66 | cls.prototype.rarity = rarity;
|
67 | cls.prototype.combinator = undefined;
|
68 | cls.prototype.dynamic = dynamic;
|
69 | return cls;
|
70 | };
|
71 | }
|
72 | function FunctionalPseudoClassProperties(specificity, rarity, pseudoSelectorListType) {
|
73 | return (cls) => {
|
74 | cls.prototype.specificity = specificity;
|
75 | cls.prototype.rarity = rarity;
|
76 | cls.prototype.combinator = undefined;
|
77 | cls.prototype.dynamic = false;
|
78 | cls.prototype.pseudoSelectorListType = pseudoSelectorListType;
|
79 | return cls;
|
80 | };
|
81 | }
|
82 | export class SelectorBase {
|
83 | }
|
84 | let SelectorCore = class SelectorCore extends SelectorBase {
|
85 | lookupSort(sorter, base) {
|
86 | sorter.sortAsUniversal(base || this);
|
87 | }
|
88 | };
|
89 | SelectorCore = __decorate([
|
90 | SelectorProperties(0 , 0 , Match.Static)
|
91 | ], SelectorCore);
|
92 | export { SelectorCore };
|
93 | export class SimpleSelector extends SelectorCore {
|
94 | accumulateChanges(node, map) {
|
95 | if (!this.dynamic) {
|
96 | return this.match(node);
|
97 | }
|
98 | else if (this.mayMatch(node)) {
|
99 | this.trackChanges(node, map);
|
100 | return true;
|
101 | }
|
102 | return false;
|
103 | }
|
104 | mayMatch(node) {
|
105 | return this.match(node);
|
106 | }
|
107 | trackChanges(node, map) {
|
108 |
|
109 |
|
110 | }
|
111 | }
|
112 | function wrap(text) {
|
113 | return text ? ` ${text} ` : '';
|
114 | }
|
115 | let InvalidSelector = class InvalidSelector extends SimpleSelector {
|
116 | constructor(e) {
|
117 | super();
|
118 | this.e = e;
|
119 | }
|
120 | toString() {
|
121 | return `<${this.e}>`;
|
122 | }
|
123 | match(node) {
|
124 | return false;
|
125 | }
|
126 | lookupSort(sorter, base) {
|
127 |
|
128 |
|
129 |
|
130 | }
|
131 | };
|
132 | InvalidSelector = __decorate([
|
133 | SelectorProperties(0 , 4 , Match.Static),
|
134 | __metadata("design:paramtypes", [Error])
|
135 | ], InvalidSelector);
|
136 | export { InvalidSelector };
|
137 | let UniversalSelector = class UniversalSelector extends SimpleSelector {
|
138 | toString() {
|
139 | return `*${wrap(this.combinator)}`;
|
140 | }
|
141 | match(node) {
|
142 | return true;
|
143 | }
|
144 | };
|
145 | UniversalSelector = __decorate([
|
146 | SelectorProperties(0 , 0 , Match.Static)
|
147 | ], UniversalSelector);
|
148 | export { UniversalSelector };
|
149 | let IdSelector = class IdSelector extends SimpleSelector {
|
150 | constructor(id) {
|
151 | super();
|
152 | this.id = id;
|
153 | }
|
154 | toString() {
|
155 | return `#${this.id}${wrap(this.combinator)}`;
|
156 | }
|
157 | match(node) {
|
158 | return node.id === this.id;
|
159 | }
|
160 | lookupSort(sorter, base) {
|
161 | sorter.sortById(this.id, base || this);
|
162 | }
|
163 | };
|
164 | IdSelector = __decorate([
|
165 | SelectorProperties(100 , 3 , Match.Static),
|
166 | __metadata("design:paramtypes", [String])
|
167 | ], IdSelector);
|
168 | export { IdSelector };
|
169 | let TypeSelector = class TypeSelector extends SimpleSelector {
|
170 | constructor(cssType) {
|
171 | super();
|
172 | this.cssType = cssType;
|
173 | }
|
174 | toString() {
|
175 | return `${this.cssType}${wrap(this.combinator)}`;
|
176 | }
|
177 | match(node) {
|
178 | return node.cssType === this.cssType;
|
179 | }
|
180 | lookupSort(sorter, base) {
|
181 | sorter.sortByType(this.cssType, base || this);
|
182 | }
|
183 | };
|
184 | TypeSelector = __decorate([
|
185 | SelectorProperties(1 , 1 , Match.Static),
|
186 | __metadata("design:paramtypes", [String])
|
187 | ], TypeSelector);
|
188 | export { TypeSelector };
|
189 | let ClassSelector = class ClassSelector extends SimpleSelector {
|
190 | constructor(cssClass) {
|
191 | super();
|
192 | this.cssClass = cssClass;
|
193 | }
|
194 | toString() {
|
195 | return `.${this.cssClass}${wrap(this.combinator)}`;
|
196 | }
|
197 | match(node) {
|
198 | return node.cssClasses && node.cssClasses.has(this.cssClass);
|
199 | }
|
200 | lookupSort(sorter, base) {
|
201 | sorter.sortByClass(this.cssClass, base || this);
|
202 | }
|
203 | };
|
204 | ClassSelector = __decorate([
|
205 | SelectorProperties(10 , 2 , Match.Static),
|
206 | __metadata("design:paramtypes", [String])
|
207 | ], ClassSelector);
|
208 | export { ClassSelector };
|
209 | let AttributeSelector = class AttributeSelector extends SimpleSelector {
|
210 | constructor(attribute, test, value, ignoreCase) {
|
211 | super();
|
212 | this.attribute = attribute;
|
213 | this.test = test;
|
214 | this.value = value;
|
215 | this.ignoreCase = ignoreCase;
|
216 | }
|
217 | toString() {
|
218 | return `[${this.attribute}${wrap(AttributeSelectorOperator[this.test] ?? this.test)}${this.value || ''}]${wrap(this.combinator)}`;
|
219 | }
|
220 | match(node) {
|
221 | let attr = node[this.attribute];
|
222 | if (this.test === 'exists') {
|
223 | return !isNullOrUndefined(attr);
|
224 | }
|
225 | if (!this.value) {
|
226 | return false;
|
227 | }
|
228 |
|
229 | attr += '';
|
230 | if (this.ignoreCase) {
|
231 | attr = attr.toLowerCase();
|
232 | this.value = this.value.toLowerCase();
|
233 | }
|
234 |
|
235 | if (this.test === 'equals') {
|
236 | return attr === this.value;
|
237 | }
|
238 |
|
239 | if (this.test === 'start') {
|
240 | return attr.startsWith(this.value);
|
241 | }
|
242 |
|
243 | if (this.test === 'end') {
|
244 | return attr.endsWith(this.value);
|
245 | }
|
246 |
|
247 | if (this.test === 'any') {
|
248 | return attr.indexOf(this.value) !== -1;
|
249 | }
|
250 |
|
251 | if (this.test === 'element') {
|
252 | const words = attr.split(' ');
|
253 | return words && words.indexOf(this.value) !== -1;
|
254 | }
|
255 |
|
256 | if (this.test === 'hyphen') {
|
257 | return attr === this.value || attr.startsWith(this.value + '-');
|
258 | }
|
259 | return false;
|
260 | }
|
261 | mayMatch(node) {
|
262 | return true;
|
263 | }
|
264 | trackChanges(node, map) {
|
265 | map.addAttribute(node, this.attribute);
|
266 | }
|
267 | };
|
268 | AttributeSelector = __decorate([
|
269 | SelectorProperties(10 , 0 , Match.Dynamic),
|
270 | __metadata("design:paramtypes", [String, String, String, Boolean])
|
271 | ], AttributeSelector);
|
272 | export { AttributeSelector };
|
273 | let PseudoClassSelector = class PseudoClassSelector extends SimpleSelector {
|
274 | constructor(cssPseudoClass) {
|
275 | super();
|
276 | this.cssPseudoClass = cssPseudoClass;
|
277 | }
|
278 | toString() {
|
279 | return `:${this.cssPseudoClass}${wrap(this.combinator)}`;
|
280 | }
|
281 | match(node) {
|
282 | return node.cssPseudoClasses && node.cssPseudoClasses.has(this.cssPseudoClass);
|
283 | }
|
284 | mayMatch(node) {
|
285 | return true;
|
286 | }
|
287 | trackChanges(node, map) {
|
288 | map.addPseudoClass(node, this.cssPseudoClass);
|
289 | }
|
290 | };
|
291 | PseudoClassSelector = __decorate([
|
292 | SelectorProperties(10 , 0 , Match.Dynamic),
|
293 | __metadata("design:paramtypes", [String])
|
294 | ], PseudoClassSelector);
|
295 | export { PseudoClassSelector };
|
296 | export class FunctionalPseudoClassSelector extends PseudoClassSelector {
|
297 | constructor(cssPseudoClass, dataType) {
|
298 | super(cssPseudoClass);
|
299 | const selectors = [];
|
300 | const needsHighestSpecificity = this.specificity === -1 ;
|
301 | let specificity = 0;
|
302 | if (Array.isArray(dataType)) {
|
303 | for (const asts of dataType) {
|
304 | const selector = createSelectorFromAst(asts);
|
305 | if (selector instanceof InvalidSelector) {
|
306 |
|
307 | if (this.selectorListType !== 1 ) {
|
308 | selectors.splice(0);
|
309 | specificity = 0;
|
310 | break;
|
311 | }
|
312 | continue;
|
313 | }
|
314 |
|
315 | if (needsHighestSpecificity && selector.specificity > specificity) {
|
316 | specificity = selector.specificity;
|
317 | }
|
318 | selectors.push(selector);
|
319 | }
|
320 | }
|
321 | this.selectors = selectors;
|
322 | this.specificity = specificity;
|
323 |
|
324 | this.dynamic = this.selectors.some((sel) => sel.dynamic);
|
325 | }
|
326 | toString() {
|
327 | return `:${this.cssPseudoClass}(${this.selectors.join(', ')})${wrap(this.combinator)}`;
|
328 | }
|
329 | match(node) {
|
330 | return false;
|
331 | }
|
332 | mayMatch(node) {
|
333 | return true;
|
334 | }
|
335 | trackChanges(node, map) {
|
336 | this.selectors.forEach((sel) => sel.trackChanges(node, map));
|
337 | }
|
338 | }
|
339 | let NotFunctionalPseudoClassSelector = class NotFunctionalPseudoClassSelector extends FunctionalPseudoClassSelector {
|
340 | match(node) {
|
341 | return !this.selectors.some((sel) => sel.match(node));
|
342 | }
|
343 | };
|
344 | NotFunctionalPseudoClassSelector = __decorate([
|
345 | FunctionalPseudoClassProperties(-1 , 0 , 0 )
|
346 | ], NotFunctionalPseudoClassSelector);
|
347 | export { NotFunctionalPseudoClassSelector };
|
348 | let IsFunctionalPseudoClassSelector = class IsFunctionalPseudoClassSelector extends FunctionalPseudoClassSelector {
|
349 | match(node) {
|
350 | return this.selectors.some((sel) => sel.match(node));
|
351 | }
|
352 | lookupSort(sorter, base) {
|
353 |
|
354 | if (this.selectors.length === 1) {
|
355 | this.selectors[0].lookupSort(sorter, base || this);
|
356 | }
|
357 | else {
|
358 | super.lookupSort(sorter, base || this);
|
359 | }
|
360 | }
|
361 | };
|
362 | IsFunctionalPseudoClassSelector = __decorate([
|
363 | FunctionalPseudoClassProperties(-1 , 0 , 1 )
|
364 | ], IsFunctionalPseudoClassSelector);
|
365 | export { IsFunctionalPseudoClassSelector };
|
366 | let WhereFunctionalPseudoClassSelector = class WhereFunctionalPseudoClassSelector extends FunctionalPseudoClassSelector {
|
367 | match(node) {
|
368 | return this.selectors.some((sel) => sel.match(node));
|
369 | }
|
370 | lookupSort(sorter, base) {
|
371 |
|
372 | if (this.selectors.length === 1) {
|
373 | this.selectors[0].lookupSort(sorter, base || this);
|
374 | }
|
375 | else {
|
376 | super.lookupSort(sorter, base || this);
|
377 | }
|
378 | }
|
379 | };
|
380 | WhereFunctionalPseudoClassSelector = __decorate([
|
381 | FunctionalPseudoClassProperties(0 , 0 , 1 )
|
382 | ], WhereFunctionalPseudoClassSelector);
|
383 | export { WhereFunctionalPseudoClassSelector };
|
384 | export class SimpleSelectorSequence extends SimpleSelector {
|
385 | constructor(selectors) {
|
386 | super();
|
387 | this.selectors = selectors;
|
388 | this.specificity = selectors.reduce((sum, sel) => sel.specificity + sum, 0);
|
389 | this.head = selectors.reduce((prev, curr) => (!prev || curr.rarity > prev.rarity ? curr : prev), null);
|
390 | this.dynamic = selectors.some((sel) => sel.dynamic);
|
391 | }
|
392 | toString() {
|
393 | return `${this.selectors.join('')}${wrap(this.combinator)}`;
|
394 | }
|
395 | match(node) {
|
396 | return this.selectors.every((sel) => sel.match(node));
|
397 | }
|
398 | mayMatch(node) {
|
399 | return this.selectors.every((sel) => sel.mayMatch(node));
|
400 | }
|
401 | trackChanges(node, map) {
|
402 | this.selectors.forEach((sel) => sel.trackChanges(node, map));
|
403 | }
|
404 | lookupSort(sorter, base) {
|
405 | this.head.lookupSort(sorter, base || this);
|
406 | }
|
407 | }
|
408 | export class ComplexSelector extends SelectorCore {
|
409 | constructor(selectors) {
|
410 | super();
|
411 | this.selectors = selectors;
|
412 | let siblingsToGroup;
|
413 | let currentGroup;
|
414 | const groups = [];
|
415 | this.specificity = 0;
|
416 | this.dynamic = false;
|
417 | for (let i = selectors.length - 1; i >= 0; i--) {
|
418 | const sel = selectors[i];
|
419 | switch (sel.combinator) {
|
420 | case undefined:
|
421 | case Combinator.descendant:
|
422 | siblingsToGroup = [];
|
423 | currentGroup = [siblingsToGroup];
|
424 | groups.push(currentGroup);
|
425 | break;
|
426 | case Combinator.child:
|
427 | siblingsToGroup = [];
|
428 | currentGroup.push(siblingsToGroup);
|
429 | break;
|
430 | case Combinator.adjacent:
|
431 | case Combinator.sibling:
|
432 | break;
|
433 | default:
|
434 | throw new Error(`Unsupported combinator "${sel.combinator}" for selector ${sel}.`);
|
435 | }
|
436 | this.specificity += sel.specificity;
|
437 | if (sel.dynamic) {
|
438 | this.dynamic = true;
|
439 | }
|
440 | siblingsToGroup.push(sel);
|
441 | }
|
442 | this.groups = groups.map((g) => new Selector.ChildGroup(g.map((selectors) => (selectors.length > 1 ? new Selector.SiblingGroup(selectors) : selectors[0]))));
|
443 | this.last = selectors[selectors.length - 1];
|
444 | }
|
445 | toString() {
|
446 | return this.selectors.join('');
|
447 | }
|
448 | match(node) {
|
449 | return this.groups.every((group, i) => {
|
450 | if (i === 0) {
|
451 | node = group.getMatchingNode(node, true);
|
452 | return !!node;
|
453 | }
|
454 | else {
|
455 | let ancestor = node;
|
456 | while ((ancestor = ancestor.parent ?? ancestor._modalParent)) {
|
457 | if ((node = group.getMatchingNode(ancestor, true))) {
|
458 | return true;
|
459 | }
|
460 | }
|
461 | return false;
|
462 | }
|
463 | });
|
464 | }
|
465 | mayMatch(node) {
|
466 | return false;
|
467 | }
|
468 | trackChanges(node, map) {
|
469 | this.selectors.forEach((sel) => sel.trackChanges(node, map));
|
470 | }
|
471 | lookupSort(sorter, base) {
|
472 | this.last.lookupSort(sorter, base || this);
|
473 | }
|
474 | accumulateChanges(node, map) {
|
475 | if (!this.dynamic) {
|
476 | return this.match(node);
|
477 | }
|
478 | const bounds = [];
|
479 | const mayMatch = this.groups.every((group, i) => {
|
480 | if (i === 0) {
|
481 | const nextNode = group.getMatchingNode(node, false);
|
482 | bounds.push({ left: node, right: node });
|
483 | node = nextNode;
|
484 | return !!node;
|
485 | }
|
486 | else {
|
487 | let ancestor = node;
|
488 | while ((ancestor = ancestor.parent)) {
|
489 | const nextNode = group.getMatchingNode(ancestor, false);
|
490 | if (nextNode) {
|
491 | bounds.push({ left: ancestor, right: null });
|
492 | node = nextNode;
|
493 | return true;
|
494 | }
|
495 | }
|
496 | return false;
|
497 | }
|
498 | });
|
499 |
|
500 | if (!mayMatch) {
|
501 | return false;
|
502 | }
|
503 | if (!map) {
|
504 | return mayMatch;
|
505 | }
|
506 | for (let i = 0; i < this.groups.length; i++) {
|
507 | const group = this.groups[i];
|
508 | if (!group.dynamic) {
|
509 | continue;
|
510 | }
|
511 | const bound = bounds[i];
|
512 | let node = bound.left;
|
513 | do {
|
514 | if (group.mayMatch(node)) {
|
515 | group.trackChanges(node, map);
|
516 | }
|
517 | } while (node !== bound.right && (node = node.parent));
|
518 | }
|
519 | return mayMatch;
|
520 | }
|
521 | }
|
522 | export var Selector;
|
523 | (function (Selector) {
|
524 |
|
525 | class ChildGroup extends SelectorBase {
|
526 | constructor(selectors) {
|
527 | super();
|
528 | this.selectors = selectors;
|
529 | this.dynamic = selectors.some((sel) => sel.dynamic);
|
530 | }
|
531 | getMatchingNode(node, strict) {
|
532 | const funcName = strict ? 'match' : 'mayMatch';
|
533 | return this.selectors.every((sel, i) => (node = i === 0 ? node : node.parent) && sel[funcName](node)) ? node : null;
|
534 | }
|
535 | match(node) {
|
536 | return this.getMatchingNode(node, true) != null;
|
537 | }
|
538 | mayMatch(node) {
|
539 | return this.getMatchingNode(node, false) != null;
|
540 | }
|
541 | trackChanges(node, map) {
|
542 | this.selectors.forEach((sel, i) => {
|
543 | if (i === 0) {
|
544 | node && sel.trackChanges(node, map);
|
545 | }
|
546 | else {
|
547 | node = node.parent;
|
548 | if (node && sel.mayMatch(node)) {
|
549 | sel.trackChanges(node, map);
|
550 | }
|
551 | }
|
552 | });
|
553 | }
|
554 | }
|
555 | Selector.ChildGroup = ChildGroup;
|
556 | class SiblingGroup extends SelectorBase {
|
557 | constructor(selectors) {
|
558 | super();
|
559 | this.selectors = selectors;
|
560 | this.dynamic = selectors.some((sel) => sel.dynamic);
|
561 | }
|
562 | match(node) {
|
563 | return this.selectors.every((sel, i) => {
|
564 | if (i === 0) {
|
565 | return node && sel.match(node);
|
566 | }
|
567 | if (sel.combinator === Combinator.adjacent) {
|
568 | node = getNodePreviousDirectSibling(node);
|
569 | return node && sel.match(node);
|
570 | }
|
571 |
|
572 | let isMatching = false;
|
573 | eachNodePreviousGeneralSibling(node, (sibling) => {
|
574 | isMatching = sel.match(sibling);
|
575 | return !isMatching;
|
576 | });
|
577 | return isMatching;
|
578 | });
|
579 | }
|
580 | mayMatch(node) {
|
581 | return this.selectors.every((sel, i) => {
|
582 | if (i === 0) {
|
583 | return node && sel.mayMatch(node);
|
584 | }
|
585 | if (sel.combinator === Combinator.adjacent) {
|
586 | node = getNodePreviousDirectSibling(node);
|
587 | return node && sel.mayMatch(node);
|
588 | }
|
589 |
|
590 | let isMatching = false;
|
591 | eachNodePreviousGeneralSibling(node, (sibling) => {
|
592 | isMatching = sel.mayMatch(sibling);
|
593 | return !isMatching;
|
594 | });
|
595 | return isMatching;
|
596 | });
|
597 | }
|
598 | trackChanges(node, map) {
|
599 | this.selectors.forEach((sel, i) => {
|
600 | if (i === 0) {
|
601 | if (node) {
|
602 | sel.trackChanges(node, map);
|
603 | }
|
604 | }
|
605 | else {
|
606 | if (sel.combinator === Combinator.adjacent) {
|
607 | node = getNodePreviousDirectSibling(node);
|
608 | if (node && sel.mayMatch(node)) {
|
609 | sel.trackChanges(node, map);
|
610 | }
|
611 | }
|
612 | else {
|
613 |
|
614 | let matchingSibling;
|
615 | eachNodePreviousGeneralSibling(node, (sibling) => {
|
616 | const isMatching = sel.mayMatch(sibling);
|
617 | if (isMatching) {
|
618 | matchingSibling = sibling;
|
619 | }
|
620 | return !isMatching;
|
621 | });
|
622 | if (matchingSibling) {
|
623 | sel.trackChanges(matchingSibling, map);
|
624 | }
|
625 | }
|
626 | }
|
627 | });
|
628 | }
|
629 | }
|
630 | Selector.SiblingGroup = SiblingGroup;
|
631 | })(Selector || (Selector = {}));
|
632 | export class RuleSet {
|
633 | constructor(selectors, declarations) {
|
634 | this.selectors = selectors;
|
635 | this.declarations = declarations;
|
636 | this.selectors.forEach((sel) => (sel.ruleset = this));
|
637 | }
|
638 | toString() {
|
639 | let desc = `${this.selectors.join(', ')} {${this.declarations.map((d, i) => `${i === 0 ? ' ' : ''}${d.property}: ${d.value}`).join('; ')} }`;
|
640 | if (this.mediaQueryString) {
|
641 | desc = `@media ${this.mediaQueryString} { ${desc} }`;
|
642 | }
|
643 | return desc;
|
644 | }
|
645 | lookupSort(sorter) {
|
646 | this.selectors.forEach((sel) => sel.lookupSort(sorter));
|
647 | }
|
648 | }
|
649 | export function fromAstNode(astRule) {
|
650 | const declarations = astRule.declarations.filter(isDeclaration).map(createDeclaration);
|
651 | const selectors = astRule.selectors.map(createSelector);
|
652 | return new RuleSet(selectors, declarations);
|
653 | }
|
654 | function createDeclaration(decl) {
|
655 | return { property: isCssVariable(decl.property) ? decl.property : decl.property.toLowerCase(), value: decl.value };
|
656 | }
|
657 | function createSimpleSelectorFromAst(ast) {
|
658 | if (ast.type === 'attribute') {
|
659 | if (ast.name === 'class') {
|
660 | return new ClassSelector(ast.value);
|
661 | }
|
662 | if (ast.name === 'id') {
|
663 | return new IdSelector(ast.value);
|
664 | }
|
665 | return new AttributeSelector(ast.name, ast.action, ast.value, !!ast.ignoreCase);
|
666 | }
|
667 | if (ast.type === 'tag') {
|
668 | return new TypeSelector(ast.name.replace('-', '').toLowerCase());
|
669 | }
|
670 | if (ast.type === 'pseudo') {
|
671 | if (ast.name === 'is') {
|
672 | return new IsFunctionalPseudoClassSelector(ast.name, ast.data);
|
673 | }
|
674 | if (ast.name === 'where') {
|
675 | return new WhereFunctionalPseudoClassSelector(ast.name, ast.data);
|
676 | }
|
677 | if (ast.name === 'not') {
|
678 | return new NotFunctionalPseudoClassSelector(ast.name, ast.data);
|
679 | }
|
680 | return new PseudoClassSelector(ast.name);
|
681 | }
|
682 | if (ast.type === 'universal') {
|
683 | return new UniversalSelector();
|
684 | }
|
685 | return new InvalidSelector(new Error(ast.type));
|
686 | }
|
687 | function createSimpleSelectorSequenceFromAst(asts) {
|
688 | if (asts.length === 0) {
|
689 | return new InvalidSelector(new Error('Empty simple selector sequence.'));
|
690 | }
|
691 | if (asts.length === 1) {
|
692 | return createSimpleSelectorFromAst(asts[0]);
|
693 | }
|
694 | const sequenceSelectors = [];
|
695 | for (const ast of asts) {
|
696 | const selector = createSimpleSelectorFromAst(ast);
|
697 | if (selector instanceof InvalidSelector) {
|
698 | return selector;
|
699 | }
|
700 | sequenceSelectors.push(selector);
|
701 | }
|
702 | return new SimpleSelectorSequence(sequenceSelectors);
|
703 | }
|
704 | function createSelectorFromAst(asts) {
|
705 | let result;
|
706 | if (asts.length === 0) {
|
707 | return new InvalidSelector(new Error('Empty selector.'));
|
708 | }
|
709 | if (asts.length === 1) {
|
710 | return createSimpleSelectorFromAst(asts[0]);
|
711 | }
|
712 | const simpleSelectorSequences = [];
|
713 | let sequenceAsts = [];
|
714 | let combinatorCount = 0;
|
715 | for (const ast of asts) {
|
716 | const combinator = Combinator[ast.type];
|
717 |
|
718 | if (combinator != null) {
|
719 | const selector = createSimpleSelectorSequenceFromAst(sequenceAsts);
|
720 | if (selector instanceof InvalidSelector) {
|
721 | return selector;
|
722 | }
|
723 | selector.combinator = combinator;
|
724 | simpleSelectorSequences.push(selector);
|
725 | combinatorCount++;
|
726 |
|
727 | sequenceAsts = [];
|
728 | }
|
729 | else {
|
730 | sequenceAsts.push(ast);
|
731 | }
|
732 | }
|
733 | if (combinatorCount > 0) {
|
734 |
|
735 | if (sequenceAsts.length) {
|
736 | const selector = createSimpleSelectorSequenceFromAst(sequenceAsts);
|
737 | if (selector instanceof InvalidSelector) {
|
738 | return selector;
|
739 | }
|
740 | simpleSelectorSequences.push(selector);
|
741 | }
|
742 | return new ComplexSelector(simpleSelectorSequences);
|
743 | }
|
744 | return createSimpleSelectorSequenceFromAst(sequenceAsts);
|
745 | }
|
746 | export function createSelector(sel) {
|
747 | try {
|
748 | const result = convertToCSSWhatSelector(sel);
|
749 | if (!result?.length) {
|
750 | return new InvalidSelector(new Error('Empty selector'));
|
751 | }
|
752 | return createSelectorFromAst(result[0]);
|
753 | }
|
754 | catch (e) {
|
755 | return new InvalidSelector(e);
|
756 | }
|
757 | }
|
758 | function isDeclaration(node) {
|
759 | return node.type === 'declaration';
|
760 | }
|
761 | export function matchMediaQueryString(mediaQueryString, cachedQueries) {
|
762 |
|
763 | const mediaQueryStrings = mediaQueryString.split(MEDIA_QUERY_SEPARATOR);
|
764 | return mediaQueryStrings.every((mq) => {
|
765 | let isMatching;
|
766 |
|
767 | if (cachedQueries.includes(mq)) {
|
768 | isMatching = true;
|
769 | }
|
770 | else {
|
771 | isMatching = checkIfMediaQueryMatches(mq);
|
772 | if (isMatching) {
|
773 | cachedQueries.push(mq);
|
774 | }
|
775 | }
|
776 | return isMatching;
|
777 | });
|
778 | }
|
779 | export class SelectorScope {
|
780 | constructor() {
|
781 | this.id = {};
|
782 | this.class = {};
|
783 | this.type = {};
|
784 | this.universal = [];
|
785 | this.position = 0;
|
786 | }
|
787 | getSelectorCandidates(node) {
|
788 | const { cssClasses, id, cssType } = node;
|
789 | const selectorClasses = [this.universal, this.id[id], this.type[cssType]];
|
790 | if (cssClasses && cssClasses.size) {
|
791 | cssClasses.forEach((c) => selectorClasses.push(this.class[c]));
|
792 | }
|
793 | return selectorClasses.reduce((cur, next) => cur.concat(next || []), []);
|
794 | }
|
795 | sortById(id, sel) {
|
796 | this.addToMap(this.id, id, sel);
|
797 | }
|
798 | sortByClass(cssClass, sel) {
|
799 | this.addToMap(this.class, cssClass, sel);
|
800 | }
|
801 | sortByType(cssType, sel) {
|
802 | this.addToMap(this.type, cssType, sel);
|
803 | }
|
804 | sortAsUniversal(sel) {
|
805 | this.universal.push(this.makeDocSelector(sel));
|
806 | }
|
807 | addToMap(map, head, sel) {
|
808 | if (!map[head]) {
|
809 | map[head] = [];
|
810 | }
|
811 | map[head].push(this.makeDocSelector(sel));
|
812 | }
|
813 | makeDocSelector(sel) {
|
814 | sel.pos = this.position++;
|
815 | return sel;
|
816 | }
|
817 | }
|
818 | export class MediaQuerySelectorScope extends SelectorScope {
|
819 | constructor(mediaQueryString) {
|
820 | super();
|
821 | this._mediaQueryString = mediaQueryString;
|
822 | }
|
823 | get mediaQueryString() {
|
824 | return this._mediaQueryString;
|
825 | }
|
826 | }
|
827 | export class StyleSheetSelectorScope extends SelectorScope {
|
828 | constructor(rulesets) {
|
829 | super();
|
830 | this.lookupRulesets(rulesets);
|
831 | }
|
832 | createMediaQuerySelectorScope(mediaQueryString) {
|
833 | const selectorScope = new MediaQuerySelectorScope(mediaQueryString);
|
834 | selectorScope.position = this.position;
|
835 | if (this.mediaQuerySelectorScopes) {
|
836 | this.mediaQuerySelectorScopes.push(selectorScope);
|
837 | }
|
838 | else {
|
839 | this.mediaQuerySelectorScopes = [selectorScope];
|
840 | }
|
841 | return selectorScope;
|
842 | }
|
843 | lookupRulesets(rulesets) {
|
844 | let lastMediaSelectorScope;
|
845 | for (let i = 0, length = rulesets.length; i < length; i++) {
|
846 | const ruleset = rulesets[i];
|
847 | if (lastMediaSelectorScope && lastMediaSelectorScope.mediaQueryString !== ruleset.mediaQueryString) {
|
848 |
|
849 | this.position = lastMediaSelectorScope.position;
|
850 | lastMediaSelectorScope = null;
|
851 | }
|
852 | if (ruleset.mediaQueryString) {
|
853 |
|
854 | if (!lastMediaSelectorScope) {
|
855 | lastMediaSelectorScope = this.createMediaQuerySelectorScope(ruleset.mediaQueryString);
|
856 | }
|
857 | ruleset.lookupSort(lastMediaSelectorScope);
|
858 | }
|
859 | else {
|
860 | ruleset.lookupSort(this);
|
861 | }
|
862 | }
|
863 |
|
864 | if (lastMediaSelectorScope) {
|
865 | this.position = lastMediaSelectorScope.position;
|
866 | lastMediaSelectorScope = null;
|
867 | }
|
868 | }
|
869 | query(node) {
|
870 | const selectorsMatch = new SelectorsMatch();
|
871 | const selectors = this.getSelectorCandidates(node);
|
872 |
|
873 | if (this.mediaQuerySelectorScopes) {
|
874 |
|
875 | const validatedMediaQueries = [];
|
876 | for (let i = 0, length = this.mediaQuerySelectorScopes.length; i < length; i++) {
|
877 | const selectorScope = this.mediaQuerySelectorScopes[i];
|
878 | const isMatchingAllQueries = matchMediaQueryString(selectorScope.mediaQueryString, validatedMediaQueries);
|
879 | if (isMatchingAllQueries) {
|
880 | const mediaQuerySelectors = selectorScope.getSelectorCandidates(node);
|
881 | selectors.push(...mediaQuerySelectors);
|
882 | }
|
883 | }
|
884 | }
|
885 | selectorsMatch.selectors = selectors.filter((sel) => sel.accumulateChanges(node, selectorsMatch)).sort((a, b) => a.specificity - b.specificity || a.pos - b.pos);
|
886 | return selectorsMatch;
|
887 | }
|
888 | }
|
889 | export class SelectorsMatch {
|
890 | constructor() {
|
891 | this.changeMap = new Map();
|
892 | }
|
893 | addAttribute(node, attribute) {
|
894 | const deps = this.properties(node);
|
895 | if (!deps.attributes) {
|
896 | deps.attributes = new Set();
|
897 | }
|
898 | deps.attributes.add(attribute);
|
899 | }
|
900 | addPseudoClass(node, pseudoClass) {
|
901 | const deps = this.properties(node);
|
902 | if (!deps.pseudoClasses) {
|
903 | deps.pseudoClasses = new Set();
|
904 | }
|
905 | deps.pseudoClasses.add(pseudoClass);
|
906 | }
|
907 | properties(node) {
|
908 | let set = this.changeMap.get(node);
|
909 | if (!set) {
|
910 | this.changeMap.set(node, (set = {}));
|
911 | }
|
912 | return set;
|
913 | }
|
914 | }
|
915 | export const CSSHelper = {
|
916 | createSelector,
|
917 | SelectorCore,
|
918 | SimpleSelector,
|
919 | InvalidSelector,
|
920 | UniversalSelector,
|
921 | TypeSelector,
|
922 | ClassSelector,
|
923 | AttributeSelector,
|
924 | PseudoClassSelector,
|
925 | SimpleSelectorSequence,
|
926 | Selector,
|
927 | RuleSet,
|
928 | SelectorScope,
|
929 | MediaQuerySelectorScope,
|
930 | StyleSheetSelectorScope,
|
931 | fromAstNode,
|
932 | SelectorsMatch,
|
933 | };
|
934 |
|
\ | No newline at end of file |