@lobehub/editor 3.3.2 → 3.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/es/editor-kernel/index.d.ts +1 -0
- package/es/editor-kernel/index.js +3 -1
- package/es/editor-kernel/kernel.js +1 -0
- package/es/editor-kernel/lexical/Lexical.dev.js +3052 -0
- package/es/editor-kernel/lexical/Lexical.dev.mjs +15365 -0
- package/es/editor-kernel/lexical/Lexical.js +7634 -0
- package/es/editor-kernel/lexical/Lexical.mjs +7258 -0
- package/es/editor-kernel/lexical/LexicalCommands.d.ts +175 -0
- package/es/editor-kernel/lexical/LexicalConstants.d.ts +54 -0
- package/es/editor-kernel/lexical/LexicalEditor.d.ts +672 -0
- package/es/editor-kernel/lexical/LexicalEditorState.d.ts +39 -0
- package/es/editor-kernel/lexical/LexicalEvents.d.ts +22 -0
- package/es/editor-kernel/lexical/LexicalGC.d.ts +23 -0
- package/es/editor-kernel/lexical/LexicalMutations.d.ts +12 -0
- package/es/editor-kernel/lexical/LexicalNode.d.ts +689 -0
- package/es/editor-kernel/lexical/LexicalNodeState.d.ts +569 -0
- package/es/editor-kernel/lexical/LexicalNormalization.d.ts +11 -0
- package/es/editor-kernel/lexical/LexicalReconciler.d.ts +28 -0
- package/es/editor-kernel/lexical/LexicalSelection.d.ts +368 -0
- package/es/editor-kernel/lexical/LexicalUpdateTags.d.ts +67 -0
- package/es/editor-kernel/lexical/LexicalUpdates.d.ts +72 -0
- package/es/editor-kernel/lexical/LexicalUtils.d.ts +492 -0
- package/es/editor-kernel/lexical/caret/LexicalCaret.d.ts +635 -0
- package/es/editor-kernel/lexical/caret/LexicalCaretUtils.d.ts +224 -0
- package/es/editor-kernel/lexical/extension-core/defineExtension.d.ts +126 -0
- package/es/editor-kernel/lexical/extension-core/index.d.ts +38 -0
- package/es/editor-kernel/lexical/extension-core/internal.d.ts +32 -0
- package/es/editor-kernel/lexical/extension-core/safeCast.d.ts +15 -0
- package/es/editor-kernel/lexical/extension-core/shallowMergeConfig.d.ts +20 -0
- package/es/editor-kernel/lexical/extension-core/types.d.ts +371 -0
- package/es/editor-kernel/lexical/index.d.ts +368 -0
- package/es/editor-kernel/lexical/nodes/ArtificialNode.d.ts +16 -0
- package/es/editor-kernel/lexical/nodes/LexicalDecoratorNode.d.ts +32 -0
- package/es/editor-kernel/lexical/nodes/LexicalElementNode.d.ts +235 -0
- package/es/editor-kernel/lexical/nodes/LexicalLineBreakNode.d.ts +30 -0
- package/es/editor-kernel/lexical/nodes/LexicalParagraphNode.d.ts +39 -0
- package/es/editor-kernel/lexical/nodes/LexicalRootNode.d.ts +35 -0
- package/es/editor-kernel/lexical/nodes/LexicalTabNode.d.ts +30 -0
- package/es/editor-kernel/lexical/nodes/LexicalTextNode.d.ts +311 -0
- package/es/plugins/common/data-source/json-data-source.js +29 -3
- package/es/plugins/common/react/ReactPlainText.js +9 -0
- package/es/plugins/common/utils/index.d.ts +2 -1
- package/es/plugins/common/utils/index.js +33 -0
- package/es/plugins/litexml/command/index.js +9 -1
- package/es/plugins/litexml/data-source/litexml-data-source.js +12 -2
- package/es/plugins/litexml/plugin/index.js +41 -3
- package/es/plugins/litexml/utils/index.d.ts +2 -1
- package/es/plugins/litexml/utils/index.js +7 -1
- package/es/plugins/markdown/data-source/markdown-data-source.js +6 -25
- package/es/plugins/markdown/data-source/markdown-writer-context.d.ts +5 -1
- package/es/plugins/markdown/data-source/markdown-writer-context.js +27 -2
- package/es/plugins/markdown/service/shortcut.d.ts +7 -0
- package/es/types/kernel.d.ts +4 -0
- package/package.json +8 -2
- package/scripts/patch-lexical.js +39 -0
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
import type { LexicalNode } from '../LexicalNode';
|
|
9
|
+
import { ElementNode } from '../nodes/LexicalElementNode';
|
|
10
|
+
import { TextNode } from '../nodes/LexicalTextNode';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* The direction of a caret, 'next' points towards the end of the document
|
|
14
|
+
* and 'previous' points towards the beginning
|
|
15
|
+
*/
|
|
16
|
+
export type CaretDirection = 'next' | 'previous';
|
|
17
|
+
/**
|
|
18
|
+
* A type utility to flip next and previous
|
|
19
|
+
*/
|
|
20
|
+
export type FlipDirection<D extends CaretDirection> = (typeof FLIP_DIRECTION)[D];
|
|
21
|
+
/**
|
|
22
|
+
* A sibling caret type points from a LexicalNode origin to its next or previous sibling,
|
|
23
|
+
* and a child caret type points from an ElementNode origin to its first or last child.
|
|
24
|
+
*/
|
|
25
|
+
export type CaretType = 'sibling' | 'child';
|
|
26
|
+
/**
|
|
27
|
+
* The RootMode is specified in all caret traversals where the traversal can go up
|
|
28
|
+
* towards the root. 'root' means that it will stop at the document root,
|
|
29
|
+
* and 'shadowRoot' will stop at the document root or any shadow root
|
|
30
|
+
* (per {@link $isRootOrShadowRoot}).
|
|
31
|
+
*/
|
|
32
|
+
export type RootMode = 'root' | 'shadowRoot';
|
|
33
|
+
declare const FLIP_DIRECTION: {
|
|
34
|
+
readonly next: 'previous';
|
|
35
|
+
readonly previous: 'next';
|
|
36
|
+
};
|
|
37
|
+
/** @noInheritDoc */
|
|
38
|
+
export interface BaseCaret<T extends LexicalNode, D extends CaretDirection, Type> extends Iterable<
|
|
39
|
+
SiblingCaret<LexicalNode, D>
|
|
40
|
+
> {
|
|
41
|
+
/** The origin node of this caret, typically this is what you will use in traversals */
|
|
42
|
+
readonly origin: T;
|
|
43
|
+
/** sibling for a SiblingCaret (pointing at the next or previous sibling) or child for a ChildCaret (pointing at the first or last child) */
|
|
44
|
+
readonly type: Type;
|
|
45
|
+
/** next if pointing at the next sibling or first child, previous if pointing at the previous sibling or last child */
|
|
46
|
+
readonly direction: D;
|
|
47
|
+
/** Get the ElementNode that is the logical parent (`origin` for `ChildCaret`, `origin.getParent()` for `SiblingCaret`) */
|
|
48
|
+
getParentAtCaret: () => null | ElementNode;
|
|
49
|
+
/** Get the node connected to the origin in the caret's direction, or null if there is no node */
|
|
50
|
+
getNodeAtCaret: () => null | LexicalNode;
|
|
51
|
+
/** Get a new SiblingCaret from getNodeAtCaret() in the same direction. */
|
|
52
|
+
getAdjacentCaret: () => null | SiblingCaret<LexicalNode, D>;
|
|
53
|
+
/**
|
|
54
|
+
* Get a new SiblingCaret with this same node
|
|
55
|
+
*/
|
|
56
|
+
getSiblingCaret: () => SiblingCaret<T, D>;
|
|
57
|
+
/** Remove the getNodeAtCaret() node that this caret is pointing towards, if it exists */
|
|
58
|
+
remove: () => this;
|
|
59
|
+
/**
|
|
60
|
+
* Insert a node connected to origin in this direction (before the node that this caret is pointing towards, if any existed).
|
|
61
|
+
* For a `SiblingCaret` this is `origin.insertAfter(node)` for next, or `origin.insertBefore(node)` for previous.
|
|
62
|
+
* For a `ChildCaret` this is `origin.splice(0, 0, [node])` for next or `origin.append(node)` for previous.
|
|
63
|
+
*/
|
|
64
|
+
insert: (node: LexicalNode) => this;
|
|
65
|
+
/** If getNodeAtCaret() is not null then replace it with node, otherwise insert node */
|
|
66
|
+
replaceOrInsert: (node: LexicalNode, includeChildren?: boolean) => this;
|
|
67
|
+
/**
|
|
68
|
+
* Splice an iterable (typically an Array) of nodes into this location.
|
|
69
|
+
*
|
|
70
|
+
* @param deleteCount The number of existing nodes to replace or delete
|
|
71
|
+
* @param nodes An iterable of nodes that will be inserted in this location, using replace instead of insert for the first deleteCount nodes
|
|
72
|
+
* @param nodesDirection The direction of the nodes iterable, defaults to 'next'
|
|
73
|
+
*/
|
|
74
|
+
splice: (
|
|
75
|
+
deleteCount: number,
|
|
76
|
+
nodes: Iterable<LexicalNode>,
|
|
77
|
+
nodesDirection?: CaretDirection,
|
|
78
|
+
) => this;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* A RangeSelection expressed as a pair of Carets
|
|
82
|
+
*/
|
|
83
|
+
export interface CaretRange<D extends CaretDirection = CaretDirection> extends Iterable<
|
|
84
|
+
NodeCaret<D>
|
|
85
|
+
> {
|
|
86
|
+
readonly type: 'node-caret-range';
|
|
87
|
+
readonly direction: D;
|
|
88
|
+
anchor: PointCaret<D>;
|
|
89
|
+
focus: PointCaret<D>;
|
|
90
|
+
/** Return true if anchor and focus are the same caret */
|
|
91
|
+
isCollapsed: () => boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Iterate the carets between anchor and focus in a pre-order fashion, note
|
|
94
|
+
* that this does not include any text slices represented by the anchor and/or
|
|
95
|
+
* focus. Those are accessed separately from getTextSlices.
|
|
96
|
+
*
|
|
97
|
+
* An ElementNode origin will be yielded as a ChildCaret on enter,
|
|
98
|
+
* and a SiblingCaret on leave.
|
|
99
|
+
*/
|
|
100
|
+
iterNodeCarets: (rootMode?: RootMode) => IterableIterator<NodeCaret<D>>;
|
|
101
|
+
/**
|
|
102
|
+
* There are between zero and two non-null TextSliceCarets for a CaretRange.
|
|
103
|
+
* Note that when anchor and focus share an origin node the second element
|
|
104
|
+
* will be null because the slice is entirely represented by the first element.
|
|
105
|
+
*
|
|
106
|
+
* `[slice, slice]`: anchor and focus are TextPointCaret with distinct origin nodes
|
|
107
|
+
* `[slice, null]`: anchor is a TextPointCaret
|
|
108
|
+
* `[null, slice]`: focus is a TextPointCaret
|
|
109
|
+
* `[null, null]`: Neither anchor nor focus are TextPointCarets
|
|
110
|
+
*/
|
|
111
|
+
getTextSlices: () => TextPointCaretSliceTuple<D>;
|
|
112
|
+
}
|
|
113
|
+
export interface StepwiseIteratorConfig<State, Stop, Value> {
|
|
114
|
+
readonly initial: State | Stop;
|
|
115
|
+
readonly hasNext: (value: State | Stop) => value is State;
|
|
116
|
+
readonly step: (value: State) => State | Stop;
|
|
117
|
+
readonly map: (value: State) => Value;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* A NodeCaret is the combination of an origin node and a direction
|
|
121
|
+
* that points towards where a connected node will be fetched, inserted,
|
|
122
|
+
* or replaced. A SiblingCaret points from a node to its next or previous
|
|
123
|
+
* sibling, and a ChildCaret points to its first or last child
|
|
124
|
+
* (using next or previous as direction, for symmetry with SiblingCaret).
|
|
125
|
+
*
|
|
126
|
+
* The differences between NodeCaret and PointType are:
|
|
127
|
+
* - NodeCaret can only be used to refer to an entire node (PointCaret is used when a full analog is needed). A PointType of text type can be used to refer to a specific location inside of a TextNode.
|
|
128
|
+
* - NodeCaret stores an origin node, type (sibling or child), and direction (next or previous). A PointType stores a type (text or element), the key of a node, and a text or child offset within that node.
|
|
129
|
+
* - NodeCaret is directional and always refers to a very specific node, eliminating all ambiguity. PointType can refer to the location before or at a node depending on context.
|
|
130
|
+
* - NodeCaret is more robust to nearby mutations, as it relies only on a node's direct connections. An element Any change to the count of previous siblings in an element PointType will invalidate it.
|
|
131
|
+
* - NodeCaret is designed to work more directly with the internal representation of the document tree, making it suitable for use in traversals without performing any redundant work.
|
|
132
|
+
*
|
|
133
|
+
* The caret does *not* update in response to any mutations, you should
|
|
134
|
+
* not persist it across editor updates, and using a caret after its origin
|
|
135
|
+
* node has been removed or replaced may result in runtime errors.
|
|
136
|
+
*/
|
|
137
|
+
export type NodeCaret<D extends CaretDirection = CaretDirection> =
|
|
138
|
+
| SiblingCaret<LexicalNode, D>
|
|
139
|
+
| ChildCaret<ElementNode, D>;
|
|
140
|
+
/**
|
|
141
|
+
* A PointCaret is a NodeCaret that also includes a
|
|
142
|
+
* TextPointCaret type which refers to a specific offset of a TextNode.
|
|
143
|
+
* This type is separate because it is not relevant to general node traversal
|
|
144
|
+
* so it doesn't make sense to have it show up except when defining
|
|
145
|
+
* a CaretRange and in those cases there will be at most two of them only
|
|
146
|
+
* at the boundaries.
|
|
147
|
+
*
|
|
148
|
+
* The addition of TextPointCaret allows this type to represent any location
|
|
149
|
+
* that is representable by PointType, as the TextPointCaret refers to a
|
|
150
|
+
* specific offset within a TextNode.
|
|
151
|
+
*/
|
|
152
|
+
export type PointCaret<D extends CaretDirection = CaretDirection> =
|
|
153
|
+
| TextPointCaret<TextNode, D>
|
|
154
|
+
| SiblingCaret<LexicalNode, D>
|
|
155
|
+
| ChildCaret<ElementNode, D>;
|
|
156
|
+
/**
|
|
157
|
+
* A SiblingCaret points from an origin LexicalNode towards its next or previous sibling.
|
|
158
|
+
*/
|
|
159
|
+
export interface SiblingCaret<
|
|
160
|
+
T extends LexicalNode = LexicalNode,
|
|
161
|
+
D extends CaretDirection = CaretDirection,
|
|
162
|
+
> extends BaseCaret<T, D, 'sibling'> {
|
|
163
|
+
/** Get a new caret with the latest origin pointer */
|
|
164
|
+
getLatest: () => SiblingCaret<T, D>;
|
|
165
|
+
/**
|
|
166
|
+
* If the origin of this node is an ElementNode, return the ChildCaret of this origin in the same direction.
|
|
167
|
+
* If the origin is not an ElementNode, this will return null.
|
|
168
|
+
*/
|
|
169
|
+
getChildCaret: () => null | ChildCaret<T & ElementNode, D>;
|
|
170
|
+
/**
|
|
171
|
+
* Get the caret in the same direction from the parent of this origin.
|
|
172
|
+
*
|
|
173
|
+
* @param mode 'root' to return null at the root, 'shadowRoot' to return null at the root or any shadow root
|
|
174
|
+
* @returns A SiblingCaret with the parent of this origin, or null if the parent is a root according to mode.
|
|
175
|
+
*/
|
|
176
|
+
getParentCaret: (mode?: RootMode) => null | SiblingCaret<ElementNode, D>;
|
|
177
|
+
/**
|
|
178
|
+
* Return true if other is a SiblingCaret or TextPointCaret with the same
|
|
179
|
+
* origin (by node key comparison) and direction.
|
|
180
|
+
*/
|
|
181
|
+
isSameNodeCaret: (
|
|
182
|
+
other: null | undefined | PointCaret,
|
|
183
|
+
) => other is SiblingCaret<T, D> | T extends TextNode ? TextPointCaret<T & TextNode, D> : never;
|
|
184
|
+
/**
|
|
185
|
+
* Return true if other is a SiblingCaret with the same
|
|
186
|
+
* origin (by node key comparison) and direction.
|
|
187
|
+
*/
|
|
188
|
+
isSamePointCaret: (other: null | undefined | PointCaret) => other is SiblingCaret<T, D>;
|
|
189
|
+
/**
|
|
190
|
+
* Get a new NodeCaret with the head and tail of its directional arrow flipped, such that flipping twice is the identity.
|
|
191
|
+
* For example, given a non-empty parent with a firstChild and lastChild, and a second emptyParent node with no children:
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* ```
|
|
195
|
+
* caret.getFlipped().getFlipped().is(caret) === true;
|
|
196
|
+
* $getChildCaret(parent, 'next').getFlipped().is($getSiblingCaret(firstChild, 'previous')) === true;
|
|
197
|
+
* $getSiblingCaret(lastChild, 'next').getFlipped().is($getChildCaret(parent, 'previous')) === true;
|
|
198
|
+
* $getSiblingCaret(firstChild, 'next).getFlipped().is($getSiblingCaret(lastChild, 'previous')) === true;
|
|
199
|
+
* $getChildCaret(emptyParent, 'next').getFlipped().is($getChildCaret(emptyParent, 'previous')) === true;
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
getFlipped: () => NodeCaret<FlipDirection<D>>;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* A ChildCaret points from an origin ElementNode towards its first or last child.
|
|
206
|
+
*/
|
|
207
|
+
export interface ChildCaret<
|
|
208
|
+
T extends ElementNode = ElementNode,
|
|
209
|
+
D extends CaretDirection = CaretDirection,
|
|
210
|
+
> extends BaseCaret<T, D, 'child'> {
|
|
211
|
+
/** Get a new caret with the latest origin pointer */
|
|
212
|
+
getLatest: () => ChildCaret<T, D>;
|
|
213
|
+
getParentCaret: (mode?: RootMode) => null | SiblingCaret<T, D>;
|
|
214
|
+
getParentAtCaret: () => T;
|
|
215
|
+
/** Return this, the ChildCaret is already a child caret of its origin */
|
|
216
|
+
getChildCaret: () => this;
|
|
217
|
+
/**
|
|
218
|
+
* Return true if other is a ChildCaret with the same
|
|
219
|
+
* origin (by node key comparison) and direction.
|
|
220
|
+
*/
|
|
221
|
+
isSameNodeCaret: (other: null | undefined | PointCaret) => other is ChildCaret<T, D>;
|
|
222
|
+
/**
|
|
223
|
+
* Return true if other is a ChildCaret with the same
|
|
224
|
+
* origin (by node key comparison) and direction.
|
|
225
|
+
*/
|
|
226
|
+
isSamePointCaret: (other: null | undefined | PointCaret) => other is ChildCaret<T, D>;
|
|
227
|
+
/**
|
|
228
|
+
* Get a new NodeCaret with the head and tail of its directional arrow flipped, such that flipping twice is the identity.
|
|
229
|
+
* For example, given a non-empty parent with a firstChild and lastChild, and a second emptyParent node with no children:
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
* ```
|
|
233
|
+
* caret.getFlipped().getFlipped().is(caret) === true;
|
|
234
|
+
* $getChildCaret(parent, 'next').getFlipped().is($getSiblingCaret(firstChild, 'previous')) === true;
|
|
235
|
+
* $getSiblingCaret(lastChild, 'next').getFlipped().is($getChildCaret(parent, 'previous')) === true;
|
|
236
|
+
* $getSiblingCaret(firstChild, 'next).getFlipped().is($getSiblingCaret(lastChild, 'previous')) === true;
|
|
237
|
+
* $getChildCaret(emptyParent, 'next').getFlipped().is($getChildCaret(emptyParent, 'previous')) === true;
|
|
238
|
+
* ```
|
|
239
|
+
*/
|
|
240
|
+
getFlipped: () => NodeCaret<FlipDirection<D>>;
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* A TextPointCaret is a special case of a SiblingCaret that also carries
|
|
244
|
+
* an offset used for representing partially selected TextNode at the edges
|
|
245
|
+
* of a CaretRange.
|
|
246
|
+
*
|
|
247
|
+
* The direction determines which part of the text is adjacent to the caret,
|
|
248
|
+
* if next it's all of the text after offset. If previous, it's all of the
|
|
249
|
+
* text before offset.
|
|
250
|
+
*
|
|
251
|
+
* While this can be used in place of any SiblingCaret of a TextNode,
|
|
252
|
+
* the offset into the text will be ignored except in contexts that
|
|
253
|
+
* specifically use the TextPointCaret or PointCaret types.
|
|
254
|
+
*/
|
|
255
|
+
export interface TextPointCaret<
|
|
256
|
+
T extends TextNode = TextNode,
|
|
257
|
+
D extends CaretDirection = CaretDirection,
|
|
258
|
+
> extends BaseCaret<T, D, 'text'> {
|
|
259
|
+
/** The offset into the string */
|
|
260
|
+
readonly offset: number;
|
|
261
|
+
/** Get a new caret with the latest origin pointer */
|
|
262
|
+
getLatest: () => TextPointCaret<T, D>;
|
|
263
|
+
/**
|
|
264
|
+
* A TextPointCaret can not have a ChildCaret.
|
|
265
|
+
*/
|
|
266
|
+
getChildCaret: () => null;
|
|
267
|
+
/**
|
|
268
|
+
* Get the caret in the same direction from the parent of this origin.
|
|
269
|
+
*
|
|
270
|
+
* @param mode 'root' to return null at the root, 'shadowRoot' to return null at the root or any shadow root
|
|
271
|
+
* @returns A SiblingCaret with the parent of this origin, or null if the parent is a root according to mode.
|
|
272
|
+
*/
|
|
273
|
+
getParentCaret: (mode?: RootMode) => null | SiblingCaret<ElementNode, D>;
|
|
274
|
+
/**
|
|
275
|
+
* Return true if other is a TextPointCaret or SiblingCaret with the same
|
|
276
|
+
* origin (by node key comparison) and direction.
|
|
277
|
+
*/
|
|
278
|
+
isSameNodeCaret: (
|
|
279
|
+
other: null | undefined | PointCaret,
|
|
280
|
+
) => other is TextPointCaret<T, D> | SiblingCaret<T, D>;
|
|
281
|
+
/**
|
|
282
|
+
* Return true if other is a ChildCaret with the same
|
|
283
|
+
* origin (by node key comparison) and direction.
|
|
284
|
+
*/
|
|
285
|
+
isSamePointCaret: (other: null | undefined | PointCaret) => other is TextPointCaret<T, D>;
|
|
286
|
+
/**
|
|
287
|
+
* Get a new TextPointCaret with the head and tail of its directional arrow flipped, such that flipping twice is the identity.
|
|
288
|
+
* For a TextPointCaret this merely flips the direction because the arrow is internal to the node.
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```
|
|
292
|
+
* caret.getFlipped().getFlipped().is(caret) === true;
|
|
293
|
+
* ```
|
|
294
|
+
*/
|
|
295
|
+
getFlipped: () => TextPointCaret<T, FlipDirection<D>>;
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* A TextPointCaretSlice is a wrapper for a TextPointCaret that carries a signed
|
|
299
|
+
* distance representing the direction and amount of text selected from the given
|
|
300
|
+
* caret. A negative distance means that text before offset is selected, a
|
|
301
|
+
* positive distance means that text after offset is selected. The offset+distance
|
|
302
|
+
* pair is not affected in any way by the direction of the caret.
|
|
303
|
+
*/
|
|
304
|
+
export interface TextPointCaretSlice<
|
|
305
|
+
T extends TextNode = TextNode,
|
|
306
|
+
D extends CaretDirection = CaretDirection,
|
|
307
|
+
> {
|
|
308
|
+
readonly type: 'slice';
|
|
309
|
+
readonly caret: TextPointCaret<T, D>;
|
|
310
|
+
readonly distance: number;
|
|
311
|
+
/**
|
|
312
|
+
* @returns absolute coordinates into the text (for use with `text.slice(...)`)
|
|
313
|
+
*/
|
|
314
|
+
getSliceIndices: () => [startIndex: number, endIndex: number];
|
|
315
|
+
/**
|
|
316
|
+
* @returns The text represented by the slice
|
|
317
|
+
*/
|
|
318
|
+
getTextContent: () => string;
|
|
319
|
+
/**
|
|
320
|
+
* @returns The size of the text represented by the slice
|
|
321
|
+
*/
|
|
322
|
+
getTextContentSize: () => number;
|
|
323
|
+
/**
|
|
324
|
+
* Remove the slice of text from the contained caret, returning a new
|
|
325
|
+
* TextPointCaret without the wrapper (since the size would be zero).
|
|
326
|
+
*
|
|
327
|
+
* Note that this is a lower-level utility that does not have any specific
|
|
328
|
+
* behavior for 'segmented' or 'token' modes and it will not remove
|
|
329
|
+
* an empty TextNode.
|
|
330
|
+
*
|
|
331
|
+
* @returns The inner TextPointCaret with the same offset and direction
|
|
332
|
+
* and the latest TextNode origin after mutation
|
|
333
|
+
*/
|
|
334
|
+
removeTextSlice(): TextPointCaret<T, D>;
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* A utility type to specify that a CaretRange may have zero,
|
|
338
|
+
* one, or two associated TextPointCaretSlice. If the anchor
|
|
339
|
+
* and focus are on the same node, the anchorSlice will contain
|
|
340
|
+
* the slice and focusSlie will be null.
|
|
341
|
+
*/
|
|
342
|
+
export type TextPointCaretSliceTuple<D extends CaretDirection> = readonly [
|
|
343
|
+
anchorSlice: null | TextPointCaretSlice<TextNode, D>,
|
|
344
|
+
focusSlice: null | TextPointCaretSlice<TextNode, D>,
|
|
345
|
+
];
|
|
346
|
+
/**
|
|
347
|
+
* Flip a direction ('next' -> 'previous'; 'previous' -> 'next').
|
|
348
|
+
*
|
|
349
|
+
* Note that TypeScript can't prove that FlipDirection is its own
|
|
350
|
+
* inverse (but if you have a concrete 'next' or 'previous' it will
|
|
351
|
+
* simplify accordingly).
|
|
352
|
+
*
|
|
353
|
+
* @param direction A direction
|
|
354
|
+
* @returns The opposite direction
|
|
355
|
+
*/
|
|
356
|
+
export declare function flipDirection<D extends CaretDirection>(direction: D): FlipDirection<D>;
|
|
357
|
+
/**
|
|
358
|
+
* Guard to check if the given caret is specifically a TextPointCaret
|
|
359
|
+
*
|
|
360
|
+
* @param caret Any caret
|
|
361
|
+
* @returns true if it is a TextPointCaret
|
|
362
|
+
*/
|
|
363
|
+
export declare function $isTextPointCaret<D extends CaretDirection>(
|
|
364
|
+
caret: null | undefined | PointCaret<D>,
|
|
365
|
+
): caret is TextPointCaret<TextNode, D>;
|
|
366
|
+
/**
|
|
367
|
+
* Guard to check if the given argument is any type of caret
|
|
368
|
+
*
|
|
369
|
+
* @param caret
|
|
370
|
+
* @returns true if caret is any type of caret
|
|
371
|
+
*/
|
|
372
|
+
export declare function $isNodeCaret<D extends CaretDirection>(
|
|
373
|
+
caret: null | undefined | PointCaret<D>,
|
|
374
|
+
): caret is PointCaret<D>;
|
|
375
|
+
/**
|
|
376
|
+
* Guard to check if the given argument is specifically a SiblingCaret (or TextPointCaret)
|
|
377
|
+
*
|
|
378
|
+
* @param caret
|
|
379
|
+
* @returns true if caret is a SiblingCaret
|
|
380
|
+
*/
|
|
381
|
+
export declare function $isSiblingCaret<D extends CaretDirection>(
|
|
382
|
+
caret: null | undefined | PointCaret<D>,
|
|
383
|
+
): caret is SiblingCaret<LexicalNode, D>;
|
|
384
|
+
/**
|
|
385
|
+
* Guard to check if the given argument is specifically a ChildCaret
|
|
386
|
+
|
|
387
|
+
* @param caret
|
|
388
|
+
* @returns true if caret is a ChildCaret
|
|
389
|
+
*/
|
|
390
|
+
export declare function $isChildCaret<D extends CaretDirection>(
|
|
391
|
+
caret: null | undefined | PointCaret<D>,
|
|
392
|
+
): caret is ChildCaret<ElementNode, D>;
|
|
393
|
+
/**
|
|
394
|
+
* Get a caret that points at the next or previous sibling of the given origin node.
|
|
395
|
+
*
|
|
396
|
+
* @param origin The origin node
|
|
397
|
+
* @param direction 'next' or 'previous'
|
|
398
|
+
* @returns null if origin is null, otherwise a SiblingCaret for this origin and direction
|
|
399
|
+
*/
|
|
400
|
+
export declare function $getSiblingCaret<T extends LexicalNode, D extends CaretDirection>(
|
|
401
|
+
origin: T,
|
|
402
|
+
direction: D,
|
|
403
|
+
): SiblingCaret<T, D>;
|
|
404
|
+
export declare function $getSiblingCaret<T extends LexicalNode, D extends CaretDirection>(
|
|
405
|
+
origin: null | T,
|
|
406
|
+
direction: D,
|
|
407
|
+
): null | SiblingCaret<T, D>;
|
|
408
|
+
/**
|
|
409
|
+
* Construct a TextPointCaret
|
|
410
|
+
*
|
|
411
|
+
* @param origin The TextNode
|
|
412
|
+
* @param direction The direction (next points to the end of the text, previous points to the beginning)
|
|
413
|
+
* @param offset The offset into the text in absolute positive string coordinates (0 is the start)
|
|
414
|
+
* @returns a TextPointCaret
|
|
415
|
+
*/
|
|
416
|
+
export declare function $getTextPointCaret<T extends TextNode, D extends CaretDirection>(
|
|
417
|
+
origin: T,
|
|
418
|
+
direction: D,
|
|
419
|
+
offset: number | CaretDirection,
|
|
420
|
+
): TextPointCaret<T, D>;
|
|
421
|
+
export declare function $getTextPointCaret<T extends TextNode, D extends CaretDirection>(
|
|
422
|
+
origin: null | T,
|
|
423
|
+
direction: D,
|
|
424
|
+
offset: number | CaretDirection,
|
|
425
|
+
): null | TextPointCaret<T, D>;
|
|
426
|
+
/**
|
|
427
|
+
* Get a normalized offset into a TextNode given a numeric offset or a
|
|
428
|
+
* direction for which end of the string to use. Throws in dev if the offset
|
|
429
|
+
* is not in the bounds of the text content size.
|
|
430
|
+
*
|
|
431
|
+
* @param origin a TextNode
|
|
432
|
+
* @param offset An absolute offset into the TextNode string, or a direction for which end to use as the offset
|
|
433
|
+
* @param mode If 'error' (the default) out of bounds offsets will be an error in dev. Otherwise it will clamp to a valid offset.
|
|
434
|
+
* @returns An absolute offset into the TextNode string
|
|
435
|
+
*/
|
|
436
|
+
export declare function $getTextNodeOffset(
|
|
437
|
+
origin: TextNode,
|
|
438
|
+
offset: number | CaretDirection,
|
|
439
|
+
mode?: 'error' | 'clamp',
|
|
440
|
+
): number;
|
|
441
|
+
/**
|
|
442
|
+
* Construct a TextPointCaretSlice given a TextPointCaret and a signed distance. The
|
|
443
|
+
* distance should be negative to slice text before the caret's offset, and positive
|
|
444
|
+
* to slice text after the offset. The direction of the caret itself is not
|
|
445
|
+
* relevant to the string coordinates when working with a TextPointCaretSlice
|
|
446
|
+
* but mutation operations will preserve the direction.
|
|
447
|
+
*
|
|
448
|
+
* @param caret
|
|
449
|
+
* @param distance
|
|
450
|
+
* @returns TextPointCaretSlice
|
|
451
|
+
*/
|
|
452
|
+
export declare function $getTextPointCaretSlice<T extends TextNode, D extends CaretDirection>(
|
|
453
|
+
caret: TextPointCaret<T, D>,
|
|
454
|
+
distance: number,
|
|
455
|
+
): TextPointCaretSlice<T, D>;
|
|
456
|
+
/**
|
|
457
|
+
* Get a caret that points at the first or last child of the given origin node,
|
|
458
|
+
* which must be an ElementNode.
|
|
459
|
+
*
|
|
460
|
+
* @param origin The origin ElementNode
|
|
461
|
+
* @param direction 'next' for first child or 'previous' for last child
|
|
462
|
+
* @returns null if origin is null or not an ElementNode, otherwise a ChildCaret for this origin and direction
|
|
463
|
+
*/
|
|
464
|
+
export declare function $getChildCaret<T extends ElementNode, D extends CaretDirection>(
|
|
465
|
+
origin: T,
|
|
466
|
+
direction: D,
|
|
467
|
+
): ChildCaret<T, D>;
|
|
468
|
+
/**
|
|
469
|
+
* Gets the ChildCaret if one is possible at this caret origin, otherwise return the caret
|
|
470
|
+
*/
|
|
471
|
+
export declare function $getChildCaretOrSelf<Caret extends PointCaret | null>(
|
|
472
|
+
caret: Caret,
|
|
473
|
+
): Caret | ChildCaret<ElementNode, NonNullable<Caret>['direction']>;
|
|
474
|
+
/**
|
|
475
|
+
* Gets the adjacent caret, if not-null and if the origin of the adjacent caret is an ElementNode, then return
|
|
476
|
+
* the ChildCaret. This can be used along with the getParentAdjacentCaret method to perform a full DFS
|
|
477
|
+
* style traversal of the tree.
|
|
478
|
+
*
|
|
479
|
+
* @param caret The caret to start at
|
|
480
|
+
*/
|
|
481
|
+
export declare function $getAdjacentChildCaret<D extends CaretDirection>(
|
|
482
|
+
caret: null | NodeCaret<D>,
|
|
483
|
+
): null | NodeCaret<D>;
|
|
484
|
+
/**
|
|
485
|
+
* Guard to check for a TextPointCaretSlice
|
|
486
|
+
*
|
|
487
|
+
* @param caretOrSlice A caret or slice
|
|
488
|
+
* @returns true if caretOrSlice is a TextPointCaretSlice
|
|
489
|
+
*/
|
|
490
|
+
export declare function $isTextPointCaretSlice<D extends CaretDirection>(
|
|
491
|
+
caretOrSlice: null | undefined | PointCaret<D> | TextPointCaretSlice<TextNode, D>,
|
|
492
|
+
): caretOrSlice is TextPointCaretSlice<TextNode, D>;
|
|
493
|
+
/**
|
|
494
|
+
* Construct a CaretRange that starts at anchor and goes to the end of the
|
|
495
|
+
* document in the anchor caret's direction.
|
|
496
|
+
*/
|
|
497
|
+
export declare function $extendCaretToRange<D extends CaretDirection>(
|
|
498
|
+
anchor: PointCaret<D>,
|
|
499
|
+
): CaretRange<D>;
|
|
500
|
+
/**
|
|
501
|
+
* Construct a collapsed CaretRange that starts and ends at anchor.
|
|
502
|
+
*/
|
|
503
|
+
export declare function $getCollapsedCaretRange<D extends CaretDirection>(
|
|
504
|
+
anchor: PointCaret<D>,
|
|
505
|
+
): CaretRange<D>;
|
|
506
|
+
/**
|
|
507
|
+
* Construct a CaretRange from anchor and focus carets pointing in the
|
|
508
|
+
* same direction. In order to get the expected behavior,
|
|
509
|
+
* the anchor must point towards the focus or be the same point.
|
|
510
|
+
*
|
|
511
|
+
* In the 'next' direction the anchor should be at or before the
|
|
512
|
+
* focus in the document. In the 'previous' direction the anchor
|
|
513
|
+
* should be at or after the focus in the document
|
|
514
|
+
* (similar to a backwards RangeSelection).
|
|
515
|
+
*
|
|
516
|
+
* @param anchor
|
|
517
|
+
* @param focus
|
|
518
|
+
* @returns a CaretRange
|
|
519
|
+
*/
|
|
520
|
+
export declare function $getCaretRange<D extends CaretDirection>(
|
|
521
|
+
anchor: PointCaret<D>,
|
|
522
|
+
focus: PointCaret<D>,
|
|
523
|
+
): CaretRange<D>;
|
|
524
|
+
/**
|
|
525
|
+
* A generalized utility for creating a stepwise iterator
|
|
526
|
+
* based on:
|
|
527
|
+
*
|
|
528
|
+
* - an initial state
|
|
529
|
+
* - a stop guard that returns true if the iteration is over, this
|
|
530
|
+
* is typically used to detect a sentinel value such as null or
|
|
531
|
+
* undefined from the state but may return true for other conditions
|
|
532
|
+
* as well
|
|
533
|
+
* - a step function that advances the state (this will be called
|
|
534
|
+
* after map each time next() is called to prepare the next state)
|
|
535
|
+
* - a map function that will be called that may transform the state
|
|
536
|
+
* before returning it. It will only be called once for each next()
|
|
537
|
+
* call when stop(state) === false
|
|
538
|
+
*
|
|
539
|
+
* @param config
|
|
540
|
+
* @returns An IterableIterator
|
|
541
|
+
*/
|
|
542
|
+
export declare function makeStepwiseIterator<State, Stop, Value>(
|
|
543
|
+
config: StepwiseIteratorConfig<State, Stop, Value>,
|
|
544
|
+
): IterableIterator<Value>;
|
|
545
|
+
/**
|
|
546
|
+
* A total ordering for `PointCaret<'next'>`, based on
|
|
547
|
+
* the same order that a {@link CaretRange} would iterate
|
|
548
|
+
* them.
|
|
549
|
+
*
|
|
550
|
+
* For a given origin node:
|
|
551
|
+
* - ChildCaret comes before SiblingCaret
|
|
552
|
+
* - TextPointCaret comes before SiblingCaret
|
|
553
|
+
*
|
|
554
|
+
* An exception is thrown when a and b do not have any
|
|
555
|
+
* common ancestor.
|
|
556
|
+
*
|
|
557
|
+
* This ordering is a sort of mix of pre-order and post-order
|
|
558
|
+
* because each ElementNode will show up as a ChildCaret
|
|
559
|
+
* on 'enter' (pre-order) and a SiblingCaret on 'leave' (post-order).
|
|
560
|
+
*
|
|
561
|
+
* @param a
|
|
562
|
+
* @param b
|
|
563
|
+
* @returns -1 if a comes before b, 0 if a and b are the same, or 1 if a comes after b
|
|
564
|
+
*/
|
|
565
|
+
export declare function $comparePointCaretNext(
|
|
566
|
+
a: PointCaret<'next'>,
|
|
567
|
+
b: PointCaret<'next'>,
|
|
568
|
+
): -1 | 0 | 1;
|
|
569
|
+
/**
|
|
570
|
+
* Return the ordering of siblings in a {@link CommonAncestorResultBranch}
|
|
571
|
+
* @param compare Returns -1 if a precedes b, 1 otherwise
|
|
572
|
+
*/
|
|
573
|
+
export declare function $getCommonAncestorResultBranchOrder<
|
|
574
|
+
A extends LexicalNode,
|
|
575
|
+
B extends LexicalNode,
|
|
576
|
+
>(compare: CommonAncestorResultBranch<A, B>): -1 | 1;
|
|
577
|
+
/**
|
|
578
|
+
* The two compared nodes are the same
|
|
579
|
+
*/
|
|
580
|
+
export interface CommonAncestorResultSame<A extends LexicalNode> {
|
|
581
|
+
readonly type: 'same';
|
|
582
|
+
readonly commonAncestor: A;
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Node a was a descendant of node b, and not the same node
|
|
586
|
+
*/
|
|
587
|
+
export interface CommonAncestorResultDescendant<B extends ElementNode> {
|
|
588
|
+
readonly type: 'descendant';
|
|
589
|
+
readonly commonAncestor: B;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Node a is an ancestor of node b, and not the same node
|
|
593
|
+
*/
|
|
594
|
+
export interface CommonAncestorResultAncestor<A extends ElementNode> {
|
|
595
|
+
readonly type: 'ancestor';
|
|
596
|
+
readonly commonAncestor: A;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Node a and node b have a common ancestor but are on different branches,
|
|
600
|
+
* the `a` and `b` properties of this result are the ancestors of a and b
|
|
601
|
+
* that are children of the commonAncestor. Since they are siblings, their
|
|
602
|
+
* positions are comparable to determine order in the document.
|
|
603
|
+
*/
|
|
604
|
+
export interface CommonAncestorResultBranch<A extends LexicalNode, B extends LexicalNode> {
|
|
605
|
+
readonly type: 'branch';
|
|
606
|
+
readonly commonAncestor: ElementNode;
|
|
607
|
+
/** The ancestor of `a` that is a child of `commonAncestor` */
|
|
608
|
+
readonly a: A | ElementNode;
|
|
609
|
+
/** The ancestor of `b` that is a child of `commonAncestor` */
|
|
610
|
+
readonly b: B | ElementNode;
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* The result of comparing two nodes that share some common ancestor
|
|
614
|
+
*/
|
|
615
|
+
export type CommonAncestorResult<A extends LexicalNode, B extends LexicalNode> =
|
|
616
|
+
| CommonAncestorResultSame<A>
|
|
617
|
+
| CommonAncestorResultAncestor<A & ElementNode>
|
|
618
|
+
| CommonAncestorResultDescendant<B & ElementNode>
|
|
619
|
+
| CommonAncestorResultBranch<A, B>;
|
|
620
|
+
/**
|
|
621
|
+
* Find a common ancestor of a and b and return a detailed result object,
|
|
622
|
+
* or null if there is no common ancestor between the two nodes.
|
|
623
|
+
*
|
|
624
|
+
* The result object will have a commonAncestor property, and the other
|
|
625
|
+
* properties can be used to quickly compare these positions in the tree.
|
|
626
|
+
*
|
|
627
|
+
* @param a A LexicalNode
|
|
628
|
+
* @param b A LexicalNode
|
|
629
|
+
* @returns A comparison result between the two nodes or null if they have no common ancestor
|
|
630
|
+
*/
|
|
631
|
+
export declare function $getCommonAncestor<A extends LexicalNode, B extends LexicalNode>(
|
|
632
|
+
a: A,
|
|
633
|
+
b: B,
|
|
634
|
+
): null | CommonAncestorResult<A, B>;
|
|
635
|
+
export {};
|