Gatsby: Not clear how to display markdown that is not coming from a file

Created on 17 Dec 2019  路  10Comments  路  Source: gatsbyjs/gatsby

I have a graphql API for a blog that contains fields that have formatting with markdown/mdx. I'd like to render that markdown using Gatsby. The docs of gatsby-transformer-markdown only show how to do this when the markdown is coming from static files. However I'd like to know how to do this with plain strings in gatsby-node.js and createPage.

stale? question or discussion

All 10 comments

Sadly there is no easy way to do this right now (like a @mdx directive for schema customization API) so you're stuck with e.g. changing the mediaType to text/markdown. The gatsby-transformer-remark and gatsby-plugin-mdx automatically parse files with this mediaType.

Please see this issue: https://github.com/gatsbyjs/gatsby/issues/19119
Or this blogpost: https://www.christopherbiscardi.com/post/creating-mdx-nodes-from-raw-strings/

Excerpt from it for archival reasons:

exports.sourceNodes = ({
  actions,
  createNodeId,
  createContentDigest
}) => {
  const { createNode } = actions;
  const mdxContent = `---
some: frontmatter
---
# heading
and stuff
`;
  createNode({
    id: `a-node-id`,
    parent: null,
    children: [],
    internal: {
      type: `MyCustomMdxNodesFromString`,
      contentDigest: createContentDigest(mdxContent),
      mediaType: `text/markdown`,
      content: mdxContent,
      description: `My custom MDX nodes`
    }
  });
};

Thanks for your comment. I tried to search for this a lot but couldn't find anything relevant. Appreciated!

Should we keep this open until you got it working or did this unblock you and we can close? :)

I am still researching what a 'node' is. I linked a graphql api with Gatsby using gatsby-source-graphql. I am not really sure how with these building blocks I can set (or override) the mediaType of a string field in the graphql schema. What if there are multiple fields that I want to format as markdown in the component?

@jfrolich One of the problems with gatsby-source-graphql is that it doesn't actually source nodes. It requests data from the remote API during query running and this data effectively bypasses Gatsby node sourcing step. There is a bit more context in this issue: #15906 (which also explains what a node is, node sourcing, etc)

In other words, this plugin works fine when you need to consume data from the remote API as-is. But if you want to transform it into something else then it will stay in your way.

One workaround could be sourcing part of the data you want to transform manually. It could be something like this:

// gatsby-node.js
const axios = require(`axios`)

const get = query =>
  axios.get(
    `https://www.myblog.com/graphql?query=${encodeURIComponent(query)}`
  )

exports.sourceNodes = async ({
  actions,
  createNodeId,
  createContentDigest,
}) => {
  // Manually fetching markdown data from your blog's GraphQL API:
  const result = await get(`
{
  allStories {
    id
    markdownBody
  }
}
`)

  // Transforming this data into Gatsby nodes
  const { createNode } = actions
  result.data.allStories.forEach((story, i) => {
    const mdxContent = story.markdownBody

    createNode({
      id: createNodeId(story.id),
      parent: null,
      children: [],
      originalStoryId: story.id,
      internal: {
        type: `MyCustomMdxNodeFromString`,
        contentDigest: createContentDigest(mdxContent),
        mediaType: `text/markdown`,
        content: mdxContent,
        description: `My custom MDX node`,
      },
    })
  })
}

After this, you should see your custom markdown nodes in GraphiQL. Hope it helps!

This does show the custom markdown nodes, but now they're all in a separate Gatsby created GraphQL connection just because it happened to have a field with markdown formatting. I'm still not sure what needs to be done if you have two fields with markdown formatting.

It's also not very elegant, needing to pull in a http client and manually fetching. I thought this was a typical use-case of Gatsby (pulling in blog content from an external API that has formatting as markdown).

Isn't it better to transform markdown in a component that takes the raw markdown and transforms it to formatting? Or does that have certain problems like with server rendering?

@jfrolich Yes, an alternative is to define custom resolvers for such fields (using createResolvers API) and parse markdown in those resolvers. In fact, our example for gatsby-source-graphql does something similar.

See post field resolver for inspiration:

https://github.com/gatsbyjs/gatsby/blob/f274630b7a2702b0687471fc8f6536a7bebb73c6/examples/using-gatsby-source-graphql/gatsby-node.js#L49-L55

Ah that would actually be perfect!

Hiya!

This issue has gone quiet. Spooky quiet. 馃懟

We get a lot of issues, so we currently close issues after 30 days of inactivity. It鈥檚 been at least 20 days since the last update here.
If we missed this issue or if you want to keep it open, please reply here. You can also add the label "not stale" to keep this issue open!
As a friendly reminder: the best way to see this issue, or any other, fixed is to open a Pull Request. Check out gatsby.dev/contribute for more information about opening PRs, triaging issues, and contributing!

Thanks for being a part of the Gatsby community! 馃挭馃挏

Looks like this is resolved with help from @vladar and @LekoArts (thanks folks)

Let鈥檚 go ahead and close this. Thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Oppenheimer1 picture Oppenheimer1  路  3Comments

signalwerk picture signalwerk  路  3Comments

ghost picture ghost  路  3Comments

jimfilippou picture jimfilippou  路  3Comments

dustinhorton picture dustinhorton  路  3Comments