release: WRNexusJS 0.2.39
This commit is contained in:
+183
-23
@@ -493,12 +493,6 @@ function parseHtmlView(src, pos) {
|
||||
let i = pos;
|
||||
const isNameStart = (c) => /[A-Za-z_]/.test(c);
|
||||
const isTagNamePart = (c) => /[A-Za-z0-9_$:.-]/.test(c);
|
||||
const isAttributeNamePart = (c, next) => {
|
||||
if (c === "/") {
|
||||
return next !== ">";
|
||||
}
|
||||
return /[A-Za-z0-9_$:.[\]%-]/.test(c);
|
||||
};
|
||||
const isWs2 = (c) => c === " " || c === "\t" || c === `
|
||||
` || c === "\r";
|
||||
const fail = (msg) => {
|
||||
@@ -738,6 +732,7 @@ function parseHtmlView(src, pos) {
|
||||
}
|
||||
|
||||
// ../../packages/compiler/src/codegen.ts
|
||||
var import_node_buffer = require("node:buffer");
|
||||
function isComponentTag(tag) {
|
||||
return /^[A-Z][A-Za-z0-9_$]*$/.test(tag);
|
||||
}
|
||||
@@ -976,9 +971,9 @@ function renderNode(node, ssrBindings, csrBindings, apiBindings, loops, reactive
|
||||
return `<${node.tag}${renderAttrs(node.attrs, csrId, reactive)}>${inner}</${node.tag}>`;
|
||||
}
|
||||
function renderPageComponentInvocation(node, ssrBindings, csrBindings, apiBindings, loops, reactive) {
|
||||
const attrs = node.attrs.filter((attr) => attr.name !== "data-component");
|
||||
const attrs = node.attrs.filter((attr) => attr.name !== "data-component").map((attr) => renderPageComponentAttr(attr, loops)).join("");
|
||||
const inner = node.children.map((child) => renderNode(child, ssrBindings, csrBindings, apiBindings, loops, reactive)).join("");
|
||||
return `<div data-component="${attrEscape(node.tag)}"${renderAttrs(attrs, undefined, reactive)}>${inner}</div>`;
|
||||
return `<div data-component="${attrEscape(node.tag)}"` + `${attrs}>${inner}</div>`;
|
||||
}
|
||||
function renderNestedComponentInvocation(node, ctx) {
|
||||
let bindIndex = 0;
|
||||
@@ -989,8 +984,10 @@ function renderNestedComponentInvocation(node, ctx) {
|
||||
if (attr.boolean) {
|
||||
return ` ${attr.name}`;
|
||||
}
|
||||
const rendered = ` ${attr.name}="` + `${compileAttrValue(attr.value, ctx)}"`;
|
||||
if (!attr.value.includes("{") || !exprRefsState(attr.value, ctx.stateNames)) {
|
||||
const wholeExpression = wholeAttributeExpression(attr.value);
|
||||
const compiledValue = wholeExpression ? `\${__wireProp(${ctx.resolveExpr(wholeExpression)})}` : compileAttrValue(attr.value, ctx);
|
||||
const rendered = ` ${attr.name}="${compiledValue}"`;
|
||||
if (wholeExpression || !attr.value.includes("{") || !exprRefsState(attr.value, ctx.stateNames)) {
|
||||
return rendered;
|
||||
}
|
||||
const marker = attrEscape(JSON.stringify([attr.name, attr.value]));
|
||||
@@ -1091,6 +1088,28 @@ function __wrnexusEvalData(data: unknown, body: string, helpers = "", ctx: any):
|
||||
return new Function("$data", "$adapters", "const cookies = $adapters.cookies;\\nconst session = $adapters.session;\\nconst localStorage = $adapters.localStorage;\\nwith ($data ?? {}) {\\n" + helpers + "\\n" + body + "\\n}")(data, adapters);
|
||||
}
|
||||
|
||||
function __wrnexusPropAttr(
|
||||
value: unknown,
|
||||
): string {
|
||||
const serialized =
|
||||
value !== null &&
|
||||
typeof value === "object"
|
||||
? JSON.stringify(value)
|
||||
: String(value == null ? "" : value);
|
||||
|
||||
return serialized.replace(
|
||||
/[&<>"]/g,
|
||||
(character) =>
|
||||
character === "&"
|
||||
? "&"
|
||||
: character === "<"
|
||||
? "<"
|
||||
: character === ">"
|
||||
? ">"
|
||||
: """,
|
||||
);
|
||||
}
|
||||
|
||||
async function __wrnexusCallApi(path: string, method: string, ctx: any): Promise<unknown> {
|
||||
if (typeof ctx.__wrnexusCallApi === "function") {
|
||||
return await ctx.__wrnexusCallApi(path, method);
|
||||
@@ -1348,7 +1367,7 @@ function behaviorAttribute(behavior) {
|
||||
if (!behavior) {
|
||||
return "";
|
||||
}
|
||||
const encoded = Buffer.from(JSON.stringify(behavior), "utf8").toString("base64");
|
||||
const encoded = import_node_buffer.Buffer.from(JSON.stringify(behavior), "utf8").toString("base64");
|
||||
return ` data-wrn-behavior="${encoded}"`;
|
||||
}
|
||||
var INTERP_RE = /\{([^{}]+)\}/g;
|
||||
@@ -1360,7 +1379,17 @@ function exprRefsState(expr, stateNames) {
|
||||
return false;
|
||||
}
|
||||
function viewHasEvents(nodes) {
|
||||
return nodes.some((n) => n.type === "element" && (n.attrs.some((a) => a.event) || viewHasEvents(n.children)));
|
||||
return nodes.some((node) => {
|
||||
if (node.type === "text")
|
||||
return false;
|
||||
if (node.type === "each") {
|
||||
return viewHasEvents(node.body) || viewHasEvents(node.empty);
|
||||
}
|
||||
if (node.type === "if") {
|
||||
return node.branches.some((branch) => viewHasEvents(branch.body));
|
||||
}
|
||||
return node.attrs.some((attr) => attr.event) || viewHasEvents(node.children);
|
||||
});
|
||||
}
|
||||
function compileText(raw, ctx) {
|
||||
let out = "";
|
||||
@@ -1404,11 +1433,36 @@ function compileAttrValue(raw, ctx) {
|
||||
}
|
||||
return out + escLit(attrEscape(raw.slice(last)));
|
||||
}
|
||||
function renderComponentIfNode(node, ctx) {
|
||||
let expression = "``";
|
||||
for (let index = node.branches.length - 1;index >= 0; index--) {
|
||||
const branch = node.branches[index];
|
||||
const body = branch.body.map((child) => renderComponentNode(child, ctx)).join("");
|
||||
const bodyExpression = "`" + body + "`";
|
||||
expression = branch.cond === null ? bodyExpression : `(${ctx.resolveExpr(branch.cond)}) ? ${bodyExpression} : ${expression}`;
|
||||
}
|
||||
return "${" + expression + "}";
|
||||
}
|
||||
function renderComponentEachNode(node, ctx) {
|
||||
const item = node.item;
|
||||
const index = node.index ?? "__wi";
|
||||
const list = ctx.resolveExpr(node.list);
|
||||
const childCtx = {
|
||||
...ctx,
|
||||
serverLocals: new Set([...ctx.serverLocals ?? [], item, index])
|
||||
};
|
||||
const body = node.body.map((child) => renderComponentNode(child, childCtx)).join("");
|
||||
const empty = node.empty.map((child) => renderComponentNode(child, ctx)).join("");
|
||||
return "${(() => { const __wl = Array.isArray(" + list + ") ? (" + list + ") : []; return __wl.length ? __wl.map((" + item + ", " + index + ") => `" + body + '`).join("") : `' + empty + "`; })()}";
|
||||
}
|
||||
function renderComponentNode(node, ctx) {
|
||||
if (node.type === "text")
|
||||
return compileText(node.value, ctx);
|
||||
if (node.type === "each" || node.type === "if") {
|
||||
throw new Error("Server `{#each}` / `{#if}` blocks are supported in pages, not components. Move them into a page (or use data-for / data-show on the client).");
|
||||
if (node.type === "each") {
|
||||
return renderComponentEachNode(node, ctx);
|
||||
}
|
||||
if (node.type === "if") {
|
||||
return renderComponentIfNode(node, ctx);
|
||||
}
|
||||
if (isComponentTag(node.tag)) {
|
||||
return renderNestedComponentInvocation(node, ctx);
|
||||
@@ -1448,7 +1502,9 @@ function renderComponentNode(node, ctx) {
|
||||
const classHasReactiveExpression = staticClassValue.includes("{") && exprRefsState(staticClassValue, ctx.stateNames);
|
||||
const classAttribute = staticClasses.length > 0 || conditionalClasses.length > 0 ? ` class="${compileAttrValue(staticClassValue, ctx)}${initialConditionalClasses}"` : "";
|
||||
const classReactiveBinding = classHasReactiveExpression ? ` data-wrn-bind-class="${escLit(attrEscape(JSON.stringify(["class", staticClassValue])))}"` : "";
|
||||
const classBindings = conditionalClasses.map(({ className, expression }, index) => {
|
||||
const classBindings = conditionalClasses.filter(({ expression }) => {
|
||||
return !ctx.serverLocals || !exprRefsState(expression, ctx.serverLocals);
|
||||
}).map(({ className, expression }, index) => {
|
||||
const marker = attrEscape(JSON.stringify([className, expression]));
|
||||
return ` data-wrn-class-${index}="${escLit(marker)}"`;
|
||||
}).join("");
|
||||
@@ -1519,18 +1575,103 @@ ${styles.map(styleEscape).join(`
|
||||
out.push(`export const __wrnexusBehavior = ${JSON.stringify(behavior, null, 2)};`);
|
||||
}
|
||||
out.push(`function __coerce(v: any, def: any): any {
|
||||
if (v === undefined || v === null) return def;
|
||||
if (typeof def === "number") return Number(v);
|
||||
if (typeof def === "boolean") return v === true || v === "" || v === "true";
|
||||
if (v === undefined || v === null) {
|
||||
return def;
|
||||
}
|
||||
|
||||
if (typeof def === "number") {
|
||||
return Number(v);
|
||||
}
|
||||
|
||||
if (typeof def === "boolean") {
|
||||
return v === true || v === "" || v === "true";
|
||||
}
|
||||
|
||||
if (Array.isArray(def)) {
|
||||
if (Array.isArray(v)) {
|
||||
return v;
|
||||
}
|
||||
|
||||
if (typeof v === "string") {
|
||||
try {
|
||||
const parsed = JSON.parse(v);
|
||||
return Array.isArray(parsed) ? parsed : def;
|
||||
} catch {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
if (def !== null && typeof def === "object") {
|
||||
if (
|
||||
v !== null &&
|
||||
typeof v === "object" &&
|
||||
!Array.isArray(v)
|
||||
) {
|
||||
return v;
|
||||
}
|
||||
|
||||
if (typeof v === "string") {
|
||||
try {
|
||||
const parsed = JSON.parse(v);
|
||||
|
||||
return (
|
||||
parsed !== null &&
|
||||
typeof parsed === "object" &&
|
||||
!Array.isArray(parsed)
|
||||
)
|
||||
? parsed
|
||||
: def;
|
||||
} catch {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
return String(v);
|
||||
}
|
||||
|
||||
function __wireHtml(v: any): string {
|
||||
return String(v == null ? "" : v).replace(/[&<>]/g, (c) => (c === "&" ? "&" : c === "<" ? "<" : ">"));
|
||||
}
|
||||
function __wireAttr(v: any): string {
|
||||
return String(v == null ? "" : v).replace(/[&<>"]/g, (c) =>
|
||||
c === "&" ? "&" : c === "<" ? "<" : c === ">" ? ">" : """,
|
||||
return String(v == null ? "" : v).replace(
|
||||
/[&<>]/g,
|
||||
(c) =>
|
||||
c === "&"
|
||||
? "&"
|
||||
: c === "<"
|
||||
? "<"
|
||||
: ">",
|
||||
);
|
||||
}
|
||||
|
||||
function __wireAttr(v: any): string {
|
||||
return String(v == null ? "" : v).replace(
|
||||
/[&<>"]/g,
|
||||
(c) =>
|
||||
c === "&"
|
||||
? "&"
|
||||
: c === "<"
|
||||
? "<"
|
||||
: c === ">"
|
||||
? ">"
|
||||
: """,
|
||||
);
|
||||
}
|
||||
|
||||
function __wireProp(v: any): string {
|
||||
const value =
|
||||
v !== null && typeof v === "object"
|
||||
? JSON.stringify(v)
|
||||
: String(v == null ? "" : v);
|
||||
|
||||
return __wireAttr(value);
|
||||
}
|
||||
|
||||
function __wireRaw(v: any): string {
|
||||
return String(v == null ? "" : v);
|
||||
}`);
|
||||
if (needsScope) {
|
||||
out.push(`function __wrnexusScopeDecl(obj: Record<string, any>): string {
|
||||
@@ -1558,6 +1699,25 @@ function __wireAttr(v: any): string {
|
||||
`) + `
|
||||
`;
|
||||
}
|
||||
function wholeAttributeExpression(value) {
|
||||
const match = /^\s*\{([\s\S]+)\}\s*$/.exec(value);
|
||||
return match?.[1]?.trim() || null;
|
||||
}
|
||||
function renderPageComponentAttr(attr, dynamicExpressions) {
|
||||
if (attr.event) {
|
||||
return ` ${eventAttribute(attr.name)}="${attrEscape(attr.value)}"`;
|
||||
}
|
||||
if (attr.boolean) {
|
||||
return ` ${attr.name}`;
|
||||
}
|
||||
const expression = wholeAttributeExpression(attr.value);
|
||||
if (!expression) {
|
||||
return ` ${attr.name}="${attrEscape(attr.value)}"`;
|
||||
}
|
||||
dynamicExpressions.push(`\${__wrnexusPropAttr(${expression})}`);
|
||||
const marker = `\x00WRNEACH${dynamicExpressions.length - 1}\x00`;
|
||||
return ` ${attr.name}="${marker}"`;
|
||||
}
|
||||
|
||||
// ../../packages/compiler/src/native-codegen.ts
|
||||
class NativeCompileError extends Error {
|
||||
|
||||
Reference in New Issue
Block a user