@bernierllc/contentful-rich-text
v1.0.3
Published
Rich text rendering for Contentful content to HTML, Markdown, and React components
Readme
@bernierllc/contentful-rich-text
Rich text rendering for Contentful content to HTML, Markdown, and React components.
Installation
npm install @bernierllc/contentful-rich-textFor React rendering support:
npm install @bernierllc/contentful-rich-text reactFeatures
- HTML Rendering: Convert Contentful rich text to HTML strings
- Markdown Rendering: Convert Contentful rich text to Markdown
- React Rendering: Convert Contentful rich text to React components (requires React peer dependency)
- Plain Text Extraction: Extract plain text from rich text documents
- Custom Renderers: Override default rendering for specific node types
- Embedded Content: Handle embedded entries and assets
- Hyperlink Support: Full support for hyperlinks, entry links, and asset links
- Text Marks: Handle bold, italic, underline, and code formatting
Usage
Basic HTML Rendering
import { ContentfulRichTextRenderer } from '@bernierllc/contentful-rich-text';
import { Document } from '@contentful/rich-text-types';
const renderer = new ContentfulRichTextRenderer();
const document: Document = {
nodeType: 'document',
data: {},
content: [
{
nodeType: 'paragraph',
data: {},
content: [
{
nodeType: 'text',
value: 'Hello, world!',
marks: [],
data: {}
}
]
}
]
};
const html = renderer.toHTML(document);
console.log(html); // <p>Hello, world!</p>Markdown Rendering
const markdown = renderer.toMarkdown(document);
console.log(markdown); // Hello, world!Plain Text Extraction
const plainText = renderer.toPlainText(document);
console.log(plainText); // Hello, world!React Rendering
import React from 'react';
// React must be installed as a peer dependency
const reactComponent = renderer.toReact(document);
// Use in your React app
function MyComponent() {
return <div>{reactComponent}</div>;
}Custom Node Renderers
import { BLOCKS, INLINES } from '@bernierllc/contentful-rich-text';
const html = renderer.toHTML(document, {
renderNode: {
[BLOCKS.EMBEDDED_ENTRY]: (node) => {
const id = node.data?.target?.sys?.id;
return `<div class="custom-entry" data-id="${id}">Custom Entry</div>`;
},
[BLOCKS.EMBEDDED_ASSET]: (node) => {
const asset = node.data?.target;
const url = asset?.fields?.file?.url;
return url ? `<figure><img src="${url}" /></figure>` : '';
}
}
});Custom Text Renderer
const html = renderer.toHTML(document, {
renderText: (text) => text.toUpperCase()
});Custom Mark Renderer
import { MARKS } from '@bernierllc/contentful-rich-text';
const html = renderer.toHTML(document, {
renderMark: {
[MARKS.BOLD]: (text) => `<strong class="custom-bold">${text}</strong>`
}
});Renderer with Default Options
import { createRenderer } from '@bernierllc/contentful-rich-text';
const customRenderer = createRenderer({
renderNode: {
[BLOCKS.PARAGRAPH]: (node, next) => {
return `<p class="custom-paragraph">${next(node.content)}</p>`;
}
}
});
// All renders will use the custom paragraph renderer
const html = customRenderer.toHTML(document);Using withOptions
const baseRenderer = new ContentfulRichTextRenderer();
const customRenderer = baseRenderer.withOptions({
renderText: (text) => text.trim()
});
// Override default options for specific renders
const html = customRenderer.toHTML(document, {
renderText: (text) => text.toUpperCase()
});API Reference
ContentfulRichTextRenderer
Methods
toHTML(document: Document, options?: RichTextRenderOptions): string
Converts a Contentful rich text document to an HTML string.
Parameters:
document: Contentful rich text documentoptions: Optional custom rendering options
Returns: HTML string
toMarkdown(document: Document, options?: RichTextRenderOptions): string
Converts a Contentful rich text document to Markdown.
Parameters:
document: Contentful rich text documentoptions: Optional custom rendering options
Returns: Markdown string
toReact(document: Document, options?: RichTextRenderOptions): React.ReactNode
Converts a Contentful rich text document to React components.
Requires: React peer dependency
Parameters:
document: Contentful rich text documentoptions: Optional custom rendering options
Returns: React node
Throws: Error if React is not installed
toPlainText(document: Document): string
Extracts plain text from a Contentful rich text document.
Parameters:
document: Contentful rich text document
Returns: Plain text string
withOptions(defaultOptions: RichTextRenderOptions): ContentfulRichTextRenderer
Creates a new renderer instance with default options applied.
Parameters:
defaultOptions: Default rendering options
Returns: New renderer instance
RichTextRenderOptions
interface RichTextRenderOptions {
renderNode?: {
[nodeType: string]: (node: Node, next: (nodes: Node[]) => string | React.ReactNode) => string | React.ReactNode;
};
renderMark?: {
[markType: string]: (text: string) => string | React.ReactNode;
};
renderText?: (text: string) => string;
}createRenderer
function createRenderer(options?: RichTextRenderOptions): ContentfulRichTextRendererFactory function to create a new renderer instance with optional default options.
Embedded Content
Embedded Entries
By default, embedded entries are rendered as:
<div class="embedded-entry" data-id="entry-id">Embedded Entry: entry-id</div>Inline embedded entries:
<span class="embedded-entry-inline" data-id="entry-id">Embedded Entry: entry-id</span>Embedded Assets
By default, embedded assets with images are rendered as:
<img src="asset-url" alt="asset-title" class="embedded-asset" />Hyperlinks
Standard hyperlinks:
<a href="url" target="_blank" rel="noopener noreferrer">Link Text</a>Entry hyperlinks:
<a href="/entry/entry-id" class="entry-link">Link Text</a>Asset hyperlinks:
<a href="/asset/asset-id" class="asset-link">Link Text</a>Supported Node Types
- Blocks:
DOCUMENT,PARAGRAPH,HEADING_1throughHEADING_6,UL_LIST,OL_LIST,LIST_ITEM,BLOCKQUOTE,HR,EMBEDDED_ENTRY,EMBEDDED_ASSET - Inlines:
HYPERLINK,ENTRY_HYPERLINK,ASSET_HYPERLINK,EMBEDDED_ENTRY - Marks:
BOLD,ITALIC,UNDERLINE,CODE
TypeScript Support
This package is written in TypeScript and includes full type definitions.
import {
ContentfulRichTextRenderer,
RichTextRenderOptions,
RichTextDocument,
BLOCKS,
INLINES,
MARKS
} from '@bernierllc/contentful-rich-text';Integration Documentation
This is a core package that provides pure rich text rendering functionality with zero external dependencies beyond Contentful types. As a core package, it does not include logger or NeverHub integrations.
Logger Integration
Not applicable - this is a stateless rendering library that does not perform operations requiring logging. Applications consuming this package may add their own logging around render operations if needed.
NeverHub Integration
Not applicable - this package provides pure rendering functions without side effects or external service interactions. It operates entirely in-memory and does not require NeverHub coordination.
Design Philosophy
This package follows the core package pattern:
- Zero side effects: Pure functions only
- Minimal dependencies: Only Contentful types required
- Stateless operations: No internal state management
- Framework agnostic: Works in any JavaScript/TypeScript environment
Applications integrating this package can wrap rendering operations with their own:
- Error logging via
@bernierllc/logger - Performance monitoring
- Analytics tracking
- Cache management
Related Packages
- @bernierllc/contentful-types - TypeScript types for Contentful
- @contentful/rich-text-types - Contentful rich text types
License
Copyright (c) 2025 Bernier LLC. See LICENSE file for details.
