feat(wrn): support native structured prop expressions
This commit is contained in:
@@ -164,8 +164,8 @@ A file opens with `page <Name>` or `component <Name>` followed by a `{ ... }` bo
|
||||
- `types { <TypeScript declarations> }` — reusable interfaces and aliases for the current file.
|
||||
- `props { name: Type = <default> ... }` — typed component props. Omit `= <default>` to make a prop required. Legacy inferred props remain supported.
|
||||
- `@event name = function` inside `props` — declares a public component event. Emit it from component behavior with `name(detail)` or `$emit("name", detail)`, and consume it with `<Component @name="handler(event)" />`.
|
||||
- `state <ident>: Type = <expr>` — typed reactive state seeded from a raw JS expression. The annotation is optional for backward compatibility.
|
||||
- `view { <html> }` — plain HTML with `{expr}` interpolation in text and attributes, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`. Attribute expressions that reference `state` keep an SSR value and update reactively in the browser.
|
||||
- `state <ident>: Type = <expr>` — typed reactive state seeded from a raw JS expression, including native array and object literals. The annotation is optional for backward compatibility.
|
||||
- `view { <html> }` — plain HTML with `{expr}` interpolation in text and attributes, JSX-style component props such as `items={items}`, `items={[...]}`, and `options={{...}}`, hyphenated attributes, boolean attributes, `@event="..."` client bindings, and `<!-- comments -->`. Structured component props are serialized safely for SSR; expressions that reference `state` retain their initial value and update reactively in the browser.
|
||||
- `seo { key = "value" ... }` — metadata merged into the generated `meta`.
|
||||
- `style { <raw css> }` — inlined page/component stylesheet (repeatable).
|
||||
- `functions { <TypeScript> }` — helpers with typed parameters and return values. Types remain in server output and are safely erased from browser behavior code.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@wrnexus/compiler",
|
||||
"version": "0.5.0",
|
||||
"version": "0.5.1",
|
||||
"type": "module",
|
||||
"main": "src/index.ts",
|
||||
"exports": {
|
||||
|
||||
@@ -464,6 +464,28 @@ component ParentCard {
|
||||
expect(output).toContain("function __wireProp");
|
||||
});
|
||||
|
||||
test("native array and object props serialize through component mounts", async () => {
|
||||
const mod = await compileAndImport(`
|
||||
component NativeProps {
|
||||
state items = [{"label":"Home","href":"/"}]
|
||||
view {
|
||||
<Navbar items={items} options={{"dense":true}} />
|
||||
<Sidebar items={[{"label":"Cases","href":"/cases"}]} />
|
||||
}
|
||||
}
|
||||
`);
|
||||
const render = mod.render as (props?: Record<string, unknown>) => string;
|
||||
const html = render();
|
||||
|
||||
expect(html).toContain(
|
||||
'items="[{"label":"Home","href":"/"}]"',
|
||||
);
|
||||
expect(html).toContain('options="{"dense":true}"');
|
||||
expect(html).toContain(
|
||||
'items="[{"label":"Cases","href":"/cases"}]"',
|
||||
);
|
||||
});
|
||||
|
||||
test("parses a layout block", () => {
|
||||
const ast = parse(`
|
||||
layout AppLayout {
|
||||
|
||||
Reference in New Issue
Block a user