HTML Serializer
You can customize the HTML output of a Rich Text Field by incorporating an HTML Serializer into your project. This allows you to do things like adding custom classes to certain elements or modifying the way an element will be displayed.
Before Reading
In order for this serializer to work, you must ensure that you are using the prismic-reactjs kit version 0.3.0 or higher.
To be able to modify the HTML output of a Rich Text, you need to first create the HTML Serializer functions. You will need functions that do the following:
- Add the unique key to an element's properties
- Serialize the HTML elements
The serializer will need to identify the element by type and return the desired output.
Make sure to add a default case that returns null. This will leave all the other elements untouched.
Here is an example of an HTML Serializer that will prevent image elements from being wrapped in paragraph tags and add a custom class to all hyperlink and paragraph elements.
import React from 'react';
import { RichText, Elements } from 'prismic-reactjs';
// -- 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;
}
};
Note that if you want to change the output for the hyperlink element, 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} />
Here is an example that shows you how to change all of the available Rich Text elements.
These give the normal output of each field, so modify any of these to get your desired results.
import React from 'react';
import { RichText, Elements } from 'prismic-reactjs';
// -- Function to add unique key to props
const propsWithUniqueKey = function(props, 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: // Image
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.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;
}
};
As mentioned above, if you want to change the output for the hyperlink element or an image with a link, you will need to use a Link Resolver function. You can read more about this on the Link Resolving page.