release: WRNexusJS 0.2.46

This commit is contained in:
2026-07-15 20:09:47 +05:30
parent 8a8328a308
commit 973d580bc5
58 changed files with 453 additions and 147 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@wrnexus/compiler",
"version": "0.2.45",
"version": "0.2.46",
"type": "module",
"main": "src/index.ts",
"exports": {
+53 -14
View File
@@ -1303,7 +1303,9 @@ function generateComponent(ast: PageAst): string {
const scopeLine =
needsScope && scopeKeys.length > 0
? ` const __scope = __wrnexusScopeDecl({ ${scopeKeys.map((k) => `${JSON.stringify(k)}: ${nameRefs.get(k)}`).join(", ")} });\n`
? ` const __scope = __wrnexusScopeDecl({ ${scopeKeys
.map((key) => `${JSON.stringify(key)}: ${nameRefs.get(key)}`)
.join(", ")} });\n`
: needsScope
? ` const __scope = "";\n`
: "";
@@ -1419,19 +1421,56 @@ function __wireRaw(v: any): string {
}`);
if (needsScope) {
out.push(`function __wrnexusScopeDecl(obj: Record<string, any>): string {
const lit = (v: any) =>
typeof v === "number" || typeof v === "boolean"
? String(v)
: "'" + String(v).replace(/\\\\/g, "\\\\\\\\").replace(/'/g, "\\\\'").replace(/\\n/g, "\\\\n") + "'";
return Object.keys(obj)
.map((k) => k + ": " + lit(obj[k]))
.join(", ")
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}`);
out.push(`function __wrnexusSerializeScopeValue(value: any): string {
if (value === undefined) {
return "undefined";
}
if (value === null) {
return "null";
}
if (typeof value === "number") {
return Number.isFinite(value)
? String(value)
: "null";
}
if (typeof value === "boolean") {
return value ? "true" : "false";
}
if (typeof value === "string") {
return JSON.stringify(value);
}
try {
const serialized = JSON.stringify(value);
return serialized === undefined
? "undefined"
: serialized;
} catch {
return "null";
}
}
function __wrnexusScopeDecl(obj: Record<string, any>): string {
return Object.keys(obj)
.map(
(key) =>
key +
": " +
__wrnexusSerializeScopeValue(
obj[key],
),
)
.join(", ")
.replace(/&/g, "&amp;")
.replace(/"/g, "&quot;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;");
}`);
}
const serverFunctionSource = serverFunctions ? `${serverFunctions}\n` : "";
+9 -1
View File
@@ -98,10 +98,18 @@ test("stateful component: state text baked into a reactive data-text span, prop
);
const render = mod.render as (p: Record<string, string>) => string;
const out = render({ start: "10", label: "Score" });
expect(out).toContain("data-scope=\"start: 10, label: 'Score', count: 10\"");
expect(out).toContain('data-scope="start: 10, label: &quot;Score&quot;, count: 10"');
expect(out).toContain('data-on-click="count++"');
// label baked as static text; count baked as its initial value AND kept live.
expect(out).toContain('Score: <span data-text="count">10</span>');
expect(out).toContain('data-scope="');
expect(out).toContain("start: 10");
expect(out).toContain("label: &quot;Score&quot;");
expect(out).toContain("count: 10");
});
test("prop type coercion follows the default value's type", async () => {