diff --git a/packages/gatsby-plugin-mdx/gatsby/on-create-node.js b/packages/gatsby-plugin-mdx/gatsby/on-create-node.js index b33d246c6f6d9..13cc593edc32c 100644 --- a/packages/gatsby-plugin-mdx/gatsby/on-create-node.js +++ b/packages/gatsby-plugin-mdx/gatsby/on-create-node.js @@ -6,7 +6,6 @@ const { createContentDigest } = require(`gatsby-core-utils`) const defaultOptions = require(`../utils/default-options`) const createMDXNode = require(`../utils/create-mdx-node`) const { MDX_SCOPES_LOCATION } = require(`../constants`) -const { findImports } = require(`../utils/gen-mdx`) const contentDigest = val => createContentDigest(val) @@ -18,6 +17,7 @@ module.exports = async ( createNodeId, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -46,20 +46,14 @@ module.exports = async ( const content = await loadNodeContent(node) - const mdxNode = await createMDXNode({ + const { mdxNode, scopeIdentifiers, scopeImports } = await createMDXNode({ id: createNodeId(`${node.id} >>> Mdx`), node, content, - }) - createNode(mdxNode) - createParentChildLink({ parent: node, child: mdxNode }) - - // write scope files into .cache for later consumption - const { scopeImports, scopeIdentifiers } = await findImports({ - node: mdxNode, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -69,6 +63,11 @@ module.exports = async ( createNodeId, ...helpers, }) + + createNode(mdxNode) + createParentChildLink({ parent: node, child: mdxNode }) + + // write scope files into .cache for later consumption await cacheScope({ cache, scopeIdentifiers, diff --git a/packages/gatsby-plugin-mdx/loaders/mdx-loader.js b/packages/gatsby-plugin-mdx/loaders/mdx-loader.js index 962090df3cec9..f82d3eebc8261 100644 --- a/packages/gatsby-plugin-mdx/loaders/mdx-loader.js +++ b/packages/gatsby-plugin-mdx/loaders/mdx-loader.js @@ -94,6 +94,7 @@ module.exports = async function (content) { const { getNode: rawGetNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -121,11 +122,15 @@ module.exports = async function (content) { let mdxNode try { - mdxNode = await createMDXNode({ + // This node attempts to break the chicken-egg problem, where parsing mdx + // allows for custom plugins, which can receive a mdx node + ;({ mdxNode } = await createMDXNode({ id: `fakeNodeIdMDXFileABugIfYouSeeThis`, node: fileNode, content, - }) + options, + getNodesByType, + })) } catch (e) { return callback(e) } @@ -192,6 +197,7 @@ ${contentWithoutFrontmatter}` node: { ...mdxNode, rawBody: code }, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, diff --git a/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js b/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js index 397e8c28ba308..6610550442e31 100644 --- a/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js +++ b/packages/gatsby-plugin-mdx/loaders/mdx-loader.test.js @@ -16,9 +16,9 @@ array: [1,2,3] )`, namedExports: `export const meta = {author: "chris"}`, body: `# Some title - + a bit of a paragraph - + some content`, } diff --git a/packages/gatsby-plugin-mdx/utils/create-mdx-node.js b/packages/gatsby-plugin-mdx/utils/create-mdx-node.js index 1071f9dbad46a..07c7f7d3c278e 100644 --- a/packages/gatsby-plugin-mdx/utils/create-mdx-node.js +++ b/packages/gatsby-plugin-mdx/utils/create-mdx-node.js @@ -1,20 +1,19 @@ const { createContentDigest } = require(`gatsby-core-utils`) -const mdx = require(`../utils/mdx`) -const extractExports = require(`../utils/extract-exports`) - -module.exports = async ({ id, node, content }) => { - let code - try { - code = await mdx(content) - } catch (e) { - // add the path of the file to simplify debugging error messages - e.message += `${node.absolutePath}: ${e.message}` - throw e - } - - // extract all the exports - const { frontmatter, ...nodeExports } = extractExports(code) +const { findImportsExports } = require(`../utils/gen-mdx`) + +async function createMdxNode({ id, node, content, ...helpers }) { + const { + frontmatter, + scopeImports, + scopeExports, + scopeIdentifiers, + } = await findImportsExports({ + mdxNode: node, + rawInput: content, + absolutePath: node.absolutePath, + ...helpers, + }) const mdxNode = { id, @@ -24,17 +23,15 @@ module.exports = async ({ id, node, content }) => { content: content, type: `Mdx`, }, + excerpt: frontmatter.excerpt, + exports: scopeExports, + rawBody: content, + frontmatter: { + title: ``, // always include a title + ...frontmatter, + }, } - mdxNode.frontmatter = { - title: ``, // always include a title - ...frontmatter, - } - - mdxNode.excerpt = frontmatter.excerpt - mdxNode.exports = nodeExports - mdxNode.rawBody = content - // Add path to the markdown file path if (node.internal.type === `File`) { mdxNode.fileAbsolutePath = node.absolutePath @@ -42,5 +39,7 @@ module.exports = async ({ id, node, content }) => { mdxNode.internal.contentDigest = createContentDigest(mdxNode) - return mdxNode + return { mdxNode, scopeIdentifiers, scopeImports } } + +module.exports = createMdxNode diff --git a/packages/gatsby-plugin-mdx/utils/gen-mdx.js b/packages/gatsby-plugin-mdx/utils/gen-mdx.js index 05c7df33cec80..dca1a25ce3c92 100644 --- a/packages/gatsby-plugin-mdx/utils/gen-mdx.js +++ b/packages/gatsby-plugin-mdx/utils/gen-mdx.js @@ -47,6 +47,7 @@ async function genMDX( options, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -114,6 +115,7 @@ export const _frontmatter = ${JSON.stringify(data)}` // files, getNode, getNodes, + getNodesByType, reporter, cache, pathPrefix, @@ -194,8 +196,10 @@ ${code}` module.exports = genMDX // Legacy API, drop in v3 in favor of named export module.exports.genMDX = genMDX -async function findImports({ - node, +async function findImportsExports({ + mdxNode, + rawInput, + absolutePath = null, options, getNode, getNodes, @@ -205,12 +209,12 @@ async function findImports({ pathPrefix, ...helpers }) { - const { content } = grayMatter(node.rawBody) + const { data: frontmatter, content } = grayMatter(rawInput) const gatsbyRemarkPluginsAsremarkPlugins = await getSourcePluginsAsRemarkPlugins( { gatsbyRemarkPlugins: options.gatsbyRemarkPlugins, - mdxNode: node, + mdxNode, getNode, getNodes, getNodesByType, @@ -226,18 +230,19 @@ async function findImports({ ) const compilerOptions = { - filepath: node.fileAbsolutePath, + filepath: absolutePath, ...options, remarkPlugins: [ ...options.remarkPlugins, ...gatsbyRemarkPluginsAsremarkPlugins, ], } + const compiler = mdx.createCompiler(compilerOptions) const fileOpts = { contents: content } - if (node.fileAbsolutePath) { - fileOpts.path = node.fileAbsolutePath + if (absolutePath) { + fileOpts.path = absolutePath } const mdast = await compiler.parse(fileOpts) @@ -246,16 +251,19 @@ async function findImports({ // we don't need to dedupe the symbols here. const identifiers = [] const imports = [] + const exports = [] mdast.children.forEach(node => { - if (node.type !== `import`) return - - const importCode = node.value + if (node.type === `import`) { + const importCode = node.value - imports.push(importCode) + imports.push(importCode) - const bindings = parseImportBindings(importCode) - identifiers.push(...bindings) + const bindings = parseImportBindings(importCode) + identifiers.push(...bindings) + } else if (node.type === `export`) { + exports.push(node.value) + } }) if (!identifiers.includes(`React`)) { @@ -264,9 +272,11 @@ async function findImports({ } return { + frontmatter, scopeImports: imports, + scopeExports: exports, scopeIdentifiers: identifiers, } } -module.exports.findImports = findImports +module.exports.findImportsExports = findImportsExports