fix: vs code formatter
This commit is contained in:
+133
-20
@@ -448,7 +448,13 @@ function parse(source) {
|
||||
function parseHtmlView(src, pos) {
|
||||
let i = pos;
|
||||
const isNameStart = (c) => /[A-Za-z_]/.test(c);
|
||||
const isNamePart = (c) => /[A-Za-z0-9_:-]/.test(c);
|
||||
const isNamePart = (c) => /[A-Za-z0-9_:.[\]%-]/.test(c);
|
||||
const isAttributeNamePart = (c, next) => {
|
||||
if (c === "/") {
|
||||
return next !== ">";
|
||||
}
|
||||
return isNamePart(c);
|
||||
};
|
||||
const isWs2 = (c) => c === " " || c === "\t" || c === `
|
||||
` || c === "\r";
|
||||
const fail = (msg) => {
|
||||
@@ -489,8 +495,9 @@ function parseHtmlView(src, pos) {
|
||||
if (i >= src.length || !isNameStart(src[i]))
|
||||
return fail("Expected a tag or attribute name");
|
||||
const start = i++;
|
||||
while (i < src.length && isNamePart(src[i]))
|
||||
while (i < src.length && isAttributeNamePart(src[i], src[i + 1])) {
|
||||
i++;
|
||||
}
|
||||
return src.slice(start, i);
|
||||
};
|
||||
const parseTag = () => {
|
||||
@@ -700,8 +707,34 @@ function eventAttribute(name) {
|
||||
return `data-on-wrnexus-mobile-${name.slice(7)}`;
|
||||
return `data-on-${name}`;
|
||||
}
|
||||
function renderAttrs(attrs, csrId) {
|
||||
const rendered = attrs.map(renderAttr).join("");
|
||||
function reactiveAttrValue(raw, reactive) {
|
||||
let found = false;
|
||||
const value = raw.replace(/\{([^{}]+)\}/g, (whole, inner) => {
|
||||
const expr = inner.trim();
|
||||
if (!exprRefsState(expr, reactive.stateNames))
|
||||
return whole;
|
||||
found = true;
|
||||
try {
|
||||
const result = new Function("with(this){return (" + expr + ");}").call(reactive.scope);
|
||||
return result == null ? "" : String(result);
|
||||
} catch {
|
||||
return whole;
|
||||
}
|
||||
});
|
||||
return found ? value : null;
|
||||
}
|
||||
function renderAttrs(attrs, csrId, reactive = null) {
|
||||
let bindIndex = 0;
|
||||
const rendered = attrs.map((attr) => {
|
||||
const base = renderAttr(attr);
|
||||
if (!reactive || attr.event || attr.boolean || !base || !attr.value.includes("{"))
|
||||
return base;
|
||||
const initial = reactiveAttrValue(attr.value, reactive);
|
||||
if (initial === null)
|
||||
return base;
|
||||
const marker = JSON.stringify([attr.name, attr.value]);
|
||||
return ` ${attr.name}="${attrEscape(initial)}" data-wrn-bind-${bindIndex++}="${attrEscape(marker)}"`;
|
||||
}).join("");
|
||||
return csrId ? `${rendered} data-wrnexus-csr="${attrEscape(csrId)}"` : rendered;
|
||||
}
|
||||
function substituteTMarkers(text) {
|
||||
@@ -845,7 +878,7 @@ function renderNode(node, ssrBindings, csrBindings, apiBindings, loops, reactive
|
||||
helpers: ""
|
||||
}) : undefined;
|
||||
if (VOID_ELEMENTS.has(node.tag.toLowerCase())) {
|
||||
return `<${node.tag}${renderAttrs(node.attrs, csrId)}>`;
|
||||
return `<${node.tag}${renderAttrs(node.attrs, csrId, reactive)}>`;
|
||||
}
|
||||
const inner = apiBinding?.mode === "ssr" ? ssrMarker(ssrBindings, renderBinding(apiBinding)) : ssrGet && ssrText ? ssrMarker(ssrBindings, {
|
||||
method: "GET",
|
||||
@@ -853,7 +886,7 @@ function renderNode(node, ssrBindings, csrBindings, apiBindings, loops, reactive
|
||||
body: expressionBody(ssrText),
|
||||
helpers: ""
|
||||
}) : node.children.map((child) => renderNode(child, ssrBindings, csrBindings, apiBindings, loops, reactive)).join("");
|
||||
return `<${node.tag}${renderAttrs(node.attrs, csrId)}>${inner}</${node.tag}>`;
|
||||
return `<${node.tag}${renderAttrs(node.attrs, csrId, reactive)}>${inner}</${node.tag}>`;
|
||||
}
|
||||
function ssrMarker(bindings, binding) {
|
||||
const marker = `<!--wrnexus-ssr:${bindings.length}-->`;
|
||||
@@ -989,8 +1022,8 @@ ${helpers}`);
|
||||
const styles = ast.styles.map((body2) => body2.trim()).filter(Boolean);
|
||||
const needsClientRuntime = ast.states.length > 0 || hasClientBehavior(ast.view);
|
||||
if (needsClientRuntime) {
|
||||
const scope = ast.states.map((s) => `${s.name}: ${s.expr}`).join(", ");
|
||||
html = `<div data-scope="${attrEscape(scope)}">${html}</div>`;
|
||||
const scopePlaceholder = "__WRNEXUS_DYNAMIC_SCOPE__";
|
||||
html = `<div data-scope="${scopePlaceholder}">${html}</div>`;
|
||||
}
|
||||
if (styles.length > 0) {
|
||||
const css = styles.map(styleEscape).join(`
|
||||
@@ -1003,6 +1036,7 @@ ${css}
|
||||
out.push(`export const __wrnexusCsr = ${JSON.stringify(csrBindings, null, 2)};`);
|
||||
}
|
||||
let body = templateEscape(html);
|
||||
const dynamicStateScope = ast.states.map((state) => `${JSON.stringify(state.name)}: (() => { try { return (${state.expr}); } catch { return undefined; } })()`).join(", ");
|
||||
loops.forEach((code, idx) => {
|
||||
body = body.replace(`\x00WRNEACH${idx}\x00`, () => code);
|
||||
});
|
||||
@@ -1017,7 +1051,7 @@ ${css}
|
||||
loopConsts.push(` const ${name} = __wrnexusEvalData(await __wrnexusCallApi(${JSON.stringify(binding.path)}, ${JSON.stringify(binding.method)}, ctx), ${JSON.stringify(binding.body)}, ${JSON.stringify(binding.helpers)}, ctx);`);
|
||||
}
|
||||
}
|
||||
const needsSsrRuntime = ssrBindings.length > 0 || loops.length > 0;
|
||||
const needsSsrRuntime = ssrBindings.length > 0 || loops.length > 0 || ast.states.some((state) => /\bctx\b/.test(state.expr));
|
||||
if (needsSsrRuntime) {
|
||||
out.push(ssrRuntimeSource());
|
||||
out.push(`const __wrnexusSsrBindings = ${JSON.stringify(ssrBindings, null, 2)};`);
|
||||
@@ -1025,13 +1059,55 @@ ${css}
|
||||
`) + `
|
||||
` : "";
|
||||
out.push(`export default async function ${ast.name}(ctx: any) {
|
||||
${decls} const html = \`${body}\`;
|
||||
return await __wrnexusRenderSsrBindings(html, ctx);
|
||||
}`);
|
||||
${decls}
|
||||
const __state = { ${dynamicStateScope} };
|
||||
|
||||
const __scopeValue = Object.entries(__state)
|
||||
.map(([key, value]) => {
|
||||
const encoded =
|
||||
typeof value === "number" || typeof value === "boolean"
|
||||
? String(value)
|
||||
: JSON.stringify(value == null ? "" : String(value));
|
||||
|
||||
return key + ": " + encoded;
|
||||
})
|
||||
.join(", ")
|
||||
.replace(/&/g, "&")
|
||||
.replace(/"/g, """)
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
|
||||
const html = \`${body}\`.replace(
|
||||
"__WRNEXUS_DYNAMIC_SCOPE__",
|
||||
__scopeValue,
|
||||
);
|
||||
|
||||
return await __wrnexusRenderSsrBindings(html, ctx);
|
||||
}`);
|
||||
} else {
|
||||
out.push(`export default function ${ast.name}() {
|
||||
return \`${body}\`;
|
||||
}`);
|
||||
out.push(`export default function ${ast.name}(ctx: any) {
|
||||
const __state = { ${dynamicStateScope} };
|
||||
|
||||
const __scopeValue = Object.entries(__state)
|
||||
.map(([key, value]) => {
|
||||
const encoded =
|
||||
typeof value === "number" || typeof value === "boolean"
|
||||
? String(value)
|
||||
: JSON.stringify(value == null ? "" : String(value));
|
||||
|
||||
return key + ": " + encoded;
|
||||
})
|
||||
.join(", ")
|
||||
.replace(/&/g, "&")
|
||||
.replace(/"/g, """)
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">");
|
||||
|
||||
return \`${body}\`.replace(
|
||||
"__WRNEXUS_DYNAMIC_SCOPE__",
|
||||
__scopeValue,
|
||||
);
|
||||
}`);
|
||||
}
|
||||
if (ast.apis.length > 0) {
|
||||
ast.apis.forEach((api, index) => {
|
||||
@@ -1186,13 +1262,50 @@ function renderComponentNode(node, 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).");
|
||||
}
|
||||
const attrs = node.attrs.map((a) => a.event ? ` ${eventAttribute(a.name)}="${compileAttrValue(a.value, ctx)}"` : a.boolean ? ` ${a.name}` : ` ${a.name}="${compileAttrValue(a.value, ctx)}"`).join("");
|
||||
let bindIndex = 0;
|
||||
const staticClasses = [];
|
||||
const conditionalClasses = [];
|
||||
for (const attr of node.attrs) {
|
||||
if (!attr.event && attr.name === "class") {
|
||||
staticClasses.push(attr.value);
|
||||
}
|
||||
if (!attr.event && attr.name.startsWith("class:")) {
|
||||
conditionalClasses.push({
|
||||
className: attr.name.slice("class:".length),
|
||||
expression: attr.value
|
||||
});
|
||||
}
|
||||
}
|
||||
const attrs = node.attrs.filter((a) => a.name !== "class" && !a.name.startsWith("class:")).map((a) => {
|
||||
if (a.event) {
|
||||
return ` ${eventAttribute(a.name)}="${compileAttrValue(a.value, ctx)}"`;
|
||||
}
|
||||
if (a.boolean) {
|
||||
return ` ${a.name}`;
|
||||
}
|
||||
const rendered = ` ${a.name}="${compileAttrValue(a.value, ctx)}"`;
|
||||
if (!a.value.includes("{") || !exprRefsState(a.value, ctx.stateNames)) {
|
||||
return rendered;
|
||||
}
|
||||
const marker = attrEscape(JSON.stringify([a.name, a.value]));
|
||||
return `${rendered} data-wrn-bind-${bindIndex++}="${escLit(marker)}"`;
|
||||
}).join("");
|
||||
const initialConditionalClasses = conditionalClasses.map(({ className, expression }) => {
|
||||
return `\${(${ctx.resolveExpr(expression)}) ? ${JSON.stringify(` ${className}`)} : ""}`;
|
||||
}).join("");
|
||||
const classAttribute = staticClasses.length > 0 || conditionalClasses.length > 0 ? ` class="${compileAttrValue(staticClasses.join(" "), ctx)}${initialConditionalClasses}"` : "";
|
||||
const classBindings = conditionalClasses.map(({ className, expression }, index) => {
|
||||
const marker = attrEscape(JSON.stringify([className, expression]));
|
||||
return ` data-wrn-class-${index}="${escLit(marker)}"`;
|
||||
}).join("");
|
||||
const loops = loopVarsOf(node);
|
||||
const childCtx = loops.length > 0 ? { ...ctx, loopVars: new Set([...ctx.loopVars ?? [], ...loops]) } : ctx;
|
||||
if (VOID_ELEMENTS.has(node.tag.toLowerCase()))
|
||||
return `<${node.tag}${attrs}>`;
|
||||
const inner = node.children.map((c) => renderComponentNode(c, childCtx)).join("");
|
||||
return `<${node.tag}${attrs}>${inner}</${node.tag}>`;
|
||||
const allAttrs = `${classAttribute}${classBindings}${attrs}`;
|
||||
if (VOID_ELEMENTS.has(node.tag.toLowerCase())) {
|
||||
return `<${node.tag}${allAttrs}>`;
|
||||
}
|
||||
const inner = node.children.map((child) => renderComponentNode(child, childCtx)).join("");
|
||||
return `<${node.tag}${allAttrs}>${inner}</${node.tag}>`;
|
||||
}
|
||||
function generateComponent(ast) {
|
||||
const out = [];
|
||||
|
||||
Reference in New Issue
Block a user