Add support for components defined in frontmatter (#637)

* fix: add support for components defined in frontmatter

* chore: add changeset

* test: update test to match example use case
This commit is contained in:
Nate Moore 2021-07-08 16:47:23 -05:00 committed by GitHub
parent b4f145a0e7
commit 42a6acee28
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 1 deletions

View file

@ -0,0 +1,14 @@
---
'astro': patch
---
Add support for components defined in Frontmatter. Previously, the following code would throw an error. Now it is officially supported!
```astro
---
const { level = 1 } = Astro.props;
const Element = `h${level}`;
---
<Element>Hello world!</Element>
```

View file

@ -688,7 +688,21 @@ async function compileHtml(enterNode: TemplateNode, state: CodegenState, compile
componentInfo = components.get(componentNamespace); componentInfo = components.get(componentNamespace);
} }
if (!componentInfo && !isCustomElementTag(componentName)) { if (!componentInfo && !isCustomElementTag(componentName)) {
throw new Error(`Unknown Component: ${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.`);
}
// Previously we would throw here, but this is valid!
// If the frontmatter script defines `const Element = 'h1'`,
// you should be able to statically render `<Element>`
if (curr === 'markdown') {
await pushMarkdownToBuffer();
}
paren++;
buffers[curr] += `h(${componentName}, ${attributes ? generateAttributes(attributes) : 'null'}`;
return;
} }
if (componentName === 'Markdown') { if (componentName === 'Markdown') {
const { $scope } = attributes ?? {}; const { $scope } = attributes ?? {};

View file

@ -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 Components defined in frontmatter', async ({ runtime }) => {
const result = await runtime.load('/frontmatter-component');
const html = result.contents;
const $ = doc(html);
assert.equal($('h1').length, 1);
});
Basics.run(); Basics.run();

View file

@ -0,0 +1,6 @@
---
const { level = 1 } = Astro.props;
const Element = `h${level}`;
---
<Element>Hello world!</Element>