summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Ben Holmes <hey@bholmes.dev> 2022-08-11 12:36:34 -0500
committerGravatar GitHub <noreply@github.com> 2022-08-11 12:36:34 -0500
commit4116128082121ee276d51cb245bf8095be4728a1 (patch)
treecf5b82544feb3597443c2fb3bc4e164ed5a1c932
parent5afb5ef7af95f9245c1010d35aaf508d4989cb4a (diff)
downloadastro-4116128082121ee276d51cb245bf8095be4728a1.tar.gz
astro-4116128082121ee276d51cb245bf8095be4728a1.tar.zst
astro-4116128082121ee276d51cb245bf8095be4728a1.zip
[MDX] Pass injected frontmatter to layouts (#4255)
* fix: move layout generation to remark plugin * test: frontmatter injection in layout * chore: changeset * fix: remove content fallback
-rw-r--r--.changeset/tasty-masks-draw.md5
-rw-r--r--packages/integrations/mdx/src/astro-data-utils.ts36
-rw-r--r--packages/integrations/mdx/src/index.ts11
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/layouts/Base.astro17
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-1.mdx4
-rw-r--r--packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-2.mdx4
-rw-r--r--packages/integrations/mdx/test/mdx-frontmatter-injection.test.js12
7 files changed, 79 insertions, 10 deletions
diff --git a/.changeset/tasty-masks-draw.md b/.changeset/tasty-masks-draw.md
new file mode 100644
index 000000000..790cac151
--- /dev/null
+++ b/.changeset/tasty-masks-draw.md
@@ -0,0 +1,5 @@
+---
+'@astrojs/mdx': patch
+---
+
+Pass injected frontmatter from remark and rehype plugins to layouts
diff --git a/packages/integrations/mdx/src/astro-data-utils.ts b/packages/integrations/mdx/src/astro-data-utils.ts
index fdad15b8f..0bc375c27 100644
--- a/packages/integrations/mdx/src/astro-data-utils.ts
+++ b/packages/integrations/mdx/src/astro-data-utils.ts
@@ -19,6 +19,42 @@ export function rehypeApplyFrontmatterExport(pageFrontmatter: Record<string, any
const exportNodes = [
jsToTreeNode(`export const ${EXPORT_NAME} = ${JSON.stringify(frontmatter)};`),
];
+ if (frontmatter.layout) {
+ exportNodes.unshift(
+ jsToTreeNode(
+ /** @see 'vite-plugin-markdown' for layout props reference */
+ `import { jsx as layoutJsx } from 'astro/jsx-runtime';
+ import Layout from ${JSON.stringify(frontmatter.layout)};
+
+ export default function ({ children }) {
+ const { layout, ...content } = frontmatter;
+ content.astro = {};
+ Object.defineProperty(content.astro, 'headings', {
+ get() {
+ throw new Error('The "astro" property is no longer supported! To access "headings" from your layout, try using "Astro.props.headings."')
+ }
+ });
+ Object.defineProperty(content.astro, 'html', {
+ get() {
+ throw new Error('The "astro" property is no longer supported! To access "html" from your layout, try using "Astro.props.compiledContent()."')
+ }
+ });
+ Object.defineProperty(content.astro, 'source', {
+ get() {
+ throw new Error('The "astro" property is no longer supported! To access "source" from your layout, try using "Astro.props.rawContent()."')
+ }
+ });
+ return layoutJsx(Layout, {
+ content,
+ frontmatter: content,
+ headings: getHeadings(),
+ 'server:root': true,
+ children,
+ });
+ };`
+ )
+ );
+ }
tree.children = exportNodes.concat(tree.children);
};
}
diff --git a/packages/integrations/mdx/src/index.ts b/packages/integrations/mdx/src/index.ts
index 05b803705..f92a10a53 100644
--- a/packages/integrations/mdx/src/index.ts
+++ b/packages/integrations/mdx/src/index.ts
@@ -98,16 +98,7 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
async transform(code, id) {
if (!id.endsWith('mdx')) return;
- let { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
- if (frontmatter.layout) {
- const { layout, ...contentProp } = frontmatter;
- pageContent += `\n\nexport default async function({ children }) {\nconst Layout = (await import(${JSON.stringify(
- frontmatter.layout
- )})).default;\nconst frontmatter=${JSON.stringify(
- contentProp
- )};\nreturn <Layout frontmatter={frontmatter} content={frontmatter} headings={getHeadings()}>{children}</Layout> }`;
- }
-
+ const { data: frontmatter, content: pageContent } = parseFrontmatter(code, id);
const compiled = await mdxCompile(new VFile({ value: pageContent, path: id }), {
...mdxPluginOpts,
rehypePlugins: [
diff --git a/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/layouts/Base.astro b/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/layouts/Base.astro
new file mode 100644
index 000000000..b3d55f0a8
--- /dev/null
+++ b/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/layouts/Base.astro
@@ -0,0 +1,17 @@
+---
+const defaults = { title: 'Frontmatter not passed to layout!' }
+const { frontmatter = defaults, content = defaults } = Astro.props;
+---
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{frontmatter.title}</title>
+</head>
+<body>
+ <slot />
+</body>
+</html>
diff --git a/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-1.mdx b/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-1.mdx
index 2fcd655ec..1092099f0 100644
--- a/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-1.mdx
+++ b/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-1.mdx
@@ -1,3 +1,7 @@
+---
+layout: '../layouts/Base.astro'
+---
+
# Page 1
Look at that!
diff --git a/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-2.mdx b/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-2.mdx
index 4a6b9addd..c82eb97c2 100644
--- a/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-2.mdx
+++ b/packages/integrations/mdx/test/fixtures/mdx-frontmatter-injection/src/pages/page-2.mdx
@@ -1,3 +1,7 @@
+---
+layout: '../layouts/Base.astro'
+---
+
# Page 2
## Table of contents
diff --git a/packages/integrations/mdx/test/mdx-frontmatter-injection.test.js b/packages/integrations/mdx/test/mdx-frontmatter-injection.test.js
index 420e4716e..780f7252c 100644
--- a/packages/integrations/mdx/test/mdx-frontmatter-injection.test.js
+++ b/packages/integrations/mdx/test/mdx-frontmatter-injection.test.js
@@ -1,4 +1,5 @@
import { expect } from 'chai';
+import { parseHTML } from 'linkedom';
import { loadFixture } from '../../../astro/test/test-utils.js';
const FIXTURE_ROOT = new URL('./fixtures/mdx-frontmatter-injection/', import.meta.url);
@@ -41,4 +42,15 @@ describe('MDX frontmatter injection', () => {
expect(titles).to.contain('Overridden title');
expect(readingTimes).to.contain('1000 min read');
});
+
+ it('passes injected frontmatter to layouts', async () => {
+ const html1 = await fixture.readFile('/page-1/index.html');
+ const html2 = await fixture.readFile('/page-2/index.html');
+
+ const title1 = parseHTML(html1).document.querySelector('title');
+ const title2 = parseHTML(html2).document.querySelector('title');
+
+ expect(title1.innerHTML).to.equal('Page 1');
+ expect(title2.innerHTML).to.equal('Page 2');
+ });
});