HTML Serializer

The HTML Serializer is a function that processes rich text fields. It enables you to customize the markup of your text content. An HTML Serializer function takes a rich text element from Prismic and specifies how that content should be rendered in HTML. The prismic-reactjs plugin has a built-in serializer that handles text rendered by the <RichText /> component, but you can also define your own HTML Serializer.

A practical use of the HTML Serializer is processing labels in the Prismic Rich Text Editor. For example, it's common, to define an "inline-code" label in the Rich Text Editor for snippets like this. By default, the <RichText /> component will render that text as <span class='inline-code'>{children}</span>. Using the HTML serializer, you could render it as <code>{children}</code>.

Configuring the HTML Serializer as a helper function.

Content writers may add links to internal documents as part of Rich Text fields. By default, this will be simple <a href> elements which does not make for an optimal, consistent navigation experience. This is why it's important to provide an automated method for these user-created links to be handled with client-side routing as well, without the need of reloading the web application.

The best approach to do this is setting up an HTML serializer helper function that will modify the <a href> elements when rendering Rich Text. However, instead of outright replacing them for <Link> elements, it's better to modify their onClick behavior so that they perform an imperative router push, effectively replicating the behavior of Next's Link component. The reason for this roundabout approach is that replacing <a> directly for <Link> elements won't trigger the same associated behavior.

HTML Serializer Example

Below you can find an example HTML Serializer function that will handle both regular links and links added to images for internal documents.

import React from 'react'
import { RichText } from 'prismic-reactjs'
import { linkResolver } from 'path/to/linkResolver'
import { hrefResolver } from 'path/to/hrefResolver'
import Router from 'next/router'

const Elements = RichText.Elements
const onClickHandler = function (href, as) {
  // Handler that will do routing imperatively on internal links
  return e => {
    e.preventDefault()
    Router.push(href, as)
  }
}

const propsWithUniqueKey = function (props, key) {
  return Object.assign(props || {}, { key })
}

export const htmlSerializer = function (type, element, content, children, key) {
  var props = {}
  switch (type) {
    case Elements.hyperlink: // Link
      if (element.data.link_type === 'Document') {
        // Only for internal links add the new onClick that will imperatively route to the appropiate page
        props = Object.assign({
          onClick: onClickHandler(hrefResolver(element.data), linkResolver(element.data)),
          href: linkResolver(element.data)
        })
        return React.createElement('a', propsWithUniqueKey(props, key), children)
      } else {
        // Default link handling
        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)
        return React.createElement('a', propsWithUniqueKey(props, key), children)
      }

    case Elements.image: // Image
      var props = {}
      var internal = false

      if (element.linkTo && element.linkTo.link_type === 'Document') {
        // Exclusively for internal links, build the object that can be used for router push
        internal = true
        props = Object.assign({
          onClick: onClickHandler(hrefResolver(element.linkTo), linkResolver(element.linkTo)),
          href: linkResolver(element.linkTo)
        })
      }
      // Handle images just like regular HTML Serializer
      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',
          // if it's an internal link, replace the onClick
          internal ? propsWithUniqueKey(props, key) : Object.assign({ href: linkUrl },
          linkTarget, linkRel), img) : img
      )

    default:
      return null
  }
}

export default htmlSerializer

💡Links

Note that if you want to change the path of the hyperlink, you will need to use a Link Resolver. You can read more about this on the Link Resolving page.

Using the serializer function

To use it, all you need to do is pass the Serializer function into the <RichText htmlSerializer={} /> property of a RichText component that is rendering a rich text field.

<RichText render={document.data.text_field} htmlSerializer={htmlSerializer} />
9 Rue de la Pierre Levée, 75011 Paris