@nuxtjs/prismic v4 - changes to the rich-text-serializer

I have a Nuxt project. I just updated all my dependencies and noticed some breaking changes moving to v4 of "@nuxtjs/prismic"

"@nuxtjs/prismic": "^4.0.1",

What seems to be affected are the <PrismicRichText /> blocks. I have added a wrapper div to all of them to keep my styling as it was since the default wrapper has been removed.

But I have a problem understanding what needs to be done to make the htmlSerializer work again. What I had was the following:

// ./prismic/htmlSerializer.ts

export const htmlSerializer: prismicH.HTMLMapSerializer = {
  paragraph: ({ children }) => {
    //...
  },
  hyperlink: ({ children, node }) => {
    //...
  },
  label: ({ node, children }) => {
    //...
  },
}
<script setup lang="ts">
import { htmlSerializer } from '@/prismic/htmlSerializer'
</script>

<template>
      <PrismicRichText
        :field="props.slice.primary.content"
        :html-serializer="htmlSerializer"
        wrapper="div"
      />
</template>

This does not seem to be working anymore.

I found this here: @prismicio/vue - v5 - Documentation - Prismic - but it is not very clear I find.

Would appreciate tips on how to fix this...

Thanks.

PS: besides the PrismicRichText, is there something else I should be looking at?

Your Role

Developer

Package.json file


  "dependencies": {
    "@prismicio/helpers": "^2.3.9",
    "nuxt": "^3.15.4",
  },
  "devDependencies": {
    "@nuxtjs/prismic": "^4.0.1",
    "@slicemachine/adapter-nuxt": "^0.3.66",
    "slice-machine-ui": "^2.12.3"
  }

Hi @leopold,

Just to clarify, you did the move from v3 -> v4? Is it just the htmlSerializer not working, are you getting any specific error related to it? The documentation for Vue v4 mentions this:

You can check it out here: @prismicio/vue - v4 - Documentation - Prismic, maybe that will help?

The link you referred to is for v5, so that might be a different step altogether. You could also try upgrading to v5 and see if it fixes it!

Yes, I moved from

"@nuxtjs/prismic": "^3.4.5",

to:

"@nuxtjs/prismic": "^4.0.1",

and @nuxtjs/prismic v4 uses @prismicio/vue v5 if I understand correctly

This is what I was looking for:

1 Like

Ah excellent, good eye! Has that solved it for you? :slight_smile:

Yes, and no.

This works, but seems to be deprecated. The following gets logged to the console after setting things up the following way:

import { htmlSerializer } from '@/prismic/htmlSerializer'

      <PrismicRichText
        :field="someField"
        :serializer="() => htmlSerializer"
        wrapper="div"
      />

[PrismicRichText] You're using the deprecated version of <PrismicRichText> because either the serializer prop or the plugin richTextSerializer option were provided. This API will be removed in a future major.

If you have info on how to refactor this to be future proof, I would appreciate that.

Hi @leopold, sorry for the delay getting back to you!

With @prismicio/vue v5, we deprecated the old HTML-based serializer in favor of a more secure and flexible component-based serializer (no v-html) and flexible (component-based).

I noticed we had an issue with the link that should have been added to the warning you shared, I just published a fix.

This guide should help you understand how to migrate from the old serializer (HTML-based), to the new one components: prismic-vue/messages/html-serialization-is-deprecated-with-prismic-rich-text.md at master · prismicio/prismic-vue · GitHub

Let us know if that helps you, we'll also work on improving the documentation in that regard!

1 Like

I noticed we had an issue with the link that should have been added to the warning you shared, I just published a fix.

Yes. Thanks, exactly the link in the warning was broken.

I will try following the example in the guide you shared.

In the link you provided there is an example for h2.

<script setup lang="ts">
import { getRichTextComponentProps } from "@prismicio/vue"

defineProps(getRichTextComponentProps())
</script>

<template>
	<h2><slot /></h2>
</template>

Could you provide a slightly more advanced example, for example a hyperlink? I am wondering about the correct approach to extracting and working with the props from defineProps(getRichTextComponentProps()).

The following works, but is it the correct way? Also wondering about TS, since props.node can be many different types in this case.

const props = defineProps(getRichTextComponentProps())
const myFinalText = props.node.text + ' - ' + 'test'
const myFinalUrl = props.node.data.url + ' - ' + 'test'

I find the recommended solution a bit verbose.

We have hundreds of PrismicRichText in our projects and updating all of them to just add a new prop`` components` seems too much. Also adding one file per component is too much, since the component we require in the serializer are simple.

So using VueUse createReusableTemplate I created this:

<script setup lang="ts">
import type { RTLabelNode } from '@prismicio/client'
import type { PrismicRichTextProps } from '@prismicio/vue'

const props = defineProps<PrismicRichTextProps>()

const [DefineLabel, ReuseLabel] = createReusableTemplate<{ node: RTLabelNode & { text: string } }>()

const components = {
  label: ReuseLabel,
}
</script>

<template>
  <DefineLabel v-slot="{ node: { data, text } }">
    <template v-if="data?.label === 'HTML'">
      <div v-html="text" />
    </template>
  </DefineLabel>
  <PrismicRichText v-bind="props" :components />
</template>

So all the rich text related components stays in just one component. This is just a simple example if anyone is interested :)

Note: I could find the proper types for the RTNodeLabel as they are missing the field text. If you know a better way to type the props, please let me know, thank you!

2 Likes

Thanks for sharing @soeren - great to have the discussion here.