@prismicio/client
Version:
The official JavaScript + TypeScript client library for Prismic
122 lines (120 loc) • 3.66 kB
JavaScript
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