npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@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-text

For React rendering support:

npm install @bernierllc/contentful-rich-text react

Features

  • 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 document
  • options: 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 document
  • options: 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 document
  • options: 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): ContentfulRichTextRenderer

Factory 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_1 through HEADING_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

License

Copyright (c) 2025 Bernier LLC. See LICENSE file for details.