@homebound/truss 2.29.6 → 2.29.7
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.js +120 -55
- package/build/plugin/index.js.map +1 -1
- package/build/runtime.d.ts +26 -16
- package/build/runtime.js +215 -26
- package/build/runtime.js.map +1 -1
- package/package.json +1 -1
- package/tsconfig.tsbuildinfo +1 -1
package/build/plugin/index.js
CHANGED
|
@@ -1874,6 +1874,55 @@ function flattenWhenObjectParts(resolved) {
|
|
|
1874
1874
|
return segments;
|
|
1875
1875
|
}
|
|
1876
1876
|
|
|
1877
|
+
// src/css-order.ts
|
|
1878
|
+
function ruleSortKey(priority, className, atRulePrelude2) {
|
|
1879
|
+
const widthInterval = atRulePrelude2 === void 0 ? null : parseWidthInterval(atRulePrelude2);
|
|
1880
|
+
return { priority, className, widthInterval };
|
|
1881
|
+
}
|
|
1882
|
+
function compareRuleSortKeys(a, b) {
|
|
1883
|
+
return a.priority - b.priority || compareWidthIntervals(a.widthInterval, b.widthInterval) || compareClassNames(a.className, b.className);
|
|
1884
|
+
}
|
|
1885
|
+
function compareClassNames(a, b) {
|
|
1886
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
|
1887
|
+
}
|
|
1888
|
+
function atRulePrelude(cssText) {
|
|
1889
|
+
if (!cssText.startsWith("@")) return void 0;
|
|
1890
|
+
const brace = cssText.indexOf("{");
|
|
1891
|
+
return brace === -1 ? void 0 : cssText.slice(0, brace).trim();
|
|
1892
|
+
}
|
|
1893
|
+
function parseWidthInterval(prelude) {
|
|
1894
|
+
if (/,|\bnot\b|\bor\b|[<>]/.test(prelude)) return null;
|
|
1895
|
+
const terms = Array.from(prelude.matchAll(/\((min|max)-width:\s*([^)]*)\)/g));
|
|
1896
|
+
if (terms.length === 0) return null;
|
|
1897
|
+
let lo = 0;
|
|
1898
|
+
let hi = Infinity;
|
|
1899
|
+
for (const term of terms) {
|
|
1900
|
+
const px = parsePxLength(term[2]);
|
|
1901
|
+
if (px === null) return null;
|
|
1902
|
+
if (term[1] === "min") {
|
|
1903
|
+
lo = Math.max(lo, px);
|
|
1904
|
+
} else {
|
|
1905
|
+
hi = Math.min(hi, px);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
return { lo, hi };
|
|
1909
|
+
}
|
|
1910
|
+
function parsePxLength(value) {
|
|
1911
|
+
const match = value.trim().match(/^(\d+(?:\.\d+)?)(px)?$/);
|
|
1912
|
+
if (!match) return null;
|
|
1913
|
+
if (match[2] === void 0 && Number(match[1]) !== 0) return null;
|
|
1914
|
+
return Number(match[1]);
|
|
1915
|
+
}
|
|
1916
|
+
function compareWidthIntervals(a, b) {
|
|
1917
|
+
if (a === null || b === null) {
|
|
1918
|
+
return (a === null ? 1 : 0) - (b === null ? 1 : 0);
|
|
1919
|
+
}
|
|
1920
|
+
const widthA = a.hi - a.lo;
|
|
1921
|
+
const widthB = b.hi - b.lo;
|
|
1922
|
+
if (widthA !== widthB) return widthA > widthB ? -1 : 1;
|
|
1923
|
+
return a.lo - b.lo;
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1877
1926
|
// src/plugin/property-priorities.ts
|
|
1878
1927
|
var longHandPhysical = /* @__PURE__ */ new Set();
|
|
1879
1928
|
var longHandLogical = /* @__PURE__ */ new Set();
|
|
@@ -2428,13 +2477,6 @@ function computeRulePriority(rule) {
|
|
|
2428
2477
|
function isVariableRule(rule) {
|
|
2429
2478
|
return rule.declarations.some((d) => d.cssVarName !== void 0);
|
|
2430
2479
|
}
|
|
2431
|
-
function ruleSortKey(priority, className, atRulePrelude2) {
|
|
2432
|
-
const widthInterval = atRulePrelude2 === void 0 ? null : parseWidthInterval(atRulePrelude2);
|
|
2433
|
-
return { priority, className, widthInterval };
|
|
2434
|
-
}
|
|
2435
|
-
function compareRuleSortKeys(a, b) {
|
|
2436
|
-
return a.priority - b.priority || compareWidthIntervals(a.widthInterval, b.widthInterval) || compareClassNames(a.className, b.className);
|
|
2437
|
-
}
|
|
2438
2480
|
function sortRulesByPriority(rules) {
|
|
2439
2481
|
const decorated = Array.from(rules, (rule) => {
|
|
2440
2482
|
const priority = computeRulePriority(rule);
|
|
@@ -2443,41 +2485,6 @@ function sortRulesByPriority(rules) {
|
|
|
2443
2485
|
decorated.sort((a, b) => compareRuleSortKeys(a.key, b.key));
|
|
2444
2486
|
return decorated.map((d) => ({ rule: d.rule, priority: d.priority }));
|
|
2445
2487
|
}
|
|
2446
|
-
function compareClassNames(a, b) {
|
|
2447
|
-
return a < b ? -1 : a > b ? 1 : 0;
|
|
2448
|
-
}
|
|
2449
|
-
function parseWidthInterval(prelude) {
|
|
2450
|
-
if (/,|\bnot\b|\bor\b|[<>]/.test(prelude)) return null;
|
|
2451
|
-
const terms = Array.from(prelude.matchAll(/\((min|max)-width:\s*([^)]*)\)/g));
|
|
2452
|
-
if (terms.length === 0) return null;
|
|
2453
|
-
let lo = 0;
|
|
2454
|
-
let hi = Infinity;
|
|
2455
|
-
for (const term of terms) {
|
|
2456
|
-
const px = parsePxLength(term[2]);
|
|
2457
|
-
if (px === null) return null;
|
|
2458
|
-
if (term[1] === "min") {
|
|
2459
|
-
lo = Math.max(lo, px);
|
|
2460
|
-
} else {
|
|
2461
|
-
hi = Math.min(hi, px);
|
|
2462
|
-
}
|
|
2463
|
-
}
|
|
2464
|
-
return { lo, hi };
|
|
2465
|
-
}
|
|
2466
|
-
function parsePxLength(value) {
|
|
2467
|
-
const match = value.trim().match(/^(\d+(?:\.\d+)?)(px)?$/);
|
|
2468
|
-
if (!match) return null;
|
|
2469
|
-
if (match[2] === void 0 && Number(match[1]) !== 0) return null;
|
|
2470
|
-
return Number(match[1]);
|
|
2471
|
-
}
|
|
2472
|
-
function compareWidthIntervals(a, b) {
|
|
2473
|
-
if (a === null || b === null) {
|
|
2474
|
-
return (a === null ? 1 : 0) - (b === null ? 1 : 0);
|
|
2475
|
-
}
|
|
2476
|
-
const widthA = a.hi - a.lo;
|
|
2477
|
-
const widthB = b.hi - b.lo;
|
|
2478
|
-
if (widthA !== widthB) return widthA > widthB ? -1 : 1;
|
|
2479
|
-
return a.lo - b.lo;
|
|
2480
|
-
}
|
|
2481
2488
|
|
|
2482
2489
|
// src/plugin/emit-css.ts
|
|
2483
2490
|
function collectAtomicRules(chains, mapping) {
|
|
@@ -3429,6 +3436,8 @@ function findLastImportLine(lines) {
|
|
|
3429
3436
|
|
|
3430
3437
|
// src/plugin/merge-css.ts
|
|
3431
3438
|
import { readFileSync as readFileSync2 } from "fs";
|
|
3439
|
+
|
|
3440
|
+
// src/truss-css.ts
|
|
3432
3441
|
var RULE_ANNOTATION_RE = /^\/\* @truss p:([\d.]+) c:(\S+) \*\/$/;
|
|
3433
3442
|
var PROPERTY_ANNOTATION_RE = /^\/\* @truss @property \*\/$/;
|
|
3434
3443
|
var ARBITRARY_START_RE = /^\/\* @truss arbitrary:start \*\/$/;
|
|
@@ -3485,10 +3494,6 @@ function parseTrussCss(cssText) {
|
|
|
3485
3494
|
}
|
|
3486
3495
|
return { rules, properties, arbitraryCssBlocks };
|
|
3487
3496
|
}
|
|
3488
|
-
function readTrussCss(filePath) {
|
|
3489
|
-
const content = readFileSync2(filePath, "utf8");
|
|
3490
|
-
return parseTrussCss(content);
|
|
3491
|
-
}
|
|
3492
3497
|
function annotateArbitraryCssBlock(cssText) {
|
|
3493
3498
|
const trimmed = cssText.trim();
|
|
3494
3499
|
if (trimmed.length === 0) {
|
|
@@ -3496,6 +3501,12 @@ function annotateArbitraryCssBlock(cssText) {
|
|
|
3496
3501
|
}
|
|
3497
3502
|
return ["/* @truss arbitrary:start */", trimmed, "/* @truss arbitrary:end */"].join("\n");
|
|
3498
3503
|
}
|
|
3504
|
+
|
|
3505
|
+
// src/plugin/merge-css.ts
|
|
3506
|
+
function readTrussCss(filePath) {
|
|
3507
|
+
const content = readFileSync2(filePath, "utf8");
|
|
3508
|
+
return parseTrussCss(content);
|
|
3509
|
+
}
|
|
3499
3510
|
function mergeTrussCss(sources) {
|
|
3500
3511
|
const seenClasses = /* @__PURE__ */ new Set();
|
|
3501
3512
|
const allRules = [];
|
|
@@ -3535,11 +3546,6 @@ function mergeTrussCss(sources) {
|
|
|
3535
3546
|
}
|
|
3536
3547
|
return lines.join("\n");
|
|
3537
3548
|
}
|
|
3538
|
-
function atRulePrelude(cssText) {
|
|
3539
|
-
if (!cssText.startsWith("@")) return void 0;
|
|
3540
|
-
const brace = cssText.indexOf("{");
|
|
3541
|
-
return brace === -1 ? void 0 : cssText.slice(0, brace).trim();
|
|
3542
|
-
}
|
|
3543
3549
|
|
|
3544
3550
|
// src/plugin/transform-session.ts
|
|
3545
3551
|
function createTrussTransformSession(options) {
|
|
@@ -3569,6 +3575,7 @@ function createTrussTransformSession(options) {
|
|
|
3569
3575
|
libraryCache = null;
|
|
3570
3576
|
}
|
|
3571
3577
|
function updateArbitraryCssRegistry(sourcePath, sourceCode) {
|
|
3578
|
+
sourcePath = resolve2(sourcePath).replace(/\\/g, "/");
|
|
3572
3579
|
const css = transformCssTs(sourceCode, sourcePath, ensureMapping()).trim();
|
|
3573
3580
|
if (css.length > 0) {
|
|
3574
3581
|
const prev = arbitraryCssRegistry.get(sourcePath);
|
|
@@ -3598,7 +3605,7 @@ function createTrussTransformSession(options) {
|
|
|
3598
3605
|
function collectCss() {
|
|
3599
3606
|
const mapping2 = ensureMapping();
|
|
3600
3607
|
const appCssParts = [generateCssText(cssRegistry)];
|
|
3601
|
-
const allArbitrary = Array.from(arbitraryCssRegistry.
|
|
3608
|
+
const allArbitrary = Array.from(arbitraryCssRegistry.entries()).sort((a, b) => compareClassNames(a[0], b[0])).map((entry) => entry[1]).join("\n\n");
|
|
3602
3609
|
appCssParts.push(annotateArbitraryCssBlock(allArbitrary));
|
|
3603
3610
|
const appCss = appCssParts.filter((part) => part.length > 0).join("\n");
|
|
3604
3611
|
const libs = loadLibraries();
|
|
@@ -3610,8 +3617,16 @@ ${body}`;
|
|
|
3610
3617
|
function hasCss() {
|
|
3611
3618
|
return cssRegistry.size > 0 || arbitraryCssRegistry.size > 0 || libraryPaths.length > 0;
|
|
3612
3619
|
}
|
|
3620
|
+
function collectTestCss() {
|
|
3621
|
+
return mergeTrussCss(loadLibraries());
|
|
3622
|
+
}
|
|
3623
|
+
function getArbitraryCss(sourcePath) {
|
|
3624
|
+
return arbitraryCssRegistry.get(resolve2(sourcePath).replace(/\\/g, "/")) ?? "";
|
|
3625
|
+
}
|
|
3613
3626
|
return {
|
|
3614
3627
|
collectCss,
|
|
3628
|
+
collectTestCss,
|
|
3629
|
+
getArbitraryCss,
|
|
3615
3630
|
ensureMapping,
|
|
3616
3631
|
hasCss,
|
|
3617
3632
|
reset,
|
|
@@ -3620,6 +3635,9 @@ ${body}`;
|
|
|
3620
3635
|
};
|
|
3621
3636
|
}
|
|
3622
3637
|
|
|
3638
|
+
// src/plugin/index.ts
|
|
3639
|
+
import * as t16 from "@babel/types";
|
|
3640
|
+
|
|
3623
3641
|
// src/plugin/esbuild-plugin.ts
|
|
3624
3642
|
import { readFileSync as readFileSync3, writeFileSync, mkdirSync } from "fs";
|
|
3625
3643
|
import { resolve as resolve3, join } from "path";
|
|
@@ -3667,6 +3685,7 @@ function loaderForPath(filePath) {
|
|
|
3667
3685
|
|
|
3668
3686
|
// src/plugin/index.ts
|
|
3669
3687
|
var VIRTUAL_CSS_PREFIX = "\0truss-css:";
|
|
3688
|
+
var VIRTUAL_TEST_CSS_PREFIX = "\0truss-test-css:";
|
|
3670
3689
|
var CSS_TS_QUERY = "?truss-css";
|
|
3671
3690
|
var TRUSS_CSS_PLACEHOLDER = "__TRUSS_CSS_HASH__";
|
|
3672
3691
|
var VIRTUAL_CSS_ENDPOINT = "/virtual:truss.css";
|
|
@@ -3756,6 +3775,7 @@ function trussPlugin(opts) {
|
|
|
3756
3775
|
if (!source.endsWith(CSS_TS_QUERY)) return null;
|
|
3757
3776
|
const absolutePath = resolveImportPath(source.slice(0, -CSS_TS_QUERY.length), importer, projectRoot);
|
|
3758
3777
|
if (!existsSync2(absolutePath)) return null;
|
|
3778
|
+
if (isTest) return VIRTUAL_TEST_CSS_PREFIX + absolutePath;
|
|
3759
3779
|
return VIRTUAL_CSS_PREFIX + absolutePath.slice(0, -3);
|
|
3760
3780
|
},
|
|
3761
3781
|
load(id) {
|
|
@@ -3789,11 +3809,27 @@ function trussPlugin(opts) {
|
|
|
3789
3809
|
`;
|
|
3790
3810
|
}
|
|
3791
3811
|
if (id === RESOLVED_VIRTUAL_TEST_CSS_ID) {
|
|
3792
|
-
const css = session.
|
|
3812
|
+
const css = session.collectTestCss();
|
|
3813
|
+
const options = {
|
|
3814
|
+
source: "libraries",
|
|
3815
|
+
order: 0,
|
|
3816
|
+
prelude: rootSpacingPreludeCss(session.ensureMapping().increment)
|
|
3817
|
+
};
|
|
3793
3818
|
return `
|
|
3794
3819
|
import { __injectTrussCSS } from "@homebound/truss/runtime";
|
|
3795
3820
|
|
|
3796
|
-
__injectTrussCSS(${JSON.stringify(css)});
|
|
3821
|
+
__injectTrussCSS(${JSON.stringify(css)}, ${JSON.stringify(options)});
|
|
3822
|
+
`;
|
|
3823
|
+
}
|
|
3824
|
+
if (id.startsWith(VIRTUAL_TEST_CSS_PREFIX)) {
|
|
3825
|
+
const sourcePath2 = resolve4(id.slice(VIRTUAL_TEST_CSS_PREFIX.length)).replace(/\\/g, "/");
|
|
3826
|
+
session.updateArbitraryCssRegistry(sourcePath2, readFileSync4(sourcePath2, "utf8"));
|
|
3827
|
+
const css = annotateArbitraryCssBlock(session.getArbitraryCss(sourcePath2));
|
|
3828
|
+
return `
|
|
3829
|
+
import "${VIRTUAL_TEST_CSS_ID}";
|
|
3830
|
+
import { __injectTrussCSS } from "@homebound/truss/runtime";
|
|
3831
|
+
|
|
3832
|
+
__injectTrussCSS(${JSON.stringify(css)}, ${JSON.stringify({ source: sourcePath2 })});
|
|
3797
3833
|
`;
|
|
3798
3834
|
}
|
|
3799
3835
|
if (!id.startsWith(VIRTUAL_CSS_PREFIX)) return null;
|
|
@@ -3803,16 +3839,45 @@ __injectTrussCSS(${JSON.stringify(css)});
|
|
|
3803
3839
|
return `/* [truss] ${sourcePath} \u2014 included via truss.css */`;
|
|
3804
3840
|
},
|
|
3805
3841
|
transform(code, id) {
|
|
3842
|
+
if (id.startsWith(VIRTUAL_TEST_CSS_PREFIX)) return null;
|
|
3806
3843
|
if (!/\.[cm]?[jt]sx?(\?|$)/.test(id)) return null;
|
|
3807
3844
|
const fileId = stripQueryAndHash(id);
|
|
3808
3845
|
if (isNodeModulesFile(fileId)) return null;
|
|
3809
3846
|
const rewrittenImports = rewriteCssTsImports(code, id);
|
|
3810
|
-
const shouldBootstrapTestCss = isTest
|
|
3847
|
+
const shouldBootstrapTestCss = isTest;
|
|
3811
3848
|
const transformedCode = shouldBootstrapTestCss ? `${rewrittenImports.code}
|
|
3812
3849
|
import "${VIRTUAL_TEST_CSS_ID}";` : rewrittenImports.code;
|
|
3813
3850
|
const importsOnlyResult = rewrittenImports.changed || shouldBootstrapTestCss ? { code: transformedCode, map: null } : null;
|
|
3814
3851
|
if (fileId.endsWith(".css.ts")) {
|
|
3815
3852
|
session.updateArbitraryCssRegistry(fileId, code);
|
|
3853
|
+
if (isTest) {
|
|
3854
|
+
const css = annotateArbitraryCssBlock(session.getArbitraryCss(fileId));
|
|
3855
|
+
const ast = parseModule(transformedCode, fileId);
|
|
3856
|
+
traverse(ast, {
|
|
3857
|
+
Program(path) {
|
|
3858
|
+
const inject = path.scope.generateUidIdentifier("injectTrussCSS");
|
|
3859
|
+
path.unshiftContainer(
|
|
3860
|
+
"body",
|
|
3861
|
+
t16.importDeclaration(
|
|
3862
|
+
[t16.importSpecifier(inject, t16.identifier("__injectTrussCSS"))],
|
|
3863
|
+
t16.stringLiteral("@homebound/truss/runtime")
|
|
3864
|
+
)
|
|
3865
|
+
);
|
|
3866
|
+
path.pushContainer(
|
|
3867
|
+
"body",
|
|
3868
|
+
t16.expressionStatement(
|
|
3869
|
+
t16.callExpression(inject, [
|
|
3870
|
+
t16.stringLiteral(css),
|
|
3871
|
+
t16.objectExpression([
|
|
3872
|
+
t16.objectProperty(t16.identifier("source"), t16.stringLiteral(resolve4(fileId).replace(/\\/g, "/")))
|
|
3873
|
+
])
|
|
3874
|
+
])
|
|
3875
|
+
)
|
|
3876
|
+
);
|
|
3877
|
+
}
|
|
3878
|
+
});
|
|
3879
|
+
return { code: generate(ast, { sourceFileName: fileId }).code, map: null };
|
|
3880
|
+
}
|
|
3816
3881
|
return importsOnlyResult;
|
|
3817
3882
|
}
|
|
3818
3883
|
const hasCssDsl = rewrittenImports.code.includes("Css") || rewrittenImports.code.includes("css=");
|