Skip to content
This repository has been archived by the owner on Nov 3, 2019. It is now read-only.

MDX/Markdown in frontmatter #352

Closed
mrozilla opened this issue Apr 10, 2019 · 6 comments
Closed

MDX/Markdown in frontmatter #352

mrozilla opened this issue Apr 10, 2019 · 6 comments

Comments

@mrozilla
Copy link

mrozilla commented Apr 10, 2019

Is your feature request related to a problem? Please describe.
I'm using this package with Netlify CMS. There are situations (e.g. with variable list types) when mdx/markdown ends up saved in the frontmatter of an .mdx file.

Describe the solution you'd like
Since we're already parsing the body of an .mdx file, we could do the same thing to certain fields in the frontmatter which can then be rendered through the MDXRenderer just like the body.

Describe alternatives you've considered
At the moment, it's possible to manually parse the saved string through @mdx/runtime which warns about overhead and bundle sizes (sure, Gatsby is static but still would have to load the larger bundle, affecting the TTI).

The trickiest part of this would probably be defining which frontmatter fields to parse, not sure about a robust-enough solution here yet—I'm using a field called markdown or mdx in my userland solution.

Additional context
I'd love to take a stab at a PR but wanted to check with the maintainers (for opinions and possibly guidance) and the community (for interest) first :) Cheers for a lovely package!

@renvrant
Copy link

Having recently encountered the same issues, I did get around it by using the runtime. Support for frontmatter would be great, but if it winds up being undesirable, adding some documentation would still most likely be valuable.

@mrozilla
Copy link
Author

@ChristopherBiscardi I'd love to get your opinion before I start hacking anything together :)

@ChristopherBiscardi
Copy link
Owner

@mrozilla Can you make the use case a bit more concrete for me? It seems like you want to write multiple MDX files in one file?

@mrozilla
Copy link
Author

mrozilla commented May 8, 2019

Here's a minimal example of such .mdx file:

---
title: This is a title that includes a [link](https://example.com)
---

This is a body that includes a [link](https://example.com)

This could, of course, be accomplished by multiple MDX files and referencing, however, Netlify CMS doesn't save like this.

Since we're already parsing the body of an .mdx file (which is just a string), extending the functionality to certain fields in the frontmatter (which are just strings) should not be that complicated.

Does this answer your question? :)

@ChristopherBiscardi
Copy link
Owner

ChristopherBiscardi commented May 9, 2019

hmm yeah, I could see that being useful. There seem to be two paths to this functionality.

  1. Make export const in mdx core process as MDX in the same way as the body content
  2. Take advantage of the upcoming mdxs functionality somehow

I think I'm inclined towards path 1 because frontmatter is something gatsby-mdx implements for compatibility with MarkdownRemark and is not an mdx core feature. We would need mdx core to be able to process this example file:

export const frontmatter = {
  title: "This is a title that includes a [link](https://example.com)"
}

# some mdx

yadda yadda

An alternate implementation would be to transform frontmatter into top-level exports, but this seems like it could conflict and the processing boils down to the same thing anyway (if export includes strings, process as mdx)

export const title = "This is a title that includes a [link](https://example.com)"

# some mdx

yadda yadda

Another concern is that if you use MDX in the title frontmatter, anywhere you query for title outside of the MDX file itself now needs to be rendered with MDXRenderer.


In the meantime you can accomplish this with some special processing in onCreateNode. The idea being that you use createNode to create a new node in the gatsby system that will be processed by MDX. You will need to make sure the parent is not File node (in the example below the parent is an Mdx node), and that the mediaType is set to a value in your media types list for Mdx processing. The default options are text/markdown and text/x-markdown, but you could also create your own media type if you wanted as long as it was included in that list in the gatsby-mdx options.

exports.onCreateNode = ({ node, actions, getNode, createNodeId }) => {
  const { createNodeField, createNode, createParentChildLink } = actions;

  if (node.internal.type === `Mdx`) {
    const { frontmatter } = node;
    if (frontmatter.title) {
      const myNode = createNode({
        id: createNodeId(`${node.id} >>> MdxCustomSetupType`),
        parent: node.id,
        children: [],
        internal: {
          type: `MdxCustomSetupType`,
          contentDigest: crypto
            .createHash(`md5`)
            .update(node.frontmatter.title)
            .digest(`hex`),
          content: node.frontmatter.title,
          mediaType: "text/markdown",
          description: `A custom node so that MDX will process the title field`
        }
      });
      createParentChildLink({ parent: node, child: myNode });
    }
  }
};

The query would look something like this (note that you may want to change the names of the variables to make it make more sense for users).

{
  mdx {
    frontmatter {
      title // would be a string
    }
    childMdxCustomSetupType {
      body // would be the MDX version of the title
    }
  }
}

and you'd have to use MDXRenderer for rendering the title body

@mrozilla
Copy link
Author

Closing due to the core logic related to this proposal being moved to https://github.com/gatsbyjs/gatsby/tree/master/packages/gatsby-plugin-mdx

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants