@portabletext/editor 7.0.6 → 7.1.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.
@@ -1 +1 @@
1
- {"version":3,"file":"resolve-containers.d.ts","names":[],"sources":["../../src/types/paths.ts","../../src/engine/interfaces/path.ts","../../src/renderers/renderer.types.ts","../../src/schema/container-types.ts","../../src/editor/editor-schema.ts","../../src/engine/interfaces/node.ts","../../src/node-traversal/traversal-snapshot.ts","../../src/schema/resolve-container-at.ts"],"sourcesContent":[],"mappings":"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"}
1
+ {"version":3,"file":"resolve-containers.d.ts","names":[],"sources":["../../src/types/paths.ts","../../src/engine/interfaces/path.ts","../../src/renderers/renderer.types.ts","../../src/schema/container-types.ts","../../src/editor/editor-schema.ts","../../src/engine/interfaces/node.ts","../../src/traversal/traversal-snapshot.ts","../../src/schema/resolve-container-at.ts"],"sourcesContent":[],"mappings":"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"}
@@ -1,6 +1,24 @@
1
- import { getChildren, getNode, isKeyedSegment, getNodeChildren } from "./get-node.js";
1
+ import { getAncestors, isObject, isEditableContainer, getNodes } from "./get-path-sub-schema.js";
2
+ import { getChildren, getNode } from "./get-parent.js";
2
3
  import { isSpan, isTextBlock, getSubSchema } from "@portabletext/schema";
3
- import { getNodes } from "./get-path-sub-schema.js";
4
+ function getAncestor(snapshot, path, options) {
5
+ const {
6
+ match,
7
+ mode = "lowest"
8
+ } = options, ancestors = getAncestors(snapshot, path);
9
+ if (mode === "highest") {
10
+ for (const ancestor of [...ancestors].reverse())
11
+ if (match(ancestor.node, ancestor.path))
12
+ return ancestor;
13
+ return;
14
+ }
15
+ for (const ancestor of ancestors)
16
+ if (match(ancestor.node, ancestor.path))
17
+ return ancestor;
18
+ }
19
+ function isLeafObject(snapshot, node, path) {
20
+ return isObject(snapshot, node) && !isEditableContainer(snapshot, node, path);
21
+ }
4
22
  function getLeaf(snapshot, path, options) {
5
23
  const {
6
24
  edge
@@ -45,7 +63,7 @@ function getText(snapshot, path) {
45
63
  }, descendant.node) && (text += descendant.node.text);
46
64
  return text;
47
65
  }
48
- function getSpanNode(snapshot, path) {
66
+ function getSpan(snapshot, path) {
49
67
  const entry = getNode(snapshot, path);
50
68
  if (entry && isSpan({
51
69
  schema: snapshot.context.schema
@@ -55,7 +73,7 @@ function getSpanNode(snapshot, path) {
55
73
  path: entry.path
56
74
  };
57
75
  }
58
- function getTextBlockNode(snapshot, path) {
76
+ function getTextBlock(snapshot, path) {
59
77
  const entry = getNode(snapshot, path);
60
78
  if (entry && isTextBlock({
61
79
  schema: snapshot.context.schema
@@ -91,40 +109,17 @@ function mergeByName(source, target) {
91
109
  target.some((existing) => existing.name === entry.name) || target.push(entry);
92
110
  return target;
93
111
  }
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
112
  function getFirstChild(snapshot, path) {
119
113
  return getChildren(snapshot, path).at(0);
120
114
  }
121
115
  export {
116
+ getAncestor,
122
117
  getFirstChild,
123
118
  getLeaf,
124
- getSpanNode,
119
+ getSpan,
125
120
  getText,
126
- getTextBlockNode,
121
+ getTextBlock,
127
122
  getUnionSchema,
128
- isLeaf
123
+ isLeafObject
129
124
  };
130
125
  //# sourceMappingURL=get-first-child.js.map
@@ -1 +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 '../engine/interfaces/node'\nimport type {Path} from '../engine/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 '../engine/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 '../engine/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 '../engine/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 '../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 * 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 '../engine/interfaces/node'\nimport type {Path} from '../engine/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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"}
1
+ {"version":3,"file":"get-first-child.js","sources":["../../src/traversal/get-ancestor.ts","../../src/traversal/is-leaf-object.ts","../../src/traversal/get-leaf.ts","../../src/traversal/get-text.ts","../../src/traversal/get-span.ts","../../src/traversal/get-text-block.ts","../../src/traversal/get-union-schema.ts","../../src/traversal/get-first-child.ts"],"sourcesContent":["import type {PortableTextBlock} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {getAncestors} from './get-ancestors'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Find an 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 * `mode: 'lowest'` (default) returns the nearest matching ancestor.\n * `mode: 'highest'` returns the outermost matching ancestor.\n *\n * When `match` is a type predicate, the returned `node` narrows to that type.\n *\n * @beta\n */\nexport function getAncestor<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 getAncestor(\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 getAncestor(\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, mode = 'lowest'} = options\n const ancestors = getAncestors(snapshot, path)\n\n if (mode === 'highest') {\n for (const ancestor of [...ancestors].reverse()) {\n if (match(ancestor.node, ancestor.path)) {\n return ancestor\n }\n }\n return undefined\n }\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","import type {PortableTextObject} from '@portabletext/schema'\nimport type {Path} from '../engine/interfaces/path'\nimport {isEditableContainer} from '../schema/is-editable-container'\nimport {isObject} from './is-object'\nimport type {TraversalSnapshot} from './traversal-snapshot'\n\n/**\n * Check if a node is a leaf object: an object node that has no editable\n * children (not a container).\n * Returns true for block objects and inline objects that don't have\n * registered editable content (containers).\n *\n * @beta\n */\nexport function isLeafObject(\n snapshot: TraversalSnapshot,\n node: unknown,\n path: Path,\n): node is PortableTextObject {\n return isObject(snapshot, node) && !isEditableContainer(snapshot, node, path)\n}\n","import type {Node} from '../engine/interfaces/node'\nimport type {Path} from '../engine/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 '../engine/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 '../engine/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 getSpan(\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 '../engine/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 getTextBlock(\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 '../engine/interfaces/node'\nimport type {Path} from '../engine/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":["getAncestor","snapshot","path","options","match","mode","ancestors","getAncestors","ancestor","reverse","node","isLeafObject","isObject","isEditableContainer","getLeaf","edge","currentPath","length","children","getChildren","firstOrLast","at","entry","getNode","undefined","getText","isSpan","schema","context","text","descendant","getNodes","getSpan","getTextBlock","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","getFirstChild"],"mappings":"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"}
@@ -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 (isObjectNode(context, node)) {
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-node.js.map
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 { getNode, isTypedObject, isKeyedSegment, getChildren, getNodeChildren, getAncestors, isObjectNode } from "./get-node.js";
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 parentPath(path) {
157
- if (path.length === 0)
158
- throw new Error(`Cannot get the parent path of the root path [${path}].`);
159
- let lastNodeIndex = -1;
160
- for (let i = path.length - 1; i >= 0; i--)
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 === -1)
178
- return;
179
- const siblingIndex = direction === "next" ? currentIndex + 1 : currentIndex - 1;
180
- if (!(siblingIndex < 0 || siblingIndex >= children.length))
181
- return children[siblingIndex];
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 (isBlock(snapshot, ancestor.path)) {
218
- const block = getBlock(snapshot, ancestor.path);
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 (!isObjectNode({
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