DEV Community

FidelVe
FidelVe

Posted on

The definitive guide for using PrismJs in Gatsby

wisdom of the ancients

wisdom of the ancients by xkcd

Learning to use a new technology has been in my experience, a process of spending days searching for information to piece together a puzzle of which you don't have the entire picture yet.

A process that is at the same time rewarding and frustrating, it has become a new experience that I just have to get used to while walking the path of a self-taught developer.

The most recent time I walked this path, was when I decided to remake my personal website using Gatsby and upon watching a lot of blogs and sites with really cool and styled block codes with syntax highlighting, I thought that it would be good to use it on my site.

There are many libraries for syntax highlighting, but the one that seems to be the most used and preferred is Prism, so I decided to not spend too much time searching the pros and cons of all of them and give Prism a try, I would be happy to see your opinions on other libraries in the comments.

The main thing that you need to take into account

If you are in the process of porting (or creating from scratch) your website or blog to Gatsby, and wanted to use Prism for code highlighting, the first thing that you need to decide is whether you're going to be using markdown files or not, because the process is different depending on this decision.

The need for using markdown files will depend on the type of website you are creating, but basically, if you are creating a blog or blog-like type of website, in the end using Markdown to source the content to your site is the most efficient way to go. If this is your case, the process will involve installing and configuring a couple of gatsby plugins (gatsby-transformer-remark and gatsby-remark-prismjs), installing the Prism npm package and querying for the Markdown files (or snippets) with GraphQL.

On the other hand, if you are creating any other type of website, with a more complex design, Markdown won't give you enough flexibility to apply things like collapsible containers, carousels, etc. In this case, you just need to get Prism working in React while using a custom .babelrc configuration file.

I created a blank Gatsby project to use for both examples, you can download it here, or create it from the console using the following format.

gatsby new <project-name> https://github.com/FidelVe/gatsby-blank-starter
Enter fullscreen mode Exit fullscreen mode

In case you haven't install Gatsby yet, run the following command first:

npm i -g gatsby-cli
Enter fullscreen mode Exit fullscreen mode

Gatsby, React and PrismJs without remark

The first scenario that I will be explained is using Prism without markdown files. This scenario is basically using Prism inside React in a way that Gatsby can process without any problems.

Lets first create a new gatsby project.

gatsby new gatsby-prism https://github.com/FidelVe/gatsby-blank-starter
Enter fullscreen mode Exit fullscreen mode

Try running the gatsby develop server and you will see the following page with the default <code> style.

before prism

The first thing to do is install the npm Prism package:

npm install  --save prismjs
Enter fullscreen mode Exit fullscreen mode

Now we are going to install babel-plugin-prismjs, this plugin allows us to configure and customize Prism by using Babel.

npm install --save babel-plugin-prismjs
Enter fullscreen mode Exit fullscreen mode

To use this plugin we need to create a .babelrc file and put our configurations in it. Gatsby ships with a default .babelrc file, in order to create our own file and modify it we need to install the babel-preset-gatsby preset and add it to our new .babelrc file.

npm install --save babel-preset-gatsby
Enter fullscreen mode Exit fullscreen mode

At this point, we have already installed everything we need so let's start with the configurations.

First, create a new file at the root of the project and call it .babelrc. Inside this file, we can customize Prism, in my case this is the content of the .babelrc file.

{
  "presets": ["babel-preset-gatsby"],
  "plugins": [
    ["prismjs", {
      "languages": ["javascript", "css", "markup"],
      "plugins": ["show-language"],
      "theme": "okaidia",
      "css": true
    }]
  ]
}
Enter fullscreen mode Exit fullscreen mode

With the installations and configurations out of the way, now we just need to import prismjs and use the Prism.highlightAll() function call to style our code blocks.

If you're using the repo I linked at the beginning, open the src/pages/index.js file and add the following:

import React from "react"
import { useEffect } from "react"
import Layout from "../components/layout"

//import the Prism package
import Prism from "prismjs"

// The code we will be displaying
const code = `const foo = 'foo';
const bar = 'bar';
console.log(foo + bar);
`

const IndexPage = () => {
  useEffect(() => {
    // call the highlightAll() function to style our code blocks
    Prism.highlightAll()
  })

  return (
    <Layout>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          flexFlow: "column nowrap",
          margin: "6px 10px",
          maxWidth: "800px",
        }}
      >
        <h2>
          Using Prism to style <code>code blocks</code> in Gatsby
        </h2>
        <div className="code-container">
          <pre>
            <code className="language-javascript">{code}</code>
          </pre>
        </div>
      </div>
    </Layout>
  )
}

export default IndexPage
Enter fullscreen mode Exit fullscreen mode

Run the gatsby develop server and you will see the following page with the code block styled with the prism theme.

page using prism

Congratulations, now you know how to add code styles with Prism inside Gatsby, here is a list of links to expand more on this topic.

Gatsby, React and PrismJs with remark

Parsing markdown files on gatsby is done with a transformer plugin called gatsby-transformer-remark. This plugin takes markdown formatted content and transform it into valid html, so in this case, we are going to write our code snippets in triple backtick () inside markdown files (.md), use GraphQl to query the data inside the file and put it inside our code.

Let's start by creating a new blank gatsby project.

gatsby new gatsby-markdown-prism https://github.com/FidelVe/gatsby-blank-starter
Enter fullscreen mode Exit fullscreen mode

Now, lets install prismjs, gatsby-transformer-remark and gatsby-remark-prismjs.

npm install --save prismjs gatsby-transformer-remark gatsby-remark-prismjs
Enter fullscreen mode Exit fullscreen mode

There are several themes to choose from in Prism, for this project I'm using the okaidia theme. In order to define a theme, create a file called gatsby-browser.js in the root folder and add the following.

require("prismjs/themes/prism-okaidia.css");
Enter fullscreen mode Exit fullscreen mode

Since we are going to be using .md files to write our code snippets in them, create a folder (src/content/). to put all the markdown files, and inside that folder create a new markdown file called code.md and add the following content.

markdown content

The next step is to configure the plugins we have installed. open the gatsby-config.js file at the root of the project and add the following:

module.exports = {
  plugins: [
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `code`,
        path: `${__dirname}/src/content`,
      },
    },
    {
      resolve: `gatsby-transformer-remark`,
      options: {
        plugins: [
          {
            resolve: `gatsby-remark-prismjs`,
            options: {},
          },
        ],
      },
    },
  ],
}
Enter fullscreen mode Exit fullscreen mode

The gatsby-source-filesystem plugin creates File nodes from the files in our system. In this case, we are creating nodes from each file inside our src/content/ folder.

Every .md file we create inside our src/content/ folder gets parsed and transformed into valid html by gastby-transformer-remark, and because we are using the gatsby-remark-prismjs plugin, content inside triple backticks is automatically formatted by Prism.

Having installed and configured all the necessary plugins, the only thing that's left is inserting the parsed content into our page and for that we will use GraphQl.

Open the src/page/index.js file and add the following content to it.

import React from "react"
import { useStaticQuery, graphql } from "gatsby"
import Layout from "../components/layout"

const IndexPage = () => {
  const data = useStaticQuery(graphql`
    {
      allMarkdownRemark(filter: { fileAbsolutePath: { regex: "/code.md/" } }) {
        nodes {
          html
        }
      }
    }
  `)

  return (
    <Layout>
      <div
        style={{
          display: "flex",
          alignItems: "center",
          flexFlow: "column nowrap",
          margin: "6px 10px",
          maxWidth: "800px",
        }}
      >
        <h2>
          Using Prism to style <code>code blocks</code> in Gatsby
        </h2>
        <div
          className="code-container"
          dangerouslySetInnerHTML={{
            __html: data.allMarkdownRemark.nodes[0].html,
          }}
        ></div>
      </div>
    </Layout>
  )
}

export default IndexPage
Enter fullscreen mode Exit fullscreen mode

Start the gatsby develop server and you should see the code styled as shown in the image.

page with prism and markdown

Thanks for reading, hope this helped you implement Prism to your Gatsby pages.

Again, here is a list of links to expand more on this topic.

Top comments (8)

Collapse
 
alexhwoods profile image
Alex Woods

The best resource I've read about this. I'm a very casual frontend engineer (I'm a backend engineer), so my Gatsby / React skills are "eh".

I had no idea the "remark" plugins were for dealing with markup files. This helped me solve my issue.

Thank you!

Collapse
 
tweettamimi profile image
Tamimi

Thanks for the article! I am wondering if you have ever incorporated a copy-to-clipboard functionality with the code block that is generated from the gatsby-remark-prismjs plugin. There seems to be a bunch of prism specific plugins that are not accessible/exposed to the gatsby-remark-prismjs plugin. Thanks!

Collapse
 
taphathoughts profile image
Tapha

Hey Fidel, thanks for the great tutorial.

I'm wondering how you would do this with

dangerouslySetInnerHTML={{ __html: post.content.html }}

. When I followed your above steps, it did not work for me.

Collapse
 
ncoughlin profile image
Nick Coughlin

I would love to see an addition to this that covers how to work with Prism Plugins within Gatsby, for example prismjs.com/plugins/show-language/

Collapse
 
poutingemoji profile image
poutingemoji

As of 6/12/2021, there's still no way to use most Prism plugins like show-language with Gatsby. Someone made a pull request that added in the show-invisibles plugin though! github.com/gatsbyjs/gatsby/pull/21439

Collapse
 
ashishkumar3 profile image
Ashish

How to add file type on the code snippet?

Collapse
 
tranduclinh197 profile image
Trần Đức Lĩnh

Thanks .

Collapse
 
apustula profile image
Aga

Thanks for your article, this is exactly what I was looking for!