Search code examples
javascriptreactjsgraphqlmarkdowngatsby

Markdown files in GatsbyJS not converting to HTML as expected when transformed


I'm building a website with a blog using the Gatsby starter blog on Github. I changed the default styling, pages and some setting, but I kept the same code in the gatsby-node file that gets all the markdown files which you can then get using graphQL query.

This is how it is supposed to be formatted as HTML. But the screenshot below shows how different the formatting is on the website. The markdown is not properly formatted. When I inspect it using the developer console I can see the proper HTML tags, but it doesn't format

Apparently, I'm doing something wrong, but I can't figure out what.

enter image description here

Source code below:

gasty-node.js:

const path = require(`path`)
const { createFilePath } = require(`gatsby-source-filesystem`)

exports.createPages = async ({ graphql, actions }) => {
  const { createPage } = actions

  const blogPost = path.resolve(`./src/templates/blog-post.js`)
  const result = await graphql(
    `
      {
        allMarkdownRemark(
          sort: { fields: [frontmatter___date], order: DESC }
          limit: 1000
        ) {
          edges {
            node {
              fields {
                slug
              }
              frontmatter {
                title
                date(formatString: "MMMM DD, YYYY")
                description
                path
                tags
              }
            }
          }
        }
      }
    `
  )

  if (result.errors) {
    throw result.errors
  }

  const posts = result.data.allMarkdownRemark.edges

  posts.forEach((post, index) => {
    const previous = index === posts.length - 1 ? null : posts[index + 1].node
    const next = index === 0 ? null : posts[index - 1].node

    createPage({
      path: post.node.fields.slug,
      component: blogPost,
      context: {
        slug: post.node.fields.slug,
        previous,
        next,
      },
    })
  })
}

exports.onCreateNode = ({ node, actions, getNode }) => {
  const { createNodeField } = actions

  if (node.internal.type === `MarkdownRemark`) {
    const value = createFilePath({ node, getNode })
    createNodeField({
      name: `slug`,
      node,
      value,
    })
  }
}

Blog-post template

import React from "react"
import { Link, graphql } from "gatsby"

import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"

const BlogPostTemplate = ({ data, pageContext, location }) => {
  const post = data.markdownRemark
  const siteTitle = data.site.siteMetadata.title
  const { previous, next } = pageContext

  return (
    <Layout location={location} title={siteTitle}>
      <SEO
        title={post.frontmatter.title}
        description={post.frontmatter.description || post.excerpt}
      />
      <div className="post-wrapper">
        <article id="post">
          <header className="sm:mb-5 md:mt-10 md:mb-10 lg:mb-20">
            <h1
              className="sm:text-2xl md: md:text-3xl lg:text-5xl font-bold mt-10"
              id="post-title"
            >
              {post.frontmatter.title}
            </h1>
            <p className="text-gray-600" id="post-date">
              {" "}
              - {post.frontmatter.date}
            </p>
          </header>
          <section
            id="post-body"
            dangerouslySetInnerHTML={{ __html: post.html }}
          />

          <hr className="mb-10" />

          <footer>
            <Bio />
          </footer>
        </article>

        <nav id="post-nav">
          <ul>
            {previous && (
              <li className="text-black font-bold text-lg border border-black hover:bg-black hover:text-white rounded p-5">
                <Link to={previous.fields.slug} rel="prev">
                  ← {previous.frontmatter.title}
                </Link>
              </li>
            )}{" "}
            {next && (
              <li className="text-black font-bold text-lg border border-black hover:bg-black hover:text-white rounded p-5">
                <Link to={next.fields.slug} rel="next">
                  {next.frontmatter.title} →
                </Link>
              </li>
            )}
          </ul>
        </nav>
      </div>
    </Layout>
  )
}

export default BlogPostTemplate

export const pageQuery = graphql`
  query BlogPostBySlug($slug: String!) {
    site {
      siteMetadata {
        title
      }
    }
    markdownRemark(fields: { slug: { eq: $slug } }) {
      id
      excerpt(pruneLength: 160)
      html
      frontmatter {
        title
        date(formatString: "MMMM DD, YYYY")
        description
      }
    }
  }
`


Solution

  • Your code is seting correctly the content from the markdown files, there's no mistake there: your dangerouslySetInnerHTML is working perfectly. You are only missing the styling.

    Just add a CSS/SCSS file and add the desired style. In your BlogPostTemplate component:

    import React from "react"
    import { Link, graphql } from "gatsby"
    
    import Bio from "../components/bio"
    import Layout from "../components/layout"
    import SEO from "../components/seo"
    import './yourStyles.scss' // <-- here you are importing your styles
    

    Note that the path in yourStyles.scss is pointing to the same folder than the BlogPostTemplate.

    In your yourStyles.scss just add what you need:

    h1, h2, h3 {
      font-size: 3rem;
      color: blue;
    }
    
    // and so on...