0.1.11 • Published 1 year ago

@pokornyd/kontent-ai-rich-text-parser v0.1.11

Weekly downloads
-
License
ISC
Repository
github
Last release
1 year ago

Kontent.ai rich text transformer

:information_source: This module is in experimental mode and may undergo changes in the future.

Last modified Issues Contributors MIT License codecov Stack Overflow Discord

This package provides you with tools to transform rich text element value from Kontent.ai into a JSON tree and optionally to portable text standard.

Installation

Install the package via npm

npm i @pokornyd/kontent-ai-rich-text-parser


Usage

Module provides two functions to parse rich text HTML into a simplified JSON tree: browserParse for client-side resolution and nodeParse for server-side use with Node.js. Their use is identical, the only difference is the underlying parsing logic.

Parsed output can then be passed to a transformToPortableText function, which converts the JSON tree into portable text blocks.

Full specification of portable text format can be found in the corresponding repository.

💡 The intermediate JSON structure can be manipulated before rendering into Portable text or used altogether independently. See JSON transformer docs for further information.

Portable text resolution

Portable text supports majority of popular languages and frameworks.

Resolution is described in each corresponding repository. You can also find example resolution below.

Custom portable text blocks

Besides default blocks for common elements, Portable text supports custom blocks, which can represent other (not only) HTML entities. Each custom block should extend IPortableTextBaseItem to ensure _key and _type properties are present. Key should be a unique identifier (e.g. guid), while type should point out what said custom block represents. Value of _type property is used for subsequent override for resolution purposes. This package comes with built-in custom block definitions for representing Kontent.ai-specific objects:

Component/linked item

https://github.com/kontent-ai/rich-text-resolver-js/blob/main/src/showcase/showcase.ts#L8-L15

Image

https://github.com/kontent-ai/rich-text-resolver-js/blob/main/src/showcase/showcase.ts#L17-L25

Item link

https://github.com/kontent-ai/rich-text-resolver-js/blob/main/src/showcase/showcase.ts#L27-L34

Table

https://github.com/kontent-ai/rich-text-resolver-js/blob/main/src/showcase/showcase.ts#L36-L69

💡 For table resolution, you may use resolveTable helper function. It accepts two arguments -- custom block of type table and a method to transform content of its cells into valid HTML. See below for usage examples. Alternatively, you can iterate over the table structure and resolve it as per your requirements (e.g. if you want to add CSS classes to its elements)

Examples

HTML resolution using @portabletext/to-html package.

import { escapeHTML, PortableTextOptions, toHTML } from '@portabletext/to-html';
import { browserParse, transformToPortableText, resolveTable } from '@pokornyd/kontent-ai-rich-text-parser';

const richTextValue = '<rich text html>';
const linkedItems = ['<array of linked items>'];
const parsedTree = browserParse(richTextValue);
const portableText = transformToPortableText(parsedTree);

const portableTextComponents: PortableTextOptions = {
  components: {
    types: {
      image: ({value}) => {
        return `<img src="${value.asset.url}"></img>`;
      },
      component: ({value}) => {
        const linkedItem = linkedItems.find(item => item.system.codename === value.component._ref);
        switch(linkedItem?.system.type) {
          case('component_type_codename'): {
            return `<p>resolved value of text_element: ${linkedItem?.elements.text_element.value}</p>`;
          }
          default: {
            return `Resolver for type ${linkedItem?.system.type} not implemented.`
          }
        }
      },
      table: ({value}) => {
        const tableHtml = resolveTable(value, toHTML); // helper method for resolving tables
        return tableHtml;
      }
    },
    marks: {
      internalLink: ({children, value}) => {
        return `\<a href=\"https://website.com/${value.reference._ref}">${children}</a>`
      },
      link: ({ children, value }) => {
        return `\<a href=${value?.href} target=${target} rel=${value?.rel} title=${value?.title} data-new-window=${value['data-new-window']}>${children}</a>`
      }
    }
  }
}

const resolvedHtml = toHTML(portableText, portableTextComponents);

React, using @portabletext/react package.

import { PortableText, toPlainText } from '@portabletext/react';
import { nodeParse, resolveTable, transformToPortableText } from '@pokornyd/kontent-ai-rich-text-parser';

const richTextValue = '<rich text html>';
const linkedItems = ['<array of linked items>'];
const parsedTree = browserParse(richTextValue);
const portableText = transformToPortableText(parsedTree);

interface IMyComponentProps {
  value: IPortableTextItem[];
  components: Partial<PortableTextReactComponents>;
}

const portableTextComponents: Partial<PortableTextReactComponents> = {
  types: {
    component: (block) => {
      const item = linkedItems.find(item => item.system.codename === block.value.component._ref);
      return <div>{item?.elements.text_element.value}</div>;
    },
    table: ({ value }) => {
      let tableString = resolveTable(value, toPlainText);
      return <>{tableString}</>;
    },
    image: ({ value }) => {
      return <img src={value.asset.url}></img>;
    }
  },
  marks: {
    link: ({ value, children }) => {
      const target = (value?.href || '').startsWith('http') ? '_blank' : undefined
      return (
        <a href={value?.href} target={target} rel={value?.rel} title={value?.title} data-new-window={value['data-new-window']}>
          {children}
        </a>
      )
    },
    internalLink: ({ value, children }) => {
      const item = linkedItems.find(item => item.system.id === value.reference._ref);
      return (
        <a href={"https://somerandomwebsite.xyz/" + item?.system.codename}>
          {children}
        </a>
      )
    }
  }
}

export const MyComponent = ({value, components}: IMyComponentProps) => {
  return <PortableText value={value} components={components} />
}
0.1.10

1 year ago

0.1.11

1 year ago

0.1.0

1 year ago

0.1.2

1 year ago

0.1.1

1 year ago

0.1.8

1 year ago

0.1.7

1 year ago

0.1.9

1 year ago

0.1.4

1 year ago

0.1.3

1 year ago

0.1.6

1 year ago

0.1.5

1 year ago

0.0.14

1 year ago

0.0.13

1 year ago

0.0.12

1 year ago

0.0.11

1 year ago

0.0.10

1 year ago

0.0.9

1 year ago

0.0.8

1 year ago

0.0.7

1 year ago

0.0.6

1 year ago

0.0.5

1 year ago

0.0.4

1 year ago

0.0.3

1 year ago

0.0.2

1 year ago

0.0.1

1 year ago