@master/css 2.0.0-rc.25 → 2.0.0-rc.27

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 (93) hide show
  1. package/dist/common.cjs +124 -0
  2. package/dist/common.d.ts +22 -0
  3. package/dist/common.mjs +106 -0
  4. package/dist/config/functions.cjs +40 -41
  5. package/dist/config/functions.mjs +39 -40
  6. package/dist/config/index.cjs +7 -7
  7. package/dist/config/index.d.ts +12 -13
  8. package/dist/config/index.mjs +6 -6
  9. package/dist/config/queries.cjs +17 -0
  10. package/dist/config/queries.d.ts +22 -0
  11. package/dist/config/queries.mjs +15 -0
  12. package/dist/config/rules.cjs +964 -851
  13. package/dist/config/rules.d.ts +8 -5
  14. package/dist/config/rules.mjs +966 -852
  15. package/dist/config/selectors.cjs +0 -1
  16. package/dist/config/selectors.d.ts +0 -1
  17. package/dist/config/selectors.mjs +0 -1
  18. package/dist/config/{semantics.cjs → utilities.cjs} +2 -5
  19. package/dist/config/{semantics.d.ts → utilities.d.ts} +2 -5
  20. package/dist/config/{semantics.mjs → utilities.mjs} +2 -5
  21. package/dist/config/variables.mjs +2 -2
  22. package/dist/core.cjs +260 -195
  23. package/dist/core.d.ts +20 -16
  24. package/dist/core.mjs +258 -193
  25. package/dist/index.cjs +45 -15
  26. package/dist/index.d.ts +13 -3
  27. package/dist/index.mjs +15 -7
  28. package/dist/layer.cjs +25 -20
  29. package/dist/layer.d.ts +26 -9
  30. package/dist/layer.mjs +22 -19
  31. package/dist/rule.cjs +147 -125
  32. package/dist/rule.d.ts +58 -20
  33. package/dist/rule.mjs +147 -125
  34. package/dist/tokens/screen-sizes.cjs +2 -2
  35. package/dist/tokens/screen-sizes.mjs +2 -2
  36. package/dist/utils/are-rule-modes-equal.cjs +7 -0
  37. package/dist/utils/are-rule-modes-equal.d.ts +2 -0
  38. package/dist/utils/are-rule-modes-equal.mjs +5 -0
  39. package/dist/utils/are-rule-queries-equal.cjs +22 -0
  40. package/dist/utils/are-rule-queries-equal.d.ts +2 -0
  41. package/dist/utils/are-rule-queries-equal.mjs +20 -0
  42. package/dist/utils/are-rule-selectors-equal.cjs +29 -0
  43. package/dist/utils/are-rule-selectors-equal.d.ts +2 -0
  44. package/dist/utils/are-rule-selectors-equal.mjs +27 -0
  45. package/dist/utils/are-rule-states-equal.cjs +11 -0
  46. package/dist/utils/are-rule-states-equal.d.ts +2 -0
  47. package/dist/utils/are-rule-states-equal.mjs +9 -0
  48. package/dist/utils/are-rules-duplicated.cjs +17 -0
  49. package/dist/utils/are-rules-duplicated.d.ts +2 -0
  50. package/dist/utils/are-rules-duplicated.mjs +15 -0
  51. package/dist/utils/extend-config.cjs +27 -14
  52. package/dist/utils/extend-config.d.ts +1 -1
  53. package/dist/utils/extend-config.mjs +27 -14
  54. package/dist/utils/generate-css.cjs +13 -0
  55. package/dist/utils/generate-css.d.ts +2 -0
  56. package/dist/utils/generate-css.mjs +11 -0
  57. package/dist/utils/hex-to-rgb.cjs +1 -1
  58. package/dist/utils/hex-to-rgb.d.ts +1 -1
  59. package/dist/utils/hex-to-rgb.mjs +1 -1
  60. package/dist/utils/is-core-rule.cjs +9 -0
  61. package/dist/utils/is-core-rule.d.ts +1 -0
  62. package/dist/utils/is-core-rule.mjs +7 -0
  63. package/dist/{functions → utils}/reorder-for-readable-classes.cjs +12 -18
  64. package/dist/{functions → utils}/reorder-for-readable-classes.d.ts +1 -5
  65. package/dist/{functions → utils}/reorder-for-readable-classes.mjs +13 -19
  66. package/package.json +1 -1
  67. package/dist/config/media-queries.cjs +0 -7
  68. package/dist/config/media-queries.d.ts +0 -1
  69. package/dist/config/media-queries.mjs +0 -1
  70. package/dist/constants/base-unit-regex.cjs +0 -5
  71. package/dist/constants/base-unit-regex.d.ts +0 -1
  72. package/dist/constants/base-unit-regex.mjs +0 -3
  73. package/dist/constants/start-symbol.cjs +0 -10
  74. package/dist/constants/start-symbol.d.ts +0 -6
  75. package/dist/constants/start-symbol.mjs +0 -8
  76. package/dist/functions/transform-color-with-opacity.cjs +0 -9
  77. package/dist/functions/transform-color-with-opacity.d.ts +0 -1
  78. package/dist/functions/transform-color-with-opacity.mjs +0 -7
  79. package/dist/utils/concat-arrays.cjs +0 -12
  80. package/dist/utils/concat-arrays.d.ts +0 -1
  81. package/dist/utils/concat-arrays.mjs +0 -10
  82. package/dist/utils/get-type.cjs +0 -12
  83. package/dist/utils/get-type.d.ts +0 -7
  84. package/dist/utils/get-type.mjs +0 -10
  85. package/dist/utils/is-plain-object.cjs +0 -15
  86. package/dist/utils/is-plain-object.d.ts +0 -8
  87. package/dist/utils/is-plain-object.mjs +0 -13
  88. package/dist/utils/is-symbol.cjs +0 -14
  89. package/dist/utils/is-symbol.d.ts +0 -7
  90. package/dist/utils/is-symbol.mjs +0 -12
  91. package/dist/utils/rgb-to-hex.cjs +0 -7
  92. package/dist/utils/rgb-to-hex.d.ts +0 -1
  93. package/dist/utils/rgb-to-hex.mjs +0 -5
package/dist/rule.cjs CHANGED
@@ -1,25 +1,24 @@
1
1
  'use strict';
2
2
 
3
- var startSymbol = require('./constants/start-symbol.cjs');
4
3
  var cssEscape = require('./shared/utils/css-escape.cjs');
5
4
  var layer = require('./layer.cjs');
6
- var baseUnitRegex = require('./constants/base-unit-regex.cjs');
5
+ var common = require('./common.cjs');
7
6
 
8
- const atRuleRegExp = /^(media|supports|page|font-face|keyframes|counter-style|font-feature-values|property|layer|container)(?=\||{|\(|$)/;
9
7
  class Rule {
10
8
  className;
9
+ RegisteredRule;
11
10
  css;
12
11
  at;
13
12
  priority;
14
13
  natives;
15
14
  order;
16
15
  layer;
17
- stateToken;
18
16
  declarations;
19
17
  animationNames;
20
18
  variableNames;
21
19
  constructor(className, RegisteredRule, css){
22
20
  this.className = className;
21
+ this.RegisteredRule = RegisteredRule;
23
22
  this.css = css;
24
23
  this.at = {};
25
24
  this.priority = -1;
@@ -36,20 +35,20 @@ class Rule {
36
35
  const functionDefinition = functions && functions[eachValueComponent.name];
37
36
  if (functionDefinition?.transform && !eachValueComponent.bypassTransform) {
38
37
  const result = functionDefinition.transform.call(this, this.resolveValue(eachValueComponent.children, functionDefinition.unit ?? unit, bypassVariableNames, bypassParsing || eachValueComponent.name === 'calc'), bypassVariableNames);
39
- currentValue += eachValueComponent.text = typeof result === 'string' ? result : this.resolveValue(result, functionDefinition?.unit ?? unit, bypassVariableNames, bypassParsing);
38
+ currentValue += eachValueComponent.token = eachValueComponent.text = typeof result === 'string' ? result : this.resolveValue(result, functionDefinition?.unit ?? unit, bypassVariableNames, bypassParsing);
40
39
  } else {
41
- currentValue += eachValueComponent.text = eachValueComponent.name + eachValueComponent.symbol + this.resolveValue(eachValueComponent.children, functionDefinition?.unit ?? unit, bypassVariableNames, bypassParsing) + startSymbol.START_SYMBOLS[eachValueComponent.symbol];
40
+ currentValue += eachValueComponent.token = eachValueComponent.text = eachValueComponent.name + eachValueComponent.symbol + this.resolveValue(eachValueComponent.children, functionDefinition?.unit ?? unit, bypassVariableNames, bypassParsing) + common.VALUE_DELIMITERS[eachValueComponent.symbol];
42
41
  }
43
42
  break;
44
- // todo: 應挪到 parseValue 階段處理才能支援 variables: { x: 'calc(20vw-30px)' } 這種情況,並且解析上可能會比較合理、精簡
43
+ // todo: 應挪到 parseValues 階段處理才能支援 variables: { x: 'calc(20vw-30px)' } 這種情況,並且解析上可能會比較合理、精簡
45
44
  case 'variable':
46
45
  // eslint-disable-next-line no-case-declarations
47
46
  const variable = this.css.variables[eachValueComponent.name];
48
47
  if (variable) {
49
48
  const handleVariable = (normalHandler, varHandler)=>{
50
- if (variable.themes) {
51
- if (this.theme) {
52
- const themeVariable = variable.themes[this.theme] ?? variable;
49
+ if (variable.modes) {
50
+ if (this.mode) {
51
+ const themeVariable = variable.modes[this.mode] ?? variable;
53
52
  if (themeVariable?.value) {
54
53
  normalHandler(themeVariable);
55
54
  }
@@ -70,7 +69,7 @@ class Rule {
70
69
  case 'string':
71
70
  handleVariable((variable)=>{
72
71
  const valueComponents = [];
73
- this.parseValue(valueComponents, 0, variable.value, unit, '', undefined, bypassParsing, [
72
+ this.parseValues(valueComponents, 0, variable.value, unit, '', undefined, bypassParsing, [
74
73
  ...bypassVariableNames,
75
74
  eachValueComponent.name
76
75
  ]);
@@ -85,9 +84,9 @@ class Rule {
85
84
  case 'number':
86
85
  handleVariable((variable)=>{
87
86
  if (bypassParsing) {
88
- currentValue += eachValueComponent.text = variable.value;
87
+ currentValue += eachValueComponent.text = String(variable.value);
89
88
  } else {
90
- const valueComponent = this.parseValueComponent(variable.value, unit);
89
+ const valueComponent = this.parseValue(variable.value, unit);
91
90
  currentValue += eachValueComponent.text = valueComponent.value + (valueComponent.unit ?? '');
92
91
  }
93
92
  }, ()=>{
@@ -121,7 +120,7 @@ class Rule {
121
120
  }
122
121
  return currentValue;
123
122
  };
124
- this.parseValue = (currentValueComponents, i, value, unit, endSymbol, parentFunctionName, bypassParsing = false, bypassVariableNames = [])=>{
123
+ this.parseValues = (currentValueComponents, i, value, unit, endSymbol, parentFunctionName, bypassParsing = false, bypassVariableNames = [])=>{
125
124
  const root = parentFunctionName === undefined;
126
125
  const isVarFunction = !root && (parentFunctionName.endsWith('$') || parentFunctionName.endsWith('var'));
127
126
  const checkIsString = (value)=>value === '\'' || value === '"';
@@ -146,7 +145,8 @@ class Rule {
146
145
  const valueComponent = {
147
146
  type: 'variable',
148
147
  name,
149
- variable: this.css.variables[name]
148
+ variable: this.css.variables[name],
149
+ token: currentValue
150
150
  };
151
151
  if (alpha) valueComponent.alpha = alpha;
152
152
  currentValueComponents.push(valueComponent);
@@ -154,14 +154,14 @@ class Rule {
154
154
  }
155
155
  };
156
156
  handleVariable(currentValue);
157
- if (!handled && this.colored) {
157
+ if (!handled) {
158
158
  const [colorName, alpha] = currentValue.split('/');
159
159
  handleVariable(colorName, alpha);
160
160
  }
161
161
  }
162
162
  if (!handled) {
163
163
  if (!isVarFunction) {
164
- const result = baseUnitRegex.BASE_UNIT_REGEX.exec(currentValue);
164
+ const result = common.BASE_UNIT_REGEX.exec(currentValue);
165
165
  if (result) {
166
166
  currentValue = String(+result[1] * (this.css.config.baseUnit ?? 1));
167
167
  }
@@ -169,10 +169,14 @@ class Rule {
169
169
  if (bypassParsing) {
170
170
  currentValueComponents.push({
171
171
  type: 'string',
172
- value: currentValue
172
+ value: currentValue,
173
+ token: currentValue
173
174
  });
174
175
  } else {
175
- currentValueComponents.push(this.parseValueComponent(currentValue, unit));
176
+ currentValueComponents.push({
177
+ ...this.parseValue(currentValue, unit),
178
+ token: currentValue
179
+ });
176
180
  }
177
181
  }
178
182
  currentValue = '';
@@ -197,27 +201,25 @@ class Rule {
197
201
  parse();
198
202
  }
199
203
  return i;
200
- } else if (!isString && val in startSymbol.START_SYMBOLS) {
204
+ } else if (!isString && val in common.VALUE_DELIMITERS) {
201
205
  const functionName = currentValue;
202
206
  const newValueComponent = {
203
207
  type: 'function',
204
208
  name: functionName,
205
209
  symbol: val,
206
- children: []
210
+ children: [],
211
+ token: ''
207
212
  };
208
213
  currentValueComponents.push(newValueComponent);
209
214
  currentValue = '';
210
215
  const functionDefinition = val === '(' ? this.css.config.functions?.[functionName] : undefined;
211
- if (!this.colored && functionDefinition?.colored) {
212
- // @ts-ignore
213
- this.colored = true;
214
- }
215
- i = this.parseValue(newValueComponent.children, ++i, value, functionDefinition?.unit ?? unit, startSymbol.START_SYMBOLS[val], functionName || parentFunctionName || '', bypassParsing || functionName === 'calc');
216
+ i = this.parseValues(newValueComponent.children, ++i, value, functionDefinition?.unit ?? unit, common.VALUE_DELIMITERS[val], functionName || parentFunctionName || '', bypassParsing || functionName === 'calc');
216
217
  } else if ((val === '|' || val === ' ') && endSymbol !== '}' && (!isString || parentFunctionName === 'path')) {
217
218
  parse();
218
219
  currentValueComponents.push({
219
220
  type: 'separator',
220
- value: ' '
221
+ value: ' ',
222
+ token: val
221
223
  });
222
224
  } else {
223
225
  if (!isString) {
@@ -232,7 +234,8 @@ class Rule {
232
234
  currentValueComponents.push({
233
235
  type: 'separator',
234
236
  value: val,
235
- text: (val === ',' ? '' : ' ') + val + (val === ',' ? '' : ' ')
237
+ text: (val === ',' ? '' : ' ') + val + (val === ',' ? '' : ' '),
238
+ token: val
236
239
  });
237
240
  continue;
238
241
  } else if (root && (val === '#' && (currentValue || currentValueComponents.length && currentValueComponents[currentValueComponents.length - 1]['type'] !== 'separator') || [
@@ -257,22 +260,21 @@ class Rule {
257
260
  };
258
261
  Object.assign(this, RegisteredRule);
259
262
  const { id, definition } = RegisteredRule;
260
- const { analyze, transformValue, declare, transformValueComponents, create, layer: layer$1, unit, colored } = definition;
263
+ const { analyze, transformValue, declare, transformValueComponents, create, layer: layer$1, unit } = definition;
261
264
  this.layer = layer$1;
262
- this.colored = !!colored;
263
265
  if (!definition.unit) definition.unit = '';
264
266
  if (!definition.separators) definition.separators = [
265
267
  ','
266
268
  ];
267
- const { scope, important, themeDriver } = css.config;
268
- const { selectors, mediaQueries, stylesBy, animations } = css;
269
+ const { scope, important, modeDriver } = css.config;
270
+ const { selectors, queries, stylesBy, animations } = css;
269
271
  const classNames = stylesBy[className];
270
272
  if (create) create.call(this, className);
271
273
  // 1. value / selectorToken
272
274
  this.declarations = definition.declarations;
273
275
  let stateToken;
274
276
  let prefixToken;
275
- if (layer$1 === layer.Layer.Semantic) {
277
+ if (layer$1 === layer.Utility) {
276
278
  // TODO: id 使用其他方式傳遞
277
279
  stateToken = className.slice(id.length - 1);
278
280
  } else {
@@ -281,11 +283,13 @@ class Rule {
281
283
  [valueToken, prefixToken] = analyze.call(this, className);
282
284
  } else {
283
285
  const indexOfColon = className.indexOf(':');
284
- this.prefix = className.slice(0, indexOfColon + 1);
286
+ this.keyToken = className.slice(0, indexOfColon + 1);
285
287
  valueToken = className.slice(indexOfColon + 1);
286
288
  }
287
289
  this.valueComponents = [];
288
- stateToken = valueToken.slice(this.parseValue(this.valueComponents, 0, valueToken, unit, '', undefined, false, id === 'animation' || id === 'animation-name' ? Object.keys(this.css.animations) : []));
290
+ const parsedValueIndex = this.parseValues(this.valueComponents, 0, valueToken, unit, '', undefined, false, definition.includeAnimations ? Object.keys(this.css.animations) : []);
291
+ this.valueToken = valueToken.slice(0, parsedValueIndex);
292
+ stateToken = valueToken.slice(parsedValueIndex);
289
293
  }
290
294
  // 2. !important
291
295
  if (stateToken[0] === '!') {
@@ -450,110 +454,118 @@ class Rule {
450
454
  // 5. atTokens
451
455
  for(let i = 1; i < stateTokens.length; i++){
452
456
  const atToken = stateTokens[i];
457
+ this.atToken = (this.atToken || '') + '@' + atToken;
453
458
  if (atToken) {
454
459
  if (atToken === 'rtl' || atToken === 'ltr') {
455
460
  this.direction = atToken;
456
461
  } else {
457
- let type = '';
458
- let queryText;
459
- const atRuleResult = atRuleRegExp.exec(atToken);
462
+ let queryType;
463
+ const atComponents = [];
464
+ // x font-face, counter-style, keyframes, font-feature-values, property, layer
465
+ const queryTypeRegExp = /^(media|supports|container)/;
466
+ const atRuleResult = queryTypeRegExp.exec(atToken);
460
467
  if (atRuleResult) {
461
- type = atRuleResult[1];
462
- queryText = atToken.slice(type.length);
463
- } else {
464
- this.media = {
468
+ queryType = atRuleResult[1];
469
+ atComponents.push({
470
+ type: 'arbitrary',
465
471
  token: atToken,
466
- features: {}
467
- };
468
- const queryTexts = [];
469
- const analyzeToken = (typeOrFeatureToken)=>{
470
- if (typeOrFeatureToken === 'all' || typeOrFeatureToken === 'print' || typeOrFeatureToken === 'screen' || typeOrFeatureToken === 'speech') {
471
- this.media.type = typeOrFeatureToken;
472
- } else if (typeOrFeatureToken.startsWith('')) {
473
- if (typeOrFeatureToken === 'landscape' || typeOrFeatureToken === 'portrait') {
474
- queryTexts.push('(orientation:' + typeOrFeatureToken + ')');
475
- } else if (typeOrFeatureToken === 'motion' || typeOrFeatureToken === 'reduced-motion') {
476
- queryTexts.push('(prefers-reduced-motion:' + (typeOrFeatureToken === 'motion' ? 'no-preference' : 'reduce') + ')');
472
+ value: atToken.slice(queryType.length).replace(/\|/g, ' ')
473
+ });
474
+ } else {
475
+ const analyzeToken = (atComponentToken)=>{
476
+ if (atComponentToken === '&') {
477
+ atComponents.push({
478
+ type: 'operator',
479
+ token: atComponentToken,
480
+ value: 'and'
481
+ });
482
+ } else if (atComponentToken.startsWith('')) {
483
+ const targetQuery = queries[atComponentToken];
484
+ if (targetQuery && typeof targetQuery === 'string') {
485
+ const match = targetQuery.match(queryTypeRegExp);
486
+ queryType = match ? match[1] : '';
487
+ if (!queryType) throw new Error(`Invalid query '${atComponentToken}': '${targetQuery}'`);
488
+ atComponents.push({
489
+ type: 'arbitrary',
490
+ value: targetQuery.slice(match ? match[1].length + 1 : 0)
491
+ });
477
492
  } else {
478
- const targetMediaQuery = mediaQueries[typeOrFeatureToken];
479
- if (targetMediaQuery && typeof targetMediaQuery === 'string') {
480
- queryTexts.push(targetMediaQuery);
481
- } else {
482
- let featureName = '';
483
- let extremumOperator = '';
484
- let correction = 0;
485
- if (typeOrFeatureToken.startsWith('<=')) {
486
- extremumOperator = '<=';
487
- featureName = 'max-width';
488
- } else if (typeOrFeatureToken.startsWith('>=') || targetMediaQuery) {
489
- extremumOperator = '>=';
490
- featureName = 'min-width';
491
- } else if (typeOrFeatureToken.startsWith('>')) {
492
- extremumOperator = '>';
493
- featureName = 'min-width';
494
- correction = .02;
495
- } else if (typeOrFeatureToken.startsWith('<')) {
496
- extremumOperator = '<';
497
- featureName = 'max-width';
498
- correction = -.02;
499
- }
500
- const token = extremumOperator ? typeOrFeatureToken.replace(extremumOperator, '') : typeOrFeatureToken;
501
- const viewport = mediaQueries[token];
502
- switch(featureName){
503
- case 'max-width':
504
- case 'min-width':
505
- // eslint-disable-next-line no-case-declarations
506
- let featureComponent = {};
507
- if (typeof viewport === 'number') {
508
- featureComponent = {
509
- type: 'number',
510
- value: viewport + correction,
511
- unit: 'px'
512
- };
513
- } else {
514
- featureComponent = this.parseValueComponent(token, 'px');
515
- if (featureComponent.type === 'number' && featureComponent.unit === 'px') {
516
- featureComponent.value += correction;
517
- }
518
- }
519
- this.media.features[featureName] = featureComponent;
520
- if (featureComponent.type === 'number') {
521
- queryTexts.push('(' + featureName + ':' + (featureComponent.value + featureComponent.unit) + ')');
493
+ // todo: container queries
494
+ queryType = 'media';
495
+ let featureName = '';
496
+ let extremumOperator = '';
497
+ let correction = 0;
498
+ if (atComponentToken.startsWith('<=')) {
499
+ extremumOperator = '<=';
500
+ featureName = 'max-width';
501
+ } else if (atComponentToken.startsWith('>=') || targetQuery) {
502
+ extremumOperator = '>=';
503
+ featureName = 'min-width';
504
+ } else if (atComponentToken.startsWith('>')) {
505
+ extremumOperator = '>';
506
+ featureName = 'min-width';
507
+ correction = .02;
508
+ } else if (atComponentToken.startsWith('<')) {
509
+ extremumOperator = '<';
510
+ featureName = 'max-width';
511
+ correction = -.02;
512
+ }
513
+ const token = extremumOperator ? atComponentToken.replace(extremumOperator, '') : atComponentToken;
514
+ const viewport = queries[token];
515
+ switch(featureName){
516
+ case 'max-width':
517
+ case 'min-width':
518
+ // eslint-disable-next-line no-case-declarations
519
+ if (typeof viewport === 'number') {
520
+ atComponents.push({
521
+ type: 'feature',
522
+ name: featureName,
523
+ valueType: 'number',
524
+ value: viewport + correction,
525
+ unit: 'px'
526
+ });
527
+ } else {
528
+ const valueComponent = this.parseValue(token, 'px');
529
+ if (valueComponent.type === 'number') {
530
+ atComponents.push({
531
+ type: 'feature',
532
+ name: featureName,
533
+ valueType: 'number',
534
+ value: valueComponent.value + correction,
535
+ unit: valueComponent.unit
536
+ });
522
537
  } else {
523
- queryTexts.push('(' + featureName + ':' + featureComponent.value + ')');
538
+ atComponents.push({
539
+ type: 'feature',
540
+ name: featureName,
541
+ valueType: 'string',
542
+ value: token
543
+ });
524
544
  }
525
- break;
526
- }
545
+ }
546
+ break;
527
547
  }
528
548
  }
529
549
  }
530
550
  };
531
551
  const isAmpersandIncluded = atToken.includes('&');
532
552
  if (isAmpersandIncluded) {
533
- const typeOrFeatureTokens = atToken.split('&');
534
- for (const typeOrFeatureToken of typeOrFeatureTokens){
535
- analyzeToken(typeOrFeatureToken);
553
+ const typeOrFeatureTokens = atToken.split(/(&|,)/);
554
+ for (const atComponentToken of typeOrFeatureTokens){
555
+ analyzeToken(atComponentToken);
536
556
  }
537
557
  } else {
538
558
  analyzeToken(atToken);
539
559
  }
540
- if (this.media.type) {
541
- queryText = this.media.type;
542
- }
543
- if (queryTexts.length) {
544
- queryText = queryTexts.join(' and ');
545
- }
546
- if (!queryText) {
560
+ if (!atComponents.length) {
547
561
  if (!isAmpersandIncluded) {
548
- this.theme = atToken;
562
+ this.mode = atToken;
549
563
  continue;
550
564
  }
551
- } else {
552
- type = 'media';
553
565
  }
554
566
  }
555
- if (queryText) {
556
- this.at[type] = (type in this.at ? this.at[type] + ' and ' : '') + queryText.replace(/\|/g, ' ');
567
+ if (queryType) {
568
+ this.at[queryType] = atComponents;
557
569
  }
558
570
  }
559
571
  }
@@ -591,14 +603,14 @@ class Rule {
591
603
  }
592
604
  propertiesText.push(propertyText + ((this.important || important) && !propertyText.endsWith('!important') ? '!important' : ''));
593
605
  };
594
- const prefix = propertyName + ':';
606
+ const keyToken = propertyName + ':';
595
607
  const declarations = this.declarations[propertyName];
596
608
  if (Array.isArray(declarations)) {
597
609
  for (const value of declarations){
598
- push(prefix + String(value));
610
+ push(keyToken + String(value));
599
611
  }
600
612
  } else {
601
- push(prefix + String(declarations));
613
+ push(keyToken + String(declarations));
602
614
  }
603
615
  }
604
616
  // 創建 Natives
@@ -612,7 +624,7 @@ class Rule {
612
624
  const prefixSelectors = this.vendorPrefixSelectors[prefixSelectorVendor];
613
625
  const suffixSelectors = this.vendorSuffixSelectors[eachSuffixSelectorVendor];
614
626
  const prefixTexts = prefixSelectors.map((eachPrefixSelector)=>eachPrefixSelector + prefixText);
615
- const getCssText = (name)=>prefixTexts.map((eachPrefixText)=>(this.theme && themeDriver !== 'media' ? themeDriver === 'host' ? `:host(.${this.theme}) ` : `.${this.theme} ` : '') + (scope ? scope + ' ' : '') + eachPrefixText).reduce((arr, eachPrefixText)=>{
627
+ const getCssText = (name)=>prefixTexts.map((eachPrefixText)=>(this.mode && modeDriver !== 'media' ? modeDriver === 'host' ? `:host(.${this.mode}) ` : `.${this.mode} ` : '') + (scope ? scope + ' ' : '') + eachPrefixText).reduce((arr, eachPrefixText)=>{
616
628
  arr.push(suffixSelectors.reduce((_arr, eachSuffixSelector)=>{
617
629
  _arr.push(eachPrefixText + '.' + cssEscape(name) + eachSuffixSelector);
618
630
  return _arr;
@@ -621,10 +633,10 @@ class Rule {
621
633
  }, []).join(',');
622
634
  let cssText = getCssText(className) + (classNames ? classNames.reduce((str, className)=>str + ',' + getCssText(className), '') : '') + '{' + propertiesText.join(';') + '}';
623
635
  for (const key of Object.keys(this.at).sort((_a, b)=>b === 'supports' ? -1 : 1)){
624
- cssText = '@' + key + (key.includes(' ') ? '' : ' ') + this.at[key] + '{' + cssText + '}';
636
+ cssText = '@' + key + (key.includes(' ') ? '' : ' ') + this.at[key].map((eachAtComponent)=>this.resolveAtComponent(eachAtComponent)).join(' ') + '{' + cssText + '}';
625
637
  }
626
- if (this.theme && themeDriver === 'media') {
627
- cssText = `@media(prefers-color-scheme:${this.theme}){` + cssText + '}';
638
+ if (this.mode && modeDriver === 'media') {
639
+ cssText = `@media(prefers-color-scheme:${this.mode}){` + cssText + '}';
628
640
  }
629
641
  this.natives.push({
630
642
  text: cssText
@@ -633,12 +645,22 @@ class Rule {
633
645
  }
634
646
  }
635
647
  }
648
+ resolveAtComponent(atComponent) {
649
+ switch(atComponent.type){
650
+ case 'arbitrary':
651
+ return atComponent.value;
652
+ case 'feature':
653
+ return '(' + atComponent.name + ':' + atComponent.value + (atComponent.unit || '') + ')';
654
+ case 'operator':
655
+ return atComponent.value;
656
+ }
657
+ }
636
658
  resolveValue;
637
659
  get text() {
638
660
  return this.natives.map((eachNative)=>eachNative.text).join('');
639
661
  }
640
- parseValue;
641
- parseValueComponent(token, unit = this.definition.unit) {
662
+ parseValues;
663
+ parseValue(token, unit = this.definition.unit) {
642
664
  const defaultUnit = unit ?? this.definition.unit;
643
665
  let newUnit = '';
644
666
  let value;
@@ -669,7 +691,7 @@ class Rule {
669
691
  type: 'number'
670
692
  };
671
693
  }
672
- const matches = token.match(/^([+-.]?\d+(\.?\d+)?)(%|cm|mm|q|in|pt|pc|px|em|rem|ex|rex|cap|rcap|ch|rch|ic|ric|lh|rlh|vw|svw|lvw|dvw|vh|svh|lvh|dvh|vi|svi|lvi|dvi|vb|svb|lvb|dvb|vmin|svmin|lvmin|dvmin|vmax|svmax|lvmax|dvmax|cqw|cqh|cqi|cqb|cqmin|cqmax|deg|grad|rad|turn|s|ms|hz|khz|dpi|dpcm|dppx|x|fr|db|st)?$/);
694
+ const matches = token.match(common.UNIT_REGEX);
673
695
  // ['0.5deg', '0.5', 'deg', index: 0, input: '0.5deg', groups: undefined]
674
696
  if (matches) {
675
697
  value = +matches[1];
package/dist/rule.d.ts CHANGED
@@ -1,41 +1,68 @@
1
1
  import MasterCSS, { type Variable } from './core';
2
- import { Layer } from './layer';
2
+ import Layer from './layer';
3
3
  import { type PropertiesHyphen } from 'csstype';
4
4
  export declare class Rule {
5
5
  readonly className: string;
6
+ readonly RegisteredRule: RegisteredRule;
6
7
  css: MasterCSS;
7
- readonly at: Record<string, string>;
8
+ readonly at: Record<string, AtComponent[]>;
8
9
  readonly priority: number;
9
10
  readonly natives: NativeRule[];
10
11
  readonly order: number;
11
12
  readonly layer: Layer;
12
- readonly stateToken: string;
13
13
  readonly declarations?: PropertiesHyphen;
14
14
  animationNames?: string[];
15
15
  variableNames?: string[];
16
16
  constructor(className: string, RegisteredRule: RegisteredRule, css: MasterCSS);
17
+ resolveAtComponent(atComponent: AtComponent): string;
17
18
  resolveValue: (valueComponents: ValueComponent[], unit: string, bypassVariableNames: string[], bypassParsing: boolean) => string;
18
19
  get text(): string;
19
- parseValue: (currentValueComponents: ValueComponent[], i: number, value: string, unit: string, endSymbol: string, parentFunctionName?: string, bypassParsing?: boolean, bypassVariableNames?: string[]) => number;
20
- parseValueComponent(token: string | number, unit?: any): StringValueComponent | NumericValueComponent;
20
+ parseValues: (currentValueComponents: ValueComponent[], i: number, value: string, unit: string, endSymbol: string, parentFunctionName?: string, bypassParsing?: boolean, bypassVariableNames?: string[]) => number;
21
+ parseValue(token: string | number, unit?: any): {
22
+ value: string;
23
+ type: 'string';
24
+ } | {
25
+ value: number;
26
+ unit: string;
27
+ type: 'number';
28
+ };
29
+ }
30
+ export type AtComponent = AtArbitraryComponent | AtFeatureComponent | AtOperatorComponent;
31
+ export interface AtArbitraryComponent {
32
+ type: 'arbitrary';
33
+ token?: string;
34
+ value: string;
35
+ }
36
+ export interface AtFeatureComponent {
37
+ type: 'feature';
38
+ token?: string;
39
+ name: string;
40
+ valueType: 'number' | 'string';
41
+ value: string | number;
42
+ unit?: string;
43
+ }
44
+ export interface AtOperatorComponent {
45
+ type: 'operator';
46
+ token: '&';
47
+ value: 'and';
21
48
  }
22
49
  export type ValueComponent = StringValueComponent | NumericValueComponent | FunctionValueComponent | VariableValueComponent | SeparatorValueComponent;
23
50
  export interface StringValueComponent {
24
51
  text?: string;
25
- token?: string;
52
+ token: string;
26
53
  type: 'string';
27
54
  value: string;
28
55
  }
29
56
  export interface NumericValueComponent {
30
57
  text?: string;
31
- token?: string;
58
+ token: string;
32
59
  type: 'number';
33
60
  value: number;
34
61
  unit?: string;
35
62
  }
36
63
  export interface FunctionValueComponent {
37
64
  text?: string;
38
- token?: string;
65
+ token: string;
39
66
  type: 'function';
40
67
  name: string;
41
68
  symbol: string;
@@ -44,7 +71,7 @@ export interface FunctionValueComponent {
44
71
  }
45
72
  export interface VariableValueComponent {
46
73
  text?: string;
47
- token?: string;
74
+ token: string;
48
75
  type: 'variable';
49
76
  name: string;
50
77
  alpha?: string;
@@ -53,41 +80,52 @@ export interface VariableValueComponent {
53
80
  }
54
81
  export interface SeparatorValueComponent {
55
82
  text?: string;
83
+ token: string;
56
84
  type: 'separator';
57
85
  value: string;
58
86
  }
59
87
  export interface Rule extends RegisteredRule {
60
- colored: boolean;
61
- prefix: string;
62
88
  token: string;
63
89
  vendorPrefixSelectors: Record<string, string[]>;
64
90
  vendorSuffixSelectors: Record<string, string[]>;
65
91
  important: boolean;
66
- media: MediaQuery;
67
92
  direction: string;
68
- theme: string;
93
+ mode: string;
69
94
  unitToken: string;
95
+ keyToken: string;
96
+ valueToken: string;
97
+ stateToken: string;
98
+ atToken: string;
70
99
  hasWhere: boolean;
71
100
  valueComponents: Array<ValueComponent>;
72
101
  }
73
102
  export interface RegisteredRule {
74
103
  id: string;
75
- match?: RegExp;
76
- variables?: any;
104
+ key?: string;
105
+ keys: string[];
106
+ matchers: {
107
+ key?: RegExp;
108
+ variable?: RegExp;
109
+ value?: RegExp;
110
+ arbitrary?: RegExp;
111
+ };
112
+ variables: Record<string, Variable>;
77
113
  order: number;
78
114
  definition: RuleDefinition;
79
115
  }
80
116
  export interface RuleDefinition {
81
117
  layer?: Layer;
82
- match?: RegExp | [string, string[]?];
118
+ matcher?: RegExp;
119
+ sign?: string;
120
+ key?: string;
121
+ subkey?: string;
122
+ ambiguousKeys?: string[];
123
+ ambiguousValues?: (RegExp | string)[];
83
124
  variables?: string[];
84
125
  separators?: string[];
85
- shorthand?: string;
86
- colored?: boolean;
87
- numeric?: boolean;
88
126
  unit?: any;
89
- native?: boolean;
90
127
  declarations?: PropertiesHyphen;
128
+ includeAnimations?: boolean;
91
129
  analyze?: (this: Rule, className: string) => [valueToken: string, prefixToken?: string];
92
130
  transformValue?(this: Rule, value: string): string;
93
131
  transformValueComponents?(this: Rule, valueComponents: ValueComponent[]): ValueComponent[];