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