Contentful rich text renderer for solid-js, based upon rich-text-react-renderer but with some tweaks

rich-text-solid-renderer

Solid-js renderer for contentful rich text.

Installation

Using npm:

npm install rich-text-solid-renderer

Using yarn:

yarn add rich-text-solid-renderer

Usage

import {ParentComponent} from 'solid-js';
import SolidRichText from 'rich-text-solid-renderer';

const document = {
  nodeType: 'document',
  data: {},
  content: [
    {
      nodeType: 'paragraph',
      data: {},
      content: [
        {
          nodeType: 'text',
          value: 'Hello world!',
          marks: [],
          data: {}
        },
      ],
    },
  ],
};

const Parent: ParentComponent = (props) => {
    return <SolidRichText document={document}/>
}; // -> <p>Hello world!</p>

import {ParentComponent} from 'solid-js';
import SolidRichText from 'rich-text-solid-renderer';

const document = {
  nodeType: 'document',
  content: [
    {
      nodeType: 'paragraph',
      content: [
        {
          nodeType: 'text',
          value: 'Hello',
          marks: [{ type: 'bold' }],
        },
        {
          nodeType: 'text',
          value: ' world!',
          marks: [{ type: 'italic' }],
        },
      ],
    },
  ],
};


const Parent: ParentComponent = (props) => {
    return <SolidRichText document={document}/>
};
// -> <p><b>Hello</b><u> world!</u></p>

You can also pass custom renderers for both marks and nodes as an optional parameter like so:

import { BLOCKS, MARKS } from '@contentful/rich-text-types';
import {ParentComponent} from 'solid-js';
import SolidRichText, { NodeRendererProps } from 'rich-text-solid-renderer';


const document = {
  nodeType: 'document',
  content: [
    {
      nodeType: 'paragraph',
      content: [
        {
          nodeType: 'text',
          value: 'Hello',
          marks: [{ type: 'bold' }],
        },
        {
          nodeType: 'text',
          value: ' world!',
          marks: [{ type: 'italic' }],
        },
      ],
    },
  ],
};

const Bold = (props) => <p className="bold">{props.children}</p>;

const Text = (props) => <p className="align-center">{props.children}</p>;

const options = {
  renderMark: {
    [MARKS.BOLD]: props => <Bold>{props.children}</Bold>,
  },
  renderNode: {
    [BLOCKS.PARAGRAPH]: (props) => <Text>{props.children}</Text>,
  },
  renderText: text => text.replace('!', '?'),
};

const Parent: ParentComponent = (props) => {
    return <SolidRichText document={document} option={options}/>
};
// -> <p class="align-center"><p class="bold">Hello</p><u> world?</u></p>

Last, but not least, you can pass a custom rendering component for an embedded entry:

import { BLOCKS } from '@contentful/rich-text-types';
import SolidRichText from 'rich-text-solid-renderer';

const document = {
  nodeType: 'document',
  content: [
    {
      nodeType: 'embedded-entry-block',
      data: {
        target: (...)Link<'Entry'>(...);
      },
    },
  ]
};

const CustomComponent = (props) => (
  <div>
    <h2>{props.title}</h2>
    <p>{props.description}</p>
  </div>
);

const options = {
  renderNode: {
    [BLOCKS.EMBEDDED_ENTRY]: (props) => {
      return <CustomComponent title={props.node.data.target.fields.title} description={props.node.data.target.fields.description} />
    }
  }
};

const Parent: ParentComponent = (props) => {
    return <SolidRichText document={document} option={options}/>
};
// -> <div><h2>[title]</h2><p>[description]</p></div>

The renderNode keys should be one of the following BLOCKS and INLINES properties as defined in @contentful/rich-text-types:

  • BLOCKS

    • DOCUMENT
    • PARAGRAPH
    • HEADING_1
    • HEADING_2
    • HEADING_3
    • HEADING_4
    • HEADING_5
    • HEADING_6
    • UL_LIST
    • OL_LIST
    • LIST_ITEM
    • QUOTE
    • HR
    • EMBEDDED_ENTRY
    • EMBEDDED_ASSET
  • INLINES

    • EMBEDDED_ENTRY (this is different from the BLOCKS.EMBEDDED_ENTRY)
    • HYPERLINK
    • ENTRY_HYPERLINK
    • ASSET_HYPERLINK

The renderMark keys should be one of the following MARKS properties as defined in @contentful/rich-text-types:

  • BOLD
  • ITALIC
  • UNDERLINE
  • CODE

The renderText callback is a function that has a single string argument and returns a React node. Each text node is evaluated individually by this callback. A possible use case for this is to replace instances of \n produced by Shift + Enter with <br/> React elements. This could be accomplished in the following way:

const options = {
  renderText: (props) => {
            return props.split('\n').reduce((children, textSegment, index) => {
              return [...children, index > 0 && <br />, textSegment];
            }, []);
          },
};

GitHub

View Github