UNPKG

@prismicio/client

Version:

The official JavaScript + TypeScript client library for Prismic

122 lines (120 loc) 3.66 kB
const require_richText = require('../types/value/richText.cjs'); //#region src/richtext/asTree.ts const uuid = () => { return (++uuid.i).toString(); }; uuid.i = 0; /** * Parses a rich text or title field into a tree * * @remarks * This is a low level helper mainly intended to be used by higher level * packages. Most users aren't expected to this function directly. * * @param nodes - A rich text or title field from Prismic * * @returns Tree from given rich text or title field */ const asTree = (nodes) => { const preparedNodes = prepareNodes(nodes); const children = []; for (let i = 0; i < preparedNodes.length; i++) children.push(nodeToTreeNode(preparedNodes[i])); return { key: uuid(), children }; }; const createTreeNode = (node, children = []) => { return { key: uuid(), type: node.type, text: "text" in node ? node.text : void 0, node, children }; }; const createTextTreeNode = (text) => { return createTreeNode({ type: require_richText.RichTextNodeType.span, text, spans: [] }); }; const prepareNodes = (nodes) => { const mutNodes = nodes.slice(0); for (let i = 0; i < mutNodes.length; i++) { const node = mutNodes[i]; if (node.type === require_richText.RichTextNodeType.listItem || node.type === require_richText.RichTextNodeType.oListItem) { const items = [node]; while (mutNodes[i + 1] && mutNodes[i + 1].type === node.type) { items.push(mutNodes[i + 1]); mutNodes.splice(i, 1); } if (node.type === require_richText.RichTextNodeType.listItem) mutNodes[i] = { type: require_richText.RichTextNodeType.list, items }; else mutNodes[i] = { type: require_richText.RichTextNodeType.oList, items }; } } return mutNodes; }; const nodeToTreeNode = (node) => { if ("text" in node) return createTreeNode(node, textNodeSpansToTreeNodeChildren(node.spans, node)); if ("items" in node) { const children = []; for (let i = 0; i < node.items.length; i++) children.push(nodeToTreeNode(node.items[i])); return createTreeNode(node, children); } return createTreeNode(node); }; const textNodeSpansToTreeNodeChildren = (spans, node, parentSpan) => { if (!spans.length) return [createTextTreeNode(node.text)]; const mutSpans = spans.slice(0); mutSpans.sort((a, b) => a.start - b.start || b.end - a.end); const children = []; for (let i = 0; i < mutSpans.length; i++) { const span = mutSpans[i]; const parentSpanStart = parentSpan && parentSpan.start || 0; const spanStart = span.start - parentSpanStart; const spanEnd = span.end - parentSpanStart; const text = node.text.slice(spanStart, spanEnd); const childSpans = []; for (let j = i; j < mutSpans.length; j++) { const siblingSpan = mutSpans[j]; if (siblingSpan !== span) { if (siblingSpan.start >= span.start && siblingSpan.end <= span.end) { childSpans.push(siblingSpan); mutSpans.splice(j, 1); j--; } else if (siblingSpan.start < span.end && siblingSpan.end > span.start) { childSpans.push({ ...siblingSpan, end: span.end }); mutSpans[j] = { ...siblingSpan, start: span.end }; } } } if (i === 0 && spanStart > 0) children.push(createTextTreeNode(node.text.slice(0, spanStart))); const spanWithText = { ...span, text }; children.push(createTreeNode(spanWithText, textNodeSpansToTreeNodeChildren(childSpans, { ...node, text }, span))); if (spanEnd < node.text.length) children.push(createTextTreeNode(node.text.slice(spanEnd, mutSpans[i + 1] ? mutSpans[i + 1].start - parentSpanStart : void 0))); } return children; }; //#endregion exports.asTree = asTree; //# sourceMappingURL=asTree.cjs.map