Allow using the Fragment built-in in Astro components (#793)
* Allow using the Fragment built-in in Astro components * Adds a changeset
This commit is contained in:
parent
ac64d198e4
commit
4a601adbf2
4 changed files with 46 additions and 2 deletions
5
.changeset/flat-apes-pump.md
Normal file
5
.changeset/flat-apes-pump.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
'astro': patch
|
||||
---
|
||||
|
||||
Restores the ability to use Fragment in astro components
|
|
@ -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') {
|
||||
|
|
|
@ -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();
|
||||
|
|
12
packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro
vendored
Normal file
12
packages/astro/test/fixtures/astro-basic/src/pages/fragment.astro
vendored
Normal file
|
@ -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>
|
Loading…
Reference in a new issue