@master/css-compiler 2.0.0-rc.84 → 2.0.0-rc.86
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 +5 -5
- package/dist/browser.d.ts +3 -4
- package/dist/core.d.ts +1 -2
- package/dist/core.js +117 -64
- package/dist/css-transform.d.ts +0 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/lexer/imports.d.ts +0 -1
- package/dist/lexer/source.d.ts +0 -1
- package/dist/lexer/standalone-master.d.ts +0 -1
- package/dist/lower-css-directives.d.ts +1 -1
- package/dist/lower-css-directives.js +159 -144
- package/dist/master-css-manifest.d.ts +0 -1
- package/dist/master-css-manifest.js +127 -65
- package/dist/native-declaration.d.ts +0 -1
- package/dist/stylesheet-value.d.ts +9 -0
- package/dist/stylesheet-value.js +141 -0
- package/dist/utils/selectors.js +6 -1
- package/dist/utils/wrap-conditions.d.ts +4 -0
- package/dist/utils/wrap-conditions.js +11 -0
- package/package.json +5 -5
- package/dist/utils/wrap-at-rules.d.ts +0 -4
- package/dist/utils/wrap-at-rules.js +0 -11
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
import { normalizeStylesheetValue } from "./stylesheet-value.js";
|
|
1
2
|
import { addCompilerDiagnosticCount, setCompilerDiagnosticCount, timeCompilerDiagnostic } from "./diagnostics.js";
|
|
2
|
-
import { createCompilerCSS,
|
|
3
|
+
import { createCompilerCSS, parseCondition, parseSelector } from "@master/css-engine/compiler";
|
|
3
4
|
import UtilityType from "@master/css-schema/utility-type";
|
|
4
5
|
import { flattenMasterCSSManifestVariables, groupMasterCSSManifestVariables } from "@master/css-schema/manifest";
|
|
5
6
|
import { builtinNamespaces } from "@master/css-engine";
|
|
@@ -92,12 +93,6 @@ function getVariableNumericValue(value, namespace) {
|
|
|
92
93
|
...match[2] ? { unit: match[2] } : {}
|
|
93
94
|
};
|
|
94
95
|
}
|
|
95
|
-
function collectVariableDependencies(value, dependencies = /* @__PURE__ */ new Set()) {
|
|
96
|
-
if (typeof value !== "string") return dependencies;
|
|
97
|
-
for (const match of value.matchAll(/\$(-?[_a-zA-Z0-9-]+)/g)) dependencies.add(match[1]);
|
|
98
|
-
for (const match of value.matchAll(/var\(\s*--(-?[_a-zA-Z0-9-]+)/g)) dependencies.add(match[1]);
|
|
99
|
-
return dependencies;
|
|
100
|
-
}
|
|
101
96
|
function variableSlot(variable) {
|
|
102
97
|
return variable.name || `${variable.namespace || ""}\0${variable.key}`;
|
|
103
98
|
}
|
|
@@ -114,10 +109,15 @@ function compileVariables(input, resolveVariableName) {
|
|
|
114
109
|
for (const definition of input) {
|
|
115
110
|
const resolved = resolveVariableName(definition);
|
|
116
111
|
if (!resolved.name) continue;
|
|
117
|
-
const
|
|
112
|
+
const rawValue = normalizeZero(definition.value);
|
|
113
|
+
const normalized = typeof rawValue === "string" || typeof rawValue === "number" ? normalizeStylesheetValue(rawValue, { replacePipes: true }) : {
|
|
114
|
+
value: rawValue,
|
|
115
|
+
dependencies: /* @__PURE__ */ new Set()
|
|
116
|
+
};
|
|
117
|
+
const value = typeof rawValue === "number" ? rawValue : normalized.value;
|
|
118
118
|
const numeric = getVariableNumericValue(value, resolved.namespace);
|
|
119
119
|
const type = numeric ? "number" : getVariableType(value);
|
|
120
|
-
const dependencies =
|
|
120
|
+
const dependencies = normalized.dependencies;
|
|
121
121
|
if (definition.mode) {
|
|
122
122
|
let target = byName.get(resolved.name);
|
|
123
123
|
if (!target) {
|
|
@@ -161,7 +161,7 @@ function compileVariables(input, resolveVariableName) {
|
|
|
161
161
|
}
|
|
162
162
|
return variables.length ? variables : void 0;
|
|
163
163
|
}
|
|
164
|
-
function
|
|
164
|
+
function normalizeNumericConditionValue(variable, rootSize) {
|
|
165
165
|
if (variable.key.startsWith("-")) return;
|
|
166
166
|
const numeric = variable.numeric || (typeof variable.value === "number" ? { value: variable.value } : void 0);
|
|
167
167
|
if (!numeric) return;
|
|
@@ -173,8 +173,8 @@ function normalizeNumericAtRuleValue(variable, rootSize) {
|
|
|
173
173
|
default: return;
|
|
174
174
|
}
|
|
175
175
|
}
|
|
176
|
-
function
|
|
177
|
-
const value =
|
|
176
|
+
function createVariableCondition(variable, id, rootSize) {
|
|
177
|
+
const value = normalizeNumericConditionValue(variable, rootSize);
|
|
178
178
|
if (value === void 0) return;
|
|
179
179
|
return {
|
|
180
180
|
id,
|
|
@@ -185,36 +185,36 @@ function createVariableAtRule(variable, id, rootSize) {
|
|
|
185
185
|
}]
|
|
186
186
|
};
|
|
187
187
|
}
|
|
188
|
-
function
|
|
189
|
-
const
|
|
190
|
-
const
|
|
191
|
-
const
|
|
188
|
+
function compileConditions(variables, rootSize) {
|
|
189
|
+
const conditions = {};
|
|
190
|
+
const breakpointConditions = {};
|
|
191
|
+
const containerConditions = {};
|
|
192
192
|
for (const variable of variables || []) if (variable.namespace === "breakpoint") {
|
|
193
|
-
const
|
|
194
|
-
if (
|
|
195
|
-
|
|
196
|
-
|
|
193
|
+
const condition = createVariableCondition(variable, "media", rootSize);
|
|
194
|
+
if (condition) {
|
|
195
|
+
conditions[variable.key] = condition;
|
|
196
|
+
breakpointConditions[variable.key] = condition;
|
|
197
197
|
}
|
|
198
198
|
} else if (variable.namespace === "container") {
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
199
|
+
const condition = createVariableCondition(variable, "container", rootSize);
|
|
200
|
+
if (condition) containerConditions[variable.key] = condition;
|
|
201
201
|
}
|
|
202
202
|
return {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
conditions: Object.keys(conditions).length ? conditions : void 0,
|
|
204
|
+
breakpointConditions: Object.keys(breakpointConditions).length ? breakpointConditions : void 0,
|
|
205
|
+
containerConditions: Object.keys(containerConditions).length ? containerConditions : void 0
|
|
206
206
|
};
|
|
207
207
|
}
|
|
208
|
-
function
|
|
208
|
+
function cloneConditionNode(node) {
|
|
209
209
|
return "children" in node ? {
|
|
210
210
|
...node,
|
|
211
|
-
children: node.children.map(
|
|
211
|
+
children: node.children.map(cloneConditionNode)
|
|
212
212
|
} : { ...node };
|
|
213
213
|
}
|
|
214
|
-
function
|
|
214
|
+
function cloneCondition(condition) {
|
|
215
215
|
return {
|
|
216
|
-
id:
|
|
217
|
-
nodes:
|
|
216
|
+
id: condition.id,
|
|
217
|
+
nodes: condition.nodes.map(cloneConditionNode)
|
|
218
218
|
};
|
|
219
219
|
}
|
|
220
220
|
function cloneSelectorNode(node) {
|
|
@@ -227,12 +227,12 @@ function compileVariantBranch(branch, css) {
|
|
|
227
227
|
const selector = branch.selector?.trim();
|
|
228
228
|
const bodylessSelector = selector ? selector.includes("&") ? selector.replace(/&/g, "") : selector : void 0;
|
|
229
229
|
const selectorNodes = branch.selectorNodes?.length ? branch.selectorNodes.map(cloneSelectorNode) : bodylessSelector ? parseSelector(bodylessSelector, css, false).map((node) => cloneSelectorNode(node)) : void 0;
|
|
230
|
-
const
|
|
230
|
+
const conditionNodes = branch.conditionNodes?.length ? branch.conditionNodes.map(cloneCondition) : branch.conditions?.length ? branch.conditions.map((condition) => cloneCondition(parseCondition(condition, css, false))) : void 0;
|
|
231
231
|
return {
|
|
232
232
|
...branch,
|
|
233
233
|
...selectorNodes?.length ? { selectorNodes } : {},
|
|
234
|
-
...branch.
|
|
235
|
-
...
|
|
234
|
+
...branch.conditions?.length ? { conditions: [...branch.conditions] } : {},
|
|
235
|
+
...conditionNodes?.length ? { conditionNodes } : {}
|
|
236
236
|
};
|
|
237
237
|
}
|
|
238
238
|
function compileVariants(input, baseManifest) {
|
|
@@ -240,7 +240,7 @@ function compileVariants(input, baseManifest) {
|
|
|
240
240
|
const css = createCompilerCSS(baseManifest);
|
|
241
241
|
const variants = [];
|
|
242
242
|
const selectors = {};
|
|
243
|
-
const
|
|
243
|
+
const conditions = {};
|
|
244
244
|
for (const variant of input) {
|
|
245
245
|
const branches = variant.branches.map((branch) => compileVariantBranch(branch, css));
|
|
246
246
|
variants.push({
|
|
@@ -252,11 +252,11 @@ function compileVariants(input, baseManifest) {
|
|
|
252
252
|
if (firstSelectorNodes?.length) selectors[variant.token] = firstSelectorNodes.map(cloneSelectorNode);
|
|
253
253
|
}
|
|
254
254
|
if (variant.token.startsWith("@")) {
|
|
255
|
-
const
|
|
256
|
-
if (
|
|
255
|
+
const firstCondition = branches.find((branch) => branch.conditionNodes?.length)?.conditionNodes?.[0];
|
|
256
|
+
if (firstCondition) conditions[variant.token.slice(1)] = cloneCondition(firstCondition);
|
|
257
257
|
else {
|
|
258
258
|
const firstLayer = branches.find((branch) => branch.layer)?.layer;
|
|
259
|
-
if (firstLayer)
|
|
259
|
+
if (firstLayer) conditions[variant.token.slice(1)] = {
|
|
260
260
|
id: "layer",
|
|
261
261
|
nodes: [{
|
|
262
262
|
type: "string",
|
|
@@ -269,39 +269,100 @@ function compileVariants(input, baseManifest) {
|
|
|
269
269
|
return {
|
|
270
270
|
variants,
|
|
271
271
|
...Object.keys(selectors).length ? { selectors } : {},
|
|
272
|
-
...Object.keys(
|
|
272
|
+
...Object.keys(conditions).length ? { conditions } : {}
|
|
273
273
|
};
|
|
274
274
|
}
|
|
275
275
|
function cloneDeclarations(declarations) {
|
|
276
276
|
return Array.isArray(declarations) ? [...declarations] : { ...declarations };
|
|
277
277
|
}
|
|
278
278
|
function assertNoValuePlaceholder(declarations) {
|
|
279
|
-
for (const property in declarations) if (declarations[property]
|
|
279
|
+
for (const property in declarations) if (containsValuePlaceholderReference(declarations[property])) throw new Error("--value() is only supported inside managed pattern declarations");
|
|
280
280
|
}
|
|
281
281
|
function compileUtilityRule(rule) {
|
|
282
282
|
assertNoValuePlaceholder(rule.declarations);
|
|
283
283
|
return {
|
|
284
284
|
declarations: cloneDeclarations(rule.declarations),
|
|
285
|
-
...rule.
|
|
285
|
+
...rule.conditions?.length ? { conditions: [...rule.conditions] } : {},
|
|
286
286
|
...rule.selector && rule.selector !== "&" ? { selector: rule.selector } : {}
|
|
287
287
|
};
|
|
288
288
|
}
|
|
289
|
+
const VALUE_PLACEHOLDER_NAME = "--value";
|
|
289
290
|
const VALUE_PLACEHOLDER_FUNCTION = "--value()";
|
|
290
|
-
|
|
291
|
+
function isCSSIdentifierCharacter(value) {
|
|
292
|
+
return value !== void 0 && /[-_a-zA-Z0-9]/.test(value);
|
|
293
|
+
}
|
|
294
|
+
function skipQuotedText(value, index) {
|
|
295
|
+
const quote = value[index];
|
|
296
|
+
index++;
|
|
297
|
+
while (index < value.length) {
|
|
298
|
+
if (value[index] === "\\") {
|
|
299
|
+
index += 2;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
if (value[index] === quote) return index + 1;
|
|
303
|
+
index++;
|
|
304
|
+
}
|
|
305
|
+
return index;
|
|
306
|
+
}
|
|
307
|
+
function skipComment(value, index) {
|
|
308
|
+
const end = value.indexOf("*/", index + 2);
|
|
309
|
+
return end === -1 ? value.length : end + 2;
|
|
310
|
+
}
|
|
311
|
+
function containsValuePlaceholderReference(value) {
|
|
312
|
+
if (!value.includes(VALUE_PLACEHOLDER_NAME)) return false;
|
|
313
|
+
for (let index = 0; index < value.length;) {
|
|
314
|
+
const character = value[index];
|
|
315
|
+
if (character === "\"" || character === "'") {
|
|
316
|
+
index = skipQuotedText(value, index);
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
if (character === "/" && value[index + 1] === "*") {
|
|
320
|
+
index = skipComment(value, index);
|
|
321
|
+
continue;
|
|
322
|
+
}
|
|
323
|
+
if (value.startsWith(VALUE_PLACEHOLDER_NAME, index)) return true;
|
|
324
|
+
index++;
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
function parseValuePlaceholderCall(value, index) {
|
|
329
|
+
if (isCSSIdentifierCharacter(value[index - 1])) throw new Error("--value() must be a standalone CSS value placeholder");
|
|
330
|
+
const openParenIndex = index + 7;
|
|
331
|
+
if (value[openParenIndex] !== "(") throw new Error("--value() must be called as --value()");
|
|
332
|
+
const closeParenIndex = value.indexOf(")", openParenIndex + 1);
|
|
333
|
+
if (closeParenIndex === -1) throw new Error("--value() must be called as --value()");
|
|
334
|
+
if (value.slice(openParenIndex + 1, closeParenIndex).trim()) throw new Error("--value() does not accept arguments");
|
|
335
|
+
const end = closeParenIndex + 1;
|
|
336
|
+
if (isCSSIdentifierCharacter(value[end])) throw new Error("--value() must be a standalone CSS value placeholder");
|
|
337
|
+
return end;
|
|
338
|
+
}
|
|
291
339
|
function compilePatternDeclarationValue(value) {
|
|
292
|
-
if (!value.includes(
|
|
340
|
+
if (!value.includes(VALUE_PLACEHOLDER_NAME)) return value;
|
|
293
341
|
const parts = [];
|
|
294
342
|
let lastIndex = 0;
|
|
295
343
|
let matched = false;
|
|
296
|
-
|
|
297
|
-
|
|
344
|
+
for (let index = 0; index < value.length;) {
|
|
345
|
+
const character = value[index];
|
|
346
|
+
if (character === "\"" || character === "'") {
|
|
347
|
+
index = skipQuotedText(value, index);
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
if (character === "/" && value[index + 1] === "*") {
|
|
351
|
+
index = skipComment(value, index);
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
if (!value.startsWith(VALUE_PLACEHOLDER_NAME, index)) {
|
|
355
|
+
index++;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
const end = parseValuePlaceholderCall(value, index);
|
|
298
359
|
matched = true;
|
|
299
|
-
if (
|
|
300
|
-
if (match.index > lastIndex) parts.push(value.slice(lastIndex, match.index));
|
|
360
|
+
if (index > lastIndex) parts.push(value.slice(lastIndex, index));
|
|
301
361
|
parts.push(null);
|
|
302
|
-
lastIndex =
|
|
362
|
+
lastIndex = end;
|
|
363
|
+
index = end;
|
|
303
364
|
}
|
|
304
|
-
if (!matched
|
|
365
|
+
if (!matched) return value;
|
|
305
366
|
if (lastIndex < value.length) parts.push(value.slice(lastIndex));
|
|
306
367
|
return value === VALUE_PLACEHOLDER_FUNCTION ? null : parts;
|
|
307
368
|
}
|
|
@@ -313,7 +374,7 @@ function compilePatternDeclarations(declarations) {
|
|
|
313
374
|
function compilePatternUtilityRule(rule) {
|
|
314
375
|
return {
|
|
315
376
|
declarations: compilePatternDeclarations(rule.declarations),
|
|
316
|
-
...rule.
|
|
377
|
+
...rule.conditions?.length ? { conditions: [...rule.conditions] } : {},
|
|
317
378
|
...rule.selector && rule.selector !== "&" ? { selector: rule.selector } : {}
|
|
318
379
|
};
|
|
319
380
|
}
|
|
@@ -335,7 +396,8 @@ function getPatternMatcher(pattern) {
|
|
|
335
396
|
return {
|
|
336
397
|
type: "pattern",
|
|
337
398
|
prefix: pattern.prefix,
|
|
338
|
-
values: [...pattern.values]
|
|
399
|
+
values: [...pattern.values],
|
|
400
|
+
...pattern.valueMap ? { valueMap: { ...pattern.valueMap } } : {}
|
|
339
401
|
};
|
|
340
402
|
}
|
|
341
403
|
function getDynamicMatchers(dynamic) {
|
|
@@ -366,7 +428,7 @@ function compileUtility(definition, order) {
|
|
|
366
428
|
const rules = [];
|
|
367
429
|
if (definition.declarations) rules.push({
|
|
368
430
|
declarations: compilePatternDeclarations(definition.declarations),
|
|
369
|
-
...definition.
|
|
431
|
+
...definition.conditions?.length ? { conditions: [...definition.conditions] } : {}
|
|
370
432
|
});
|
|
371
433
|
if (definition.rules?.length) rules.push(...definition.rules.map(compilePatternUtilityRule));
|
|
372
434
|
return {
|
|
@@ -387,7 +449,7 @@ function compileUtility(definition, order) {
|
|
|
387
449
|
const rules = [];
|
|
388
450
|
if (definition.declarations) rules.push({
|
|
389
451
|
declarations: compilePatternDeclarations(definition.declarations),
|
|
390
|
-
...definition.
|
|
452
|
+
...definition.conditions?.length ? { conditions: [...definition.conditions] } : {}
|
|
391
453
|
});
|
|
392
454
|
if (definition.rules?.length) rules.push(...definition.rules.map(compilePatternUtilityRule));
|
|
393
455
|
return {
|
|
@@ -411,7 +473,7 @@ function compileUtility(definition, order) {
|
|
|
411
473
|
assertNoValuePlaceholder(definition.declarations);
|
|
412
474
|
rules.push({
|
|
413
475
|
declarations: cloneDeclarations(definition.declarations),
|
|
414
|
-
...definition.
|
|
476
|
+
...definition.conditions?.length ? { conditions: [...definition.conditions] } : {}
|
|
415
477
|
});
|
|
416
478
|
}
|
|
417
479
|
if (definition.rules?.length) rules.push(...definition.rules.map(compileUtilityRule));
|
|
@@ -478,9 +540,9 @@ function mergeManifest(baseManifest, fragment) {
|
|
|
478
540
|
animations: mergeRecords(baseManifest.animations, fragment.animations),
|
|
479
541
|
animationOptions: mergeAnimationOptions(baseManifest.animationOptions, fragment.animationOptions, fragment.animations),
|
|
480
542
|
variants: mergeBy(baseManifest.variants, fragment.variants, (variant) => variant.token),
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
543
|
+
conditions: mergeRecords(baseManifest.conditions, fragment.conditions),
|
|
544
|
+
breakpointConditions: mergeRecords(baseManifest.breakpointConditions, fragment.breakpointConditions),
|
|
545
|
+
containerConditions: mergeRecords(baseManifest.containerConditions, fragment.containerConditions),
|
|
484
546
|
selectors: mergeRecords(baseManifest.selectors, fragment.selectors),
|
|
485
547
|
utilities: mergeBy(baseManifest.utilities, fragment.utilities, (utility) => `${utility.id}\0${utility.layer || ""}`),
|
|
486
548
|
debug: mergeRecords(baseManifest.debug, fragment.debug)
|
|
@@ -498,7 +560,7 @@ function createMasterCSSManifest(input = {}, options = {}) {
|
|
|
498
560
|
const resolveVariableName = timeCompilerDiagnostic(diagnostics, "manifest-variable-name-resolver-ms", () => createVariableNameResolver(input, options));
|
|
499
561
|
const variableDefinitions = timeCompilerDiagnostic(diagnostics, "manifest-compile-variables-ms", () => compileVariables(input.variables, resolveVariableName));
|
|
500
562
|
const variables = timeCompilerDiagnostic(diagnostics, "manifest-group-variables-ms", () => groupMasterCSSManifestVariables(variableDefinitions));
|
|
501
|
-
const {
|
|
563
|
+
const { conditions, breakpointConditions, containerConditions } = timeCompilerDiagnostic(diagnostics, "manifest-compile-conditions-ms", () => compileConditions(variableDefinitions, rootSize));
|
|
502
564
|
const settings = {
|
|
503
565
|
...input.rootSize !== void 0 ? { rootSize: input.rootSize } : {},
|
|
504
566
|
...input.baseUnit !== void 0 ? { baseUnit: input.baseUnit } : {},
|
|
@@ -512,11 +574,11 @@ function createMasterCSSManifest(input = {}, options = {}) {
|
|
|
512
574
|
version: 1,
|
|
513
575
|
...Object.keys(settings).length ? { settings } : {},
|
|
514
576
|
...variables ? { variables } : {},
|
|
515
|
-
...
|
|
516
|
-
...
|
|
517
|
-
...
|
|
577
|
+
...conditions ? { conditions } : {},
|
|
578
|
+
...breakpointConditions ? { breakpointConditions } : {},
|
|
579
|
+
...containerConditions ? { containerConditions } : {}
|
|
518
580
|
}));
|
|
519
|
-
const { variants, selectors,
|
|
581
|
+
const { variants, selectors, conditions: variantConditions } = timeCompilerDiagnostic(diagnostics, "manifest-compile-variants-ms", () => compileVariants(input.variants, variantBaseManifest));
|
|
520
582
|
const utilities = timeCompilerDiagnostic(diagnostics, "manifest-compile-utilities-ms", () => compileUtilities(input.utilities));
|
|
521
583
|
const animations = timeCompilerDiagnostic(diagnostics, "manifest-compile-animations-ms", () => compileAnimations(input.animations));
|
|
522
584
|
const animationOptions = timeCompilerDiagnostic(diagnostics, "manifest-compile-animation-options-ms", () => compileAnimationOptions(input.animationOptions));
|
|
@@ -527,9 +589,9 @@ function createMasterCSSManifest(input = {}, options = {}) {
|
|
|
527
589
|
...animations ? { animations } : {},
|
|
528
590
|
...animationOptions ? { animationOptions } : {},
|
|
529
591
|
...variants?.length ? { variants } : {},
|
|
530
|
-
...
|
|
531
|
-
...
|
|
532
|
-
...
|
|
592
|
+
...conditions || variantConditions ? { conditions: mergeRecords(conditions, variantConditions) } : {},
|
|
593
|
+
...breakpointConditions ? { breakpointConditions } : {},
|
|
594
|
+
...containerConditions ? { containerConditions } : {},
|
|
533
595
|
...selectors ? { selectors } : {},
|
|
534
596
|
...utilities?.length ? { utilities } : {}
|
|
535
597
|
};
|
|
@@ -538,7 +600,7 @@ function createMasterCSSManifest(input = {}, options = {}) {
|
|
|
538
600
|
setCompilerDiagnosticCount(diagnostics, "manifest-output-utility-count", manifest.utilities?.length || 0);
|
|
539
601
|
setCompilerDiagnosticCount(diagnostics, "manifest-output-variant-count", manifest.variants?.length || 0);
|
|
540
602
|
setCompilerDiagnosticCount(diagnostics, "manifest-output-selector-count", Object.keys(manifest.selectors || {}).length);
|
|
541
|
-
setCompilerDiagnosticCount(diagnostics, "manifest-output-
|
|
603
|
+
setCompilerDiagnosticCount(diagnostics, "manifest-output-condition-count", Object.keys(manifest.conditions || {}).length);
|
|
542
604
|
setCompilerDiagnosticCount(diagnostics, "manifest-output-animation-count", Object.keys(manifest.animations || {}).length);
|
|
543
605
|
return manifest;
|
|
544
606
|
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { collectCSSVariableReferences, findCSSClosingQuote, findCSSCommentEnd, readCSSFunction } from "@master/css-lexer";
|
|
2
|
+
//#region src/stylesheet-value.ts
|
|
3
|
+
const CSS_VARIABLE_ALIAS = /\$(-?[_a-zA-Z0-9-]+)\b/g;
|
|
4
|
+
const CSS_NUMBER = /^[+-]?(?:\d+(?:\.\d+)?|\.\d+)$/;
|
|
5
|
+
function collectUnquotedMatches(value, pattern) {
|
|
6
|
+
const matches = [];
|
|
7
|
+
for (let index = 0; index < value.length;) {
|
|
8
|
+
const char = value[index];
|
|
9
|
+
if (char === "\"" || char === "'") {
|
|
10
|
+
index = findCSSClosingQuote(value, index, char) + 1;
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (char === "/" && value[index + 1] === "*") {
|
|
14
|
+
index = findCSSCommentEnd(value, index);
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
pattern.lastIndex = index;
|
|
18
|
+
const match = pattern.exec(value);
|
|
19
|
+
if (!match || match.index !== index) {
|
|
20
|
+
index++;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
matches.push(match);
|
|
24
|
+
index = pattern.lastIndex;
|
|
25
|
+
}
|
|
26
|
+
return matches;
|
|
27
|
+
}
|
|
28
|
+
function collectCSSVariableAliases(value) {
|
|
29
|
+
return collectUnquotedMatches(value, CSS_VARIABLE_ALIAS).filter((match) => value[match.index - 1] !== "\\");
|
|
30
|
+
}
|
|
31
|
+
function findTopLevelAlphaSeparator(value) {
|
|
32
|
+
let separatorIndex = -1;
|
|
33
|
+
let depth = 0;
|
|
34
|
+
for (let index = 0; index < value.length; index++) {
|
|
35
|
+
const char = value[index];
|
|
36
|
+
if (char === "\"" || char === "'") {
|
|
37
|
+
index = findCSSClosingQuote(value, index, char);
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
if (char === "/" && value[index + 1] === "*") {
|
|
41
|
+
index = findCSSCommentEnd(value, index) - 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
44
|
+
if (char === "(") {
|
|
45
|
+
depth++;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (char === ")") {
|
|
49
|
+
if (depth > 0) depth--;
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
if (char === "/" && depth === 0) {
|
|
53
|
+
if (separatorIndex !== -1) return;
|
|
54
|
+
separatorIndex = index;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return separatorIndex;
|
|
58
|
+
}
|
|
59
|
+
function isWholeCSSFunction(value, name) {
|
|
60
|
+
const trimmed = value.trim();
|
|
61
|
+
const fn = readCSSFunction(trimmed, 0, name);
|
|
62
|
+
return Boolean(fn && fn.end === trimmed.length);
|
|
63
|
+
}
|
|
64
|
+
function formatAlphaPercentage(value) {
|
|
65
|
+
return String(Object.is(value, -0) ? 0 : value).replace(/^(-?)0\./, "$1.") + "%";
|
|
66
|
+
}
|
|
67
|
+
function normalizeStylesheetAlpha(value) {
|
|
68
|
+
const trimmed = value.trim();
|
|
69
|
+
if (!trimmed) throw new Error("Invalid --alpha() function: alpha value cannot be empty");
|
|
70
|
+
if (CSS_NUMBER.test(trimmed)) {
|
|
71
|
+
const alpha = Number(trimmed);
|
|
72
|
+
if (alpha < 0 || alpha > 1) throw new Error(`Invalid --alpha() function: numeric alpha must be between 0 and 1: ${trimmed}`);
|
|
73
|
+
return formatAlphaPercentage(alpha * 100);
|
|
74
|
+
}
|
|
75
|
+
if (trimmed.endsWith("%") && CSS_NUMBER.test(trimmed.slice(0, -1))) {
|
|
76
|
+
const percentage = Number(trimmed.slice(0, -1));
|
|
77
|
+
if (percentage < 0 || percentage > 100) throw new Error(`Invalid --alpha() function: percentage alpha must be between 0% and 100%: ${trimmed}`);
|
|
78
|
+
return formatAlphaPercentage(percentage);
|
|
79
|
+
}
|
|
80
|
+
if (isWholeCSSFunction(trimmed, "var") || isWholeCSSFunction(trimmed, "calc")) return trimmed;
|
|
81
|
+
throw new Error(`Invalid --alpha() function: unsupported alpha value "${trimmed}"`);
|
|
82
|
+
}
|
|
83
|
+
function createStylesheetAlphaColorValue(value, alpha) {
|
|
84
|
+
return `color-mix(in oklab,${value} ${alpha},transparent)`;
|
|
85
|
+
}
|
|
86
|
+
function normalizeAlphaFunction(body) {
|
|
87
|
+
const separatorIndex = findTopLevelAlphaSeparator(body);
|
|
88
|
+
if (separatorIndex === void 0 || separatorIndex === -1) throw new Error("Invalid --alpha() function: expected \"<color> / <alpha>\"");
|
|
89
|
+
const color = body.slice(0, separatorIndex).trim();
|
|
90
|
+
const alpha = body.slice(separatorIndex + 1).trim();
|
|
91
|
+
if (!color) throw new Error("Invalid --alpha() function: color value cannot be empty");
|
|
92
|
+
return createStylesheetAlphaColorValue(color, normalizeStylesheetAlpha(alpha));
|
|
93
|
+
}
|
|
94
|
+
function normalizeStylesheetValue(value, options = {}) {
|
|
95
|
+
if (typeof value === "number") return {
|
|
96
|
+
value: String(value),
|
|
97
|
+
dependencies: /* @__PURE__ */ new Set()
|
|
98
|
+
};
|
|
99
|
+
const aliases = collectCSSVariableAliases(value);
|
|
100
|
+
if (aliases.length) {
|
|
101
|
+
const alias = aliases[0][1];
|
|
102
|
+
throw new Error(`Stylesheet values use native CSS variable references. Replace "$${alias}" with "var(--${alias})".`);
|
|
103
|
+
}
|
|
104
|
+
let result = "";
|
|
105
|
+
for (let index = 0; index < value.length;) {
|
|
106
|
+
const char = value[index];
|
|
107
|
+
if (char === "\"" || char === "'") {
|
|
108
|
+
const end = findCSSClosingQuote(value, index, char) + 1;
|
|
109
|
+
result += value.slice(index, end);
|
|
110
|
+
index = end;
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (char === "/" && value[index + 1] === "*") {
|
|
114
|
+
const end = findCSSCommentEnd(value, index);
|
|
115
|
+
result += value.slice(index, end);
|
|
116
|
+
index = end;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (value.startsWith("--alpha(", index)) {
|
|
120
|
+
const alphaFunction = readCSSFunction(value, index, "--alpha");
|
|
121
|
+
if (alphaFunction) {
|
|
122
|
+
result += normalizeAlphaFunction(alphaFunction.body);
|
|
123
|
+
index = alphaFunction.end;
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (options.replacePipes && char === "|") {
|
|
128
|
+
result += " ";
|
|
129
|
+
index++;
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
result += char;
|
|
133
|
+
index++;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
value: result,
|
|
137
|
+
dependencies: collectCSSVariableReferences(result)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
//#endregion
|
|
141
|
+
export { normalizeStylesheetValue };
|
package/dist/utils/selectors.js
CHANGED
|
@@ -39,9 +39,14 @@ function splitSelectorList(selectorText) {
|
|
|
39
39
|
}
|
|
40
40
|
function combineSelectorLists(parentSelectors, childSelectors) {
|
|
41
41
|
const selectors = [];
|
|
42
|
-
for (const child of childSelectors) for (const parent of parentSelectors) selectors.push(
|
|
42
|
+
for (const child of childSelectors) for (const parent of parentSelectors) selectors.push(combineSelector(parent, child));
|
|
43
43
|
return selectors;
|
|
44
44
|
}
|
|
45
|
+
function combineSelector(parent, child) {
|
|
46
|
+
const trimmedChild = child.trim();
|
|
47
|
+
if (trimmedChild.includes("&")) return trimmedChild.replace(/&/g, parent);
|
|
48
|
+
return `${parent} ${child}`;
|
|
49
|
+
}
|
|
45
50
|
function combineStyleSelectors(parentSelector, childSelector) {
|
|
46
51
|
return combineSelectorLists(splitSelectorList(parentSelector), splitSelectorList(childSelector)).join(",");
|
|
47
52
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//#region src/utils/wrap-conditions.ts
|
|
2
|
+
function wrapConditions(text, conditions) {
|
|
3
|
+
if (!conditions?.length) return text;
|
|
4
|
+
for (let index = conditions.length - 1; index >= 0; index--) {
|
|
5
|
+
const condition = conditions[index]?.trim();
|
|
6
|
+
if (condition) text = `${condition}{${text}}`;
|
|
7
|
+
}
|
|
8
|
+
return text;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { wrapConditions as default };
|
package/package.json
CHANGED
|
@@ -50,15 +50,15 @@
|
|
|
50
50
|
"csstype": "^3.2.3",
|
|
51
51
|
"lightningcss": "^1.32.0",
|
|
52
52
|
"lightningcss-wasm": "^1.32.0",
|
|
53
|
-
"@master/css-
|
|
54
|
-
"@master/css-
|
|
55
|
-
"@master/css-schema": "^2.0.0-rc.
|
|
53
|
+
"@master/css-lexer": "^2.0.0-rc.86",
|
|
54
|
+
"@master/css-engine": "^2.0.0-rc.86",
|
|
55
|
+
"@master/css-schema": "^2.0.0-rc.86"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
58
58
|
"@types/css-tree": "^2.3.11",
|
|
59
|
-
"@master/css-preset": "^2.0.0-rc.
|
|
59
|
+
"@master/css-preset": "^2.0.0-rc.86"
|
|
60
60
|
},
|
|
61
|
-
"version": "2.0.0-rc.
|
|
61
|
+
"version": "2.0.0-rc.86",
|
|
62
62
|
"scripts": {
|
|
63
63
|
"build": "tsdown --config ../../shared/tsdown-package.config.ts",
|
|
64
64
|
"dev": "tsdown --config ../../shared/tsdown-package.config.ts --watch",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
//#region src/utils/wrap-at-rules.ts
|
|
2
|
-
function wrapAtRules(text, atRules) {
|
|
3
|
-
if (!atRules?.length) return text;
|
|
4
|
-
for (let index = atRules.length - 1; index >= 0; index--) {
|
|
5
|
-
const atRule = atRules[index]?.trim();
|
|
6
|
-
if (atRule) text = `${atRule}{${text}}`;
|
|
7
|
-
}
|
|
8
|
-
return text;
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
11
|
-
export { wrapAtRules as default };
|