@master/css 2.0.0-rc.61 → 2.0.0-rc.63
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/animation-rule.cjs +24 -0
- package/dist/animation-rule.d.ts +11 -0
- package/dist/animation-rule.mjs +22 -0
- package/dist/common.cjs +52 -1
- package/dist/common.d.ts +15 -0
- package/dist/common.mjs +46 -2
- package/dist/config/at.cjs +13 -10
- package/dist/config/at.d.ts +4 -1
- package/dist/config/at.mjs +13 -10
- package/dist/config/index.cjs +3 -0
- package/dist/config/index.d.ts +2 -1
- package/dist/config/index.mjs +3 -1
- package/dist/config/modes.d.ts +4 -2
- package/dist/config/rules.cjs +25 -13
- package/dist/config/rules.d.ts +4 -2
- package/dist/config/rules.mjs +25 -13
- package/dist/config/screens.cjs +17 -0
- package/dist/config/screens.d.ts +14 -0
- package/dist/config/screens.mjs +15 -0
- package/dist/config/selectors.cjs +11 -15
- package/dist/config/selectors.d.ts +10 -8
- package/dist/config/selectors.mjs +11 -15
- package/dist/config/utilities.cjs +3 -0
- package/dist/config/utilities.d.ts +3 -0
- package/dist/config/utilities.mjs +3 -0
- package/dist/config/variables.cjs +0 -13
- package/dist/config/variables.d.ts +0 -13
- package/dist/config/variables.mjs +0 -13
- package/dist/core.cjs +438 -476
- package/dist/core.d.ts +13 -4
- package/dist/core.mjs +438 -476
- package/dist/factories/with-syntax-layer.cjs +37 -260
- package/dist/factories/with-syntax-layer.mjs +37 -260
- package/dist/index.cjs +39 -12
- package/dist/index.d.ts +19 -7
- package/dist/index.mjs +17 -7
- package/dist/layer.cjs +11 -7
- package/dist/layer.d.ts +4 -3
- package/dist/layer.mjs +11 -7
- package/dist/non-layer.cjs +10 -17
- package/dist/non-layer.d.ts +1 -1
- package/dist/non-layer.mjs +10 -17
- package/dist/rule.cjs +4 -6
- package/dist/rule.d.ts +3 -10
- package/dist/rule.mjs +4 -6
- package/dist/syntax-rule-type.cjs +7 -8
- package/dist/syntax-rule-type.d.ts +7 -7
- package/dist/syntax-rule-type.mjs +7 -8
- package/dist/syntax-rule.cjs +116 -328
- package/dist/syntax-rule.d.ts +18 -25
- package/dist/syntax-rule.mjs +117 -329
- package/dist/types/common.d.ts +2 -0
- package/dist/types/config.d.ts +12 -7
- package/dist/types/syntax.d.ts +5 -24
- package/dist/utils/compare-rule-priority.cjs +143 -0
- package/dist/utils/compare-rule-priority.d.ts +7 -0
- package/dist/utils/compare-rule-priority.mjs +138 -0
- package/dist/utils/equal-at-rules.cjs +22 -0
- package/dist/utils/equal-at-rules.d.ts +2 -0
- package/dist/utils/equal-at-rules.mjs +20 -0
- package/dist/utils/equal-declarations.cjs +10 -0
- package/dist/utils/equal-declarations.d.ts +2 -0
- package/dist/utils/equal-declarations.mjs +8 -0
- package/dist/utils/equal-selectors.cjs +70 -0
- package/dist/utils/equal-selectors.d.ts +2 -0
- package/dist/utils/equal-selectors.mjs +68 -0
- package/dist/utils/equal-variants.cjs +10 -0
- package/dist/utils/equal-variants.d.ts +2 -0
- package/dist/utils/equal-variants.mjs +8 -0
- package/dist/utils/extend-config.cjs +0 -1
- package/dist/utils/extend-config.mjs +0 -1
- package/dist/utils/generate-at.cjs +30 -0
- package/dist/utils/generate-at.d.ts +2 -0
- package/dist/utils/generate-at.mjs +28 -0
- package/dist/utils/generate-selector.cjs +49 -0
- package/dist/utils/generate-selector.d.ts +2 -0
- package/dist/utils/generate-selector.mjs +47 -0
- package/dist/utils/get-single-at-number-rule-node.cjs +9 -0
- package/dist/utils/get-single-at-number-rule-node.d.ts +2 -0
- package/dist/utils/get-single-at-number-rule-node.mjs +7 -0
- package/dist/utils/parse-at.cjs +157 -0
- package/dist/utils/parse-at.d.ts +39 -0
- package/dist/utils/parse-at.mjs +155 -0
- package/dist/utils/parse-pair.cjs +51 -0
- package/dist/utils/parse-pair.d.ts +8 -0
- package/dist/utils/parse-pair.mjs +49 -0
- package/dist/utils/parse-selector.cjs +114 -0
- package/dist/utils/parse-selector.d.ts +19 -0
- package/dist/utils/parse-selector.mjs +112 -0
- package/dist/utils/parse-value.cjs +39 -0
- package/dist/utils/parse-value.d.ts +2 -0
- package/dist/utils/parse-value.mjs +37 -0
- package/dist/utils/replace-char-outside-quotes.cjs +21 -0
- package/dist/utils/replace-char-outside-quotes.d.ts +1 -0
- package/dist/utils/replace-char-outside-quotes.mjs +19 -0
- package/dist/utils/sort-readable-classes.cjs +86 -0
- package/dist/utils/{reorder-for-readable-classes.d.ts → sort-readable-classes.d.ts} +1 -1
- package/dist/utils/sort-readable-classes.mjs +84 -0
- package/dist/utils/split-char-outside-quotes.cjs +29 -0
- package/dist/utils/split-char-outside-quotes.d.ts +1 -0
- package/dist/utils/split-char-outside-quotes.mjs +27 -0
- package/dist/variable-rule.cjs +86 -0
- package/dist/variable-rule.d.ts +23 -0
- package/dist/variable-rule.mjs +81 -0
- package/package.json +1 -1
- package/dist/rule-node.cjs +0 -18
- package/dist/rule-node.d.ts +0 -14
- package/dist/rule-node.mjs +0 -16
- package/dist/utils/are-rule-at-equal.cjs +0 -12
- package/dist/utils/are-rule-at-equal.d.ts +0 -2
- package/dist/utils/are-rule-at-equal.mjs +0 -10
- package/dist/utils/are-rule-modes-equal.cjs +0 -7
- package/dist/utils/are-rule-modes-equal.d.ts +0 -2
- package/dist/utils/are-rule-modes-equal.mjs +0 -5
- package/dist/utils/are-rule-selectors-equal.cjs +0 -29
- package/dist/utils/are-rule-selectors-equal.d.ts +0 -2
- package/dist/utils/are-rule-selectors-equal.mjs +0 -27
- package/dist/utils/are-rule-states-equal.cjs +0 -11
- package/dist/utils/are-rule-states-equal.d.ts +0 -2
- package/dist/utils/are-rule-states-equal.mjs +0 -9
- package/dist/utils/are-rules-duplicated.cjs +0 -17
- package/dist/utils/are-rules-duplicated.d.ts +0 -2
- package/dist/utils/are-rules-duplicated.mjs +0 -15
- package/dist/utils/reorder-for-readable-classes.cjs +0 -62
- package/dist/utils/reorder-for-readable-classes.mjs +0 -60
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
// ✅ Pseudo-class priority (lower = weaker)
|
|
6
|
+
const selectorPriority = {
|
|
7
|
+
hover: 1,
|
|
8
|
+
focus: 2,
|
|
9
|
+
active: 3,
|
|
10
|
+
disabled: 4
|
|
11
|
+
};
|
|
12
|
+
function extractSelectorPriority(nodes = []) {
|
|
13
|
+
let priority = 0;
|
|
14
|
+
for (const node of nodes){
|
|
15
|
+
if ('value' in node && typeof node.value === 'string') {
|
|
16
|
+
priority += selectorPriority[node.value] ?? 0;
|
|
17
|
+
}
|
|
18
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
19
|
+
priority += extractSelectorPriority(node.children);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return priority;
|
|
23
|
+
}
|
|
24
|
+
const NOT_COMPARISON_OPERATORS = {
|
|
25
|
+
'>=': '<',
|
|
26
|
+
'<=': '>',
|
|
27
|
+
'>': '<=',
|
|
28
|
+
'<': '>='
|
|
29
|
+
};
|
|
30
|
+
function getAtRuleEntries(nestNodes) {
|
|
31
|
+
const featureMap = new Map();
|
|
32
|
+
const walk = (list, isOutsideNot = false)=>{
|
|
33
|
+
(list ?? []).forEach((node, i, arr)=>{
|
|
34
|
+
const prev = arr[i - 1];
|
|
35
|
+
if ('operator' in node) {
|
|
36
|
+
const entry = featureMap.get(node.name) ?? {};
|
|
37
|
+
let operator = node.operator;
|
|
38
|
+
if (isOutsideNot) operator = NOT_COMPARISON_OPERATORS[operator];
|
|
39
|
+
if (prev?.type === 'logical' && prev.value === 'not') operator = NOT_COMPARISON_OPERATORS[operator];
|
|
40
|
+
switch(operator){
|
|
41
|
+
case '>':
|
|
42
|
+
entry.min = node.value + 0.02;
|
|
43
|
+
break;
|
|
44
|
+
case '>=':
|
|
45
|
+
entry.min = node.value;
|
|
46
|
+
break;
|
|
47
|
+
case '<':
|
|
48
|
+
entry.max = node.value - 0.02;
|
|
49
|
+
break;
|
|
50
|
+
case '<=':
|
|
51
|
+
entry.max = node.value;
|
|
52
|
+
break;
|
|
53
|
+
}
|
|
54
|
+
featureMap.set(node.name, entry);
|
|
55
|
+
}
|
|
56
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
57
|
+
walk(node.children, prev?.type === 'logical' && prev.value === 'not');
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
walk(nestNodes);
|
|
62
|
+
return featureMap;
|
|
63
|
+
}
|
|
64
|
+
// ✅ Calculate RulePriority from AST
|
|
65
|
+
function calcRulePriority(rule) {
|
|
66
|
+
const features = [];
|
|
67
|
+
const extractFeatures = (nodes)=>{
|
|
68
|
+
const featureMap = getAtRuleEntries(nodes);
|
|
69
|
+
for (const [name, entry] of featureMap.entries()){
|
|
70
|
+
const max = entry.max ?? Number.MAX_SAFE_INTEGER;
|
|
71
|
+
const min = entry.min ?? 0;
|
|
72
|
+
features.push([
|
|
73
|
+
name,
|
|
74
|
+
min,
|
|
75
|
+
max
|
|
76
|
+
]);
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
if (rule.atRules?.media) extractFeatures(rule.atRules.media);
|
|
80
|
+
if (rule.atRules?.container) extractFeatures(rule.atRules.container);
|
|
81
|
+
features.sort(([a], [b])=>a.localeCompare(b, undefined, {
|
|
82
|
+
numeric: true
|
|
83
|
+
}));
|
|
84
|
+
const selector = extractSelectorPriority(rule.selectorNodes ?? []);
|
|
85
|
+
return {
|
|
86
|
+
features,
|
|
87
|
+
selector
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
function compareFeatureTuples(a, b) {
|
|
91
|
+
const len = Math.max(a.length, b.length);
|
|
92
|
+
for(let i = 0; i < len; i++){
|
|
93
|
+
const aa = a[i];
|
|
94
|
+
const bb = b[i];
|
|
95
|
+
if (!aa) return -1;
|
|
96
|
+
if (!bb) return 1;
|
|
97
|
+
const [nameA, minA, maxA] = aa;
|
|
98
|
+
const [nameB, minB, maxB] = bb;
|
|
99
|
+
const nameCmp = nameA.localeCompare(nameB, undefined, {
|
|
100
|
+
numeric: true
|
|
101
|
+
});
|
|
102
|
+
if (nameCmp !== 0) return nameCmp;
|
|
103
|
+
const rangeA = maxA - minA;
|
|
104
|
+
const rangeB = maxB - minB;
|
|
105
|
+
if (rangeA !== rangeB) return rangeB - rangeA;
|
|
106
|
+
if (minA !== minB) return minB - minA;
|
|
107
|
+
if (maxA !== maxB) return maxB - maxA;
|
|
108
|
+
}
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
// ✅ Compare function
|
|
112
|
+
function compareRulePriority(a, b) {
|
|
113
|
+
const getTier = (rule)=>{
|
|
114
|
+
const hasSelector = rule.selectorNodes?.length;
|
|
115
|
+
const hasAtRules = !!rule.atRules;
|
|
116
|
+
const hasMode = !!rule.mode;
|
|
117
|
+
if (hasAtRules) return 3;
|
|
118
|
+
if (hasMode) return 2;
|
|
119
|
+
if (hasSelector) return 1;
|
|
120
|
+
return 0;
|
|
121
|
+
};
|
|
122
|
+
const aTier = getTier(a);
|
|
123
|
+
const bTier = getTier(b);
|
|
124
|
+
if (aTier !== bTier) return aTier - bTier;
|
|
125
|
+
// 1. features
|
|
126
|
+
const fa = a.priority.features || [];
|
|
127
|
+
const fb = b.priority.features || [];
|
|
128
|
+
const featureCmp = compareFeatureTuples(fa, fb);
|
|
129
|
+
if (featureCmp !== 0) return featureCmp;
|
|
130
|
+
// 2. selector
|
|
131
|
+
const selectorCmp = a.priority.selector - b.priority.selector;
|
|
132
|
+
if (selectorCmp !== 0) return selectorCmp;
|
|
133
|
+
// 3. rule.type
|
|
134
|
+
const typeCmp = a.type - b.type;
|
|
135
|
+
if (typeCmp !== 0) return typeCmp;
|
|
136
|
+
// 4. fallback: name
|
|
137
|
+
return a.key.localeCompare(b.key, undefined, {
|
|
138
|
+
numeric: true
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
exports.calcRulePriority = calcRulePriority;
|
|
143
|
+
exports.default = compareRulePriority;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { SyntaxRule } from '../syntax-rule';
|
|
2
|
+
export type RulePriority = {
|
|
3
|
+
features?: [string, number, number][];
|
|
4
|
+
selector: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function calcRulePriority(rule: SyntaxRule): RulePriority;
|
|
7
|
+
export default function compareRulePriority(a: SyntaxRule, b: SyntaxRule): number;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// ✅ Pseudo-class priority (lower = weaker)
|
|
2
|
+
const selectorPriority = {
|
|
3
|
+
hover: 1,
|
|
4
|
+
focus: 2,
|
|
5
|
+
active: 3,
|
|
6
|
+
disabled: 4
|
|
7
|
+
};
|
|
8
|
+
function extractSelectorPriority(nodes = []) {
|
|
9
|
+
let priority = 0;
|
|
10
|
+
for (const node of nodes){
|
|
11
|
+
if ('value' in node && typeof node.value === 'string') {
|
|
12
|
+
priority += selectorPriority[node.value] ?? 0;
|
|
13
|
+
}
|
|
14
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
15
|
+
priority += extractSelectorPriority(node.children);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return priority;
|
|
19
|
+
}
|
|
20
|
+
const NOT_COMPARISON_OPERATORS = {
|
|
21
|
+
'>=': '<',
|
|
22
|
+
'<=': '>',
|
|
23
|
+
'>': '<=',
|
|
24
|
+
'<': '>='
|
|
25
|
+
};
|
|
26
|
+
function getAtRuleEntries(nestNodes) {
|
|
27
|
+
const featureMap = new Map();
|
|
28
|
+
const walk = (list, isOutsideNot = false)=>{
|
|
29
|
+
(list ?? []).forEach((node, i, arr)=>{
|
|
30
|
+
const prev = arr[i - 1];
|
|
31
|
+
if ('operator' in node) {
|
|
32
|
+
const entry = featureMap.get(node.name) ?? {};
|
|
33
|
+
let operator = node.operator;
|
|
34
|
+
if (isOutsideNot) operator = NOT_COMPARISON_OPERATORS[operator];
|
|
35
|
+
if (prev?.type === 'logical' && prev.value === 'not') operator = NOT_COMPARISON_OPERATORS[operator];
|
|
36
|
+
switch(operator){
|
|
37
|
+
case '>':
|
|
38
|
+
entry.min = node.value + 0.02;
|
|
39
|
+
break;
|
|
40
|
+
case '>=':
|
|
41
|
+
entry.min = node.value;
|
|
42
|
+
break;
|
|
43
|
+
case '<':
|
|
44
|
+
entry.max = node.value - 0.02;
|
|
45
|
+
break;
|
|
46
|
+
case '<=':
|
|
47
|
+
entry.max = node.value;
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
featureMap.set(node.name, entry);
|
|
51
|
+
}
|
|
52
|
+
if ('children' in node && Array.isArray(node.children)) {
|
|
53
|
+
walk(node.children, prev?.type === 'logical' && prev.value === 'not');
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
walk(nestNodes);
|
|
58
|
+
return featureMap;
|
|
59
|
+
}
|
|
60
|
+
// ✅ Calculate RulePriority from AST
|
|
61
|
+
function calcRulePriority(rule) {
|
|
62
|
+
const features = [];
|
|
63
|
+
const extractFeatures = (nodes)=>{
|
|
64
|
+
const featureMap = getAtRuleEntries(nodes);
|
|
65
|
+
for (const [name, entry] of featureMap.entries()){
|
|
66
|
+
const max = entry.max ?? Number.MAX_SAFE_INTEGER;
|
|
67
|
+
const min = entry.min ?? 0;
|
|
68
|
+
features.push([
|
|
69
|
+
name,
|
|
70
|
+
min,
|
|
71
|
+
max
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
if (rule.atRules?.media) extractFeatures(rule.atRules.media);
|
|
76
|
+
if (rule.atRules?.container) extractFeatures(rule.atRules.container);
|
|
77
|
+
features.sort(([a], [b])=>a.localeCompare(b, undefined, {
|
|
78
|
+
numeric: true
|
|
79
|
+
}));
|
|
80
|
+
const selector = extractSelectorPriority(rule.selectorNodes ?? []);
|
|
81
|
+
return {
|
|
82
|
+
features,
|
|
83
|
+
selector
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function compareFeatureTuples(a, b) {
|
|
87
|
+
const len = Math.max(a.length, b.length);
|
|
88
|
+
for(let i = 0; i < len; i++){
|
|
89
|
+
const aa = a[i];
|
|
90
|
+
const bb = b[i];
|
|
91
|
+
if (!aa) return -1;
|
|
92
|
+
if (!bb) return 1;
|
|
93
|
+
const [nameA, minA, maxA] = aa;
|
|
94
|
+
const [nameB, minB, maxB] = bb;
|
|
95
|
+
const nameCmp = nameA.localeCompare(nameB, undefined, {
|
|
96
|
+
numeric: true
|
|
97
|
+
});
|
|
98
|
+
if (nameCmp !== 0) return nameCmp;
|
|
99
|
+
const rangeA = maxA - minA;
|
|
100
|
+
const rangeB = maxB - minB;
|
|
101
|
+
if (rangeA !== rangeB) return rangeB - rangeA;
|
|
102
|
+
if (minA !== minB) return minB - minA;
|
|
103
|
+
if (maxA !== maxB) return maxB - maxA;
|
|
104
|
+
}
|
|
105
|
+
return 0;
|
|
106
|
+
}
|
|
107
|
+
// ✅ Compare function
|
|
108
|
+
function compareRulePriority(a, b) {
|
|
109
|
+
const getTier = (rule)=>{
|
|
110
|
+
const hasSelector = rule.selectorNodes?.length;
|
|
111
|
+
const hasAtRules = !!rule.atRules;
|
|
112
|
+
const hasMode = !!rule.mode;
|
|
113
|
+
if (hasAtRules) return 3;
|
|
114
|
+
if (hasMode) return 2;
|
|
115
|
+
if (hasSelector) return 1;
|
|
116
|
+
return 0;
|
|
117
|
+
};
|
|
118
|
+
const aTier = getTier(a);
|
|
119
|
+
const bTier = getTier(b);
|
|
120
|
+
if (aTier !== bTier) return aTier - bTier;
|
|
121
|
+
// 1. features
|
|
122
|
+
const fa = a.priority.features || [];
|
|
123
|
+
const fb = b.priority.features || [];
|
|
124
|
+
const featureCmp = compareFeatureTuples(fa, fb);
|
|
125
|
+
if (featureCmp !== 0) return featureCmp;
|
|
126
|
+
// 2. selector
|
|
127
|
+
const selectorCmp = a.priority.selector - b.priority.selector;
|
|
128
|
+
if (selectorCmp !== 0) return selectorCmp;
|
|
129
|
+
// 3. rule.type
|
|
130
|
+
const typeCmp = a.type - b.type;
|
|
131
|
+
if (typeCmp !== 0) return typeCmp;
|
|
132
|
+
// 4. fallback: name
|
|
133
|
+
return a.key.localeCompare(b.key, undefined, {
|
|
134
|
+
numeric: true
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export { calcRulePriority, compareRulePriority as default };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var common = require('../common.cjs');
|
|
4
|
+
|
|
5
|
+
function areNodesEqual(a, b) {
|
|
6
|
+
return a.type === b.type && a.value === b.value && a.unit === b.unit && a.name === b.name && a.operator === b.operator && areNodeArraysEqual(a.children ?? [], b.children ?? []);
|
|
7
|
+
}
|
|
8
|
+
function areNodeArraysEqual(aNodes, bNodes) {
|
|
9
|
+
if (aNodes.length !== bNodes.length) return false;
|
|
10
|
+
const matched = new Array(bNodes.length).fill(false);
|
|
11
|
+
for (const aNode of aNodes){
|
|
12
|
+
const index = bNodes.findIndex((bNode, i)=>!matched[i] && areNodesEqual(aNode, bNode));
|
|
13
|
+
if (index === -1) return false;
|
|
14
|
+
matched[index] = true;
|
|
15
|
+
}
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
function equalAtRules(a, b) {
|
|
19
|
+
return common.AT_IDENTIFIERS.every((key)=>areNodeArraysEqual(a?.[key] ?? [], b?.[key] ?? []));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
module.exports = equalAtRules;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AT_IDENTIFIERS } from '../common.mjs';
|
|
2
|
+
|
|
3
|
+
function areNodesEqual(a, b) {
|
|
4
|
+
return a.type === b.type && a.value === b.value && a.unit === b.unit && a.name === b.name && a.operator === b.operator && areNodeArraysEqual(a.children ?? [], b.children ?? []);
|
|
5
|
+
}
|
|
6
|
+
function areNodeArraysEqual(aNodes, bNodes) {
|
|
7
|
+
if (aNodes.length !== bNodes.length) return false;
|
|
8
|
+
const matched = new Array(bNodes.length).fill(false);
|
|
9
|
+
for (const aNode of aNodes){
|
|
10
|
+
const index = bNodes.findIndex((bNode, i)=>!matched[i] && areNodesEqual(aNode, bNode));
|
|
11
|
+
if (index === -1) return false;
|
|
12
|
+
matched[index] = true;
|
|
13
|
+
}
|
|
14
|
+
return true;
|
|
15
|
+
}
|
|
16
|
+
function equalAtRules(a, b) {
|
|
17
|
+
return AT_IDENTIFIERS.every((key)=>areNodeArraysEqual(a?.[key] ?? [], b?.[key] ?? []));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { equalAtRules as default };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function isCombinator(node) {
|
|
4
|
+
return node.type === 'combinator';
|
|
5
|
+
}
|
|
6
|
+
function areSelectorNodesEqual(a, b) {
|
|
7
|
+
if (a.type !== b.type) return false;
|
|
8
|
+
if (a.value !== b.value) return false;
|
|
9
|
+
const aChildren = a.children ?? [];
|
|
10
|
+
const bChildren = b.children ?? [];
|
|
11
|
+
if (aChildren.length !== bChildren.length) return false;
|
|
12
|
+
return equalUnorderedSelectorNodes(aChildren, bChildren);
|
|
13
|
+
}
|
|
14
|
+
function equalUnorderedSelectorNodes(a, b) {
|
|
15
|
+
if (a.length !== b.length) return false;
|
|
16
|
+
const unmatchedB = new Set(b);
|
|
17
|
+
for (const nodeA of a){
|
|
18
|
+
let matched = false;
|
|
19
|
+
for (const nodeB of unmatchedB){
|
|
20
|
+
if (areSelectorNodesEqual(nodeA, nodeB)) {
|
|
21
|
+
unmatchedB.delete(nodeB);
|
|
22
|
+
matched = true;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (!matched) return false;
|
|
27
|
+
}
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
function splitByCombinators(nodes) {
|
|
31
|
+
const parts = [];
|
|
32
|
+
let buffer = [];
|
|
33
|
+
for (const node of nodes){
|
|
34
|
+
if (isCombinator(node)) {
|
|
35
|
+
if (buffer.length > 0) {
|
|
36
|
+
parts.push(buffer);
|
|
37
|
+
buffer = [];
|
|
38
|
+
}
|
|
39
|
+
parts.push(node) // push combinator as-is
|
|
40
|
+
;
|
|
41
|
+
} else {
|
|
42
|
+
buffer.push(node);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (buffer.length > 0) {
|
|
46
|
+
parts.push(buffer);
|
|
47
|
+
}
|
|
48
|
+
return parts;
|
|
49
|
+
}
|
|
50
|
+
function equalSelectors(a = [], b = []) {
|
|
51
|
+
const aParts = splitByCombinators(a);
|
|
52
|
+
const bParts = splitByCombinators(b);
|
|
53
|
+
if (aParts.length !== bParts.length) return false;
|
|
54
|
+
for(let i = 0; i < aParts.length; i++){
|
|
55
|
+
const partA = aParts[i];
|
|
56
|
+
const partB = bParts[i];
|
|
57
|
+
if (Array.isArray(partA) && Array.isArray(partB)) {
|
|
58
|
+
if (!equalUnorderedSelectorNodes(partA, partB)) return false;
|
|
59
|
+
} else if (!Array.isArray(partA) && !Array.isArray(partB)) {
|
|
60
|
+
// both are combinators
|
|
61
|
+
if (!areSelectorNodesEqual(partA, partB)) return false;
|
|
62
|
+
} else {
|
|
63
|
+
return false // mismatch between combinator vs non-combinator
|
|
64
|
+
;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
module.exports = equalSelectors;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
function isCombinator(node) {
|
|
2
|
+
return node.type === 'combinator';
|
|
3
|
+
}
|
|
4
|
+
function areSelectorNodesEqual(a, b) {
|
|
5
|
+
if (a.type !== b.type) return false;
|
|
6
|
+
if (a.value !== b.value) return false;
|
|
7
|
+
const aChildren = a.children ?? [];
|
|
8
|
+
const bChildren = b.children ?? [];
|
|
9
|
+
if (aChildren.length !== bChildren.length) return false;
|
|
10
|
+
return equalUnorderedSelectorNodes(aChildren, bChildren);
|
|
11
|
+
}
|
|
12
|
+
function equalUnorderedSelectorNodes(a, b) {
|
|
13
|
+
if (a.length !== b.length) return false;
|
|
14
|
+
const unmatchedB = new Set(b);
|
|
15
|
+
for (const nodeA of a){
|
|
16
|
+
let matched = false;
|
|
17
|
+
for (const nodeB of unmatchedB){
|
|
18
|
+
if (areSelectorNodesEqual(nodeA, nodeB)) {
|
|
19
|
+
unmatchedB.delete(nodeB);
|
|
20
|
+
matched = true;
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
if (!matched) return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
function splitByCombinators(nodes) {
|
|
29
|
+
const parts = [];
|
|
30
|
+
let buffer = [];
|
|
31
|
+
for (const node of nodes){
|
|
32
|
+
if (isCombinator(node)) {
|
|
33
|
+
if (buffer.length > 0) {
|
|
34
|
+
parts.push(buffer);
|
|
35
|
+
buffer = [];
|
|
36
|
+
}
|
|
37
|
+
parts.push(node) // push combinator as-is
|
|
38
|
+
;
|
|
39
|
+
} else {
|
|
40
|
+
buffer.push(node);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
if (buffer.length > 0) {
|
|
44
|
+
parts.push(buffer);
|
|
45
|
+
}
|
|
46
|
+
return parts;
|
|
47
|
+
}
|
|
48
|
+
function equalSelectors(a = [], b = []) {
|
|
49
|
+
const aParts = splitByCombinators(a);
|
|
50
|
+
const bParts = splitByCombinators(b);
|
|
51
|
+
if (aParts.length !== bParts.length) return false;
|
|
52
|
+
for(let i = 0; i < aParts.length; i++){
|
|
53
|
+
const partA = aParts[i];
|
|
54
|
+
const partB = bParts[i];
|
|
55
|
+
if (Array.isArray(partA) && Array.isArray(partB)) {
|
|
56
|
+
if (!equalUnorderedSelectorNodes(partA, partB)) return false;
|
|
57
|
+
} else if (!Array.isArray(partA) && !Array.isArray(partB)) {
|
|
58
|
+
// both are combinators
|
|
59
|
+
if (!areSelectorNodesEqual(partA, partB)) return false;
|
|
60
|
+
} else {
|
|
61
|
+
return false // mismatch between combinator vs non-combinator
|
|
62
|
+
;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { equalSelectors as default };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var equalSelectors = require('./equal-selectors.cjs');
|
|
4
|
+
var equalAtRules = require('./equal-at-rules.cjs');
|
|
5
|
+
|
|
6
|
+
function equalVariants(a, b) {
|
|
7
|
+
return a.mode === b.mode && equalSelectors(a.selectorNodes, b.selectorNodes) && equalAtRules(a.atRules, b.atRules);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = equalVariants;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import equalSelectors from './equal-selectors.mjs';
|
|
2
|
+
import equalAtRules from './equal-at-rules.mjs';
|
|
3
|
+
|
|
4
|
+
function equalVariants(a, b) {
|
|
5
|
+
return a.mode === b.mode && equalSelectors(a.selectorNodes, b.selectorNodes) && equalAtRules(a.atRules, b.atRules);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export { equalVariants as default };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function generateAt(atRule) {
|
|
4
|
+
const generate = (nodes)=>{
|
|
5
|
+
let text = nodes.map((comp)=>{
|
|
6
|
+
let current = '';
|
|
7
|
+
if ('children' in comp) {
|
|
8
|
+
const body = generate(comp.children);
|
|
9
|
+
current = comp.type === 'group' ? '(' + body + ')' : body;
|
|
10
|
+
} else {
|
|
11
|
+
const value = comp.type === 'number' ? String(comp.value) + (comp.unit || '') : comp.value;
|
|
12
|
+
if ('name' in comp) {
|
|
13
|
+
if ('operator' in comp) {
|
|
14
|
+
current = '(' + `${comp.name}${comp.operator}${value}` + ')';
|
|
15
|
+
} else {
|
|
16
|
+
current = '(' + `${comp.name}:${value}` + ')';
|
|
17
|
+
}
|
|
18
|
+
} else {
|
|
19
|
+
current = value;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return current;
|
|
23
|
+
}).filter(Boolean).join(atRule.id === 'layer' ? '.' : ' ');
|
|
24
|
+
return text;
|
|
25
|
+
};
|
|
26
|
+
const result = generate(atRule.nodes);
|
|
27
|
+
return '@' + atRule.id + (result ? ' ' + result : '');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
module.exports = generateAt;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function generateAt(atRule) {
|
|
2
|
+
const generate = (nodes)=>{
|
|
3
|
+
let text = nodes.map((comp)=>{
|
|
4
|
+
let current = '';
|
|
5
|
+
if ('children' in comp) {
|
|
6
|
+
const body = generate(comp.children);
|
|
7
|
+
current = comp.type === 'group' ? '(' + body + ')' : body;
|
|
8
|
+
} else {
|
|
9
|
+
const value = comp.type === 'number' ? String(comp.value) + (comp.unit || '') : comp.value;
|
|
10
|
+
if ('name' in comp) {
|
|
11
|
+
if ('operator' in comp) {
|
|
12
|
+
current = '(' + `${comp.name}${comp.operator}${value}` + ')';
|
|
13
|
+
} else {
|
|
14
|
+
current = '(' + `${comp.name}:${value}` + ')';
|
|
15
|
+
}
|
|
16
|
+
} else {
|
|
17
|
+
current = value;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return current;
|
|
21
|
+
}).filter(Boolean).join(atRule.id === 'layer' ? '.' : ' ');
|
|
22
|
+
return text;
|
|
23
|
+
};
|
|
24
|
+
const result = generate(atRule.nodes);
|
|
25
|
+
return '@' + atRule.id + (result ? ' ' + result : '');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { generateAt as default };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var common = require('../common.cjs');
|
|
4
|
+
|
|
5
|
+
const prefixMap = {
|
|
6
|
+
'class': '.',
|
|
7
|
+
'pseudo-class': ':',
|
|
8
|
+
'pseudo-element': '::',
|
|
9
|
+
'attribute': '',
|
|
10
|
+
'combinator': ''
|
|
11
|
+
};
|
|
12
|
+
function generateSelector(nodes, body = '') {
|
|
13
|
+
const generate = (node)=>{
|
|
14
|
+
if (node.type === 'attribute') return `[${node.value}]`;
|
|
15
|
+
if (node.type === 'combinator') return node.value;
|
|
16
|
+
const prefix = node.type && prefixMap[node.type] || '';
|
|
17
|
+
const base = node.value ? prefix + node.value : '';
|
|
18
|
+
if ('children' in node && node.children?.length) {
|
|
19
|
+
const childrenText = node.children.map(generate).join('');
|
|
20
|
+
return node.value ? base + `(${childrenText})` : base + childrenText;
|
|
21
|
+
}
|
|
22
|
+
return base;
|
|
23
|
+
};
|
|
24
|
+
let pre = '';
|
|
25
|
+
let current = '';
|
|
26
|
+
const groups = [];
|
|
27
|
+
const flatNodes = nodes.flatMap((node)=>!('value' in node) && 'children' in node && node.children?.length ? node.children : node);
|
|
28
|
+
flatNodes.forEach((node)=>{
|
|
29
|
+
if (node.value === ',') {
|
|
30
|
+
groups.push(current);
|
|
31
|
+
current = '';
|
|
32
|
+
} else if (node.value === 'of' && 'children' in node) {
|
|
33
|
+
pre += node.children.map(generate).join('');
|
|
34
|
+
} else {
|
|
35
|
+
current += generate(node);
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
if (current) groups.push(current);
|
|
39
|
+
if (pre) {
|
|
40
|
+
const lastChar = pre.charAt(pre.length - 1);
|
|
41
|
+
if (!common.SELECTOR_COMBINATORS.includes(lastChar) && lastChar !== ' ') {
|
|
42
|
+
pre += ' ';
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const result = groups.length ? groups.map((text)=>pre + body + text).join(',') : pre + body;
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
module.exports = generateSelector;
|