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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@charlietango/umbraco-rich-text

v2.0.0

Published

React component for working with rich text from the Umbraco Content Delivery API.

Readme

Umbraco Rich Text

npm version License

Takes the JSON rich text output from the Umbraco Content Delivery API and renders it with React.

[!IMPORTANT]
You need to enable the RichTextOutputAsJson option in the Content Delivery API. See Content Delivery API configuration for details.

Open in StackBlitz

Install

Install the @charlietango/umbraco-rich-text package with your package manager of choice.

npm install @charlietango/umbraco-rich-text

<UmbracoRichText>

Props

  • element: The rich text property from the Umbraco Content Delivery API.
  • renderBlock: Render a specific block type. Return null to skip rendering the node.
  • renderNode: Overwrite the default rendering of a node. Return undefined to render the default node. Return null to skip rendering the node.
    • meta: A function you can call to retrieve metadata describing the current element’s ancestor, children, previous, and next siblings. The values are built lazily when you invoke the function, keeping memory lower when renderNode doesn’t need the metadata for a given node.
  • htmlAttributes: Default attributes to set on the defined HTML elements. These will be used, unless the element already has the attribute set. The only exception is the className attribute, which will be merged with the default value.
  • stripStyles: Remove inline style attributes from HTML elements. Accepts:
    • true: Removes all inline styles from all HTML elements
    • An object with configuration options:
      • tags: Array of HTML tags from which to strip styles. If not provided, styles are stripped from all tags.
      • except: Array of HTML tags that should keep their styles, even if they are in the tags array.
    • Default is false (all inline styles are preserved).

When passing the renderBlock and renderNode props, consider making them static functions (move them outside the consuming component) to avoid unnecessary re-renders.

import {
  UmbracoRichText,
  RenderBlockContext,
  RenderNodeContext,
} from "@charlietango/umbraco-rich-text";
import Image from "next/image";
import Link from "next/link";

function renderNode({ tag, children, attributes }: RenderNodeContext) {
  switch (tag) {
    case "a":
      return <Link {...attributes}>{children}</Link>;
    case "p":
      return (
        <p className="text-lg" {...attributes}>
          {children}
        </p>
      );
    default:
      // Return `undefined` to render the default HTML node
      return undefined;
  }
}

function renderBlock({ content }: RenderBlockContext) {
  switch (content?.contentType) {
    // Switch over your Umbraco document types that can be rendered in the Rich Text blocks
    case "imageBlock":
      return <Image {...content.properties} />;
    default:
      return null;
  }
}

function RichText({ data }) {
  return (
    <UmbracoRichText
      data={data.richText}
      renderNode={renderNode}
      renderBlock={renderBlock}
      htmlAttributes={{ p: { className: "mb-4" } }}
      stripStyles={{
        // Strip styles from all tags except the following:
        except: ["img"], // Keep styles on `img` tags
      }}
    />
  );
}

Blocks

You can augment the renderBlock method with the generated OpenAPI types from Umbraco Content Delivery API. That way you can correctly filter the blocks you are rendering, based on the contentType, and get the associated properties. Create types/umbraco-rich-text.d.ts, and augment the UmbracoBlockItemModel interface with your applications definition for ApiBlockItemModel.

To generate the types, you'll want to use the Delivery Api Extensions package, alongside a tool to generate the types from the OpenAPI schema, like openapi-typescript.

types/umbraco-rich-text.d.ts

// Import the `components` generated by OpenAPI TypeScript.
import { components } from "./umbraco-openapi";

// Define the intermediate interface
type ApiBlockItemModel = components["schemas"]["ApiBlockItemModel"];

declare module "@charlietango/umbraco-rich-text" {
  interface UmbracoBlockItemModel extends ApiBlockItemModel {}
}

richTextToPlainText

A utility function to convert an Umbraco RichText element to plain text. This can be useful for generating meta descriptions or other text-based properties.

Parameters

  • data (RichTextElementModel): The rich text element to be converted.
  • options (Options, optional): An object to specify additional options.
    • firstParagraph (boolean, optional): If true, only the first paragraph with text content will be returned.
    • maxLength (number, optional): The maximum length of the returned text. If the text exceeds this length, it will be truncated to the nearest word and an ellipsis will be added.
    • ignoreTags (Array<string>, optional): An array of tags to be ignored during the conversion.

Returns

  • string: The plain text representation of the rich text element.

Example

import { richTextToPlainText } from "@charlietango/umbraco-rich-text";

const plainText = richTextToPlainText(richTextData);

// Just the first paragraph
const firstParagraph = richTextToPlainText(richTextData, {
  firstParagraph: true,
});

// Just the first 100 characters, truncated at the nearest word with an ellipsis
const first100Characters = richTextToPlainText(richTextData, {
  maxLength: 100,
});

// Ignore certain tags, skipping their content
const ignoreTags = richTextToPlainText(richTextData, {
  ignoreTags: ["h1", "h2", "ol", "figure"],
});

Tips & Tricks

Passing values to renderNode and renderBlock

You can pass additional values to the renderNode and renderBlock functions, by making an inline function that returns the renderNode or renderBlock function. This can be useful if you need to pass extra context or props to the rendering functions. E.g. sizes for images, translations, or other data that is not part of the rich text element.

import {
  UmbracoRichText,
  RenderBlockContext,
  RenderNodeContext,
} from "@charlietango/umbraco-rich-text";
import Image from "next/image";
import Link from "next/link";

function renderNode(
  { tag, children, attributes }: RenderNodeContext,
  extra: { sizes: string },
) {
  switch (tag) {
    case "img":
      return <img {...attributes} sizes={extra.sizes} />;
    default:
      return undefined;
  }
}

function RichText({ data }) {
  return (
    <UmbracoRichText
      data={data.richText}
      renderNode={(node) => {
        return renderNode(node, { sizes: "720vw" });
      }}
    />
  );
}