Skip to content

Commit

Permalink
Adds support for handle, links, and loader to mdx
Browse files Browse the repository at this point in the history
  • Loading branch information
TAGraves committed Jul 16, 2022
1 parent f1e94b9 commit 9c91865
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 2 deletions.
7 changes: 6 additions & 1 deletion docs/guides/mdx.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Remix supports using MDX in two ways:

The simplest way to get started with MDX in Remix is to create a route module. Just like `.js` and `.ts` files in your `app/routes` directory, `.mdx` (and `.md`) files will participate in automatic file system based routing.

MDX routes allow you to define both meta and headers as if they were a code based route:
MDX routes allow you to define `meta`, `headers`, `links`, and `handle` as if they were a code based route:

```md
---
Expand All @@ -25,6 +25,9 @@ meta:
description: Isn't this awesome?
headers:
Cache-Control: no-cache
links: [{ rel: "stylesheet", href: "app.css" }]
handle:
someData: "abc"
---

# Hello Content!
Expand All @@ -47,6 +50,8 @@ import SomeComponent from "~/components/some-component";
<SomeComponent {...attributes.componentData} />
```

You can also access your frontmatter fields from a parent component via the `data` field in `useMatches`.

### Example

By creating a `app/routes/posts/first-post.mdx` we can start writing a blog post:
Expand Down
104 changes: 104 additions & 0 deletions integration/mdx-test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { test, expect } from "@playwright/test";

import {
createAppFixture,
createFixture,
js,
mdx,
} from "./helpers/create-fixture";
import type { Fixture, AppFixture } from "./helpers/create-fixture";
import { PlaywrightFixture } from "./helpers/playwright-fixture";

test.describe("mdx", () => {
let fixture: Fixture;
let appFixture: AppFixture;

test.beforeAll(async () => {
fixture = await createFixture({
files: {
"app/root.jsx": js`
import { json } from "@remix-run/node";
import { Links, Meta, Outlet, Scripts } from "@remix-run/react";
export default function Root() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Outlet />
<Scripts />
</body>
</html>
);
}
`,

"app/routes/blog.jsx": js`
import { json } from "@remix-run/node";
import { useMatches, Outlet } from "@remix-run/react";
export default function Index() {
const matches = useMatches();
const mdxMatch = matches[matches.length - 1];
return (
<div>
<p id="additionalData">{mdxMatch.data.additionalData === 10 && 'Additional Data: 10'}</p>
<p id="handle">{mdxMatch.handle.someData}</p>
<Outlet />
</div>
);
}
`,

"app/routes/blog/post.mdx": mdx`---
meta:
title: My First Post
description: Isn't this awesome?
headers:
Cache-Control: no-cache
links: [
{ rel: "stylesheet", href: "app.css" }
]
handle:
someData: "abc"
additionalData: 10
---
# This is some markdown!
`,

"app/routes/basic.mdx": mdx`
# This is some basic markdown!
`,
},
});
appFixture = await createAppFixture(fixture);
});

test.afterAll(async () => {
await appFixture.close();
});

test("can render basic markdown", async ({ page }) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/basic");

expect(await app.getHtml()).toMatch("This is some basic markdown!");
});

test("converts the frontmatter to meta, headers, links, handle, and loader", async ({
page,
}) => {
let app = new PlaywrightFixture(appFixture, page);
await app.goto("/blog/post");
expect(await app.getHtml('meta[name="description"]')).toMatch(
"Isn't this awesome?"
);
expect(await app.getHtml("title")).toMatch("My First Post");
expect(await app.getHtml("#additionalData")).toMatch("Additional Data: 10");
expect(await app.getHtml("#handle")).toMatch("abc");
expect(await app.getHtml('link[rel="stylesheet"]')).toMatch("app.css");
});
});
4 changes: 3 additions & 1 deletion packages/remix-dev/compiler/plugins/mdx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ export function mdxPlugin(config: RemixConfig): esbuild.Plugin {
export const filename = ${JSON.stringify(path.basename(args.path))};
export const headers = typeof attributes !== "undefined" && attributes.headers;
export const meta = typeof attributes !== "undefined" && attributes.meta;
export const links = undefined;
export const handle = typeof attributes !== "undefined" && attributes.handle;
export const links = typeof attributes === "undefined" ? undefined : () => attributes.links;
export const loader = typeof attributes === "undefined" ? undefined : () => attributes;
`;

let compiled = await xdm.compile(fileContents, {
Expand Down

0 comments on commit 9c91865

Please sign in to comment.