summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.changeset/flat-apes-pump.md5
-rw-r--r--packages/astro/src/compiler/codegen/index.ts23
-rw-r--r--packages/astro/test/astro-basic.test.js8
-rw-r--r--packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro12
4 files changed, 46 insertions, 2 deletions
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<string> {
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 @@
+<html lang="en">
+<head>
+ <title>Fragment test</title>
+</head>
+<body>
+<ul>
+<Fragment>
+ <li id="one">One</li>
+</Fragment>
+</ul>
+</body>
+</html> \ No newline at end of file