@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
package/dist/core.mjs
CHANGED
|
@@ -9,6 +9,9 @@ import Layer from './layer.mjs';
|
|
|
9
9
|
import SyntaxLayer from './syntax-layer.mjs';
|
|
10
10
|
import NonLayer from './non-layer.mjs';
|
|
11
11
|
import registerGlobal from './register-global.mjs';
|
|
12
|
+
import parseAt from './utils/parse-at.mjs';
|
|
13
|
+
import parseValue from './utils/parse-value.mjs';
|
|
14
|
+
import parseSelector from './utils/parse-selector.mjs';
|
|
12
15
|
|
|
13
16
|
class MasterCSS {
|
|
14
17
|
customConfig;
|
|
@@ -17,6 +20,7 @@ class MasterCSS {
|
|
|
17
20
|
config;
|
|
18
21
|
layerStatementRule;
|
|
19
22
|
rules;
|
|
23
|
+
classRules;
|
|
20
24
|
animationsNonLayer;
|
|
21
25
|
baseLayer;
|
|
22
26
|
themeLayer;
|
|
@@ -26,19 +30,16 @@ class MasterCSS {
|
|
|
26
30
|
components;
|
|
27
31
|
selectors;
|
|
28
32
|
variables;
|
|
29
|
-
|
|
33
|
+
atRules;
|
|
30
34
|
animations;
|
|
31
35
|
constructor(customConfig){
|
|
32
36
|
this.customConfig = customConfig;
|
|
33
37
|
this.definedRules = [];
|
|
34
|
-
this.layerStatementRule = new Rule('layer-statement',
|
|
35
|
-
{
|
|
36
|
-
text: '@layer base,theme,preset,components,general;'
|
|
37
|
-
}
|
|
38
|
-
]);
|
|
38
|
+
this.layerStatementRule = new Rule('layer-statement', '@layer base,theme,preset,components,general;');
|
|
39
39
|
this.rules = [
|
|
40
40
|
this.layerStatementRule
|
|
41
41
|
];
|
|
42
|
+
this.classRules = new Map();
|
|
42
43
|
this.animationsNonLayer = new NonLayer(this);
|
|
43
44
|
this.baseLayer = new SyntaxLayer('base', this);
|
|
44
45
|
this.themeLayer = new Layer('theme', this);
|
|
@@ -48,10 +49,9 @@ class MasterCSS {
|
|
|
48
49
|
this.components = new Map();
|
|
49
50
|
this.selectors = new Map();
|
|
50
51
|
this.variables = new Map();
|
|
51
|
-
this.
|
|
52
|
+
this.atRules = new Map();
|
|
52
53
|
this.animations = new Map();
|
|
53
|
-
this.
|
|
54
|
-
this.resolve();
|
|
54
|
+
this.resolve(customConfig);
|
|
55
55
|
}
|
|
56
56
|
get text() {
|
|
57
57
|
return this.rules.sort((a, b)=>{
|
|
@@ -68,224 +68,433 @@ class MasterCSS {
|
|
|
68
68
|
return indexA - indexB;
|
|
69
69
|
}).map(({ text })=>text).join('');
|
|
70
70
|
}
|
|
71
|
-
resolve() {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
71
|
+
resolve(customConfig) {
|
|
72
|
+
if (customConfig) {
|
|
73
|
+
this.customConfig = customConfig;
|
|
74
|
+
} else {
|
|
75
|
+
customConfig = this.customConfig;
|
|
76
|
+
}
|
|
77
|
+
// @ts-expect-error read-only
|
|
78
|
+
this.config = customConfig?.override ? extendConfig(customConfig) : extendConfig(config, customConfig);
|
|
79
|
+
this.resolveVariables();
|
|
80
|
+
this.resolveAnimations();
|
|
81
|
+
this.resolveSelectors();
|
|
82
|
+
this.resolveAtRules();
|
|
83
|
+
this.resolveRules();
|
|
84
|
+
this.resolveComponents();
|
|
85
|
+
}
|
|
86
|
+
resolveAnimations() {
|
|
87
|
+
const { animations } = this.config;
|
|
88
|
+
if (animations) {
|
|
89
|
+
for(const animationName in animations){
|
|
90
|
+
const eachAnimation = {};
|
|
91
|
+
this.animations.set(animationName, eachAnimation);
|
|
92
|
+
const eachKeyframes = animations[animationName];
|
|
93
|
+
for(const eachKeyframeValue in eachKeyframes){
|
|
94
|
+
const newValueByPropertyName = eachAnimation[eachKeyframeValue] = {};
|
|
95
|
+
const eachKeyframeDeclarations = eachKeyframes[eachKeyframeValue];
|
|
96
|
+
for(const propertyName in eachKeyframeDeclarations){
|
|
97
|
+
newValueByPropertyName[propertyName] = eachKeyframeDeclarations[propertyName];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
resolveRules() {
|
|
104
|
+
const { rules, utilities } = this.config;
|
|
84
105
|
function escapeString(str) {
|
|
85
106
|
return str.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&');
|
|
86
107
|
}
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
this.selectors.set(vendor, selectorValues = []);
|
|
108
|
+
if (!rules && !utilities) return;
|
|
109
|
+
const rulesEntries = [];
|
|
110
|
+
// Collect utility rules
|
|
111
|
+
if (utilities) {
|
|
112
|
+
for(const utilityName in utilities){
|
|
113
|
+
const declarations = utilities[utilityName];
|
|
114
|
+
rulesEntries.push([
|
|
115
|
+
utilityName,
|
|
116
|
+
{
|
|
117
|
+
declarations,
|
|
118
|
+
type: SyntaxRuleType.Utility
|
|
99
119
|
}
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// Collect normal rules
|
|
124
|
+
if (rules) {
|
|
125
|
+
rulesEntries.push(...Object.entries(rules));
|
|
126
|
+
}
|
|
127
|
+
const rulesEntriesLength = rulesEntries.length;
|
|
128
|
+
// Prepare color variables
|
|
129
|
+
const colorNames = new Set([
|
|
130
|
+
'current',
|
|
131
|
+
'currentColor',
|
|
132
|
+
'transparent'
|
|
133
|
+
]);
|
|
134
|
+
this.variables.forEach((v)=>{
|
|
135
|
+
if (v.type === 'color') colorNames.add(v.name);
|
|
136
|
+
});
|
|
137
|
+
const colorPattern = [
|
|
138
|
+
...colorNames
|
|
139
|
+
].join('|');
|
|
140
|
+
// Main loop
|
|
141
|
+
rulesEntries.sort((a, b)=>{
|
|
142
|
+
if (a[1].type !== b[1].type) {
|
|
143
|
+
return (b[1].type || 0) - (a[1].type || 0);
|
|
144
|
+
}
|
|
145
|
+
return b[0].localeCompare(a[0], undefined, {
|
|
146
|
+
numeric: true
|
|
147
|
+
});
|
|
148
|
+
}).forEach(([id, def], index)=>{
|
|
149
|
+
const order = rulesEntriesLength - 1 - index;
|
|
150
|
+
const syntax = {
|
|
151
|
+
id,
|
|
152
|
+
keys: [],
|
|
153
|
+
variables: {},
|
|
154
|
+
matchers: {},
|
|
155
|
+
order,
|
|
156
|
+
definition: def
|
|
157
|
+
};
|
|
158
|
+
def.unit ??= '';
|
|
159
|
+
def.separators ??= [
|
|
160
|
+
','
|
|
161
|
+
];
|
|
162
|
+
this.definedRules.push(syntax);
|
|
163
|
+
const { matcher, type, subkey, ambiguousKeys, ambiguousValues, sign, key: originalKey, variables: ruleVariableGroups } = def;
|
|
164
|
+
const keys = [];
|
|
165
|
+
let key = originalKey;
|
|
166
|
+
// Helper: resolve variable groups
|
|
167
|
+
const addResolvedVariables = (groupName)=>{
|
|
168
|
+
this.variables.forEach((v)=>{
|
|
169
|
+
if (v.group === groupName) {
|
|
170
|
+
syntax.variables[v.key] = v;
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
};
|
|
174
|
+
// Rule-defined variable groups
|
|
175
|
+
if (ruleVariableGroups) {
|
|
176
|
+
ruleVariableGroups.forEach(addResolvedVariables);
|
|
177
|
+
}
|
|
178
|
+
// Auto variable binding
|
|
179
|
+
addResolvedVariables(id);
|
|
180
|
+
// Key derivation logic
|
|
181
|
+
if (type === SyntaxRuleType.NativeShorthand || type === SyntaxRuleType.Native) {
|
|
182
|
+
if (!key) def.key = key = id;
|
|
183
|
+
keys.push(id);
|
|
184
|
+
}
|
|
185
|
+
if (sign) {
|
|
186
|
+
syntax.matchers.arbitrary = new RegExp(`^${sign}[^!*>+~:[@_]+\\|`);
|
|
187
|
+
} else if (!matcher) {
|
|
188
|
+
if (!key && !subkey) {
|
|
189
|
+
keys.push(id);
|
|
190
|
+
} else {
|
|
191
|
+
if (key && !keys.includes(key)) keys.push(key);
|
|
192
|
+
if (subkey) keys.push(subkey);
|
|
193
|
+
if (type === SyntaxRuleType.Shorthand) keys.push(id);
|
|
194
|
+
}
|
|
195
|
+
// Ambiguous keys and values
|
|
196
|
+
if (ambiguousKeys?.length) {
|
|
197
|
+
const keyPattern = ambiguousKeys.length > 1 ? `(?:${ambiguousKeys.join('|')})` : ambiguousKeys[0];
|
|
198
|
+
const variableKeys = Object.keys(syntax.variables);
|
|
199
|
+
if (ambiguousValues?.length) {
|
|
200
|
+
const valuePatterns = ambiguousValues.map((val)=>val instanceof RegExp ? val.source.replace('\\$colors', colorPattern) : `${val}(?:\\b|_)`);
|
|
201
|
+
syntax.matchers.value = new RegExp(`^${keyPattern}:(?:${valuePatterns.join('|')})[^|]*?(?:@|$)`);
|
|
202
|
+
}
|
|
203
|
+
if (variableKeys.length) {
|
|
204
|
+
syntax.matchers.variable = new RegExp(`^${keyPattern}:(?:${variableKeys.join('|')}(?![a-zA-Z0-9-]))[^|]*?(?:@|$)`);
|
|
107
205
|
}
|
|
108
|
-
currentSelectValue[1].push(eachNewSelectorText);
|
|
109
206
|
}
|
|
207
|
+
} else {
|
|
208
|
+
syntax.matchers.arbitrary = matcher;
|
|
110
209
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
210
|
+
// Utility rule matcher
|
|
211
|
+
if (type === SyntaxRuleType.Utility) {
|
|
212
|
+
syntax.id = '.' + id;
|
|
213
|
+
syntax.matchers.arbitrary = new RegExp('^' + escapeString(id) + '(?=!|\\*|>|\\+|~|:|\\[|@|_|\\.|$)', 'm');
|
|
214
|
+
}
|
|
215
|
+
// Key matcher
|
|
216
|
+
if (keys.length) {
|
|
217
|
+
syntax.keys = keys;
|
|
218
|
+
syntax.matchers.key = new RegExp(`^${keys.length > 1 ? `(${keys.join('|')})` : keys[0]}:.`);
|
|
219
|
+
}
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
resolveComponents() {
|
|
223
|
+
const { components } = this.config;
|
|
224
|
+
const flatComps = components ? flattenObject(components) : {};
|
|
225
|
+
const names = Object.keys(flatComps);
|
|
226
|
+
const nameSet = new Set(names);
|
|
227
|
+
// First pass: expand class names recursively
|
|
228
|
+
for (const name of names){
|
|
229
|
+
if (this.components.has(name)) continue;
|
|
230
|
+
const currentClass = [];
|
|
231
|
+
this.components.set(name, currentClass);
|
|
232
|
+
const className = flatComps[name];
|
|
233
|
+
if (!className) continue;
|
|
234
|
+
const classNames = className.replace(/(?:\n\s*)+/g, ' ').trim().split(' ');
|
|
235
|
+
const seen = new Set();
|
|
236
|
+
const addClass = (cls)=>{
|
|
237
|
+
if (!seen.has(cls)) {
|
|
238
|
+
seen.add(cls);
|
|
239
|
+
currentClass.push(cls);
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
for (const eachClassName of classNames){
|
|
243
|
+
if (nameSet.has(eachClassName)) {
|
|
244
|
+
addClass(eachClassName);
|
|
245
|
+
// Lazy expand dependencies if not processed
|
|
246
|
+
if (!this.components.has(eachClassName)) {
|
|
247
|
+
const componentClass = flatComps[eachClassName];
|
|
248
|
+
if (componentClass) {
|
|
249
|
+
this.components.set(eachClassName, []) // placeholder to prevent infinite loop
|
|
250
|
+
;
|
|
251
|
+
// Recursively resolve
|
|
252
|
+
const depClassNames = componentClass.replace(/(?:\n\s*)+/g, ' ').trim().split(' ');
|
|
253
|
+
depClassNames.forEach(addClass);
|
|
131
254
|
}
|
|
132
|
-
colorVariableNames[flatName] = undefined;
|
|
133
255
|
}
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
256
|
+
const componentClasses = this.components.get(eachClassName);
|
|
257
|
+
componentClasses?.forEach(addClass);
|
|
258
|
+
} else {
|
|
259
|
+
addClass(eachClassName);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// Second pass: convert to grouped syntax rule strings
|
|
264
|
+
this.components.forEach((componentClasses, componentName)=>{
|
|
265
|
+
const syntaxRulesByStateToken = {};
|
|
266
|
+
for (const syntax of componentClasses){
|
|
267
|
+
const parsed = this.create(syntax);
|
|
268
|
+
if (parsed?.text) {
|
|
269
|
+
const group = syntaxRulesByStateToken[parsed.stateToken] ||= [];
|
|
270
|
+
group.push(parsed);
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
const result = Object.entries(syntaxRulesByStateToken).map(([stateToken, syntaxRules])=>{
|
|
274
|
+
if (syntaxRules.length === 1) return syntaxRules[0].name;
|
|
275
|
+
const namesWithoutToken = syntaxRules.map((s)=>s.name.slice(0, s.name.length - s.stateToken.length));
|
|
276
|
+
return `{${namesWithoutToken.join(';')}}${stateToken}`;
|
|
277
|
+
});
|
|
278
|
+
this.components.set(componentName, result);
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
resolveSelectors() {
|
|
282
|
+
const { selectors } = this.config;
|
|
283
|
+
if (selectors) {
|
|
284
|
+
const flatSelectors = flattenObject(selectors);
|
|
285
|
+
for(const token in flatSelectors){
|
|
286
|
+
const value = flatSelectors[token];
|
|
287
|
+
const nodes = parseSelector(value, this, false);
|
|
288
|
+
this.selectors.set(token, nodes);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
resolveAtRules() {
|
|
293
|
+
const { at, screens } = this.config;
|
|
294
|
+
if (screens) {
|
|
295
|
+
for(const key in screens){
|
|
296
|
+
const value = screens[key];
|
|
297
|
+
const node = this.parseValue(value);
|
|
298
|
+
this.atRules.set(key, {
|
|
299
|
+
id: 'media',
|
|
300
|
+
nodes: [
|
|
301
|
+
node
|
|
302
|
+
]
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
if (at) {
|
|
307
|
+
const flatAt = flattenObject(at);
|
|
308
|
+
for(const token in flatAt){
|
|
309
|
+
const value = flatAt[token];
|
|
310
|
+
if (typeof value === 'number') {
|
|
311
|
+
const node = this.parseValue(value);
|
|
312
|
+
this.atRules.set(token, {
|
|
313
|
+
id: 'media',
|
|
314
|
+
nodes: [
|
|
315
|
+
node
|
|
316
|
+
]
|
|
317
|
+
});
|
|
318
|
+
} else {
|
|
319
|
+
const atRule = parseAt(value, this, false);
|
|
320
|
+
this.atRules.set(token, atRule);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
resolveVariables() {
|
|
326
|
+
const { variables, screens } = this.config;
|
|
327
|
+
const aliasVariableModeResolvers = new Map();
|
|
328
|
+
const resolveVariable = (variableDefinition, name, mode)=>{
|
|
329
|
+
if (variableDefinition === undefined || variableDefinition === null) return;
|
|
330
|
+
const addVariable = (name, variable, replacedMode, alpha)=>{
|
|
331
|
+
if (variable === undefined) return;
|
|
332
|
+
const flatName = name.join('-');
|
|
333
|
+
const groups = name.slice(0, -1).filter(Boolean);
|
|
334
|
+
const key = (name[0] === '' ? '-' : '') + name[name.length - 1];
|
|
335
|
+
variable.key = key;
|
|
336
|
+
variable.name = flatName;
|
|
337
|
+
if (groups.length) variable.group = groups.join('.');
|
|
338
|
+
if (variable.type === 'color') {
|
|
339
|
+
if (alpha) {
|
|
340
|
+
const slashIndex = variable.value.indexOf('/');
|
|
341
|
+
variable = {
|
|
342
|
+
...variable,
|
|
343
|
+
value: slashIndex === -1 ? variable.value + ' / ' + (alpha.startsWith('0.') ? alpha.slice(1) : alpha) : variable.value.slice(0, slashIndex + 2) + String(+variable.value.slice(slashIndex + 2) * +alpha).slice(1)
|
|
344
|
+
};
|
|
138
345
|
}
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
foundVariable.modes[currentMode] = variable;
|
|
148
|
-
} else {
|
|
149
|
-
foundVariable.value = variable.value;
|
|
150
|
-
if (variable.type === 'color') {
|
|
151
|
-
foundVariable.space = variable.space;
|
|
152
|
-
}
|
|
346
|
+
}
|
|
347
|
+
const currentMode = replacedMode ?? mode;
|
|
348
|
+
if (currentMode !== undefined) {
|
|
349
|
+
const foundVariable = this.variables.get(flatName);
|
|
350
|
+
if (foundVariable) {
|
|
351
|
+
if (currentMode) {
|
|
352
|
+
if (!foundVariable.modes) {
|
|
353
|
+
foundVariable.modes = {};
|
|
153
354
|
}
|
|
355
|
+
foundVariable.modes[currentMode] = variable;
|
|
154
356
|
} else {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
name: variable.name,
|
|
159
|
-
group: variable.group,
|
|
160
|
-
type: variable.type,
|
|
161
|
-
modes: {
|
|
162
|
-
[currentMode]: variable
|
|
163
|
-
}
|
|
164
|
-
};
|
|
165
|
-
if (variable.type === 'color') {
|
|
166
|
-
newVariable.space = variable.space;
|
|
167
|
-
}
|
|
168
|
-
this.variables.set(flatName, newVariable);
|
|
169
|
-
} else {
|
|
170
|
-
this.variables.set(flatName, variable);
|
|
357
|
+
foundVariable.value = variable.value;
|
|
358
|
+
if (variable.type === 'color') {
|
|
359
|
+
foundVariable.space = variable.space;
|
|
171
360
|
}
|
|
172
361
|
}
|
|
173
362
|
} else {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (eachKey === '' || eachKey.startsWith('@')) {
|
|
187
|
-
resolveVariable(variableDefinition[eachKey], name, eachKey || keys.some((eachKey)=>eachKey.startsWith('@')) ? eachKey.slice(1) : undefined);
|
|
188
|
-
} else {
|
|
189
|
-
resolveVariable(variableDefinition[eachKey], [
|
|
190
|
-
...name,
|
|
191
|
-
eachKey
|
|
192
|
-
]);
|
|
363
|
+
if (currentMode) {
|
|
364
|
+
const newVariable = {
|
|
365
|
+
key: variable.key,
|
|
366
|
+
name: variable.name,
|
|
367
|
+
group: variable.group,
|
|
368
|
+
type: variable.type,
|
|
369
|
+
modes: {
|
|
370
|
+
[currentMode]: variable
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
if (variable.type === 'color') {
|
|
374
|
+
newVariable.space = variable.space;
|
|
193
375
|
}
|
|
376
|
+
this.variables.set(flatName, newVariable);
|
|
377
|
+
} else {
|
|
378
|
+
this.variables.set(flatName, variable);
|
|
194
379
|
}
|
|
195
380
|
}
|
|
196
|
-
} else
|
|
381
|
+
} else {
|
|
382
|
+
this.variables.set(flatName, variable);
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
if (typeof variableDefinition === 'object') {
|
|
386
|
+
if (Array.isArray(variableDefinition)) {
|
|
197
387
|
addVariable(name, {
|
|
198
|
-
type: '
|
|
199
|
-
value: variableDefinition
|
|
388
|
+
type: 'string',
|
|
389
|
+
value: variableDefinition.join(',')
|
|
200
390
|
});
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (aliasResult) {
|
|
212
|
-
let aliasVariableModeResolver = aliasVariableModeResolvers.get(flatName);
|
|
213
|
-
if (!aliasVariableModeResolver) {
|
|
214
|
-
aliasVariableModeResolvers.set(flatName, aliasVariableModeResolver = {});
|
|
391
|
+
} else {
|
|
392
|
+
const keys = Object.keys(variableDefinition);
|
|
393
|
+
for (const eachKey of keys){
|
|
394
|
+
if (eachKey === '' || eachKey.startsWith('@')) {
|
|
395
|
+
resolveVariable(variableDefinition[eachKey], name, eachKey || keys.some((eachKey)=>eachKey.startsWith('@')) ? eachKey.slice(1) : undefined);
|
|
396
|
+
} else {
|
|
397
|
+
resolveVariable(variableDefinition[eachKey], [
|
|
398
|
+
...name,
|
|
399
|
+
eachKey
|
|
400
|
+
]);
|
|
215
401
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
} else if (typeof variableDefinition === 'number') {
|
|
405
|
+
addVariable(name, {
|
|
406
|
+
type: 'number',
|
|
407
|
+
value: variableDefinition
|
|
408
|
+
});
|
|
409
|
+
addVariable([
|
|
410
|
+
'',
|
|
411
|
+
...name
|
|
412
|
+
], {
|
|
413
|
+
type: 'number',
|
|
414
|
+
value: variableDefinition * -1
|
|
415
|
+
});
|
|
416
|
+
} else if (typeof variableDefinition === 'string') {
|
|
417
|
+
const aliasResult = /^\$\((.*?)\)(?: ?\/ ?(.+?))?$/.exec(variableDefinition);
|
|
418
|
+
const flatName = name.join('-');
|
|
419
|
+
if (aliasResult) {
|
|
420
|
+
let aliasVariableModeResolver = aliasVariableModeResolvers.get(flatName);
|
|
421
|
+
if (!aliasVariableModeResolver) {
|
|
422
|
+
aliasVariableModeResolvers.set(flatName, aliasVariableModeResolver = {});
|
|
423
|
+
}
|
|
424
|
+
aliasVariableModeResolver[mode] = ()=>{
|
|
425
|
+
delete aliasVariableModeResolver[mode];
|
|
426
|
+
const [alias, aliasMode] = aliasResult[1].split('@');
|
|
427
|
+
if (alias) {
|
|
428
|
+
const eachAliasModeVariableResolver = aliasVariableModeResolvers.get(alias);
|
|
429
|
+
if (eachAliasModeVariableResolver) {
|
|
430
|
+
for (const mode of Object.keys(eachAliasModeVariableResolver)){
|
|
431
|
+
eachAliasModeVariableResolver[mode]?.();
|
|
225
432
|
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
addVariable(name, newVariable, undefined, aliasResult[2]);
|
|
433
|
+
}
|
|
434
|
+
const aliasVariable = this.variables.get(alias);
|
|
435
|
+
if (aliasVariable) {
|
|
436
|
+
if (aliasMode === undefined && aliasVariable.modes) {
|
|
437
|
+
addVariable(name, {
|
|
438
|
+
type: aliasVariable.type,
|
|
439
|
+
value: aliasVariable.value,
|
|
440
|
+
space: aliasVariable.space
|
|
441
|
+
}, '', aliasResult[2]);
|
|
442
|
+
for(const mode in aliasVariable.modes){
|
|
443
|
+
addVariable(name, aliasVariable.modes[mode], mode, aliasResult[2]);
|
|
444
|
+
}
|
|
445
|
+
} else {
|
|
446
|
+
const variable = aliasMode !== undefined ? aliasVariable.modes?.[aliasMode] : aliasVariable;
|
|
447
|
+
if (variable) {
|
|
448
|
+
const newVariable = {
|
|
449
|
+
type: variable.type,
|
|
450
|
+
value: variable.value
|
|
451
|
+
};
|
|
452
|
+
if (variable.type === 'color') {
|
|
453
|
+
newVariable.space = variable.space;
|
|
248
454
|
}
|
|
455
|
+
addVariable(name, newVariable, undefined, aliasResult[2]);
|
|
249
456
|
}
|
|
250
457
|
}
|
|
251
458
|
}
|
|
252
|
-
}
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
} else {
|
|
462
|
+
const hexColorResult = /^#([A-Fa-f0-9]{3,4}|[A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/.exec(variableDefinition);
|
|
463
|
+
if (hexColorResult) {
|
|
464
|
+
const [r, g, b, a] = hexToRgb(hexColorResult[1]);
|
|
465
|
+
addVariable(name, {
|
|
466
|
+
type: 'color',
|
|
467
|
+
value: `${r} ${g} ${b}${a === 1 ? '' : ' / ' + a}`,
|
|
468
|
+
space: 'rgb'
|
|
469
|
+
});
|
|
253
470
|
} else {
|
|
254
|
-
const
|
|
255
|
-
if (
|
|
256
|
-
const [r, g, b, a] = hexToRgb(hexColorResult[1]);
|
|
471
|
+
const rgbFunctionResult = /^rgb\( *([0-9]{1,3})(?: *, *| +)([0-9]{1,3})(?: *, *| +)([0-9]{1,3}) *(?:(?:,|\/) *(.*?) *)?\)$/.exec(variableDefinition);
|
|
472
|
+
if (rgbFunctionResult) {
|
|
257
473
|
addVariable(name, {
|
|
258
474
|
type: 'color',
|
|
259
|
-
value:
|
|
475
|
+
value: rgbFunctionResult[1] + ' ' + rgbFunctionResult[2] + ' ' + rgbFunctionResult[3] + (rgbFunctionResult[4] ? ' / ' + (rgbFunctionResult[4].startsWith('0.') ? rgbFunctionResult[4].slice(1) : rgbFunctionResult[4]) : ''),
|
|
260
476
|
space: 'rgb'
|
|
261
477
|
});
|
|
262
478
|
} else {
|
|
263
|
-
const
|
|
264
|
-
if (
|
|
479
|
+
const hslFunctionResult = /^hsl\((.*?)\)$/.exec(variableDefinition);
|
|
480
|
+
if (hslFunctionResult) {
|
|
265
481
|
addVariable(name, {
|
|
266
482
|
type: 'color',
|
|
267
|
-
value:
|
|
268
|
-
space: '
|
|
483
|
+
value: hslFunctionResult[1],
|
|
484
|
+
space: 'hsl'
|
|
269
485
|
});
|
|
270
486
|
} else {
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
value: hslFunctionResult[1],
|
|
276
|
-
space: 'hsl'
|
|
277
|
-
});
|
|
278
|
-
} else {
|
|
279
|
-
addVariable(name, {
|
|
280
|
-
type: 'string',
|
|
281
|
-
value: variableDefinition
|
|
282
|
-
});
|
|
283
|
-
}
|
|
487
|
+
addVariable(name, {
|
|
488
|
+
type: 'string',
|
|
489
|
+
value: variableDefinition
|
|
490
|
+
});
|
|
284
491
|
}
|
|
285
492
|
}
|
|
286
493
|
}
|
|
287
494
|
}
|
|
288
|
-
}
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
if (variables) {
|
|
289
498
|
for(const parnetKey in variables){
|
|
290
499
|
resolveVariable(variables[parnetKey], [
|
|
291
500
|
parnetKey
|
|
@@ -298,178 +507,14 @@ class MasterCSS {
|
|
|
298
507
|
}
|
|
299
508
|
});
|
|
300
509
|
}
|
|
301
|
-
if (
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
}
|
|
510
|
+
if (screens) {
|
|
511
|
+
resolveVariable(screens, [
|
|
512
|
+
'screen'
|
|
513
|
+
]);
|
|
306
514
|
}
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
this.animations.set(animationName, eachAnimation);
|
|
311
|
-
const eachKeyframes = animations[animationName];
|
|
312
|
-
for(const eachKeyframeValue in eachKeyframes){
|
|
313
|
-
const newValueByPropertyName = eachAnimation[eachKeyframeValue] = {};
|
|
314
|
-
const eachKeyframeDeclarations = eachKeyframes[eachKeyframeValue];
|
|
315
|
-
for(const propertyName in eachKeyframeDeclarations){
|
|
316
|
-
newValueByPropertyName[propertyName] = eachKeyframeDeclarations[propertyName];
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
const flattedStyles = components ? flattenObject(components) : {};
|
|
322
|
-
const utilityNames = Object.keys(flattedStyles);
|
|
323
|
-
const handleUtilityName = (utilityName)=>{
|
|
324
|
-
if (this.components.has(utilityName)) return;
|
|
325
|
-
const currentClass = [];
|
|
326
|
-
this.components.set(utilityName, currentClass);
|
|
327
|
-
const className = flattedStyles[utilityName];
|
|
328
|
-
if (!className) return;
|
|
329
|
-
const classNames = className.replace(/(?:\n(?:\s*))+/g, ' ').trim().split(' ');
|
|
330
|
-
for (const eachClassName of classNames){
|
|
331
|
-
const handle = (className)=>{
|
|
332
|
-
if (!currentClass.includes(className)) {
|
|
333
|
-
currentClass.push(className);
|
|
334
|
-
}
|
|
335
|
-
};
|
|
336
|
-
if (utilityNames.includes(eachClassName)) {
|
|
337
|
-
handleUtilityName(eachClassName);
|
|
338
|
-
const componentClasses = this.components.get(eachClassName);
|
|
339
|
-
componentClasses?.forEach(handle);
|
|
340
|
-
} else {
|
|
341
|
-
handle(eachClassName);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
};
|
|
345
|
-
for (const eachUtilityName of utilityNames){
|
|
346
|
-
handleUtilityName(eachUtilityName);
|
|
347
|
-
}
|
|
348
|
-
if (rules || utilities) {
|
|
349
|
-
const rulesEntries = [];
|
|
350
|
-
if (utilities) {
|
|
351
|
-
for(const utilityName in utilities){
|
|
352
|
-
const declarations = utilities[utilityName];
|
|
353
|
-
rulesEntries.push([
|
|
354
|
-
utilityName,
|
|
355
|
-
{
|
|
356
|
-
declarations,
|
|
357
|
-
type: SyntaxRuleType.Utility
|
|
358
|
-
}
|
|
359
|
-
]);
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
if (rules) {
|
|
363
|
-
rulesEntries.push(...Object.entries(rules));
|
|
364
|
-
}
|
|
365
|
-
const rulesEntriesLength = rulesEntries.length;
|
|
366
|
-
const colorNames = Object.keys(colorVariableNames);
|
|
367
|
-
rulesEntries.sort((a, b)=>{
|
|
368
|
-
if (a[1].type !== b[1].type) {
|
|
369
|
-
return (b[1].type || 0) - (a[1].type || 0);
|
|
370
|
-
}
|
|
371
|
-
return b[0].localeCompare(a[0]);
|
|
372
|
-
}).forEach(([id, eachSyntaxRuleDefinition], index)=>{
|
|
373
|
-
const syntax = {
|
|
374
|
-
id,
|
|
375
|
-
keys: [],
|
|
376
|
-
variables: {},
|
|
377
|
-
matchers: {},
|
|
378
|
-
order: rulesEntriesLength - 1 - index,
|
|
379
|
-
definition: eachSyntaxRuleDefinition
|
|
380
|
-
};
|
|
381
|
-
if (!eachSyntaxRuleDefinition.unit) {
|
|
382
|
-
eachSyntaxRuleDefinition.unit = '';
|
|
383
|
-
}
|
|
384
|
-
if (!eachSyntaxRuleDefinition.separators) {
|
|
385
|
-
eachSyntaxRuleDefinition.separators = [
|
|
386
|
-
','
|
|
387
|
-
];
|
|
388
|
-
}
|
|
389
|
-
this.definedRules.push(syntax);
|
|
390
|
-
const { matcher, type, subkey, ambiguousKeys, ambiguousValues, sign } = eachSyntaxRuleDefinition;
|
|
391
|
-
if (type === SyntaxRuleType.Utility) {
|
|
392
|
-
syntax.id = '.' + id;
|
|
393
|
-
syntax.matchers.arbitrary = new RegExp('^' + escapeString(id) + '(?=!|\\*|>|\\+|~|:|\\[|@|_|\\.|$)', 'm');
|
|
394
|
-
}
|
|
395
|
-
// todo: 不可使用 startsWith 判斷,應改為更精準的從 config.variables 取得目標變數群組,但 config.variables 中的值還沒被 resolve 像是 Array
|
|
396
|
-
const addResolvedVariables = (groupName)=>{
|
|
397
|
-
this.variables.forEach((eachVariable)=>{
|
|
398
|
-
if (eachVariable.group === groupName) {
|
|
399
|
-
syntax.variables[eachVariable.key] = eachVariable;
|
|
400
|
-
}
|
|
401
|
-
});
|
|
402
|
-
};
|
|
403
|
-
// 1. custom `config.rules[id].variables`
|
|
404
|
-
if (eachSyntaxRuleDefinition.variables) {
|
|
405
|
-
for (const eachVariableGroup of eachSyntaxRuleDefinition.variables){
|
|
406
|
-
addResolvedVariables(eachVariableGroup);
|
|
407
|
-
}
|
|
408
|
-
}
|
|
409
|
-
// 2. custom `config.variables`
|
|
410
|
-
addResolvedVariables(id);
|
|
411
|
-
const keys = [];
|
|
412
|
-
let { key } = eachSyntaxRuleDefinition;
|
|
413
|
-
if (type === SyntaxRuleType.NativeShorthand || type === SyntaxRuleType.Native) {
|
|
414
|
-
if (!key) eachSyntaxRuleDefinition.key = key = id;
|
|
415
|
-
keys.push(id);
|
|
416
|
-
}
|
|
417
|
-
if (sign) {
|
|
418
|
-
syntax.matchers.arbitrary = new RegExp(`^${sign}[^!*>+~:[@_]+\\|`);
|
|
419
|
-
} else if (!matcher) {
|
|
420
|
-
const colorsPatten = colorNames.join('|');
|
|
421
|
-
if (!key && !subkey) {
|
|
422
|
-
keys.push(id);
|
|
423
|
-
} else {
|
|
424
|
-
if (key && !keys.includes(key)) keys.push(key);
|
|
425
|
-
if (subkey) keys.push(subkey);
|
|
426
|
-
if (type === SyntaxRuleType.Shorthand) {
|
|
427
|
-
keys.push(id);
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
if (ambiguousKeys?.length) {
|
|
431
|
-
const ambiguousKeyPattern = ambiguousKeys.length > 1 ? `(?:${ambiguousKeys.join('|')})` : ambiguousKeys[0];
|
|
432
|
-
const variableKeys = Object.keys(syntax.variables);
|
|
433
|
-
if (ambiguousValues?.length) {
|
|
434
|
-
const ambiguousValuePatterns = [];
|
|
435
|
-
for (const eachAmbiguousValue of ambiguousValues){
|
|
436
|
-
if (eachAmbiguousValue instanceof RegExp) {
|
|
437
|
-
ambiguousValuePatterns.push(eachAmbiguousValue.source.replace('\\$colors', colorsPatten));
|
|
438
|
-
} else {
|
|
439
|
-
ambiguousValuePatterns.unshift(`${eachAmbiguousValue}(?:\\b|_)`);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
syntax.matchers.value = new RegExp(`^${ambiguousKeyPattern}:(?:${ambiguousValuePatterns.join('|')})[^|]*?(?:@|$)`);
|
|
443
|
-
}
|
|
444
|
-
if (variableKeys.length) {
|
|
445
|
-
syntax.matchers.variable = new RegExp(`^${ambiguousKeyPattern}:(?:${variableKeys.join('|')}(?![a-zA-Z0-9-]))[^|]*?(?:@|$)`);
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
} else {
|
|
449
|
-
syntax.matchers.arbitrary = matcher;
|
|
450
|
-
}
|
|
451
|
-
if (keys.length) {
|
|
452
|
-
syntax.keys = keys;
|
|
453
|
-
syntax.matchers.key = new RegExp(`^${keys.length > 1 ? `(${keys.join('|')})` : keys[0]}:.`);
|
|
454
|
-
}
|
|
455
|
-
});
|
|
456
|
-
}
|
|
457
|
-
this.components.forEach((componentClasses, componentClass)=>{
|
|
458
|
-
const syntaxRulesByStateToken = componentClasses.map((eachSyntax)=>this.create(eachSyntax)).filter((eachSyntax)=>eachSyntax?.text).reduce((obj, eachSyntaxRule)=>{
|
|
459
|
-
if (eachSyntaxRule.stateToken in obj) {
|
|
460
|
-
obj[eachSyntaxRule.stateToken].push(eachSyntaxRule);
|
|
461
|
-
} else {
|
|
462
|
-
obj[eachSyntaxRule.stateToken] = [
|
|
463
|
-
eachSyntaxRule
|
|
464
|
-
];
|
|
465
|
-
}
|
|
466
|
-
return obj;
|
|
467
|
-
}, {});
|
|
468
|
-
this.components.set(componentClass, Object.keys(syntaxRulesByStateToken).map((stateToken)=>{
|
|
469
|
-
const syntaxRules = syntaxRulesByStateToken[stateToken];
|
|
470
|
-
return syntaxRules.length === 1 ? syntaxRules[0].name : '{' + syntaxRulesByStateToken[stateToken].map((eachSyntaxRule)=>eachSyntaxRule.name.slice(0, eachSyntaxRule.name.length - eachSyntaxRule.stateToken.length)).join(';') + '}' + stateToken;
|
|
471
|
-
}));
|
|
472
|
-
});
|
|
515
|
+
}
|
|
516
|
+
parseValue(token, unit = 'rem') {
|
|
517
|
+
return parseValue(token, unit, this.config.rootSize);
|
|
473
518
|
}
|
|
474
519
|
/**
|
|
475
520
|
* Match check if Master CSS syntax
|
|
@@ -511,7 +556,9 @@ class MasterCSS {
|
|
|
511
556
|
if (componentClasses) {
|
|
512
557
|
componentClasses.forEach((eachSyntax)=>{
|
|
513
558
|
const syntaxRule = this.create(eachSyntax, className, mode);
|
|
514
|
-
if (syntaxRule
|
|
559
|
+
if (syntaxRule && syntaxRule.valid) {
|
|
560
|
+
syntaxRules.push(syntaxRule);
|
|
561
|
+
}
|
|
515
562
|
});
|
|
516
563
|
} else {
|
|
517
564
|
const atIndex = className.indexOf('@');
|
|
@@ -522,98 +569,18 @@ class MasterCSS {
|
|
|
522
569
|
const atToken = className.slice(atIndex);
|
|
523
570
|
componentClasses.forEach((eachSyntax)=>{
|
|
524
571
|
const syntaxRule = this.create(eachSyntax + atToken, className, mode);
|
|
525
|
-
if (syntaxRule
|
|
572
|
+
if (syntaxRule && syntaxRule.valid) {
|
|
573
|
+
syntaxRules.push(syntaxRule);
|
|
574
|
+
}
|
|
526
575
|
});
|
|
527
576
|
}
|
|
528
577
|
}
|
|
529
578
|
const syntaxRule = this.create(className, undefined, mode);
|
|
530
|
-
if (syntaxRule
|
|
531
|
-
|
|
532
|
-
return syntaxRules;
|
|
533
|
-
}
|
|
534
|
-
generateVendorSelectors(selectorText) {
|
|
535
|
-
const vendorSelectors = {};
|
|
536
|
-
const transformSelector = (selectorText, selectorValues, selectors, matched)=>{
|
|
537
|
-
for (const [regexp, newSelectorTexts] of selectorValues){
|
|
538
|
-
if (regexp.test(selectorText)) {
|
|
539
|
-
for (const eachNewSelectorText of newSelectorTexts){
|
|
540
|
-
transformSelector(selectorText.replace(regexp, eachNewSelectorText), selectorValues, selectors, true);
|
|
541
|
-
}
|
|
542
|
-
return;
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
if (matched) {
|
|
546
|
-
selectors.push(selectorText);
|
|
547
|
-
}
|
|
548
|
-
};
|
|
549
|
-
const spacedSelectorToken = (selectorText)=>{
|
|
550
|
-
// 1. \'123\'
|
|
551
|
-
// 2. [href='http://localhost']
|
|
552
|
-
const transformedSelectorText = selectorText.split(/(\\'(?:.*?)[^\\]\\')(?=[*_>~+,)])|(\[[^=]+='(?:.*?)[^\\]'\])/).map((eachToken, i)=>i % 3 ? eachToken : eachToken.replace(/(^|[^_])_(?!_)/g, '$1 ')).join('');
|
|
553
|
-
const selectors = [];
|
|
554
|
-
let currentSelector = '';
|
|
555
|
-
let symbolCount = 0;
|
|
556
|
-
for(let i = 0; i < transformedSelectorText.length; i++){
|
|
557
|
-
const char = transformedSelectorText[i];
|
|
558
|
-
if (char === '\\') {
|
|
559
|
-
currentSelector += char + transformedSelectorText[++i];
|
|
560
|
-
continue;
|
|
561
|
-
}
|
|
562
|
-
if (!symbolCount && char === ',') {
|
|
563
|
-
selectors.push(currentSelector);
|
|
564
|
-
currentSelector = '';
|
|
565
|
-
} else {
|
|
566
|
-
currentSelector += char;
|
|
567
|
-
if (symbolCount && char === ')') {
|
|
568
|
-
symbolCount--;
|
|
569
|
-
} else if (char === '(') {
|
|
570
|
-
symbolCount++;
|
|
571
|
-
}
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
if (currentSelector) {
|
|
575
|
-
selectors.push(currentSelector);
|
|
576
|
-
}
|
|
577
|
-
return selectors;
|
|
578
|
-
};
|
|
579
|
-
const transformedSelectors = [];
|
|
580
|
-
const selectorValues = this.selectors.get('');
|
|
581
|
-
if (selectorValues) {
|
|
582
|
-
transformSelector(selectorText, selectorValues, transformedSelectors, true);
|
|
583
|
-
} else {
|
|
584
|
-
transformedSelectors.push(selectorText);
|
|
585
|
-
}
|
|
586
|
-
const unspacedVendorSelectors = {};
|
|
587
|
-
this.selectors.forEach((selectorValues, vendor)=>{
|
|
588
|
-
if (!vendor) return;
|
|
589
|
-
const newUnspacedVendorSelectors = [];
|
|
590
|
-
for (const eachTransformedSelector of transformedSelectors){
|
|
591
|
-
transformSelector(eachTransformedSelector, selectorValues, newUnspacedVendorSelectors, false);
|
|
592
|
-
}
|
|
593
|
-
if (newUnspacedVendorSelectors.length) {
|
|
594
|
-
unspacedVendorSelectors[vendor] = newUnspacedVendorSelectors;
|
|
595
|
-
}
|
|
596
|
-
});
|
|
597
|
-
const insertVendorSelectors = (vendor, selectorTexts)=>{
|
|
598
|
-
const groupedSelectorTexts = selectorTexts.reduce((arr, eachSuffixSelector)=>{
|
|
599
|
-
arr.push(...spacedSelectorToken(eachSuffixSelector));
|
|
600
|
-
return arr;
|
|
601
|
-
}, []);
|
|
602
|
-
if (vendor in vendorSelectors) {
|
|
603
|
-
vendorSelectors[vendor].push(...groupedSelectorTexts);
|
|
604
|
-
} else {
|
|
605
|
-
vendorSelectors[vendor] = groupedSelectorTexts;
|
|
606
|
-
}
|
|
607
|
-
};
|
|
608
|
-
const vendors = Object.keys(unspacedVendorSelectors);
|
|
609
|
-
if (vendors.length) {
|
|
610
|
-
for (const eachVendor of vendors){
|
|
611
|
-
insertVendorSelectors(eachVendor, unspacedVendorSelectors[eachVendor]);
|
|
579
|
+
if (syntaxRule && syntaxRule.valid) {
|
|
580
|
+
syntaxRules.push(syntaxRule);
|
|
612
581
|
}
|
|
613
|
-
} else {
|
|
614
|
-
insertVendorSelectors('', transformedSelectors);
|
|
615
582
|
}
|
|
616
|
-
return
|
|
583
|
+
return syntaxRules;
|
|
617
584
|
}
|
|
618
585
|
/**
|
|
619
586
|
* Create syntax rule from given class name
|
|
@@ -634,7 +601,7 @@ class MasterCSS {
|
|
|
634
601
|
for(let i = 0; i < selectorTextSplits.length; i++){
|
|
635
602
|
const eachField = selectorTextSplits[i];
|
|
636
603
|
const modeSelector = this.getModeSelector(eachField);
|
|
637
|
-
if (i === 0 && eachField === modeSelector) continue;
|
|
604
|
+
if (i === 0 && eachField === modeSelector || (i === 0 || i === 1) && eachField === this.config.scope) continue;
|
|
638
605
|
if (eachField.startsWith('.')) {
|
|
639
606
|
const eachFieldName = eachField.slice(1);
|
|
640
607
|
let className = '';
|
|
@@ -660,17 +627,23 @@ class MasterCSS {
|
|
|
660
627
|
* 根據蒐集到的所有 DOM class 重新 create
|
|
661
628
|
*/ refresh(customConfig) {
|
|
662
629
|
this.reset();
|
|
663
|
-
|
|
664
|
-
this.customConfig = customConfig;
|
|
665
|
-
} else {
|
|
666
|
-
customConfig = this.customConfig;
|
|
667
|
-
}
|
|
668
|
-
// @ts-ignore
|
|
669
|
-
this.config = customConfig?.override ? extendConfig(customConfig) : extendConfig(config, customConfig);
|
|
670
|
-
this.resolve();
|
|
630
|
+
this.resolve(customConfig);
|
|
671
631
|
return this;
|
|
672
632
|
}
|
|
673
633
|
reset() {
|
|
634
|
+
// @ts-ignore
|
|
635
|
+
this.animations = new Map();
|
|
636
|
+
// @ts-ignore
|
|
637
|
+
this.variables = new Map();
|
|
638
|
+
// @ts-ignore
|
|
639
|
+
this.atRules = new Map();
|
|
640
|
+
// @ts-ignore
|
|
641
|
+
this.selectors = new Map();
|
|
642
|
+
// @ts-ignore
|
|
643
|
+
this.components = new Map();
|
|
644
|
+
// @ts-ignore
|
|
645
|
+
this.classRules = new Map();
|
|
646
|
+
this.definedRules.length = 0;
|
|
674
647
|
this.baseLayer.reset();
|
|
675
648
|
this.themeLayer.reset();
|
|
676
649
|
this.presetLayer.reset();
|
|
@@ -685,7 +658,13 @@ class MasterCSS {
|
|
|
685
658
|
}
|
|
686
659
|
add(...classNames) {
|
|
687
660
|
for (const className of classNames){
|
|
688
|
-
this.
|
|
661
|
+
const rules = this.classRules.get(className);
|
|
662
|
+
if (rules) continue;
|
|
663
|
+
const newRules = this.generate(className);
|
|
664
|
+
if (newRules.length) {
|
|
665
|
+
newRules.forEach((eachSyntaxRule)=>eachSyntaxRule.layer.insert(eachSyntaxRule));
|
|
666
|
+
this.classRules.set(className, newRules);
|
|
667
|
+
}
|
|
689
668
|
}
|
|
690
669
|
return this;
|
|
691
670
|
}
|
|
@@ -694,27 +673,10 @@ class MasterCSS {
|
|
|
694
673
|
* class name 從 DOM tree 中被移除,
|
|
695
674
|
* 匹配並刪除對應的 rule
|
|
696
675
|
*/ for (const className of classNames){
|
|
697
|
-
const
|
|
698
|
-
if (
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
});
|
|
702
|
-
} else {
|
|
703
|
-
const atIndex = className.indexOf('@');
|
|
704
|
-
if (atIndex !== -1) {
|
|
705
|
-
const name = className.slice(0, atIndex);
|
|
706
|
-
const componentClasses = this.components.get(name);
|
|
707
|
-
if (componentClasses) {
|
|
708
|
-
const atToken = className.slice(atIndex);
|
|
709
|
-
componentClasses.forEach((componentClass)=>{
|
|
710
|
-
this.componentsLayer.delete(componentClass + atToken + ' ' + className);
|
|
711
|
-
});
|
|
712
|
-
} else {
|
|
713
|
-
this.generalLayer.delete(className);
|
|
714
|
-
}
|
|
715
|
-
} else {
|
|
716
|
-
this.generalLayer.delete(className);
|
|
717
|
-
}
|
|
676
|
+
const rules = this.classRules.get(className);
|
|
677
|
+
if (rules) {
|
|
678
|
+
rules.forEach((rule)=>rule.layer.delete(rule.key));
|
|
679
|
+
this.classRules.delete(className);
|
|
718
680
|
}
|
|
719
681
|
}
|
|
720
682
|
}
|