@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.
- 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.d.ts +2 -2
- package/lib/index.js +292 -188
- 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
|
@@ -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/
|
|
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 {
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
119
|
+
getSpan,
|
|
125
120
|
getText,
|
|
126
|
-
|
|
121
|
+
getTextBlock,
|
|
127
122
|
getUnionSchema,
|
|
128
|
-
|
|
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 (
|
|
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
|