@homebound/truss 2.15.0 → 2.15.1

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.
@@ -41,7 +41,8 @@ interface TrussEsbuildPluginOptions {
41
41
  outputCss?: string;
42
42
  }
43
43
  /**
44
- * esbuild plugin that transforms `Css.*.$` expressions and emits a `truss.css` file.
44
+ * esbuild plugin that transforms `Css.*.$` expressions, collects `.css.ts` blocks,
45
+ * and emits a `truss.css` file.
45
46
  *
46
47
  * Designed for library builds using tsup/esbuild. Transforms source files
47
48
  * during the build and writes an annotated `truss.css` alongside the output
@@ -3358,11 +3358,14 @@ function toVirtualCssSpecifier(source) {
3358
3358
  import { readFileSync } from "fs";
3359
3359
  var RULE_ANNOTATION_RE = /^\/\* @truss p:([\d.]+) c:(\S+) \*\/$/;
3360
3360
  var PROPERTY_ANNOTATION_RE = /^\/\* @truss @property \*\/$/;
3361
+ var ARBITRARY_START_RE = /^\/\* @truss arbitrary:start \*\/$/;
3362
+ var ARBITRARY_END_RE = /^\/\* @truss arbitrary:end \*\/$/;
3361
3363
  var PROPERTY_VAR_RE = /^@property\s+(--\S+)/;
3362
3364
  function parseTrussCss(cssText) {
3363
3365
  const lines = cssText.split("\n");
3364
3366
  const rules = [];
3365
3367
  const properties = [];
3368
+ const arbitraryCssBlocks = [];
3366
3369
  let i = 0;
3367
3370
  while (i < lines.length) {
3368
3371
  const line = lines[i].trim();
@@ -3391,19 +3394,43 @@ function parseTrussCss(cssText) {
3391
3394
  i++;
3392
3395
  continue;
3393
3396
  }
3397
+ if (ARBITRARY_START_RE.test(line)) {
3398
+ i++;
3399
+ const blockLines = [];
3400
+ while (i < lines.length && !ARBITRARY_END_RE.test(lines[i].trim())) {
3401
+ blockLines.push(lines[i]);
3402
+ i++;
3403
+ }
3404
+ const blockText = blockLines.join("\n").trim();
3405
+ if (blockText.length > 0) {
3406
+ arbitraryCssBlocks.push({ cssText: blockText });
3407
+ }
3408
+ if (i < lines.length && ARBITRARY_END_RE.test(lines[i].trim())) {
3409
+ i++;
3410
+ }
3411
+ continue;
3412
+ }
3394
3413
  i++;
3395
3414
  }
3396
- return { rules, properties };
3415
+ return { rules, properties, arbitraryCssBlocks };
3397
3416
  }
3398
3417
  function readTrussCss(filePath) {
3399
3418
  const content = readFileSync(filePath, "utf8");
3400
3419
  return parseTrussCss(content);
3401
3420
  }
3421
+ function annotateArbitraryCssBlock(cssText) {
3422
+ const trimmed = cssText.trim();
3423
+ if (trimmed.length === 0) {
3424
+ return "";
3425
+ }
3426
+ return ["/* @truss arbitrary:start */", trimmed, "/* @truss arbitrary:end */"].join("\n");
3427
+ }
3402
3428
  function mergeTrussCss(sources) {
3403
3429
  const seenClasses = /* @__PURE__ */ new Set();
3404
3430
  const allRules = [];
3405
3431
  const seenProperties = /* @__PURE__ */ new Set();
3406
3432
  const allProperties = [];
3433
+ const allArbitraryCssBlocks = [];
3407
3434
  for (const source of sources) {
3408
3435
  for (const rule of source.rules) {
3409
3436
  if (!seenClasses.has(rule.className)) {
@@ -3417,6 +3444,7 @@ function mergeTrussCss(sources) {
3417
3444
  allProperties.push(prop);
3418
3445
  }
3419
3446
  }
3447
+ allArbitraryCssBlocks.push(...source.arbitraryCssBlocks ?? []);
3420
3448
  }
3421
3449
  allRules.sort((a, b) => {
3422
3450
  const diff = a.priority - b.priority;
@@ -3432,6 +3460,9 @@ function mergeTrussCss(sources) {
3432
3460
  lines.push(`/* @truss @property */`);
3433
3461
  lines.push(prop.cssText);
3434
3462
  }
3463
+ for (const block of allArbitraryCssBlocks) {
3464
+ lines.push(annotateArbitraryCssBlock(block.cssText));
3465
+ }
3435
3466
  return lines.join("\n");
3436
3467
  }
3437
3468
 
@@ -3440,6 +3471,7 @@ import { readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
3440
3471
  import { resolve, join } from "path";
3441
3472
  function trussEsbuildPlugin(opts) {
3442
3473
  const cssRegistry = /* @__PURE__ */ new Map();
3474
+ const arbitraryCssRegistry = /* @__PURE__ */ new Map();
3443
3475
  let mapping = null;
3444
3476
  let outDir;
3445
3477
  return {
@@ -3448,6 +3480,18 @@ function trussEsbuildPlugin(opts) {
3448
3480
  outDir = build.initialOptions.outdir ?? build.initialOptions.outdir;
3449
3481
  build.onLoad({ filter: /\.[cm]?[jt]sx?$/ }, (args) => {
3450
3482
  const code = readFileSync2(args.path, "utf8");
3483
+ if (args.path.endsWith(".css.ts")) {
3484
+ if (!mapping) {
3485
+ mapping = loadMapping(resolve(process.cwd(), opts.mapping));
3486
+ }
3487
+ const css = annotateArbitraryCssBlock(transformCssTs(code, args.path, mapping));
3488
+ if (css.length > 0) {
3489
+ arbitraryCssRegistry.set(args.path, css);
3490
+ } else {
3491
+ arbitraryCssRegistry.delete(args.path);
3492
+ }
3493
+ return { contents: code, loader: loaderForPath(args.path) };
3494
+ }
3451
3495
  if (!code.includes("Css") && !code.includes("css=")) return void 0;
3452
3496
  if (!mapping) {
3453
3497
  mapping = loadMapping(resolve(process.cwd(), opts.mapping));
@@ -3464,8 +3508,11 @@ function trussEsbuildPlugin(opts) {
3464
3508
  return { contents: result.code, loader: loaderForPath(args.path) };
3465
3509
  });
3466
3510
  build.onEnd(() => {
3467
- if (cssRegistry.size === 0) return;
3468
- const css = generateCssText(cssRegistry);
3511
+ if (cssRegistry.size === 0 && arbitraryCssRegistry.size === 0) return;
3512
+ const cssParts = [generateCssText(cssRegistry), ...arbitraryCssRegistry.values()].filter(
3513
+ (part) => part.length > 0
3514
+ );
3515
+ const css = cssParts.join("\n");
3469
3516
  const cssFileName = opts.outputCss ?? "truss.css";
3470
3517
  const cssPath = resolve(outDir ?? join(process.cwd(), "dist"), cssFileName);
3471
3518
  mkdirSync(resolve(cssPath, ".."), { recursive: true });
@@ -3565,7 +3612,7 @@ function trussPlugin(opts) {
3565
3612
  },
3566
3613
  transformIndexHtml(html) {
3567
3614
  if (isBuild) {
3568
- const stripped = html.replace(/\s*<link[^>]*href=["'][^"']*virtual:truss\.css["'][^>]*\/?>/, "");
3615
+ 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
3616
  const link = `<link rel="stylesheet" href="${TRUSS_CSS_PLACEHOLDER}">`;
3570
3617
  return stripped.replace("</head>", ` ${link}
3571
3618
  </head>`);