@master/css-engine 2.0.0-rc.70
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/README.md +57 -0
- package/dist/animation-rule.d.ts +12 -0
- package/dist/animation-rule.mjs +38 -0
- package/dist/common.d.ts +40 -0
- package/dist/common.mjs +114 -0
- package/dist/compile-manifest.d.ts +54 -0
- package/dist/compile-manifest.mjs +451 -0
- package/dist/compiler.d.ts +32 -0
- package/dist/compiler.mjs +38 -0
- package/dist/core.d.ts +141 -0
- package/dist/core.mjs +848 -0
- package/dist/emitted-globals.d.ts +4 -0
- package/dist/emitted-globals.mjs +1 -0
- package/dist/hydration-manifest.d.ts +4 -0
- package/dist/hydration-manifest.mjs +61 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.mjs +15 -0
- package/dist/key-aliases.d.ts +4 -0
- package/dist/key-aliases.mjs +95 -0
- package/dist/layer.d.ts +17 -0
- package/dist/layer.mjs +78 -0
- package/dist/namespaces.d.ts +5 -0
- package/dist/namespaces.mjs +28 -0
- package/dist/native-value-namespaces.d.ts +9 -0
- package/dist/native-value-namespaces.mjs +346 -0
- package/dist/non-layer.d.ts +12 -0
- package/dist/non-layer.mjs +53 -0
- package/dist/rule.d.ts +7 -0
- package/dist/rule.mjs +14 -0
- package/dist/theme-layer.d.ts +21 -0
- package/dist/theme-layer.mjs +52 -0
- package/dist/utility-layer.d.ts +10 -0
- package/dist/utility-layer.mjs +118 -0
- package/dist/utility.d.ts +102 -0
- package/dist/utility.mjs +1263 -0
- package/dist/utils/collect-animation-names.d.ts +10 -0
- package/dist/utils/collect-animation-names.mjs +61 -0
- package/dist/utils/collect-variable-names.d.ts +3 -0
- package/dist/utils/collect-variable-names.mjs +18 -0
- package/dist/utils/compare-rule-priority.d.ts +14 -0
- package/dist/utils/compare-rule-priority.mjs +136 -0
- package/dist/utils/css-variables.d.ts +12 -0
- package/dist/utils/css-variables.mjs +197 -0
- package/dist/utils/find-native-css-rule-index.d.ts +1 -0
- package/dist/utils/find-native-css-rule-index.mjs +10 -0
- package/dist/utils/generate-at.d.ts +2 -0
- package/dist/utils/generate-at.mjs +32 -0
- package/dist/utils/generate-selector.d.ts +2 -0
- package/dist/utils/generate-selector.mjs +48 -0
- package/dist/utils/natural-compare.d.ts +2 -0
- package/dist/utils/natural-compare.mjs +6 -0
- package/dist/utils/parse-at.d.ts +44 -0
- package/dist/utils/parse-at.mjs +179 -0
- package/dist/utils/parse-pair.d.ts +8 -0
- package/dist/utils/parse-pair.mjs +46 -0
- package/dist/utils/parse-selector.d.ts +19 -0
- package/dist/utils/parse-selector.mjs +124 -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.d.ts +1 -0
- package/dist/utils/replace-char-outside-quotes.mjs +19 -0
- package/dist/utils/split-char-outside-quotes.d.ts +1 -0
- package/dist/utils/split-char-outside-quotes.mjs +27 -0
- package/dist/utils/wrap-at-rules.d.ts +1 -0
- package/dist/utils/wrap-at-rules.mjs +10 -0
- package/dist/variable-rule.d.ts +26 -0
- package/dist/variable-rule.mjs +105 -0
- package/package.json +1 -0
package/dist/utility.mjs
ADDED
|
@@ -0,0 +1,1263 @@
|
|
|
1
|
+
import { cssEscape } from '@master/css-lexer';
|
|
2
|
+
import UtilityType from '@master/css-schema/utility-type';
|
|
3
|
+
import { VALUE_DELIMITERS, AT_IDENTIFIERS, BASE_UNIT_REGEX } from './common.mjs';
|
|
4
|
+
import parseValue from './utils/parse-value.mjs';
|
|
5
|
+
import parseAt from './utils/parse-at.mjs';
|
|
6
|
+
import generateAt from './utils/generate-at.mjs';
|
|
7
|
+
import parseSelector from './utils/parse-selector.mjs';
|
|
8
|
+
import generateSelector from './utils/generate-selector.mjs';
|
|
9
|
+
import { calcRulePriority } from './utils/compare-rule-priority.mjs';
|
|
10
|
+
import collectVariableNames from './utils/collect-variable-names.mjs';
|
|
11
|
+
import wrapAtRules from './utils/wrap-at-rules.mjs';
|
|
12
|
+
import { createAlphaColorValue, createCSSVariableReference, normalizeVariableValue, replaceCSSVariableReferences, createNegativeNumberVariableReference, createNumberVariableReference } from './utils/css-variables.mjs';
|
|
13
|
+
import collectAnimationNames from './utils/collect-animation-names.mjs';
|
|
14
|
+
|
|
15
|
+
function isVariantToken(value) {
|
|
16
|
+
return /^:{1,2}[-_a-zA-Z][-_a-zA-Z0-9]*$/.test(value) || /^@[-_a-zA-Z][-_a-zA-Z0-9]*$/.test(value);
|
|
17
|
+
}
|
|
18
|
+
function matchesPatternUtilityName(className, name) {
|
|
19
|
+
if (!className.startsWith(name)) return false;
|
|
20
|
+
const next = className[name.length];
|
|
21
|
+
return next === undefined || next === '!' || next === '*' || next === '>' || next === '+' || next === '~' || next === ':' || next === '[' || next === '@' || next === '_' || next === '.';
|
|
22
|
+
}
|
|
23
|
+
function getPatternUtilityMatch(className, matcher) {
|
|
24
|
+
if (matcher.type !== 'pattern') return;
|
|
25
|
+
for (const value of matcher.values){
|
|
26
|
+
const name = matcher.prefix + value;
|
|
27
|
+
if (matchesPatternUtilityName(className, name)) {
|
|
28
|
+
return {
|
|
29
|
+
value,
|
|
30
|
+
length: name.length
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function getUtilityPatternMatch(className, utility) {
|
|
36
|
+
for (const matcher of utility.matchers){
|
|
37
|
+
const match = getPatternUtilityMatch(className, matcher);
|
|
38
|
+
if (match) return match;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function getExactUtilityDefinitionMatch(className, utility) {
|
|
42
|
+
for (const matcher of utility.matchers){
|
|
43
|
+
if (matcher.type === 'static' && matchesPatternUtilityName(className, matcher.name)) {
|
|
44
|
+
return {
|
|
45
|
+
length: matcher.name.length
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const ANIMATION_REFERENCE_PROPERTIES = new Set([
|
|
51
|
+
'animation',
|
|
52
|
+
'animation-name'
|
|
53
|
+
]);
|
|
54
|
+
function utilityMayReferenceAnimations(utility) {
|
|
55
|
+
const emit = utility.emit;
|
|
56
|
+
switch(emit.type){
|
|
57
|
+
case 'declarations':
|
|
58
|
+
return emit.declarations.some((property)=>ANIMATION_REFERENCE_PROPERTIES.has(property));
|
|
59
|
+
case 'property':
|
|
60
|
+
return ANIMATION_REFERENCE_PROPERTIES.has(emit.property);
|
|
61
|
+
case 'template':
|
|
62
|
+
return Object.keys(emit.declarations).some((property)=>ANIMATION_REFERENCE_PROPERTIES.has(property));
|
|
63
|
+
case 'static':
|
|
64
|
+
return emit.rules.some((rule)=>Object.keys(rule.declarations).some((property)=>ANIMATION_REFERENCE_PROPERTIES.has(property)));
|
|
65
|
+
default:
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function formatMasterBaseUnitValue(value, baseUnit, rootSize) {
|
|
70
|
+
const resolved = value * baseUnit / rootSize;
|
|
71
|
+
return String(Object.is(resolved, -0) ? 0 : resolved).replace(/^(-?)0\./, '$1.') + 'rem';
|
|
72
|
+
}
|
|
73
|
+
function composeSelectorTemplate(current, next) {
|
|
74
|
+
if (!next || next === '&') return current;
|
|
75
|
+
return next.replace(/&/g, current || '&');
|
|
76
|
+
}
|
|
77
|
+
function cloneAtRules(atRules) {
|
|
78
|
+
if (!atRules) return;
|
|
79
|
+
const cloned = {};
|
|
80
|
+
for (const id of AT_IDENTIFIERS){
|
|
81
|
+
const nodes = atRules[id];
|
|
82
|
+
if (nodes?.length) cloned[id] = [
|
|
83
|
+
...nodes
|
|
84
|
+
];
|
|
85
|
+
}
|
|
86
|
+
return cloned;
|
|
87
|
+
}
|
|
88
|
+
function mergeAtRuleNodeMap(current, atRule) {
|
|
89
|
+
const merged = cloneAtRules(current) || {};
|
|
90
|
+
merged[atRule.id] = [
|
|
91
|
+
...merged[atRule.id] || [],
|
|
92
|
+
...atRule.nodes
|
|
93
|
+
];
|
|
94
|
+
return merged;
|
|
95
|
+
}
|
|
96
|
+
function mergeBranch(base, branch, css, key) {
|
|
97
|
+
let atRules = cloneAtRules(base.atRules);
|
|
98
|
+
for (const atRule of branch.atRuleNodes || []){
|
|
99
|
+
atRules = mergeAtRuleNodeMap(atRules, atRule);
|
|
100
|
+
}
|
|
101
|
+
if (!branch.atRuleNodes?.length) {
|
|
102
|
+
for (const atRule of branch.atRules || []){
|
|
103
|
+
const parsed = parseAt(atRule, css);
|
|
104
|
+
atRules = mergeAtRuleNodeMap(atRules, parsed);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (branch.selectorNodes?.length && !branch.selector) {
|
|
108
|
+
return {
|
|
109
|
+
...base,
|
|
110
|
+
key: base.key + key,
|
|
111
|
+
selectorNodes: branch.selectorNodes,
|
|
112
|
+
...atRules ? {
|
|
113
|
+
atRules
|
|
114
|
+
} : {},
|
|
115
|
+
...branch.layer || base.layer ? {
|
|
116
|
+
layer: branch.layer || base.layer
|
|
117
|
+
} : {},
|
|
118
|
+
valid: base.valid !== false && !(base.layer && branch.layer && base.layer !== branch.layer)
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
const layer = branch.layer || base.layer;
|
|
122
|
+
return {
|
|
123
|
+
...base,
|
|
124
|
+
key: base.key + key,
|
|
125
|
+
selectorTemplate: composeSelectorTemplate(base.selectorTemplate, branch.selector),
|
|
126
|
+
...atRules ? {
|
|
127
|
+
atRules
|
|
128
|
+
} : {},
|
|
129
|
+
...layer ? {
|
|
130
|
+
layer
|
|
131
|
+
} : {},
|
|
132
|
+
valid: base.valid !== false && !(base.layer && branch.layer && base.layer !== branch.layer)
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function findClosingParen(value, start) {
|
|
136
|
+
let depth = 0;
|
|
137
|
+
let quote = '';
|
|
138
|
+
for(let index = start; index < value.length; index++){
|
|
139
|
+
const char = value[index];
|
|
140
|
+
if (quote) {
|
|
141
|
+
if (char === '\\') {
|
|
142
|
+
index++;
|
|
143
|
+
} else if (char === quote) {
|
|
144
|
+
quote = '';
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (char === '"' || char === '\'') {
|
|
149
|
+
quote = char;
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
if (char === '(') depth++;
|
|
153
|
+
if (char === ')') {
|
|
154
|
+
depth--;
|
|
155
|
+
if (depth === 0) return index;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return -1;
|
|
159
|
+
}
|
|
160
|
+
function splitTopLevelArguments(value) {
|
|
161
|
+
const parts = [];
|
|
162
|
+
let depth = 0;
|
|
163
|
+
let start = 0;
|
|
164
|
+
for(let i = 0; i < value.length; i++){
|
|
165
|
+
const char = value[i];
|
|
166
|
+
if (char === '(') {
|
|
167
|
+
depth++;
|
|
168
|
+
} else if (char === ')') {
|
|
169
|
+
depth--;
|
|
170
|
+
} else if (char === ',' && depth === 0) {
|
|
171
|
+
parts.push(value.slice(start, i), char);
|
|
172
|
+
start = i + 1;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
parts.push(value.slice(start));
|
|
176
|
+
return parts;
|
|
177
|
+
}
|
|
178
|
+
function hasTopLevelOperator(value) {
|
|
179
|
+
let depth = 0;
|
|
180
|
+
for(let i = 0; i < value.length; i++){
|
|
181
|
+
const char = value[i];
|
|
182
|
+
if (char === '(') {
|
|
183
|
+
depth++;
|
|
184
|
+
} else if (char === ')') {
|
|
185
|
+
depth--;
|
|
186
|
+
} else if (depth === 0 && (char === '+' || char === '-' || char === '*' || char === '/')) {
|
|
187
|
+
let previousIndex = i - 1;
|
|
188
|
+
while(value[previousIndex] === ' ')previousIndex--;
|
|
189
|
+
const previousChar = value[previousIndex];
|
|
190
|
+
if ((char === '+' || char === '-') && (!previousChar || previousChar === '(' || previousChar === ',' || previousChar === ' ')) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
function wrapCalcArguments(value) {
|
|
199
|
+
return splitTopLevelArguments(value).map((part)=>{
|
|
200
|
+
if (part === ',') return part;
|
|
201
|
+
const trimmed = part.trim();
|
|
202
|
+
if (!trimmed || /^(?:calc|clamp|min|max|var)\(/.test(trimmed) || !hasTopLevelOperator(trimmed)) {
|
|
203
|
+
return part;
|
|
204
|
+
}
|
|
205
|
+
const leadingWhitespace = part.match(/^\s*/)[0];
|
|
206
|
+
const trailingWhitespace = part.match(/\s*$/)[0];
|
|
207
|
+
return `${leadingWhitespace}calc(${trimmed})${trailingWhitespace}`;
|
|
208
|
+
}).join('');
|
|
209
|
+
}
|
|
210
|
+
class Utility {
|
|
211
|
+
name;
|
|
212
|
+
css;
|
|
213
|
+
registeredUtility;
|
|
214
|
+
fixedClass;
|
|
215
|
+
native;
|
|
216
|
+
nodes;
|
|
217
|
+
atRules;
|
|
218
|
+
priority;
|
|
219
|
+
type = UtilityType.Normal;
|
|
220
|
+
declarations;
|
|
221
|
+
declarationRules;
|
|
222
|
+
layer;
|
|
223
|
+
layerName;
|
|
224
|
+
explicitLayerName;
|
|
225
|
+
valid = true;
|
|
226
|
+
animationNames;
|
|
227
|
+
variableNames;
|
|
228
|
+
branchIndex;
|
|
229
|
+
branchCount = 1;
|
|
230
|
+
selectorTemplate;
|
|
231
|
+
variantBranchKey;
|
|
232
|
+
invalidValueSyntax = false;
|
|
233
|
+
constructor(name, css, registeredUtility, fixedClass, mode, branchIndex = 0){
|
|
234
|
+
this.name = name;
|
|
235
|
+
this.css = css;
|
|
236
|
+
this.registeredUtility = registeredUtility;
|
|
237
|
+
this.fixedClass = fixedClass;
|
|
238
|
+
this.branchIndex = branchIndex;
|
|
239
|
+
this.mode = mode;
|
|
240
|
+
this.layerName = registeredUtility.layer || 'utilities';
|
|
241
|
+
const { name: _registeredName, key: _key, layer: _layer, atRules: _sourceAtRules, ...runtimeUtility } = registeredUtility;
|
|
242
|
+
Object.assign(this, runtimeUtility);
|
|
243
|
+
const { id, type } = registeredUtility;
|
|
244
|
+
this.type = type;
|
|
245
|
+
// 1. value / selectorToken
|
|
246
|
+
let stateToken = '';
|
|
247
|
+
const exactUtilityMatch = getExactUtilityDefinitionMatch(name, registeredUtility);
|
|
248
|
+
if (exactUtilityMatch) {
|
|
249
|
+
stateToken = name.slice(exactUtilityMatch.length);
|
|
250
|
+
} else {
|
|
251
|
+
let valueToken;
|
|
252
|
+
const patternMatch = getUtilityPatternMatch(name, registeredUtility);
|
|
253
|
+
if (patternMatch) {
|
|
254
|
+
valueToken = patternMatch.value;
|
|
255
|
+
stateToken = name.slice(patternMatch.length);
|
|
256
|
+
this.keyToken = name.slice(0, patternMatch.length - patternMatch.value.length);
|
|
257
|
+
} else if (id.endsWith('()')) {
|
|
258
|
+
valueToken = name;
|
|
259
|
+
} else if (id === 'group') {
|
|
260
|
+
valueToken = name;
|
|
261
|
+
} else {
|
|
262
|
+
const indexOfColon = name.indexOf(':');
|
|
263
|
+
this.keyToken = name.slice(0, indexOfColon + 1);
|
|
264
|
+
valueToken = name.slice(indexOfColon + 1);
|
|
265
|
+
}
|
|
266
|
+
this.valueComponents = [];
|
|
267
|
+
const parsedValueIndex = this.parseValues(this.valueComponents, 0, valueToken, '', '', undefined, false, utilityMayReferenceAnimations(registeredUtility) ? Array.from(this.css.animations.keys()) : []);
|
|
268
|
+
if (this.invalidValueSyntax) {
|
|
269
|
+
this.valid = false;
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
this.valueToken = valueToken.slice(0, parsedValueIndex);
|
|
273
|
+
if (!patternMatch) {
|
|
274
|
+
stateToken = valueToken.slice(parsedValueIndex);
|
|
275
|
+
} else if (parsedValueIndex !== valueToken.length) {
|
|
276
|
+
stateToken = valueToken.slice(parsedValueIndex) + stateToken;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// 2. !important
|
|
280
|
+
if (stateToken[0] === '!') {
|
|
281
|
+
this.important = true;
|
|
282
|
+
stateToken = stateToken.slice(1);
|
|
283
|
+
}
|
|
284
|
+
this.stateToken = stateToken;
|
|
285
|
+
const stateBranches = this.resolveStateBranches(stateToken);
|
|
286
|
+
this.branchCount = stateBranches.length;
|
|
287
|
+
const stateBranch = stateBranches[branchIndex];
|
|
288
|
+
if (!stateBranch) {
|
|
289
|
+
this.valid = false;
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
if (stateBranch.mode) this.mode = stateBranch.mode;
|
|
293
|
+
if (stateBranch.selectorNodes?.length) this.selectorNodes = stateBranch.selectorNodes;
|
|
294
|
+
if (stateBranch.selectorTemplate) this.selectorTemplate = stateBranch.selectorTemplate;
|
|
295
|
+
if (stateBranch.atRules) this.atRules = stateBranch.atRules;
|
|
296
|
+
if (stateBranch.valid === false) this.valid = false;
|
|
297
|
+
this.variantBranchKey = stateBranch.key;
|
|
298
|
+
if (this.mode && css.settings.modeTrigger === 'media') {
|
|
299
|
+
const atComp = {
|
|
300
|
+
name: 'prefers-color-scheme',
|
|
301
|
+
value: this.mode
|
|
302
|
+
};
|
|
303
|
+
if (this.atRules?.media) {
|
|
304
|
+
this.atRules.media.push(atComp);
|
|
305
|
+
} else {
|
|
306
|
+
this.atRules = {
|
|
307
|
+
media: [
|
|
308
|
+
atComp
|
|
309
|
+
]
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
if (this.atRules?.layer && this.atRules.layer.length > 1) {
|
|
314
|
+
this.valid = false;
|
|
315
|
+
}
|
|
316
|
+
if (stateBranch.layer) {
|
|
317
|
+
if (this.explicitLayerName && this.explicitLayerName !== stateBranch.layer) {
|
|
318
|
+
this.valid = false;
|
|
319
|
+
}
|
|
320
|
+
this.layerName = stateBranch.layer;
|
|
321
|
+
this.explicitLayerName = stateBranch.layer;
|
|
322
|
+
}
|
|
323
|
+
const onlyNode = this.atRules?.layer?.length === 1 && this.atRules.layer[0];
|
|
324
|
+
if (onlyNode) {
|
|
325
|
+
const layerName = String(onlyNode.value);
|
|
326
|
+
if (layerName === 'base' || layerName === 'defaults' || layerName === 'components' || layerName === 'utilities') {
|
|
327
|
+
this.layerName = layerName;
|
|
328
|
+
this.explicitLayerName = layerName;
|
|
329
|
+
this.atRules.layer = undefined;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
this.layer = css.getUtilityLayer(this.layerName);
|
|
333
|
+
// 7. value
|
|
334
|
+
let newValue;
|
|
335
|
+
if (this.valueComponents) {
|
|
336
|
+
newValue = this.resolveValue(this.valueComponents, '', [], false);
|
|
337
|
+
if (this.invalidValueSyntax) {
|
|
338
|
+
this.valid = false;
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
const dynamicDeclarationRules = this.emitDynamicDeclarationRules(newValue);
|
|
342
|
+
if (dynamicDeclarationRules) {
|
|
343
|
+
this.declarations = dynamicDeclarationRules[0]?.declarations;
|
|
344
|
+
if (dynamicDeclarationRules.length > 1 || dynamicDeclarationRules.some(({ atRules, selector })=>atRules?.length || selector)) {
|
|
345
|
+
this.declarationRules = dynamicDeclarationRules;
|
|
346
|
+
}
|
|
347
|
+
} else {
|
|
348
|
+
const declarations = this.emitDynamicDeclarations(newValue);
|
|
349
|
+
this.declarations = declarations;
|
|
350
|
+
if (declarations && registeredUtility.atRules?.length) {
|
|
351
|
+
this.declarationRules = [
|
|
352
|
+
{
|
|
353
|
+
declarations,
|
|
354
|
+
atRules: registeredUtility.atRules
|
|
355
|
+
}
|
|
356
|
+
];
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
} else {
|
|
360
|
+
const declarationRules = registeredUtility.emit.type === 'static' ? registeredUtility.emit.rules.map(({ declarations, atRules, selector })=>({
|
|
361
|
+
declarations: declarations,
|
|
362
|
+
atRules,
|
|
363
|
+
selector
|
|
364
|
+
})) : [];
|
|
365
|
+
this.declarations = declarationRules[0]?.declarations;
|
|
366
|
+
if (declarationRules.length > 1 || declarationRules.some(({ atRules, selector })=>atRules?.length || selector)) {
|
|
367
|
+
this.declarationRules = declarationRules;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
const declarationRules = this.declarationRules || (this.declarations ? [
|
|
371
|
+
{
|
|
372
|
+
declarations: this.declarations
|
|
373
|
+
}
|
|
374
|
+
] : []);
|
|
375
|
+
if (!declarationRules.some(({ declarations })=>Object.entries(declarations ?? {}).length)) {
|
|
376
|
+
this.valid = false;
|
|
377
|
+
} else {
|
|
378
|
+
for (const { declarations } of declarationRules){
|
|
379
|
+
const variableNames = collectVariableNames(declarations, this.css.variables);
|
|
380
|
+
if (variableNames) {
|
|
381
|
+
for (const variableName of variableNames){
|
|
382
|
+
if (this.variableNames) {
|
|
383
|
+
this.variableNames.add(variableName);
|
|
384
|
+
} else {
|
|
385
|
+
this.variableNames = new Set([
|
|
386
|
+
variableName
|
|
387
|
+
]);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
const animationNames = collectAnimationNames(declarations, {
|
|
392
|
+
animationNames: this.css.animations.keys(),
|
|
393
|
+
variables: this.css.variables,
|
|
394
|
+
variableNames
|
|
395
|
+
});
|
|
396
|
+
if (animationNames) {
|
|
397
|
+
for (const animationName of animationNames){
|
|
398
|
+
if (this.animationNames) {
|
|
399
|
+
this.animationNames.add(animationName);
|
|
400
|
+
} else {
|
|
401
|
+
this.animationNames = new Set([
|
|
402
|
+
animationName
|
|
403
|
+
]);
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
this.priority = calcRulePriority(this);
|
|
409
|
+
if (declarationRules.length > 1) {
|
|
410
|
+
this.nodes = declarationRules.map(({ declarations, atRules, selector })=>new UtilityRuleNode(this, declarations, atRules, selector));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
resolveVariableAlias(variableName) {
|
|
415
|
+
const variable = this.variables?.get(variableName) || this.css.variables.get(variableName);
|
|
416
|
+
if (variable) {
|
|
417
|
+
return {
|
|
418
|
+
name: variable.name ?? variableName,
|
|
419
|
+
variable
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
if (variableName[0] !== '-') return;
|
|
423
|
+
const positiveVariableName = variableName.slice(1);
|
|
424
|
+
const positiveVariable = this.variables?.get(positiveVariableName) || this.css.variables.get(positiveVariableName);
|
|
425
|
+
if (positiveVariable?.type !== 'number') return;
|
|
426
|
+
return {
|
|
427
|
+
name: positiveVariable.name ?? positiveVariableName,
|
|
428
|
+
variable: positiveVariable,
|
|
429
|
+
negative: true
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
resolveDynamicDeclarationValue(value, newValue) {
|
|
433
|
+
if (value === null) return newValue;
|
|
434
|
+
return Array.isArray(value) ? value.map((eachValue)=>eachValue === null ? newValue : eachValue).join('') : value;
|
|
435
|
+
}
|
|
436
|
+
resolveDynamicDeclarations(declarations, newValue) {
|
|
437
|
+
const resolved = {};
|
|
438
|
+
for(const propertyName in declarations){
|
|
439
|
+
resolved[propertyName] = this.resolveDynamicDeclarationValue(declarations[propertyName], newValue);
|
|
440
|
+
}
|
|
441
|
+
return resolved;
|
|
442
|
+
}
|
|
443
|
+
emitDynamicDeclarationRules(newValue) {
|
|
444
|
+
const emit = this.registeredUtility.emit;
|
|
445
|
+
if (emit.type !== 'static') return;
|
|
446
|
+
return emit.rules.map(({ declarations, atRules, selector })=>({
|
|
447
|
+
declarations: this.resolveDynamicDeclarations(declarations, newValue),
|
|
448
|
+
atRules,
|
|
449
|
+
selector
|
|
450
|
+
}));
|
|
451
|
+
}
|
|
452
|
+
emitDynamicDeclarations(newValue) {
|
|
453
|
+
const emit = this.registeredUtility.emit;
|
|
454
|
+
switch(emit.type){
|
|
455
|
+
case 'declarations':
|
|
456
|
+
{
|
|
457
|
+
const declarations = {};
|
|
458
|
+
for (const property of emit.declarations){
|
|
459
|
+
declarations[property] = newValue;
|
|
460
|
+
}
|
|
461
|
+
return declarations;
|
|
462
|
+
}
|
|
463
|
+
case 'template':
|
|
464
|
+
{
|
|
465
|
+
const declarations = {};
|
|
466
|
+
for(const propertyName in emit.declarations){
|
|
467
|
+
const propertyValue = emit.declarations[propertyName];
|
|
468
|
+
declarations[propertyName] = propertyValue == null ? newValue : Array.isArray(propertyValue) ? propertyValue.map((value)=>value == null ? newValue : value).join('') : propertyValue;
|
|
469
|
+
}
|
|
470
|
+
return declarations;
|
|
471
|
+
}
|
|
472
|
+
case 'group':
|
|
473
|
+
return this.emitGroupDeclarations(newValue);
|
|
474
|
+
case 'property':
|
|
475
|
+
return {
|
|
476
|
+
[emit.property]: newValue
|
|
477
|
+
};
|
|
478
|
+
case 'static':
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
emitGroupDeclarations(value) {
|
|
483
|
+
const declarations = {};
|
|
484
|
+
const addProp = (propertyName)=>{
|
|
485
|
+
const indexOfColon = propertyName.indexOf(':');
|
|
486
|
+
if (indexOfColon !== -1) {
|
|
487
|
+
const propName = propertyName.slice(0, indexOfColon);
|
|
488
|
+
declarations[propName] = propertyName.slice(indexOfColon + 1).replace(/\|/g, ' ');
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
const handleRule = (rule)=>{
|
|
492
|
+
const ruleDeclarations = rule.declarations;
|
|
493
|
+
for(const propertyName in ruleDeclarations){
|
|
494
|
+
let propertyValue = String(ruleDeclarations[propertyName]);
|
|
495
|
+
const important = 'important' in rule && rule.important;
|
|
496
|
+
if ((important || rule.css.settings.important) && !propertyValue.endsWith('!important')) {
|
|
497
|
+
propertyValue += '!important';
|
|
498
|
+
}
|
|
499
|
+
declarations[propertyName] = propertyValue;
|
|
500
|
+
}
|
|
501
|
+
if (rule.animationNames) {
|
|
502
|
+
if (!this.animationNames) this.animationNames = new Set();
|
|
503
|
+
for (const eachKeyframeName of rule.animationNames){
|
|
504
|
+
this.animationNames.add(eachKeyframeName);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if (rule.variableNames) {
|
|
508
|
+
if (this.variableNames) {
|
|
509
|
+
for (const eachVariableName of rule.variableNames){
|
|
510
|
+
this.variableNames.add(eachVariableName);
|
|
511
|
+
}
|
|
512
|
+
} else {
|
|
513
|
+
this.variableNames = new Set(rule.variableNames);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
};
|
|
517
|
+
const names = [];
|
|
518
|
+
let currentName = '';
|
|
519
|
+
const addName = ()=>{
|
|
520
|
+
if (currentName) {
|
|
521
|
+
names.push(currentName.replace(/ /g, '|'));
|
|
522
|
+
currentName = '';
|
|
523
|
+
}
|
|
524
|
+
};
|
|
525
|
+
let i = 1;
|
|
526
|
+
(function analyze(end) {
|
|
527
|
+
for(; i < value.length; i++){
|
|
528
|
+
const char = value[i];
|
|
529
|
+
if (!end) {
|
|
530
|
+
if (char === ';') {
|
|
531
|
+
addName();
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
if (char === '}') {
|
|
535
|
+
break;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
currentName += char;
|
|
539
|
+
if (end === char) {
|
|
540
|
+
if (end === '\'' || end === '"') {
|
|
541
|
+
let count = 0;
|
|
542
|
+
for(let j = currentName.length - 2;; j--){
|
|
543
|
+
if (currentName[j] !== '\\') {
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
count++;
|
|
547
|
+
}
|
|
548
|
+
if (count % 2) {
|
|
549
|
+
continue;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
break;
|
|
553
|
+
} else if (char in VALUE_DELIMITERS && end !== '\'' && end !== '"') {
|
|
554
|
+
i++;
|
|
555
|
+
analyze(VALUE_DELIMITERS[char]);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
})('');
|
|
559
|
+
addName();
|
|
560
|
+
for (const eachName of names){
|
|
561
|
+
const rules = this.css.generate(eachName, this.mode);
|
|
562
|
+
if (rules.length) {
|
|
563
|
+
for (const eachRule of rules){
|
|
564
|
+
handleRule(eachRule);
|
|
565
|
+
}
|
|
566
|
+
} else {
|
|
567
|
+
addProp(eachName);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
return declarations;
|
|
571
|
+
}
|
|
572
|
+
resolveStateBranches(stateToken) {
|
|
573
|
+
const [selectorToken = '', ...conditionTokens] = stateToken.split('@');
|
|
574
|
+
let branches = [
|
|
575
|
+
{
|
|
576
|
+
key: ''
|
|
577
|
+
}
|
|
578
|
+
];
|
|
579
|
+
branches = this.applySelectorTokenBranches(branches, selectorToken);
|
|
580
|
+
for (const conditionToken of conditionTokens){
|
|
581
|
+
if (this.css.modes.includes(conditionToken)) {
|
|
582
|
+
branches = branches.map((branch)=>({
|
|
583
|
+
...branch,
|
|
584
|
+
mode: conditionToken,
|
|
585
|
+
key: branch.key + '@' + conditionToken
|
|
586
|
+
}));
|
|
587
|
+
continue;
|
|
588
|
+
}
|
|
589
|
+
this.atToken = (this.atToken || '') + '@' + conditionToken;
|
|
590
|
+
const variantToken = `@${conditionToken}`;
|
|
591
|
+
const variantBranches = this.css.resolveVariant(variantToken);
|
|
592
|
+
if (variantBranches) {
|
|
593
|
+
branches = branches.flatMap((branch)=>variantBranches.map((variantBranch, index)=>mergeBranch(branch, variantBranch, this.css, `${variantToken}#${index}`)));
|
|
594
|
+
continue;
|
|
595
|
+
}
|
|
596
|
+
const atRule = parseAt(conditionToken, this.css);
|
|
597
|
+
branches = branches.map((branch)=>({
|
|
598
|
+
...branch,
|
|
599
|
+
key: branch.key + '@' + conditionToken,
|
|
600
|
+
atRules: mergeAtRuleNodeMap(branch.atRules, atRule)
|
|
601
|
+
}));
|
|
602
|
+
}
|
|
603
|
+
return branches.length ? branches : [
|
|
604
|
+
{
|
|
605
|
+
key: ''
|
|
606
|
+
}
|
|
607
|
+
];
|
|
608
|
+
}
|
|
609
|
+
applySelectorTokenBranches(branches, selectorToken) {
|
|
610
|
+
if (!selectorToken) return branches;
|
|
611
|
+
const selectorVariantTokens = [
|
|
612
|
+
...this.css.variants.keys()
|
|
613
|
+
].filter((token)=>token.startsWith(':')).sort((a, b)=>b.length - a.length);
|
|
614
|
+
let index = 0;
|
|
615
|
+
let raw = '';
|
|
616
|
+
const flushRaw = ()=>{
|
|
617
|
+
if (!raw) return;
|
|
618
|
+
const rawSelector = generateSelector(parseSelector(raw, this.css), '&');
|
|
619
|
+
branches = branches.map((branch)=>({
|
|
620
|
+
...branch,
|
|
621
|
+
key: branch.key + raw,
|
|
622
|
+
selectorTemplate: composeSelectorTemplate(branch.selectorTemplate, rawSelector),
|
|
623
|
+
selectorNodes: parseSelector(branch.selectorTemplate ? composeSelectorTemplate(branch.selectorTemplate, rawSelector)?.replace(/&/g, '') || '' : raw, this.css)
|
|
624
|
+
}));
|
|
625
|
+
raw = '';
|
|
626
|
+
};
|
|
627
|
+
while(index < selectorToken.length){
|
|
628
|
+
if (selectorToken[index] === '(') {
|
|
629
|
+
const end = findClosingParen(selectorToken, index);
|
|
630
|
+
if (end !== -1) {
|
|
631
|
+
raw += selectorToken.slice(index, end + 1);
|
|
632
|
+
index = end + 1;
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
const matchedToken = selectorVariantTokens.find((token)=>{
|
|
637
|
+
if (!selectorToken.startsWith(token, index)) return false;
|
|
638
|
+
const next = selectorToken[index + token.length];
|
|
639
|
+
return next === undefined || next === '(' || !/[-_a-zA-Z0-9]/.test(next);
|
|
640
|
+
});
|
|
641
|
+
if (!matchedToken || !isVariantToken(matchedToken)) {
|
|
642
|
+
raw += selectorToken[index++];
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
const variantBranches = this.css.resolveVariant(matchedToken);
|
|
646
|
+
if (!variantBranches) {
|
|
647
|
+
raw += selectorToken[index++];
|
|
648
|
+
continue;
|
|
649
|
+
}
|
|
650
|
+
flushRaw();
|
|
651
|
+
index += matchedToken.length;
|
|
652
|
+
let suffix = '';
|
|
653
|
+
if (selectorToken[index] === '(') {
|
|
654
|
+
const end = findClosingParen(selectorToken, index);
|
|
655
|
+
if (end !== -1) {
|
|
656
|
+
suffix = selectorToken.slice(index, end + 1);
|
|
657
|
+
index = end + 1;
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
branches = branches.flatMap((branch)=>variantBranches.map((variantBranch, branchIndex)=>{
|
|
661
|
+
const selector = variantBranch.selector && suffix ? variantBranch.selector + suffix : variantBranch.selector;
|
|
662
|
+
const merged = mergeBranch(branch, {
|
|
663
|
+
...variantBranch,
|
|
664
|
+
...selector ? {
|
|
665
|
+
selector
|
|
666
|
+
} : {}
|
|
667
|
+
}, this.css, `${matchedToken}#${branchIndex}${suffix}`);
|
|
668
|
+
const selectorTemplate = merged.selectorTemplate;
|
|
669
|
+
return {
|
|
670
|
+
...merged,
|
|
671
|
+
...selectorTemplate ? {
|
|
672
|
+
selectorNodes: parseSelector(selectorTemplate.replace(/&/g, ''), this.css)
|
|
673
|
+
} : {}
|
|
674
|
+
};
|
|
675
|
+
}));
|
|
676
|
+
}
|
|
677
|
+
flushRaw();
|
|
678
|
+
return branches;
|
|
679
|
+
}
|
|
680
|
+
get text() {
|
|
681
|
+
if (!this.valid) return '';
|
|
682
|
+
if (this.nodes) {
|
|
683
|
+
return this.nodes.map(({ text })=>text).join('');
|
|
684
|
+
}
|
|
685
|
+
if (this.declarationRules) {
|
|
686
|
+
return this.declarationRules.map(({ declarations, atRules, selector })=>this.createRuleText(declarations, atRules, selector)).join('');
|
|
687
|
+
}
|
|
688
|
+
return this.createRuleText(this.declarations);
|
|
689
|
+
}
|
|
690
|
+
createRuleText(declarations, atRules, selector) {
|
|
691
|
+
const propertiesText = [];
|
|
692
|
+
for(const propertyName in declarations){
|
|
693
|
+
const propertyValue = declarations[propertyName];
|
|
694
|
+
const propertyText = propertyName + ':' + String(propertyValue);
|
|
695
|
+
propertiesText.push(propertyText + ((this.important || this.css.settings.important) && !propertyText.endsWith('!important') ? '!important' : ''));
|
|
696
|
+
}
|
|
697
|
+
let text = this.createSelectorText(selector) + '{' + propertiesText.join(';') + '}';
|
|
698
|
+
if (this.atRules !== undefined) AT_IDENTIFIERS.forEach((id)=>{
|
|
699
|
+
const nodes = this.atRules?.[id];
|
|
700
|
+
if (!nodes) return;
|
|
701
|
+
text = generateAt({
|
|
702
|
+
id,
|
|
703
|
+
nodes
|
|
704
|
+
}) + '{' + text + '}';
|
|
705
|
+
});
|
|
706
|
+
return wrapAtRules(text, atRules);
|
|
707
|
+
}
|
|
708
|
+
get selectorText() {
|
|
709
|
+
return this.createSelectorText();
|
|
710
|
+
}
|
|
711
|
+
createSelectorText(selector) {
|
|
712
|
+
let pre = '';
|
|
713
|
+
if (this.css.settings.scope) {
|
|
714
|
+
pre = this.css.settings.scope + ' ' + pre;
|
|
715
|
+
}
|
|
716
|
+
if (this.mode) {
|
|
717
|
+
const modeSelector = this.css.getModeSelector(this.mode);
|
|
718
|
+
if (modeSelector) {
|
|
719
|
+
pre = modeSelector + ' ' + pre;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
const body = pre + '.' + cssEscape(this.fixedClass ?? this.name);
|
|
723
|
+
let base = this.selectorTemplate ? body : this.selectorNodes ? generateSelector(this.selectorNodes, body) : body;
|
|
724
|
+
if (this.selectorTemplate) {
|
|
725
|
+
base = this.selectorTemplate.replace(/&/g, base);
|
|
726
|
+
}
|
|
727
|
+
return selector ? selector.replace(/&/g, base) : base;
|
|
728
|
+
}
|
|
729
|
+
resolveValue = (valueComponents, unit, bypassVariableNames, bypassParsing)=>{
|
|
730
|
+
let currentValue = '';
|
|
731
|
+
const addVariableName = (variableName)=>{
|
|
732
|
+
if (this.variableNames) {
|
|
733
|
+
this.variableNames.add(variableName);
|
|
734
|
+
} else {
|
|
735
|
+
this.variableNames = new Set([
|
|
736
|
+
variableName
|
|
737
|
+
]);
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
const formatResolvedInlineNumber = (value)=>{
|
|
741
|
+
const parsedValue = this.parseValue(value, unit);
|
|
742
|
+
return parsedValue.type === 'number' ? String(parsedValue.value) + (parsedValue.unit || '') : parsedValue.value;
|
|
743
|
+
};
|
|
744
|
+
const resolveInlineVariable = (variable, stack = [])=>{
|
|
745
|
+
const stackIndex = stack.indexOf(variable.name);
|
|
746
|
+
if (stackIndex !== -1) {
|
|
747
|
+
throw new Error(`Circular inline variable reference: ${[
|
|
748
|
+
...stack.slice(stackIndex),
|
|
749
|
+
variable.name
|
|
750
|
+
].join(' -> ')}`);
|
|
751
|
+
}
|
|
752
|
+
if (variable.value === undefined) {
|
|
753
|
+
return createCSSVariableReference(variable.name);
|
|
754
|
+
}
|
|
755
|
+
const nextStack = [
|
|
756
|
+
...stack,
|
|
757
|
+
variable.name
|
|
758
|
+
];
|
|
759
|
+
const value = variable.type === 'number' && typeof variable.value === 'number' && !bypassParsing ? formatResolvedInlineNumber(variable.value) : normalizeVariableValue(variable.value).value;
|
|
760
|
+
return replaceCSSVariableReferences(value, (variableName)=>{
|
|
761
|
+
const dependency = this.css.variables.get(variableName);
|
|
762
|
+
if (!dependency) return;
|
|
763
|
+
if (dependency.inline) {
|
|
764
|
+
return resolveInlineVariable(dependency, nextStack);
|
|
765
|
+
}
|
|
766
|
+
if (!bypassVariableNames.includes(variableName)) {
|
|
767
|
+
addVariableName(variableName);
|
|
768
|
+
}
|
|
769
|
+
});
|
|
770
|
+
};
|
|
771
|
+
const negateResolvedValue = (value)=>`calc(${value} * -1)`;
|
|
772
|
+
for (const eachValueComponent of valueComponents){
|
|
773
|
+
switch(eachValueComponent.type){
|
|
774
|
+
case 'function':
|
|
775
|
+
{
|
|
776
|
+
if (eachValueComponent.name === '$') {
|
|
777
|
+
this.invalidValueSyntax = true;
|
|
778
|
+
break;
|
|
779
|
+
}
|
|
780
|
+
if (!eachValueComponent.bypassTransform && eachValueComponent.name === 'calc') {
|
|
781
|
+
currentValue += eachValueComponent.token = eachValueComponent.text = this.resolveMathFunction(this.stringifyValueComponents(eachValueComponent.children), bypassVariableNames);
|
|
782
|
+
} else if (!eachValueComponent.bypassTransform && eachValueComponent.name === 'clamp') {
|
|
783
|
+
currentValue += eachValueComponent.token = eachValueComponent.text = this.resolveMathFunction(this.stringifyValueComponents(eachValueComponent.children), bypassVariableNames, {
|
|
784
|
+
name: 'clamp',
|
|
785
|
+
wrapArguments: true
|
|
786
|
+
});
|
|
787
|
+
} else {
|
|
788
|
+
currentValue += eachValueComponent.token = eachValueComponent.text = eachValueComponent.name + eachValueComponent.symbol + this.resolveValue(eachValueComponent.children, unit, bypassVariableNames, bypassParsing) + VALUE_DELIMITERS[eachValueComponent.symbol];
|
|
789
|
+
}
|
|
790
|
+
break;
|
|
791
|
+
}
|
|
792
|
+
case 'variable':
|
|
793
|
+
const resolvedVariableAlias = this.resolveVariableAlias(eachValueComponent.name);
|
|
794
|
+
const variable = resolvedVariableAlias?.variable;
|
|
795
|
+
const variableName = resolvedVariableAlias?.name ?? eachValueComponent.name;
|
|
796
|
+
const negative = eachValueComponent.negative || resolvedVariableAlias?.negative;
|
|
797
|
+
const resolveFallback = ()=>{
|
|
798
|
+
if (!eachValueComponent.fallback) return;
|
|
799
|
+
const fallbackComponents = [];
|
|
800
|
+
this.parseValues(fallbackComponents, 0, eachValueComponent.fallback, unit, '', undefined, bypassParsing, bypassVariableNames);
|
|
801
|
+
return this.resolveValue(fallbackComponents, unit, bypassVariableNames, bypassParsing);
|
|
802
|
+
};
|
|
803
|
+
const emitVariable = (variable)=>{
|
|
804
|
+
if (variable?.type === 'number' && eachValueComponent.alpha === undefined) {
|
|
805
|
+
if (negative) {
|
|
806
|
+
return bypassParsing ? negateResolvedValue(createCSSVariableReference(variable.name)) : createNegativeNumberVariableReference(variable, unit, this.css.settings.rootSize);
|
|
807
|
+
}
|
|
808
|
+
if (!bypassParsing) {
|
|
809
|
+
return createNumberVariableReference(variable, unit, this.css.settings.rootSize);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return createCSSVariableReference(variableName, eachValueComponent.alpha, resolveFallback());
|
|
813
|
+
};
|
|
814
|
+
if (variable?.inline) {
|
|
815
|
+
const inlineValue = resolveInlineVariable(variable);
|
|
816
|
+
currentValue += eachValueComponent.text = eachValueComponent.alpha === undefined ? negative ? negateResolvedValue(inlineValue) : inlineValue : createAlphaColorValue(inlineValue, eachValueComponent.alpha);
|
|
817
|
+
} else if (variable) {
|
|
818
|
+
addVariableName(variableName);
|
|
819
|
+
currentValue += eachValueComponent.text = emitVariable(variable);
|
|
820
|
+
} else {
|
|
821
|
+
currentValue += eachValueComponent.text = emitVariable();
|
|
822
|
+
}
|
|
823
|
+
break;
|
|
824
|
+
case 'separator':
|
|
825
|
+
currentValue += eachValueComponent.text ? eachValueComponent.text : eachValueComponent.text = eachValueComponent.value;
|
|
826
|
+
break;
|
|
827
|
+
case 'number':
|
|
828
|
+
currentValue += eachValueComponent.text = eachValueComponent.value + (eachValueComponent.unit || '');
|
|
829
|
+
break;
|
|
830
|
+
default:
|
|
831
|
+
currentValue += eachValueComponent.text = eachValueComponent.value;
|
|
832
|
+
break;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
return currentValue;
|
|
836
|
+
};
|
|
837
|
+
stringifyValueComponents(valueComponents) {
|
|
838
|
+
let text = '';
|
|
839
|
+
for (const component of valueComponents){
|
|
840
|
+
switch(component.type){
|
|
841
|
+
case 'function':
|
|
842
|
+
text += component.name + component.symbol + this.stringifyValueComponents(component.children) + VALUE_DELIMITERS[component.symbol];
|
|
843
|
+
break;
|
|
844
|
+
case 'separator':
|
|
845
|
+
text += component.value;
|
|
846
|
+
break;
|
|
847
|
+
case 'variable':
|
|
848
|
+
text += component.token || '$' + component.name;
|
|
849
|
+
break;
|
|
850
|
+
case 'number':
|
|
851
|
+
text += component.token || String(component.value) + (component.unit || '');
|
|
852
|
+
break;
|
|
853
|
+
default:
|
|
854
|
+
text += component.token || component.value;
|
|
855
|
+
break;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
return text;
|
|
859
|
+
}
|
|
860
|
+
resolveMathFunction(value, bypassVariableNames, data) {
|
|
861
|
+
const functionName = data?.name ?? 'calc';
|
|
862
|
+
const valueComponents = [];
|
|
863
|
+
let i = 0;
|
|
864
|
+
const utilityUnit = String();
|
|
865
|
+
const anaylzeDeeply = (currentValueComponents, bypassHandlingSeparator, parentBypassParsing, parentUnitChecking, isVarFunction)=>{
|
|
866
|
+
const isChildHandler = valueComponents !== currentValueComponents;
|
|
867
|
+
const unparsedValueComponents = [];
|
|
868
|
+
let bypassParsing = false;
|
|
869
|
+
let hasUnit = false;
|
|
870
|
+
let currentHasUnit = false;
|
|
871
|
+
let unitChecking = false;
|
|
872
|
+
let childHasUnit = undefined;
|
|
873
|
+
let current = '';
|
|
874
|
+
const clear = (separator, prefix = '', suffix = '')=>{
|
|
875
|
+
if (childHasUnit === false && separator !== ' ' && utilityUnit) {
|
|
876
|
+
childHasUnit = undefined;
|
|
877
|
+
if (!unitChecking) {
|
|
878
|
+
pushUnitValueComponents();
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
if (current) {
|
|
882
|
+
if (!isVarFunction) {
|
|
883
|
+
const result = BASE_UNIT_REGEX.exec(current);
|
|
884
|
+
if (result) {
|
|
885
|
+
current = formatMasterBaseUnitValue(+result[1], this.css.settings.baseUnit ?? 1, this.css.settings.rootSize);
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
if (!bypassParsing && !parentBypassParsing) {
|
|
889
|
+
const valueComponent = {
|
|
890
|
+
...this.parseValue(current),
|
|
891
|
+
token: current
|
|
892
|
+
};
|
|
893
|
+
if (!hasUnit && isNaN(+current) && valueComponent.type === 'number') {
|
|
894
|
+
hasUnit = true;
|
|
895
|
+
}
|
|
896
|
+
if (unitChecking) {
|
|
897
|
+
if (isNaN(+current)) {
|
|
898
|
+
if (valueComponent.type === 'number') {
|
|
899
|
+
currentValueComponents.push(valueComponent);
|
|
900
|
+
currentHasUnit = true;
|
|
901
|
+
} else {
|
|
902
|
+
currentValueComponents.push(valueComponent);
|
|
903
|
+
}
|
|
904
|
+
} else {
|
|
905
|
+
currentValueComponents.push({
|
|
906
|
+
type: 'number',
|
|
907
|
+
value: +current,
|
|
908
|
+
token: current
|
|
909
|
+
});
|
|
910
|
+
}
|
|
911
|
+
} else {
|
|
912
|
+
if (isChildHandler) {
|
|
913
|
+
const newValueComponent = {
|
|
914
|
+
type: 'string',
|
|
915
|
+
value: current,
|
|
916
|
+
token: current
|
|
917
|
+
};
|
|
918
|
+
unparsedValueComponents.push(newValueComponent);
|
|
919
|
+
currentValueComponents.push(newValueComponent);
|
|
920
|
+
} else {
|
|
921
|
+
currentValueComponents.push(valueComponent);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
} else {
|
|
925
|
+
currentValueComponents.push({
|
|
926
|
+
type: 'string',
|
|
927
|
+
value: current,
|
|
928
|
+
token: current
|
|
929
|
+
});
|
|
930
|
+
}
|
|
931
|
+
current = '';
|
|
932
|
+
}
|
|
933
|
+
if (separator) {
|
|
934
|
+
if (separator === '+' || separator === '-') {
|
|
935
|
+
handleUnitChecking();
|
|
936
|
+
}
|
|
937
|
+
if (prefix && value[i - 1] === ' ') {
|
|
938
|
+
prefix = '';
|
|
939
|
+
}
|
|
940
|
+
if (suffix && value[i + 1] === ' ') {
|
|
941
|
+
suffix = '';
|
|
942
|
+
}
|
|
943
|
+
if (bypassHandlingSeparator) {
|
|
944
|
+
currentValueComponents.push({
|
|
945
|
+
type: 'separator',
|
|
946
|
+
value: separator,
|
|
947
|
+
text: separator,
|
|
948
|
+
token: separator
|
|
949
|
+
});
|
|
950
|
+
} else {
|
|
951
|
+
currentValueComponents.push({
|
|
952
|
+
type: 'separator',
|
|
953
|
+
value: separator,
|
|
954
|
+
text: prefix + separator + suffix,
|
|
955
|
+
token: separator
|
|
956
|
+
});
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
bypassParsing = false;
|
|
960
|
+
};
|
|
961
|
+
const pushUnitValueComponents = ()=>{
|
|
962
|
+
if (utilityUnit === 'rem' || utilityUnit === 'em') {
|
|
963
|
+
currentValueComponents.push({
|
|
964
|
+
type: 'separator',
|
|
965
|
+
value: '/',
|
|
966
|
+
text: ' / ',
|
|
967
|
+
token: '/'
|
|
968
|
+
}, {
|
|
969
|
+
type: 'number',
|
|
970
|
+
value: this.css.settings.rootSize,
|
|
971
|
+
token: String(this.css.settings.rootSize)
|
|
972
|
+
});
|
|
973
|
+
}
|
|
974
|
+
currentValueComponents.push({
|
|
975
|
+
type: 'separator',
|
|
976
|
+
value: '*',
|
|
977
|
+
text: ' * ',
|
|
978
|
+
token: '*'
|
|
979
|
+
}, {
|
|
980
|
+
type: 'number',
|
|
981
|
+
value: 1,
|
|
982
|
+
unit: utilityUnit,
|
|
983
|
+
token: utilityUnit
|
|
984
|
+
});
|
|
985
|
+
};
|
|
986
|
+
const handleUnitChecking = ()=>{
|
|
987
|
+
if (unitChecking && !currentHasUnit && !parentUnitChecking && (!isChildHandler || hasUnit)) {
|
|
988
|
+
pushUnitValueComponents();
|
|
989
|
+
}
|
|
990
|
+
unitChecking = false;
|
|
991
|
+
currentHasUnit = false;
|
|
992
|
+
};
|
|
993
|
+
for(; i < value.length; i++){
|
|
994
|
+
const char = value[i];
|
|
995
|
+
if (char === '(') {
|
|
996
|
+
const symbolResult = /^([+-])/.exec(current);
|
|
997
|
+
if (symbolResult) {
|
|
998
|
+
currentValueComponents.push({
|
|
999
|
+
type: 'string',
|
|
1000
|
+
value: symbolResult[1],
|
|
1001
|
+
token: symbolResult[1]
|
|
1002
|
+
});
|
|
1003
|
+
}
|
|
1004
|
+
const nestedFunctionName = symbolResult ? current.slice(1) : current;
|
|
1005
|
+
const newValueComponent = {
|
|
1006
|
+
type: 'function',
|
|
1007
|
+
name: nestedFunctionName,
|
|
1008
|
+
symbol: char,
|
|
1009
|
+
children: [],
|
|
1010
|
+
bypassTransform: nestedFunctionName === 'calc',
|
|
1011
|
+
token: current
|
|
1012
|
+
};
|
|
1013
|
+
currentValueComponents.push(newValueComponent);
|
|
1014
|
+
current = '';
|
|
1015
|
+
i++;
|
|
1016
|
+
if (nestedFunctionName === '$') {
|
|
1017
|
+
this.invalidValueSyntax = true;
|
|
1018
|
+
}
|
|
1019
|
+
const nestedIsVarFunction = nestedFunctionName === 'var';
|
|
1020
|
+
childHasUnit = anaylzeDeeply(newValueComponent.children, nestedIsVarFunction, bypassParsing || nestedIsVarFunction || unitChecking && currentHasUnit, unitChecking, nestedIsVarFunction) || nestedFunctionName === 'var';
|
|
1021
|
+
if (childHasUnit) {
|
|
1022
|
+
hasUnit = true;
|
|
1023
|
+
currentHasUnit = true;
|
|
1024
|
+
}
|
|
1025
|
+
} else if (char === ')') {
|
|
1026
|
+
clear('');
|
|
1027
|
+
if (hasUnit) {
|
|
1028
|
+
for (const eachUnparsedValueComponent of unparsedValueComponents){
|
|
1029
|
+
Object.assign(eachUnparsedValueComponent, this.parseValue(eachUnparsedValueComponent.value));
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
return hasUnit;
|
|
1033
|
+
} else if (char === ',') {
|
|
1034
|
+
clear(char, '', ' ');
|
|
1035
|
+
} else if (char === ' ') {
|
|
1036
|
+
clear(char);
|
|
1037
|
+
} else {
|
|
1038
|
+
const previousChar = value[i - 1];
|
|
1039
|
+
switch(char){
|
|
1040
|
+
case '+':
|
|
1041
|
+
if (!current && previousChar !== ')') {
|
|
1042
|
+
current += char;
|
|
1043
|
+
} else {
|
|
1044
|
+
clear(char, ' ', ' ');
|
|
1045
|
+
}
|
|
1046
|
+
break;
|
|
1047
|
+
case '-':
|
|
1048
|
+
if (!current && previousChar !== ')') {
|
|
1049
|
+
current += char;
|
|
1050
|
+
} else {
|
|
1051
|
+
clear(char, ' ', ' ');
|
|
1052
|
+
}
|
|
1053
|
+
break;
|
|
1054
|
+
case '*':
|
|
1055
|
+
if (utilityUnit) {
|
|
1056
|
+
unitChecking = true;
|
|
1057
|
+
}
|
|
1058
|
+
clear(char, ' ', ' ');
|
|
1059
|
+
break;
|
|
1060
|
+
case '/':
|
|
1061
|
+
if (utilityUnit) {
|
|
1062
|
+
unitChecking = true;
|
|
1063
|
+
}
|
|
1064
|
+
clear(char, ' ', ' ');
|
|
1065
|
+
bypassParsing = true;
|
|
1066
|
+
break;
|
|
1067
|
+
default:
|
|
1068
|
+
current += char;
|
|
1069
|
+
break;
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
clear('');
|
|
1074
|
+
handleUnitChecking();
|
|
1075
|
+
};
|
|
1076
|
+
anaylzeDeeply(valueComponents, false, false, false, false);
|
|
1077
|
+
let resolvedValue = this.resolveValue(valueComponents, utilityUnit, bypassVariableNames, true);
|
|
1078
|
+
if (data?.wrapArguments) {
|
|
1079
|
+
resolvedValue = wrapCalcArguments(resolvedValue);
|
|
1080
|
+
}
|
|
1081
|
+
return functionName + '(' + resolvedValue + ')';
|
|
1082
|
+
}
|
|
1083
|
+
parseValues = (currentValueComponents, i, value, unit, endSymbol, parentFunctionName, bypassParsing = false, bypassVariableNames = [])=>{
|
|
1084
|
+
const root = parentFunctionName === undefined;
|
|
1085
|
+
const isVarFunction = !root && parentFunctionName.endsWith('var');
|
|
1086
|
+
const checkIsString = (value)=>value === '\'' || value === '"';
|
|
1087
|
+
const isString = checkIsString(endSymbol);
|
|
1088
|
+
const separators = [
|
|
1089
|
+
','
|
|
1090
|
+
];
|
|
1091
|
+
if (this.registeredUtility.separators?.length) {
|
|
1092
|
+
separators.push(...this.registeredUtility.separators);
|
|
1093
|
+
}
|
|
1094
|
+
let currentValue = '';
|
|
1095
|
+
const parse = ()=>{
|
|
1096
|
+
if (currentValue) {
|
|
1097
|
+
let handled = false;
|
|
1098
|
+
if (!isVarFunction || currentValueComponents.length) {
|
|
1099
|
+
const pushVariable = (variableName, alpha, token = currentValue, negative)=>{
|
|
1100
|
+
const valueComponent = {
|
|
1101
|
+
type: 'variable',
|
|
1102
|
+
name: variableName,
|
|
1103
|
+
variable: this.css.variables.get(variableName),
|
|
1104
|
+
token
|
|
1105
|
+
};
|
|
1106
|
+
if (alpha) valueComponent.alpha = Number(alpha);
|
|
1107
|
+
if (negative) valueComponent.negative = true;
|
|
1108
|
+
currentValueComponents.push(valueComponent);
|
|
1109
|
+
};
|
|
1110
|
+
const handleVariable = (variableName, alpha)=>{
|
|
1111
|
+
const resolvedVariableAlias = this.resolveVariableAlias(variableName);
|
|
1112
|
+
if (resolvedVariableAlias && (!resolvedVariableAlias.negative || alpha === undefined)) {
|
|
1113
|
+
const { name, negative } = resolvedVariableAlias;
|
|
1114
|
+
if (!bypassVariableNames.includes(name)) {
|
|
1115
|
+
handled = true;
|
|
1116
|
+
pushVariable(name, alpha, currentValue, negative);
|
|
1117
|
+
}
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
if (/^\$[a-zA-Z0-9-]+(?:\/[^\/]+)?$/.test(currentValue)) {
|
|
1121
|
+
const [raw, alpha] = currentValue.slice(1).split('/');
|
|
1122
|
+
handleVariable(raw, alpha);
|
|
1123
|
+
if (!handled && !bypassVariableNames.includes(raw)) {
|
|
1124
|
+
handled = true;
|
|
1125
|
+
pushVariable(raw, alpha);
|
|
1126
|
+
}
|
|
1127
|
+
} else {
|
|
1128
|
+
handleVariable(currentValue);
|
|
1129
|
+
if (!handled) {
|
|
1130
|
+
const [colorName, alpha] = currentValue.split('/');
|
|
1131
|
+
handleVariable(colorName, alpha);
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
if (!handled) {
|
|
1136
|
+
if (!isVarFunction) {
|
|
1137
|
+
const result = BASE_UNIT_REGEX.exec(currentValue);
|
|
1138
|
+
if (result) {
|
|
1139
|
+
currentValue = formatMasterBaseUnitValue(+result[1], this.css.settings.baseUnit ?? 1, this.css.settings.rootSize);
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1142
|
+
if (bypassParsing) {
|
|
1143
|
+
currentValueComponents.push({
|
|
1144
|
+
type: 'string',
|
|
1145
|
+
value: currentValue,
|
|
1146
|
+
token: currentValue
|
|
1147
|
+
});
|
|
1148
|
+
} else {
|
|
1149
|
+
const parsedValue = this.parseValue(currentValue, unit);
|
|
1150
|
+
currentValueComponents.push({
|
|
1151
|
+
...parsedValue,
|
|
1152
|
+
token: currentValue
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
currentValue = '';
|
|
1157
|
+
}
|
|
1158
|
+
};
|
|
1159
|
+
for(; i < value.length; i++){
|
|
1160
|
+
const val = value[i];
|
|
1161
|
+
if (val === endSymbol) {
|
|
1162
|
+
if (isString) {
|
|
1163
|
+
let count = 0;
|
|
1164
|
+
for(let j = currentValue.length - 1;; j--){
|
|
1165
|
+
if (currentValue[j] !== '\\') break;
|
|
1166
|
+
count++;
|
|
1167
|
+
}
|
|
1168
|
+
if (count % 2) {
|
|
1169
|
+
currentValue += val;
|
|
1170
|
+
continue;
|
|
1171
|
+
} else {
|
|
1172
|
+
parse();
|
|
1173
|
+
}
|
|
1174
|
+
} else {
|
|
1175
|
+
parse();
|
|
1176
|
+
}
|
|
1177
|
+
return i;
|
|
1178
|
+
} else if (!isString && val in VALUE_DELIMITERS) {
|
|
1179
|
+
const functionName = currentValue;
|
|
1180
|
+
if (val === '(' && functionName === '$') {
|
|
1181
|
+
this.invalidValueSyntax = true;
|
|
1182
|
+
return value.length;
|
|
1183
|
+
}
|
|
1184
|
+
const newValueComponent = {
|
|
1185
|
+
type: 'function',
|
|
1186
|
+
name: functionName,
|
|
1187
|
+
symbol: val,
|
|
1188
|
+
children: [],
|
|
1189
|
+
token: ''
|
|
1190
|
+
};
|
|
1191
|
+
currentValueComponents.push(newValueComponent);
|
|
1192
|
+
currentValue = '';
|
|
1193
|
+
i = this.parseValues(newValueComponent.children, ++i, value, unit, VALUE_DELIMITERS[val], functionName || parentFunctionName || '', bypassParsing || functionName === 'calc');
|
|
1194
|
+
} else if ((val === '|' || val === ' ') && endSymbol !== '}' && (!isString || parentFunctionName === 'path')) {
|
|
1195
|
+
parse();
|
|
1196
|
+
currentValueComponents.push({
|
|
1197
|
+
type: 'separator',
|
|
1198
|
+
value: ' ',
|
|
1199
|
+
token: val
|
|
1200
|
+
});
|
|
1201
|
+
} else {
|
|
1202
|
+
if (!isString) {
|
|
1203
|
+
if (val === '.') {
|
|
1204
|
+
if (isNaN(+value[i + 1])) {
|
|
1205
|
+
if (root) break;
|
|
1206
|
+
} else if (value[i - 1] === '-') {
|
|
1207
|
+
currentValue += '0';
|
|
1208
|
+
}
|
|
1209
|
+
} else if (separators.includes(val)) {
|
|
1210
|
+
parse();
|
|
1211
|
+
currentValueComponents.push({
|
|
1212
|
+
type: 'separator',
|
|
1213
|
+
value: val,
|
|
1214
|
+
text: (val === ',' ? '' : ' ') + val + (val === ',' ? '' : ' '),
|
|
1215
|
+
token: val
|
|
1216
|
+
});
|
|
1217
|
+
continue;
|
|
1218
|
+
} else if (root && (val === '#' && (currentValue || currentValueComponents.length && currentValueComponents[currentValueComponents.length - 1]['type'] !== 'separator') || [
|
|
1219
|
+
'!',
|
|
1220
|
+
'*',
|
|
1221
|
+
'>',
|
|
1222
|
+
'+',
|
|
1223
|
+
'~',
|
|
1224
|
+
':',
|
|
1225
|
+
'[',
|
|
1226
|
+
'@',
|
|
1227
|
+
'_'
|
|
1228
|
+
].includes(val))) {
|
|
1229
|
+
break;
|
|
1230
|
+
}
|
|
1231
|
+
}
|
|
1232
|
+
currentValue += val;
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
parse();
|
|
1236
|
+
return i;
|
|
1237
|
+
};
|
|
1238
|
+
parseValue(token, unit = '') {
|
|
1239
|
+
const parsed = parseValue(token, unit, this.css.settings.rootSize);
|
|
1240
|
+
return parsed;
|
|
1241
|
+
}
|
|
1242
|
+
get key() {
|
|
1243
|
+
return (this.fixedClass ? this.fixedClass + ' ' : '') + this.name + (this.variantBranchKey ? '\0' + this.variantBranchKey : '');
|
|
1244
|
+
}
|
|
1245
|
+
}
|
|
1246
|
+
class UtilityRuleNode {
|
|
1247
|
+
rule;
|
|
1248
|
+
declarations;
|
|
1249
|
+
atRules;
|
|
1250
|
+
selector;
|
|
1251
|
+
native;
|
|
1252
|
+
constructor(rule, declarations, atRules, selector){
|
|
1253
|
+
this.rule = rule;
|
|
1254
|
+
this.declarations = declarations;
|
|
1255
|
+
this.atRules = atRules;
|
|
1256
|
+
this.selector = selector;
|
|
1257
|
+
}
|
|
1258
|
+
get text() {
|
|
1259
|
+
return this.rule.createRuleText(this.declarations, this.atRules, this.selector);
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
export { Utility, UtilityRuleNode };
|