Contentful’s Rich Text Editor provides content creators with powerful text editing capabilities via the use of Contentful’s “What you see is what you get” (wysiwyg) editor. When using the editor, content can be easily formatted using all the usual text formatting methods; bold, italic, underline etc, along with providing support for headings, embedded images, block quotes, code snippets, links and lists.
I used Rich Text recently in the Gatsby Contentful Demo for the blog posts body. You can see the demo site here: Gatsby Demo Contentful
If you’re looking for the source code this can be found on Gatsby’s GitHub here: gatsby-demo-contentful
Before you dive into the code here’s a quick summary for adding Rich Text to your content models in Contentful.
Content models in Contentful
After creating a new Content Type from the Contentful App interface Rich Text is made available under the Add field option.
After Rich Text has been added to your content model you can inspect the settings where you’ll see the available formatting options named above.
With Rich Text enabled creative control can now be handed over to the content creators. Using the wysiwyg editor it’s possible to embed images, format headings, add paragraphs and so forth. But Contentful also makes it simple to limit some of this functionality, striking a balance between authoring creativity and actual development bumpers.
Data sourcing with Rich Text
With the gatsby-source-contentful plugin installed and configured it’s possible to query the richText
field using GraphQL
raw
There are two types of nodes available on richText
, the first is called raw
, the second is references
, i’ll come back to references later.
Using GraphQL you can query the raw data for e.g all blog posts like this.
This GraphQL query will return a large chunk of some rather spurious looking data, but hang in there I’ll explain this shortly.
If you have a look at the image below you may notice that amongst the jumbled mass of data are some “clues” as to what the data actually is.
You might notice a line that contains the following…
This loosely translates to: The word “Bacon” uses the mark type bold, and as you might expect the desired result would be that when this pops out in the browser, the word Bacon is in fact bold.
However, you will need to give Rich Text a helping hand in transforming the nodes to their respective HTML types using the “clues” mentioned above.
To do this the Gatsby Contentful plugin comes with a helper function called renderRichText
The helper function can be used to “catch” these marks or node types and gives you a little more control over how they will eventually appear in the browser.
renderRichText
To use the helper function import it from the gatsby-source-contentful package
The helper function accepts two arguments, the first is the raw data as queried by GraphQL above, and the second in an options object.
Options object
The options object can be configured as follows. You can see that for the bold text I’ve wrapped it with an HTML <b>
element and applied a class name of font-bold
. This makes the bold text semantically correct and styles it in an appropriate fashion.
For hyperlinks i’ve used a similar approach but this time used an HTML <a>
element, also note the href
attribute which is given the data returned by node.data.uri
which is the actual link applied in the wysiwyg editor, i’ve also applied a class name of underline
Naturally the styles you apply will depend on your requirements but hopefully this will give you an idea of how to transform and style each node type. For the Gatsby Contentful Demo i’ve used TailwindCSS
renderMark
catches node types like bold, italic, underline.renderNode
catches node types like headings, links, lists etc
Each of the types come from Contentful’s rich-text-types package, and you can import them into your page or component like so
You can see the full set of types in the Contentful’s GitHub repository using the links below
- MARKS: rich-text/packages/rich-text-types/src/marks.ts
- BLOCKS: rich-text/packages/rich-text-types/src/blocks.ts
- INLINES: rich-text/packages/rich-text-types/src/inlines.ts
Image sourcing with Rich Text
I mentioned earlier that the richText
GraphQL type contains two node types, i’ve covered raw
above and in this next section i’ll discuss references
References
References can be used to query Contentful’s Assets. In this case i’ll be using it to query images that have been embedded using the wysiwyg editor
The two child nodes I query are; description
which i’ll use later as alt text, and gatsbyImageData
which is all the gatsby-plugin-image goodness!
I set a default width of 1000px to ensure that even if very large image files are uploaded by content creators Gatsby’s Image plugin will resize them to keep your site blazing fast!
To “catch” assets of type image I use BLOCKS.EMBEDDED_ASSET
and pass the gatsbyImage
data onto the <GatsbyImage />
component via the image
prop, you’ll also notice I pass the description
on via the alt
prop.
The GatsbyImage
component and the getImage
helper function can be imported from the gatsby-plugin-image package as per the below
As with <b>
and <a>
you can also apply any class names to the <GatsbyImage />
component to suit your needs.
To see the full Rich Text component and all the options i’ve used in the Gatsby Contentful Demo it can be found on GitHub here: gatsby-demo-contentful/src/components/contentful-rich-text.js
I use the component inside the {contentfulPosts.url}.js
collection route. You can see that in action on GitHub here:
gatsby-demo-contentful/src/pages/{contentfulPosts.url}.js
Enhancements
You may notice in the demo I’ve applied a few other tricks. For instance, node types that are “headings” have been transformed to apply a jump link so when clicked the blog post will move the browser window to the position of the heading. I achieved this by using Gatsby’s onRouteUpdate from the gatsby-browser API which fires whenever a url is changed. You can see that code in the demo repo on GitHub here: gatsby-demo-contentful/gatsby-browser.js
I also transform all nodes of type <h1>
to <h2>
. This ensures there’s only ever one <h1>
tag used on a blog post regardless of how the wysiwyg editor is used to style headings.
That just about sums it up. It can be strange at first when looking at that huge lump of data but personally I prefer Contentful’s approach of returning JSON rather than actual HTML as it gives you greater control over the final HTML output for each node type.
I hope you’ve found this helpful and if you have any questions feel free to find me on Twitter: @PaulieScanlon
Ttfn
Paul