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>.
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.
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.
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} />