diff --git a/src/frontend/render/utils.ts b/src/frontend/render/utils.ts index 2a1cc9ecf6..9d55626fe1 100644 --- a/src/frontend/render/utils.ts +++ b/src/frontend/render/utils.ts @@ -16,7 +16,10 @@ function childrenToTree(children: string[]) { */ export const childrenToVnodes = moize.deep(function childrenToVnodes(h: any, children: string[]) { const tree = childrenToTree(children); - const vnodes = tree.map((subtree) => toH(h, subtree)); + const vnodes = tree.map((subtree) => { + if (subtree.type === 'text') return subtree.value; + return toH(h, subtree); + }); return vnodes; }); @@ -37,11 +40,13 @@ export const childrenToH = moize.deep(function childrenToH(renderer: ComponentRe return { ...vnode, __SERIALIZED }; }; const serializeChild = (child: unknown) => { - if (typeof child === 'string') return `\`${child}\``; - if (typeof child === 'number' || typeof child === 'boolean') return `${child}`; + if (['string', 'number', 'boolean'].includes(typeof child)) return JSON.stringify(child); if (child === null) return `null`; if ((child as any).__SERIALIZED) return (child as any).__SERIALIZED; return innerH(child).__SERIALIZED; }; - return tree.map((subtree) => toH(innerH, subtree).__SERIALIZED); + return tree.map((subtree) => { + if (subtree.type === 'text') return JSON.stringify(subtree.value); + return toH(innerH, subtree).__SERIALIZED + }); }); diff --git a/test/astro-children.test.js b/test/astro-children.test.js new file mode 100644 index 0000000000..368cfc9f9d --- /dev/null +++ b/test/astro-children.test.js @@ -0,0 +1,75 @@ +import { suite } from 'uvu'; +import * as assert from 'uvu/assert'; +import { doc } from './test-utils.js'; +import { setup, setupBuild } from './helpers.js'; + +const ComponentChildren = suite('Component children tests'); + +setup(ComponentChildren, './fixtures/astro-children'); +setupBuild(ComponentChildren, './fixtures/astro-children'); + +ComponentChildren('Passes string children to framework components', async ({ runtime }) => { + let result = await runtime.load('/strings'); + + assert.equal(result.statusCode, 200); + const $ = doc(result.contents); + + const $preact = $('#preact'); + assert.equal($preact.text().trim(), 'Hello world', 'Can pass text to Preact components'); + + const $vue = $('#vue'); + assert.equal($vue.text().trim(), 'Hello world', 'Can pass text to Vue components'); + + const $svelte = $('#svelte'); + assert.equal($svelte.text().trim(), 'Hello world', 'Can pass text to Svelte components'); +}); + +ComponentChildren('Passes markup children to framework components', async ({ runtime }) => { + let result = await runtime.load('/markup'); + + assert.equal(result.statusCode, 200); + const $ = doc(result.contents); + + const $preact = $('#preact > h1'); + assert.equal($preact.text().trim(), 'Hello world', 'Can pass markup to Preact components'); + + const $vue = $('#vue > h1'); + assert.equal($vue.text().trim(), 'Hello world', 'Can pass markup to Vue components'); + + const $svelte = $('#svelte > h1'); + assert.equal($svelte.text().trim(), 'Hello world', 'Can pass markup to Svelte components'); +}); + +ComponentChildren('Passes multiple children to framework components', async ({ runtime }) => { + let result = await runtime.load('/multiple'); + + assert.equal(result.statusCode, 200); + const $ = doc(result.contents); + + const $preact = $('#preact'); + assert.equal($preact.children().length, 2, 'Can pass multiple children to Preact components'); + assert.equal($preact.children(':first-child').text().trim(), 'Hello world'); + assert.equal($preact.children(':last-child').text().trim(), 'Goodbye world'); + + const $vue = $('#vue'); + assert.equal($vue.children().length, 2, 'Can pass multiple children to Vue components'); + assert.equal($vue.children(':first-child').text().trim(), 'Hello world'); + assert.equal($vue.children(':last-child').text().trim(), 'Goodbye world'); + + const $svelte = $('#svelte'); + assert.equal($svelte.children().length, 2, 'Can pass multiple children to Svelte components'); + assert.equal($svelte.children(':first-child').text().trim(), 'Hello world'); + assert.equal($svelte.children(':last-child').text().trim(), 'Goodbye world'); +}); + +ComponentChildren('Can be built', async ({ build }) => { + try { + await build(); + assert.ok(true, 'Can build a project with component children'); + } catch (err) { + console.log(err); + assert.ok(false, 'build threw'); + } +}); + +ComponentChildren.run(); diff --git a/test/fixtures/astro-children/astro.config.mjs b/test/fixtures/astro-children/astro.config.mjs new file mode 100644 index 0000000000..e2a209f838 --- /dev/null +++ b/test/fixtures/astro-children/astro.config.mjs @@ -0,0 +1,5 @@ +export default { + extensions: { + '.jsx': 'preact' + }, +}; diff --git a/test/fixtures/astro-children/src/components/Component.jsx b/test/fixtures/astro-children/src/components/Component.jsx new file mode 100644 index 0000000000..bf9280f861 --- /dev/null +++ b/test/fixtures/astro-children/src/components/Component.jsx @@ -0,0 +1,5 @@ +import { h } from 'preact'; + +export default function PreactComponent({ children }) { + return
{children}
+} diff --git a/test/fixtures/astro-children/src/components/Component.svelte b/test/fixtures/astro-children/src/components/Component.svelte new file mode 100644 index 0000000000..4276a78b80 --- /dev/null +++ b/test/fixtures/astro-children/src/components/Component.svelte @@ -0,0 +1,3 @@ +
+ +
diff --git a/test/fixtures/astro-children/src/components/Component.vue b/test/fixtures/astro-children/src/components/Component.vue new file mode 100644 index 0000000000..22e6e11433 --- /dev/null +++ b/test/fixtures/astro-children/src/components/Component.vue @@ -0,0 +1,9 @@ + + + diff --git a/test/fixtures/astro-children/src/pages/markup.astro b/test/fixtures/astro-children/src/pages/markup.astro new file mode 100644 index 0000000000..b771c24335 --- /dev/null +++ b/test/fixtures/astro-children/src/pages/markup.astro @@ -0,0 +1,21 @@ +--- +import PreactComponent from '../components/Component.jsx'; +import VueComponent from '../components/Component.vue'; +import SvelteComponent from '../components/Component.svelte'; +--- + +Children + + +

Hello world

+
+ + +

Hello world

+
+ + +

Hello world

+
+ + diff --git a/test/fixtures/astro-children/src/pages/multiple.astro b/test/fixtures/astro-children/src/pages/multiple.astro new file mode 100644 index 0000000000..8c2f73a91e --- /dev/null +++ b/test/fixtures/astro-children/src/pages/multiple.astro @@ -0,0 +1,24 @@ +--- +import PreactComponent from '../components/Component.jsx'; +import VueComponent from '../components/Component.vue'; +import SvelteComponent from '../components/Component.svelte'; +--- + +Children + + +

Hello world

+

Goodbye world

+
+ + +

Hello world

+

Goodbye world

+
+ + +

Hello world

+

Goodbye world

+
+ + diff --git a/test/fixtures/astro-children/src/pages/strings.astro b/test/fixtures/astro-children/src/pages/strings.astro new file mode 100644 index 0000000000..10b1a887fc --- /dev/null +++ b/test/fixtures/astro-children/src/pages/strings.astro @@ -0,0 +1,21 @@ +--- +import PreactComponent from '../components/Component.jsx'; +import VueComponent from '../components/Component.vue'; +import SvelteComponent from '../components/Component.svelte'; +--- + +Children + + + Hello world + + + + Hello world + + + + Hello world + + +