')
+ expect(html).toContain('[Outer]')
+ })
+})
diff --git a/packages/comark/src/internal/stringify/state.ts b/packages/comark/src/internal/stringify/state.ts
index a18612d4..1cad594e 100644
--- a/packages/comark/src/internal/stringify/state.ts
+++ b/packages/comark/src/internal/stringify/state.ts
@@ -58,12 +58,22 @@ export async function one(node: Node, state: State, parent?: ElementNode, atLine
// element's values, regardless of which handler (html / ansi / user) runs.
// Elements with no attributes (e.g. an auto-generated `` wrapper) must
// NOT shadow the parent's scope, otherwise `{{ props.* }}` inside them would
- // resolve to nothing.
+ // resolve to nothing. The check uses the raw attributes, because resolving
+ // can drop all of them and the parent's props must not leak back in.
const prevRenderData = state.renderData
if (state.renderData && node[1]) {
- const resolved = resolveAttributes(node[1] as Record, prevRenderData)
- if (Object.keys(resolved).length > 0) {
- state.renderData = { ...prevRenderData, props: resolved }
+ let hasOwnAttrs = false
+ for (const key in node[1]) {
+ if (key !== '$') {
+ hasOwnAttrs = true
+ break
+ }
+ }
+ if (hasOwnAttrs) {
+ state.renderData = {
+ ...prevRenderData,
+ props: resolveAttributes(node[1] as Record, prevRenderData),
+ }
}
}
diff --git a/test/bundle.test.ts b/test/bundle.test.ts
index fd08d983..a1b7a4e0 100644
--- a/test/bundle.test.ts
+++ b/test/bundle.test.ts
@@ -60,13 +60,13 @@ describe('package bundle size', { timeout: 60_000 }, () => {
expect(report).toMatchInlineSnapshot(`
{
- "@comark/angular": "56.2k (72 files)",
+ "@comark/angular": "56.5k (72 files)",
"@comark/ansi": "37.3k (98 files)",
"@comark/html": "16.5k (58 files)",
"@comark/nuxt": "11.9k (58 files)",
- "@comark/react": "38.5k (76 files)",
- "@comark/svelte": "46.5k (84 files)",
- "@comark/vue": "56.2k (80 files)",
+ "@comark/react": "38.6k (76 files)",
+ "@comark/svelte": "46.8k (84 files)",
+ "@comark/vue": "56.4k (80 files)",
"comark": "385k (152 files)",
}
`)