Advanced Templating

On this page, you'll learn how to add further configuration to Prismic content in your Vue app with an HTML Serializer.


The HTML Serializer

You can customize the HTML output of a Rich Text Field with a custom HTML Serializer. An HTML Serializer defines how Rich Text content should be interpreted in your code. For instance: the default HTML Serializer dictates that italicized text should be rendered inside <em> tags.

If your project is configured with Prismic, it should already have a default HTML Serializer integrated. If you would like to add custom formatting, you can add a custom HTML Serializer as needed.

How an HTML Serializer Works

The HTML Serializer is a function. It works by taking a Rich Text element and evaluating it through a switch statement to determine how to render it. If your custom HTML Serializer doesn't have a case for the element, it should return null. Then the default HTML Serializer will take over and render the element.

The HTML Serializer receives the following arguments:

  • type: the type of the element, such as "paragraph" or "list-item"
  • element: the complete element, represented as an object
  • content: the string content of the element
  • children: any children contained within the element

You can define a local HTML Serializer and pass it as a property to the RichText component, or you can define a global HTML Serializer to be used automatically on all Rich Text elements.

Using a custom HTML Serializer locally

You can define a simple HTML Serializer in your code like so:

Copy
<template>
  <div>
    <!-- Pass the HTML Serializer to your rich text component. -->
    <prismic-rich-text :field="document.data.description" :htmlSerializer="htmlSerializer" />
  </div>
</template>

<script>
export default {
  async asyncData({ $prismic, params, error }) {
    const document = await $prismic.api.getSingle("homepage")
    return { document };
  },
  methods: {
    htmlSerializer(type, element, content, children) {
      // If element is a list item,
      if (type === "list-item") {
        // return some customized HTML.
        return `<li class="example-class">${children.join("")}</li>`;
      }
      /// Otherwise, return null.
      return null;
    }
  }
};
</script>

Using a custom HTML Serializer globally

It may be necessary to declare a global HTML Serializer that will be applied to every <prismic-rich-text/> component in your Vue app.

Rendering Vue Links

If you are using vue-router, you will need a global HTML Serializer to render your links as <router-links> elements rather than <a> elements. While <a> links will work, they won't use client-side routing, defeating the purpose of vue-router.

To declare a global HTML Serializer, create an htmlSerializer and pass it as an option to your Vue instance.

To create your global HTML Serializer, you can create a file ~/src/html-serializer.js:

Copy
import prismicDOM from 'prismic-dom'
import linkResolver from './link-resolver' // Update the path to your Link Resolver

const Elements = prismicDOM.RichText.Elements

export default function(type, element, content, children) {
  const url = prismicDOM.Link.url(element.linkTo, linkResolver)

  // Generate links to Prismic Documents as <router-link> components
  if (type === Elements.hyperlink) {
    if (element.data.link_type === 'Document') {
      return `<router-link to="${url}">${children.join('')}</router-link>`
    }
  }

  // If the image is also a link to a Prismic Document, it will return a <router-link> component
  if (type === Elements.image) {
    if (element.linkTo) {
      if (element.linkTo.link_type === 'Document') {
        return `<img src="${element.url}" alt="${element.alt ||
          ''}" copyright="${element.copyright || ''}">`
      }
    }
  }

  // Return null to stick with the default behavior for everything else
  return null
}

What is a Link Resolver?

A Link Resolver tells Vue how to structure relative URLs for your content. Learn more on the setup page.

Then, pass the HTML Serializer as an option in your Vue instance:

Copy
import Vue from 'vue'
import App from './App'
import PrismicVue from '@prismicio/vue'
import linkResolver from './link-resolver' // Update this path
import htmlSerializer from './html-serializer' // Update this path

const accessToken = '' // Leave empty if your repo is public
const endpoint = 'https://your-repo-name.cdn.prismic.io/api/v2' // Use your repo name

// Register plugin
Vue.use(PrismicVue, {
  endpoint,
  apiOptions: { accessToken },
  linkResolver,
  htmlSerializer
})

// Create a Vue instance
new Vue({
  render: (h) => h(App)
}).$mount('#app')

Now the markup defined in your HTML Serializer will apply to all Rich Text and Title fields in your project. If your serializer returns null for an element, the default serializer will render the element.