@homebound/truss 2.15.0 → 2.15.2
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/plugin/index.d.ts +2 -1
- package/build/plugin/index.js +311 -212
- package/build/plugin/index.js.map +1 -1
- package/package.json +1 -1
package/build/plugin/index.js
CHANGED
|
@@ -544,7 +544,7 @@ var RELATIONSHIP_BASE = {
|
|
|
544
544
|
siblingAfter: 40
|
|
545
545
|
};
|
|
546
546
|
function computeRulePriority(rule) {
|
|
547
|
-
let priority = getPropertyPriority(rule.cssProperty);
|
|
547
|
+
let priority = getPropertyPriority(rule.declarations[0].cssProperty);
|
|
548
548
|
if (rule.pseudoElement) {
|
|
549
549
|
priority += PSEUDO_ELEMENT_PRIORITY;
|
|
550
550
|
}
|
|
@@ -565,10 +565,7 @@ function computeRulePriority(rule) {
|
|
|
565
565
|
return priority;
|
|
566
566
|
}
|
|
567
567
|
function isVariableRule(rule) {
|
|
568
|
-
|
|
569
|
-
return rule.declarations.some((d) => d.cssVarName !== void 0);
|
|
570
|
-
}
|
|
571
|
-
return rule.cssVarName !== void 0;
|
|
568
|
+
return rule.declarations.some((d) => d.cssVarName !== void 0);
|
|
572
569
|
}
|
|
573
570
|
function sortRulesByPriority(rules) {
|
|
574
571
|
const decorated = rules.map((rule, i) => {
|
|
@@ -1013,6 +1010,27 @@ function whenPrefix(whenPseudo) {
|
|
|
1013
1010
|
const markerPart = whenPseudo.markerNode?.type === "Identifier" ? `${whenPseudo.markerNode.name}_` : "";
|
|
1014
1011
|
return `wh_${rel}_${pseudoTag}_${markerPart}`;
|
|
1015
1012
|
}
|
|
1013
|
+
function conditionPrefix(pseudoClass, mediaQuery, pseudoElement, breakpoints) {
|
|
1014
|
+
const parts = [];
|
|
1015
|
+
if (pseudoElement) {
|
|
1016
|
+
parts.push(`${pseudoElement.replace(/^::/, "")}_`);
|
|
1017
|
+
}
|
|
1018
|
+
if (mediaQuery && breakpoints) {
|
|
1019
|
+
const bpKey = Object.entries(breakpoints).find(([, v]) => v === mediaQuery)?.[0];
|
|
1020
|
+
if (bpKey) {
|
|
1021
|
+
const shortName = bpKey.replace(/^if/, "").toLowerCase();
|
|
1022
|
+
parts.push(`${shortName}_`);
|
|
1023
|
+
} else {
|
|
1024
|
+
parts.push("mq_");
|
|
1025
|
+
}
|
|
1026
|
+
} else if (mediaQuery) {
|
|
1027
|
+
parts.push("mq_");
|
|
1028
|
+
}
|
|
1029
|
+
if (pseudoClass) {
|
|
1030
|
+
parts.push(`${pseudoSelectorTag(pseudoClass)}_`);
|
|
1031
|
+
}
|
|
1032
|
+
return parts.join("");
|
|
1033
|
+
}
|
|
1016
1034
|
function pseudoSelectorTag(pseudo) {
|
|
1017
1035
|
const replaced = pseudo.trim().replace(/::?[a-zA-Z-]+/g, (match) => {
|
|
1018
1036
|
return `_${pseudoIdentifierTag(match)}_`;
|
|
@@ -1036,27 +1054,6 @@ function normalizePseudoIdentifier(pseudo) {
|
|
|
1036
1054
|
});
|
|
1037
1055
|
return `${prefix}${name}`;
|
|
1038
1056
|
}
|
|
1039
|
-
function conditionPrefix(pseudoClass, mediaQuery, pseudoElement, breakpoints) {
|
|
1040
|
-
const parts = [];
|
|
1041
|
-
if (pseudoElement) {
|
|
1042
|
-
parts.push(`${pseudoElement.replace(/^::/, "")}_`);
|
|
1043
|
-
}
|
|
1044
|
-
if (mediaQuery && breakpoints) {
|
|
1045
|
-
const bpKey = Object.entries(breakpoints).find(([, v]) => v === mediaQuery)?.[0];
|
|
1046
|
-
if (bpKey) {
|
|
1047
|
-
const shortName = bpKey.replace(/^if/, "").toLowerCase();
|
|
1048
|
-
parts.push(`${shortName}_`);
|
|
1049
|
-
} else {
|
|
1050
|
-
parts.push("mq_");
|
|
1051
|
-
}
|
|
1052
|
-
} else if (mediaQuery) {
|
|
1053
|
-
parts.push("mq_");
|
|
1054
|
-
}
|
|
1055
|
-
if (pseudoClass) {
|
|
1056
|
-
parts.push(`${pseudoSelectorTag(pseudoClass)}_`);
|
|
1057
|
-
}
|
|
1058
|
-
return parts.join("");
|
|
1059
|
-
}
|
|
1060
1057
|
function camelToKebab(s) {
|
|
1061
1058
|
return s.replace(/^(Webkit|Moz|Ms|O)/, (m) => `-${m.toLowerCase()}`).replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
|
|
1062
1059
|
}
|
|
@@ -1067,6 +1064,9 @@ function cleanValueForClassName(value) {
|
|
|
1067
1064
|
}
|
|
1068
1065
|
return cleaned.replace(/[^a-zA-Z0-9]/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "");
|
|
1069
1066
|
}
|
|
1067
|
+
function getPropertyAbbreviation(cssProp) {
|
|
1068
|
+
return cssPropertyAbbreviations[cssProp] ?? cssProp;
|
|
1069
|
+
}
|
|
1070
1070
|
function buildLonghandLookup(mapping) {
|
|
1071
1071
|
const lookup = /* @__PURE__ */ new Map();
|
|
1072
1072
|
for (const [abbrev, entry] of Object.entries(mapping.abbreviations)) {
|
|
@@ -1091,9 +1091,6 @@ function getLonghandLookup(mapping) {
|
|
|
1091
1091
|
}
|
|
1092
1092
|
return cachedLookup;
|
|
1093
1093
|
}
|
|
1094
|
-
function getPropertyAbbreviation(cssProp) {
|
|
1095
|
-
return cssPropertyAbbreviations[cssProp] ?? cssProp;
|
|
1096
|
-
}
|
|
1097
1094
|
function computeStaticBaseName(seg, cssProp, cssValue, isMultiProp, mapping) {
|
|
1098
1095
|
const abbr = seg.abbr;
|
|
1099
1096
|
if (seg.argResolved !== void 0) {
|
|
@@ -1145,10 +1142,11 @@ function collectAtomicRules(chains, mapping) {
|
|
|
1145
1142
|
return { rules, needsMaybeInc };
|
|
1146
1143
|
}
|
|
1147
1144
|
function segmentContext(seg, mapping) {
|
|
1145
|
+
const prefix = `${conditionPrefix(seg.pseudoClass, seg.mediaQuery, seg.pseudoElement, mapping.breakpoints)}${seg.whenPseudo ? whenPrefix(seg.whenPseudo) : ""}`;
|
|
1148
1146
|
if (seg.whenPseudo) {
|
|
1149
1147
|
const wp = seg.whenPseudo;
|
|
1150
1148
|
return {
|
|
1151
|
-
prefix
|
|
1149
|
+
prefix,
|
|
1152
1150
|
whenSelector: {
|
|
1153
1151
|
relationship: wp.relationship ?? "ancestor",
|
|
1154
1152
|
markerClass: markerClassName(wp.markerNode),
|
|
@@ -1156,7 +1154,7 @@ function segmentContext(seg, mapping) {
|
|
|
1156
1154
|
}
|
|
1157
1155
|
};
|
|
1158
1156
|
}
|
|
1159
|
-
return { prefix
|
|
1157
|
+
return { prefix };
|
|
1160
1158
|
}
|
|
1161
1159
|
function baseRuleFields(seg) {
|
|
1162
1160
|
return {
|
|
@@ -1175,9 +1173,8 @@ function collectStaticRules(rules, seg, mapping) {
|
|
|
1175
1173
|
if (!rules.has(className)) {
|
|
1176
1174
|
rules.set(className, {
|
|
1177
1175
|
className,
|
|
1178
|
-
cssProperty: camelToKebab(cssProp),
|
|
1179
|
-
|
|
1180
|
-
...!whenSelector && baseRuleFields(seg),
|
|
1176
|
+
declarations: [{ cssProperty: camelToKebab(cssProp), cssValue }],
|
|
1177
|
+
...baseRuleFields(seg),
|
|
1181
1178
|
whenSelector
|
|
1182
1179
|
});
|
|
1183
1180
|
}
|
|
@@ -1193,22 +1190,12 @@ function collectVariableRules(rules, seg, mapping) {
|
|
|
1193
1190
|
if (!existingRule) {
|
|
1194
1191
|
rules.set(className, {
|
|
1195
1192
|
className,
|
|
1196
|
-
cssProperty: declaration.cssProperty,
|
|
1197
|
-
cssValue: declaration.cssValue,
|
|
1198
1193
|
declarations: [declaration],
|
|
1199
|
-
|
|
1200
|
-
...!whenSelector && baseRuleFields(seg),
|
|
1194
|
+
...baseRuleFields(seg),
|
|
1201
1195
|
whenSelector
|
|
1202
1196
|
});
|
|
1203
1197
|
continue;
|
|
1204
1198
|
}
|
|
1205
|
-
existingRule.declarations ??= [
|
|
1206
|
-
{
|
|
1207
|
-
cssProperty: existingRule.cssProperty,
|
|
1208
|
-
cssValue: existingRule.cssValue,
|
|
1209
|
-
cssVarName: existingRule.cssVarName
|
|
1210
|
-
}
|
|
1211
|
-
];
|
|
1212
1199
|
if (!existingRule.declarations.some((entry) => {
|
|
1213
1200
|
return entry.cssProperty === declaration.cssProperty;
|
|
1214
1201
|
})) {
|
|
@@ -1225,9 +1212,8 @@ function collectVariableRules(rules, seg, mapping) {
|
|
|
1225
1212
|
if (!rules.has(extraName)) {
|
|
1226
1213
|
rules.set(extraName, {
|
|
1227
1214
|
className: extraName,
|
|
1228
|
-
cssProperty: camelToKebab(cssProp),
|
|
1229
|
-
|
|
1230
|
-
...!whenSelector && baseRuleFields(seg),
|
|
1215
|
+
declarations: [{ cssProperty: camelToKebab(cssProp), cssValue }],
|
|
1216
|
+
...baseRuleFields(seg),
|
|
1231
1217
|
whenSelector
|
|
1232
1218
|
});
|
|
1233
1219
|
}
|
|
@@ -1256,61 +1242,51 @@ function generateCssText(rules) {
|
|
|
1256
1242
|
return lines.join("\n");
|
|
1257
1243
|
}
|
|
1258
1244
|
function formatRule(rule) {
|
|
1259
|
-
if (rule.whenSelector) return formatWhenRule(rule);
|
|
1260
|
-
if (rule.mediaQuery && rule.pseudoClass) return formatMediaPseudoRule(rule);
|
|
1261
|
-
if (rule.mediaQuery && rule.pseudoElement) return formatMediaPseudoElementRule(rule);
|
|
1262
|
-
if (rule.mediaQuery) return formatMediaRule(rule);
|
|
1263
|
-
if (rule.pseudoClass && rule.pseudoElement) return formatPseudoRule(rule);
|
|
1264
|
-
if (rule.pseudoElement) return formatPseudoElementRule(rule);
|
|
1265
|
-
if (rule.pseudoClass) return formatPseudoRule(rule);
|
|
1266
|
-
return formatBaseRule(rule);
|
|
1267
|
-
}
|
|
1268
|
-
function formatBaseRule(rule) {
|
|
1269
|
-
return formatRuleBlock(`.${rule.className}`, rule);
|
|
1270
|
-
}
|
|
1271
|
-
function formatPseudoRule(rule) {
|
|
1272
|
-
const pe = rule.pseudoElement ? rule.pseudoElement : "";
|
|
1273
|
-
return formatRuleBlock(`.${rule.className}${rule.pseudoClass}${pe}`, rule);
|
|
1274
|
-
}
|
|
1275
|
-
function formatPseudoElementRule(rule) {
|
|
1276
|
-
return formatRuleBlock(`.${rule.className}${rule.pseudoElement}`, rule);
|
|
1277
|
-
}
|
|
1278
|
-
function formatWhenRule(rule) {
|
|
1279
1245
|
const whenSelector = rule.whenSelector;
|
|
1280
|
-
if (
|
|
1281
|
-
|
|
1282
|
-
|
|
1246
|
+
if (whenSelector) return formatWhenRule(rule, whenSelector);
|
|
1247
|
+
const selector = buildTargetSelector(rule, !!rule.mediaQuery);
|
|
1248
|
+
return formatRuleWithOptionalMedia(rule, selector);
|
|
1249
|
+
}
|
|
1250
|
+
function formatWhenRule(rule, whenSelector) {
|
|
1283
1251
|
const markerSelector = `.${whenSelector.markerClass}${whenSelector.pseudo}`;
|
|
1284
|
-
const
|
|
1252
|
+
const duplicateClassName = !!rule.mediaQuery;
|
|
1285
1253
|
if (whenSelector.relationship === "ancestor") {
|
|
1286
|
-
return
|
|
1254
|
+
return formatRuleWithOptionalMedia(rule, `${markerSelector} ${buildTargetSelector(rule, duplicateClassName)}`);
|
|
1287
1255
|
}
|
|
1288
1256
|
if (whenSelector.relationship === "descendant") {
|
|
1289
|
-
return
|
|
1257
|
+
return formatRuleWithOptionalMedia(rule, buildTargetSelector(rule, duplicateClassName, `:has(${markerSelector})`));
|
|
1290
1258
|
}
|
|
1291
1259
|
if (whenSelector.relationship === "siblingAfter") {
|
|
1292
|
-
return
|
|
1260
|
+
return formatRuleWithOptionalMedia(
|
|
1261
|
+
rule,
|
|
1262
|
+
buildTargetSelector(rule, duplicateClassName, `:has(~ ${markerSelector})`)
|
|
1263
|
+
);
|
|
1293
1264
|
}
|
|
1294
1265
|
if (whenSelector.relationship === "siblingBefore") {
|
|
1295
|
-
return
|
|
1266
|
+
return formatRuleWithOptionalMedia(rule, `${markerSelector} ~ ${buildTargetSelector(rule, duplicateClassName)}`);
|
|
1296
1267
|
}
|
|
1297
1268
|
if (whenSelector.relationship === "anySibling") {
|
|
1298
|
-
|
|
1269
|
+
const afterSelector = buildTargetSelector(rule, duplicateClassName, `:has(~ ${markerSelector})`);
|
|
1270
|
+
const beforeSelector = `${markerSelector} ~ ${buildTargetSelector(rule, duplicateClassName)}`;
|
|
1271
|
+
return formatRuleWithOptionalMedia(rule, `${afterSelector}, ${beforeSelector}`);
|
|
1299
1272
|
}
|
|
1300
|
-
return
|
|
1273
|
+
return formatRuleWithOptionalMedia(rule, `${markerSelector} ${buildTargetSelector(rule, duplicateClassName)}`);
|
|
1301
1274
|
}
|
|
1302
|
-
function
|
|
1303
|
-
|
|
1275
|
+
function buildTargetSelector(rule, duplicateClassName, extraPseudoClass) {
|
|
1276
|
+
const classSelector = duplicateClassName ? `.${rule.className}.${rule.className}` : `.${rule.className}`;
|
|
1277
|
+
const pseudoClass = rule.pseudoClass ?? "";
|
|
1278
|
+
const relationshipPseudoClass = extraPseudoClass ?? "";
|
|
1279
|
+
const pseudoElement = rule.pseudoElement ?? "";
|
|
1280
|
+
return `${classSelector}${pseudoClass}${relationshipPseudoClass}${pseudoElement}`;
|
|
1304
1281
|
}
|
|
1305
|
-
function
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
return formatNestedRuleBlock(rule.mediaQuery, `.${rule.className}.${rule.className}${pe}`, rule);
|
|
1282
|
+
function formatRuleWithOptionalMedia(rule, selector) {
|
|
1283
|
+
if (rule.mediaQuery) {
|
|
1284
|
+
return formatNestedRuleBlock(rule.mediaQuery, selector, rule);
|
|
1285
|
+
}
|
|
1286
|
+
return formatRuleBlock(selector, rule);
|
|
1311
1287
|
}
|
|
1312
1288
|
function getRuleDeclarations(rule) {
|
|
1313
|
-
return rule.declarations
|
|
1289
|
+
return rule.declarations;
|
|
1314
1290
|
}
|
|
1315
1291
|
function formatRuleBlock(selector, rule) {
|
|
1316
1292
|
const body = getRuleDeclarations(rule).map((declaration) => {
|
|
@@ -1449,6 +1425,78 @@ import * as t4 from "@babel/types";
|
|
|
1449
1425
|
import { basename } from "path";
|
|
1450
1426
|
|
|
1451
1427
|
// src/plugin/resolve-chain.ts
|
|
1428
|
+
function emptyConditionContext() {
|
|
1429
|
+
return {
|
|
1430
|
+
mediaQuery: null,
|
|
1431
|
+
pseudoClass: null,
|
|
1432
|
+
pseudoElement: null,
|
|
1433
|
+
whenPseudo: null
|
|
1434
|
+
};
|
|
1435
|
+
}
|
|
1436
|
+
function cloneConditionContext(context) {
|
|
1437
|
+
return {
|
|
1438
|
+
mediaQuery: context.mediaQuery,
|
|
1439
|
+
pseudoClass: context.pseudoClass,
|
|
1440
|
+
pseudoElement: context.pseudoElement,
|
|
1441
|
+
whenPseudo: context.whenPseudo ? { ...context.whenPseudo } : null
|
|
1442
|
+
};
|
|
1443
|
+
}
|
|
1444
|
+
function segmentWithConditionContext(segment, context) {
|
|
1445
|
+
return {
|
|
1446
|
+
...segment,
|
|
1447
|
+
mediaQuery: context.mediaQuery,
|
|
1448
|
+
pseudoClass: context.pseudoClass,
|
|
1449
|
+
pseudoElement: context.pseudoElement,
|
|
1450
|
+
whenPseudo: context.whenPseudo
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function applyModifierNodeToConditionContext(context, node, mapping) {
|
|
1454
|
+
if (node.type === "__mediaQuery") {
|
|
1455
|
+
context.mediaQuery = node.mediaQuery;
|
|
1456
|
+
return;
|
|
1457
|
+
}
|
|
1458
|
+
if (node.type === "getter") {
|
|
1459
|
+
if (isPseudoMethod(node.name)) {
|
|
1460
|
+
context.pseudoClass = pseudoSelector(node.name);
|
|
1461
|
+
return;
|
|
1462
|
+
}
|
|
1463
|
+
if (mapping.breakpoints && node.name in mapping.breakpoints) {
|
|
1464
|
+
context.mediaQuery = mapping.breakpoints[node.name];
|
|
1465
|
+
}
|
|
1466
|
+
return;
|
|
1467
|
+
}
|
|
1468
|
+
if (node.type !== "call") {
|
|
1469
|
+
return;
|
|
1470
|
+
}
|
|
1471
|
+
if (node.name === "ifContainer") {
|
|
1472
|
+
try {
|
|
1473
|
+
context.mediaQuery = containerSelectorFromCall(node);
|
|
1474
|
+
} catch {
|
|
1475
|
+
}
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1478
|
+
if (node.name === "element") {
|
|
1479
|
+
if (node.args.length === 1 && node.args[0].type === "StringLiteral") {
|
|
1480
|
+
context.pseudoElement = node.args[0].value;
|
|
1481
|
+
}
|
|
1482
|
+
return;
|
|
1483
|
+
}
|
|
1484
|
+
if (node.name === "when") {
|
|
1485
|
+
try {
|
|
1486
|
+
const resolved = resolveWhenCall(node);
|
|
1487
|
+
if (resolved.kind === "selector") {
|
|
1488
|
+
context.pseudoClass = resolved.pseudo;
|
|
1489
|
+
} else {
|
|
1490
|
+
context.whenPseudo = resolved;
|
|
1491
|
+
}
|
|
1492
|
+
} catch {
|
|
1493
|
+
}
|
|
1494
|
+
return;
|
|
1495
|
+
}
|
|
1496
|
+
if (isPseudoMethod(node.name)) {
|
|
1497
|
+
context.pseudoClass = pseudoSelector(node.name);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1452
1500
|
function resolveFullChain(chain, mapping) {
|
|
1453
1501
|
const parts = [];
|
|
1454
1502
|
const markers = [];
|
|
@@ -1470,20 +1518,38 @@ function resolveFullChain(chain, mapping) {
|
|
|
1470
1518
|
}
|
|
1471
1519
|
let i = 0;
|
|
1472
1520
|
let currentNodes = [];
|
|
1521
|
+
let currentContext = emptyConditionContext();
|
|
1522
|
+
let currentNodesStartContext = emptyConditionContext();
|
|
1523
|
+
function flushCurrentNodes() {
|
|
1524
|
+
if (currentNodes.length === 0) {
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
parts.push({
|
|
1528
|
+
type: "unconditional",
|
|
1529
|
+
segments: resolveChain(currentNodes, mapping, currentNodesStartContext)
|
|
1530
|
+
});
|
|
1531
|
+
currentNodes = [];
|
|
1532
|
+
currentNodesStartContext = cloneConditionContext(currentContext);
|
|
1533
|
+
}
|
|
1534
|
+
function pushCurrentNode(nodeToPush) {
|
|
1535
|
+
if (currentNodes.length === 0) {
|
|
1536
|
+
currentNodesStartContext = cloneConditionContext(currentContext);
|
|
1537
|
+
}
|
|
1538
|
+
currentNodes.push(nodeToPush);
|
|
1539
|
+
applyModifierNodeToConditionContext(currentContext, nodeToPush, mapping);
|
|
1540
|
+
}
|
|
1473
1541
|
while (i < filteredChain.length) {
|
|
1474
1542
|
const node = filteredChain[i];
|
|
1475
1543
|
const mediaStart = getMediaConditionalStartNode(node, mapping);
|
|
1476
1544
|
if (mediaStart) {
|
|
1477
1545
|
const elseIndex = findElseIndex(filteredChain, i + 1);
|
|
1478
1546
|
if (elseIndex !== -1) {
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
currentNodes = [];
|
|
1482
|
-
}
|
|
1547
|
+
flushCurrentNodes();
|
|
1548
|
+
const branchContext = cloneConditionContext(currentContext);
|
|
1483
1549
|
const thenNodes = mediaStart.thenNodes ? [...mediaStart.thenNodes, ...filteredChain.slice(i + 1, elseIndex)] : filteredChain.slice(i, elseIndex);
|
|
1484
1550
|
const elseNodes = [makeMediaQueryNode(mediaStart.inverseMediaQuery), ...filteredChain.slice(elseIndex + 1)];
|
|
1485
|
-
const thenSegs = resolveChain(thenNodes, mapping);
|
|
1486
|
-
const elseSegs = resolveChain(elseNodes, mapping);
|
|
1551
|
+
const thenSegs = resolveChain(thenNodes, mapping, branchContext);
|
|
1552
|
+
const elseSegs = resolveChain(elseNodes, mapping, branchContext);
|
|
1487
1553
|
parts.push({ type: "unconditional", segments: [...thenSegs, ...elseSegs] });
|
|
1488
1554
|
i = filteredChain.length;
|
|
1489
1555
|
break;
|
|
@@ -1492,14 +1558,12 @@ function resolveFullChain(chain, mapping) {
|
|
|
1492
1558
|
if (node.type === "if") {
|
|
1493
1559
|
if (node.conditionNode.type === "StringLiteral") {
|
|
1494
1560
|
const mediaQuery = node.conditionNode.value;
|
|
1495
|
-
|
|
1561
|
+
pushCurrentNode({ type: "__mediaQuery", mediaQuery });
|
|
1496
1562
|
i++;
|
|
1497
1563
|
continue;
|
|
1498
1564
|
}
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
currentNodes = [];
|
|
1502
|
-
}
|
|
1565
|
+
flushCurrentNodes();
|
|
1566
|
+
const branchContext = cloneConditionContext(currentContext);
|
|
1503
1567
|
const thenNodes = [];
|
|
1504
1568
|
const elseNodes = [];
|
|
1505
1569
|
i++;
|
|
@@ -1520,8 +1584,8 @@ function resolveFullChain(chain, mapping) {
|
|
|
1520
1584
|
}
|
|
1521
1585
|
i++;
|
|
1522
1586
|
}
|
|
1523
|
-
const thenSegs = resolveChain(thenNodes, mapping);
|
|
1524
|
-
const elseSegs = resolveChain(elseNodes, mapping);
|
|
1587
|
+
const thenSegs = resolveChain(thenNodes, mapping, branchContext);
|
|
1588
|
+
const elseSegs = resolveChain(elseNodes, mapping, branchContext);
|
|
1525
1589
|
parts.push({
|
|
1526
1590
|
type: "conditional",
|
|
1527
1591
|
conditionNode: node.conditionNode,
|
|
@@ -1529,13 +1593,11 @@ function resolveFullChain(chain, mapping) {
|
|
|
1529
1593
|
elseSegments: elseSegs
|
|
1530
1594
|
});
|
|
1531
1595
|
} else {
|
|
1532
|
-
|
|
1596
|
+
pushCurrentNode(node);
|
|
1533
1597
|
i++;
|
|
1534
1598
|
}
|
|
1535
1599
|
}
|
|
1536
|
-
|
|
1537
|
-
parts.push({ type: "unconditional", segments: resolveChain(currentNodes, mapping) });
|
|
1538
|
-
}
|
|
1600
|
+
flushCurrentNodes();
|
|
1539
1601
|
const segmentErrors = [];
|
|
1540
1602
|
for (const part of parts) {
|
|
1541
1603
|
const segs = part.type === "unconditional" ? part.segments : [...part.thenSegments, ...part.elseSegments];
|
|
@@ -1594,29 +1656,23 @@ function invertMediaQuery(query) {
|
|
|
1594
1656
|
}
|
|
1595
1657
|
return query.replace("@media", "@media not");
|
|
1596
1658
|
}
|
|
1597
|
-
function resolveChain(chain, mapping) {
|
|
1659
|
+
function resolveChain(chain, mapping, initialContext = emptyConditionContext()) {
|
|
1598
1660
|
const segments = [];
|
|
1599
|
-
|
|
1600
|
-
let currentPseudoClass = null;
|
|
1601
|
-
let currentPseudoElement = null;
|
|
1602
|
-
let currentWhenPseudo = null;
|
|
1661
|
+
const context = cloneConditionContext(initialContext);
|
|
1603
1662
|
for (const node of chain) {
|
|
1604
1663
|
try {
|
|
1605
1664
|
if (node.type === "__mediaQuery") {
|
|
1606
|
-
|
|
1607
|
-
currentWhenPseudo = null;
|
|
1665
|
+
context.mediaQuery = node.mediaQuery;
|
|
1608
1666
|
continue;
|
|
1609
1667
|
}
|
|
1610
1668
|
if (node.type === "getter") {
|
|
1611
1669
|
const abbr = node.name;
|
|
1612
1670
|
if (isPseudoMethod(abbr)) {
|
|
1613
|
-
|
|
1614
|
-
currentWhenPseudo = null;
|
|
1671
|
+
context.pseudoClass = pseudoSelector(abbr);
|
|
1615
1672
|
continue;
|
|
1616
1673
|
}
|
|
1617
1674
|
if (mapping.breakpoints && abbr in mapping.breakpoints) {
|
|
1618
|
-
|
|
1619
|
-
currentWhenPseudo = null;
|
|
1675
|
+
context.mediaQuery = mapping.breakpoints[abbr];
|
|
1620
1676
|
continue;
|
|
1621
1677
|
}
|
|
1622
1678
|
const entry = mapping.abbreviations[abbr];
|
|
@@ -1627,27 +1683,26 @@ function resolveChain(chain, mapping) {
|
|
|
1627
1683
|
abbr,
|
|
1628
1684
|
entry,
|
|
1629
1685
|
mapping,
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1686
|
+
context.mediaQuery,
|
|
1687
|
+
context.pseudoClass,
|
|
1688
|
+
context.pseudoElement,
|
|
1689
|
+
context.whenPseudo
|
|
1634
1690
|
);
|
|
1635
1691
|
segments.push(...resolved);
|
|
1636
1692
|
} else if (node.type === "call") {
|
|
1637
1693
|
const abbr = node.name;
|
|
1638
1694
|
if (abbr === "ifContainer") {
|
|
1639
|
-
|
|
1640
|
-
currentWhenPseudo = null;
|
|
1695
|
+
context.mediaQuery = containerSelectorFromCall(node);
|
|
1641
1696
|
continue;
|
|
1642
1697
|
}
|
|
1643
1698
|
if (abbr === "add" || abbr === "addCss") {
|
|
1644
1699
|
const seg = resolveAddCall(
|
|
1645
1700
|
node,
|
|
1646
1701
|
mapping,
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1702
|
+
context.mediaQuery,
|
|
1703
|
+
context.pseudoClass,
|
|
1704
|
+
context.pseudoElement,
|
|
1705
|
+
context.whenPseudo
|
|
1651
1706
|
);
|
|
1652
1707
|
segments.push(seg);
|
|
1653
1708
|
continue;
|
|
@@ -1655,10 +1710,10 @@ function resolveChain(chain, mapping) {
|
|
|
1655
1710
|
if (abbr === "className") {
|
|
1656
1711
|
const seg = resolveClassNameCall(
|
|
1657
1712
|
node,
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1713
|
+
context.mediaQuery,
|
|
1714
|
+
context.pseudoClass,
|
|
1715
|
+
context.pseudoElement,
|
|
1716
|
+
context.whenPseudo
|
|
1662
1717
|
);
|
|
1663
1718
|
segments.push(seg);
|
|
1664
1719
|
continue;
|
|
@@ -1667,9 +1722,10 @@ function resolveChain(chain, mapping) {
|
|
|
1667
1722
|
const resolved = resolveTypographyCall(
|
|
1668
1723
|
node,
|
|
1669
1724
|
mapping,
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1725
|
+
context.mediaQuery,
|
|
1726
|
+
context.pseudoClass,
|
|
1727
|
+
context.pseudoElement,
|
|
1728
|
+
context.whenPseudo
|
|
1673
1729
|
);
|
|
1674
1730
|
segments.push(...resolved);
|
|
1675
1731
|
continue;
|
|
@@ -1680,24 +1736,20 @@ function resolveChain(chain, mapping) {
|
|
|
1680
1736
|
`element() requires exactly one string literal argument (e.g. "::placeholder")`
|
|
1681
1737
|
);
|
|
1682
1738
|
}
|
|
1683
|
-
|
|
1739
|
+
context.pseudoElement = node.args[0].value;
|
|
1684
1740
|
continue;
|
|
1685
1741
|
}
|
|
1686
1742
|
if (abbr === "when") {
|
|
1687
1743
|
const resolved = resolveWhenCall(node);
|
|
1688
1744
|
if (resolved.kind === "selector") {
|
|
1689
|
-
|
|
1690
|
-
currentWhenPseudo = null;
|
|
1745
|
+
context.pseudoClass = resolved.pseudo;
|
|
1691
1746
|
} else {
|
|
1692
|
-
|
|
1693
|
-
currentMediaQuery = null;
|
|
1694
|
-
currentWhenPseudo = resolved;
|
|
1747
|
+
context.whenPseudo = resolved;
|
|
1695
1748
|
}
|
|
1696
1749
|
continue;
|
|
1697
1750
|
}
|
|
1698
1751
|
if (isPseudoMethod(abbr)) {
|
|
1699
|
-
|
|
1700
|
-
currentWhenPseudo = null;
|
|
1752
|
+
context.pseudoClass = pseudoSelector(abbr);
|
|
1701
1753
|
if (node.args.length > 0) {
|
|
1702
1754
|
throw new UnsupportedPatternError(
|
|
1703
1755
|
`${abbr}() does not take arguments -- use when(marker, "ancestor", ":hover") for relationship selectors`
|
|
@@ -1715,10 +1767,10 @@ function resolveChain(chain, mapping) {
|
|
|
1715
1767
|
entry,
|
|
1716
1768
|
node,
|
|
1717
1769
|
mapping,
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1770
|
+
context.mediaQuery,
|
|
1771
|
+
context.pseudoClass,
|
|
1772
|
+
context.pseudoElement,
|
|
1773
|
+
context.whenPseudo
|
|
1722
1774
|
);
|
|
1723
1775
|
segments.push(seg);
|
|
1724
1776
|
} else if (entry.kind === "delegate") {
|
|
@@ -1727,10 +1779,10 @@ function resolveChain(chain, mapping) {
|
|
|
1727
1779
|
entry,
|
|
1728
1780
|
node,
|
|
1729
1781
|
mapping,
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1782
|
+
context.mediaQuery,
|
|
1783
|
+
context.pseudoClass,
|
|
1784
|
+
context.pseudoElement,
|
|
1785
|
+
context.whenPseudo
|
|
1734
1786
|
);
|
|
1735
1787
|
segments.push(seg);
|
|
1736
1788
|
} else {
|
|
@@ -1747,7 +1799,7 @@ function resolveChain(chain, mapping) {
|
|
|
1747
1799
|
}
|
|
1748
1800
|
return segments;
|
|
1749
1801
|
}
|
|
1750
|
-
function typographyLookupKeySuffix(mediaQuery, pseudoClass, pseudoElement, breakpoints) {
|
|
1802
|
+
function typographyLookupKeySuffix(mediaQuery, pseudoClass, pseudoElement, whenPseudo, breakpoints) {
|
|
1751
1803
|
const parts = [];
|
|
1752
1804
|
if (pseudoElement) parts.push(pseudoElement.replace(/^::/, ""));
|
|
1753
1805
|
if (mediaQuery && breakpoints) {
|
|
@@ -1757,25 +1809,36 @@ function typographyLookupKeySuffix(mediaQuery, pseudoClass, pseudoElement, break
|
|
|
1757
1809
|
parts.push("mq");
|
|
1758
1810
|
}
|
|
1759
1811
|
if (pseudoClass) parts.push(pseudoClass.replace(/^:+/, "").replace(/-/g, "_"));
|
|
1812
|
+
if (whenPseudo) parts.push(whenLookupKeyPart(whenPseudo));
|
|
1813
|
+
return parts.join("_");
|
|
1814
|
+
}
|
|
1815
|
+
function whenLookupKeyPart(whenPseudo) {
|
|
1816
|
+
const parts = ["when", whenPseudo.relationship ?? "ancestor", sanitizeLookupToken(whenPseudo.pseudo)];
|
|
1817
|
+
if (whenPseudo.markerNode?.type === "Identifier" && whenPseudo.markerNode.name) {
|
|
1818
|
+
parts.push(whenPseudo.markerNode.name);
|
|
1819
|
+
}
|
|
1760
1820
|
return parts.join("_");
|
|
1761
1821
|
}
|
|
1762
|
-
function
|
|
1822
|
+
function sanitizeLookupToken(value) {
|
|
1823
|
+
return value.replace(/[^a-zA-Z0-9]+/g, "_").replace(/_+/g, "_").replace(/^_|_$/g, "") || "value";
|
|
1824
|
+
}
|
|
1825
|
+
function resolveTypographyCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
|
|
1763
1826
|
if (node.args.length !== 1) {
|
|
1764
1827
|
throw new UnsupportedPatternError(`typography() expects exactly 1 argument, got ${node.args.length}`);
|
|
1765
1828
|
}
|
|
1766
1829
|
const argAst = node.args[0];
|
|
1767
1830
|
if (argAst.type === "StringLiteral") {
|
|
1768
|
-
return resolveTypographyEntry(argAst.value, mapping, mediaQuery, pseudoClass, pseudoElement);
|
|
1831
|
+
return resolveTypographyEntry(argAst.value, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo);
|
|
1769
1832
|
}
|
|
1770
1833
|
const typography = mapping.typography ?? [];
|
|
1771
1834
|
if (typography.length === 0) {
|
|
1772
1835
|
throw new UnsupportedPatternError(`typography() is unavailable because no typography abbreviations were generated`);
|
|
1773
1836
|
}
|
|
1774
|
-
const suffix = typographyLookupKeySuffix(mediaQuery, pseudoClass, pseudoElement, mapping.breakpoints);
|
|
1837
|
+
const suffix = typographyLookupKeySuffix(mediaQuery, pseudoClass, pseudoElement, whenPseudo, mapping.breakpoints);
|
|
1775
1838
|
const lookupKey = suffix ? `typography__${suffix}` : "typography";
|
|
1776
1839
|
const segmentsByName = {};
|
|
1777
1840
|
for (const name of typography) {
|
|
1778
|
-
segmentsByName[name] = resolveTypographyEntry(name, mapping, mediaQuery, pseudoClass, pseudoElement);
|
|
1841
|
+
segmentsByName[name] = resolveTypographyEntry(name, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo);
|
|
1779
1842
|
}
|
|
1780
1843
|
return [
|
|
1781
1844
|
{
|
|
@@ -1789,7 +1852,7 @@ function resolveTypographyCall(node, mapping, mediaQuery, pseudoClass, pseudoEle
|
|
|
1789
1852
|
}
|
|
1790
1853
|
];
|
|
1791
1854
|
}
|
|
1792
|
-
function resolveTypographyEntry(name, mapping, mediaQuery, pseudoClass, pseudoElement) {
|
|
1855
|
+
function resolveTypographyEntry(name, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
|
|
1793
1856
|
if (!(mapping.typography ?? []).includes(name)) {
|
|
1794
1857
|
throw new UnsupportedPatternError(`Unknown typography abbreviation "${name}"`);
|
|
1795
1858
|
}
|
|
@@ -1797,21 +1860,24 @@ function resolveTypographyEntry(name, mapping, mediaQuery, pseudoClass, pseudoEl
|
|
|
1797
1860
|
if (!entry) {
|
|
1798
1861
|
throw new UnsupportedPatternError(`Unknown typography abbreviation "${name}"`);
|
|
1799
1862
|
}
|
|
1800
|
-
const resolved = resolveEntry(name, entry, mapping, mediaQuery, pseudoClass, pseudoElement,
|
|
1863
|
+
const resolved = resolveEntry(name, entry, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo);
|
|
1801
1864
|
for (const segment of resolved) {
|
|
1802
|
-
if (segment.variableProps
|
|
1865
|
+
if (segment.variableProps) {
|
|
1803
1866
|
throw new UnsupportedPatternError(`Typography abbreviation "${name}" cannot require runtime arguments`);
|
|
1804
1867
|
}
|
|
1805
1868
|
}
|
|
1806
1869
|
return resolved;
|
|
1807
1870
|
}
|
|
1808
1871
|
function resolveEntry(abbr, entry, mapping, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
|
|
1872
|
+
const context = {
|
|
1873
|
+
mediaQuery,
|
|
1874
|
+
pseudoClass,
|
|
1875
|
+
pseudoElement,
|
|
1876
|
+
whenPseudo
|
|
1877
|
+
};
|
|
1809
1878
|
switch (entry.kind) {
|
|
1810
1879
|
case "static": {
|
|
1811
|
-
|
|
1812
|
-
return [{ abbr, defs: entry.defs, whenPseudo }];
|
|
1813
|
-
}
|
|
1814
|
-
return [{ abbr, defs: entry.defs, mediaQuery, pseudoClass, pseudoElement }];
|
|
1880
|
+
return [segmentWithConditionContext({ abbr, defs: entry.defs }, context)];
|
|
1815
1881
|
}
|
|
1816
1882
|
case "alias": {
|
|
1817
1883
|
const result = [];
|
|
@@ -1874,40 +1940,32 @@ function resolveDelegateCall(abbr, entry, node, mapping, mediaQuery, pseudoClass
|
|
|
1874
1940
|
}
|
|
1875
1941
|
function buildParameterizedSegment(params) {
|
|
1876
1942
|
const { abbr, props, incremented, appendPx, extraDefs, argAst, literalValue, whenPseudo } = params;
|
|
1943
|
+
const context = {
|
|
1944
|
+
mediaQuery: params.mediaQuery,
|
|
1945
|
+
pseudoClass: params.pseudoClass,
|
|
1946
|
+
pseudoElement: params.pseudoElement,
|
|
1947
|
+
whenPseudo
|
|
1948
|
+
};
|
|
1877
1949
|
if (literalValue !== null) {
|
|
1878
1950
|
const defs = {};
|
|
1879
1951
|
for (const prop of props) {
|
|
1880
1952
|
defs[prop] = literalValue;
|
|
1881
1953
|
}
|
|
1882
1954
|
if (extraDefs) Object.assign(defs, extraDefs);
|
|
1883
|
-
|
|
1884
|
-
return { abbr, defs, whenPseudo, argResolved: literalValue };
|
|
1885
|
-
}
|
|
1886
|
-
return {
|
|
1887
|
-
abbr,
|
|
1888
|
-
defs,
|
|
1889
|
-
mediaQuery: params.mediaQuery,
|
|
1890
|
-
pseudoClass: params.pseudoClass,
|
|
1891
|
-
pseudoElement: params.pseudoElement,
|
|
1892
|
-
argResolved: literalValue
|
|
1893
|
-
};
|
|
1955
|
+
return segmentWithConditionContext({ abbr, defs, argResolved: literalValue }, context);
|
|
1894
1956
|
}
|
|
1895
|
-
const base =
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1957
|
+
const base = segmentWithConditionContext(
|
|
1958
|
+
{
|
|
1959
|
+
abbr,
|
|
1960
|
+
defs: {},
|
|
1961
|
+
variableProps: props,
|
|
1962
|
+
incremented,
|
|
1963
|
+
variableExtraDefs: extraDefs,
|
|
1964
|
+
argNode: argAst
|
|
1965
|
+
},
|
|
1966
|
+
context
|
|
1967
|
+
);
|
|
1903
1968
|
if (appendPx) base.appendPx = true;
|
|
1904
|
-
if (whenPseudo) {
|
|
1905
|
-
base.whenPseudo = whenPseudo;
|
|
1906
|
-
} else {
|
|
1907
|
-
base.mediaQuery = params.mediaQuery;
|
|
1908
|
-
base.pseudoClass = params.pseudoClass;
|
|
1909
|
-
base.pseudoElement = params.pseudoElement;
|
|
1910
|
-
}
|
|
1911
1969
|
return base;
|
|
1912
1970
|
}
|
|
1913
1971
|
function resolveClassNameCall(node, mediaQuery, pseudoClass, pseudoElement, whenPseudo) {
|
|
@@ -1977,34 +2035,28 @@ function resolveAddCall(node, mapping, mediaQuery, pseudoClass, pseudoElement, w
|
|
|
1977
2035
|
const propName = propArg.value;
|
|
1978
2036
|
const valueArg = node.args[1];
|
|
1979
2037
|
const literalValue = tryEvaluateAddLiteral(valueArg);
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
}
|
|
2038
|
+
const context = {
|
|
2039
|
+
mediaQuery,
|
|
2040
|
+
pseudoClass,
|
|
2041
|
+
pseudoElement,
|
|
2042
|
+
whenPseudo
|
|
2043
|
+
};
|
|
1987
2044
|
if (literalValue !== null) {
|
|
1988
|
-
return
|
|
1989
|
-
abbr: propName,
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
};
|
|
1996
|
-
} else {
|
|
1997
|
-
return {
|
|
2045
|
+
return segmentWithConditionContext(
|
|
2046
|
+
{ abbr: propName, defs: { [propName]: literalValue }, argResolved: literalValue },
|
|
2047
|
+
context
|
|
2048
|
+
);
|
|
2049
|
+
}
|
|
2050
|
+
return segmentWithConditionContext(
|
|
2051
|
+
{
|
|
1998
2052
|
abbr: propName,
|
|
1999
2053
|
defs: {},
|
|
2000
|
-
mediaQuery,
|
|
2001
|
-
pseudoClass,
|
|
2002
|
-
pseudoElement,
|
|
2003
2054
|
variableProps: [propName],
|
|
2004
2055
|
incremented: false,
|
|
2005
2056
|
argNode: valueArg
|
|
2006
|
-
}
|
|
2007
|
-
|
|
2057
|
+
},
|
|
2058
|
+
context
|
|
2059
|
+
);
|
|
2008
2060
|
}
|
|
2009
2061
|
function tryEvaluateAddLiteral(node) {
|
|
2010
2062
|
if (node.type === "StringLiteral") {
|
|
@@ -3358,11 +3410,14 @@ function toVirtualCssSpecifier(source) {
|
|
|
3358
3410
|
import { readFileSync } from "fs";
|
|
3359
3411
|
var RULE_ANNOTATION_RE = /^\/\* @truss p:([\d.]+) c:(\S+) \*\/$/;
|
|
3360
3412
|
var PROPERTY_ANNOTATION_RE = /^\/\* @truss @property \*\/$/;
|
|
3413
|
+
var ARBITRARY_START_RE = /^\/\* @truss arbitrary:start \*\/$/;
|
|
3414
|
+
var ARBITRARY_END_RE = /^\/\* @truss arbitrary:end \*\/$/;
|
|
3361
3415
|
var PROPERTY_VAR_RE = /^@property\s+(--\S+)/;
|
|
3362
3416
|
function parseTrussCss(cssText) {
|
|
3363
3417
|
const lines = cssText.split("\n");
|
|
3364
3418
|
const rules = [];
|
|
3365
3419
|
const properties = [];
|
|
3420
|
+
const arbitraryCssBlocks = [];
|
|
3366
3421
|
let i = 0;
|
|
3367
3422
|
while (i < lines.length) {
|
|
3368
3423
|
const line = lines[i].trim();
|
|
@@ -3391,19 +3446,43 @@ function parseTrussCss(cssText) {
|
|
|
3391
3446
|
i++;
|
|
3392
3447
|
continue;
|
|
3393
3448
|
}
|
|
3449
|
+
if (ARBITRARY_START_RE.test(line)) {
|
|
3450
|
+
i++;
|
|
3451
|
+
const blockLines = [];
|
|
3452
|
+
while (i < lines.length && !ARBITRARY_END_RE.test(lines[i].trim())) {
|
|
3453
|
+
blockLines.push(lines[i]);
|
|
3454
|
+
i++;
|
|
3455
|
+
}
|
|
3456
|
+
const blockText = blockLines.join("\n").trim();
|
|
3457
|
+
if (blockText.length > 0) {
|
|
3458
|
+
arbitraryCssBlocks.push({ cssText: blockText });
|
|
3459
|
+
}
|
|
3460
|
+
if (i < lines.length && ARBITRARY_END_RE.test(lines[i].trim())) {
|
|
3461
|
+
i++;
|
|
3462
|
+
}
|
|
3463
|
+
continue;
|
|
3464
|
+
}
|
|
3394
3465
|
i++;
|
|
3395
3466
|
}
|
|
3396
|
-
return { rules, properties };
|
|
3467
|
+
return { rules, properties, arbitraryCssBlocks };
|
|
3397
3468
|
}
|
|
3398
3469
|
function readTrussCss(filePath) {
|
|
3399
3470
|
const content = readFileSync(filePath, "utf8");
|
|
3400
3471
|
return parseTrussCss(content);
|
|
3401
3472
|
}
|
|
3473
|
+
function annotateArbitraryCssBlock(cssText) {
|
|
3474
|
+
const trimmed = cssText.trim();
|
|
3475
|
+
if (trimmed.length === 0) {
|
|
3476
|
+
return "";
|
|
3477
|
+
}
|
|
3478
|
+
return ["/* @truss arbitrary:start */", trimmed, "/* @truss arbitrary:end */"].join("\n");
|
|
3479
|
+
}
|
|
3402
3480
|
function mergeTrussCss(sources) {
|
|
3403
3481
|
const seenClasses = /* @__PURE__ */ new Set();
|
|
3404
3482
|
const allRules = [];
|
|
3405
3483
|
const seenProperties = /* @__PURE__ */ new Set();
|
|
3406
3484
|
const allProperties = [];
|
|
3485
|
+
const allArbitraryCssBlocks = [];
|
|
3407
3486
|
for (const source of sources) {
|
|
3408
3487
|
for (const rule of source.rules) {
|
|
3409
3488
|
if (!seenClasses.has(rule.className)) {
|
|
@@ -3417,6 +3496,7 @@ function mergeTrussCss(sources) {
|
|
|
3417
3496
|
allProperties.push(prop);
|
|
3418
3497
|
}
|
|
3419
3498
|
}
|
|
3499
|
+
allArbitraryCssBlocks.push(...source.arbitraryCssBlocks ?? []);
|
|
3420
3500
|
}
|
|
3421
3501
|
allRules.sort((a, b) => {
|
|
3422
3502
|
const diff = a.priority - b.priority;
|
|
@@ -3432,6 +3512,9 @@ function mergeTrussCss(sources) {
|
|
|
3432
3512
|
lines.push(`/* @truss @property */`);
|
|
3433
3513
|
lines.push(prop.cssText);
|
|
3434
3514
|
}
|
|
3515
|
+
for (const block of allArbitraryCssBlocks) {
|
|
3516
|
+
lines.push(annotateArbitraryCssBlock(block.cssText));
|
|
3517
|
+
}
|
|
3435
3518
|
return lines.join("\n");
|
|
3436
3519
|
}
|
|
3437
3520
|
|
|
@@ -3440,6 +3523,7 @@ import { readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
|
3440
3523
|
import { resolve, join } from "path";
|
|
3441
3524
|
function trussEsbuildPlugin(opts) {
|
|
3442
3525
|
const cssRegistry = /* @__PURE__ */ new Map();
|
|
3526
|
+
const arbitraryCssRegistry = /* @__PURE__ */ new Map();
|
|
3443
3527
|
let mapping = null;
|
|
3444
3528
|
let outDir;
|
|
3445
3529
|
return {
|
|
@@ -3448,6 +3532,18 @@ function trussEsbuildPlugin(opts) {
|
|
|
3448
3532
|
outDir = build.initialOptions.outdir ?? build.initialOptions.outdir;
|
|
3449
3533
|
build.onLoad({ filter: /\.[cm]?[jt]sx?$/ }, (args) => {
|
|
3450
3534
|
const code = readFileSync2(args.path, "utf8");
|
|
3535
|
+
if (args.path.endsWith(".css.ts")) {
|
|
3536
|
+
if (!mapping) {
|
|
3537
|
+
mapping = loadMapping(resolve(process.cwd(), opts.mapping));
|
|
3538
|
+
}
|
|
3539
|
+
const css = annotateArbitraryCssBlock(transformCssTs(code, args.path, mapping));
|
|
3540
|
+
if (css.length > 0) {
|
|
3541
|
+
arbitraryCssRegistry.set(args.path, css);
|
|
3542
|
+
} else {
|
|
3543
|
+
arbitraryCssRegistry.delete(args.path);
|
|
3544
|
+
}
|
|
3545
|
+
return { contents: code, loader: loaderForPath(args.path) };
|
|
3546
|
+
}
|
|
3451
3547
|
if (!code.includes("Css") && !code.includes("css=")) return void 0;
|
|
3452
3548
|
if (!mapping) {
|
|
3453
3549
|
mapping = loadMapping(resolve(process.cwd(), opts.mapping));
|
|
@@ -3464,8 +3560,11 @@ function trussEsbuildPlugin(opts) {
|
|
|
3464
3560
|
return { contents: result.code, loader: loaderForPath(args.path) };
|
|
3465
3561
|
});
|
|
3466
3562
|
build.onEnd(() => {
|
|
3467
|
-
if (cssRegistry.size === 0) return;
|
|
3468
|
-
const
|
|
3563
|
+
if (cssRegistry.size === 0 && arbitraryCssRegistry.size === 0) return;
|
|
3564
|
+
const cssParts = [generateCssText(cssRegistry), ...arbitraryCssRegistry.values()].filter(
|
|
3565
|
+
(part) => part.length > 0
|
|
3566
|
+
);
|
|
3567
|
+
const css = cssParts.join("\n");
|
|
3469
3568
|
const cssFileName = opts.outputCss ?? "truss.css";
|
|
3470
3569
|
const cssPath = resolve(outDir ?? join(process.cwd(), "dist"), cssFileName);
|
|
3471
3570
|
mkdirSync(resolve(cssPath, ".."), { recursive: true });
|
|
@@ -3565,7 +3664,7 @@ function trussPlugin(opts) {
|
|
|
3565
3664
|
},
|
|
3566
3665
|
transformIndexHtml(html) {
|
|
3567
3666
|
if (isBuild) {
|
|
3568
|
-
const stripped = html.replace(/\s*<link[^>]*href=["'][^"']*virtual:truss\.css["'][^>]
|
|
3667
|
+
const stripped = html.replace(/\s*<link[^>]*href=["'][^"']*virtual:truss\.css["'][^>]*\/?>/g, "").replace(/\s*<link[^>]*href=["'][^"']*__TRUSS_CSS_HASH__["'][^>]*\/?>/g, "").replace(/\s*<link[^>]*href=["'][^"']*\/assets\/truss-[0-9a-f]+\.css["'][^>]*\/?>/g, "");
|
|
3569
3668
|
const link = `<link rel="stylesheet" href="${TRUSS_CSS_PLACEHOLDER}">`;
|
|
3570
3669
|
return stripped.replace("</head>", ` ${link}
|
|
3571
3670
|
</head>`);
|