htmlmarkdowngatsbygatsby-remark-image

How to display Markdown files containing HTML syntax in Gatsby?


I am using Markdown file to generate pages for gatby. In order to control the style of pictures, I use html syntax. However, the page generated by gatsby does not display the html part.

This is my markdown file:

---
......frontmatter......
--- 
......content......
<table>
  <tr>
    <td><img src="./images/2018/zotero/ZoteroWebDAV.png"></td>
    <td><img src="./images/2018/zotero/ZoteroExts.png" width=100%></td>
  </tr>
</table>
......content......

Everything else is rendered normally, however, neither the table nor the pictures in it are displayed. Here is my gatsby-config.js.

{
      resolve: `gatsby-transformer-remark`,
      options: {
        excerpt_separator: `<!-- endexcerpt -->`,
        plugins: [
          // 'gatsby-remark-relative-images',
          {
            resolve: `gatsby-remark-images`,
            options: {
              maxWidth: 1200,
            },
          },
          {
            resolve: `gatsby-remark-image-attributes`,
            options: {
              dataAttributes: true
            }
          },
        ],
      },
    },

What can I do to make the html part in Markdown render normally?


Solution

  • You can use as well the built-in dangerouslySetInnerHtml property or any markdown parser like markdown-to-jsx.

    Using the first approach, following Gatsby's guides:

    import React from "react"
    import { graphql } from "gatsby"
    
    export default function Template({data}) {
      const { markdownRemark } = data // data.markdownRemark holds your post data
      const { frontmatter, html } = markdownRemark
      return (
        <div className="blog-post-container">
          <div className="blog-post">
            <h1>{frontmatter.title}</h1>
            <h2>{frontmatter.date}</h2>
            <div
              className="blog-post-content"
              dangerouslySetInnerHTML={{ __html: html }}
            />
          </div>
        </div>
      )
    }
    
    export const pageQuery = graphql`
      query($id: String!) {
        markdownRemark(id: { eq: $id }) {
          html
          frontmatter {
            date(formatString: "MMMM DD, YYYY")
            slug
            title
          }
        }
      }
    `
    

    Because you haven't shared your query I've used the one in the guide but tweak it as you wish. As you can see, everything that is in the end of the frontmatter is html:

    <div
      className="blog-post-content"
      dangerouslySetInnerHTML={{ __html: html }}
    />
    

    Using the second approach, and following the previous query structure, the html should be rendered as:

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    
    <Markdown>{html}</Markdown>
    

    If there's any hindrance I'd say that the second approach is better because, as the dangerouslySetInnerHTML name suggests, you are potentially exposing your site to XSS (Cross-Site Scripting), while the second approach sanitizes the implementation.