Rich Text HTML Renderer
Converts Contentful Rich Text documents into clean, customizable HTML strings.
Repository Health
Technical Analysis
@contentful/rich-text-html-renderer turns the JSON-based Rich Text field type from Contentful’s CMS into an HTML string, handling every standard node type — paragraphs, headings, lists, tables, quotes, embedded entries and assets, and inline hyperlinks — out of the box. It ships as part of the official contentful/rich-text monorepo alongside the type definitions, plain-text renderer, and React renderer, so it shares the same Document/Block/Inline types and BLOCKS/INLINES/MARKS constants used across the Contentful ecosystem.
Rather than hard-coding markup, the library exposes renderNode and renderMark override maps that merge with sensible defaults, letting consumers replace how any single node or text mark is rendered without reimplementing the whole traversal. Options like preserveWhitespace and stripEmptyTrailingParagraph handle the practical edge cases teams hit when moving Rich Text content into static HTML, emails, or server-rendered pages, and every text value is HTML-escaped by default to guard against injection from user-authored content.
What You Get
- Default HTML renderers for every standard Rich Text block and inline node (paragraphs, headings 1-6, lists, tables, blockquotes, embedded entries/assets, hyperlinks)
- Overridable renderNode and renderMark maps that merge with the defaults so you only replace what you need
- Built-in HTML escaping (escapeHtml) for text values, attribute values, and asset URLs/descriptions
- preserveWhitespace option to convert line breaks and repeated spaces into <br/>/ sequences
- stripEmptyTrailingParagraph option to drop the empty trailing paragraph Contentful’s editor often appends
Common Use Cases
- Rendering a Contentful Rich Text field directly to HTML for a server-rendered page or static site
- Generating HTML email bodies from Rich Text content authored in Contentful
- Customizing how embedded entries/assets render (e.g. swapping the default <div>/<img> output for themed component markup)
- Enforcing consistent HTML escaping when Rich Text content includes user-generated or untrusted text
Under The Hood
Architecture The package is a single-file recursive tree-walker: documentToHtmlString (src/index.ts) merges the caller’s optional renderNode/renderMark maps over defaultNodeRenderers/defaultMarkRenderers, then delegates to nodeListToHtmlString and nodeToHtmlString, which recursively distinguish text nodes from block/inline nodes and thread the merged renderer maps through closures rather than a class or DI container. There is no separate rendering pipeline stage — the recursion itself is the pipeline — so changing the core traversal in nodeToHtmlString would ripple into every consumer’s custom NodeRenderer/RenderMark signatures, since those types are exported and threaded through the whole call chain.
Tech Stack Written in TypeScript, compiled with tsc and bundled by Rollup (rollup.config.js) into ES5/ESM builds plus a types bundle, managed as an Nx-orchestrated pnpm workspace (nx.json, pnpm-workspace.yaml) alongside sibling packages in the same monorepo. Its only runtime dependency is the sibling @contentful/rich-text-types package for shared Document/Block/Mark types and BLOCKS/INLINES/MARKS constants. CI runs through GitHub Actions (ci.yml, check.yaml, build.yaml, release.yaml) with commitlint and husky enforcing conventional commits for release automation.
Code Quality A single, extensive test file (src/test/index.test.ts) exercises every default node and mark renderer, override behavior, escaping, preserveWhitespace, and stripEmptyTrailingParagraph, with fixture documents factored into a separate documents/ directory rather than inlined. Tests run under @swc/jest with jest-junit reporting for CI consumption. TypeScript interfaces (RenderNode, RenderMark, Options, Next) give consumers compile-time safety on custom renderers, and the monorepo enforces ESLint plus Prettier via lint-staged/husky pre-commit hooks.
What Makes It Unique The library isn’t algorithmically novel — it’s a straightforward tree-walk-to-string serializer — but its renderer-override design (a shallow merge of caller overrides over ~20 defaults, for both nodes and marks) lets a consumer replace exactly one rendering rule without redefining the rest, and it bakes in Contentful-specific edge cases — trailing empty paragraph stripping, escaped asset URLs/descriptions, default markup for embedded entries/assets/resources — that generic Markdown-to-HTML renderers don’t address.
Used by 4 apps in this directory
overleaf
Collaboration · Productivity
Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.
overleaf
Collaboration · Productivity
Open-source, real-time collaborative LaTeX editor with sandboxed compilation and full TeXLive support for self-hosted academic and research teams.
Plasmic
CMS · Low Code Platforms · No Code Platforms
The open-source visual builder that lets teams design React apps and websites with drag-and-drop while integrating seamlessly with your codebase.
Plasmic
CMS · Low Code Platforms · No Code Platforms
The open-source visual builder that lets teams design React apps and websites with drag-and-drop while integrating seamlessly with your codebase.