Templating Rich Text fields

Learn how to template your Rich text and Title fields.


🕙 Before Reading

This page assumes that you have:

1. Already imported the prismic-reactjs library, as shown below.

import { RichText } from 'prismic-reactjs';

2. Retrieved your content and stored it in a state variable named document.

3. Imported a Link Resolver with the variable name linkResolver. To learn more about this, check out the Link Resolving page. 

Template Rich Text & Title fields

Rich Text and Titles are delivered in an array that contains information about the text structure. Here's an example of a Rich Text field (Title fields follow the same format):

Copy
"example_rich_text": {
  "html": "<p>The future is here.</p>",
  "raw": [
    {
      "type": "paragraph",
      "text": "The future is here.",
      "spans": []
    }
  ],
  "text": "The future is here."
}

Render as HTML

The basic usage of the Rich Text or Title field is to use the <RichText /> component to transform the Rich Text content into HTML using the raw option of the field:

Copy
<RichText render={document.example_rich_text.raw} />

Render as plain text

Occasionally, you may require to render not a component but a simple string. To do so, render the text option of the field:

Copy
<h1>{document.example_rich_text.text}</h1>

Links in Rich text fields

If your Rich text field has links to internal documents and/or external URLs, you'll want to render them appropriately with either Gatsby Link to handle internal links or custom links as React router dom Link instead of <a> tags. For that, you can use serializeHyperlink.

In this example, we provide you with a full component that will render the appropriate custom link depending on the type of the link_type that is being passed to the Rich text field and we show you an example of how to pass the customLink to the serializeHyperlink option:

  • CustomLink.js
  • Example usage
Copy
import React from 'react'
import { Link } from 'gatsby'
import { Link as PrismicLink } from 'prismic-reactjs'
import linkResolver from '../example_path_to_linkResolver'

const CustomLink = (type, element, content, children, index) => {
  if (element.data.link_type === 'Document') {
    return (
      <Link to={linkResolver(element.data)} key={element.data.id}>
        {content}
      </Link>
    )
  }

  if (element.data.link_type === 'Web') {
    <PrismicLink key={element.data.id} to={linkResolver(element.data)}>
      <a>{content}</a>
    </PrismicLink>
  }
  return null
}

export default CustomLink
Copy
import CustomLink from '../example_path_to_CustomLink'

const MyComponent = (document) => (
  <div>
    <RichText
      render={document.example_text_with_links}
      serializeHyperlink={CustomLink}
    />
  </div>

export default MyComponent

ℹ️ Link Resolver

In the previous example, the RichText component has a linkResolver property where you can pass in a Link Resolver function. This is necessary to provide the correct URL for any Link to a Document that exists in your Rich Text content.

To learn more about how to set up a Link Resolver, check out our Link Resolving page.

The HTML Serializer

🕙 Before Reading

For this serializer to work, you must ensure that you are using the prismic-reactjs kit version 1.3.0 or higher, as well as the gatsby-source-prismic plugin.

The HTML Serializer defines the markup of your Rich Text. (For example, italic text should have <em> tags.) prismic-reactjs contains a default HTML Serializer for standard markup, but you can create your own HTML Serializer if you want to customize your markup.

If serializeHyperlink is not enough, you can alternatively pass an htmlSerializer function to customize the HTML output of a Rich Text Field. This allows you to add custom classes to certain elements or add a target element to all hyperlinks.

To use it, all you need to do is pass the HTML Serializer function into the property of a RichText component that is rendering a Rich Text field.

Copy
<RichText render={document.example_rich_text.raw} htmlSerializer={htmlSerializer} />

Here are two examples of an HTML Serializer.

1. First example: This HTML Serializer will prevent image elements from being wrapped in paragraph tags and add a custom class to all hyperlink and paragraph elements.

2. Second example: This HTML Serializer shows you how to change all of the available Rich Text elements. The examples render the normal output of each field, so you can modify any of these to get your desired results.

  • 1st example
  • 2nd example
Copy
import React from 'react'
import { Elements } from 'prismic-richtext'
import { linkResolver } from './example_path_to_linkResolver'

// -- Function to add unique key to props
const propsWithUniqueKey = function(props, key) {
  return Object.assign(props || {}, { key })
}

// -- HTML Serializer
// This function will be used to change the way the HTML is loaded
const htmlSerializer = function(type, element, content, children, key) {
  var props = {}

  switch(type) {
    // Add a class to paragraph elements
    case Elements.paragraph:
      props = {className: 'paragraph-class'}
      return React.createElement('p', propsWithUniqueKey(props, key), children)

    // Don't wrap images in a <p> tag
    case Elements.image:
      props = { src: element.url , alt: element.alt || '' }
      return React.createElement('img', propsWithUniqueKey(props, key))

    // Add a class to hyperlinks
    case Elements.hyperlink:
      const targetAttr = element.data.target ? { target: element.data.target } : {}
      const relAttr = element.data.target ? { rel: 'noopener' } : {}
      props = Object.assign({
        className: 'link-class',
        href: element.data.url || linkResolver(element.data)
      }, targetAttr, relAttr)
      return React.createElement('a', propsWithUniqueKey(props, key), children)

    // Return null to stick with the default behavior
    default:
      return null
  }
}

export default htmlSerializer
Copy
import React from 'react'
import { Elements } from 'prismic-richtext'
import { linkResolver } from './example_path_to_linkResolver'
import { Link as PrismicLink } from 'prismic-reactjs'
import { Link } from "gatsby"

// -- Function to add unique key to props
const propsWithUniqueKey = function(props, key) {
console.log(key)
  return Object.assign(props || {}, { key })
}

// -- HTML Serializer
const htmlSerializer = function(type, element, content, children, key) {
  var props = {}

  switch(type) {
    case Elements.heading1: // Heading 1
      return React.createElement('h1', propsWithUniqueKey(props, key), children)

    case Elements.heading2: // Heading 2
      return React.createElement('h2', propsWithUniqueKey(props, key), children)

    case Elements.heading3: // Heading 3
      return React.createElement('h3', propsWithUniqueKey(props, key), children)

    case Elements.heading4: // Heading 4
      return React.createElement('h4', propsWithUniqueKey(props, key), children)

    case Elements.heading5: // Heading 5
      return React.createElement('h5', propsWithUniqueKey(props, key), children)

    case Elements.heading6: // Heading 6
      return React.createElement('h6', propsWithUniqueKey(props, key), children)

    case Elements.paragraph: // Paragraph
      return React.createElement('p', propsWithUniqueKey(props, key), children)

    case Elements.preformatted: // Preformatted
      return React.createElement('pre', propsWithUniqueKey(props, key), children)

    case Elements.strong: // Strong
      return React.createElement('strong', propsWithUniqueKey(props, key), children)

    case Elements.em: // Emphasis
      return React.createElement('em', propsWithUniqueKey(props, key), children)

    case Elements.listItem: // Unordered List Item
      return React.createElement('li', propsWithUniqueKey(props, key), children)

    case Elements.oListItem: // Ordered List Item
      return React.createElement('li', propsWithUniqueKey(props, key), children)

    case Elements.list: // Unordered List
      return React.createElement('ul', propsWithUniqueKey(props, key), children)

    case Elements.oList: // Ordered List
      return React.createElement('ol', propsWithUniqueKey(props, key), children)

    case Elements.image: // Image
      const linkUrl = element.linkTo ? element.linkTo.url || linkResolver(element.linkTo) : null
      const linkTarget = (element.linkTo && element.linkTo.target) ? { target: element.linkTo.target } : {}
      const linkRel = linkTarget.target ? { rel: 'noopener' } : {}
      const img = React.createElement('img', { src: element.url , alt: element.alt || '' })
      return React.createElement(
        'p',
        propsWithUniqueKey({ className: [element.label || '', 'block-img'].join(' ') }, key),
        linkUrl ? React.createElement('a', Object.assign({ href: linkUrl }, linkTarget, linkRel), img) : img
      )

    case Elements.embed: // Embed
      props = Object.assign({
        "data-oembed": element.oembed.embed_url,
        "data-oembed-type": element.oembed.type,
        "data-oembed-provider": element.oembed.provider_name,
      }, element.label ? {className: element.label} : {})
      const embedHtml = React.createElement('div', {dangerouslySetInnerHTML: {__html: element.oembed.html}})
      return React.createElement('div', propsWithUniqueKey(props, key), embedHtml)

    case Elements.hyperlink: // Hyperlinks
      let result = ''
      const url = PrismicLink.url(element.data, linkResolver)
      if (element.data.link_type === 'Document') {
        result = <Link to={ url } key={ key }>{ content }</Link>
      } else {
        const targetAttr = element.data.target ? { target: element.data.target } : {}
        const relAttr = element.data.target ? { rel: 'noopener' } : {}
        props = Object.assign({
          href: element.data.url || linkResolver(element.data)
        }, targetAttr, relAttr)
        result = React.createElement('a', propsWithUniqueKey(props, key), children)
      }
      return result

    case Elements.label: // Label
      props = element.data ? Object.assign({}, { className: element.data.label }) : {}
      return React.createElement('span', propsWithUniqueKey(props, key), children)

    case Elements.span: // Span
      if (content) {
        return content.split("\\n").reduce((acc, p) => {
          if (acc.length === 0) {
            return [p]
          } else {
            const brIndex = (acc.length + 1)/2 - 1
            const br = React.createElement('br', propsWithUniqueKey({}, brIndex))
            return acc.concat([br, p])
          }
        }, [])
      } else {
        return null
      }

    default: // Always include a default that returns null
      return null
  }
}

export default htmlSerializer