From ae49f2a035a1329e37fb741bbb97a320e4151532 Mon Sep 17 00:00:00 2001 From: Tommy Graves Date: Fri, 15 Jul 2022 22:47:22 -0400 Subject: [PATCH 1/3] feat(remix-dev): add support for handle, links, and loader to mdx --- contributors.yml | 1 + docs/guides/mdx.md | 7 +- integration/mdx-test.ts | 104 +++++++++++++++++++++ packages/remix-dev/compiler/plugins/mdx.ts | 4 +- 4 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 integration/mdx-test.ts diff --git a/contributors.yml b/contributors.yml index 26d5859dd9e..e4f12650499 100644 --- a/contributors.yml +++ b/contributors.yml @@ -394,3 +394,4 @@ - zhe - garand - kiancross +- tagraves diff --git a/docs/guides/mdx.md b/docs/guides/mdx.md index 4f6c70bad36..975a4558826 100644 --- a/docs/guides/mdx.md +++ b/docs/guides/mdx.md @@ -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 --- @@ -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! @@ -47,6 +50,8 @@ import SomeComponent from "~/components/some-component"; ``` +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: diff --git a/integration/mdx-test.ts b/integration/mdx-test.ts new file mode 100644 index 00000000000..29124d4252e --- /dev/null +++ b/integration/mdx-test.ts @@ -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 ( + + + + + + + + + + + ); + } + `, + + "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 ( +
+

{mdxMatch.data.additionalData === 10 && 'Additional Data: 10'}

+

{mdxMatch.handle.someData}

+ +
+ ); + } + `, + + "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"); + }); +}); diff --git a/packages/remix-dev/compiler/plugins/mdx.ts b/packages/remix-dev/compiler/plugins/mdx.ts index 9ed7d16c5a4..2cc1d91839b 100644 --- a/packages/remix-dev/compiler/plugins/mdx.ts +++ b/packages/remix-dev/compiler/plugins/mdx.ts @@ -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, { From dedc635f526f65c4ccb7b82e4f45f3379b1a3f17 Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Sat, 16 Jul 2022 07:56:46 -0600 Subject: [PATCH 2/3] Create tender-impalas-invite.md --- .changeset/tender-impalas-invite.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/tender-impalas-invite.md diff --git a/.changeset/tender-impalas-invite.md b/.changeset/tender-impalas-invite.md new file mode 100644 index 00000000000..0d4e5456959 --- /dev/null +++ b/.changeset/tender-impalas-invite.md @@ -0,0 +1,6 @@ +--- +"remix": patch +"@remix-run/dev": patch +--- + +Adds support for handle, links, and loader to mdx routes From cea4a3ec2b149ae03f7ec00abd79b115ec225b2e Mon Sep 17 00:00:00 2001 From: "Kent C. Dodds" Date: Sat, 16 Jul 2022 07:57:07 -0600 Subject: [PATCH 3/3] Update docs/guides/mdx.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michaƫl De Boey --- docs/guides/mdx.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/mdx.md b/docs/guides/mdx.md index 975a4558826..dd9da49525d 100644 --- a/docs/guides/mdx.md +++ b/docs/guides/mdx.md @@ -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 `meta`, `headers`, `links`, and `handle` as if they were a code based route: +MDX routes allow you to define `handle`, `headers`, `links`, and `meta` as if they were a code based route: ```md ---