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']);
|
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 */
|
/** Compile page markup */
|
||||||
async function compileHtml(enterNode: TemplateNode, state: CodegenState, compileOptions: CompileOptions): Promise<string> {
|
async function compileHtml(enterNode: TemplateNode, state: CodegenState, compileOptions: CompileOptions): Promise<string> {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
|
@ -658,7 +669,12 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile
|
||||||
const [componentNamespace] = componentName.split('.');
|
const [componentNamespace] = componentName.split('.');
|
||||||
componentInfo = components.get(componentNamespace);
|
componentInfo = components.get(componentNamespace);
|
||||||
}
|
}
|
||||||
if (state.declarations.has(componentName) && !componentInfo && !isCustomElementTag(componentName)) {
|
if (
|
||||||
|
(
|
||||||
|
isFrontmatterDefinedComponent(componentName, componentInfo, state) &&
|
||||||
|
!isCustomElementTag(componentName)
|
||||||
|
) || isFragmentComponent(componentName)
|
||||||
|
) {
|
||||||
if (hydrationAttributes.method) {
|
if (hydrationAttributes.method) {
|
||||||
throw new Error(
|
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.`
|
`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'}`;
|
buffers[curr] += `h(${componentName}, ${attributes ? generateAttributes(attributes) : 'null'}`;
|
||||||
paren++;
|
paren++;
|
||||||
return;
|
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}`);
|
throw new Error(`Unable to render "${componentName}" because it is undefined\n ${state.filename}`);
|
||||||
}
|
}
|
||||||
if (componentName === 'Markdown') {
|
if (componentName === 'Markdown') {
|
||||||
|
|
|
@ -95,4 +95,12 @@ Basics('Allows spread attributes with TypeScript (#521)', async ({ runtime }) =>
|
||||||
assert.equal($('#spread-ts').attr('c'), '2');
|
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();
|
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…
Add table
Reference in a new issue