Skip to content

Commit

Permalink
CTC-2582 Extend rich text resolver samples
Browse files Browse the repository at this point in the history
Added comments and changed return values
  • Loading branch information
jancerman committed Oct 23, 2024
1 parent 17ed265 commit 2c8a7e6
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 197 deletions.
49 changes: 12 additions & 37 deletions ts/structure-in-rte/resolve_rich_text_components_items.tsx
Original file line number Diff line number Diff line change
@@ -1,60 +1,35 @@
import { Elements } from "@kontent-ai/delivery-sdk";
import {
nodeParse,
PortableTextComponent,
transformToPortableText,
} from "@kontent-ai/rich-text-resolver";
import {
PortableText,
PortableTextComponents,
PortableTextTypeComponentProps,
} from "@portabletext/react";
import { PortableTextComponent } from "@kontent-ai/rich-text-resolver";
import { PortableTextComponents, PortableTextTypeComponentProps, } from "@portabletext/react";
import { React } from 'react';

import { CalloutComponent } from "../components/shared/richText/Callout";
import { contentTypes } from "../models";


type RichTextComponentProps = {
richTextElement: Elements.RichTextElement;
};

const getPortableTextComponents = (
element: Elements.RichTextElement
): Partial<PortableTextComponents> => ({
const createRichTextResolver = (element: Elements.RichTextElement): Partial<PortableTextComponents> => ({
types: {
// Components and content items inserted in rich text
component: ({
value,
}: PortableTextTypeComponentProps<PortableTextComponent>) => {
// Checks if the inserted content item is included in the response
// Kontent.ai components are always included in the response
const componentOrItem = element.linkedItems.find(
(i) => i.system.codename === value.component._ref
);

if (!componentOrItem) {
throw new Error("Component or item not found.");
return (<div>The referenced content item '{componentOrItem.system.codename}' wasn't found.</div>);
}

// Renders the component or content item based on its type
switch (componentOrItem.system.type) {
// Tip: Generate models at https://kontent.ai/learn/strongly-typed-models
case contentTypes.callout.codename:
return <CalloutComponent item={componentOrItem} />;
default:
return (
<div>
Resolution for content type {componentOrItem.system.type} not
implemented.
</div>
);
return (<div>Content based on the type '{componentOrItem.system.type}' couldn't be resolved.</div>);
}
},
},
});

export const RichTextComponent: React.FC<RichTextComponentProps> = (props) => {
const parsedTree = nodeParse(props.richTextElement.value);
const portableText = transformToPortableText(parsedTree);
return (
<PortableText
value={portableText}
components={getPortableTextComponents(props.richTextElement)}
/>
);
};
});
52 changes: 29 additions & 23 deletions ts/structure-in-rte/resolve_rich_text_flow.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
import { Elements } from "@kontent-ai/delivery-sdk";
import {
nodeParse,
transformToPortableText,
} from "@kontent-ai/rich-text-resolver";
import { PortableText } from "@portabletext/react";

type RichTextComponentProps = {
richTextElement: Elements.RichTextElement;
};
import { nodeParse, transformToPortableText, } from "@kontent-ai/rich-text-resolver";
import { PortableText, PortableTextComponents } from "@portabletext/react";
import { React } from "react";

// Defines how to transform Kontent.ai-specific portable text components, as well as default blocks
const portableTextComponents = {
// The logic for each portable text component is explained later in the lesson
const createRichTextResolver = (element: Elements.RichTextElement): Partial<PortableTextComponents> => ({
// The logic for individual portable text components is explained later in the lesson
types: {
component: undefined, // Components and linked items in rich text
table: undefined, // Tables in rich text
image: undefined, // Assets in rich text
// Resolution for components and content items inserted in rich text
component: undefined,
// Resolution for tables in rich text
table: undefined,
// Resolution for assets in rich text
image: undefined,
},
marks: {
link: undefined, // Links to external URLs
internalLink: undefined, // Links to content items
// Resolution for links to external URLs
link: undefined,
// Resolution for links to content items
internalLink: undefined,
},
block: {
// Custom resolution for default blocks
h1: undefined, // h1 heading
p: undefined, // paragraph
// Exmamples of custom resolution for default blocks
h1: undefined, // h1 headings
p: undefined, // paragraphs
},
});

type RichTextComponentProps = {
richTextElement: Elements.RichTextElement;
};

// Custom React component that renders your rich text element
export const RichTextComponent: React.FC<RichTextComponentProps> = (props) => {
// Converts Kontent.ai rich text HTML to a JSON tree
// Converts a Kontent.ai rich text element value to a JSON tree
const parsedTree = nodeParse(props.richTextElement.value);
// Converts the JSON tree to portable text
const portableText = transformToPortableText(parsedTree);
// Renders portable text based on the specified portable text component transformations
// Renders content based on the specified transformations
return (
<PortableText value={portableText} components={portableTextComponents} />
<PortableText
value={portableText}
components={createRichTextResolver(props.richTextElement)}
/>
);
};

Expand All @@ -46,4 +52,4 @@ export const RichTextComponent: React.FC<RichTextComponentProps> = (props) => {
// Example: using 'MyComponent' to render your rich text element in a <div>
// <div>
// <MyComponent value={richTextElement} />
// </div>
// </div>
78 changes: 27 additions & 51 deletions ts/structure-in-rte/resolve_rich_text_links_to_items.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,19 @@
import { Elements, ILink } from "@kontent-ai/delivery-sdk";
import {
nodeParse,
PortableTextInternalLink,
transformToPortableText,
} from "@kontent-ai/rich-text-resolver";
import {
PortableText,
PortableTextComponents,
PortableTextMarkComponentProps,
} from "@portabletext/react";
import { ReactNode } from "react";
import { PortableTextInternalLink } from "@kontent-ai/rich-text-resolver";
import { PortableTextComponents, PortableTextMarkComponentProps } from "@portabletext/react";
import { React, ReactNode } from "react";

import { ProductLink } from "../components";
import { contentTypes } from "../models";

type RichTextComponentProps = {
richTextElement: Elements.RichTextElement;
};

type ItemLinkProps = {
type ContentItemLinkProps = {
link: ILink;
children: ReactNode;
};

type ProductLinkProps = {};

const getPortableTextComponents = (
element: Elements.RichTextElement
): Partial<PortableTextComponents> => ({
marks: {
internalLink: ({
value,
children,
}: PortableTextMarkComponentProps<PortableTextInternalLink>) => {
const link = element.links.find(
(l) => l.linkId === value?.reference._ref
);

return <ItemLink link={link!}>{children}</ItemLink>;
},
},
});

export const RichTextComponent: React.FC<RichTextComponentProps> = (props) => {
const parsedTree = nodeParse(props.richTextElement.value);
const portableText = transformToPortableText(parsedTree);
return (
<PortableText
value={portableText}
components={getPortableTextComponents(props.richTextElement)}
/>
);
};

const ItemLink: React.FC<ItemLinkProps> = (props) => {
// Custom React component for rendering links to content items
const ContentItemLink: React.FC<ContentItemLinkProps> = (props) => {
// Use different resolution logic based on the content type
switch (props.link.type) {
case contentTypes.product.codename:
return (
Expand All @@ -65,12 +25,28 @@ const ItemLink: React.FC<ItemLinkProps> = (props) => {
</ProductLink>
);
default:
throw new Error(
`No resolution implemented for item links of type ${props.link.type}.`
);
return (<div>Link to the content item '{props.link.codename}' couldn't be resolved.</div>);
}
};

type ProductLinkProps = {};
const ProductLink: React.FC<ProductLinkProps> = (props) => {
// implementation of ProductLink component
// Based on your app routing, resolve links to products
};

const createRichTextResolver = (element: Elements.RichTextElement): Partial<PortableTextComponents> => ({
marks: {
// Links to content items
internalLink: ({
value, // The linked item's metadata
children, // Link text that might include text formatting
}: PortableTextMarkComponentProps<PortableTextInternalLink>) => {
// Gets content item link metadata from the response
const link = element.links.find(
(l) => l.linkId === value?.reference._ref
);

return <ContentItemLink link={link!}>{children}</ContentItemLink>;
},
},
});
86 changes: 0 additions & 86 deletions ts/structure-in-rte/structure_in_rte_use_standalone_resolver.tsx

This file was deleted.

0 comments on commit 2c8a7e6

Please sign in to comment.