Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MDX] Add headings and frontmatter to layout props #4134

Merged
merged 4 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/hip-glasses-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@astrojs/mdx': minor
---

Add `headings` and `frontmatter` properties to layout props
4 changes: 2 additions & 2 deletions packages/integrations/mdx/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ export default function mdx(mdxOptions: MdxOptions = {}): AstroIntegration {
const { layout, ...content } = frontmatter;
code += `\nexport default async function({ children }) {\nconst Layout = (await import(${JSON.stringify(
frontmatter.layout
)})).default;\nreturn <Layout content={${JSON.stringify(
)})).default;\nconst frontmatter=${JSON.stringify(
content
)}}>{children}</Layout> }`;
)};\nreturn <Layout frontmatter={frontmatter} content={frontmatter} headings={getHeadings()}>{children}</Layout> }`;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
---
const { content = { title: "Didn't work" } } = Astro.props;
const {
content = { title: "content didn't work" },
frontmatter = { title: "frontmatter didn't work" },
headings = [],
} = 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>{content.title}</title>
</head>

<body>
<h1>{content.title}</h1>
<p data-content-title>{content.title}</p>
<p data-frontmatter-title>{frontmatter.title}</p>
<p data-layout-rendered>Layout rendered!</p>
<ul data-headings>
{headings.map(heading => <li>{heading.slug}</li>)}
</ul>
<slot />
</body>

</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
layout: '../layouts/Base.astro'
---

## Section 1

## Section 2
51 changes: 25 additions & 26 deletions packages/integrations/mdx/test/mdx-frontmatter.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,24 @@ import { loadFixture } from '../../../astro/test/test-utils.js';
const FIXTURE_ROOT = new URL('./fixtures/mdx-frontmatter/', import.meta.url);

describe('MDX frontmatter', () => {
it('builds when "frontmatter.property" is in JSX expression', async () => {
const fixture = await loadFixture({
let fixture;
before(async () => {
fixture = await loadFixture({
root: FIXTURE_ROOT,
integrations: [mdx()],
});
await fixture.build();
})
it('builds when "frontmatter.property" is in JSX expression', async () => {
expect(true).to.equal(true);
});

it('extracts frontmatter to "frontmatter" export', async () => {
const fixture = await loadFixture({
root: FIXTURE_ROOT,
integrations: [mdx()],
});
await fixture.build();

const { titles } = JSON.parse(await fixture.readFile('/glob.json'));
expect(titles).to.include('Using YAML frontmatter');
});

it('renders layout from "layout" frontmatter property', async () => {
const fixture = await loadFixture({
root: FIXTURE_ROOT,
integrations: [mdx()],
});
await fixture.build();

const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);

Expand All @@ -42,23 +33,31 @@ describe('MDX frontmatter', () => {
expect(layoutParagraph).to.not.be.null;
});

it('passes frontmatter to layout via "content" prop', async () => {
const fixture = await loadFixture({
root: FIXTURE_ROOT,
integrations: [mdx()],
});
await fixture.build();

it('passes frontmatter to layout via "content" and "frontmatter" props', async () => {
const html = await fixture.readFile('/index.html');
const { document } = parseHTML(html);

const h1 = document.querySelector('h1');
const contentTitle = document.querySelector('[data-content-title]');
const frontmatterTitle = document.querySelector('[data-frontmatter-title]');

expect(contentTitle.textContent).to.equal('Using YAML frontmatter');
expect(frontmatterTitle.textContent).to.equal('Using YAML frontmatter');
});

it('passes headings to layout via "headings" prop', async () => {
const html = await fixture.readFile('/with-headings/index.html');
const { document } = parseHTML(html);

const headingSlugs = [...document.querySelectorAll('[data-headings] > li')]
.map(el => el.textContent);

expect(h1.textContent).to.equal('Using YAML frontmatter');
expect(headingSlugs.length).to.be.greaterThan(0);
expect(headingSlugs).to.contain('section-1');
expect(headingSlugs).to.contain('section-2');
});

it('extracts frontmatter to "customFrontmatter" export when configured', async () => {
const fixture = await loadFixture({
const customFixture = await loadFixture({
root: new URL('./fixtures/mdx-custom-frontmatter-name/', import.meta.url),
integrations: [
mdx({
Expand All @@ -68,9 +67,9 @@ describe('MDX frontmatter', () => {
}),
],
});
await fixture.build();
await customFixture.build();

const { titles } = JSON.parse(await fixture.readFile('/glob.json'));
const { titles } = JSON.parse(await customFixture.readFile('/glob.json'));
expect(titles).to.include('Using YAML frontmatter');
});
});