fix(csr): recognize component-local CSS variables
Quality / quality (ubuntu-latest) (push) Failing after 6m8s
Quality / quality (windows-latest) (push) Canceled after 0s

This commit is contained in:
2026-08-11 16:24:15 +05:30
parent b72f517fa4
commit 904127687b
6 changed files with 51 additions and 7 deletions
+3 -3
View File
@@ -268,7 +268,7 @@
}, },
"packages/cli": { "packages/cli": {
"name": "@wrnexus/cli", "name": "@wrnexus/cli",
"version": "0.8.10", "version": "0.8.11",
"bin": { "bin": {
"wrnexus": "src/index.ts", "wrnexus": "src/index.ts",
}, },
@@ -317,7 +317,7 @@
}, },
"packages/csr": { "packages/csr": {
"name": "@wrnexus/csr", "name": "@wrnexus/csr",
"version": "0.8.8", "version": "0.8.9",
"dependencies": { "dependencies": {
"@wrnexus/core": "workspace:*", "@wrnexus/core": "workspace:*",
}, },
@@ -332,7 +332,7 @@
}, },
"packages/dev-server": { "packages/dev-server": {
"name": "@wrnexus/dev-server", "name": "@wrnexus/dev-server",
"version": "0.8.9", "version": "0.8.10",
"dependencies": { "dependencies": {
"@wrnexus/authz": "workspace:*", "@wrnexus/authz": "workspace:*",
"@wrnexus/cache": "workspace:*", "@wrnexus/cache": "workspace:*",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@wrnexus/cli", "name": "@wrnexus/cli",
"version": "0.8.10", "version": "0.8.11",
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
"exports": { "exports": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@wrnexus/csr", "name": "@wrnexus/csr",
"version": "0.8.8", "version": "0.8.9",
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
"exports": { "exports": {
+12 -1
View File
@@ -224,12 +224,18 @@ export const REACTIVE_RUNTIME = String.raw`
function warnMissingThemeTokens() { function warnMissingThemeTokens() {
var referenced = Object.create(null); var referenced = Object.create(null);
var declared = Object.create(null);
function collect(rules) { function collect(rules) {
Array.prototype.forEach.call(rules || [], function (rule) { Array.prototype.forEach.call(rules || [], function (rule) {
var cssText = rule.cssText || ""; var cssText = rule.cssText || "";
var match; var match;
var pattern = /var\(\s*(--wire-[A-Za-z0-9_-]+)/g; var pattern = /var\(\s*(--wire-[A-Za-z0-9_-]+)/g;
while ((match = pattern.exec(cssText))) referenced[match[1]] = true; while ((match = pattern.exec(cssText))) referenced[match[1]] = true;
if (rule.style) {
Array.prototype.forEach.call(rule.style, function (property) {
if (String(property).indexOf("--wire-") === 0) declared[property] = true;
});
}
try { try {
if (rule.cssRules) collect(rule.cssRules); if (rule.cssRules) collect(rule.cssRules);
} catch (_) { } catch (_) {
@@ -240,9 +246,14 @@ export const REACTIVE_RUNTIME = String.raw`
Array.prototype.forEach.call(document.styleSheets || [], function (sheet) { Array.prototype.forEach.call(document.styleSheets || [], function (sheet) {
try { collect(sheet.cssRules); } catch (_) {} try { collect(sheet.cssRules); } catch (_) {}
}); });
Array.prototype.forEach.call(document.querySelectorAll("[style]") || [], function (element) {
Array.prototype.forEach.call(element.style || [], function (property) {
if (String(property).indexOf("--wire-") === 0) declared[property] = true;
});
});
var rendered = window.getComputedStyle(document.documentElement); var rendered = window.getComputedStyle(document.documentElement);
Object.keys(referenced).forEach(function (token) { Object.keys(referenced).forEach(function (token) {
if (rendered.getPropertyValue(token).trim()) return; if (declared[token] || rendered.getPropertyValue(token).trim()) return;
warnOnce( warnOnce(
"WRN-DEV-THEME-TOKEN-MISSING", "WRN-DEV-THEME-TOKEN-MISSING",
"Theme token '" + token + "' is referenced by rendered CSS but is not defined.", "Theme token '" + token + "' is referenced by rendered CSS but is not defined.",
+33
View File
@@ -813,6 +813,39 @@ test("development runtime warns for referenced theme tokens absent from rendered
expect(String(warnings[0]?.[0])).toContain("--wire-missing-test"); expect(String(warnings[0]?.[0])).toContain("--wire-missing-test");
}); });
test("development runtime accepts component-local and inline wire variables", () => {
const win = new Window() as unknown as Window & Record<string, unknown>;
win.document.head.innerHTML =
`<style>.component { --wire-component-local: red; color: var(--wire-component-local); ` +
`background: var(--wire-inline-local); }</style>`;
win.document.body.innerHTML =
`<div class="component" style="--wire-inline-local: blue" data-scope=""></div>`;
(globalThis as Record<string, unknown>).window = win;
(globalThis as Record<string, unknown>).document = win.document;
(globalThis as Record<string, unknown>).location = win.location;
(globalThis as Record<string, unknown>).NodeFilter = (
win as unknown as { NodeFilter: unknown }
).NodeFilter;
(globalThis as Record<string, unknown>).MutationObserver = (
win as unknown as { MutationObserver: unknown }
).MutationObserver;
(globalThis as Record<string, unknown>).CustomEvent = (
win as unknown as { CustomEvent: unknown }
).CustomEvent;
const warnings: unknown[][] = [];
const originalWarn = console.warn;
console.warn = (...args: unknown[]) => warnings.push(args);
try {
(0, eval)(getReactiveRuntime(true));
(
win as unknown as { __wrnexusHydrateScopes?: (root: unknown) => void }
).__wrnexusHydrateScopes?.(win.document);
} finally {
console.warn = originalWarn;
}
expect(warnings).toHaveLength(0);
});
test("production runtime strips development diagnostics", () => { test("production runtime strips development diagnostics", () => {
const production = getReactiveRuntime(); const production = getReactiveRuntime();
expect(production).not.toContain("WRN-DEV-"); expect(production).not.toContain("WRN-DEV-");
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "@wrnexus/dev-server", "name": "@wrnexus/dev-server",
"version": "0.8.9", "version": "0.8.10",
"type": "module", "type": "module",
"main": "src/index.ts", "main": "src/index.ts",
"exports": { "exports": {