Files
openclaw/scripts/run-lint.mts
Peter Steinberger 9ccbbf83f2 perf(control-ui): load built-in theme palettes on demand (#130473)
* perf(control-ui): load built-in theme palettes on demand

Every built-in theme's tokens shipped in the startup stylesheet, so the default
path downloaded six palettes it never painted and each new theme taxed everyone.
That is what pushed the startup CSS ceiling from 45 to 47 KiB when Tide, Beacon,
and Phosphor landed.

Moves the twelve non-default palettes into public/themes/<family>.css, one file
per family covering both modes. Claw stays inline because its tokens are the
:root defaults, so the default path loses nothing and gains the bytes back.

The first-paint story this needed: index.html's boot script now links the active
family's palette during head parsing, which makes it render-blocking exactly
like the app stylesheet, so a persisted theme paints its own colours on the
first frame instead of flashing the default. The href is built from the mount
prefix the gateway already stamps on <html>, so it follows a configured Control
UI base path without the script having to know one. theme.ts keeps the link
correct when the theme changes at runtime, reusing the helper the webfont
stylesheets already use.

The nested resolve-theme ternary became a family table in the same script, since
it now picks an asset as well as a data-theme value.

  startup CSS  45.8 -> 42.2 KiB gzip, below the 44.3 KiB it measured before the
               three themes landed; ceiling restored 47 -> 45 KiB
  base.css     64.0 -> 35.8 KiB raw

Adds a regression test that blocks every bundle script and asserts the palette
still applies, so moving this back into the app bundle fails instead of silently
reintroducing the flash. Verified it catches that: with the boot-script link
removed the assertion reports `expected null to be '/themes/tide.css'`.

* fix(control-ui): publish themes after their palettes load

* fix(control-ui): clean up palette completion listeners

* refactor(control-ui): consolidate theme name resolution
2026-08-26 18:56:14 -07:00

65 lines
2.1 KiB
TypeScript

// Runs the complete lint pipeline after preparing a linked-worktree toolchain.
import { spawnSync, type SpawnSyncOptions } from "node:child_process";
import { createRequire } from "node:module";
import path from "node:path";
import { pathToFileURL } from "node:url";
import {
ensureRepoToolNodeModulesLink,
resolveRepoToolBinPath,
} from "./lib/local-check-runtime.mts";
function run(command: string, args: string[], options: SpawnSyncOptions) {
const result = spawnSync(command, args, options);
if (result.error) {
throw result.error;
}
return result.status ?? 1;
}
const oxlintPath = resolveRepoToolBinPath("oxlint");
const tsxPath = resolveRepoToolBinPath("tsx");
ensureRepoToolNodeModulesLink(oxlintPath);
const tsxImportSpecifier = pathToFileURL(createRequire(tsxPath).resolve("tsx")).href;
// Invoke the pre-step directly: running pnpm through a linked node_modules can
// reconcile the owning checkout's dependency tree instead of merely running it.
const uiI18nStatus = run(
process.execPath,
["--import", tsxImportSpecifier, path.resolve("scripts", "control-ui-i18n-verify.ts"), "verify"],
{ env: process.env, stdio: "inherit" },
);
if (uiI18nStatus !== 0) {
process.exitCode = uiI18nStatus;
} else {
const oxlintStatus = run(
process.execPath,
[
"--import",
tsxImportSpecifier,
path.resolve("scripts", "run-oxlint-shards.mts"),
...process.argv.slice(2),
],
{ env: process.env, stdio: "inherit" },
);
if (oxlintStatus !== 0) {
process.exitCode = oxlintStatus;
} else {
// Control UI CSS hygiene: plain stylesheets plus css`` templates in Lit
// components. oxlint cannot see inside tagged CSS templates.
// Delegate like the steps above: the stylelint runner already resolves and
// launches the shim, so this pipeline never handles a tool path itself.
process.exitCode = run(
process.execPath,
[
"--import",
tsxImportSpecifier,
path.resolve("scripts", "run-stylelint.mts"),
"ui/src/**/*.css",
"ui/src/**/*.ts",
"ui/public/themes/*.css",
],
{ env: process.env, stdio: "inherit" },
);
}
}