15.19.6 • Published 2 months ago

@contentful/rich-text-react-renderer v15.19.6

Weekly downloads
175,364
License
MIT
Repository
github
Last release
2 months ago

rich-text-react-renderer

React renderer for the Contentful rich text field type.

Installation

Using npm:

npm install @contentful/rich-text-react-renderer

Using yarn:

yarn add @contentful/rich-text-react-renderer

Usage

import { documentToReactComponents } from '@contentful/rich-text-react-renderer';

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

documentToReactComponents(document); // -> <p>Hello world!</p>
import { documentToReactComponents } from '@contentful/rich-text-react-renderer';

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

documentToReactComponents(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 { documentToReactComponents } from '@contentful/rich-text-react-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 = ({ children }) => <p className="bold">{children}</p>;

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

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

documentToReactComponents(document, 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 { documentToReactComponents } from '@contentful/rich-text-react-renderer';

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

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

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

documentToReactComponents(document, 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
    • EMBEDDED_RESOURCE
  • INLINES

    • EMBEDDED_ENTRY (this is different from the BLOCKS.EMBEDDED_ENTRY)
    • EMBEDDED_RESOURCE
    • HYPERLINK
    • ENTRY_HYPERLINK
    • ASSET_HYPERLINK
    • RESOURCE_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: (text) => {
    return text.split('\n').reduce((children, textSegment, index) => {
      return [...children, index > 0 && <br key={index} />, textSegment];
    }, []);
  },
};

Note on adding a key prop in custom renderers:

It is possible to pass a key prop in the components returned by custom renderers. A good use case for this is in embeded entries using the node's target.sys.id. It is important not to pass anything that is index-like (e.g. 1 or "1") as it may clash with the default renderers which automatically inject a key prop using their index in the Contentful rich text AST.

To work around this limitation, just append any non-numeric character to your custom key.

const options = {
  renderMark: {
    [MARKS.BOLD]: (text) => {
      return <b key={`${text}-key`}>{text}</b>;
    },
  },
};

Preserving Whitespace

The options object can include a preserveWhitespace boolean flag. When set to true, this flag ensures that multiple spaces in the rich text content are preserved by replacing them with &nbsp;, and line breaks are maintained with <br /> tags. This is useful for content that relies on specific formatting using spaces and line breaks.

import { documentToReactComponents } from '@contentful/rich-text-react-renderer';

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

const options = {
  preserveWhitespace: true,
};

documentToReactComponents(document, options);
// -> <p>Hello&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;world!</p>

In this example, the multiple spaces between "Hello" and "world!" are preserved in the rendered output.

portfolio-gatsby@techstars/contentful@sandalboyz/gatsby-theme-sandalboyzgatsby-theme-sandalboyzwmk-pkg-willsbr-ripley-seguroscomponents-seguroscomponents-sitio-publicotest-test-sp-rick@infinitebrahmanuniverse/nolb-_contgatsby-source-contentful@everything-registry/sub-chunk-196eliasfrigard-reusable-componentsfigdog-themegatsby-affiliate-themejie-webgatsby-theme-affiliategatsby-theme-careersgatsby-shared-uigatsby-theme-direct-democracygatsby-theme-q3gatsby-theme-contentfulgatsby-theme-wom-coregatsby-theme-loveriaindependenceaustralia-design-librarymyinvisalign@mdrt/mdrt-theme-recruitmentmejuri-components@jeromevvb/equinox-lib@last-rev/component-library@last-rev/rich-text-editorpoleodev-blog@plasmicpkgs/plasmic-contentful@ninetailed/experience-sdk-gatsbyprosci-components@packdigital/gatsby-theme-ripperoni-componentsomahti-cms-web-starter5c-20235c-angle5c-bresson5c-cobb5c-cody5c-corn5c-dvon5c-flowers5c-helms5c-rhodes5c-rise5c-snow5c-test-off5c-yoh5c-zsj5c-kidd5c-mac5c-mark5c-mick5c-mox5c-naito5c-njc235c-obi5c-okada5c-pen5c-ramon@zalastax/nolb-_contsentral.rn@tdcerhverv/richtext@arcanetechnology/react-ui-lib@xbge/gatsby-components@xbge/gatsby-theme@tuwhana/react-gatsby-contentful@servicetitan/contentful@servicetitan/contentful-proxy@servicetitan/onboarding-ui@ultracommerce/cra-template-ultra-commerce-storefrontreact-contentful-update@smithc/gatsby-source-contentfulalexlee-dev-portfolio@ashr81/gatsby-theme-profile-builder@dadoagency/contentful-gatsby-componentsconsumer-smileviewcontentful-slice-machine@slatwall/cra-template-ultra-commerce-storefront@cheerful-ui/ui@comfortdelgro/react-compass@comfortdelgro/react-compass-testing@comfortdelgro/staticbrand-siteboring-plugin-contentful@contentful/experience-builder-components@contentful/experiences-components-reactbroadside-campaigbroadside-coretai-react-realm@fabiodesousa/gatsby-theme-contentful@equinox-fund/equinox-lib@etchteam/contentful@ejiwen/gatsby-theme-ejiwencx-web@flarehr/apollo-benefitstop-gun-library
15.19.6

2 months ago

15.19.5

2 months ago

15.19.4

3 months ago

15.19.2

3 months ago

15.19.3

3 months ago

15.19.1

3 months ago

15.19.0

6 months ago

15.17.2

7 months ago

15.18.0

7 months ago

15.17.1

9 months ago

15.16.5

11 months ago

15.16.4

12 months ago

15.17.0

11 months ago

15.16.3

1 year ago

15.16.2

1 year ago

15.16.0

1 year ago

15.15.1

1 year ago

15.12.1

2 years ago

15.12.0

2 years ago

15.9.0

2 years ago

15.9.1

2 years ago

15.11.0

2 years ago

15.10.1

2 years ago

15.11.1

2 years ago

15.10.0

2 years ago

15.6.0

2 years ago

15.6.2

2 years ago

15.5.1

2 years ago

15.4.0

3 years ago

15.3.6

3 years ago

15.3.5

3 years ago

15.3.2

3 years ago

15.3.1

3 years ago

15.3.3

3 years ago

15.3.0

3 years ago

15.2.0

3 years ago

15.1.0

3 years ago

15.0.0

3 years ago

14.1.3

3 years ago

14.1.2

3 years ago

14.1.1

4 years ago

14.1.0

4 years ago

13.4.0

5 years ago

13.2.0

5 years ago

13.1.0

5 years ago

13.0.1

5 years ago