@portabletext/editor 7.0.5 → 7.1.0
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.
- package/lib/_chunks-dts/behavior.types.action.d.ts +37 -30
- package/lib/_chunks-dts/behavior.types.action.d.ts.map +1 -1
- package/lib/_chunks-dts/resolve-containers.d.ts.map +1 -1
- package/lib/_chunks-es/get-first-child.js +26 -31
- package/lib/_chunks-es/get-first-child.js.map +1 -1
- package/lib/_chunks-es/{get-node.js → get-parent.js} +35 -60
- package/lib/_chunks-es/get-parent.js.map +1 -0
- package/lib/_chunks-es/get-path-sub-schema.js +87 -43
- package/lib/_chunks-es/get-path-sub-schema.js.map +1 -1
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js +32 -34
- package/lib/_chunks-es/selector.is-at-the-start-of-block.js.map +1 -1
- package/lib/_chunks-es/util.slice-blocks.js +6 -15
- package/lib/_chunks-es/util.slice-blocks.js.map +1 -1
- package/lib/index.js +637 -550
- package/lib/index.js.map +1 -1
- package/lib/selectors/index.d.ts.map +1 -1
- package/lib/selectors/index.js +4 -8
- package/lib/selectors/index.js.map +1 -1
- package/lib/traversal/index.d.ts +94 -18
- package/lib/traversal/index.d.ts.map +1 -1
- package/lib/traversal/index.js +8 -7
- package/lib/traversal/index.js.map +1 -1
- package/lib/utils/index.js +7 -3
- package/lib/utils/index.js.map +1 -1
- package/package.json +1 -1
- package/lib/_chunks-es/get-node.js.map +0 -1
|
@@ -8,9 +8,6 @@ function isTypedObject(object) {
|
|
|
8
8
|
function isRecord(value) {
|
|
9
9
|
return !!value && (typeof value == "object" || typeof value == "function");
|
|
10
10
|
}
|
|
11
|
-
function isObjectNode(context, node) {
|
|
12
|
-
return isTypedObject(node) && node._type !== context.schema.block.name && node._type !== context.schema.span.name;
|
|
13
|
-
}
|
|
14
11
|
function getChildren(snapshot, path) {
|
|
15
12
|
let currentChildren = snapshot.context.value, currentFieldName = "value", currentPath = [], isRoot = !0, currentParent;
|
|
16
13
|
for (const segment of path) {
|
|
@@ -45,7 +42,7 @@ function getNodeChildren(context, node, parent) {
|
|
|
45
42
|
fieldName: "children",
|
|
46
43
|
parent: void 0
|
|
47
44
|
};
|
|
48
|
-
if (
|
|
45
|
+
if (isTypedObject(node) && node._type !== context.schema.block.name && node._type !== context.schema.span.name) {
|
|
49
46
|
const resolved = resolveNodeContainer(context.containers, parent, node);
|
|
50
47
|
if (!resolved)
|
|
51
48
|
return;
|
|
@@ -71,57 +68,6 @@ function resolveNodeContainer(containers, parent, node) {
|
|
|
71
68
|
}
|
|
72
69
|
return containers.get(node._type);
|
|
73
70
|
}
|
|
74
|
-
function getAncestors(snapshot, path) {
|
|
75
|
-
const keyedIndices = [];
|
|
76
|
-
for (let i = 0; i < path.length; i++)
|
|
77
|
-
isKeyedSegment(path[i]) && keyedIndices.push(i);
|
|
78
|
-
if (keyedIndices.length <= 1)
|
|
79
|
-
return [];
|
|
80
|
-
const {
|
|
81
|
-
context,
|
|
82
|
-
blockIndexMap
|
|
83
|
-
} = snapshot;
|
|
84
|
-
let currentChildren = context.value, isRootLevel = !0, currentParent;
|
|
85
|
-
const ancestorsByDepth = [], resolvedPath = [], targetKeyedIndex = keyedIndices[keyedIndices.length - 1];
|
|
86
|
-
let segmentIndex = 0;
|
|
87
|
-
for (; segmentIndex < targetKeyedIndex; ) {
|
|
88
|
-
const segment = path[segmentIndex];
|
|
89
|
-
if (typeof segment == "string") {
|
|
90
|
-
resolvedPath.push(segment), segmentIndex++;
|
|
91
|
-
continue;
|
|
92
|
-
}
|
|
93
|
-
let node;
|
|
94
|
-
if (isKeyedSegment(segment)) {
|
|
95
|
-
if (isRootLevel && blockIndexMap.size === currentChildren.length) {
|
|
96
|
-
const index = blockIndexMap.get(segment._key);
|
|
97
|
-
node = index !== void 0 ? currentChildren[index] : 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
|
-
const next = getNodeChildren(context, node, currentParent);
|
|
110
|
-
if (!next)
|
|
111
|
-
return [];
|
|
112
|
-
ancestorsByDepth.push({
|
|
113
|
-
node,
|
|
114
|
-
path: resolvedPath.slice()
|
|
115
|
-
}), currentChildren = next.children, currentParent = next.parent, segmentIndex++;
|
|
116
|
-
}
|
|
117
|
-
return ancestorsByDepth.reverse();
|
|
118
|
-
}
|
|
119
|
-
function getAncestor(snapshot, path, match) {
|
|
120
|
-
const ancestors = getAncestors(snapshot, path);
|
|
121
|
-
for (const ancestor of ancestors)
|
|
122
|
-
if (match(ancestor.node, ancestor.path))
|
|
123
|
-
return ancestor;
|
|
124
|
-
}
|
|
125
71
|
function getNode(snapshot, path) {
|
|
126
72
|
if (path.length === 0)
|
|
127
73
|
return;
|
|
@@ -178,15 +124,44 @@ function getNode(snapshot, path) {
|
|
|
178
124
|
path: resolvedPath
|
|
179
125
|
};
|
|
180
126
|
}
|
|
127
|
+
function parentPath(path) {
|
|
128
|
+
if (path.length === 0)
|
|
129
|
+
throw new Error(`Cannot get the parent path of the root path [${path}].`);
|
|
130
|
+
let lastNodeIndex = -1;
|
|
131
|
+
for (let i = path.length - 1; i >= 0; i--)
|
|
132
|
+
if (isKeyedSegment(path[i]) || typeof path[i] == "number") {
|
|
133
|
+
lastNodeIndex = i;
|
|
134
|
+
break;
|
|
135
|
+
}
|
|
136
|
+
if (lastNodeIndex === -1)
|
|
137
|
+
return [];
|
|
138
|
+
const result = path.slice(0, lastNodeIndex);
|
|
139
|
+
return result.length > 0 && typeof result[result.length - 1] == "string" ? result.slice(0, -1) : result;
|
|
140
|
+
}
|
|
141
|
+
function getParent(snapshot, path, options) {
|
|
142
|
+
if (path.length === 0)
|
|
143
|
+
return;
|
|
144
|
+
const parent = parentPath(path);
|
|
145
|
+
if (parent.length === 0)
|
|
146
|
+
return;
|
|
147
|
+
const entry = getNode(snapshot, parent);
|
|
148
|
+
if (!entry)
|
|
149
|
+
return;
|
|
150
|
+
const result = {
|
|
151
|
+
node: entry.node,
|
|
152
|
+
path: entry.path
|
|
153
|
+
};
|
|
154
|
+
if (!(options?.match && !options.match(result.node, result.path)))
|
|
155
|
+
return result;
|
|
156
|
+
}
|
|
181
157
|
export {
|
|
182
|
-
getAncestor,
|
|
183
|
-
getAncestors,
|
|
184
158
|
getChildren,
|
|
185
159
|
getNode,
|
|
186
160
|
getNodeChildren,
|
|
161
|
+
getParent,
|
|
187
162
|
isKeyedSegment,
|
|
188
|
-
isObjectNode,
|
|
189
163
|
isRecord,
|
|
190
|
-
isTypedObject
|
|
164
|
+
isTypedObject,
|
|
165
|
+
parentPath
|
|
191
166
|
};
|
|
192
|
-
//# sourceMappingURL=get-
|
|
167
|
+
//# sourceMappingURL=get-parent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"get-parent.js","sources":["../../src/utils/util.is-keyed-segment.ts","../../src/utils/asserters.ts","../../src/traversal/get-children.ts","../../src/traversal/get-node.ts","../../src/engine/path/parent-path.ts","../../src/traversal/get-parent.ts"],"sourcesContent":["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 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 {isTextBlock} from '@portabletext/schema'\nimport type {EditorSchema} from '../editor/editor-schema'\nimport type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport type {\n Containers,\n RegisteredContainer,\n} from '../schema/resolve-containers'\nimport {isTypedObject} from '../utils/asserters'\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 */\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 (\n isTypedObject(node) &&\n node._type !== context.schema.block.name &&\n node._type !== context.schema.span.name\n ) {\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 '../engine/interfaces/node'\nimport type {Path} from '../engine/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 {isKeyedSegment} from '../../utils/util.is-keyed-segment'\nimport type {Path} from '../interfaces/path'\n\n/**\n * Get the parent path of a path.\n *\n * Drops the last node segment (keyed or numeric) and the preceding field\n * name string.\n *\n * [{_key:'b1'}, 'children', {_key:'s1'}] → [{_key:'b1'}]\n * [{_key:'b1'}, 'children', 0] → [{_key:'b1'}]\n * [{_key:'b1'}] → []\n */\nexport function parentPath(path: Path): Path {\n if (path.length === 0) {\n throw new Error(`Cannot get the parent path of the root path [${path}].`)\n }\n\n let lastNodeIndex = -1\n for (let i = path.length - 1; i >= 0; i--) {\n if (isKeyedSegment(path[i]) || typeof path[i] === 'number') {\n lastNodeIndex = i\n break\n }\n }\n\n if (lastNodeIndex === -1) {\n return []\n }\n\n const result = path.slice(0, lastNodeIndex)\n\n if (result.length > 0 && typeof result[result.length - 1] === 'string') {\n return result.slice(0, -1)\n }\n\n return result\n}\n","import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {parentPath} from '../engine/path/parent-path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the parent of a node at a given path.\n *\n * A parent has children, so it is always a `PortableTextBlock` (text block\n * or object node).\n *\n * When `match` is provided and the parent does not satisfy it, returns\n * `undefined`.\n *\n * @beta\n */\nexport function getParent<TMatch extends PortableTextBlock>(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match: (node: PortableTextBlock, path: Path) => node is TMatch\n },\n): {node: TMatch; path: Path} | undefined\n/**\n * @beta\n */\nexport function getParent(\n snapshot: TraversalSnapshot,\n path: Path,\n options?: {\n match?: (node: PortableTextBlock, path: Path) => boolean\n },\n): {node: PortableTextBlock; path: Path} | undefined\nexport function getParent(\n snapshot: TraversalSnapshot,\n path: Path,\n options?: {\n match?: (node: PortableTextBlock, path: Path) => boolean\n },\n): {node: PortableTextBlock; path: Path} | undefined {\n if (path.length === 0) {\n return undefined\n }\n\n const parent = parentPath(path)\n\n if (parent.length === 0) {\n return undefined\n }\n\n const entry = getNode(snapshot, parent)\n\n if (!entry) {\n return undefined\n }\n\n const result = {node: entry.node as PortableTextBlock, path: entry.path}\n\n if (options?.match && !options.match(result.node, result.path)) {\n return undefined\n }\n\n return result\n}\n"],"names":["isKeyedSegment","segment","isTypedObject","object","isRecord","value","getChildren","snapshot","path","currentChildren","context","currentFieldName","currentPath","isRoot","currentParent","node","find","child","_key","at","next","getNodeChildren","children","fieldName","parent","map","isTextBlock","undefined","_type","schema","block","name","span","resolved","resolveNodeContainer","containers","fieldValue","field","Array","isArray","of","entry","type","get","getNode","length","blockIndexMap","resolvedPath","isRootLevel","i","push","size","index","candidate","hasMoreSegments","j","s","parentPath","Error","lastNodeIndex","result","slice","getParent","options","match"],"mappings":"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"}
|
|
@@ -1,11 +1,53 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isKeyedSegment, getNodeChildren, getNode, isTypedObject, getChildren, parentPath, getParent } from "./get-parent.js";
|
|
2
2
|
import { getSubSchema } from "@portabletext/schema";
|
|
3
|
+
function getAncestors(snapshot, path) {
|
|
4
|
+
const keyedIndices = [];
|
|
5
|
+
for (let i = 0; i < path.length; i++)
|
|
6
|
+
isKeyedSegment(path[i]) && keyedIndices.push(i);
|
|
7
|
+
if (keyedIndices.length <= 1)
|
|
8
|
+
return [];
|
|
9
|
+
const {
|
|
10
|
+
context,
|
|
11
|
+
blockIndexMap
|
|
12
|
+
} = snapshot;
|
|
13
|
+
let currentChildren = context.value, isRootLevel = !0, currentParent;
|
|
14
|
+
const ancestorsByDepth = [], resolvedPath = [], targetKeyedIndex = keyedIndices[keyedIndices.length - 1];
|
|
15
|
+
let segmentIndex = 0;
|
|
16
|
+
for (; segmentIndex < targetKeyedIndex; ) {
|
|
17
|
+
const segment = path[segmentIndex];
|
|
18
|
+
if (typeof segment == "string") {
|
|
19
|
+
resolvedPath.push(segment), segmentIndex++;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
let node;
|
|
23
|
+
if (isKeyedSegment(segment)) {
|
|
24
|
+
if (isRootLevel && blockIndexMap.size === currentChildren.length) {
|
|
25
|
+
const index = blockIndexMap.get(segment._key);
|
|
26
|
+
node = index !== void 0 ? currentChildren[index] : currentChildren.find((child) => child._key === segment._key);
|
|
27
|
+
} else
|
|
28
|
+
node = currentChildren.find((child) => child._key === segment._key);
|
|
29
|
+
resolvedPath.push(segment), isRootLevel = !1;
|
|
30
|
+
} else if (typeof segment == "number")
|
|
31
|
+
node = currentChildren.at(segment), node && resolvedPath.push({
|
|
32
|
+
_key: node._key
|
|
33
|
+
});
|
|
34
|
+
else
|
|
35
|
+
return [];
|
|
36
|
+
if (!node)
|
|
37
|
+
return [];
|
|
38
|
+
const next = getNodeChildren(context, node, currentParent);
|
|
39
|
+
if (!next)
|
|
40
|
+
return [];
|
|
41
|
+
ancestorsByDepth.push({
|
|
42
|
+
node,
|
|
43
|
+
path: resolvedPath.slice()
|
|
44
|
+
}), currentChildren = next.children, currentParent = next.parent, segmentIndex++;
|
|
45
|
+
}
|
|
46
|
+
return ancestorsByDepth.reverse();
|
|
47
|
+
}
|
|
3
48
|
function hasNode(snapshot, path) {
|
|
4
49
|
return getNode(snapshot, path) !== void 0;
|
|
5
50
|
}
|
|
6
|
-
function isTextBlockNode(context, node) {
|
|
7
|
-
return isTypedObject(node) && node._type === context.schema.block.name;
|
|
8
|
-
}
|
|
9
51
|
function resolveContainerAt(containers, value, path) {
|
|
10
52
|
const keyedIndices = [];
|
|
11
53
|
for (let index = 0; index < path.length; index++)
|
|
@@ -50,6 +92,18 @@ function resolveNodeEntry(containers, parent, node) {
|
|
|
50
92
|
}
|
|
51
93
|
return containers.get(node._type);
|
|
52
94
|
}
|
|
95
|
+
function isEditableContainer(snapshot, _node, path) {
|
|
96
|
+
if (snapshot.context.containers.size === 0)
|
|
97
|
+
return !1;
|
|
98
|
+
const resolved = resolveContainerAt(snapshot.context.containers, snapshot.context.value, path);
|
|
99
|
+
return !!(resolved && "field" in resolved);
|
|
100
|
+
}
|
|
101
|
+
function isObject(snapshot, node) {
|
|
102
|
+
return isTypedObject(node) && node._type !== snapshot.context.schema.block.name && node._type !== snapshot.context.schema.span.name;
|
|
103
|
+
}
|
|
104
|
+
function isTextBlockNode(context, node) {
|
|
105
|
+
return isTypedObject(node) && node._type === context.schema.block.name;
|
|
106
|
+
}
|
|
53
107
|
function isAncestorPath(path, another) {
|
|
54
108
|
if (path.length >= another.length)
|
|
55
109
|
return !1;
|
|
@@ -153,43 +207,28 @@ function couldContainInRangeNodes(snapshot, nodePath, from, to) {
|
|
|
153
207
|
function canStopTraversal(snapshot, nodePath, from, to, reverse) {
|
|
154
208
|
return reverse ? from === void 0 ? !1 : comparePathsInTree(snapshot, nodePath, from) === -1 && !isAncestorPath(nodePath, from) : to === void 0 ? !1 : comparePathsInTree(snapshot, nodePath, to) === 1;
|
|
155
209
|
}
|
|
156
|
-
function
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
if (isKeyedSegment(path[i]) || typeof path[i] == "number") {
|
|
162
|
-
lastNodeIndex = i;
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
if (lastNodeIndex === -1)
|
|
166
|
-
return [];
|
|
167
|
-
const result = path.slice(0, lastNodeIndex);
|
|
168
|
-
return result.length > 0 && typeof result[result.length - 1] == "string" ? result.slice(0, -1) : result;
|
|
169
|
-
}
|
|
170
|
-
function getSibling(snapshot, path, direction) {
|
|
210
|
+
function getSibling(snapshot, path, options) {
|
|
211
|
+
const {
|
|
212
|
+
direction,
|
|
213
|
+
match
|
|
214
|
+
} = options;
|
|
171
215
|
if (path.length === 0)
|
|
172
216
|
return;
|
|
173
217
|
const lastSegment = path.at(-1);
|
|
174
218
|
if (!isKeyedSegment(lastSegment))
|
|
175
219
|
return;
|
|
176
220
|
const parent = parentPath(path), children = getChildren(snapshot, parent), currentIndex = children.findIndex((child) => child.node._key === lastSegment._key);
|
|
177
|
-
if (currentIndex
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
221
|
+
if (currentIndex !== -1) {
|
|
222
|
+
if (!match) {
|
|
223
|
+
const siblingIndex = direction === "next" ? currentIndex + 1 : currentIndex - 1;
|
|
224
|
+
return siblingIndex < 0 || siblingIndex >= children.length ? void 0 : children[siblingIndex];
|
|
225
|
+
}
|
|
226
|
+
return (direction === "next" ? children.slice(currentIndex + 1) : children.slice(0, currentIndex).reverse()).find((child) => match(child.node, child.path));
|
|
227
|
+
}
|
|
182
228
|
}
|
|
183
229
|
function isSpanNode(context, node) {
|
|
184
230
|
return isTypedObject(node) && node._type === context.schema.span.name;
|
|
185
231
|
}
|
|
186
|
-
function getParent(snapshot, path) {
|
|
187
|
-
if (path.length === 0)
|
|
188
|
-
return;
|
|
189
|
-
const parent = parentPath(path);
|
|
190
|
-
if (parent.length !== 0)
|
|
191
|
-
return getNode(snapshot, parent);
|
|
192
|
-
}
|
|
193
232
|
function isBlock(snapshot, path) {
|
|
194
233
|
const parent = getParent(snapshot, path);
|
|
195
234
|
return parent ? !isTextBlockNode({
|
|
@@ -209,23 +248,27 @@ function getBlock(snapshot, path) {
|
|
|
209
248
|
function isInline(snapshot, path) {
|
|
210
249
|
return !isBlock(snapshot, path);
|
|
211
250
|
}
|
|
212
|
-
function getEnclosingBlock(snapshot, path) {
|
|
251
|
+
function getEnclosingBlock(snapshot, path, options) {
|
|
252
|
+
const match = options?.match;
|
|
253
|
+
if ((options?.mode ?? "lowest") === "highest") {
|
|
254
|
+
const ancestors = getAncestors(snapshot, path);
|
|
255
|
+
for (const ancestor of [...ancestors].reverse())
|
|
256
|
+
if (!match || match(ancestor.node, ancestor.path))
|
|
257
|
+
return ancestor;
|
|
258
|
+
const direct2 = getBlock(snapshot, path);
|
|
259
|
+
return direct2 && (!match || match(direct2.node, direct2.path)) ? direct2 : void 0;
|
|
260
|
+
}
|
|
213
261
|
const direct = getBlock(snapshot, path);
|
|
214
|
-
if (direct)
|
|
262
|
+
if (direct && (!match || match(direct.node, direct.path)))
|
|
215
263
|
return direct;
|
|
216
264
|
for (const ancestor of getAncestors(snapshot, path))
|
|
217
|
-
if (
|
|
218
|
-
|
|
219
|
-
if (block)
|
|
220
|
-
return block;
|
|
221
|
-
}
|
|
265
|
+
if (!match || match(ancestor.node, ancestor.path))
|
|
266
|
+
return ancestor;
|
|
222
267
|
}
|
|
223
268
|
function descendToParent(snapshot, path) {
|
|
224
269
|
const ancestors = getAncestors(snapshot, path);
|
|
225
270
|
for (const ancestor of ancestors) {
|
|
226
|
-
if (!
|
|
227
|
-
schema: snapshot.context.schema
|
|
228
|
-
}, ancestor.node))
|
|
271
|
+
if (!isObject(snapshot, ancestor.node))
|
|
229
272
|
continue;
|
|
230
273
|
const resolved = resolveContainerAt(snapshot.context.containers, snapshot.context.value, ancestor.path);
|
|
231
274
|
return !resolved || !("field" in resolved) ? void 0 : {
|
|
@@ -247,20 +290,21 @@ function getPathSubSchema(snapshot, path) {
|
|
|
247
290
|
return enclosing ? getSubSchema(snapshot.context.schema, enclosing.of) : snapshot.context.schema;
|
|
248
291
|
}
|
|
249
292
|
export {
|
|
293
|
+
getAncestors,
|
|
250
294
|
getBlock,
|
|
251
295
|
getEnclosingBlock,
|
|
252
296
|
getEnclosingContainer,
|
|
253
297
|
getNodes,
|
|
254
|
-
getParent,
|
|
255
298
|
getPathSubSchema,
|
|
256
299
|
getSibling,
|
|
257
300
|
hasNode,
|
|
258
301
|
isAncestorPath,
|
|
259
302
|
isBlock,
|
|
303
|
+
isEditableContainer,
|
|
260
304
|
isInline,
|
|
305
|
+
isObject,
|
|
261
306
|
isSpanNode,
|
|
262
307
|
isTextBlockNode,
|
|
263
|
-
parentPath,
|
|
264
308
|
resolveContainerAt
|
|
265
309
|
};
|
|
266
310
|
//# sourceMappingURL=get-path-sub-schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-path-sub-schema.js","sources":["../../src/node-traversal/has-node.ts","../../src/engine/node/is-text-block-node.ts","../../src/schema/resolve-container-at.ts","../../src/engine/path/is-ancestor-path.ts","../../src/node-traversal/get-nodes.ts","../../src/engine/path/parent-path.ts","../../src/node-traversal/get-sibling.ts","../../src/engine/node/is-span-node.ts","../../src/node-traversal/get-parent.ts","../../src/node-traversal/is-block.ts","../../src/node-traversal/is-inline.ts","../../src/node-traversal/get-enclosing-block.ts","../../src/schema/descend-to-parent.ts","../../src/schema/get-enclosing-container.ts","../../src/traversal/get-path-sub-schema.ts"],"sourcesContent":["import type {Path} from '../engine/interfaces/path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Check if a node exists at a given path.\n *\n * @beta\n */\nexport function hasNode(snapshot: TraversalSnapshot, path: Path): boolean {\n return getNode(snapshot, path) !== undefined\n}\n","import type {PortableTextObject, PortableTextSpan} from '@portabletext/schema'\nimport type {EditorSchema} from '../../editor/editor-schema'\nimport {isTypedObject} from '../../utils/asserters'\n\ntype TextBlockNode = {\n _type: string\n _key: string\n children?: Array<PortableTextSpan | PortableTextObject>\n markDefs?: Array<PortableTextObject>\n style?: string\n listItem?: string\n level?: number\n}\n\n/**\n * Checks if a node is a text block based on `_type` alone, without requiring\n * `children` to be present. This is needed to identify text blocks before\n * normalization has had a chance to add the missing `children` property.\n */\nexport function isTextBlockNode(\n context: {schema: EditorSchema},\n node: unknown,\n): node is TextBlockNode {\n return isTypedObject(node) && node._type === context.schema.block.name\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport type {\n Containers,\n RegisteredContainer,\n RegisteredPositional,\n} from './container-types'\n\n/**\n * Walk the editor value following `path` and return the\n * {@link RegisteredContainer} or {@link RegisteredPositional} that applies\n * at `path`'s target position.\n *\n * Resolution rules at each step:\n *\n * 1. **Positional override.** If the current parent declares the\n * child's `_type` in its `of`, the positional entry wins.\n * Used to resolve same-`_type` registered under different\n * parents with different `field` values.\n *\n * 2. **Global fallback.** If the parent has no positional override,\n * fall back to the top-level entry for `_type` in\n * `containers`.\n *\n * 3. **Chain validity.** If any ancestor along the path has no\n * resolved container entry (unregistered or not reachable as a\n * container at its position), return `undefined`.\n *\n * Returns `undefined` when the target's `_type` is not registered\n * at this position. Returns a {@link RegisteredPositional} when the target\n * resolves to a leaf in a positional `of` (terminal node with no\n * editable children).\n *\n * @alpha\n */\nexport function resolveContainerAt(\n containers: Containers,\n value: ReadonlyArray<Node>,\n path: Path,\n): RegisteredContainer | RegisteredPositional | undefined {\n const keyedIndices: Array<number> = []\n for (let index = 0; index < path.length; index++) {\n if (isKeyedSegment(path[index])) {\n keyedIndices.push(index)\n }\n }\n if (keyedIndices.length === 0) {\n return undefined\n }\n\n let currentChildren: ReadonlyArray<Node> = value\n let parent: RegisteredContainer | undefined\n let resolved: RegisteredContainer | RegisteredPositional | undefined\n const targetKeyedIndex = keyedIndices[keyedIndices.length - 1]!\n\n let segmentIndex = 0\n while (segmentIndex <= targetKeyedIndex) {\n const segment = path[segmentIndex]!\n if (typeof segment === 'string') {\n segmentIndex++\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 } else {\n return undefined\n }\n if (!node) {\n return undefined\n }\n\n resolved = resolveNodeEntry(containers, parent, node)\n if (!resolved) {\n return undefined\n }\n\n if (segmentIndex < targetKeyedIndex) {\n // Walk one more level. The resolved entry must be a container\n // (have children) for descent to continue.\n if (!('field' in resolved)) {\n return undefined\n }\n const fieldValue = (node as Record<string, unknown>)[resolved.field.name]\n if (!Array.isArray(fieldValue)) {\n return undefined\n }\n parent = resolved\n currentChildren = fieldValue as Array<Node>\n }\n segmentIndex++\n }\n\n return resolved\n}\n\nfunction resolveNodeEntry(\n containers: Containers,\n parent: RegisteredContainer | undefined,\n node: Node,\n): RegisteredContainer | RegisteredPositional | undefined {\n if (parent?.of) {\n for (const entry of parent.of) {\n if (entry.type === node._type) {\n return entry\n }\n }\n }\n return containers.get(node._type)\n}\n","import {isKeyedSegment} from '../../utils/util.is-keyed-segment'\nimport type {Path} from '../interfaces/path'\n\nexport function isAncestorPath(path: Path, another: Path): boolean {\n if (path.length >= another.length) {\n return false\n }\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i]\n const otherSegment = another[i]\n\n if (isKeyedSegment(segment) && isKeyedSegment(otherSegment)) {\n if (segment._key !== otherSegment._key) {\n return false\n }\n } else if (segment !== otherSegment) {\n return false\n }\n }\n\n return true\n}\n","import type {EditorSchema} from '../editor/editor-schema'\nimport type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {isAncestorPath} from '../engine/path/is-ancestor-path'\nimport type {\n Containers,\n RegisteredContainer,\n} from '../schema/resolve-containers'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getChildren, getNodeChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the descendant nodes of the node at a given path.\n *\n * When `from` and `to` are provided, performs a range-bounded DFS traversal,\n * yielding only nodes between `from` and `to` (inclusive). Both paths are\n * always in document order: `from` is the earlier path, `to` is the later\n * path. The `reverse` flag controls iteration direction within that range.\n *\n * When `match` is provided, only yields nodes where the predicate returns true.\n * The traversal still visits all nodes in range - `match` is a filter, not a\n * traversal control.\n *\n * When `at` is provided, traverses descendants of the node at that path\n * instead of the root.\n */\nexport function* getNodes(\n snapshot: TraversalSnapshot,\n options: {\n at?: Path\n from?: Path\n to?: Path\n match?: (node: Node, path: Path) => boolean\n reverse?: boolean\n } = {},\n): Generator<{node: Node; path: Path}, void, undefined> {\n const {at = [], from, to, match, reverse = false} = options\n\n if (from === undefined && to === undefined) {\n yield* getNodesSimple(snapshot, at, {match, reverse})\n return\n }\n\n yield* getNodesInRange(snapshot, at, {from, to, match, reverse})\n}\n\n/**\n * Get descendant nodes of a standalone node (not in the editor tree).\n * Used for cases like getDirtyPaths where the node hasn't been inserted yet.\n */\nexport function* getNodeDescendants(\n context: {\n schema: EditorSchema\n containers: Containers\n },\n node: Node | {value: Array<Node>},\n): Generator<{node: Node; path: Path}, void, undefined> {\n // The editor root wrapper ({value: [...]}) is not a real node, so its field\n // name is not part of paths. For standalone nodes (a real {_key, _type, ...}\n // passed in by callers like getDirtyPaths), the field name IS part of the\n // path.\n const isRoot = !('_key' in node) && !('_type' in node)\n yield* walkStandalone(context, node, [], isRoot)\n}\n\nfunction* walkStandalone(\n context: {\n schema: EditorSchema\n containers: Containers\n },\n node: Node | {value: Array<Node>},\n path: Path,\n isRoot: boolean,\n parent?: RegisteredContainer,\n): Generator<{node: Node; path: Path}, void, undefined> {\n const next = getNodeChildren(context, node, parent)\n if (!next) {\n return\n }\n\n for (const child of next.children) {\n const childPath: Path = isRoot\n ? [{_key: child._key}]\n : [...path, next.fieldName, {_key: child._key}]\n yield {node: child, path: childPath}\n yield* walkStandalone(context, child, childPath, false, next.parent)\n }\n}\n\n/**\n * Simple recursive DFS - the original behavior.\n * Yields all descendants of the node at `path`.\n */\nfunction* getNodesSimple(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match?: (node: Node, path: Path) => boolean\n reverse?: boolean\n },\n): Generator<{node: Node; path: Path}, void, undefined> {\n const {match, reverse = false} = options\n\n const children = getChildren(snapshot, path)\n\n const entries = reverse ? [...children].reverse() : children\n\n for (const entry of entries) {\n if (!match || match(entry.node, entry.path)) {\n yield entry\n }\n\n yield* getNodesSimple(snapshot, entry.path, options)\n }\n}\n\n/**\n * Compare two keyed paths in document order. Returns -1, 0, or 1.\n *\n * Descends both paths from the root in a single pass, advancing\n * `currentNode` and `currentChildren` together so each level costs\n * one keyed-segment scan instead of an O(depth) walk from root.\n *\n * Uses `blockIndexMap` for O(1) lookup at the root level. Deeper\n * levels fall back to a linear scan of the current sibling array.\n */\nfunction comparePathsInTree(\n snapshot: TraversalSnapshot,\n pathA: Path,\n pathB: Path,\n): -1 | 0 | 1 {\n const keysA = pathA.filter(isKeyedSegment)\n const keysB = pathB.filter(isKeyedSegment)\n\n const {context} = snapshot\n let currentChildren: Array<Node> = context.value\n let currentParent: RegisteredContainer | undefined\n let isRootLevel = true\n\n const minDepth = Math.min(keysA.length, keysB.length)\n\n for (let depth = 0; depth < minDepth; depth++) {\n const keyA = keysA[depth]!\n const keyB = keysB[depth]!\n\n if (keyA._key === keyB._key) {\n // Same node at this depth: descend into its children for the next\n // iteration. The root level can short-circuit via blockIndexMap;\n // deeper levels scan the current sibling array.\n let matchedNode: Node | undefined\n if (isRootLevel && snapshot.blockIndexMap.has(keyA._key)) {\n const index = snapshot.blockIndexMap.get(keyA._key)\n if (index !== undefined) {\n matchedNode = currentChildren[index]\n }\n } else {\n matchedNode = currentChildren.find((c) => c._key === keyA._key)\n }\n if (!matchedNode) {\n return 0\n }\n const next = getNodeChildren(context, matchedNode, currentParent)\n if (!next) {\n return 0\n }\n currentChildren = next.children\n currentParent = next.parent\n\n isRootLevel = false\n continue\n }\n\n if (isRootLevel) {\n const indexA = snapshot.blockIndexMap.get(keyA._key) ?? -1\n const indexB = snapshot.blockIndexMap.get(keyB._key) ?? -1\n if (indexA !== -1 && indexB !== -1) {\n if (indexA < indexB) {\n return -1\n }\n if (indexA > indexB) {\n return 1\n }\n return 0\n }\n }\n\n let indexA = -1\n let indexB = -1\n for (let i = 0; i < currentChildren.length; i++) {\n const sibling = currentChildren[i]!\n if (sibling._key === keyA._key) {\n indexA = i\n }\n if (sibling._key === keyB._key) {\n indexB = i\n }\n if (indexA !== -1 && indexB !== -1) {\n break\n }\n }\n\n if (indexA < indexB) {\n return -1\n }\n if (indexA > indexB) {\n return 1\n }\n\n return 0\n }\n\n // One path is a prefix of the other (ancestor relationship)\n // In DFS order, shorter path (ancestor) comes first\n if (keysA.length < keysB.length) {\n return -1\n }\n if (keysA.length > keysB.length) {\n return 1\n }\n\n return 0\n}\n\n/**\n * Range-bounded recursive DFS traversal.\n *\n * `from` and `to` are always in document order (from is earlier, to is\n * later), regardless of traversal direction.\n */\nfunction* getNodesInRange(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n from?: Path\n to?: Path\n match?: (node: Node, path: Path) => boolean\n reverse?: boolean\n },\n): Generator<{node: Node; path: Path}, void, undefined> {\n const {from, to, match, reverse = false} = options\n\n const children = getChildren(snapshot, path)\n const entries = reverse ? [...children].reverse() : children\n\n for (const entry of entries) {\n if (canStopTraversal(snapshot, entry.path, from, to, reverse)) {\n return\n }\n\n if (!couldContainInRangeNodes(snapshot, entry.path, from, to)) {\n continue\n }\n\n if (isInRange(snapshot, entry.path, from, to)) {\n if (!match || match(entry.node, entry.path)) {\n yield entry\n }\n }\n\n yield* getNodesInRange(snapshot, entry.path, options)\n }\n}\n\n/**\n * Check if a node is within the [from, to] range in document order.\n * Both bounds are inclusive. Ancestor nodes of from or to are also\n * considered in range since they contain the range boundary.\n */\nfunction isInRange(\n snapshot: TraversalSnapshot,\n nodePath: Path,\n from: Path | undefined,\n to: Path | undefined,\n): boolean {\n if (\n from !== undefined &&\n comparePathsInTree(snapshot, nodePath, from) === -1\n ) {\n if (!isAncestorPath(nodePath, from)) {\n return false\n }\n }\n\n if (to !== undefined && comparePathsInTree(snapshot, nodePath, to) === 1) {\n if (!isAncestorPath(nodePath, to)) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Check if a subtree rooted at `nodePath` could contain any nodes in the\n * [from, to] range.\n */\nfunction couldContainInRangeNodes(\n snapshot: TraversalSnapshot,\n nodePath: Path,\n from: Path | undefined,\n to: Path | undefined,\n): boolean {\n if (isInRange(snapshot, nodePath, from, to)) {\n return true\n }\n\n if (from !== undefined && isAncestorPath(nodePath, from)) {\n return true\n }\n\n if (to !== undefined && isAncestorPath(nodePath, to)) {\n return true\n }\n\n return false\n}\n\n/**\n * Check if all remaining nodes in iteration order will be outside the range.\n */\nfunction canStopTraversal(\n snapshot: TraversalSnapshot,\n nodePath: Path,\n from: Path | undefined,\n to: Path | undefined,\n reverse: boolean,\n): boolean {\n if (reverse) {\n if (from === undefined) {\n return false\n }\n\n return (\n comparePathsInTree(snapshot, nodePath, from) === -1 &&\n !isAncestorPath(nodePath, from)\n )\n }\n\n if (to === undefined) {\n return false\n }\n\n return comparePathsInTree(snapshot, nodePath, to) === 1\n}\n","import {isKeyedSegment} from '../../utils/util.is-keyed-segment'\nimport type {Path} from '../interfaces/path'\n\n/**\n * Get the parent path of a path.\n *\n * Drops the last node segment (keyed or numeric) and the preceding field\n * name string.\n *\n * [{_key:'b1'}, 'children', {_key:'s1'}] → [{_key:'b1'}]\n * [{_key:'b1'}, 'children', 0] → [{_key:'b1'}]\n * [{_key:'b1'}] → []\n */\nexport function parentPath(path: Path): Path {\n if (path.length === 0) {\n throw new Error(`Cannot get the parent path of the root path [${path}].`)\n }\n\n let lastNodeIndex = -1\n for (let i = path.length - 1; i >= 0; i--) {\n if (isKeyedSegment(path[i]) || typeof path[i] === 'number') {\n lastNodeIndex = i\n break\n }\n }\n\n if (lastNodeIndex === -1) {\n return []\n }\n\n const result = path.slice(0, lastNodeIndex)\n\n if (result.length > 0 && typeof result[result.length - 1] === 'string') {\n return result.slice(0, -1)\n }\n\n return result\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {parentPath} from '../engine/path/parent-path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the next or previous sibling of the node at a given path.\n *\n * @beta\n */\nexport function getSibling(\n snapshot: TraversalSnapshot,\n path: Path,\n direction: 'next' | 'previous',\n): {node: Node; path: Path} | undefined {\n if (path.length === 0) {\n return undefined\n }\n\n const lastSegment = path.at(-1)\n\n if (!isKeyedSegment(lastSegment)) {\n return undefined\n }\n\n const parent = parentPath(path)\n const children = getChildren(snapshot, parent)\n\n const currentIndex = children.findIndex(\n (child) => child.node._key === lastSegment._key,\n )\n\n if (currentIndex === -1) {\n return undefined\n }\n\n const siblingIndex =\n direction === 'next' ? currentIndex + 1 : currentIndex - 1\n\n if (siblingIndex < 0 || siblingIndex >= children.length) {\n return undefined\n }\n\n return children[siblingIndex]\n}\n","import type {EditorSchema} from '../../editor/editor-schema'\nimport {isTypedObject} from '../../utils/asserters'\n\nexport type SpanNode = {\n _type: string\n _key: string\n text?: string\n marks?: Array<string>\n}\n\n/**\n * Checks if a node is a span based on `_type` alone, without requiring `text`\n * to be present. This is needed to identify spans before normalization has had\n * a chance to add the missing `text` property.\n */\nexport function isSpanNode(\n context: {schema: EditorSchema},\n node: unknown,\n): node is SpanNode {\n return isTypedObject(node) && node._type === context.schema.span.name\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {parentPath} from '../engine/path/parent-path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the parent of a node at a given path.\n *\n * @beta\n */\nexport function getParent(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: Node; path: Path} | undefined {\n if (path.length === 0) {\n return undefined\n }\n\n const parent = parentPath(path)\n\n if (parent.length === 0) {\n return undefined\n }\n\n return getNode(snapshot, parent)\n}\n","import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {isSpanNode} from '../engine/node/is-span-node'\nimport {isTextBlockNode} from '../engine/node/is-text-block-node'\nimport {getNode} from './get-node'\nimport {getParent} from './get-parent'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Determine if a node at the given path is a block.\n *\n * A node is a block if its parent is not a text block. Top-level nodes\n * (direct children of the editor) are always blocks. Children of text blocks\n * (spans and inline objects) are not blocks. Children of containers are\n * blocks within that container.\n *\n * @beta\n */\nexport function isBlock(snapshot: TraversalSnapshot, path: Path): boolean {\n const parent = getParent(snapshot, path)\n\n if (!parent) {\n return true\n }\n\n return !isTextBlockNode({schema: snapshot.context.schema}, parent.node)\n}\n\n/**\n * Get the node at the given path if it is a block.\n *\n * Returns the node narrowed to PortableTextBlock, or undefined if the node\n * doesn't exist or is not a block.\n *\n * @beta\n */\nexport function getBlock(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextBlock; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isBlock(snapshot, path)) {\n return undefined\n }\n\n // Narrow the type: a block is never a span (spans always have a text block\n // parent, so isBlock returns false for them).\n if (isSpanNode({schema: snapshot.context.schema}, entry.node)) {\n return undefined\n }\n\n // Node minus PortableTextSpan = PortableTextTextBlock | PortableTextObject = PortableTextBlock\n return {node: entry.node, path: entry.path}\n}\n","import type {Path} from '../engine/interfaces/path'\nimport {isBlock} from './is-block'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Determine if a node at the given path is inline.\n *\n * A node is inline if its parent is a text block. This is the inverse of\n * `isBlock`. Top-level nodes are never inline.\n *\n * @beta\n */\nexport function isInline(snapshot: TraversalSnapshot, path: Path): boolean {\n return !isBlock(snapshot, path)\n}\n","import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getAncestors} from './get-ancestors'\nimport {getBlock, isBlock} from './is-block'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Walk up from a path to find the nearest enclosing block.\n *\n * Returns the node at the path if it is a block, otherwise the first ancestor\n * that is a block. Works at any depth — inside a container this returns the\n * container-internal block, not the outer container.\n *\n * @beta\n */\nexport function getEnclosingBlock(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextBlock; path: Path} | undefined {\n const direct = getBlock(snapshot, path)\n\n if (direct) {\n return direct\n }\n\n for (const ancestor of getAncestors(snapshot, path)) {\n if (isBlock(snapshot, ancestor.path)) {\n const block = getBlock(snapshot, ancestor.path)\n\n if (block) {\n return block\n }\n }\n }\n\n return undefined\n}\n","import type {Path} from '../engine/interfaces/path'\nimport {isObjectNode} from '../engine/node/is-object-node'\nimport {getAncestors} from '../node-traversal/get-ancestors'\nimport type {TraversalSnapshot} from '../node-traversal/traversal-snapshot'\nimport type {RegisteredContainer} from './container-types'\nimport {resolveContainerAt} from './resolve-container-at'\n\n/**\n * Descent primitive: return the immediate parent\n * {@link RegisteredContainer} of the node at `path` (and that parent's\n * path), or `undefined` when the target's immediate parent is the\n * editor root, when no object-node ancestor is a registered container,\n * or when descent hits an ancestor whose `_type` is not registered.\n *\n * Walks ancestors and resolves each object-node ancestor positionally\n * via {@link resolveContainerAt}. Text-block and span ancestors are\n * skipped - \"container\" here means the enclosing object container,\n * not the text-block holding spans.\n */\nexport function descendToParent(\n snapshot: TraversalSnapshot,\n path: Path,\n): {parent: RegisteredContainer; parentPath: Path} | undefined {\n const ancestors = getAncestors(snapshot, path)\n for (const ancestor of ancestors) {\n if (!isObjectNode({schema: snapshot.context.schema}, ancestor.node)) {\n continue\n }\n const resolved = resolveContainerAt(\n snapshot.context.containers,\n snapshot.context.value,\n ancestor.path,\n )\n if (!resolved || !('field' in resolved)) {\n return undefined\n }\n return {parent: resolved, parentPath: ancestor.path}\n }\n return undefined\n}\n","import type {OfDefinition} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport type {TraversalSnapshot} from '../node-traversal/traversal-snapshot'\nimport {descendToParent} from './descend-to-parent'\n\n/**\n * Return the immediate registered-container ancestor of `path` along\n * with its `of` array (the schema definitions accepted at this position).\n *\n * Position-aware: nested-only registrations (e.g. `cell` registered\n * only inside `table.row.of`) are recognized via the same descent\n * primitive used by all parent-aware traversal.\n *\n * Returns `undefined` when `path` has no registered-container ancestor\n * (i.e. is at the document root) or when descent hits a leaf-resolved\n * ancestor.\n */\nexport function getEnclosingContainer(\n snapshot: TraversalSnapshot,\n path: Path,\n):\n | {\n of: ReadonlyArray<OfDefinition>\n path: Path\n }\n | undefined {\n const descent = descendToParent(snapshot, path)\n if (!descent) {\n return undefined\n }\n return {\n of: descent.parent.field.of,\n path: descent.parentPath,\n }\n}\n","import {getSubSchema, type Schema} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport type {TraversalSnapshot} from '../node-traversal/traversal-snapshot'\nimport {getEnclosingContainer} from '../schema/get-enclosing-container'\n\n/**\n * Return the `Schema` view that applies at a given path.\n *\n * For paths at the root of the document, or for paths where no ancestor is\n * a registered container, returns the top-level schema. For paths inside a\n * container, walks ancestors to find the nearest container and returns the\n * sub-schema derived from its `of` declaration.\n *\n * @beta\n */\nexport function getPathSubSchema(\n snapshot: TraversalSnapshot,\n path: Path,\n): Schema {\n const enclosing = getEnclosingContainer(snapshot, path)\n\n if (!enclosing) {\n return snapshot.context.schema\n }\n\n return getSubSchema(snapshot.context.schema, enclosing.of)\n}\n"],"names":["hasNode","snapshot","path","getNode","undefined","isTextBlockNode","context","node","isTypedObject","_type","schema","block","name","resolveContainerAt","containers","value","keyedIndices","index","length","isKeyedSegment","push","currentChildren","parent","resolved","targetKeyedIndex","segmentIndex","segment","find","child","_key","at","resolveNodeEntry","fieldValue","field","Array","isArray","of","entry","type","get","isAncestorPath","another","i","otherSegment","getNodes","options","from","to","match","reverse","getNodesSimple","getNodesInRange","children","getChildren","entries","comparePathsInTree","pathA","pathB","keysA","filter","keysB","currentParent","isRootLevel","minDepth","Math","min","depth","keyA","keyB","matchedNode","blockIndexMap","has","c","next","getNodeChildren","indexA","indexB","sibling","canStopTraversal","couldContainInRangeNodes","isInRange","nodePath","parentPath","Error","lastNodeIndex","result","slice","getSibling","direction","lastSegment","currentIndex","findIndex","siblingIndex","isSpanNode","span","getParent","isBlock","getBlock","isInline","getEnclosingBlock","direct","ancestor","getAncestors","descendToParent","ancestors","isObjectNode","getEnclosingContainer","descent","getPathSubSchema","enclosing","getSubSchema"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"get-path-sub-schema.js","sources":["../../src/traversal/get-ancestors.ts","../../src/traversal/has-node.ts","../../src/schema/resolve-container-at.ts","../../src/schema/is-editable-container.ts","../../src/traversal/is-object.ts","../../src/engine/node/is-text-block-node.ts","../../src/engine/path/is-ancestor-path.ts","../../src/traversal/get-nodes.ts","../../src/traversal/get-sibling.ts","../../src/engine/node/is-span-node.ts","../../src/traversal/is-block.ts","../../src/traversal/is-inline.ts","../../src/traversal/get-enclosing-block.ts","../../src/schema/descend-to-parent.ts","../../src/schema/get-enclosing-container.ts","../../src/traversal/get-path-sub-schema.ts"],"sourcesContent":["import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/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 * Every ancestor is a `PortableTextBlock` — only text blocks and object\n * nodes can contain children.\n *\n * @beta\n */\nexport function getAncestors(\n snapshot: TraversalSnapshot,\n path: Path,\n): Array<{node: PortableTextBlock; 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: PortableTextBlock; 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 // An ancestor has children, so it is never a span. The narrowing\n // from `Node` to `PortableTextBlock` (text block | object) is safe.\n ancestorsByDepth.push({\n node: node as PortableTextBlock,\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 {Path} from '../engine/interfaces/path'\nimport {getNode} from './get-node'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Check if a node exists at a given path.\n *\n * @beta\n */\nexport function hasNode(snapshot: TraversalSnapshot, path: Path): boolean {\n return getNode(snapshot, path) !== undefined\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport type {\n Containers,\n RegisteredContainer,\n RegisteredPositional,\n} from './container-types'\n\n/**\n * Walk the editor value following `path` and return the\n * {@link RegisteredContainer} or {@link RegisteredPositional} that applies\n * at `path`'s target position.\n *\n * Resolution rules at each step:\n *\n * 1. **Positional override.** If the current parent declares the\n * child's `_type` in its `of`, the positional entry wins.\n * Used to resolve same-`_type` registered under different\n * parents with different `field` values.\n *\n * 2. **Global fallback.** If the parent has no positional override,\n * fall back to the top-level entry for `_type` in\n * `containers`.\n *\n * 3. **Chain validity.** If any ancestor along the path has no\n * resolved container entry (unregistered or not reachable as a\n * container at its position), return `undefined`.\n *\n * Returns `undefined` when the target's `_type` is not registered\n * at this position. Returns a {@link RegisteredPositional} when the target\n * resolves to a leaf in a positional `of` (terminal node with no\n * editable children).\n *\n * @alpha\n */\nexport function resolveContainerAt(\n containers: Containers,\n value: ReadonlyArray<Node>,\n path: Path,\n): RegisteredContainer | RegisteredPositional | undefined {\n const keyedIndices: Array<number> = []\n for (let index = 0; index < path.length; index++) {\n if (isKeyedSegment(path[index])) {\n keyedIndices.push(index)\n }\n }\n if (keyedIndices.length === 0) {\n return undefined\n }\n\n let currentChildren: ReadonlyArray<Node> = value\n let parent: RegisteredContainer | undefined\n let resolved: RegisteredContainer | RegisteredPositional | undefined\n const targetKeyedIndex = keyedIndices[keyedIndices.length - 1]!\n\n let segmentIndex = 0\n while (segmentIndex <= targetKeyedIndex) {\n const segment = path[segmentIndex]!\n if (typeof segment === 'string') {\n segmentIndex++\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 } else {\n return undefined\n }\n if (!node) {\n return undefined\n }\n\n resolved = resolveNodeEntry(containers, parent, node)\n if (!resolved) {\n return undefined\n }\n\n if (segmentIndex < targetKeyedIndex) {\n // Walk one more level. The resolved entry must be a container\n // (have children) for descent to continue.\n if (!('field' in resolved)) {\n return undefined\n }\n const fieldValue = (node as Record<string, unknown>)[resolved.field.name]\n if (!Array.isArray(fieldValue)) {\n return undefined\n }\n parent = resolved\n currentChildren = fieldValue as Array<Node>\n }\n segmentIndex++\n }\n\n return resolved\n}\n\nfunction resolveNodeEntry(\n containers: Containers,\n parent: RegisteredContainer | undefined,\n node: Node,\n): RegisteredContainer | RegisteredPositional | undefined {\n if (parent?.of) {\n for (const entry of parent.of) {\n if (entry.type === node._type) {\n return entry\n }\n }\n }\n return containers.get(node._type)\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport type {TraversalSnapshot} from '../traversal/traversal-snapshot'\nimport {resolveContainerAt} from './resolve-container-at'\n\n/**\n * Check if a node at the given path is a registered editable container.\n *\n * Position-aware: {@link resolveContainerAt} descends from the editor\n * root threading the resolved parent at each step, so positionally-\n * registered containers (e.g. `cell` registered only inside\n * `table.of`) are recognized when reached through their declared\n * parent.\n */\nexport function isEditableContainer(\n snapshot: TraversalSnapshot,\n _node: Node,\n path: Path,\n): boolean {\n if (snapshot.context.containers.size === 0) {\n return false\n }\n\n // `resolveContainerAt` aborts on the first unregistered object-node\n // ancestor (chain validity falls out of the single descent), so the\n // single call below answers both \"is the node here a container?\" and\n // \"is the ancestor chain valid?\" in one walk.\n const resolved = resolveContainerAt(\n snapshot.context.containers,\n snapshot.context.value,\n path,\n )\n return !!(resolved && 'field' in resolved)\n}\n","import type {PortableTextObject} from '@portabletext/schema'\nimport {isTypedObject} from '../utils/asserters'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Check if a node is an object node (not a text block or span).\n *\n * @beta\n */\nexport function isObject(\n snapshot: TraversalSnapshot,\n node: unknown,\n): node is PortableTextObject {\n return (\n isTypedObject(node) &&\n node._type !== snapshot.context.schema.block.name &&\n node._type !== snapshot.context.schema.span.name\n )\n}\n","import type {PortableTextObject, PortableTextSpan} from '@portabletext/schema'\nimport type {EditorSchema} from '../../editor/editor-schema'\nimport {isTypedObject} from '../../utils/asserters'\n\ntype TextBlockNode = {\n _type: string\n _key: string\n children?: Array<PortableTextSpan | PortableTextObject>\n markDefs?: Array<PortableTextObject>\n style?: string\n listItem?: string\n level?: number\n}\n\n/**\n * Checks if a node is a text block based on `_type` alone, without requiring\n * `children` to be present. This is needed to identify text blocks before\n * normalization has had a chance to add the missing `children` property.\n */\nexport function isTextBlockNode(\n context: {schema: EditorSchema},\n node: unknown,\n): node is TextBlockNode {\n return isTypedObject(node) && node._type === context.schema.block.name\n}\n","import {isKeyedSegment} from '../../utils/util.is-keyed-segment'\nimport type {Path} from '../interfaces/path'\n\nexport function isAncestorPath(path: Path, another: Path): boolean {\n if (path.length >= another.length) {\n return false\n }\n\n for (let i = 0; i < path.length; i++) {\n const segment = path[i]\n const otherSegment = another[i]\n\n if (isKeyedSegment(segment) && isKeyedSegment(otherSegment)) {\n if (segment._key !== otherSegment._key) {\n return false\n }\n } else if (segment !== otherSegment) {\n return false\n }\n }\n\n return true\n}\n","import type {EditorSchema} from '../editor/editor-schema'\nimport type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {isAncestorPath} from '../engine/path/is-ancestor-path'\nimport type {\n Containers,\n RegisteredContainer,\n} from '../schema/resolve-containers'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getChildren, getNodeChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get the descendant nodes of the node at a given path.\n *\n * When `from` and `to` are provided, performs a range-bounded DFS traversal,\n * yielding only nodes between `from` and `to` (inclusive). Both paths are\n * always in document order: `from` is the earlier path, `to` is the later\n * path. The `reverse` flag controls iteration direction within that range.\n *\n * When `match` is provided, only yields nodes where the predicate returns true.\n * The traversal still visits all nodes in range - `match` is a filter, not a\n * traversal control.\n *\n * When `at` is provided, traverses descendants of the node at that path\n * instead of the root.\n */\nexport function* getNodes(\n snapshot: TraversalSnapshot,\n options: {\n at?: Path\n from?: Path\n to?: Path\n match?: (node: Node, path: Path) => boolean\n reverse?: boolean\n } = {},\n): Generator<{node: Node; path: Path}, void, undefined> {\n const {at = [], from, to, match, reverse = false} = options\n\n if (from === undefined && to === undefined) {\n yield* getNodesSimple(snapshot, at, {match, reverse})\n return\n }\n\n yield* getNodesInRange(snapshot, at, {from, to, match, reverse})\n}\n\n/**\n * Get descendant nodes of a standalone node (not in the editor tree).\n * Used for cases like getDirtyPaths where the node hasn't been inserted yet.\n */\nexport function* getNodeDescendants(\n context: {\n schema: EditorSchema\n containers: Containers\n },\n node: Node | {value: Array<Node>},\n): Generator<{node: Node; path: Path}, void, undefined> {\n // The editor root wrapper ({value: [...]}) is not a real node, so its field\n // name is not part of paths. For standalone nodes (a real {_key, _type, ...}\n // passed in by callers like getDirtyPaths), the field name IS part of the\n // path.\n const isRoot = !('_key' in node) && !('_type' in node)\n yield* walkStandalone(context, node, [], isRoot)\n}\n\nfunction* walkStandalone(\n context: {\n schema: EditorSchema\n containers: Containers\n },\n node: Node | {value: Array<Node>},\n path: Path,\n isRoot: boolean,\n parent?: RegisteredContainer,\n): Generator<{node: Node; path: Path}, void, undefined> {\n const next = getNodeChildren(context, node, parent)\n if (!next) {\n return\n }\n\n for (const child of next.children) {\n const childPath: Path = isRoot\n ? [{_key: child._key}]\n : [...path, next.fieldName, {_key: child._key}]\n yield {node: child, path: childPath}\n yield* walkStandalone(context, child, childPath, false, next.parent)\n }\n}\n\n/**\n * Simple recursive DFS - the original behavior.\n * Yields all descendants of the node at `path`.\n */\nfunction* getNodesSimple(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match?: (node: Node, path: Path) => boolean\n reverse?: boolean\n },\n): Generator<{node: Node; path: Path}, void, undefined> {\n const {match, reverse = false} = options\n\n const children = getChildren(snapshot, path)\n\n const entries = reverse ? [...children].reverse() : children\n\n for (const entry of entries) {\n if (!match || match(entry.node, entry.path)) {\n yield entry\n }\n\n yield* getNodesSimple(snapshot, entry.path, options)\n }\n}\n\n/**\n * Compare two keyed paths in document order. Returns -1, 0, or 1.\n *\n * Descends both paths from the root in a single pass, advancing\n * `currentNode` and `currentChildren` together so each level costs\n * one keyed-segment scan instead of an O(depth) walk from root.\n *\n * Uses `blockIndexMap` for O(1) lookup at the root level. Deeper\n * levels fall back to a linear scan of the current sibling array.\n */\nfunction comparePathsInTree(\n snapshot: TraversalSnapshot,\n pathA: Path,\n pathB: Path,\n): -1 | 0 | 1 {\n const keysA = pathA.filter(isKeyedSegment)\n const keysB = pathB.filter(isKeyedSegment)\n\n const {context} = snapshot\n let currentChildren: Array<Node> = context.value\n let currentParent: RegisteredContainer | undefined\n let isRootLevel = true\n\n const minDepth = Math.min(keysA.length, keysB.length)\n\n for (let depth = 0; depth < minDepth; depth++) {\n const keyA = keysA[depth]!\n const keyB = keysB[depth]!\n\n if (keyA._key === keyB._key) {\n // Same node at this depth: descend into its children for the next\n // iteration. The root level can short-circuit via blockIndexMap;\n // deeper levels scan the current sibling array.\n let matchedNode: Node | undefined\n if (isRootLevel && snapshot.blockIndexMap.has(keyA._key)) {\n const index = snapshot.blockIndexMap.get(keyA._key)\n if (index !== undefined) {\n matchedNode = currentChildren[index]\n }\n } else {\n matchedNode = currentChildren.find((c) => c._key === keyA._key)\n }\n if (!matchedNode) {\n return 0\n }\n const next = getNodeChildren(context, matchedNode, currentParent)\n if (!next) {\n return 0\n }\n currentChildren = next.children\n currentParent = next.parent\n\n isRootLevel = false\n continue\n }\n\n if (isRootLevel) {\n const indexA = snapshot.blockIndexMap.get(keyA._key) ?? -1\n const indexB = snapshot.blockIndexMap.get(keyB._key) ?? -1\n if (indexA !== -1 && indexB !== -1) {\n if (indexA < indexB) {\n return -1\n }\n if (indexA > indexB) {\n return 1\n }\n return 0\n }\n }\n\n let indexA = -1\n let indexB = -1\n for (let i = 0; i < currentChildren.length; i++) {\n const sibling = currentChildren[i]!\n if (sibling._key === keyA._key) {\n indexA = i\n }\n if (sibling._key === keyB._key) {\n indexB = i\n }\n if (indexA !== -1 && indexB !== -1) {\n break\n }\n }\n\n if (indexA < indexB) {\n return -1\n }\n if (indexA > indexB) {\n return 1\n }\n\n return 0\n }\n\n // One path is a prefix of the other (ancestor relationship)\n // In DFS order, shorter path (ancestor) comes first\n if (keysA.length < keysB.length) {\n return -1\n }\n if (keysA.length > keysB.length) {\n return 1\n }\n\n return 0\n}\n\n/**\n * Range-bounded recursive DFS traversal.\n *\n * `from` and `to` are always in document order (from is earlier, to is\n * later), regardless of traversal direction.\n */\nfunction* getNodesInRange(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n from?: Path\n to?: Path\n match?: (node: Node, path: Path) => boolean\n reverse?: boolean\n },\n): Generator<{node: Node; path: Path}, void, undefined> {\n const {from, to, match, reverse = false} = options\n\n const children = getChildren(snapshot, path)\n const entries = reverse ? [...children].reverse() : children\n\n for (const entry of entries) {\n if (canStopTraversal(snapshot, entry.path, from, to, reverse)) {\n return\n }\n\n if (!couldContainInRangeNodes(snapshot, entry.path, from, to)) {\n continue\n }\n\n if (isInRange(snapshot, entry.path, from, to)) {\n if (!match || match(entry.node, entry.path)) {\n yield entry\n }\n }\n\n yield* getNodesInRange(snapshot, entry.path, options)\n }\n}\n\n/**\n * Check if a node is within the [from, to] range in document order.\n * Both bounds are inclusive. Ancestor nodes of from or to are also\n * considered in range since they contain the range boundary.\n */\nfunction isInRange(\n snapshot: TraversalSnapshot,\n nodePath: Path,\n from: Path | undefined,\n to: Path | undefined,\n): boolean {\n if (\n from !== undefined &&\n comparePathsInTree(snapshot, nodePath, from) === -1\n ) {\n if (!isAncestorPath(nodePath, from)) {\n return false\n }\n }\n\n if (to !== undefined && comparePathsInTree(snapshot, nodePath, to) === 1) {\n if (!isAncestorPath(nodePath, to)) {\n return false\n }\n }\n\n return true\n}\n\n/**\n * Check if a subtree rooted at `nodePath` could contain any nodes in the\n * [from, to] range.\n */\nfunction couldContainInRangeNodes(\n snapshot: TraversalSnapshot,\n nodePath: Path,\n from: Path | undefined,\n to: Path | undefined,\n): boolean {\n if (isInRange(snapshot, nodePath, from, to)) {\n return true\n }\n\n if (from !== undefined && isAncestorPath(nodePath, from)) {\n return true\n }\n\n if (to !== undefined && isAncestorPath(nodePath, to)) {\n return true\n }\n\n return false\n}\n\n/**\n * Check if all remaining nodes in iteration order will be outside the range.\n */\nfunction canStopTraversal(\n snapshot: TraversalSnapshot,\n nodePath: Path,\n from: Path | undefined,\n to: Path | undefined,\n reverse: boolean,\n): boolean {\n if (reverse) {\n if (from === undefined) {\n return false\n }\n\n return (\n comparePathsInTree(snapshot, nodePath, from) === -1 &&\n !isAncestorPath(nodePath, from)\n )\n }\n\n if (to === undefined) {\n return false\n }\n\n return comparePathsInTree(snapshot, nodePath, to) === 1\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/interfaces/path'\nimport {parentPath} from '../engine/path/parent-path'\nimport {isKeyedSegment} from '../utils/util.is-keyed-segment'\nimport {getChildren} from './get-children'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Get a sibling of the node at a given path.\n *\n * Without `match`, returns the immediate next or previous sibling.\n * With `match`, returns the first sibling in `direction` that satisfies\n * the predicate.\n *\n * When `match` is a type predicate, the returned `node` narrows to that type.\n *\n * @beta\n */\nexport function getSibling<TMatch extends Node>(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n direction: 'next' | 'previous'\n match: (node: Node, path: Path) => node is TMatch\n },\n): {node: TMatch; path: Path} | undefined\n/**\n * @beta\n */\nexport function getSibling(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n direction: 'next' | 'previous'\n match?: (node: Node, path: Path) => boolean\n },\n): {node: Node; path: Path} | undefined\nexport function getSibling(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n direction: 'next' | 'previous'\n match?: (node: Node, path: Path) => boolean\n },\n): {node: Node; path: Path} | undefined {\n const {direction, match} = options\n\n if (path.length === 0) {\n return undefined\n }\n\n const lastSegment = path.at(-1)\n\n if (!isKeyedSegment(lastSegment)) {\n return undefined\n }\n\n const parent = parentPath(path)\n const children = getChildren(snapshot, parent)\n\n const currentIndex = children.findIndex(\n (child) => child.node._key === lastSegment._key,\n )\n\n if (currentIndex === -1) {\n return undefined\n }\n\n if (!match) {\n const siblingIndex =\n direction === 'next' ? currentIndex + 1 : currentIndex - 1\n\n if (siblingIndex < 0 || siblingIndex >= children.length) {\n return undefined\n }\n\n return children[siblingIndex]\n }\n\n const candidates =\n direction === 'next'\n ? children.slice(currentIndex + 1)\n : children.slice(0, currentIndex).reverse()\n\n return candidates.find((child) => match(child.node, child.path))\n}\n","import type {EditorSchema} from '../../editor/editor-schema'\nimport {isTypedObject} from '../../utils/asserters'\n\nexport type SpanNode = {\n _type: string\n _key: string\n text?: string\n marks?: Array<string>\n}\n\n/**\n * Checks if a node is a span based on `_type` alone, without requiring `text`\n * to be present. This is needed to identify spans before normalization has had\n * a chance to add the missing `text` property.\n */\nexport function isSpanNode(\n context: {schema: EditorSchema},\n node: unknown,\n): node is SpanNode {\n return isTypedObject(node) && node._type === context.schema.span.name\n}\n","import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {isSpanNode} from '../engine/node/is-span-node'\nimport {isTextBlockNode} from '../engine/node/is-text-block-node'\nimport {getNode} from './get-node'\nimport {getParent} from './get-parent'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Determine if a node at the given path is a block.\n *\n * A node is a block if its parent is not a text block. Top-level nodes\n * (direct children of the editor) are always blocks. Children of text blocks\n * (spans and inline objects) are not blocks. Children of containers are\n * blocks within that container.\n *\n * @beta\n */\nexport function isBlock(snapshot: TraversalSnapshot, path: Path): boolean {\n const parent = getParent(snapshot, path)\n\n if (!parent) {\n return true\n }\n\n return !isTextBlockNode({schema: snapshot.context.schema}, parent.node)\n}\n\n/**\n * Get the node at the given path if it is a block.\n *\n * Returns the node narrowed to PortableTextBlock, or undefined if the node\n * doesn't exist or is not a block.\n *\n * @beta\n */\nexport function getBlock(\n snapshot: TraversalSnapshot,\n path: Path,\n): {node: PortableTextBlock; path: Path} | undefined {\n const entry = getNode(snapshot, path)\n\n if (!entry) {\n return undefined\n }\n\n if (!isBlock(snapshot, path)) {\n return undefined\n }\n\n if (isSpanNode({schema: snapshot.context.schema}, entry.node)) {\n return undefined\n }\n\n return {node: entry.node, path: entry.path}\n}\n","import type {Path} from '../engine/interfaces/path'\nimport {isBlock} from './is-block'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Determine if a node at the given path is inline.\n *\n * A node is inline if its parent is a text block. This is the inverse of\n * `isBlock`. Top-level nodes are never inline.\n *\n * @beta\n */\nexport function isInline(snapshot: TraversalSnapshot, path: Path): boolean {\n return !isBlock(snapshot, path)\n}\n","import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getAncestors} from './get-ancestors'\nimport {getBlock} from './is-block'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Walk up from a path to find the nearest enclosing block.\n *\n * Returns the node at the path if it is a block, otherwise the first ancestor\n * that is a block. Works at any depth — inside a container this returns the\n * container-internal block, not the outer container.\n *\n * With `match`, returns the first enclosing block that also satisfies the\n * predicate. When `match` is a type predicate, the returned `node` narrows\n * to that type.\n *\n * `mode: 'lowest'` (default) returns the innermost enclosing block; the node\n * at the path itself counts. `mode: 'highest'` returns the outermost\n * ancestor that matches, falling back to the node at the path only if no\n * ancestor does.\n *\n * @beta\n */\nexport function getEnclosingBlock<TMatch extends PortableTextBlock>(\n snapshot: TraversalSnapshot,\n path: Path,\n options: {\n match: (node: PortableTextBlock, path: Path) => node is TMatch\n mode?: 'lowest' | 'highest'\n },\n): {node: TMatch; path: Path} | undefined\n/**\n * @beta\n */\nexport function getEnclosingBlock(\n snapshot: TraversalSnapshot,\n path: Path,\n options?: {\n match?: (node: PortableTextBlock, path: Path) => boolean\n mode?: 'lowest' | 'highest'\n },\n): {node: PortableTextBlock; path: Path} | undefined\nexport function getEnclosingBlock(\n snapshot: TraversalSnapshot,\n path: Path,\n options?: {\n match?: (node: PortableTextBlock, path: Path) => boolean\n mode?: 'lowest' | 'highest'\n },\n): {node: PortableTextBlock; path: Path} | undefined {\n const match = options?.match\n const mode = options?.mode ?? 'lowest'\n\n if (mode === 'highest') {\n const ancestors = getAncestors(snapshot, path)\n\n for (const ancestor of [...ancestors].reverse()) {\n if (!match || match(ancestor.node, ancestor.path)) {\n return ancestor\n }\n }\n\n const direct = getBlock(snapshot, path)\n\n if (direct && (!match || match(direct.node, direct.path))) {\n return direct\n }\n\n return undefined\n }\n\n const direct = getBlock(snapshot, path)\n\n if (direct && (!match || match(direct.node, direct.path))) {\n return direct\n }\n\n for (const ancestor of getAncestors(snapshot, path)) {\n if (!match || match(ancestor.node, ancestor.path)) {\n return ancestor\n }\n }\n\n return undefined\n}\n","import type {Path} from '../engine/interfaces/path'\nimport {getAncestors} from '../traversal/get-ancestors'\nimport {isObject} from '../traversal/is-object'\nimport type {TraversalSnapshot} from '../traversal/traversal-snapshot'\nimport type {RegisteredContainer} from './container-types'\nimport {resolveContainerAt} from './resolve-container-at'\n\n/**\n * Descent primitive: return the immediate parent\n * {@link RegisteredContainer} of the node at `path` (and that parent's\n * path), or `undefined` when the target's immediate parent is the\n * editor root, when no object-node ancestor is a registered container,\n * or when descent hits an ancestor whose `_type` is not registered.\n *\n * Walks ancestors and resolves each object-node ancestor positionally\n * via {@link resolveContainerAt}. Text-block and span ancestors are\n * skipped - \"container\" here means the enclosing object container,\n * not the text-block holding spans.\n */\nexport function descendToParent(\n snapshot: TraversalSnapshot,\n path: Path,\n): {parent: RegisteredContainer; parentPath: Path} | undefined {\n const ancestors = getAncestors(snapshot, path)\n for (const ancestor of ancestors) {\n if (!isObject(snapshot, ancestor.node)) {\n continue\n }\n const resolved = resolveContainerAt(\n snapshot.context.containers,\n snapshot.context.value,\n ancestor.path,\n )\n if (!resolved || !('field' in resolved)) {\n return undefined\n }\n return {parent: resolved, parentPath: ancestor.path}\n }\n return undefined\n}\n","import type {OfDefinition} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport type {TraversalSnapshot} from '../traversal/traversal-snapshot'\nimport {descendToParent} from './descend-to-parent'\n\n/**\n * Return the immediate registered-container ancestor of `path` along\n * with its `of` array (the schema definitions accepted at this position).\n *\n * Position-aware: nested-only registrations (e.g. `cell` registered\n * only inside `table.row.of`) are recognized via the same descent\n * primitive used by all parent-aware traversal.\n *\n * Returns `undefined` when `path` has no registered-container ancestor\n * (i.e. is at the document root) or when descent hits a leaf-resolved\n * ancestor.\n */\nexport function getEnclosingContainer(\n snapshot: TraversalSnapshot,\n path: Path,\n):\n | {\n of: ReadonlyArray<OfDefinition>\n path: Path\n }\n | undefined {\n const descent = descendToParent(snapshot, path)\n if (!descent) {\n return undefined\n }\n return {\n of: descent.parent.field.of,\n path: descent.parentPath,\n }\n}\n","import {getSubSchema, type Schema} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getEnclosingContainer} from '../schema/get-enclosing-container'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Return the `Schema` view that applies at a given path.\n *\n * For paths at the root of the document, or for paths where no ancestor is\n * a registered container, returns the top-level schema. For paths inside a\n * container, walks ancestors to find the nearest container and returns the\n * sub-schema derived from its `of` declaration.\n *\n * @beta\n */\nexport function getPathSubSchema(\n snapshot: TraversalSnapshot,\n path: Path,\n): Schema {\n const enclosing = getEnclosingContainer(snapshot, path)\n\n if (!enclosing) {\n return snapshot.context.schema\n }\n\n return getSubSchema(snapshot.context.schema, enclosing.of)\n}\n"],"names":["getAncestors","snapshot","path","keyedIndices","i","length","isKeyedSegment","push","context","blockIndexMap","currentChildren","value","isRootLevel","currentParent","ancestorsByDepth","resolvedPath","targetKeyedIndex","segmentIndex","segment","node","size","index","get","_key","undefined","find","child","at","next","getNodeChildren","slice","children","parent","reverse","hasNode","getNode","resolveContainerAt","containers","resolved","resolveNodeEntry","fieldValue","field","name","Array","isArray","of","entry","type","_type","isEditableContainer","_node","isObject","isTypedObject","schema","block","span","isTextBlockNode","isAncestorPath","another","otherSegment","getNodes","options","from","to","match","getNodesSimple","getNodesInRange","getChildren","entries","comparePathsInTree","pathA","pathB","keysA","filter","keysB","minDepth","Math","min","depth","keyA","keyB","matchedNode","has","c","indexA","indexB","sibling","canStopTraversal","couldContainInRangeNodes","isInRange","nodePath","getSibling","direction","lastSegment","parentPath","currentIndex","findIndex","siblingIndex","isSpanNode","isBlock","getParent","getBlock","isInline","getEnclosingBlock","mode","ancestors","ancestor","direct","descendToParent","getEnclosingContainer","descent","getPathSubSchema","enclosing","getSubSchema"],"mappings":"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"}
|