@shopify/hydrogen-react
Version:
React components, hooks, and utilities for creating custom Shopify storefronts
161 lines (160 loc) • 4.15 kB
JavaScript
;
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const jsxRuntime = require("react/jsx-runtime");
const React = require("react");
const RichText_components = require("./RichText.components.js");
function RichText({
as,
data,
plain,
components,
...passthroughProps
}) {
try {
const Wrapper = as ?? "div";
const parsedData = React.useMemo(
() => JSON.parse(data),
[data]
);
return /* @__PURE__ */ jsxRuntime.jsx(Wrapper, { ...passthroughProps, children: plain ? richTextToString(parsedData) : serializeRichTextASTNode(components, parsedData) });
} catch (e) {
throw new Error(
"[h2:error:RichText] Parsing error. Make sure to pass a JSON string of rich text metafield",
{
cause: e
}
);
}
}
function serializeRichTextASTNode(components = {}, node, index = 0) {
let children;
if ("children" in node) {
children = node.children.map(
(child, childIndex) => serializeRichTextASTNode(components, child, childIndex)
);
}
const Component = components[node.type === "list-item" ? "listItem" : node.type] ?? RichText_components.RichTextComponents[node.type];
switch (node.type) {
case "root":
return React.createElement(
Component,
{
key: index,
node: {
type: "root",
children
}
}
);
case "heading":
return React.createElement(
Component,
{
key: index,
node: {
type: "heading",
level: node.level,
children
}
}
);
case "paragraph":
return React.createElement(
Component,
{
key: index,
node: {
type: "paragraph",
children
}
}
);
case "text": {
const elements = (node.value ?? "").split("\n").flatMap((value, subindex) => {
const key = `${index}-${value}-${subindex}`;
const textElement = React.createElement(
Component,
{
key,
node: {
type: "text",
italic: node.italic,
bold: node.bold,
value
}
}
);
return subindex === 0 ? textElement : [React.createElement("br", { key: `${key}-br` }), textElement];
});
return elements.length > 1 ? React.createElement(React.Fragment, { key: index }, elements) : elements[0];
}
case "link":
return React.createElement(
Component,
{
key: index,
node: {
type: "link",
url: node.url,
title: node.title,
target: node.target,
children
}
}
);
case "list":
return React.createElement(
Component,
{
key: index,
node: {
type: "list",
listType: node.listType,
children
}
}
);
case "list-item":
return React.createElement(
Component,
{
key: index,
node: {
type: "list-item",
children
}
}
);
}
}
function richTextToString(node, result = []) {
switch (node.type) {
case "root":
node.children.forEach((child) => richTextToString(child, result));
break;
case "heading":
case "paragraph":
node.children.forEach((child) => richTextToString(child, result));
result.push(" ");
break;
case "text":
result.push(node.value || "");
break;
case "link":
node.children.forEach((child) => richTextToString(child, result));
break;
case "list":
node.children.forEach((item) => {
if (item.children) {
item.children.forEach((child) => richTextToString(child, result));
}
result.push(" ");
});
break;
default:
throw new Error(`Unknown node encountered ${node.type}`);
}
return result.join("").trim();
}
exports.RichText = RichText;
//# sourceMappingURL=RichText.js.map