@homebound/truss 2.0.13 → 2.1.0-next.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/index.js +85 -33
- package/build/index.js.map +1 -1
- package/build/plugin/index.d.ts +11 -10
- package/build/plugin/index.js +1107 -1004
- package/build/plugin/index.js.map +1 -1
- package/build/runtime.d.ts +20 -10
- package/build/runtime.js +57 -41
- package/build/runtime.js.map +1 -1
- package/cli.js +5 -10
- package/package.json +7 -3
package/build/runtime.d.ts
CHANGED
|
@@ -1,18 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
/** A compact source label for a Truss CSS expression, used in debug mode. */
|
|
3
2
|
declare class TrussDebugInfo {
|
|
4
|
-
/**
|
|
3
|
+
/** I.e. `"FileName.tsx:line"` */
|
|
5
4
|
readonly src: string;
|
|
6
5
|
constructor(src: string);
|
|
7
6
|
}
|
|
8
|
-
/** Call StyleX while stripping Truss debug sentinels from the style list. */
|
|
9
|
-
declare function trussProps(stylexNs: typeof stylex, ...styles: unknown[]): Record<string, unknown>;
|
|
10
|
-
declare function mergeProps(stylexNs: typeof stylex, explicitClassName: string, ...styles: unknown[]): Record<string, unknown>;
|
|
11
7
|
/**
|
|
12
|
-
*
|
|
8
|
+
* Space-separated atomic class names, or a variable tuple with class names + CSS variable map.
|
|
9
|
+
*
|
|
10
|
+
* In debug mode, the transform appends a TrussDebugInfo as an extra tuple element:
|
|
11
|
+
* - static with debug: `[classNames, debugInfo]`
|
|
12
|
+
* - variable with debug: `[classNames, vars, debugInfo]`
|
|
13
|
+
*/
|
|
14
|
+
type TrussStyleValue = string | [classNames: string, vars: Record<string, string>] | [classNames: string, debugInfo: TrussDebugInfo] | [classNames: string, vars: Record<string, string>, debugInfo: TrussDebugInfo];
|
|
15
|
+
/** A property-keyed style hash where each key owns one logical CSS property. */
|
|
16
|
+
type TrussStyleHash = Record<string, TrussStyleValue>;
|
|
17
|
+
/** Merge one or more Truss style hashes into `{ className, style?, data-truss-src? }`. */
|
|
18
|
+
declare function trussProps(...hashes: ReadonlyArray<TrussStyleHash | false | null | undefined>): Record<string, unknown>;
|
|
19
|
+
/** Merge explicit className/style with Truss style hashes. */
|
|
20
|
+
declare function mergeProps(explicitClassName: string | undefined, explicitStyle: Record<string, unknown> | undefined, ...hashes: ReadonlyArray<TrussStyleHash | false | null | undefined>): Record<string, unknown>;
|
|
21
|
+
/**
|
|
22
|
+
* Inject CSS text into the document for jsdom/test environments.
|
|
13
23
|
*
|
|
14
|
-
*
|
|
24
|
+
* In browser dev mode, CSS is served via the Vite virtual endpoint instead.
|
|
15
25
|
*/
|
|
16
|
-
declare function
|
|
26
|
+
declare function __injectTrussCSS(cssText: string): void;
|
|
17
27
|
|
|
18
|
-
export { TrussDebugInfo,
|
|
28
|
+
export { TrussDebugInfo, type TrussStyleHash, type TrussStyleValue, __injectTrussCSS, mergeProps, trussProps };
|
package/build/runtime.js
CHANGED
|
@@ -1,60 +1,76 @@
|
|
|
1
1
|
// src/runtime.ts
|
|
2
2
|
var TrussDebugInfo = class {
|
|
3
|
-
/**
|
|
3
|
+
/** I.e. `"FileName.tsx:line"` */
|
|
4
4
|
src;
|
|
5
5
|
constructor(src) {
|
|
6
6
|
this.src = src;
|
|
7
7
|
}
|
|
8
8
|
};
|
|
9
|
-
function trussProps(
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
9
|
+
function trussProps(...hashes) {
|
|
10
|
+
const merged = {};
|
|
11
|
+
for (const hash of hashes) {
|
|
12
|
+
if (!hash || typeof hash !== "object") continue;
|
|
13
|
+
Object.assign(merged, hash);
|
|
14
|
+
}
|
|
15
|
+
const classNames = [];
|
|
16
|
+
const inlineStyle = {};
|
|
17
|
+
const debugSources = [];
|
|
18
|
+
for (const [key, value] of Object.entries(merged)) {
|
|
19
|
+
if (key === "__marker") {
|
|
20
|
+
if (typeof value === "string") classNames.push(value);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
if (typeof value === "string") {
|
|
24
|
+
classNames.push(value);
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
27
|
+
classNames.push(value[0]);
|
|
28
|
+
for (let i = 1; i < value.length; i++) {
|
|
29
|
+
const el = value[i];
|
|
30
|
+
if (el instanceof TrussDebugInfo) {
|
|
31
|
+
debugSources.push(el.src);
|
|
32
|
+
} else if (typeof el === "object" && el !== null) {
|
|
33
|
+
Object.assign(inlineStyle, el);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const props = {
|
|
38
|
+
className: classNames.join(" ")
|
|
20
39
|
};
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (Array.isArray(styles)) {
|
|
24
|
-
return styles;
|
|
40
|
+
if (Object.keys(inlineStyle).length > 0) {
|
|
41
|
+
props.style = inlineStyle;
|
|
25
42
|
}
|
|
26
|
-
if (
|
|
27
|
-
|
|
28
|
-
"[truss] asStyleArray received a non-empty object \u2014 this likely means a style value was not rewritten to an array. Use a style array (e.g. Css.df.$) or an empty array [] instead of {}."
|
|
29
|
-
);
|
|
43
|
+
if (debugSources.length > 0) {
|
|
44
|
+
props["data-truss-src"] = [...new Set(debugSources)].join("; ");
|
|
30
45
|
}
|
|
31
|
-
return
|
|
46
|
+
return props;
|
|
32
47
|
}
|
|
33
|
-
function
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
styleArgs.push(style);
|
|
41
|
-
}
|
|
48
|
+
function mergeProps(explicitClassName, explicitStyle, ...hashes) {
|
|
49
|
+
const result = trussProps(...hashes);
|
|
50
|
+
if (explicitClassName) {
|
|
51
|
+
result.className = `${explicitClassName} ${result.className ?? ""}`.trim();
|
|
52
|
+
}
|
|
53
|
+
if (explicitStyle) {
|
|
54
|
+
result.style = { ...explicitStyle, ...result.style };
|
|
42
55
|
}
|
|
43
|
-
return
|
|
56
|
+
return result;
|
|
44
57
|
}
|
|
45
|
-
function
|
|
46
|
-
if (
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
}
|
|
58
|
+
function __injectTrussCSS(cssText) {
|
|
59
|
+
if (typeof document === "undefined") return;
|
|
60
|
+
const id = "data-truss";
|
|
61
|
+
let style = document.querySelector(`style[${id}]`);
|
|
62
|
+
if (!style) {
|
|
63
|
+
style = document.createElement("style");
|
|
64
|
+
style.setAttribute(id, "");
|
|
65
|
+
document.head.appendChild(style);
|
|
66
|
+
}
|
|
67
|
+
if (!style.textContent?.includes(cssText)) {
|
|
68
|
+
style.textContent = (style.textContent ?? "") + cssText;
|
|
69
|
+
}
|
|
54
70
|
}
|
|
55
71
|
export {
|
|
56
72
|
TrussDebugInfo,
|
|
57
|
-
|
|
73
|
+
__injectTrussCSS,
|
|
58
74
|
mergeProps,
|
|
59
75
|
trussProps
|
|
60
76
|
};
|
package/build/runtime.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["
|
|
1
|
+
{"version":3,"sources":["../src/runtime.ts"],"sourcesContent":["/** A compact source label for a Truss CSS expression, used in debug mode. */\nexport class TrussDebugInfo {\n /** I.e. `\"FileName.tsx:line\"` */\n readonly src: string;\n\n constructor(src: string) {\n this.src = src;\n }\n}\n\n/**\n * Space-separated atomic class names, or a variable tuple with class names + CSS variable map.\n *\n * In debug mode, the transform appends a TrussDebugInfo as an extra tuple element:\n * - static with debug: `[classNames, debugInfo]`\n * - variable with debug: `[classNames, vars, debugInfo]`\n */\nexport type TrussStyleValue =\n | string\n | [classNames: string, vars: Record<string, string>]\n | [classNames: string, debugInfo: TrussDebugInfo]\n | [classNames: string, vars: Record<string, string>, debugInfo: TrussDebugInfo];\n\n/** A property-keyed style hash where each key owns one logical CSS property. */\nexport type TrussStyleHash = Record<string, TrussStyleValue>;\n\n/** Merge one or more Truss style hashes into `{ className, style?, data-truss-src? }`. */\nexport function trussProps(\n ...hashes: ReadonlyArray<TrussStyleHash | false | null | undefined>\n): Record<string, unknown> {\n const merged: Record<string, TrussStyleValue> = {};\n\n for (const hash of hashes) {\n if (!hash || typeof hash !== \"object\") continue;\n Object.assign(merged, hash);\n }\n\n const classNames: string[] = [];\n const inlineStyle: Record<string, string> = {};\n const debugSources: string[] = [];\n\n for (const [key, value] of Object.entries(merged)) {\n // __marker is a special key — its value is a marker class name, not a CSS property\n if (key === \"__marker\") {\n if (typeof value === \"string\") classNames.push(value);\n continue;\n }\n if (typeof value === \"string\") {\n // I.e. \"df\" or \"black blue_h\"\n classNames.push(value);\n continue;\n }\n\n // Tuple: [classNames, varsOrDebug?, maybeDebug?]\n classNames.push(value[0]);\n\n for (let i = 1; i < value.length; i++) {\n const el = value[i];\n if (el instanceof TrussDebugInfo) {\n debugSources.push(el.src);\n } else if (typeof el === \"object\" && el !== null) {\n Object.assign(inlineStyle, el);\n }\n }\n }\n\n const props: Record<string, unknown> = {\n className: classNames.join(\" \"),\n };\n\n if (Object.keys(inlineStyle).length > 0) {\n props.style = inlineStyle;\n }\n\n if (debugSources.length > 0) {\n props[\"data-truss-src\"] = [...new Set(debugSources)].join(\"; \");\n }\n\n return props;\n}\n\n/** Merge explicit className/style with Truss style hashes. */\nexport function mergeProps(\n explicitClassName: string | undefined,\n explicitStyle: Record<string, unknown> | undefined,\n ...hashes: ReadonlyArray<TrussStyleHash | false | null | undefined>\n): Record<string, unknown> {\n const result = trussProps(...hashes);\n\n if (explicitClassName) {\n result.className = `${explicitClassName} ${result.className ?? \"\"}`.trim();\n }\n\n if (explicitStyle) {\n result.style = { ...explicitStyle, ...(result.style as Record<string, unknown> | undefined) };\n }\n\n return result;\n}\n\n/**\n * Inject CSS text into the document for jsdom/test environments.\n *\n * In browser dev mode, CSS is served via the Vite virtual endpoint instead.\n */\nexport function __injectTrussCSS(cssText: string): void {\n if (typeof document === \"undefined\") return;\n\n const id = \"data-truss\";\n let style = document.querySelector(`style[${id}]`) as HTMLStyleElement | null;\n if (!style) {\n style = document.createElement(\"style\");\n style.setAttribute(id, \"\");\n document.head.appendChild(style);\n }\n\n // Append if not already present (dedupe across HMR re-executions)\n if (!style.textContent?.includes(cssText)) {\n style.textContent = (style.textContent ?? \"\") + cssText;\n }\n}\n"],"mappings":";AACO,IAAM,iBAAN,MAAqB;AAAA;AAAA,EAEjB;AAAA,EAET,YAAY,KAAa;AACvB,SAAK,MAAM;AAAA,EACb;AACF;AAmBO,SAAS,cACX,QACsB;AACzB,QAAM,SAA0C,CAAC;AAEjD,aAAW,QAAQ,QAAQ;AACzB,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU;AACvC,WAAO,OAAO,QAAQ,IAAI;AAAA,EAC5B;AAEA,QAAM,aAAuB,CAAC;AAC9B,QAAM,cAAsC,CAAC;AAC7C,QAAM,eAAyB,CAAC;AAEhC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAM,GAAG;AAEjD,QAAI,QAAQ,YAAY;AACtB,UAAI,OAAO,UAAU,SAAU,YAAW,KAAK,KAAK;AACpD;AAAA,IACF;AACA,QAAI,OAAO,UAAU,UAAU;AAE7B,iBAAW,KAAK,KAAK;AACrB;AAAA,IACF;AAGA,eAAW,KAAK,MAAM,CAAC,CAAC;AAExB,aAAS,IAAI,GAAG,IAAI,MAAM,QAAQ,KAAK;AACrC,YAAM,KAAK,MAAM,CAAC;AAClB,UAAI,cAAc,gBAAgB;AAChC,qBAAa,KAAK,GAAG,GAAG;AAAA,MAC1B,WAAW,OAAO,OAAO,YAAY,OAAO,MAAM;AAChD,eAAO,OAAO,aAAa,EAAE;AAAA,MAC/B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,QAAiC;AAAA,IACrC,WAAW,WAAW,KAAK,GAAG;AAAA,EAChC;AAEA,MAAI,OAAO,KAAK,WAAW,EAAE,SAAS,GAAG;AACvC,UAAM,QAAQ;AAAA,EAChB;AAEA,MAAI,aAAa,SAAS,GAAG;AAC3B,UAAM,gBAAgB,IAAI,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC,EAAE,KAAK,IAAI;AAAA,EAChE;AAEA,SAAO;AACT;AAGO,SAAS,WACd,mBACA,kBACG,QACsB;AACzB,QAAM,SAAS,WAAW,GAAG,MAAM;AAEnC,MAAI,mBAAmB;AACrB,WAAO,YAAY,GAAG,iBAAiB,IAAI,OAAO,aAAa,EAAE,GAAG,KAAK;AAAA,EAC3E;AAEA,MAAI,eAAe;AACjB,WAAO,QAAQ,EAAE,GAAG,eAAe,GAAI,OAAO,MAA8C;AAAA,EAC9F;AAEA,SAAO;AACT;AAOO,SAAS,iBAAiB,SAAuB;AACtD,MAAI,OAAO,aAAa,YAAa;AAErC,QAAM,KAAK;AACX,MAAI,QAAQ,SAAS,cAAc,SAAS,EAAE,GAAG;AACjD,MAAI,CAAC,OAAO;AACV,YAAQ,SAAS,cAAc,OAAO;AACtC,UAAM,aAAa,IAAI,EAAE;AACzB,aAAS,KAAK,YAAY,KAAK;AAAA,EACjC;AAGA,MAAI,CAAC,MAAM,aAAa,SAAS,OAAO,GAAG;AACzC,UAAM,eAAe,MAAM,eAAe,MAAM;AAAA,EAClD;AACF;","names":[]}
|
package/cli.js
CHANGED
|
@@ -1,16 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { register } from "tsx/esm/api";
|
|
6
|
-
import { generate } from "./build/index.js";
|
|
7
|
-
|
|
8
|
-
// Register tsx loader so we can import TypeScript config files
|
|
9
|
-
// (handles both CJS and ESM projects, with extensionless .ts imports).
|
|
10
|
-
const unregister = register();
|
|
3
|
+
import { createJiti } from "jiti";
|
|
4
|
+
import { join } from "path";
|
|
11
5
|
|
|
12
6
|
const filename = process.argv[2] ?? "./truss-config.ts";
|
|
13
7
|
const configPath = join(process.cwd(), filename);
|
|
8
|
+
const jiti = createJiti(import.meta.url, { interopDefault: true });
|
|
14
9
|
|
|
15
10
|
main().catch((err) => {
|
|
16
11
|
console.error(err);
|
|
@@ -18,8 +13,8 @@ main().catch((err) => {
|
|
|
18
13
|
});
|
|
19
14
|
|
|
20
15
|
async function main() {
|
|
21
|
-
const config =
|
|
22
|
-
|
|
16
|
+
const config = await jiti.import(configPath, { default: true });
|
|
17
|
+
const { generate } = await import("./build/index.js");
|
|
23
18
|
await generate(config);
|
|
24
19
|
console.log(`Generated ${config.outputPath}`);
|
|
25
20
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@homebound/truss",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.1.0-next.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"bin": "cli.js",
|
|
@@ -27,10 +27,14 @@
|
|
|
27
27
|
},
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"dependencies": {
|
|
30
|
+
"@babel/generator": "^7.29.0",
|
|
31
|
+
"@babel/parser": "^7.29.0",
|
|
32
|
+
"@babel/traverse": "^7.29.0",
|
|
33
|
+
"@babel/types": "^7.29.0",
|
|
30
34
|
"change-case": "^5.4.4",
|
|
31
35
|
"csstype": "^3.2.3",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
36
|
+
"jiti": "^2.6.1",
|
|
37
|
+
"ts-poet": "^6.12.0"
|
|
34
38
|
},
|
|
35
39
|
"devDependencies": {
|
|
36
40
|
"@homebound/tsconfig": "^1.1.1",
|