@tenphi/tasty 0.4.2 → 0.5.0
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 +11 -6
- package/dist/pipeline/conditions.d.ts +3 -3
- package/dist/pipeline/conditions.js +14 -12
- package/dist/pipeline/conditions.js.map +1 -1
- package/dist/pipeline/index.js +4 -5
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/materialize.js +223 -209
- package/dist/pipeline/materialize.js.map +1 -1
- package/dist/pipeline/parseStateKey.js +9 -18
- package/dist/pipeline/parseStateKey.js.map +1 -1
- package/dist/pipeline/simplify.js.map +1 -1
- package/dist/tasty.d.ts +3 -3
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Lru } from "../parser/lru.js";
|
|
2
|
+
import { not } from "./conditions.js";
|
|
2
3
|
|
|
3
4
|
//#region src/pipeline/materialize.ts
|
|
4
5
|
/**
|
|
@@ -31,7 +32,7 @@ function emptyVariant() {
|
|
|
31
32
|
containerConditions: [],
|
|
32
33
|
supportsConditions: [],
|
|
33
34
|
rootConditions: [],
|
|
34
|
-
|
|
35
|
+
parentGroups: [],
|
|
35
36
|
startingStyle: false
|
|
36
37
|
};
|
|
37
38
|
}
|
|
@@ -65,36 +66,46 @@ function stateToCSS(state) {
|
|
|
65
66
|
}),
|
|
66
67
|
isImpossible: false
|
|
67
68
|
};
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
variant.ownConditions.push(...ownToParsed(state));
|
|
91
|
-
break;
|
|
92
|
-
case "starting":
|
|
93
|
-
variant.startingStyle = !state.negated;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
69
|
+
case "root": return innerConditionToVariants(state.innerCondition, state.negated ?? false, "rootConditions");
|
|
70
|
+
case "parent": return parentConditionToVariants(state.innerCondition, state.negated ?? false, state.direct);
|
|
71
|
+
case "own": return innerConditionToVariants(state.innerCondition, state.negated ?? false, "ownConditions");
|
|
72
|
+
case "modifier": {
|
|
73
|
+
const v = emptyVariant();
|
|
74
|
+
v.modifierConditions.push(modifierToParsed(state));
|
|
75
|
+
return {
|
|
76
|
+
variants: [v],
|
|
77
|
+
isImpossible: false
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
case "pseudo": {
|
|
81
|
+
const v = emptyVariant();
|
|
82
|
+
v.pseudoConditions.push(pseudoToParsed(state));
|
|
83
|
+
return {
|
|
84
|
+
variants: [v],
|
|
85
|
+
isImpossible: false
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
case "container": {
|
|
89
|
+
const v = emptyVariant();
|
|
90
|
+
v.containerConditions.push(containerToParsed(state));
|
|
96
91
|
return {
|
|
97
|
-
variants: [
|
|
92
|
+
variants: [v],
|
|
93
|
+
isImpossible: false
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
case "supports": {
|
|
97
|
+
const v = emptyVariant();
|
|
98
|
+
v.supportsConditions.push(supportsToParsed(state));
|
|
99
|
+
return {
|
|
100
|
+
variants: [v],
|
|
101
|
+
isImpossible: false
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
case "starting": {
|
|
105
|
+
const v = emptyVariant();
|
|
106
|
+
v.startingStyle = !state.negated;
|
|
107
|
+
return {
|
|
108
|
+
variants: [v],
|
|
98
109
|
isImpossible: false
|
|
99
110
|
};
|
|
100
111
|
}
|
|
@@ -233,12 +244,92 @@ function supportsToParsed(state) {
|
|
|
233
244
|
};
|
|
234
245
|
}
|
|
235
246
|
/**
|
|
236
|
-
*
|
|
247
|
+
* Collect all modifier and pseudo conditions from a variant as a flat array.
|
|
237
248
|
*/
|
|
238
|
-
function
|
|
249
|
+
function collectSelectorConditions(variant) {
|
|
250
|
+
return [...variant.modifierConditions, ...variant.pseudoConditions];
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Convert an inner condition tree into SelectorVariants.
|
|
254
|
+
* Each inner OR branch becomes a separate variant, preserving disjunction.
|
|
255
|
+
* Shared by @root() and @own().
|
|
256
|
+
*/
|
|
257
|
+
function innerConditionToVariants(innerCondition, negated, target) {
|
|
258
|
+
const innerCSS = conditionToCSS(negated ? not(innerCondition) : innerCondition);
|
|
259
|
+
if (innerCSS.isImpossible || innerCSS.variants.length === 0) return {
|
|
260
|
+
variants: [],
|
|
261
|
+
isImpossible: true
|
|
262
|
+
};
|
|
263
|
+
const variants = [];
|
|
264
|
+
for (const innerVariant of innerCSS.variants) {
|
|
265
|
+
const conditions = collectSelectorConditions(innerVariant);
|
|
266
|
+
if (conditions.length > 0) {
|
|
267
|
+
const v = emptyVariant();
|
|
268
|
+
v[target].push(...conditions);
|
|
269
|
+
variants.push(v);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
if (variants.length === 0) return {
|
|
273
|
+
variants: [emptyVariant()],
|
|
274
|
+
isImpossible: false
|
|
275
|
+
};
|
|
239
276
|
return {
|
|
240
|
-
|
|
241
|
-
|
|
277
|
+
variants,
|
|
278
|
+
isImpossible: false
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* Convert a @parent() inner condition into SelectorVariants with ParentGroups.
|
|
283
|
+
*
|
|
284
|
+
* Positive: each inner OR branch becomes a separate variant with one :is() group.
|
|
285
|
+
* Negated: !(A | B) = !A & !B — all branches become :not() groups collected
|
|
286
|
+
* into a single variant so they produce :not([a] *):not([b] *) on one element.
|
|
287
|
+
*/
|
|
288
|
+
function parentConditionToVariants(innerCondition, negated, direct) {
|
|
289
|
+
const innerCSS = conditionToCSS(innerCondition);
|
|
290
|
+
if (innerCSS.isImpossible || innerCSS.variants.length === 0) return {
|
|
291
|
+
variants: [],
|
|
292
|
+
isImpossible: true
|
|
293
|
+
};
|
|
294
|
+
if (negated) {
|
|
295
|
+
const v = emptyVariant();
|
|
296
|
+
for (const innerVariant of innerCSS.variants) {
|
|
297
|
+
const conditions = collectSelectorConditions(innerVariant);
|
|
298
|
+
if (conditions.length > 0) v.parentGroups.push({
|
|
299
|
+
conditions,
|
|
300
|
+
direct,
|
|
301
|
+
negated: true
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
if (v.parentGroups.length === 0) return {
|
|
305
|
+
variants: [emptyVariant()],
|
|
306
|
+
isImpossible: false
|
|
307
|
+
};
|
|
308
|
+
return {
|
|
309
|
+
variants: [v],
|
|
310
|
+
isImpossible: false
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
const variants = [];
|
|
314
|
+
for (const innerVariant of innerCSS.variants) {
|
|
315
|
+
const conditions = collectSelectorConditions(innerVariant);
|
|
316
|
+
if (conditions.length > 0) {
|
|
317
|
+
const v = emptyVariant();
|
|
318
|
+
v.parentGroups.push({
|
|
319
|
+
conditions,
|
|
320
|
+
direct,
|
|
321
|
+
negated: false
|
|
322
|
+
});
|
|
323
|
+
variants.push(v);
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
if (variants.length === 0) return {
|
|
327
|
+
variants: [emptyVariant()],
|
|
328
|
+
isImpossible: false
|
|
329
|
+
};
|
|
330
|
+
return {
|
|
331
|
+
variants,
|
|
332
|
+
isImpossible: false
|
|
242
333
|
};
|
|
243
334
|
}
|
|
244
335
|
/**
|
|
@@ -247,49 +338,30 @@ function rootToParsed(state) {
|
|
|
247
338
|
function rootConditionsToCSS(roots) {
|
|
248
339
|
if (roots.length === 0) return void 0;
|
|
249
340
|
let prefix = ":root";
|
|
250
|
-
for (const
|
|
251
|
-
else prefix += root.selector;
|
|
341
|
+
for (const cond of roots) prefix += selectorConditionToCSS(cond);
|
|
252
342
|
return prefix;
|
|
253
343
|
}
|
|
254
344
|
/**
|
|
255
|
-
* Convert parent
|
|
345
|
+
* Convert parent groups to CSS selector fragments (for final output).
|
|
346
|
+
* Each group produces its own :is() wrapper.
|
|
256
347
|
*/
|
|
257
|
-
function
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
direct:
|
|
261
|
-
|
|
262
|
-
|
|
348
|
+
function parentGroupsToCSS(groups) {
|
|
349
|
+
let result = "";
|
|
350
|
+
for (const group of groups) {
|
|
351
|
+
const combinator = group.direct ? " > *" : " *";
|
|
352
|
+
let parts = "";
|
|
353
|
+
for (const cond of group.conditions) parts += selectorConditionToCSS(cond);
|
|
354
|
+
const wrapper = group.negated ? ":not" : ":is";
|
|
355
|
+
result += `${wrapper}(${parts}${combinator})`;
|
|
356
|
+
}
|
|
357
|
+
return result;
|
|
263
358
|
}
|
|
264
359
|
/**
|
|
265
|
-
* Convert
|
|
266
|
-
*
|
|
267
|
-
* Positive: :is([selector] *) or :is([selector] > *)
|
|
268
|
-
* Negative: :not([selector] *) or :not([selector] > *)
|
|
360
|
+
* Convert a modifier or pseudo condition to a CSS selector fragment
|
|
269
361
|
*/
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
return `:is(${parent.selector}${combinator})`;
|
|
274
|
-
}
|
|
275
|
-
/**
|
|
276
|
-
* Convert own condition to parsed structures for sub-element
|
|
277
|
-
*/
|
|
278
|
-
function ownToParsed(state) {
|
|
279
|
-
const innerCSS = conditionToCSS(state.innerCondition);
|
|
280
|
-
if (innerCSS.isImpossible || innerCSS.variants.length === 0) return [];
|
|
281
|
-
const allConditions = [];
|
|
282
|
-
for (const variant of innerCSS.variants) {
|
|
283
|
-
for (const mod of variant.modifierConditions) allConditions.push({
|
|
284
|
-
...mod,
|
|
285
|
-
negated: state.negated ? !mod.negated : mod.negated
|
|
286
|
-
});
|
|
287
|
-
for (const pseudo of variant.pseudoConditions) allConditions.push({
|
|
288
|
-
...pseudo,
|
|
289
|
-
negated: state.negated ? !pseudo.negated : pseudo.negated
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
return allConditions;
|
|
362
|
+
function selectorConditionToCSS(cond) {
|
|
363
|
+
if ("attribute" in cond) return modifierToCSS(cond);
|
|
364
|
+
return pseudoToCSS(cond);
|
|
293
365
|
}
|
|
294
366
|
/**
|
|
295
367
|
* Get unique key for a modifier condition
|
|
@@ -305,91 +377,48 @@ function getPseudoKey(pseudo) {
|
|
|
305
377
|
return pseudo.negated ? `!${pseudo.pseudo}` : pseudo.pseudo;
|
|
306
378
|
}
|
|
307
379
|
/**
|
|
308
|
-
* Get unique key for
|
|
309
|
-
*/
|
|
310
|
-
function getRootKey(root) {
|
|
311
|
-
return root.negated ? `!${root.selector}` : root.selector;
|
|
312
|
-
}
|
|
313
|
-
/**
|
|
314
|
-
* Deduplicate modifier conditions
|
|
315
|
-
*/
|
|
316
|
-
function dedupeModifierConditions(conditions) {
|
|
317
|
-
const seen = /* @__PURE__ */ new Set();
|
|
318
|
-
const result = [];
|
|
319
|
-
for (const c of conditions) {
|
|
320
|
-
const key = getModifierKey(c);
|
|
321
|
-
if (!seen.has(key)) {
|
|
322
|
-
seen.add(key);
|
|
323
|
-
result.push(c);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
return result;
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Deduplicate pseudo conditions
|
|
380
|
+
* Get unique key for any selector condition (modifier or pseudo)
|
|
330
381
|
*/
|
|
331
|
-
function
|
|
332
|
-
|
|
333
|
-
const result = [];
|
|
334
|
-
for (const c of conditions) {
|
|
335
|
-
const key = getPseudoKey(c);
|
|
336
|
-
if (!seen.has(key)) {
|
|
337
|
-
seen.add(key);
|
|
338
|
-
result.push(c);
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
return result;
|
|
382
|
+
function getSelectorConditionKey(cond) {
|
|
383
|
+
return "attribute" in cond ? `mod:${getModifierKey(cond)}` : `pseudo:${getPseudoKey(cond)}`;
|
|
342
384
|
}
|
|
343
385
|
/**
|
|
344
|
-
* Deduplicate
|
|
386
|
+
* Deduplicate selector conditions (modifiers or pseudos).
|
|
387
|
+
* Shared by root, parent, and own conditions.
|
|
345
388
|
*/
|
|
346
|
-
function
|
|
389
|
+
function dedupeSelectorConditions(conditions) {
|
|
347
390
|
const seen = /* @__PURE__ */ new Set();
|
|
348
|
-
|
|
391
|
+
let result = [];
|
|
349
392
|
for (const c of conditions) {
|
|
350
|
-
const key =
|
|
393
|
+
const key = getSelectorConditionKey(c);
|
|
351
394
|
if (!seen.has(key)) {
|
|
352
395
|
seen.add(key);
|
|
353
396
|
result.push(c);
|
|
354
397
|
}
|
|
355
398
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
const seen = /* @__PURE__ */ new Set();
|
|
370
|
-
const result = [];
|
|
371
|
-
for (const c of conditions) {
|
|
372
|
-
const key = getParentKey(c);
|
|
373
|
-
if (!seen.has(key)) {
|
|
374
|
-
seen.add(key);
|
|
375
|
-
result.push(c);
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
return result;
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* Deduplicate own conditions (modifiers or pseudos)
|
|
382
|
-
*/
|
|
383
|
-
function dedupeOwnConditions(conditions) {
|
|
384
|
-
const seen = /* @__PURE__ */ new Set();
|
|
385
|
-
const result = [];
|
|
386
|
-
for (const c of conditions) {
|
|
387
|
-
const key = "attribute" in c ? `mod:${getModifierKey(c)}` : `pseudo:${getPseudoKey(c)}`;
|
|
388
|
-
if (!seen.has(key)) {
|
|
389
|
-
seen.add(key);
|
|
390
|
-
result.push(c);
|
|
399
|
+
const negatedBooleanAttrs = /* @__PURE__ */ new Set();
|
|
400
|
+
const positiveExactValuesByAttr = /* @__PURE__ */ new Map();
|
|
401
|
+
for (const c of result) {
|
|
402
|
+
if (!("attribute" in c)) continue;
|
|
403
|
+
if (c.negated && c.value === void 0) negatedBooleanAttrs.add(c.attribute);
|
|
404
|
+
const op = c.operator ?? "=";
|
|
405
|
+
if (!c.negated && c.value !== void 0 && op === "=") {
|
|
406
|
+
let values = positiveExactValuesByAttr.get(c.attribute);
|
|
407
|
+
if (!values) {
|
|
408
|
+
values = /* @__PURE__ */ new Set();
|
|
409
|
+
positiveExactValuesByAttr.set(c.attribute, values);
|
|
410
|
+
}
|
|
411
|
+
values.add(c.value);
|
|
391
412
|
}
|
|
392
413
|
}
|
|
414
|
+
result = result.filter((c) => {
|
|
415
|
+
if (!("attribute" in c) || !c.negated || c.value === void 0) return true;
|
|
416
|
+
if (negatedBooleanAttrs.has(c.attribute)) return false;
|
|
417
|
+
if ((c.operator ?? "=") !== "=") return true;
|
|
418
|
+
const positiveValues = positiveExactValuesByAttr.get(c.attribute);
|
|
419
|
+
if (positiveValues !== void 0 && positiveValues.size === 1 && !positiveValues.has(c.value)) return false;
|
|
420
|
+
return true;
|
|
421
|
+
});
|
|
393
422
|
return result;
|
|
394
423
|
}
|
|
395
424
|
/**
|
|
@@ -418,34 +447,10 @@ function hasPseudoContradiction(conditions) {
|
|
|
418
447
|
return false;
|
|
419
448
|
}
|
|
420
449
|
/**
|
|
421
|
-
* Check for
|
|
450
|
+
* Check for selector condition contradiction (modifier or pseudo with opposite negation).
|
|
451
|
+
* Shared by root, parent, and own conditions.
|
|
422
452
|
*/
|
|
423
|
-
function
|
|
424
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
425
|
-
for (const root of conditions) {
|
|
426
|
-
const existing = byKey.get(root.selector);
|
|
427
|
-
if (existing !== void 0 && existing !== !root.negated) return true;
|
|
428
|
-
byKey.set(root.selector, !root.negated);
|
|
429
|
-
}
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
/**
|
|
433
|
-
* Check for parent condition contradiction: same selector+direct with opposite negation
|
|
434
|
-
*/
|
|
435
|
-
function hasParentContradiction(conditions) {
|
|
436
|
-
const byKey = /* @__PURE__ */ new Map();
|
|
437
|
-
for (const parent of conditions) {
|
|
438
|
-
const baseKey = `${parent.direct ? ">" : ""}${parent.selector}`;
|
|
439
|
-
const existing = byKey.get(baseKey);
|
|
440
|
-
if (existing !== void 0 && existing !== !parent.negated) return true;
|
|
441
|
-
byKey.set(baseKey, !parent.negated);
|
|
442
|
-
}
|
|
443
|
-
return false;
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* Check for own condition contradiction
|
|
447
|
-
*/
|
|
448
|
-
function hasOwnConditionContradiction(conditions) {
|
|
453
|
+
function hasSelectorConditionContradiction(conditions) {
|
|
449
454
|
const modifiers = [];
|
|
450
455
|
const pseudos = [];
|
|
451
456
|
for (const c of conditions) if ("attribute" in c) modifiers.push(c);
|
|
@@ -453,22 +458,36 @@ function hasOwnConditionContradiction(conditions) {
|
|
|
453
458
|
return hasModifierContradiction(modifiers) || hasPseudoContradiction(pseudos);
|
|
454
459
|
}
|
|
455
460
|
/**
|
|
461
|
+
* Check for parent group contradiction: same target (direct + conditions)
|
|
462
|
+
* with opposite negation. E.g. :not([data-hovered] *) and :is([data-hovered] *)
|
|
463
|
+
* in the same variant is impossible.
|
|
464
|
+
*/
|
|
465
|
+
function hasParentGroupContradiction(groups) {
|
|
466
|
+
const byBaseKey = /* @__PURE__ */ new Map();
|
|
467
|
+
for (const g of groups) {
|
|
468
|
+
const baseKey = `${g.direct ? ">" : ""}(${g.conditions.map(getSelectorConditionKey).sort().join(",")})`;
|
|
469
|
+
const existing = byBaseKey.get(baseKey);
|
|
470
|
+
if (existing !== void 0 && existing !== !g.negated) return true;
|
|
471
|
+
byBaseKey.set(baseKey, !g.negated);
|
|
472
|
+
}
|
|
473
|
+
return false;
|
|
474
|
+
}
|
|
475
|
+
/**
|
|
456
476
|
* Merge two selector variants (AND operation)
|
|
457
477
|
* Deduplicates conditions and checks for contradictions
|
|
458
478
|
*/
|
|
459
479
|
function mergeVariants(a, b) {
|
|
460
480
|
const mergedMedia = dedupeMediaConditions([...a.mediaConditions, ...b.mediaConditions]);
|
|
461
481
|
if (hasMediaContradiction(mergedMedia)) return null;
|
|
462
|
-
const mergedRoots =
|
|
463
|
-
if (
|
|
464
|
-
const mergedModifiers =
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
if (hasOwnConditionContradiction(mergedOwn)) return null;
|
|
482
|
+
const mergedRoots = dedupeSelectorConditions([...a.rootConditions, ...b.rootConditions]);
|
|
483
|
+
if (hasSelectorConditionContradiction(mergedRoots)) return null;
|
|
484
|
+
const mergedModifiers = dedupeSelectorConditions([...a.modifierConditions, ...b.modifierConditions]);
|
|
485
|
+
const mergedPseudos = dedupeSelectorConditions([...a.pseudoConditions, ...b.pseudoConditions]);
|
|
486
|
+
if (hasSelectorConditionContradiction([...mergedModifiers, ...mergedPseudos])) return null;
|
|
487
|
+
const mergedParentGroups = [...a.parentGroups, ...b.parentGroups];
|
|
488
|
+
if (hasParentGroupContradiction(mergedParentGroups)) return null;
|
|
489
|
+
const mergedOwn = dedupeSelectorConditions([...a.ownConditions, ...b.ownConditions]);
|
|
490
|
+
if (hasSelectorConditionContradiction(mergedOwn)) return null;
|
|
472
491
|
const mergedContainers = dedupeContainerConditions([...a.containerConditions, ...b.containerConditions]);
|
|
473
492
|
if (hasContainerStyleContradiction(mergedContainers)) return null;
|
|
474
493
|
const mergedSupports = dedupeSupportsConditions([...a.supportsConditions, ...b.supportsConditions]);
|
|
@@ -481,7 +500,7 @@ function mergeVariants(a, b) {
|
|
|
481
500
|
containerConditions: mergedContainers,
|
|
482
501
|
supportsConditions: mergedSupports,
|
|
483
502
|
rootConditions: mergedRoots,
|
|
484
|
-
|
|
503
|
+
parentGroups: mergedParentGroups,
|
|
485
504
|
startingStyle: a.startingStyle || b.startingStyle
|
|
486
505
|
};
|
|
487
506
|
}
|
|
@@ -631,7 +650,7 @@ function hasContainerStyleContradiction(conditions) {
|
|
|
631
650
|
function getVariantKey(v) {
|
|
632
651
|
const modifierKey = v.modifierConditions.map(getModifierKey).sort().join("|");
|
|
633
652
|
const pseudoKey = v.pseudoConditions.map(getPseudoKey).sort().join("|");
|
|
634
|
-
const ownKey = v.ownConditions.map(
|
|
653
|
+
const ownKey = v.ownConditions.map(getSelectorConditionKey).sort().join("|");
|
|
635
654
|
const containerKey = v.containerConditions.map((c) => `${c.name ?? ""}:${c.negated ? "!" : ""}${c.condition}`).sort().join("|");
|
|
636
655
|
return [
|
|
637
656
|
modifierKey,
|
|
@@ -640,8 +659,8 @@ function getVariantKey(v) {
|
|
|
640
659
|
v.mediaConditions.map((c) => `${c.subtype}:${c.negated ? "!" : ""}${c.condition}`).sort().join("|"),
|
|
641
660
|
containerKey,
|
|
642
661
|
v.supportsConditions.map((c) => `${c.subtype}:${c.negated ? "!" : ""}${c.condition}`).sort().join("|"),
|
|
643
|
-
v.rootConditions.map(
|
|
644
|
-
v.
|
|
662
|
+
v.rootConditions.map(getSelectorConditionKey).sort().join("|"),
|
|
663
|
+
v.parentGroups.map(getParentGroupKey).sort().join("|"),
|
|
645
664
|
v.startingStyle ? "1" : "0"
|
|
646
665
|
].join("###");
|
|
647
666
|
}
|
|
@@ -658,15 +677,16 @@ function getVariantKey(v) {
|
|
|
658
677
|
*/
|
|
659
678
|
function isVariantSuperset(a, b) {
|
|
660
679
|
if (a.startingStyle !== b.startingStyle) return false;
|
|
661
|
-
if (!
|
|
680
|
+
if (!isSelectorConditionsSuperset(a.rootConditions, b.rootConditions)) return false;
|
|
662
681
|
if (!isMediaConditionsSuperset(a.mediaConditions, b.mediaConditions)) return false;
|
|
663
682
|
if (!isContainerConditionsSuperset(a.containerConditions, b.containerConditions)) return false;
|
|
664
683
|
if (!isSupportsConditionsSuperset(a.supportsConditions, b.supportsConditions)) return false;
|
|
665
684
|
if (!isModifierConditionsSuperset(a.modifierConditions, b.modifierConditions)) return false;
|
|
666
685
|
if (!isPseudoConditionsSuperset(a.pseudoConditions, b.pseudoConditions)) return false;
|
|
667
|
-
if (!
|
|
668
|
-
if (!
|
|
669
|
-
|
|
686
|
+
if (!isSelectorConditionsSuperset(a.ownConditions, b.ownConditions)) return false;
|
|
687
|
+
if (!isParentGroupsSuperset(a.parentGroups, b.parentGroups)) return false;
|
|
688
|
+
const parentConditionCount = (groups) => groups.reduce((sum, g) => sum + g.conditions.length, 0);
|
|
689
|
+
return a.mediaConditions.length + a.containerConditions.length + a.supportsConditions.length + a.modifierConditions.length + a.pseudoConditions.length + a.rootConditions.length + parentConditionCount(a.parentGroups) + a.ownConditions.length > b.mediaConditions.length + b.containerConditions.length + b.supportsConditions.length + b.modifierConditions.length + b.pseudoConditions.length + b.rootConditions.length + parentConditionCount(b.parentGroups) + b.ownConditions.length;
|
|
670
690
|
}
|
|
671
691
|
/**
|
|
672
692
|
* Check if media conditions A is a superset of B
|
|
@@ -718,31 +738,26 @@ function isPseudoConditionsSuperset(a, b) {
|
|
|
718
738
|
return true;
|
|
719
739
|
}
|
|
720
740
|
/**
|
|
721
|
-
* Check if
|
|
741
|
+
* Check if selector conditions A is a superset of B.
|
|
742
|
+
* Shared by root and own conditions.
|
|
722
743
|
*/
|
|
723
|
-
function
|
|
724
|
-
const aKeys = new Set(a.map(
|
|
725
|
-
for (const c of b) if (!aKeys.has(
|
|
744
|
+
function isSelectorConditionsSuperset(a, b) {
|
|
745
|
+
const aKeys = new Set(a.map(getSelectorConditionKey));
|
|
746
|
+
for (const c of b) if (!aKeys.has(getSelectorConditionKey(c))) return false;
|
|
726
747
|
return true;
|
|
727
748
|
}
|
|
728
749
|
/**
|
|
729
|
-
* Check if parent
|
|
750
|
+
* Check if parent groups A is a superset of B.
|
|
751
|
+
* Each group in B must have a matching group in A.
|
|
730
752
|
*/
|
|
731
|
-
function
|
|
732
|
-
|
|
733
|
-
|
|
753
|
+
function isParentGroupsSuperset(a, b) {
|
|
754
|
+
if (a.length < b.length) return false;
|
|
755
|
+
const aKeys = new Set(a.map(getParentGroupKey));
|
|
756
|
+
for (const g of b) if (!aKeys.has(getParentGroupKey(g))) return false;
|
|
734
757
|
return true;
|
|
735
758
|
}
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
*/
|
|
739
|
-
function isOwnConditionsSuperset(a, b) {
|
|
740
|
-
const aKeys = new Set(a.map((c) => "attribute" in c ? `mod:${getModifierKey(c)}` : `pseudo:${getPseudoKey(c)}`));
|
|
741
|
-
for (const c of b) {
|
|
742
|
-
const key = "attribute" in c ? `mod:${getModifierKey(c)}` : `pseudo:${getPseudoKey(c)}`;
|
|
743
|
-
if (!aKeys.has(key)) return false;
|
|
744
|
-
}
|
|
745
|
-
return true;
|
|
759
|
+
function getParentGroupKey(g) {
|
|
760
|
+
return `${g.negated ? "!" : ""}${g.direct ? ">" : ""}(${g.conditions.map(getSelectorConditionKey).sort().join(",")})`;
|
|
746
761
|
}
|
|
747
762
|
/**
|
|
748
763
|
* Deduplicate variants
|
|
@@ -761,9 +776,8 @@ function dedupeVariants(variants) {
|
|
|
761
776
|
result.push(v);
|
|
762
777
|
}
|
|
763
778
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
});
|
|
779
|
+
const variantConditionCount = (v) => v.modifierConditions.length + v.pseudoConditions.length + v.ownConditions.length + v.mediaConditions.length + v.containerConditions.length + v.supportsConditions.length + v.rootConditions.length + v.parentGroups.reduce((sum, g) => sum + g.conditions.length, 0);
|
|
780
|
+
result.sort((a, b) => variantConditionCount(a) - variantConditionCount(b));
|
|
767
781
|
const filtered = [];
|
|
768
782
|
for (const candidate of result) {
|
|
769
783
|
let isRedundant = false;
|
|
@@ -890,5 +904,5 @@ function buildAtRulesFromVariant(variant) {
|
|
|
890
904
|
}
|
|
891
905
|
|
|
892
906
|
//#endregion
|
|
893
|
-
export { buildAtRulesFromVariant, conditionToCSS, modifierToCSS,
|
|
907
|
+
export { buildAtRulesFromVariant, conditionToCSS, modifierToCSS, parentGroupsToCSS, pseudoToCSS, rootConditionsToCSS, selectorConditionToCSS };
|
|
894
908
|
//# sourceMappingURL=materialize.js.map
|