UNPKG

@portabletext/editor

Version:

Portable Text Editor made in React

193 lines (192 loc) 6.22 kB
import { isTextBlock } from "@portabletext/schema"; function isTypedObject(object) { return isRecord(object) && typeof object._type == "string"; } function isRecord(value) { return !!value && (typeof value == "object" || typeof value == "function"); } function isObjectNode(context, node) { return isTypedObject(node) && node._type !== context.schema.block.name && node._type !== context.schema.span.name; } function isKeyedSegment(segment) { return typeof segment == "object" && segment !== null && "_key" in segment; } function getChildren(snapshot, path) { let currentChildren = snapshot.context.value, currentFieldName = "value", currentPath = [], isRoot = !0, currentParent; for (const segment of path) { if (typeof segment == "string") continue; let node; if (isKeyedSegment(segment) ? node = currentChildren.find((child) => child._key === segment._key) : typeof segment == "number" && (node = currentChildren.at(segment)), !node) return []; currentPath = isRoot ? [{ _key: node._key }] : [...currentPath, currentFieldName, { _key: node._key }], isRoot = !1; const next = getNodeChildren(snapshot.context, node, currentParent); if (!next) return []; currentChildren = next.children, currentFieldName = next.fieldName, currentParent = next.parent; } return currentChildren.map((child) => ({ node: child, path: isRoot ? [{ _key: child._key }] : [...currentPath, currentFieldName, { _key: child._key }] })); } function getNodeChildren(context, node, parent) { if (isTextBlock(context, node)) return { children: node.children, fieldName: "children", parent: void 0 }; if (isObjectNode(context, node)) { const resolved = resolveNodeContainer(context.containers, parent, node); if (!resolved) return; const fieldValue = node[resolved.field.name]; return Array.isArray(fieldValue) ? { children: fieldValue, fieldName: resolved.field.name, parent: resolved } : void 0; } if ("value" in node && Array.isArray(node.value) && !("_key" in node) && !("_type" in node)) return { children: node.value, fieldName: "value", parent: void 0 }; } function resolveNodeContainer(containers, parent, node) { if (parent?.of) { for (const entry of parent.of) if (entry.type === node._type) return "field" in entry ? entry : void 0; } return containers.get(node._type); } function getNode(snapshot, path) { if (path.length === 0) return; const { context, blockIndexMap } = snapshot; let currentChildren = context.value, node, currentParent; const resolvedPath = []; let isRootLevel = !0; for (let i = 0; i < path.length; i++) { const segment = path[i]; if (typeof segment == "string") { resolvedPath.push(segment); continue; } if (isKeyedSegment(segment)) { if (isRootLevel && blockIndexMap.size === currentChildren.length) { const index = blockIndexMap.get(segment._key); if (index !== void 0) { const candidate = currentChildren[index]; candidate && candidate._key === segment._key ? node = candidate : node = currentChildren.find((child) => child._key === segment._key); } else node = currentChildren.find((child) => child._key === segment._key); } else node = currentChildren.find((child) => child._key === segment._key); resolvedPath.push(segment), isRootLevel = !1; } else if (typeof segment == "number") node = currentChildren.at(segment), node && resolvedPath.push({ _key: node._key }); else return; if (!node) return; let hasMoreSegments = !1; for (let j = i + 1; j < path.length; j++) { const s = path[j]; if (isKeyedSegment(s) || typeof s == "number") { hasMoreSegments = !0; break; } } if (hasMoreSegments) { const next = getNodeChildren(context, node, currentParent); if (!next) return; currentChildren = next.children, currentParent = next.parent; } } if (node) return { node, path: resolvedPath }; } function getAncestors(snapshot, path) { const keyedIndices = []; for (let i = 0; i < path.length; i++) isKeyedSegment(path[i]) && keyedIndices.push(i); if (keyedIndices.length <= 1) return []; const { context, blockIndexMap } = snapshot; let currentChildren = context.value, isRootLevel = !0, currentParent; const ancestorsByDepth = [], resolvedPath = [], targetKeyedIndex = keyedIndices[keyedIndices.length - 1]; let segmentIndex = 0; for (; segmentIndex < targetKeyedIndex; ) { const segment = path[segmentIndex]; if (typeof segment == "string") { resolvedPath.push(segment), segmentIndex++; continue; } let node; if (isKeyedSegment(segment)) { if (isRootLevel && blockIndexMap.size === currentChildren.length) { const index = blockIndexMap.get(segment._key); node = index !== void 0 ? currentChildren[index] : currentChildren.find((child) => child._key === segment._key); } else node = currentChildren.find((child) => child._key === segment._key); resolvedPath.push(segment), isRootLevel = !1; } else if (typeof segment == "number") node = currentChildren.at(segment), node && resolvedPath.push({ _key: node._key }); else return []; if (!node) return []; const next = getNodeChildren(context, node, currentParent); if (!next) return []; ancestorsByDepth.push({ node, path: resolvedPath.slice() }), currentChildren = next.children, currentParent = next.parent, segmentIndex++; } return ancestorsByDepth.reverse(); } function getAncestor(snapshot, path, match) { const ancestors = getAncestors(snapshot, path); for (const ancestor of ancestors) if (match(ancestor.node, ancestor.path)) return ancestor; } export { getAncestor, getAncestors, getChildren, getNode, getNodeChildren, isKeyedSegment, isObjectNode, isRecord, isTypedObject }; //# sourceMappingURL=get-ancestor.js.map