diff --git a/.changeset/ninety-radios-smash.md b/.changeset/ninety-radios-smash.md new file mode 100644 index 0000000..194426f --- /dev/null +++ b/.changeset/ninety-radios-smash.md @@ -0,0 +1,5 @@ +--- +"@marko/tsrx": patch +--- + +Member expression tag names map to dynamic tags diff --git a/packages/tsrx/README.md b/packages/tsrx/README.md index b724f23..0757fb5 100644 --- a/packages/tsrx/README.md +++ b/packages/tsrx/README.md @@ -27,7 +27,7 @@ const { files } = compile(source, "App.tsrx"); | --------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | | `component App(props: T) { ... }` | `export type Input = T;` + `` | | `component App({ a, b }: T) { ... }` | `export type Input = T;` + `` | -| `component App() { ... }` | (no Input type, no binding) | +| `component App() { ... }` | (no Input type, no binding) | | `
{expr}
` | `
${expr}
` | | `{text "safe string"}` | `safe string` (plain text when value contains none of `< > $ {`) | | `{text expr}` | `${expr}` | @@ -38,12 +38,13 @@ const { files } = compile(source, "App.tsrx"); | `
` | `
` | | `const name = expr` | `` | | `let name` / `let name = expr` | `` / `` | -| `const title = {"Hi"};` | `${"Hi"}` · use `{title}` → Marko `<${title}/>` | +| `const title = {"Hi"};` | `${"Hi"}` · use `{title}` → Marko `<${title}/>` | +| `` | `<${input.content}/>` (member expression tag names map to dynamic tags) | | `if / else if / else` | ``, ``, `` | | `for (const x of xs; index i)` | `` | | `for (const x of xs; key x.id)` | ` x.id>` | | `switch (d) { case a: ...; default: ...; }` | chained `` / `` | -| `try { ... } pending { ... } catch (err) { ... }` | `` … `<@placeholder>` … `<@catch|err|>` … `` (catch param name replaces `err`) | +| `try { ... } pending { ... } catch (err) { ... }` | `` … `<@placeholder>` … `<@catch\|err\|>` … `` (catch param name replaces `err`) | | `` | `` (passed through as CSS-modules-friendly; scoped hash is applied by the existing `@tsrx/core` pipeline) | ## Not yet supported (MVP) diff --git a/packages/tsrx/src/transform.ts b/packages/tsrx/src/transform.ts index 8d9dea0..f5a4e88 100644 --- a/packages/tsrx/src/transform.ts +++ b/packages/tsrx/src/transform.ts @@ -433,8 +433,9 @@ export class Transformer { } const isDynamic = - el.id.type === "Identifier" && - this.#defineNames.has((el.id as AST.Identifier).name); + el.id.type === "MemberExpression" || + (el.id.type === "Identifier" && + this.#defineNames.has((el.id as AST.Identifier).name)); const refAttr = el.attributes.find((a) => a.type === "RefAttribute") as | (AST.BaseNode & { type: "RefAttribute"; argument: AST.Expression }) diff --git a/packages/tsrx/tests/__snapshots__/volar-mappings.txt b/packages/tsrx/tests/__snapshots__/volar-mappings.txt index 458206b..0f661d6 100644 --- a/packages/tsrx/tests/__snapshots__/volar-mappings.txt +++ b/packages/tsrx/tests/__snapshots__/volar-mappings.txt @@ -213,6 +213,10 @@ === style-tag === +=== tag-member-expression === + src: 2 "div" -> "div" + src: 2 "input.content" -> "input.content" + === top-level-text === src: 1 "{ count: number }" -> "{ count: number }" src: 1 "{ count }" -> "{ count }" diff --git a/packages/tsrx/tests/fixtures/tag-member-expression/__snapshots__/index.marko b/packages/tsrx/tests/fixtures/tag-member-expression/__snapshots__/index.marko new file mode 100644 index 0000000..225cb90 --- /dev/null +++ b/packages/tsrx/tests/fixtures/tag-member-expression/__snapshots__/index.marko @@ -0,0 +1 @@ +
<${input.content}/>
\ No newline at end of file diff --git a/packages/tsrx/tests/fixtures/tag-member-expression/index.tsrx b/packages/tsrx/tests/fixtures/tag-member-expression/index.tsrx new file mode 100644 index 0000000..4c4d595 --- /dev/null +++ b/packages/tsrx/tests/fixtures/tag-member-expression/index.tsrx @@ -0,0 +1,3 @@ +export default component(input) { +
+}