Display pretty code snippets using DatoCMS's structuredText block

DatoCMS now provides an excellent StructuredText WYSIWYG field which enables much quicker and fluid content writing in their CMS. It offers a beautiful, Notion-like editor designed for focus, with slash commands, markdown/keyboard shortcuts, and drag & drop. It stores the content in a safe, semantic and readable JSON format, representing a tree of well-defined nodes which can then be parsed by your frontend and displayed to the end-user in any way you desire.

Along side the typical headings, paragraphs, list and quotes, it also provides support for Code blocks to enable writers like myself to share and easily manage large blocks of code. (as you can see further down in this post).

The problem I found is that default browser support for Code Blocks is a bit meh and until something is done that allows easy Syntax Highlighting we'll need to continue to use third-party parsers and styles.

I love what PrismJs offers in terms of simple customisations and great styles out of the box. However in order for you to get it to work with DatoCMS's StructuredText block you'll need to do a little bit of configuration to tell the StructuredText component (from DatoCMS) that you want to use a custom component when it encounters any "code nodes".

So, chances are you have already implemented something like the below to get StructuredText to appear in your blogs frontend.

const ArticleContent = ({ article }) => {
return (
<div className={styles.article}>
<h1>{article.title}</h1>
<div className={styles.content}>
<StructuredText data={article.content} />
</div>
</div>
);
};

Now, if you have already followed the instructions in my other post around how to set up your own custom PrismJs Component, then you just need to import that into this file and add a custom renderRule to tell the StructuredText component that you want to use this block instead when a code node appears.

Simple replace the StructuredText block with the following code below to set up a custom RenderRule anytime a Code node is encountered.

1import { CodeBlock } from "../code-block";
2
3// Replace
4// <StructuredText data={article.content} />
5// with the following
6
7<StructuredText
8 data={article.content}
9 customRules={[
10 renderRule(isCode, ({ node, key }) => {
11 return (
12 <CodeBlock
13 key={key}
14 code={node.code}
15 language={node.language}
16 showLineNumbers={node.code.split(/\n/).length > 10}
17 />
18 );
19 }),
20 ]}
21/>

And thats it really!

You might need to add some more custom CSS styles to get everything looking just right. I added some extra padding to the <pre> block that is generated as well as some rounded corners to get it looking extra hot 🔥

Keep in mind that you're not limited to the above customRules. You can add all sorts of overrides to get the StructuredText block to render you own Paragraph or Heading components if you have those.