release: WRNexusJS 0.2.78
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/compiler",
|
||||
"version": "0.2.77",
|
||||
"version": "0.2.78",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -1144,6 +1144,50 @@ function serverLoopLocalsAttribute(ctx: CompCtx): string {
|
||||
return ` data-wrn-loop-locals="\${__wrnexusEncodeLoopLocals({ ${entries} })}"`;
|
||||
}
|
||||
|
||||
function unwrapDirectiveExpression(raw: string): string {
|
||||
const value = raw.trim();
|
||||
|
||||
if (!value.startsWith("{") || !value.endsWith("}")) {
|
||||
return value;
|
||||
}
|
||||
|
||||
let depth = 0;
|
||||
let quote: '"' | "'" | "`" | null = null;
|
||||
let escaped = false;
|
||||
|
||||
for (let index = 0; index < value.length; index++) {
|
||||
const char = value[index]!;
|
||||
|
||||
if (escaped) {
|
||||
escaped = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (quote) {
|
||||
if (char === "\\") {
|
||||
escaped = true;
|
||||
} else if (char === quote) {
|
||||
quote = null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char === '"' || char === "'" || char === "`") {
|
||||
quote = char;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char === "{") depth++;
|
||||
if (char === "}") depth--;
|
||||
|
||||
if (depth === 0 && index < value.length - 1) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
return depth === 0 ? value.slice(1, -1).trim() : value;
|
||||
}
|
||||
|
||||
/** Render a component view node into template-literal-ready source. */
|
||||
function renderComponentNode(node: ViewNode, ctx: CompCtx): string {
|
||||
if (node.type === "text") return compileText(node.value, ctx);
|
||||
@@ -1185,7 +1229,7 @@ function renderComponentNode(node: ViewNode, ctx: CompCtx): string {
|
||||
if (!attr.event && attr.name.startsWith("class:")) {
|
||||
conditionalClasses.push({
|
||||
className: attr.name.slice("class:".length),
|
||||
expression: attr.value,
|
||||
expression: unwrapDirectiveExpression(attr.value),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -788,6 +788,33 @@ component PageHeader {
|
||||
|
||||
expect(output).toContain("dark:bg-white/10");
|
||||
});
|
||||
test("class directives accept single-quoted brace expressions", () => {
|
||||
const output = generate(
|
||||
parse(`
|
||||
component MarketingSectionHeader {
|
||||
props {
|
||||
align = "start"
|
||||
}
|
||||
|
||||
view {
|
||||
<header
|
||||
class="max-w-3xl"
|
||||
class:mx-auto='{align === "center"}'
|
||||
class:text-center='{align === "center"}'
|
||||
>
|
||||
Header
|
||||
</header>
|
||||
}
|
||||
}
|
||||
`),
|
||||
);
|
||||
|
||||
expect(output).toContain('${(align === "center") ? " mx-auto" : ""}');
|
||||
expect(output).toContain('${(align === "center") ? " text-center" : ""}');
|
||||
expect(output).not.toContain('({align === "center"})');
|
||||
expect(output).toContain(""align === \\\\"center\\\\""");
|
||||
});
|
||||
|
||||
test("components support each blocks", () => {
|
||||
const output = generate(
|
||||
parse(`
|
||||
|
||||
Reference in New Issue
Block a user