Skip to content

Commit

Permalink
feat(richtext): add React fragment for richtext textFn (#1343)
Browse files Browse the repository at this point in the history
* feat(richtext): add unique key generation for text fragments

* fix(utils): remove workaround for text nodes
  • Loading branch information
alvarosabu authored Feb 12, 2025
1 parent 83654dc commit 3865be0
Show file tree
Hide file tree
Showing 2 changed files with 4 additions and 52 deletions.
3 changes: 3 additions & 0 deletions src/richtext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ export function useStoryblokRichTextResolver(
) {
const mergedOptions = {
renderFn: React.createElement,
textFn: (text: string) => React.createElement(React.Fragment, {
key: Math.random().toString(36).substring(2, 15),
}, text),
resolvers: {
[BlockTypes.COMPONENT]: componentResolver,
...options.resolvers,
Expand Down
53 changes: 1 addition & 52 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,47 +1,5 @@
import React from 'react';

const HTML_ENTITIES: Record<string, string> = {
'&amp;': '&',
'&lt;': '<',
'&gt;': '>',
'&quot;': '"',
'&#39;': '\'',
'&apos;': '\'',
'&nbsp;': ' ',
'&copy;': '©',
'&reg;': '®',
'&deg;': '°',
'&plusmn;': '±',
'&para;': '¶',
'&middot;': '·',
'&ndash;': '\u2013',
'&mdash;': '\u2014',
'&lsquo;': '\u2018',
'&rsquo;': '\u2019',
'&sbquo;': '\u201A',
'&ldquo;': '\u201C',
'&rdquo;': '\u201D',
'&bdquo;': '\u201E',
'&hellip;': '\u2026',
};

function decodeHtmlEntities(text: string): string {
return text.replace(/&[#\w]+;/g, (entity) => {
// Handle numeric entities
if (entity.startsWith('&#')) {
const code = entity.slice(2, -1);
// Hex entities (e.g. &#x27;)
if (code.startsWith('x')) {
return String.fromCharCode(Number.parseInt(code.slice(1), 16));
}
// Decimal entities (e.g. &#39;)
return String.fromCharCode(Number.parseInt(code, 10));
}
// Handle named entities
return HTML_ENTITIES[entity] || entity;
});
}

function camelCase(str: string) {
return str.replace(/-([a-z])/g, g => g[1].toUpperCase());
}
Expand Down Expand Up @@ -69,15 +27,6 @@ export function convertAttributesInElement(element: React.ReactElement | React.R
return element.map(el => convertAttributesInElement(el)) as React.ReactElement[];
}

// Base case: if the element is not a React element, return it unchanged.
if (!React.isValidElement(element)) {
// If it's a text node, decode any HTML entities
if (typeof element === 'string') {
return decodeHtmlEntities(element) as unknown as React.ReactElement;
}
return element;
}

// Convert attributes of the current element.
const attributeMap: { [key: string]: string } = {
class: 'className',
Expand All @@ -103,7 +52,7 @@ export function convertAttributesInElement(element: React.ReactElement | React.R
// Process children recursively.
const children = React.Children.map((element.props as React.PropsWithChildren).children, (child) => {
if (typeof child === 'string') {
return decodeHtmlEntities(child);
return child;
}
return convertAttributesInElement(child as React.ReactElement);
});
Expand Down

0 comments on commit 3865be0

Please sign in to comment.