Skip to content
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
7 changes: 5 additions & 2 deletions e2e-tests/mdx/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,18 @@ module.exports = {
},
},
`gatsby-plugin-test-regression1`,
`gatsby-plugin-sharp`,
{
resolve: `gatsby-plugin-mdx`,
options: {
lessBabel: false,
extensions: [`.mdx`, `.md`],
defaultLayouts: {
default: require.resolve("./src/components/layout.js"),
},
remarkPlugins: [remarkRequireFilePathPlugin],
gatsbyRemarkPlugins: [`gatsby-remark-images`],
mdxOptions: {
remarkPlugins: [remarkRequireFilePathPlugin],
},
},
},
!process.env.CI && `gatsby-plugin-webpack-bundle-analyser-v2`,
Expand Down
2 changes: 2 additions & 0 deletions e2e-tests/mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"fs-extra": "^8.1.0",
"gatsby": "^4.0.0",
"gatsby-plugin-mdx": "^3.0.0",
"gatsby-plugin-sharp": "^4.0.0",
"gatsby-plugin-webpack-bundle-analyser-v2": "^1.1.27",
"gatsby-remark-images": "^6.15.0",
"gatsby-source-filesystem": "^4.0.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
Expand Down
Binary file added e2e-tests/mdx/src/pages/gatsby-logo.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 12 additions & 2 deletions e2e-tests/mdx/src/pages/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,16 @@ Let's go MDX!
const codefence = true
```

<Example/>
<Example />

<Message data-testid="external">Now an external import</Message>
<Message data-testid="external">Now an external import</Message>

### An image:

![Alt text here](./gatsby-logo.png)

### HTML

<div data-something="important-information">
<strong>This is a test</strong>
</div>
8 changes: 5 additions & 3 deletions packages/gatsby-plugin-mdx/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,17 @@
"testEnvironment": "node"
},
"dependencies": {
"@mdx-js/loader": "^2.1.1",
"@mdx-js/mdx": "^2.1.1",
"change-case": "^4.1.2",
"deepmerge": "^4.2.2",
"fs-extra": "^10.1.0",
"gatsby-plugin-utils": "^3.9.0-next.2",
"gray-matter": "^4.0.3",
"mdast-util-from-markdown": "^1.2.0",
"mdast-util-mdx": "^2.0.0",
"mdast-util-to-markdown": "^1.3.0",
"micromark-extension-mdxjs": "^1.0.0"
"unified": "^10.1.2",
"unist-util-visit": "^4.1.0",
"vfile": "^5.3.2"
},
"devDependencies": {
"babel-preset-gatsby-package": "2.15.0-next.0",
Expand Down
27 changes: 27 additions & 0 deletions packages/gatsby-plugin-mdx/src/compile-mdx.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import type { ProcessorOptions } from "@mdx-js/mdx"
import type { IFileNode, IMdxNode } from "./types"

// Compiles MDX into JS
// This could be replaced by @mdx-js/mdx if MDX compile would
// accept custom data passed to the unified pipeline via processor.data()
export default async function compileMDX(
source: string,
mdxNode: IMdxNode,
fileNode: IFileNode,
options: ProcessorOptions
): Promise<string> {
const { createProcessor } = await import(`@mdx-js/mdx`)
const { VFile } = await import(`vfile`)

const processor = createProcessor(options)

// If we could pass this via MDX loader config, this whole custom loader might be obsolete.
processor.data(`mdxNode`, mdxNode)

const result = await processor.process(
// Inject path to original file for remark plugins. See: https://github.com/gatsbyjs/gatsby/issues/26914
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really still need that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I look at https://unifiedjs.com/learn/guide/create-a-plugin/ the file as a second argument is still there. So there will be remark plugins that rely on that.

Isn't the official loader also doing this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@axe312ger then we'll need to update our test later

new VFile({ value: source, path: fileNode.absolutePath })
)

return result.toString()
}
Original file line number Diff line number Diff line change
@@ -1,41 +1,34 @@
/* eslint-disable @babel/no-invalid-this */
import type { Node } from "gatsby"
import type { LoaderDefinition } from "webpack"
import type { Options } from "mdast-util-to-markdown"
import type { NodeMap } from "./types"
import type { IMdxPluginOptions } from "./plugin-options"

import grayMatter from "gray-matter"
import { getOptions } from "loader-utils"
import type { Options } from "mdast-util-to-markdown"

import { defaultOptions, IMdxPluginOptions } from "./plugin-options"

interface IFileNode extends Node {
sourceInstanceName: string
export interface IGatsbyLayoutLoaderOptions {
options: IMdxPluginOptions
nodeMap: NodeMap
}

export interface IMdxLoaderOptions {
pluginOptions: IMdxPluginOptions
fileMap: Map<string, IFileNode>
}

// Wrap MDX content with Gatsby Layout component and inject components from `@mdx-js/react`
const gatsbyMdxLoader: LoaderDefinition = async function (source) {
const { pluginOptions, fileMap }: IMdxLoaderOptions = getOptions(this)

const options = defaultOptions(pluginOptions)
// Wrap MDX content with Gatsby Layout component
const gatsbyLayoutLoader: LoaderDefinition = async function (source) {
const { options, nodeMap }: IGatsbyLayoutLoaderOptions = getOptions(this)

const fileNode = fileMap.get(this.resourcePath)
const res = nodeMap.get(this.resourcePath)

if (!fileNode) {
if (!res) {
throw new Error(
`Unable to locate GraphQL File node for ${this.resourcePath}`
)
}

// get the default layout for the file source group, or if it doesn't
// exist, the overall default layout
const layoutPath =
options.defaultLayouts[fileNode.sourceInstanceName] ||
options.defaultLayouts[`default`]
// Get the default layout for the file source instance group name,
// or fall back to the default
const layoutPath = res.fileNode.sourceInstanceName
? options.defaultLayouts[res.fileNode.sourceInstanceName]
: options.defaultLayouts[`default`]

// No default layout set? Nothing to do here!
if (!layoutPath) {
Expand Down Expand Up @@ -83,4 +76,4 @@ const gatsbyMdxLoader: LoaderDefinition = async function (source) {
return out
}

export default gatsbyMdxLoader
export default gatsbyLayoutLoader
31 changes: 31 additions & 0 deletions packages/gatsby-plugin-mdx/src/gatsby-mdx-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* eslint-disable @babel/no-invalid-this */
import type { LoaderDefinition } from "webpack"
import type { ProcessorOptions } from "@mdx-js/mdx"
import type { NodeMap } from "./types"

import { getOptions } from "loader-utils"

import compileMDX from "./compile-mdx"

export interface IGatsbyMDXLoaderOptions {
options: ProcessorOptions
nodeMap: NodeMap
}

// Custom MDX Loader that injects the GraphQL MDX node into plugin data
// This whole loaded could be replaced by @mdx-js/loader if MDX would
// accept custom data passed to the unified pipeline via processor.data()
const gatsbyMDXLoader: LoaderDefinition = async function (source) {
const { options, nodeMap }: IGatsbyMDXLoaderOptions = getOptions(this)
const res = nodeMap.get(this.resourcePath)

if (!res) {
return source
}

const { mdxNode, fileNode } = res

return compileMDX(source, mdxNode, fileNode, options)
}

export default gatsbyMDXLoader
Loading