Contentful Rich Text Vue Renderer
The `contentful-rich-text-vue-renderer` package, currently at stable version 3.2.1, provides a robust solution for rendering Contentful Rich Text fields within Vue 3 applications. It parses the Contentful Rich Text JSON structure and converts it into native Vue components, allowing for seamless integration of rich content. The library is actively maintained with regular patch and minor releases, as evidenced by recent updates fixing warnings and adding support for new marks. A key differentiator is its direct compatibility with Vue 3's composition API and rendering functions (e.g., `h`), while older 2.x versions supported Vue 2. It requires `@contentful/rich-text-types` as a peer dependency, which defines the expected structure of the rich text document and its various node and mark types. This package simplifies displaying rich content managed in Contentful without needing to manually parse and render complex JSON structures. Releases typically include dependency updates and new feature support for rich text marks/nodes.
Common errors
-
[Vue warn]: Failed to resolve component: RichTextRenderer
cause The `RichTextRenderer` component was not correctly imported or registered in your Vue component.fixEnsure you have `import RichTextRenderer from 'contentful-rich-text-vue-renderer';` at the top of your script and that the component is registered (e.g., within the `components` option or automatically via `<script setup>`). -
TypeError: (0 , vue__WEBPACK_IMPORTED_MODULE_0__.h) is not a function
cause This error typically occurs when `h` is imported incorrectly from Vue (e.g., as a default import) or if you are using an older Vue 2 project structure with a Vue 3-targeted library.fixVerify that your project is configured for Vue 3 and that `h` is imported as a named export: `import { h } from 'vue';`. Also, ensure you are on `contentful-rich-text-vue-renderer@3.x.x`. -
npm ERR! ERESOLVE unable to resolve dependency tree ... contentful-rich-text-vue-renderer@3.2.1 requires a peer of @contentful/rich-text-types@^16.5.0 || ^17.0.0 but none was installed.
cause The peer dependency `@contentful/rich-text-types` is missing or its version does not satisfy the requirements of the renderer package.fixInstall the required peer dependency: `npm install @contentful/rich-text-types@^17.0.0` or `yarn add @contentful/rich-text-types@^17.0.0`. Adjust the version as needed to match the acceptable range.
Warnings
- breaking Version 3.0.0 introduced breaking changes by migrating the renderer to support Vue 3. Projects using Vue 2 must remain on `contentful-rich-text-vue-renderer` versions 2.x.x.
- gotcha In versions prior to 3.2.1, the `RichTextRenderer` component might emit 'extraneous non-props attributes' warnings in Vue 3 due to attributes being passed down without explicit handling.
- breaking Version 2.0.0 of this library (for Vue 2 projects) dropped support for Node.js 8. While not directly affecting Vue 3, it's a historical breaking change for older Node.js environments.
- gotcha The library depends on `@contentful/rich-text-types` as a peer dependency. Failure to install it, or a version mismatch outside the specified range (`^16.5.0 || ^17.0.0`), can lead to runtime errors or build failures.
Install
-
npm install contentful-rich-text-vue-renderer -
yarn add contentful-rich-text-vue-renderer -
pnpm add contentful-rich-text-vue-renderer
Imports
- RichTextRenderer
const RichTextRenderer = require('contentful-rich-text-vue-renderer');import RichTextRenderer from 'contentful-rich-text-vue-renderer';
- h
import h from 'vue';
import { h } from 'vue'; - BLOCKS, MARKS
import { BLOCKS, MARKS } from 'contentful-rich-text-vue-renderer';import { BLOCKS, MARKS } from '@contentful/rich-text-types';
Quickstart
<script setup>
import { h } from 'vue';
import { BLOCKS, MARKS } from '@contentful/rich-text-types';
import RichTextRenderer from 'contentful-rich-text-vue-renderer';
const document = {
nodeType: 'document',
content: [
{
nodeType: 'paragraph',
content: [
{
nodeType: 'text',
value: 'Hello',
marks: [{ type: 'bold' }]
},
{
nodeType: 'text',
value: ' world!',
marks: [{ type: 'italic' }]
}
]
},
{
nodeType: 'embedded-entry-block',
data: {
target: { sys: { id: 'some-entry-id', type: 'Link', linkType: 'Entry' } }
},
content: []
}
]
};
const renderMarks = () => ({
[MARKS.BOLD]: (text, key) => h('strong', { key, style: { color: 'blue' } }, text)
});
const renderNodes = () => ({
[BLOCKS.PARAGRAPH]: (node, key, next) => h('p', { key, class: 'custom-paragraph' }, next(node.content, key, next)),
[BLOCKS.EMBEDDED_ENTRY]: (node, key) => h('div', { key, class: 'embedded-content' }, `Embedded Entry: ${node.data.target.sys.id}`)
});
</script>
<template>
<RichTextRenderer
:document="document"
:nodeRenderers="renderNodes()"
:markRenderers="renderMarks()"
/>
</template>