2

I am using Contentful's Rich-Text Field type to build pages, one of the Embedded_Blocks I have is for a Markdown field type which I am using to build a table:

Markdown Field Type:

| Title | Title | 
| ---------- | ---------- | 
| Cell | Cell | 

I can retrieve the Rich-Text data and build out my Embedded_Blocks like this:

[BLOCKS.EMBEDDED_ENTRY]: (node) => {
   const fields = node.data.target.fields;
   switch (node.data.target.sys.contentType.sys.id) {
      case 'video':
          const url = (fields.url['en-US']);
          return <Video url={url}/>

      // This is how I'm currently trying to convert Markdown to HTML
      ///////////////////////////////////////////////////////////////
      case 'markdown':
          const markdown = (fields.markdown['en-US']);
          console.log('markdown', markdown);
          return <div dangerouslySetInnerHTML={{ __html: markdown }} />
      default:
          return <div>Fallback</div>
   }
},

The problem I have with this is that it just returns a string, I'm assuming because I have not converted markdown to HTML before passing it to dangerouslySetInnerHTML={{ __html: markdown }}.

How can I convent the Markdown to HTML so that I can render it using dangerouslySetInnerHTML={{ __html: markdown }}?

Daimz
  • 3,243
  • 14
  • 49
  • 76
  • what exactly is returning a string? and why is that a problem? `markdown` is supposed to be a string in `dangerouslySetInnerHTML={{ __html: markdown }}` – mb21 May 06 '19 at 09:28
  • My understanding is that `dangerouslySetInnerHTML={{ __html: markdown }}` requires the the Markdown text has already been converted to a string containing HTML. This is not what I have. `const markdown = (fields.markdown['en-US']);` simply gives me a string of markdown that is unconverted. So `dangerouslySetInnerHTML` just displays the sting of markdown text as there is no HTML. – Daimz May 08 '19 at 01:50
  • then you need to convert it to html first using e.g. markdown-it or https://www.gatsbyjs.org/packages/gatsby-transformer-remark/ – mb21 May 08 '19 at 07:14
  • see e.g. https://stackoverflow.com/a/47113387/214446 – mb21 May 08 '19 at 07:20
  • 2
    @mb21 not sure the D'uh is deserved. My question clearly says that the converting to HTML is what I am having trouble with and it's clearly obvious that I know what dangerouslySetInnerHTML is for. I was asking for help not a smart attitude. Please read the question carefully in future before implying stupidity. – Daimz May 10 '19 at 21:25

3 Answers3

1

The most appropriate way to do this inside of Gatsby would be to create child nodes inside of the Gatsby onCreateNode lifecycle hook. This hook is only called in the nodejs process, and runs the markdown parsing once when the Contentful entry is downloaded.

This should get you started - it's based on the code inside of Gatsby's gatsby-transformer-remark

Note that this is pseudocode - you'll have to of course test it.

// gatsby-node.js

var remark = require('remark')
var recommended = require('remark-preset-lint-recommended')
var html = require('remark-html')

const processor = remark()
  .use(recommended)
  .use(html)

export async function onCreateNode({ actions, node, loadNodeContent}) {
  if (!/RichText/.test(node.internal.type)) {
    return
  }

  const markdown = // somehow load the raw markdown from the node - I haven't studied RichText nodes yet

  const html = processor.process(markdown)

  const markdownNode = {
    id: createNodeId(`${node.id} >>> MarkdownRemark`),
    children: [],
    parent: node.id,
    internal: {
      content: data.content,
      type: `MarkdownRemark`,
    },
  }

  actions.createNode(markdownNode)
  actions.createParentChildLink({ parent: node, child: markdownNode })
}

For reference, here is where Contentful creates the Rich Text nodes inside Gatsby:

Gordon Burgett
  • 1,482
  • 11
  • 15
1

I implemented the solution using the package react-markdown

npm i react-markdown 
//using version "^5.0.2",

From your problem, I can see you are able to get the markdown content as a String. Use the package above parse the markdown content like so:

import ReactMarkdownWithHtml from "react-markdown/with-html";

replace:

return <div dangerouslySetInnerHTML={{ __html: markdown }} />

with:

return <ReactMarkdownWithHtml children={markdown} allowDangerousHtml />

Here's their github page react-markdown

You can use this package or any other React package that parses markdown inside Gatsby to parse your markdown strings.

0

Using "micromark" worked for me...

  1. I just added the dependency in package.json

  2. In the gatsby.config.js I added the package:

    const micromark = require('micromark');

  3. I used it to transform the node:

    { resolve: '@contentful/gatsby-transformer-contentful-richtext', options: { renderOptions: { renderNode: {

             [BLOCKS.EMBEDDED_ENTRY]:
               (node) => {
                 const LANG = 'en-US';
                 const ENTRY_TYPES = {
                   BUTTON: 'elementbutton',
                   TIP: 'elementtip',
                   QUOTE: 'elementquote',
                   IMAGE_COLUMN: 'elementimagecolumn',
                 };
                 const type = node.data.target.sys.contentType.sys.id;
                 const { fields } = node.data.target;
    
                 switch (type) {
                   case ENTRY_TYPES.QUOTE: {
                     const text = fields.text[LANG];
                     return `
                       <div class="${ENTRY_TYPES.QUOTE}">
                         ${micromark(text)}
                       </div>
                     `;
                   }
                   default:
                     return '';
                 }
               },
           },
         },
       },
     },
    
Orland
  • 1
  • 1