@portabletext/editor 6.6.4 → 7.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/lib/_chunks-dts/behavior.types.action.d.ts +683 -512
  2. package/lib/_chunks-dts/behavior.types.action.d.ts.map +1 -1
  3. package/lib/_chunks-dts/resolve-containers.d.ts +688 -0
  4. package/lib/_chunks-dts/resolve-containers.d.ts.map +1 -0
  5. package/lib/_chunks-es/get-ancestor.js +192 -0
  6. package/lib/_chunks-es/get-ancestor.js.map +1 -0
  7. package/lib/_chunks-es/get-first-child.js +130 -0
  8. package/lib/_chunks-es/get-first-child.js.map +1 -0
  9. package/lib/_chunks-es/get-path-sub-schema.js +266 -0
  10. package/lib/_chunks-es/get-path-sub-schema.js.map +1 -0
  11. package/lib/_chunks-es/selector.is-at-the-start-of-block.js +1021 -0
  12. package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -0
  13. package/lib/_chunks-es/use-editor.js +4 -13
  14. package/lib/_chunks-es/use-editor.js.map +1 -1
  15. package/lib/_chunks-es/util.is-empty-text-block.js +15 -0
  16. package/lib/_chunks-es/util.is-empty-text-block.js.map +1 -0
  17. package/lib/_chunks-es/util.slice-blocks.js +347 -198
  18. package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
  19. package/lib/behaviors/index.d.ts +2 -1
  20. package/lib/index.d.ts +3 -2
  21. package/lib/index.js +5457 -5611
  22. package/lib/index.js.map +1 -1
  23. package/lib/plugins/index.d.ts +18 -2
  24. package/lib/plugins/index.d.ts.map +1 -1
  25. package/lib/plugins/index.js +18 -2
  26. package/lib/plugins/index.js.map +1 -1
  27. package/lib/selectors/index.d.ts +220 -5
  28. package/lib/selectors/index.d.ts.map +1 -1
  29. package/lib/selectors/index.js +62 -71
  30. package/lib/selectors/index.js.map +1 -1
  31. package/lib/traversal/index.d.ts +235 -0
  32. package/lib/traversal/index.d.ts.map +1 -0
  33. package/lib/traversal/index.js +30 -0
  34. package/lib/traversal/index.js.map +1 -0
  35. package/lib/utils/index.d.ts +11 -57
  36. package/lib/utils/index.d.ts.map +1 -1
  37. package/lib/utils/index.js +36 -107
  38. package/lib/utils/index.js.map +1 -1
  39. package/package.json +19 -17
  40. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js +0 -806
  41. package/lib/_chunks-es/selector.is-selecting-entire-blocks.js.map +0 -1
  42. package/lib/_chunks-es/util.slice-text-block.js +0 -60
  43. package/lib/_chunks-es/util.slice-text-block.js.map +0 -1
@@ -0,0 +1,192 @@
1
+ import { isTextBlock } from "@portabletext/schema";
2
+ function isTypedObject(object) {
3
+ return isRecord(object) && typeof object._type == "string";
4
+ }
5
+ function isRecord(value) {
6
+ return !!value && (typeof value == "object" || typeof value == "function");
7
+ }
8
+ function isObjectNode(context, node) {
9
+ return isTypedObject(node) && node._type !== context.schema.block.name && node._type !== context.schema.span.name;
10
+ }
11
+ function isKeyedSegment(segment) {
12
+ return typeof segment == "object" && segment !== null && "_key" in segment;
13
+ }
14
+ function getChildren(snapshot, path) {
15
+ let currentChildren = snapshot.context.value, currentFieldName = "value", currentPath = [], isRoot = !0, currentParent;
16
+ for (const segment of path) {
17
+ if (typeof segment == "string")
18
+ continue;
19
+ let node;
20
+ if (isKeyedSegment(segment) ? node = currentChildren.find((child) => child._key === segment._key) : typeof segment == "number" && (node = currentChildren.at(segment)), !node)
21
+ return [];
22
+ currentPath = isRoot ? [{
23
+ _key: node._key
24
+ }] : [...currentPath, currentFieldName, {
25
+ _key: node._key
26
+ }], isRoot = !1;
27
+ const next = getNodeChildren(snapshot.context, node, currentParent);
28
+ if (!next)
29
+ return [];
30
+ currentChildren = next.children, currentFieldName = next.fieldName, currentParent = next.parent;
31
+ }
32
+ return currentChildren.map((child) => ({
33
+ node: child,
34
+ path: isRoot ? [{
35
+ _key: child._key
36
+ }] : [...currentPath, currentFieldName, {
37
+ _key: child._key
38
+ }]
39
+ }));
40
+ }
41
+ function getNodeChildren(context, node, parent) {
42
+ if (isTextBlock(context, node))
43
+ return {
44
+ children: node.children,
45
+ fieldName: "children",
46
+ parent: void 0
47
+ };
48
+ if (isObjectNode(context, node)) {
49
+ const resolved = resolveNodeContainer(context.containers, parent, node);
50
+ if (!resolved)
51
+ return;
52
+ const fieldValue = node[resolved.field.name];
53
+ return Array.isArray(fieldValue) ? {
54
+ children: fieldValue,
55
+ fieldName: resolved.field.name,
56
+ parent: resolved
57
+ } : void 0;
58
+ }
59
+ if ("value" in node && Array.isArray(node.value) && !("_key" in node) && !("_type" in node))
60
+ return {
61
+ children: node.value,
62
+ fieldName: "value",
63
+ parent: void 0
64
+ };
65
+ }
66
+ function resolveNodeContainer(containers, parent, node) {
67
+ if (parent?.of) {
68
+ for (const entry of parent.of)
69
+ if (entry.type === node._type)
70
+ return "field" in entry ? entry : void 0;
71
+ }
72
+ return containers.get(node._type);
73
+ }
74
+ function getNode(snapshot, path) {
75
+ if (path.length === 0)
76
+ return;
77
+ const {
78
+ context,
79
+ blockIndexMap
80
+ } = snapshot;
81
+ let currentChildren = context.value, node, currentParent;
82
+ const resolvedPath = [];
83
+ let isRootLevel = !0;
84
+ for (let i = 0; i < path.length; i++) {
85
+ const segment = path[i];
86
+ if (typeof segment == "string") {
87
+ resolvedPath.push(segment);
88
+ continue;
89
+ }
90
+ if (isKeyedSegment(segment)) {
91
+ if (isRootLevel && blockIndexMap.size === currentChildren.length) {
92
+ const index = blockIndexMap.get(segment._key);
93
+ if (index !== void 0) {
94
+ const candidate = currentChildren[index];
95
+ candidate && candidate._key === segment._key ? node = candidate : node = currentChildren.find((child) => child._key === segment._key);
96
+ } else
97
+ node = currentChildren.find((child) => child._key === segment._key);
98
+ } else
99
+ node = currentChildren.find((child) => child._key === segment._key);
100
+ resolvedPath.push(segment), isRootLevel = !1;
101
+ } else if (typeof segment == "number")
102
+ node = currentChildren.at(segment), node && resolvedPath.push({
103
+ _key: node._key
104
+ });
105
+ else
106
+ return;
107
+ if (!node)
108
+ return;
109
+ let hasMoreSegments = !1;
110
+ for (let j = i + 1; j < path.length; j++) {
111
+ const s = path[j];
112
+ if (isKeyedSegment(s) || typeof s == "number") {
113
+ hasMoreSegments = !0;
114
+ break;
115
+ }
116
+ }
117
+ if (hasMoreSegments) {
118
+ const next = getNodeChildren(context, node, currentParent);
119
+ if (!next)
120
+ return;
121
+ currentChildren = next.children, currentParent = next.parent;
122
+ }
123
+ }
124
+ if (node)
125
+ return {
126
+ node,
127
+ path: resolvedPath
128
+ };
129
+ }
130
+ function getAncestors(snapshot, path) {
131
+ const keyedIndices = [];
132
+ for (let i = 0; i < path.length; i++)
133
+ isKeyedSegment(path[i]) && keyedIndices.push(i);
134
+ if (keyedIndices.length <= 1)
135
+ return [];
136
+ const {
137
+ context,
138
+ blockIndexMap
139
+ } = snapshot;
140
+ let currentChildren = context.value, isRootLevel = !0, currentParent;
141
+ const ancestorsByDepth = [], resolvedPath = [], targetKeyedIndex = keyedIndices[keyedIndices.length - 1];
142
+ let segmentIndex = 0;
143
+ for (; segmentIndex < targetKeyedIndex; ) {
144
+ const segment = path[segmentIndex];
145
+ if (typeof segment == "string") {
146
+ resolvedPath.push(segment), segmentIndex++;
147
+ continue;
148
+ }
149
+ let node;
150
+ if (isKeyedSegment(segment)) {
151
+ if (isRootLevel && blockIndexMap.size === currentChildren.length) {
152
+ const index = blockIndexMap.get(segment._key);
153
+ node = index !== void 0 ? currentChildren[index] : currentChildren.find((child) => child._key === segment._key);
154
+ } else
155
+ node = currentChildren.find((child) => child._key === segment._key);
156
+ resolvedPath.push(segment), isRootLevel = !1;
157
+ } else if (typeof segment == "number")
158
+ node = currentChildren.at(segment), node && resolvedPath.push({
159
+ _key: node._key
160
+ });
161
+ else
162
+ return [];
163
+ if (!node)
164
+ return [];
165
+ const next = getNodeChildren(context, node, currentParent);
166
+ if (!next)
167
+ return [];
168
+ ancestorsByDepth.push({
169
+ node,
170
+ path: resolvedPath.slice()
171
+ }), currentChildren = next.children, currentParent = next.parent, segmentIndex++;
172
+ }
173
+ return ancestorsByDepth.reverse();
174
+ }
175
+ function getAncestor(snapshot, path, match) {
176
+ const ancestors = getAncestors(snapshot, path);
177
+ for (const ancestor of ancestors)
178
+ if (match(ancestor.node, ancestor.path))
179
+ return ancestor;
180
+ }
181
+ export {
182
+ getAncestor,
183
+ getAncestors,
184
+ getChildren,
185
+ getNode,
186
+ getNodeChildren,
187
+ isKeyedSegment,
188
+ isObjectNode,
189
+ isRecord,
190
+ isTypedObject
191
+ };
192
+ //# sourceMappingURL=get-ancestor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-ancestor.js","sources":["../../src/utils/asserters.ts","../../src/slate/node/is-object-node.ts","../../src/utils/util.is-keyed-segment.ts","../../src/node-traversal/get-children.ts","../../src/node-traversal/get-node.ts","../../src/node-traversal/get-ancestors.ts","../../src/node-traversal/get-ancestor.ts"],"sourcesContent":["import type {TypedObject} from '@portabletext/schema'\n\nexport function isTypedObject(object: unknown): object is TypedObject {\n return isRecord(object) && typeof object['_type'] === 'string'\n}\n\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && (typeof value === 'object' || typeof value === 'function')\n}\n","import type {PortableTextObject} from '@portabletext/schema'\nimport type {EditorSchema} from '../../editor/editor-schema'\nimport {isTypedObject} from '../../utils/asserters'\n\nexport function isObjectNode(\n context: {schema: EditorSchema},\n node: unknown,\n): node is PortableTextObject {\n return (\n isTypedObject(node) &&\n node._type !== context.schema.block.name &&\n node._type !== context.schema.span.name\n )\n}\n","import type {KeyedSegment} from '../types/paths'\n\n/**\n * @public\n */\nexport function isKeyedSegment(segment: unknown): segment is KeyedSegment {\n return typeof segment === 'object' && segment !== null && '_key' in segment\n}\n","import {isTextBlock} from '@portabletext/schema'\nimport type {EditorSchema} from '../editor/editor-schema'\nimport type {\n Containers,\n RegisteredContainer,\n} from '../schema/resolve-containers'\nimport type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {isObjectNode} from '../slate/node/is-object-node'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the children of a node at a given path.\n *\n * @beta\n */\nexport function getChildren(\n snapshot: TraversalSnapshot,\n path: Path,\n): Array<{node: Node; path: Path}> {\n let currentChildren: Array<Node> = snapshot.context.value\n let currentFieldName = 'value'\n let currentPath: Path = []\n let isRoot = true\n let currentParent: RegisteredContainer | undefined\n\n for (const segment of path) {\n if (typeof segment === 'string') {\n continue\n }\n\n let node: Node | undefined\n if (isKeyedSegment(segment)) {\n node = currentChildren.find((child) => child._key === segment._key)\n } else if (typeof segment === 'number') {\n node = currentChildren.at(segment)\n }\n\n if (!node) {\n return []\n }\n\n currentPath = isRoot\n ? [{_key: node._key}]\n : [...currentPath, currentFieldName, {_key: node._key}]\n isRoot = false\n\n const next = getNodeChildren(snapshot.context, node, currentParent)\n\n if (!next) {\n return []\n }\n\n currentChildren = next.children\n currentFieldName = next.fieldName\n currentParent = next.parent\n }\n\n return currentChildren.map((child) => ({\n node: child,\n path: isRoot\n ? [{_key: child._key}]\n : [...currentPath, currentFieldName, {_key: child._key}],\n }))\n}\n\n/**\n * Resolve a node's editable child array.\n *\n * When `parent` is provided and its `of` declares a positional entry\n * matching `node._type`, that positional entry's `field` is used.\n * Otherwise the top-level `containers.get(node._type)` provides the\n * fallback.\n *\n * The returned `parent` is the resolved container entry for `node`\n * itself (used by the caller to thread further descent).\n *\n * @beta\n */\nexport function getNodeChildren(\n context: {\n schema: EditorSchema\n containers: Containers\n },\n node: Node | {value: Array<Node>},\n parent?: RegisteredContainer,\n):\n | {\n children: Array<Node>\n fieldName: string\n parent: RegisteredContainer | undefined\n }\n | undefined {\n // Text blocks store children in .children\n if (isTextBlock(context, node)) {\n return {\n children: node.children,\n fieldName: 'children',\n parent: undefined,\n }\n }\n\n if (isObjectNode(context, node)) {\n const resolved = resolveNodeContainer(context.containers, parent, node)\n\n if (!resolved) {\n return undefined\n }\n\n const fieldValue = (node as Record<string, unknown>)[resolved.field.name]\n\n if (!Array.isArray(fieldValue)) {\n return undefined\n }\n\n return {\n children: fieldValue as Array<Node>,\n fieldName: resolved.field.name,\n parent: resolved,\n }\n }\n\n // Root context: has .value array but no _key or _type\n if (\n 'value' in node &&\n Array.isArray(node['value']) &&\n !('_key' in node) &&\n !('_type' in node)\n ) {\n return {\n children: node['value'] as Array<Node>,\n fieldName: 'value',\n parent: undefined,\n }\n }\n\n return undefined\n}\n\n/**\n * Pick the positional override from `parent.of` if present; fall back\n * to the top-level entry. Returns only `RegisteredContainer` entries\n * since leaves do not have editable children.\n */\nfunction resolveNodeContainer(\n containers: Containers,\n parent: RegisteredContainer | undefined,\n node: Node,\n): RegisteredContainer | undefined {\n if (parent?.of) {\n for (const entry of parent.of) {\n if (entry.type === node._type) {\n // Only return container entries; leaves have no editable children.\n if ('field' in entry) {\n return entry\n }\n return undefined\n }\n }\n }\n return containers.get(node._type)\n}\n","import type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getNodeChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the node at a given path.\n *\n * The path can be either keyed (KeyedSegment + field name strings) or\n * indexed (numbers). Keyed segments are resolved by matching `_key`,\n * field name strings are skipped (they're structural), and numbers\n * are resolved by index.\n *\n * The returned path is always fully keyed, even if the input path\n * contained numeric indices.\n *\n * @beta\n */\nexport function getNode(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: Node; path: Path} | undefined {\n if (path.length === 0) {\n return undefined\n }\n\n const {context, blockIndexMap} = snapshot\n let currentChildren: Array<Node> = context.value\n let node: Node | undefined\n let currentParent:\n | import('../schema/resolve-containers').RegisteredContainer\n | undefined\n const resolvedPath: Path = []\n let isRootLevel = true\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i]\n\n if (typeof segment === 'string') {\n resolvedPath.push(segment)\n continue\n }\n\n if (isKeyedSegment(segment)) {\n if (isRootLevel && blockIndexMap.size === currentChildren.length) {\n const index = blockIndexMap.get(segment._key)\n if (index !== undefined) {\n const candidate = currentChildren[index]\n if (candidate && candidate._key === segment._key) {\n node = candidate\n } else {\n node = currentChildren.find((child) => child._key === segment._key)\n }\n } else {\n node = currentChildren.find((child) => child._key === segment._key)\n }\n } else {\n node = currentChildren.find((child) => child._key === segment._key)\n }\n resolvedPath.push(segment)\n isRootLevel = false\n } else if (typeof segment === 'number') {\n node = currentChildren.at(segment)\n if (node) {\n resolvedPath.push({_key: node._key})\n }\n } else {\n return undefined\n }\n\n if (!node) {\n return undefined\n }\n\n let hasMoreSegments = false\n for (let j = i + 1; j < path.length; j++) {\n const s = path[j]\n if (isKeyedSegment(s) || typeof s === 'number') {\n hasMoreSegments = true\n break\n }\n }\n\n if (hasMoreSegments) {\n const next = getNodeChildren(context, node, currentParent)\n\n if (!next) {\n return undefined\n }\n\n currentChildren = next.children\n currentParent = next.parent\n }\n }\n\n if (!node) {\n return undefined\n }\n\n return {node, path: resolvedPath}\n}\n","import type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getNodeChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get all ancestors of the node at a given path, from nearest to furthest.\n *\n * For a path like [{_key:'t1'}, 'rows', {_key:'r1'}, 'cells', {_key:'c1'}],\n * the ancestors are (nearest first):\n * [{_key:'t1'}, 'rows', {_key:'r1'}]\n * [{_key:'t1'}]\n *\n * Walks from root to the target in a single pass collecting each ancestor\n * as it goes.\n *\n * @beta\n */\nexport function getAncestors(\n snapshot: TraversalSnapshot,\n path: Path,\n): Array<{node: Node; path: Path}> {\n // Collect keyed-segment indices to know where each ancestor's path ends.\n const keyedIndices: Array<number> = []\n for (let i = 0; i < path.length; i++) {\n if (isKeyedSegment(path[i])) {\n keyedIndices.push(i)\n }\n }\n\n // Need at least 2 keyed segments to have an ancestor (the last is self).\n if (keyedIndices.length <= 1) {\n return []\n }\n\n const {context, blockIndexMap} = snapshot\n let currentChildren: Array<Node> = context.value\n let isRootLevel = true\n let currentParent:\n | import('../schema/resolve-containers').RegisteredContainer\n | undefined\n\n const ancestorsByDepth: Array<{node: Node; path: Path}> = []\n const resolvedPath: Path = []\n\n // Descend once. We walk only as far as the second-to-last keyed segment;\n // the last keyed segment is the target itself, which is not an ancestor.\n const targetKeyedIndex = keyedIndices[keyedIndices.length - 1]!\n\n let segmentIndex = 0\n while (segmentIndex < targetKeyedIndex) {\n const segment = path[segmentIndex]!\n\n if (typeof segment === 'string') {\n resolvedPath.push(segment)\n segmentIndex++\n continue\n }\n\n let node: Node | undefined\n if (isKeyedSegment(segment)) {\n // Production snapshots maintain `blockIndexMap` in lockstep with\n // `context.value` so this fast path always fires. Some test\n // fixtures still pass empty or stale maps, which is the debt this\n // size check is working around - see /specs/snapshot-invariants.md.\n // When the fixtures are aligned, drop the guard and use the map\n // directly.\n if (isRootLevel && blockIndexMap.size === currentChildren.length) {\n const index = blockIndexMap.get(segment._key)\n node =\n index !== undefined\n ? currentChildren[index]\n : currentChildren.find((child) => child._key === segment._key)\n } else {\n node = currentChildren.find((child) => child._key === segment._key)\n }\n resolvedPath.push(segment)\n isRootLevel = false\n } else if (typeof segment === 'number') {\n node = currentChildren.at(segment)\n if (node) {\n resolvedPath.push({_key: node._key})\n }\n } else {\n return []\n }\n\n if (!node) {\n return []\n }\n\n // Descend with positional awareness. `getNodeChildren` checks the\n // current parent's `of` for a positional override before falling\n // back to the top-level `containers` map - so same-`_type`\n // registered under different parents with different `field`\n // resolves to the right entry at this position.\n const next = getNodeChildren(context, node, currentParent)\n if (!next) {\n return []\n }\n\n ancestorsByDepth.push({\n node,\n path: resolvedPath.slice(),\n })\n\n currentChildren = next.children\n currentParent = next.parent\n segmentIndex++\n }\n\n // Return nearest-first (reverse of document order at the call site).\n return ancestorsByDepth.reverse()\n}\n","import type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {getAncestors} from './get-ancestors'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Find the first ancestor of the node at a given path that matches a predicate.\n * Does not check the node at the path itself, only its ancestors.\n *\n * When `match` is a type predicate, the returned `node` narrows to that type.\n *\n * @beta\n */\nexport function getAncestor<TMatch extends Node>(\n snapshot: TraversalSnapshot,\n path: Path,\n match: (node: Node, path: Path) => node is TMatch,\n): {node: TMatch; path: Path} | undefined\n/**\n * @beta\n */\nexport function getAncestor(\n snapshot: TraversalSnapshot,\n path: Path,\n match: (node: Node, path: Path) => boolean,\n): {node: Node; path: Path} | undefined\nexport function getAncestor(\n snapshot: TraversalSnapshot,\n path: Path,\n match: (node: Node, path: Path) => boolean,\n): {node: Node; path: Path} | undefined {\n const ancestors = getAncestors(snapshot, path)\n\n for (const ancestor of ancestors) {\n if (match(ancestor.node, ancestor.path)) {\n return ancestor\n }\n }\n\n return undefined\n}\n"],"names":["isTypedObject","object","isRecord","value","isObjectNode","context","node","_type","schema","block","name","span","isKeyedSegment","segment","getChildren","snapshot","path","currentChildren","currentFieldName","currentPath","isRoot","currentParent","find","child","_key","at","next","getNodeChildren","children","fieldName","parent","map","isTextBlock","undefined","resolved","resolveNodeContainer","containers","fieldValue","field","Array","isArray","of","entry","type","get","getNode","length","blockIndexMap","resolvedPath","isRootLevel","i","push","size","index","candidate","hasMoreSegments","j","s","getAncestors","keyedIndices","ancestorsByDepth","targetKeyedIndex","segmentIndex","slice","reverse","getAncestor","match","ancestors","ancestor"],"mappings":"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"}
@@ -0,0 +1,130 @@
1
+ import { getChildren, getNode, isKeyedSegment, getNodeChildren } from "./get-ancestor.js";
2
+ import { isSpan, isTextBlock, getSubSchema } from "@portabletext/schema";
3
+ import { getNodes } from "./get-path-sub-schema.js";
4
+ function getLeaf(snapshot, path, options) {
5
+ const {
6
+ edge
7
+ } = options;
8
+ let currentPath = path;
9
+ if (currentPath.length === 0) {
10
+ const children = getChildren(snapshot, []);
11
+ if (children.length === 0)
12
+ return;
13
+ const firstOrLast = edge === "end" ? children.at(-1) : children.at(0);
14
+ if (getChildren(snapshot, firstOrLast.path).length === 0)
15
+ return firstOrLast;
16
+ currentPath = firstOrLast.path;
17
+ } else {
18
+ const entry = getNode(snapshot, currentPath);
19
+ if (!entry)
20
+ return;
21
+ if (getChildren(snapshot, currentPath).length === 0)
22
+ return entry;
23
+ }
24
+ for (; ; ) {
25
+ const children = getChildren(snapshot, currentPath);
26
+ if (children.length === 0)
27
+ return getNode(snapshot, currentPath) ?? void 0;
28
+ currentPath = (edge === "end" ? children.at(-1) : children.at(0)).path;
29
+ }
30
+ }
31
+ function getText(snapshot, path) {
32
+ const entry = getNode(snapshot, path);
33
+ if (!entry)
34
+ return;
35
+ if (isSpan({
36
+ schema: snapshot.context.schema
37
+ }, entry.node))
38
+ return entry.node.text;
39
+ let text = "";
40
+ for (const descendant of getNodes(snapshot, {
41
+ at: path
42
+ }))
43
+ isSpan({
44
+ schema: snapshot.context.schema
45
+ }, descendant.node) && (text += descendant.node.text);
46
+ return text;
47
+ }
48
+ function getSpanNode(snapshot, path) {
49
+ const entry = getNode(snapshot, path);
50
+ if (entry && isSpan({
51
+ schema: snapshot.context.schema
52
+ }, entry.node))
53
+ return {
54
+ node: entry.node,
55
+ path: entry.path
56
+ };
57
+ }
58
+ function getTextBlockNode(snapshot, path) {
59
+ const entry = getNode(snapshot, path);
60
+ if (entry && isTextBlock({
61
+ schema: snapshot.context.schema
62
+ }, entry.node))
63
+ return {
64
+ node: entry.node,
65
+ path: entry.path
66
+ };
67
+ }
68
+ function getUnionSchema(schema, containers) {
69
+ const decorators = mergeByName(schema.decorators, []), annotations = mergeByName(schema.annotations, []), lists = mergeByName(schema.lists, []), styles = mergeByName(schema.styles, []), inlineObjects = mergeByName(schema.inlineObjects, []), blockObjects = mergeByName(schema.blockObjects, []);
70
+ for (const container of containers.values()) {
71
+ if (!acceptsTextBlock(container.field.of, schema.block.name))
72
+ continue;
73
+ const sub = getSubSchema(schema, container.field.of);
74
+ mergeByName(sub.decorators, decorators), mergeByName(sub.annotations, annotations), mergeByName(sub.lists, lists), mergeByName(sub.styles, styles), mergeByName(sub.inlineObjects, inlineObjects), mergeByName(sub.blockObjects, blockObjects);
75
+ }
76
+ return {
77
+ ...schema,
78
+ decorators,
79
+ annotations,
80
+ lists,
81
+ styles,
82
+ inlineObjects,
83
+ blockObjects
84
+ };
85
+ }
86
+ function acceptsTextBlock(of, blockName) {
87
+ return of.some((member) => member.type === "block" || member.type === blockName);
88
+ }
89
+ function mergeByName(source, target) {
90
+ for (const entry of source)
91
+ target.some((existing) => existing.name === entry.name) || target.push(entry);
92
+ return target;
93
+ }
94
+ function isLeaf(snapshot, path) {
95
+ if (path.length === 0)
96
+ return !1;
97
+ let currentChildren = snapshot.context.value, currentParent;
98
+ for (let i = 0; i < path.length; i++) {
99
+ const segment = path[i];
100
+ let node;
101
+ if (isKeyedSegment(segment))
102
+ node = currentChildren.find((child) => child._key === segment._key);
103
+ else if (typeof segment == "number")
104
+ node = currentChildren.at(segment);
105
+ else
106
+ continue;
107
+ if (!node)
108
+ return !1;
109
+ const next = getNodeChildren(snapshot.context, node, currentParent);
110
+ if (i === path.length - 1)
111
+ return next === void 0;
112
+ if (!next)
113
+ return !1;
114
+ currentChildren = next.children, currentParent = next.parent;
115
+ }
116
+ return !1;
117
+ }
118
+ function getFirstChild(snapshot, path) {
119
+ return getChildren(snapshot, path).at(0);
120
+ }
121
+ export {
122
+ getFirstChild,
123
+ getLeaf,
124
+ getSpanNode,
125
+ getText,
126
+ getTextBlockNode,
127
+ getUnionSchema,
128
+ isLeaf
129
+ };
130
+ //# sourceMappingURL=get-first-child.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-first-child.js","sources":["../../src/node-traversal/get-leaf.ts","../../src/node-traversal/get-text.ts","../../src/node-traversal/get-span-node.ts","../../src/node-traversal/get-text-block-node.ts","../../src/traversal/get-union-schema.ts","../../src/node-traversal/is-leaf.ts","../../src/node-traversal/get-first-child.ts"],"sourcesContent":["import type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {getChildren} from './get-children'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the deepest leaf node starting from a path, walking toward either the\n * start or end edge. A leaf is any node that has no children according to the\n * traversal context.\n *\n * @beta\n */\nexport function getLeaf(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {edge: 'start' | 'end'},\n): {node: Node; path: Path} | undefined {\n const {edge} = options\n\n let currentPath = path\n\n // If starting from root (empty path), descend into first/last child\n if (currentPath.length === 0) {\n const children = getChildren(snapshot, [])\n if (children.length === 0) {\n return undefined\n }\n const firstOrLast = edge === 'end' ? children.at(-1)! : children.at(0)!\n const nodeChildren = getChildren(snapshot, firstOrLast.path)\n if (nodeChildren.length === 0) {\n return firstOrLast\n }\n currentPath = firstOrLast.path\n } else {\n // Check if the node at path is already a leaf\n const entry = getNode(snapshot, currentPath)\n if (!entry) {\n return undefined\n }\n const children = getChildren(snapshot, currentPath)\n if (children.length === 0) {\n return entry\n }\n }\n\n // Descend to deepest leaf\n while (true) {\n const children = getChildren(snapshot, currentPath)\n if (children.length === 0) {\n const entry = getNode(snapshot, currentPath)\n return entry ?? undefined\n }\n const child = edge === 'end' ? children.at(-1)! : children.at(0)!\n currentPath = child.path\n }\n}\n","import {isSpan} from '@portabletext/schema'\nimport type {Path} from '../slate/interfaces/path'\nimport {getNode} from './get-node'\nimport {getNodes} from './get-nodes'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the concatenated text content of the node at a given path.\n *\n * @beta\n */\nexport function getText(\n snapshot: TraversalSnapshot,\n path: Path,\n): string | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (isSpan({schema: snapshot.context.schema}, entry.node)) {\n return entry.node.text\n }\n\n let text = ''\n\n for (const descendant of getNodes(snapshot, {at: path})) {\n if (isSpan({schema: snapshot.context.schema}, descendant.node)) {\n text += descendant.node.text\n }\n }\n\n return text\n}\n","import {isSpan, type PortableTextSpan} from '@portabletext/schema'\nimport type {Path} from '../slate/interfaces/path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the span node at a given path.\n *\n * @beta\n */\nexport function getSpanNode(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextSpan; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isSpan({schema: snapshot.context.schema}, entry.node)) {\n return undefined\n }\n\n return {node: entry.node, path: entry.path}\n}\n","import {isTextBlock, type PortableTextTextBlock} from '@portabletext/schema'\nimport type {Path} from '../slate/interfaces/path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the text block node at a given path.\n *\n * @beta\n */\nexport function getTextBlockNode(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextTextBlock; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isTextBlock({schema: snapshot.context.schema}, entry.node)) {\n return undefined\n }\n\n return {node: entry.node, path: entry.path}\n}\n","import {getSubSchema, type Schema} from '@portabletext/schema'\nimport type {Containers} from '../schema/resolve-containers'\n\n/**\n * Return a `Schema` that contains every named member declared anywhere\n * in the editor's schema graph that is reachable from a position where text\n * is edited - the root schema merged with the sub-schema of every registered\n * container whose field accepts text blocks, deduped by name. Useful for\n * rendering a static toolbar whose buttons stay stable across selection\n * moves while still reflecting everything that could plausibly be edited or\n * inserted somewhere.\n *\n * Containers whose field does NOT accept text blocks (e.g. a `table`\n * container whose `rows` field only accepts `row` objects, or a `row`\n * container whose `cells` field only accepts `cell` objects) are\n * **structural**: their immediate `of` types are organizational, not\n * insertable user content. Those structural types are excluded from the\n * union. Their nested text-block-accepting descendants (e.g. a `cell`\n * that contains a `content` field of `{type: 'block'}`) are reached via\n * those descendants' own container registration.\n *\n * Pair with `getPathSubSchema` (or a path-based intersection across a\n * range) to determine which of the union's members are applicable at the\n * current selection.\n *\n * @beta\n */\nexport function getUnionSchema(schema: Schema, containers: Containers): Schema {\n const decorators = mergeByName(schema.decorators, [])\n const annotations = mergeByName(schema.annotations, [])\n const lists = mergeByName(schema.lists, [])\n const styles = mergeByName(schema.styles, [])\n const inlineObjects = mergeByName(schema.inlineObjects, [])\n const blockObjects = mergeByName(schema.blockObjects, [])\n\n for (const container of containers.values()) {\n if (!acceptsTextBlock(container.field.of, schema.block.name)) {\n continue\n }\n const sub = getSubSchema(schema, container.field.of)\n mergeByName(sub.decorators, decorators)\n mergeByName(sub.annotations, annotations)\n mergeByName(sub.lists, lists)\n mergeByName(sub.styles, styles)\n mergeByName(sub.inlineObjects, inlineObjects)\n mergeByName(sub.blockObjects, blockObjects)\n }\n\n return {\n ...schema,\n decorators,\n annotations,\n lists,\n styles,\n inlineObjects,\n blockObjects,\n }\n}\n\nfunction acceptsTextBlock(\n of: ReadonlyArray<{type: string}>,\n blockName: string,\n): boolean {\n return of.some(\n (member) => member.type === 'block' || member.type === blockName,\n )\n}\n\nfunction mergeByName<T extends {name: string}>(\n source: ReadonlyArray<T>,\n target: Array<T>,\n): Array<T> {\n for (const entry of source) {\n if (target.some((existing) => existing.name === entry.name)) {\n continue\n }\n target.push(entry)\n }\n return target\n}\n","import type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getNodeChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Determine if a node at the given path is a leaf.\n *\n * A leaf node cannot have children. Spans and non-editable object nodes are\n * leaves. Text blocks and editable container objects are not.\n *\n * @beta\n */\nexport function isLeaf(snapshot: TraversalSnapshot, path: Path): boolean {\n if (path.length === 0) {\n return false\n }\n\n let currentChildren: Array<Node> = snapshot.context.value\n let currentParent:\n | import('../schema/resolve-containers').RegisteredContainer\n | undefined\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i]!\n let node: Node | undefined\n\n if (isKeyedSegment(segment)) {\n node = currentChildren.find((child) => child._key === segment._key)\n } else if (typeof segment === 'number') {\n node = currentChildren.at(segment)\n } else {\n continue\n }\n\n if (!node) {\n return false\n }\n\n const next = getNodeChildren(snapshot.context, node, currentParent)\n\n if (i === path.length - 1) {\n return next === undefined\n }\n\n if (!next) {\n return false\n }\n\n currentChildren = next.children\n currentParent = next.parent\n }\n\n return false\n}\n","import type {Node} from '../slate/interfaces/node'\nimport type {Path} from '../slate/interfaces/path'\nimport {getChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the first child of a node at a given path.\n *\n * @beta\n */\nexport function getFirstChild(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: Node; path: Path} | undefined {\n return getChildren(snapshot, path).at(0)\n}\n"],"names":["getLeaf","snapshot","path","options","edge","currentPath","length","children","getChildren","firstOrLast","at","entry","getNode","undefined","getText","isSpan","schema","context","node","text","descendant","getNodes","getSpanNode","getTextBlockNode","isTextBlock","getUnionSchema","containers","decorators","mergeByName","annotations","lists","styles","inlineObjects","blockObjects","container","values","acceptsTextBlock","field","of","block","name","sub","getSubSchema","blockName","some","member","type","source","target","existing","push","isLeaf","currentChildren","value","currentParent","i","segment","isKeyedSegment","find","child","_key","next","getNodeChildren","parent","getFirstChild"],"mappings":"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"}
@@ -0,0 +1,266 @@
1
+ import { isTypedObject, isKeyedSegment, getNode, getAncestors, getChildren, getNodeChildren, isObjectNode } from "./get-ancestor.js";
2
+ import { getSubSchema } from "@portabletext/schema";
3
+ function isSpanNode(context, node) {
4
+ return isTypedObject(node) && node._type === context.schema.span.name;
5
+ }
6
+ function isTextBlockNode(context, node) {
7
+ return isTypedObject(node) && node._type === context.schema.block.name;
8
+ }
9
+ function parentPath(path) {
10
+ if (path.length === 0)
11
+ throw new Error(`Cannot get the parent path of the root path [${path}].`);
12
+ let lastNodeIndex = -1;
13
+ for (let i = path.length - 1; i >= 0; i--)
14
+ if (isKeyedSegment(path[i]) || typeof path[i] == "number") {
15
+ lastNodeIndex = i;
16
+ break;
17
+ }
18
+ if (lastNodeIndex === -1)
19
+ return [];
20
+ const result = path.slice(0, lastNodeIndex);
21
+ return result.length > 0 && typeof result[result.length - 1] == "string" ? result.slice(0, -1) : result;
22
+ }
23
+ function getParent(snapshot, path) {
24
+ if (path.length === 0)
25
+ return;
26
+ const parent = parentPath(path);
27
+ if (parent.length !== 0)
28
+ return getNode(snapshot, parent);
29
+ }
30
+ function isBlock(snapshot, path) {
31
+ const parent = getParent(snapshot, path);
32
+ return parent ? !isTextBlockNode({
33
+ schema: snapshot.context.schema
34
+ }, parent.node) : !0;
35
+ }
36
+ function getBlock(snapshot, path) {
37
+ const entry = getNode(snapshot, path);
38
+ if (entry && isBlock(snapshot, path) && !isSpanNode({
39
+ schema: snapshot.context.schema
40
+ }, entry.node))
41
+ return {
42
+ node: entry.node,
43
+ path: entry.path
44
+ };
45
+ }
46
+ function hasNode(snapshot, path) {
47
+ return getNode(snapshot, path) !== void 0;
48
+ }
49
+ function resolveContainerAt(containers, value, path) {
50
+ const keyedIndices = [];
51
+ for (let index = 0; index < path.length; index++)
52
+ isKeyedSegment(path[index]) && keyedIndices.push(index);
53
+ if (keyedIndices.length === 0)
54
+ return;
55
+ let currentChildren = value, parent, resolved;
56
+ const targetKeyedIndex = keyedIndices[keyedIndices.length - 1];
57
+ let segmentIndex = 0;
58
+ for (; segmentIndex <= targetKeyedIndex; ) {
59
+ const segment = path[segmentIndex];
60
+ if (typeof segment == "string") {
61
+ segmentIndex++;
62
+ continue;
63
+ }
64
+ let node;
65
+ if (isKeyedSegment(segment))
66
+ node = currentChildren.find((child) => child._key === segment._key);
67
+ else if (typeof segment == "number")
68
+ node = currentChildren.at(segment);
69
+ else
70
+ return;
71
+ if (!node || (resolved = resolveNodeEntry(containers, parent, node), !resolved))
72
+ return;
73
+ if (segmentIndex < targetKeyedIndex) {
74
+ if (!("field" in resolved))
75
+ return;
76
+ const fieldValue = node[resolved.field.name];
77
+ if (!Array.isArray(fieldValue))
78
+ return;
79
+ parent = resolved, currentChildren = fieldValue;
80
+ }
81
+ segmentIndex++;
82
+ }
83
+ return resolved;
84
+ }
85
+ function resolveNodeEntry(containers, parent, node) {
86
+ if (parent?.of) {
87
+ for (const entry of parent.of)
88
+ if (entry.type === node._type)
89
+ return entry;
90
+ }
91
+ return containers.get(node._type);
92
+ }
93
+ function getEnclosingBlock(snapshot, path) {
94
+ const direct = getBlock(snapshot, path);
95
+ if (direct)
96
+ return direct;
97
+ for (const ancestor of getAncestors(snapshot, path))
98
+ if (isBlock(snapshot, ancestor.path)) {
99
+ const block = getBlock(snapshot, ancestor.path);
100
+ if (block)
101
+ return block;
102
+ }
103
+ }
104
+ function isAncestorPath(path, another) {
105
+ if (path.length >= another.length)
106
+ return !1;
107
+ for (let i = 0; i < path.length; i++) {
108
+ const segment = path[i], otherSegment = another[i];
109
+ if (isKeyedSegment(segment) && isKeyedSegment(otherSegment)) {
110
+ if (segment._key !== otherSegment._key)
111
+ return !1;
112
+ } else if (segment !== otherSegment)
113
+ return !1;
114
+ }
115
+ return !0;
116
+ }
117
+ function* getNodes(snapshot, options = {}) {
118
+ const {
119
+ at = [],
120
+ from,
121
+ to,
122
+ match,
123
+ reverse = !1
124
+ } = options;
125
+ if (from === void 0 && to === void 0) {
126
+ yield* getNodesSimple(snapshot, at, {
127
+ match,
128
+ reverse
129
+ });
130
+ return;
131
+ }
132
+ yield* getNodesInRange(snapshot, at, {
133
+ from,
134
+ to,
135
+ match,
136
+ reverse
137
+ });
138
+ }
139
+ function* getNodesSimple(snapshot, path, options) {
140
+ const {
141
+ match,
142
+ reverse = !1
143
+ } = options, children = getChildren(snapshot, path), entries = reverse ? [...children].reverse() : children;
144
+ for (const entry of entries)
145
+ (!match || match(entry.node, entry.path)) && (yield entry), yield* getNodesSimple(snapshot, entry.path, options);
146
+ }
147
+ function comparePathsInTree(snapshot, pathA, pathB) {
148
+ const keysA = pathA.filter(isKeyedSegment), keysB = pathB.filter(isKeyedSegment), {
149
+ context
150
+ } = snapshot;
151
+ let currentChildren = context.value, currentParent, isRootLevel = !0;
152
+ const minDepth = Math.min(keysA.length, keysB.length);
153
+ for (let depth = 0; depth < minDepth; depth++) {
154
+ const keyA = keysA[depth], keyB = keysB[depth];
155
+ if (keyA._key === keyB._key) {
156
+ let matchedNode;
157
+ if (isRootLevel && snapshot.blockIndexMap.has(keyA._key)) {
158
+ const index = snapshot.blockIndexMap.get(keyA._key);
159
+ index !== void 0 && (matchedNode = currentChildren[index]);
160
+ } else
161
+ matchedNode = currentChildren.find((c) => c._key === keyA._key);
162
+ if (!matchedNode)
163
+ return 0;
164
+ const next = getNodeChildren(context, matchedNode, currentParent);
165
+ if (!next)
166
+ return 0;
167
+ currentChildren = next.children, currentParent = next.parent, isRootLevel = !1;
168
+ continue;
169
+ }
170
+ if (isRootLevel) {
171
+ const indexA2 = snapshot.blockIndexMap.get(keyA._key) ?? -1, indexB2 = snapshot.blockIndexMap.get(keyB._key) ?? -1;
172
+ if (indexA2 !== -1 && indexB2 !== -1)
173
+ return indexA2 < indexB2 ? -1 : indexA2 > indexB2 ? 1 : 0;
174
+ }
175
+ let indexA = -1, indexB = -1;
176
+ for (let i = 0; i < currentChildren.length; i++) {
177
+ const sibling = currentChildren[i];
178
+ if (sibling._key === keyA._key && (indexA = i), sibling._key === keyB._key && (indexB = i), indexA !== -1 && indexB !== -1)
179
+ break;
180
+ }
181
+ return indexA < indexB ? -1 : indexA > indexB ? 1 : 0;
182
+ }
183
+ return keysA.length < keysB.length ? -1 : keysA.length > keysB.length ? 1 : 0;
184
+ }
185
+ function* getNodesInRange(snapshot, path, options) {
186
+ const {
187
+ from,
188
+ to,
189
+ match,
190
+ reverse = !1
191
+ } = options, children = getChildren(snapshot, path), entries = reverse ? [...children].reverse() : children;
192
+ for (const entry of entries) {
193
+ if (canStopTraversal(snapshot, entry.path, from, to, reverse))
194
+ return;
195
+ couldContainInRangeNodes(snapshot, entry.path, from, to) && (isInRange(snapshot, entry.path, from, to) && (!match || match(entry.node, entry.path)) && (yield entry), yield* getNodesInRange(snapshot, entry.path, options));
196
+ }
197
+ }
198
+ function isInRange(snapshot, nodePath, from, to) {
199
+ return !(from !== void 0 && comparePathsInTree(snapshot, nodePath, from) === -1 && !isAncestorPath(nodePath, from) || to !== void 0 && comparePathsInTree(snapshot, nodePath, to) === 1 && !isAncestorPath(nodePath, to));
200
+ }
201
+ function couldContainInRangeNodes(snapshot, nodePath, from, to) {
202
+ return !!(isInRange(snapshot, nodePath, from, to) || from !== void 0 && isAncestorPath(nodePath, from) || to !== void 0 && isAncestorPath(nodePath, to));
203
+ }
204
+ function canStopTraversal(snapshot, nodePath, from, to, reverse) {
205
+ return reverse ? from === void 0 ? !1 : comparePathsInTree(snapshot, nodePath, from) === -1 && !isAncestorPath(nodePath, from) : to === void 0 ? !1 : comparePathsInTree(snapshot, nodePath, to) === 1;
206
+ }
207
+ function getSibling(snapshot, path, direction) {
208
+ if (path.length === 0)
209
+ return;
210
+ const lastSegment = path.at(-1);
211
+ if (!isKeyedSegment(lastSegment))
212
+ return;
213
+ const parent = parentPath(path), children = getChildren(snapshot, parent), currentIndex = children.findIndex((child) => child.node._key === lastSegment._key);
214
+ if (currentIndex === -1)
215
+ return;
216
+ const siblingIndex = direction === "next" ? currentIndex + 1 : currentIndex - 1;
217
+ if (!(siblingIndex < 0 || siblingIndex >= children.length))
218
+ return children[siblingIndex];
219
+ }
220
+ function isInline(snapshot, path) {
221
+ return !isBlock(snapshot, path);
222
+ }
223
+ function descendToParent(snapshot, path) {
224
+ const ancestors = getAncestors(snapshot, path);
225
+ for (const ancestor of ancestors) {
226
+ if (!isObjectNode({
227
+ schema: snapshot.context.schema
228
+ }, ancestor.node))
229
+ continue;
230
+ const resolved = resolveContainerAt(snapshot.context.containers, snapshot.context.value, ancestor.path);
231
+ return !resolved || !("field" in resolved) ? void 0 : {
232
+ parent: resolved,
233
+ parentPath: ancestor.path
234
+ };
235
+ }
236
+ }
237
+ function getEnclosingContainer(snapshot, path) {
238
+ const descent = descendToParent(snapshot, path);
239
+ if (descent)
240
+ return {
241
+ of: descent.parent.field.of,
242
+ path: descent.parentPath
243
+ };
244
+ }
245
+ function getPathSubSchema(snapshot, path) {
246
+ const enclosing = getEnclosingContainer(snapshot, path);
247
+ return enclosing ? getSubSchema(snapshot.context.schema, enclosing.of) : snapshot.context.schema;
248
+ }
249
+ export {
250
+ getBlock,
251
+ getEnclosingBlock,
252
+ getEnclosingContainer,
253
+ getNodes,
254
+ getParent,
255
+ getPathSubSchema,
256
+ getSibling,
257
+ hasNode,
258
+ isAncestorPath,
259
+ isBlock,
260
+ isInline,
261
+ isSpanNode,
262
+ isTextBlockNode,
263
+ parentPath,
264
+ resolveContainerAt
265
+ };
266
+ //# sourceMappingURL=get-path-sub-schema.js.map