Rendering code snippets with Gatsby
See original GitHub issueI’m trying to include code snippets into my rich text document and render it properly formatted later on by wrapping <pre>
tags around what Gatsby generates. I tried doing this:
const Blog = (props) => {
const Code = ({children}) => <pre><code style={{backgroundColor: "red"}}>{children}</code></pre>
const options = {
renderMark: {
[MARKS.CODE]: code => <Code>{code}</Code>},
}
}
This doesn’t work though because a new <p>
tag is automatically wrapped around every line of code in the rich text document, which creates invalid HTML (<pre>
tags can’t be direct descendants of <p>
tags) and separates each line from the others, rather than displaying the code as a block.
Am I going about this the wrong way? All I want is to include a block of code in e.g a blog post and render it in my template exactly as I typed it out in Contentful.
Would appreciate any help! Thanks
Issue Analytics
- State:
- Created 4 years ago
- Reactions:1
- Comments:7
Top Results From Across the Web
Rendering Contentful Rich Code Snippets in Gatsby
At a high level: rich content comes through as an object. Each node within the object corresponds to a block of copy (a...
Read more >Gatsby-Contentful: Code Snippets - Tech Holding
“Gatsby is a free and open source framework based on React that ... Now your code snippets should be rendering and highlighted as...
Read more >Render Code Snippets with Gatsbyjs and Contentful
In this post, I'll go into how to pull a code snippet from Contentful and render it within GatsbyJS with syntax highlighting.
Read more >gatsby - How to format code snippets with <pre> tags using ...
Then, using the @contentful/rich-text-react-renderer which comes with the gatsby-source-contentful/rich-text plugin, I create a bespoke options ...
Read more >gatsby-remark-embed-snippet
gatsby -remark-embed-snippet Embeds the contents of specified files as code snippets. Installation Note: This plugin depends on gatsby-remark…
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
Hey @scirocco21 at the moment we do not natively support code blocks in the Rich Text field.
As a workaround, you can use Embedded Entry. A dedicated content type will allow specifying code metadata, like:
language
etc., that could be used at rendering time.Hope this helps 😉
I believe there are a few problems at play here. Instead of trying to write a huge comment (although inevitably this will still be quite big), I’ve written a detailed article about it here.
First and foremost, the suggestion from @sbezludny that Contentful does not natively support code blocks in the Rich Text field is - please pardon my French - BS. For such a feature-rich - and expensive - service, I’m sure we can agree that’s not really acceptable when you consider that code bocks are made available within the Contentful interface. I would perhaps understand a little more if formatted code blocks also weren’t available there… but it is, so being able to enter content that it is then not possible to render out again is a fairly significant flaw.
Secondly, what @scirocco21 was trying to do was a little mistaken.
[MARKS.CODE]
is inline code (as in: code that falls within the flow of a paragraph), not a code block. These should be wrapped in<code>
and not<pre>
(for what it’s worth: both of those tags are formatted as inline code). For reference,MARKS
also containsBOLD
,ITALIC
, andUNDERLINE
.Finally, Contentful does not provide a ‘code’ block-type, which I think it an oversight on their part. What this means is that when you create a block of code in Contentful, what you are actually creating is paragraphs, with the only child inside being a ‘code’
MARK
. This - I feel - is where Contentful is really letting themselves down at the moment.To get around this, you can modify how you handle
BLOCKS.PARAGRAPH
. We already know that where we’ve entered a block of text into Contentful’s UI, what it has sent us is a paragraph, with a single node (normal text paragraphs will likely contain several nodes for inline elements within it), and the mark type of that first node will be ‘code’.So, when we come to render a paragraph, instead of just outputting a
<p>
, we delve a little deeper to work out if it’s a code block or not, and return<pre>
(and if you want:<code>
) instead:This will (very belatedly) resolve the original issue here, although it’s a workaround. There is one minor hitch - however - that that’s this: because Contentful separates these code blocks out into paragraphs first, if your code has an empty line within it, you will actually find it gets divided out into multiple
<pre>
sections.Here’s a screenshot from my personal website showing you what I mean (each is wrapped in a lime outline):
This can be countered visually with a little bit of CSS to close the gaps, but nevertheless: what you end up with isn’t semantic markup, and has other issues like odd line-wrapping and horizontal scrolling for narrower screens where you end up being forced to use
white-space: pre-wrap
, which isn’t ideal.With the help of a close friend of mine (and very talented developer) Ben Stokoe, we have come up with a way of transforming Contentful’s data and bringing these adjacent code blocks together.
This comment is already a bit long to start dropping multi-line functions into, so if the above solution isn’t enough, then take a read through my article ‘Rendering Contentful Rich Conde snippets in Gatsby’ - the bigger solution is towards the bottom.