@homebound/truss 2.19.2 → 2.20.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/build/index.js +32 -10
- package/build/index.js.map +1 -1
- package/build/plugin/index.js +128 -85
- package/build/plugin/index.js.map +1 -1
- package/build/runtime.js +4 -6
- package/build/runtime.js.map +1 -1
- package/package.json +1 -1
package/build/plugin/index.js
CHANGED
|
@@ -6,6 +6,23 @@ import { createHash } from "crypto";
|
|
|
6
6
|
// src/plugin/emit-truss.ts
|
|
7
7
|
import * as t from "@babel/types";
|
|
8
8
|
|
|
9
|
+
// src/plugin/types.ts
|
|
10
|
+
var _longhandCache = /* @__PURE__ */ new WeakMap();
|
|
11
|
+
function getLonghandLookup(mapping) {
|
|
12
|
+
let lookup = _longhandCache.get(mapping);
|
|
13
|
+
if (lookup) return lookup;
|
|
14
|
+
lookup = /* @__PURE__ */ new Map();
|
|
15
|
+
for (const [abbr, entry] of Object.entries(mapping.abbreviations)) {
|
|
16
|
+
if (entry.kind !== "static") continue;
|
|
17
|
+
const keys = Object.keys(entry.defs);
|
|
18
|
+
if (keys.length !== 1) continue;
|
|
19
|
+
const key = `${keys[0]}\0${entry.defs[keys[0]]}`;
|
|
20
|
+
if (!lookup.has(key)) lookup.set(key, abbr);
|
|
21
|
+
}
|
|
22
|
+
_longhandCache.set(mapping, lookup);
|
|
23
|
+
return lookup;
|
|
24
|
+
}
|
|
25
|
+
|
|
9
26
|
// src/plugin/property-priorities.ts
|
|
10
27
|
var longHandPhysical = /* @__PURE__ */ new Set();
|
|
11
28
|
var longHandLogical = /* @__PURE__ */ new Set();
|
|
@@ -1067,30 +1084,6 @@ function cleanValueForClassName(value) {
|
|
|
1067
1084
|
function getPropertyAbbreviation(cssProp) {
|
|
1068
1085
|
return cssPropertyAbbreviations[cssProp] ?? cssProp;
|
|
1069
1086
|
}
|
|
1070
|
-
function buildLonghandLookup(mapping) {
|
|
1071
|
-
const lookup = /* @__PURE__ */ new Map();
|
|
1072
|
-
for (const [abbrev, entry] of Object.entries(mapping.abbreviations)) {
|
|
1073
|
-
if (entry.kind !== "static") continue;
|
|
1074
|
-
const props = Object.keys(entry.defs);
|
|
1075
|
-
if (props.length !== 1) continue;
|
|
1076
|
-
const prop = props[0];
|
|
1077
|
-
const value = String(entry.defs[prop]);
|
|
1078
|
-
const key = `${prop}\0${value}`;
|
|
1079
|
-
if (!lookup.has(key)) {
|
|
1080
|
-
lookup.set(key, abbrev);
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
return lookup;
|
|
1084
|
-
}
|
|
1085
|
-
var cachedMapping = null;
|
|
1086
|
-
var cachedLookup = null;
|
|
1087
|
-
function getLonghandLookup(mapping) {
|
|
1088
|
-
if (cachedMapping !== mapping) {
|
|
1089
|
-
cachedMapping = mapping;
|
|
1090
|
-
cachedLookup = buildLonghandLookup(mapping);
|
|
1091
|
-
}
|
|
1092
|
-
return cachedLookup;
|
|
1093
|
-
}
|
|
1094
1087
|
function computeStaticBaseName(seg, cssProp, cssValue, isMultiProp, mapping) {
|
|
1095
1088
|
const abbr = seg.abbr;
|
|
1096
1089
|
if (seg.argResolved !== void 0) {
|
|
@@ -1749,7 +1742,9 @@ function applyModifierNodeToConditionContext(context, node, mapping) {
|
|
|
1749
1742
|
context.pseudoClass = pseudoSelector(node.name);
|
|
1750
1743
|
}
|
|
1751
1744
|
}
|
|
1752
|
-
function resolveFullChain(
|
|
1745
|
+
function resolveFullChain(ctx, chain) {
|
|
1746
|
+
const { mapping } = ctx;
|
|
1747
|
+
const initialContext = ctx.initialContext ?? emptyConditionContext();
|
|
1753
1748
|
const parts = [];
|
|
1754
1749
|
const markers = [];
|
|
1755
1750
|
const nestedErrors = [];
|
|
@@ -1779,7 +1774,7 @@ function resolveFullChain(chain, mapping, cssBindingName, initialContext = empty
|
|
|
1779
1774
|
}
|
|
1780
1775
|
parts.push({
|
|
1781
1776
|
type: "unconditional",
|
|
1782
|
-
segments: resolveChain(
|
|
1777
|
+
segments: resolveChain({ ...ctx, initialContext: currentNodesStartContext }, currentNodes)
|
|
1783
1778
|
});
|
|
1784
1779
|
currentNodes = [];
|
|
1785
1780
|
currentNodesStartContext = cloneConditionContext(currentContext);
|
|
@@ -1801,8 +1796,8 @@ function resolveFullChain(chain, mapping, cssBindingName, initialContext = empty
|
|
|
1801
1796
|
const branchContext = cloneConditionContext(currentContext);
|
|
1802
1797
|
const thenNodes = mediaStart.thenNodes ? [...mediaStart.thenNodes, ...filteredChain.slice(i + 1, elseIndex)] : filteredChain.slice(i, elseIndex);
|
|
1803
1798
|
const elseNodes = [makeMediaQueryNode(mediaStart.inverseMediaQuery), ...filteredChain.slice(elseIndex + 1)];
|
|
1804
|
-
const thenSegs = resolveChain(
|
|
1805
|
-
const elseSegs = resolveChain(
|
|
1799
|
+
const thenSegs = resolveChain({ ...ctx, initialContext: branchContext }, thenNodes);
|
|
1800
|
+
const elseSegs = resolveChain({ ...ctx, initialContext: branchContext }, elseNodes);
|
|
1806
1801
|
parts.push({ type: "unconditional", segments: [...thenSegs, ...elseSegs] });
|
|
1807
1802
|
i = filteredChain.length;
|
|
1808
1803
|
break;
|
|
@@ -1810,13 +1805,7 @@ function resolveFullChain(chain, mapping, cssBindingName, initialContext = empty
|
|
|
1810
1805
|
}
|
|
1811
1806
|
if (isWhenObjectCall(node)) {
|
|
1812
1807
|
flushCurrentNodes();
|
|
1813
|
-
const resolved = resolveWhenObjectSelectors(
|
|
1814
|
-
node,
|
|
1815
|
-
mapping,
|
|
1816
|
-
cssBindingName,
|
|
1817
|
-
currentContext,
|
|
1818
|
-
resolveCssChainReference2
|
|
1819
|
-
);
|
|
1808
|
+
const resolved = resolveWhenObjectSelectors(ctx, node, currentContext);
|
|
1820
1809
|
parts.push(...resolved.parts);
|
|
1821
1810
|
markers.push(...resolved.markers);
|
|
1822
1811
|
nestedErrors.push(...resolved.errors);
|
|
@@ -1852,8 +1841,8 @@ function resolveFullChain(chain, mapping, cssBindingName, initialContext = empty
|
|
|
1852
1841
|
}
|
|
1853
1842
|
i++;
|
|
1854
1843
|
}
|
|
1855
|
-
const thenSegs = resolveChain(
|
|
1856
|
-
const elseSegs = resolveChain(
|
|
1844
|
+
const thenSegs = resolveChain({ ...ctx, initialContext: branchContext }, thenNodes);
|
|
1845
|
+
const elseSegs = resolveChain({ ...ctx, initialContext: branchContext }, elseNodes);
|
|
1857
1846
|
parts.push({
|
|
1858
1847
|
type: "conditional",
|
|
1859
1848
|
conditionNode: node.conditionNode,
|
|
@@ -1880,7 +1869,8 @@ function resolveFullChain(chain, mapping, cssBindingName, initialContext = empty
|
|
|
1880
1869
|
function isWhenObjectCall(node) {
|
|
1881
1870
|
return node.type === "call" && node.name === "when" && node.args.length === 1 && node.args[0].type === "ObjectExpression";
|
|
1882
1871
|
}
|
|
1883
|
-
function resolveWhenObjectSelectors(
|
|
1872
|
+
function resolveWhenObjectSelectors(ctx, node, initialContext) {
|
|
1873
|
+
const { cssBindingName } = ctx;
|
|
1884
1874
|
if (!cssBindingName) {
|
|
1885
1875
|
return {
|
|
1886
1876
|
parts: [],
|
|
@@ -1907,13 +1897,13 @@ function resolveWhenObjectSelectors(node, mapping, cssBindingName, initialContex
|
|
|
1907
1897
|
throw new UnsupportedPatternError(`when({ ... }) selector keys must be string literals`);
|
|
1908
1898
|
}
|
|
1909
1899
|
const value = unwrapExpression(property.value);
|
|
1910
|
-
const innerChain = resolveWhenObjectValueChain(
|
|
1900
|
+
const innerChain = resolveWhenObjectValueChain(ctx, value);
|
|
1911
1901
|
if (!innerChain) {
|
|
1912
1902
|
throw new UnsupportedPatternError(`when({ ... }) values must be Css.*.$ expressions`);
|
|
1913
1903
|
}
|
|
1914
1904
|
const selectorContext = cloneConditionContext(initialContext);
|
|
1915
1905
|
selectorContext.pseudoClass = property.key.value;
|
|
1916
|
-
const resolved = resolveFullChain(
|
|
1906
|
+
const resolved = resolveFullChain({ ...ctx, initialContext: selectorContext }, innerChain);
|
|
1917
1907
|
parts.push(...resolved.parts);
|
|
1918
1908
|
markers.push(...resolved.markers);
|
|
1919
1909
|
errors.push(...resolved.errors);
|
|
@@ -1927,7 +1917,8 @@ function resolveWhenObjectSelectors(node, mapping, cssBindingName, initialContex
|
|
|
1927
1917
|
}
|
|
1928
1918
|
return { parts, markers, errors: [...new Set(errors)] };
|
|
1929
1919
|
}
|
|
1930
|
-
function resolveWhenObjectValueChain(
|
|
1920
|
+
function resolveWhenObjectValueChain(ctx, value) {
|
|
1921
|
+
const { cssBindingName, resolveCssChainReference: resolveCssChainReference2 } = ctx;
|
|
1931
1922
|
if (cssBindingName && value.type === "MemberExpression" && !value.computed && value.property.type === "Identifier" && value.property.name === "$") {
|
|
1932
1923
|
return extractChain(value.object, cssBindingName);
|
|
1933
1924
|
}
|
|
@@ -1993,7 +1984,9 @@ function invertMediaQuery(query) {
|
|
|
1993
1984
|
}
|
|
1994
1985
|
return query.replace("@media", "@media not");
|
|
1995
1986
|
}
|
|
1996
|
-
function resolveChain(
|
|
1987
|
+
function resolveChain(ctx, chain) {
|
|
1988
|
+
const { mapping, cssBindingName } = ctx;
|
|
1989
|
+
const initialContext = ctx.initialContext ?? emptyConditionContext();
|
|
1997
1990
|
const segments = [];
|
|
1998
1991
|
const context = cloneConditionContext(initialContext);
|
|
1999
1992
|
for (const node of chain) {
|
|
@@ -2036,10 +2029,9 @@ function resolveChain(chain, mapping, initialContext = emptyConditionContext(),
|
|
|
2036
2029
|
context.mediaQuery = containerSelectorFromCall(node);
|
|
2037
2030
|
continue;
|
|
2038
2031
|
}
|
|
2039
|
-
if (abbr === "
|
|
2040
|
-
const seg =
|
|
2032
|
+
if (abbr === "with") {
|
|
2033
|
+
const seg = resolveWithCall(
|
|
2041
2034
|
node,
|
|
2042
|
-
mapping,
|
|
2043
2035
|
context.mediaQuery,
|
|
2044
2036
|
context.pseudoClass,
|
|
2045
2037
|
context.pseudoElement,
|
|
@@ -2048,6 +2040,18 @@ function resolveChain(chain, mapping, initialContext = emptyConditionContext(),
|
|
|
2048
2040
|
segments.push(seg);
|
|
2049
2041
|
continue;
|
|
2050
2042
|
}
|
|
2043
|
+
if (abbr === "add") {
|
|
2044
|
+
const segs = resolveAddCall(
|
|
2045
|
+
node,
|
|
2046
|
+
mapping,
|
|
2047
|
+
context.mediaQuery,
|
|
2048
|
+
context.pseudoClass,
|
|
2049
|
+
context.pseudoElement,
|
|
2050
|
+
context.whenPseudo
|
|
2051
|
+
);
|
|
2052
|
+
segments.push(...segs);
|
|
2053
|
+
continue;
|
|
2054
|
+
}
|
|
2051
2055
|
if (abbr === "className") {
|
|
2052
2056
|
const seg = resolveClassNameCall(
|
|
2053
2057
|
node,
|
|
@@ -2093,13 +2097,7 @@ function resolveChain(chain, mapping, initialContext = emptyConditionContext(),
|
|
|
2093
2097
|
}
|
|
2094
2098
|
if (abbr === "when") {
|
|
2095
2099
|
if (isWhenObjectCall(node)) {
|
|
2096
|
-
const resolved2 = resolveWhenObjectSelectors(
|
|
2097
|
-
node,
|
|
2098
|
-
mapping,
|
|
2099
|
-
cssBindingName,
|
|
2100
|
-
context,
|
|
2101
|
-
resolveCssChainReference2
|
|
2102
|
-
);
|
|
2100
|
+
const resolved2 = resolveWhenObjectSelectors(ctx, node, context);
|
|
2103
2101
|
segments.push(...flattenWhenObjectParts(resolved2));
|
|
2104
2102
|
continue;
|
|
2105
2103
|
}
|
|
@@ -2370,18 +2368,15 @@ function resolveStyleCall(node, mediaQuery, pseudoClass, pseudoElement, whenPseu
|
|
|
2370
2368
|
styleArg: arg
|
|
2371
2369
|
};
|
|
2372
2370
|
}
|
|
2373
|
-
function
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
if (styleArg.type === "SpreadElement") {
|
|
2383
|
-
throw new UnsupportedPatternError(`addCss() does not support spread arguments`);
|
|
2384
|
-
}
|
|
2371
|
+
function resolveWithCall(node, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
|
|
2372
|
+
if (node.args.length !== 1) {
|
|
2373
|
+
throw new UnsupportedPatternError(`with() requires exactly 1 argument`);
|
|
2374
|
+
}
|
|
2375
|
+
const styleArg = node.args[0];
|
|
2376
|
+
if (styleArg.type === "SpreadElement") {
|
|
2377
|
+
throw new UnsupportedPatternError(`with() does not support spread arguments`);
|
|
2378
|
+
}
|
|
2379
|
+
if (styleArg.type === "ObjectExpression") {
|
|
2385
2380
|
return {
|
|
2386
2381
|
abbr: "__composed_css_prop",
|
|
2387
2382
|
defs: {},
|
|
@@ -2389,25 +2384,34 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
|
|
|
2389
2384
|
isAddCss: true
|
|
2390
2385
|
};
|
|
2391
2386
|
}
|
|
2387
|
+
return {
|
|
2388
|
+
abbr: "__composed_css_prop",
|
|
2389
|
+
defs: {},
|
|
2390
|
+
styleArrayArg: styleArg
|
|
2391
|
+
};
|
|
2392
|
+
}
|
|
2393
|
+
function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
|
|
2394
|
+
const context = {
|
|
2395
|
+
mediaQuery,
|
|
2396
|
+
pseudoClass,
|
|
2397
|
+
pseudoElement,
|
|
2398
|
+
whenPseudo
|
|
2399
|
+
};
|
|
2392
2400
|
if (node.args.length === 1) {
|
|
2393
2401
|
const styleArg = node.args[0];
|
|
2394
2402
|
if (styleArg.type === "SpreadElement") {
|
|
2395
2403
|
throw new UnsupportedPatternError(`add() does not support spread arguments`);
|
|
2396
2404
|
}
|
|
2397
2405
|
if (styleArg.type === "ObjectExpression") {
|
|
2398
|
-
|
|
2399
|
-
`add(cssProp) does not accept object literals -- pass an existing CssProp expression instead`
|
|
2400
|
-
);
|
|
2406
|
+
return resolveAddObjectLiteral(styleArg, mapping, context);
|
|
2401
2407
|
}
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
styleArrayArg: styleArg
|
|
2406
|
-
};
|
|
2408
|
+
throw new UnsupportedPatternError(
|
|
2409
|
+
`add() requires 1 or 2 arguments (property name and value, or an object literal), got ${node.args.length}. Supported overloads are add({ prop: value }), add("propName", value), and with(cssProp)`
|
|
2410
|
+
);
|
|
2407
2411
|
}
|
|
2408
2412
|
if (node.args.length !== 2) {
|
|
2409
2413
|
throw new UnsupportedPatternError(
|
|
2410
|
-
`add() requires
|
|
2414
|
+
`add() requires 1 or 2 arguments (property name and value, or an object literal), got ${node.args.length}. Supported overloads are add({ prop: value }), add("propName", value), and with(cssProp)`
|
|
2411
2415
|
);
|
|
2412
2416
|
}
|
|
2413
2417
|
const propArg = node.args[0];
|
|
@@ -2417,19 +2421,13 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
|
|
|
2417
2421
|
const propName = propArg.value;
|
|
2418
2422
|
const valueArg = node.args[1];
|
|
2419
2423
|
const literalValue = tryEvaluateAddLiteral(valueArg);
|
|
2420
|
-
const context = {
|
|
2421
|
-
mediaQuery,
|
|
2422
|
-
pseudoClass,
|
|
2423
|
-
pseudoElement,
|
|
2424
|
-
whenPseudo
|
|
2425
|
-
};
|
|
2426
2424
|
if (literalValue !== null) {
|
|
2427
|
-
return segmentWithConditionContext(
|
|
2425
|
+
return [segmentWithConditionContext(
|
|
2428
2426
|
{ abbr: propName, defs: { [propName]: literalValue }, argResolved: literalValue },
|
|
2429
2427
|
context
|
|
2430
|
-
);
|
|
2428
|
+
)];
|
|
2431
2429
|
}
|
|
2432
|
-
return segmentWithConditionContext(
|
|
2430
|
+
return [segmentWithConditionContext(
|
|
2433
2431
|
{
|
|
2434
2432
|
abbr: propName,
|
|
2435
2433
|
defs: {},
|
|
@@ -2438,7 +2436,52 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
|
|
|
2438
2436
|
argNode: valueArg
|
|
2439
2437
|
},
|
|
2440
2438
|
context
|
|
2441
|
-
);
|
|
2439
|
+
)];
|
|
2440
|
+
}
|
|
2441
|
+
function resolveAddObjectLiteral(obj, mapping, context) {
|
|
2442
|
+
const segments = [];
|
|
2443
|
+
for (const property of obj.properties) {
|
|
2444
|
+
if (property.type === "SpreadElement") {
|
|
2445
|
+
throw new UnsupportedPatternError(`add({...}) does not support spread properties -- use with() instead`);
|
|
2446
|
+
}
|
|
2447
|
+
if (property.type !== "ObjectProperty" || property.computed) {
|
|
2448
|
+
throw new UnsupportedPatternError(`add({...}) only supports simple property keys`);
|
|
2449
|
+
}
|
|
2450
|
+
let propName;
|
|
2451
|
+
if (property.key.type === "Identifier") {
|
|
2452
|
+
propName = property.key.name;
|
|
2453
|
+
} else if (property.key.type === "StringLiteral") {
|
|
2454
|
+
propName = property.key.value;
|
|
2455
|
+
} else {
|
|
2456
|
+
throw new UnsupportedPatternError(`add({...}) property keys must be identifiers or string literals`);
|
|
2457
|
+
}
|
|
2458
|
+
const valueNode = property.value;
|
|
2459
|
+
const literalValue = tryEvaluateAddLiteral(valueNode);
|
|
2460
|
+
if (literalValue !== null) {
|
|
2461
|
+
const canonicalAbbr = findCanonicalAbbreviation(mapping, propName, literalValue);
|
|
2462
|
+
if (canonicalAbbr) {
|
|
2463
|
+
const entry = mapping.abbreviations[canonicalAbbr];
|
|
2464
|
+
segments.push(segmentWithConditionContext(
|
|
2465
|
+
{ abbr: canonicalAbbr, defs: entry.defs },
|
|
2466
|
+
context
|
|
2467
|
+
));
|
|
2468
|
+
} else {
|
|
2469
|
+
segments.push(segmentWithConditionContext(
|
|
2470
|
+
{ abbr: propName, defs: { [propName]: literalValue }, argResolved: literalValue },
|
|
2471
|
+
context
|
|
2472
|
+
));
|
|
2473
|
+
}
|
|
2474
|
+
} else {
|
|
2475
|
+
segments.push(segmentWithConditionContext(
|
|
2476
|
+
{ abbr: propName, defs: {}, variableProps: [propName], incremented: false, argNode: valueNode },
|
|
2477
|
+
context
|
|
2478
|
+
));
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
return segments;
|
|
2482
|
+
}
|
|
2483
|
+
function findCanonicalAbbreviation(mapping, prop, value) {
|
|
2484
|
+
return getLonghandLookup(mapping).get(`${prop}\0${value}`) ?? null;
|
|
2442
2485
|
}
|
|
2443
2486
|
function tryEvaluateAddLiteral(node) {
|
|
2444
2487
|
if (node.type === "StringLiteral") {
|
|
@@ -3114,7 +3157,7 @@ function transformTruss(code, filename, mapping, options = {}) {
|
|
|
3114
3157
|
return;
|
|
3115
3158
|
}
|
|
3116
3159
|
const resolveCssChainReference2 = buildCssChainReferenceResolver(path, cssBindingName);
|
|
3117
|
-
const resolvedChain = resolveFullChain(
|
|
3160
|
+
const resolvedChain = resolveFullChain({ mapping, cssBindingName, resolveCssChainReference: resolveCssChainReference2 }, chain);
|
|
3118
3161
|
sites.push({ path, resolvedChain });
|
|
3119
3162
|
const line = path.node.loc?.start.line ?? null;
|
|
3120
3163
|
for (const err of resolvedChain.errors) {
|
|
@@ -3515,7 +3558,7 @@ function resolveCssExpression(node, cssBindingName, mapping, filename) {
|
|
|
3515
3558
|
return { error: "when() modifiers are not supported in .css.ts files" };
|
|
3516
3559
|
}
|
|
3517
3560
|
}
|
|
3518
|
-
const resolved = resolveFullChain(
|
|
3561
|
+
const resolved = resolveFullChain({ mapping, cssBindingName }, chain);
|
|
3519
3562
|
if (resolved.errors.length > 0) {
|
|
3520
3563
|
return { error: resolved.errors[0] };
|
|
3521
3564
|
}
|