release: WRNexusJS 0.2.28

This commit is contained in:
2026-07-14 15:13:58 +05:30
parent d3094010af
commit 56027531ef
56 changed files with 175 additions and 95 deletions
+39 -5
View File
@@ -599,7 +599,9 @@ async function __wrnexusRenderSsrBindings(html: string, ctx: any): Promise<strin
}
export function generate(ast: PageAst): string {
if (ast.kind === "component") return generateComponent(ast);
if (ast.kind === "component" || ast.kind === "layout") {
return generateComponent(ast);
}
const out: string[] = [];
const ssrBindings: SsrBinding[] = [];
@@ -903,6 +905,8 @@ function compileText(raw: string, ctx: CompCtx): string {
escLit(`<span data-text="${attrEscape(expr)}">`) +
`\${__wireHtml(${ctx.resolveExpr(expr)})}` +
escLit(`</span>`);
} else if (expr === "content") {
out += `\${__wireRaw(${ctx.resolveExpr(expr)})}`;
} else {
out += `\${__wireHtml(${ctx.resolveExpr(expr)})}`;
}
@@ -1024,9 +1028,22 @@ function renderComponentNode(node: ViewNode, ctx: CompCtx): string {
function generateComponent(ast: PageAst): string {
const out: string[] = [];
const effectiveProps =
ast.kind === "layout" && !ast.props.some((prop) => prop.name === "content")
? [
{
name: "content",
default: '""',
},
...ast.props,
]
: ast.props;
const stateNames = new Set(ast.states.map((s) => s.name));
const nameRefs = new Map<string, string>();
for (const p of ast.props) nameRefs.set(p.name, safeRef(p.name));
for (const p of effectiveProps) {
nameRefs.set(p.name, safeRef(p.name));
}
for (const s of ast.states) nameRefs.set(s.name, safeRef(s.name));
const resolveExpr = (expr: string): string => {
let result = expr;
@@ -1050,10 +1067,13 @@ function generateComponent(ast: PageAst): string {
// Prop-driven text/attributes are baked server-side, so static components ship
// no JavaScript at all.
const needsScope = ast.states.length > 0 || viewHasEvents(ast.view);
const scopeKeys = [...ast.props.map((p) => p.name), ...ast.states.map((s) => s.name)];
const scopeKeys = [
...effectiveProps.map((prop) => prop.name),
...ast.states.map((state) => state.name),
];
const decls: string[] = [];
for (const prop of ast.props) {
for (const prop of effectiveProps) {
decls.push(
` const ${nameRefs.get(prop.name)} = __coerce(__p[${JSON.stringify(prop.name)}], (${resolveExpr(prop.default)}));`,
);
@@ -1073,7 +1093,11 @@ function generateComponent(ast: PageAst): string {
? ` const __scope = "";\n`
: "";
out.push(`export const __wrnexusComponent = ${JSON.stringify(ast.name)};`);
if (ast.kind === "layout") {
out.push(`export const __wrnexusLayout = ${JSON.stringify(ast.name)};`);
} else {
out.push(`export const __wrnexusComponent = ${JSON.stringify(ast.name)};`);
}
out.push(`function __coerce(v: any, def: any): any {
if (v === undefined || v === null) return def;
if (typeof def === "number") return Number(v);
@@ -1116,3 +1140,13 @@ function __wireAttr(v: any): string {
return out.join("\n\n") + "\n";
}
function __wireHtml(v: any): string {
return String(v == null ? "" : v).replace(/[&<>]/g, (c) =>
c === "&" ? "&amp;" : c === "<" ? "&lt;" : "&gt;",
);
}
function __wireRaw(v: any): string {
return String(v == null ? "" : v);
}