From 4a601adbf2ca40d813336b57d76a6736fa8ee2d0 Mon Sep 17 00:00:00 2001 From: Matthew Phillips Date: Wed, 21 Jul 2021 12:26:52 -0400 Subject: [PATCH] Allow using the Fragment built-in in Astro components (#793) * Allow using the Fragment built-in in Astro components * Adds a changeset --- .changeset/flat-apes-pump.md | 5 ++++ packages/astro/src/compiler/codegen/index.ts | 23 +++++++++++++++++-- packages/astro/test/astro-basic.test.js | 8 +++++++ .../astro-basic/src/pages/fragment.astro | 12 ++++++++++ 4 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 .changeset/flat-apes-pump.md create mode 100644 packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro diff --git a/.changeset/flat-apes-pump.md b/.changeset/flat-apes-pump.md new file mode 100644 index 000000000..457fa9677 --- /dev/null +++ b/.changeset/flat-apes-pump.md @@ -0,0 +1,5 @@ +--- +'astro': patch +--- + +Restores the ability to use Fragment in astro components diff --git a/packages/astro/src/compiler/codegen/index.ts b/packages/astro/src/compiler/codegen/index.ts index 233f2985f..3e0e4a35b 100644 --- a/packages/astro/src/compiler/codegen/index.ts +++ b/packages/astro/src/compiler/codegen/index.ts @@ -517,6 +517,17 @@ function dedent(str: string) { const FALSY_EXPRESSIONS = new Set(['false', 'null', 'undefined', 'void 0']); +function isFrontmatterDefinedComponent(componentName: string, componentInfo: ComponentInfo | undefined, state: CodegenState) { + let hasVariableDeclaration = state.declarations.has(componentName); + let isNotImported = !componentInfo; + + return hasVariableDeclaration && isNotImported; +} + +function isFragmentComponent(componentName: string) { + return componentName === 'Fragment'; +} + /** Compile page markup */ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compileOptions: CompileOptions): Promise { return new Promise((resolve) => { @@ -658,7 +669,12 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile const [componentNamespace] = componentName.split('.'); componentInfo = components.get(componentNamespace); } - if (state.declarations.has(componentName) && !componentInfo && !isCustomElementTag(componentName)) { + if ( + ( + isFrontmatterDefinedComponent(componentName, componentInfo, state) && + !isCustomElementTag(componentName) + ) || isFragmentComponent(componentName) + ) { if (hydrationAttributes.method) { throw new Error( `Unable to hydrate "${componentName}" because it is statically defined in the frontmatter script. Hydration directives may only be used on imported components.` @@ -681,7 +697,10 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile buffers[curr] += `h(${componentName}, ${attributes ? generateAttributes(attributes) : 'null'}`; paren++; return; - } else if (!state.declarations.has(componentName) && !componentInfo && !isCustomElementTag(componentName)) { + } else if ( + !componentInfo && + !isCustomElementTag(componentName) + ) { throw new Error(`Unable to render "${componentName}" because it is undefined\n ${state.filename}`); } if (componentName === 'Markdown') { diff --git a/packages/astro/test/astro-basic.test.js b/packages/astro/test/astro-basic.test.js index 87dcc84f4..ad52bb48b 100644 --- a/packages/astro/test/astro-basic.test.js +++ b/packages/astro/test/astro-basic.test.js @@ -95,4 +95,12 @@ Basics('Allows spread attributes with TypeScript (#521)', async ({ runtime }) => assert.equal($('#spread-ts').attr('c'), '2'); }); +Basics('Allows using the Fragment element to be used', async ({ runtime }) => { + const result = await runtime.load('/fragment'); + assert.ok(!result.error, 'No errors thrown'); + const html = result.contents; + const $ = doc(html); + assert.equal($('#one').length, 1, 'Element in a fragment rendered'); +}); + Basics.run(); diff --git a/packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro b/packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro new file mode 100644 index 000000000..65fd85bf6 --- /dev/null +++ b/packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro @@ -0,0 +1,12 @@ + + + Fragment test + + + + + \ No newline at end of file