prosemirror-view 1.23.13 → 1.24.0-beta.3

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,66 +1,86 @@
1
- function compareObjs(a, b) {
1
+ import {Node, Mark} from "prosemirror-model"
2
+ import {Mappable, Mapping} from "prosemirror-transform"
3
+ import {EditorView} from "./index"
4
+ import {DOMNode} from "./dom"
5
+
6
+ function compareObjs(a: {[prop: string]: any}, b: {[prop: string]: any}) {
2
7
  if (a == b) return true
3
8
  for (let p in a) if (a[p] !== b[p]) return false
4
9
  for (let p in b) if (!(p in a)) return false
5
10
  return true
6
11
  }
7
12
 
8
- class WidgetType {
9
- constructor(toDOM, spec) {
13
+ export interface DecorationType {
14
+ spec: any
15
+ map(mapping: Mappable, span: Decoration, offset: number, oldOffset: number): Decoration | null
16
+ valid(node: Node, span: Decoration): boolean
17
+ eq(other: DecorationType): boolean
18
+ destroy(dom: DOMNode): void
19
+ }
20
+
21
+ export type WidgetConstructor = ((view: EditorView, getPos: () => number | undefined) => DOMNode) | DOMNode
22
+
23
+ export class WidgetType implements DecorationType {
24
+ spec: any
25
+ side: number
26
+
27
+ constructor(readonly toDOM: WidgetConstructor, spec: any) {
10
28
  this.spec = spec || noSpec
11
29
  this.side = this.spec.side || 0
12
- this.toDOM = toDOM
13
30
  }
14
31
 
15
- map(mapping, span, offset, oldOffset) {
32
+ map(mapping: Mappable, span: Decoration, offset: number, oldOffset: number): Decoration | null {
16
33
  let {pos, deleted} = mapping.mapResult(span.from + oldOffset, this.side < 0 ? -1 : 1)
17
34
  return deleted ? null : new Decoration(pos - offset, pos - offset, this)
18
35
  }
19
36
 
20
37
  valid() { return true }
21
38
 
22
- eq(other) {
39
+ eq(other: WidgetType) {
23
40
  return this == other ||
24
41
  (other instanceof WidgetType &&
25
42
  (this.spec.key && this.spec.key == other.spec.key ||
26
43
  this.toDOM == other.toDOM && compareObjs(this.spec, other.spec)))
27
44
  }
28
45
 
29
- destroy(node) {
46
+ destroy(node: DOMNode) {
30
47
  if (this.spec.destroy) this.spec.destroy(node)
31
48
  }
32
49
  }
33
50
 
34
- class InlineType {
35
- constructor(attrs, spec) {
51
+ export class InlineType implements DecorationType {
52
+ spec: any
53
+
54
+ constructor(readonly attrs: DecorationAttrs, spec: any) {
36
55
  this.spec = spec || noSpec
37
- this.attrs = attrs
38
56
  }
39
57
 
40
- map(mapping, span, offset, oldOffset) {
58
+ map(mapping: Mappable, span: Decoration, offset: number, oldOffset: number): Decoration | null {
41
59
  let from = mapping.map(span.from + oldOffset, this.spec.inclusiveStart ? -1 : 1) - offset
42
60
  let to = mapping.map(span.to + oldOffset, this.spec.inclusiveEnd ? 1 : -1) - offset
43
61
  return from >= to ? null : new Decoration(from, to, this)
44
62
  }
45
63
 
46
- valid(_, span) { return span.from < span.to }
64
+ valid(_: Node, span: Decoration) { return span.from < span.to }
47
65
 
48
- eq(other) {
66
+ eq(other: DecorationType): boolean {
49
67
  return this == other ||
50
68
  (other instanceof InlineType && compareObjs(this.attrs, other.attrs) &&
51
69
  compareObjs(this.spec, other.spec))
52
70
  }
53
71
 
54
- static is(span) { return span.type instanceof InlineType }
72
+ static is(span: Decoration) { return span.type instanceof InlineType }
73
+
74
+ destroy() {}
55
75
  }
56
76
 
57
- class NodeType {
58
- constructor(attrs, spec) {
77
+ export class NodeType implements DecorationType {
78
+ spec: any
79
+ constructor(readonly attrs: DecorationAttrs, spec: any) {
59
80
  this.spec = spec || noSpec
60
- this.attrs = attrs
61
81
  }
62
82
 
63
- map(mapping, span, offset, oldOffset) {
83
+ map(mapping: Mappable, span: Decoration, offset: number, oldOffset: number): Decoration | null {
64
84
  let from = mapping.mapResult(span.from + oldOffset, 1)
65
85
  if (from.deleted) return null
66
86
  let to = mapping.mapResult(span.to + oldOffset, -1)
@@ -68,194 +88,208 @@ class NodeType {
68
88
  return new Decoration(from.pos - offset, to.pos - offset, this)
69
89
  }
70
90
 
71
- valid(node, span) {
91
+ valid(node: Node, span: Decoration): boolean {
72
92
  let {index, offset} = node.content.findIndex(span.from), child
73
93
  return offset == span.from && !(child = node.child(index)).isText && offset + child.nodeSize == span.to
74
94
  }
75
95
 
76
- eq(other) {
96
+ eq(other: DecorationType): boolean {
77
97
  return this == other ||
78
98
  (other instanceof NodeType && compareObjs(this.attrs, other.attrs) &&
79
99
  compareObjs(this.spec, other.spec))
80
100
  }
101
+
102
+ destroy() {}
81
103
  }
82
104
 
83
- // ::- Decoration objects can be provided to the view through the
84
- // [`decorations` prop](#view.EditorProps.decorations). They come in
85
- // several variants—see the static members of this class for details.
105
+ /// Decoration objects can be provided to the view through the
106
+ /// [`decorations` prop](#view.EditorProps.decorations). They come in
107
+ /// several variants—see the static members of this class for details.
86
108
  export class Decoration {
87
- constructor(from, to, type) {
88
- // :: number
89
- // The start position of the decoration.
90
- this.from = from
91
- // :: number
92
- // The end position. Will be the same as `from` for [widget
93
- // decorations](#view.Decoration^widget).
94
- this.to = to
95
- this.type = type
96
- }
97
-
98
- copy(from, to) {
109
+ /// @internal
110
+ constructor(
111
+ /// The start position of the decoration.
112
+ readonly from: number,
113
+ /// The end position. Will be the same as `from` for [widget
114
+ /// decorations](#view.Decoration^widget).
115
+ readonly to: number,
116
+ /// @internal
117
+ readonly type: DecorationType
118
+ ) {}
119
+
120
+ /// @internal
121
+ copy(from: number, to: number) {
99
122
  return new Decoration(from, to, this.type)
100
123
  }
101
124
 
102
- eq(other, offset = 0) {
125
+ /// @internal
126
+ eq(other: Decoration, offset = 0) {
103
127
  return this.type.eq(other.type) && this.from + offset == other.from && this.to + offset == other.to
104
128
  }
105
129
 
106
- map(mapping, offset, oldOffset) {
130
+ /// @internal
131
+ map(mapping: Mappable, offset: number, oldOffset: number) {
107
132
  return this.type.map(mapping, this, offset, oldOffset)
108
133
  }
109
134
 
110
- // :: (number, union<(view: EditorView, getPos: () → number) → dom.Node, dom.Node>, ?Object) → Decoration
111
- // Creates a widget decoration, which is a DOM node that's shown in
112
- // the document at the given position. It is recommended that you
113
- // delay rendering the widget by passing a function that will be
114
- // called when the widget is actually drawn in a view, but you can
115
- // also directly pass a DOM node. `getPos` can be used to find the
116
- // widget's current document position.
117
- //
118
- // spec::- These options are supported:
119
- //
120
- // side:: ?number
121
- // Controls which side of the document position this widget is
122
- // associated with. When negative, it is drawn before a cursor
123
- // at its position, and content inserted at that position ends
124
- // up after the widget. When zero (the default) or positive, the
125
- // widget is drawn after the cursor and content inserted there
126
- // ends up before the widget.
127
- //
128
- // When there are multiple widgets at a given position, their
129
- // `side` values determine the order in which they appear. Those
130
- // with lower values appear first. The ordering of widgets with
131
- // the same `side` value is unspecified.
132
- //
133
- // When `marks` is null, `side` also determines the marks that
134
- // the widget is wrapped in—those of the node before when
135
- // negative, those of the node after when positive.
136
- //
137
- // marks:: ?[Mark]
138
- // The precise set of marks to draw around the widget.
139
- //
140
- // stopEvent:: ?(event: dom.Event) → bool
141
- // Can be used to control which DOM events, when they bubble out
142
- // of this widget, the editor view should ignore.
143
- //
144
- // ignoreSelection:: ?bool
145
- // When set (defaults to false), selection changes inside the
146
- // widget are ignored, and don't cause ProseMirror to try and
147
- // re-sync the selection with its selection state.
148
- //
149
- // key:: ?string
150
- // When comparing decorations of this type (in order to decide
151
- // whether it needs to be redrawn), ProseMirror will by default
152
- // compare the widget DOM node by identity. If you pass a key,
153
- // that key will be compared instead, which can be useful when
154
- // you generate decorations on the fly and don't want to store
155
- // and reuse DOM nodes. Make sure that any widgets with the same
156
- // key are interchangeable—if widgets differ in, for example,
157
- // the behavior of some event handler, they should get
158
- // different keys.
159
- //
160
- // destroy:: ?(node: dom.Node)
161
- // Called when the widget decoration is removed as a result of
162
- // mapping
163
- static widget(pos, toDOM, spec) {
135
+ /// Creates a widget decoration, which is a DOM node that's shown in
136
+ /// the document at the given position. It is recommended that you
137
+ /// delay rendering the widget by passing a function that will be
138
+ /// called when the widget is actually drawn in a view, but you can
139
+ /// also directly pass a DOM node. `getPos` can be used to find the
140
+ /// widget's current document position.
141
+ static widget(pos: number, toDOM: WidgetConstructor, spec?: {
142
+ /// Controls which side of the document position this widget is
143
+ /// associated with. When negative, it is drawn before a cursor
144
+ /// at its position, and content inserted at that position ends
145
+ /// up after the widget. When zero (the default) or positive, the
146
+ /// widget is drawn after the cursor and content inserted there
147
+ /// ends up before the widget.
148
+ ///
149
+ /// When there are multiple widgets at a given position, their
150
+ /// `side` values determine the order in which they appear. Those
151
+ /// with lower values appear first. The ordering of widgets with
152
+ /// the same `side` value is unspecified.
153
+ ///
154
+ /// When `marks` is null, `side` also determines the marks that
155
+ /// the widget is wrapped in—those of the node before when
156
+ /// negative, those of the node after when positive.
157
+ side?: number
158
+
159
+ /// The precise set of marks to draw around the widget.
160
+ marks?: readonly Mark[]
161
+
162
+ /// Can be used to control which DOM events, when they bubble out
163
+ /// of this widget, the editor view should ignore.
164
+ stopEvent?: (event: Event) => boolean
165
+
166
+ /// When set (defaults to false), selection changes inside the
167
+ /// widget are ignored, and don't cause ProseMirror to try and
168
+ /// re-sync the selection with its selection state.
169
+ ignoreSelection?: boolean
170
+
171
+ /// When comparing decorations of this type (in order to decide
172
+ /// whether it needs to be redrawn), ProseMirror will by default
173
+ /// compare the widget DOM node by identity. If you pass a key,
174
+ /// that key will be compared instead, which can be useful when
175
+ /// you generate decorations on the fly and don't want to store
176
+ /// and reuse DOM nodes. Make sure that any widgets with the same
177
+ /// key are interchangeable—if widgets differ in, for example,
178
+ /// the behavior of some event handler, they should get
179
+ /// different keys.
180
+ key?: string
181
+
182
+ /// Called when the widget decoration is removed as a result of
183
+ /// mapping
184
+ destroy?: (node: DOMNode) => void
185
+ }): Decoration {
164
186
  return new Decoration(pos, pos, new WidgetType(toDOM, spec))
165
187
  }
166
188
 
167
- // :: (number, number, DecorationAttrs, ?Object) → Decoration
168
- // Creates an inline decoration, which adds the given attributes to
169
- // each inline node between `from` and `to`.
170
- //
171
- // spec::- These options are recognized:
172
- //
173
- // inclusiveStart:: ?bool
174
- // Determines how the left side of the decoration is
175
- // [mapped](#transform.Position_Mapping) when content is
176
- // inserted directly at that position. By default, the decoration
177
- // won't include the new content, but you can set this to `true`
178
- // to make it inclusive.
179
- //
180
- // inclusiveEnd:: ?bool
181
- // Determines how the right side of the decoration is mapped.
182
- // See
183
- // [`inclusiveStart`](#view.Decoration^inline^spec.inclusiveStart).
184
- static inline(from, to, attrs, spec) {
189
+ /// Creates an inline decoration, which adds the given attributes to
190
+ /// each inline node between `from` and `to`.
191
+ static inline(from: number, to: number, attrs: DecorationAttrs, spec?: {
192
+ /// Determines how the left side of the decoration is
193
+ /// [mapped](#transform.Position_Mapping) when content is
194
+ /// inserted directly at that position. By default, the decoration
195
+ /// won't include the new content, but you can set this to `true`
196
+ /// to make it inclusive.
197
+ inclusiveStart?: boolean
198
+
199
+ /// Determines how the right side of the decoration is mapped.
200
+ /// See
201
+ /// [`inclusiveStart`](#view.Decoration^inline^spec.inclusiveStart).
202
+ inclusiveEnd?: boolean
203
+ }) {
185
204
  return new Decoration(from, to, new InlineType(attrs, spec))
186
205
  }
187
206
 
188
- // :: (number, number, DecorationAttrs, ?Object) → Decoration
189
- // Creates a node decoration. `from` and `to` should point precisely
190
- // before and after a node in the document. That node, and only that
191
- // node, will receive the given attributes.
192
- //
193
- // spec::-
194
- //
195
- // Optional information to store with the decoration. It
196
- // is also used when comparing decorators for equality.
197
- static node(from, to, attrs, spec) {
207
+ /// Creates a node decoration. `from` and `to` should point precisely
208
+ /// before and after a node in the document. That node, and only that
209
+ /// node, will receive the given attributes.
210
+ static node(from: number, to: number, attrs: DecorationAttrs, spec?: any) {
198
211
  return new Decoration(from, to, new NodeType(attrs, spec))
199
212
  }
200
213
 
201
- // :: Object
202
- // The spec provided when creating this decoration. Can be useful
203
- // if you've stored extra information in that object.
214
+ /// The spec provided when creating this decoration. Can be useful
215
+ /// if you've stored extra information in that object.
204
216
  get spec() { return this.type.spec }
205
217
 
218
+ /// @internal
206
219
  get inline() { return this.type instanceof InlineType }
207
220
  }
208
221
 
209
- // DecorationAttrs:: interface
210
- // A set of attributes to add to a decorated node. Most properties
211
- // simply directly correspond to DOM attributes of the same name,
212
- // which will be set to the property's value. These are exceptions:
213
- //
214
- // class:: ?string
215
- // A CSS class name or a space-separated set of class names to be
216
- // _added_ to the classes that the node already had.
217
- //
218
- // style:: ?string
219
- // A string of CSS to be _added_ to the node's existing `style` property.
220
- //
221
- // nodeName:: ?string
222
- // When non-null, the target node is wrapped in a DOM element of
223
- // this type (and the other attributes are applied to this element).
224
-
225
- const none = [], noSpec = {}
226
-
227
- // :: class extends DecorationSource
228
- // A collection of [decorations](#view.Decoration), organized in
229
- // such a way that the drawing algorithm can efficiently use and
230
- // compare them. This is a persistent data structure—it is not
231
- // modified, updates create a new value.
232
- export class DecorationSet {
233
- constructor(local, children) {
234
- this.local = local && local.length ? local : none
235
- this.children = children && children.length ? children : none
236
- }
237
-
238
- // :: (Node, [Decoration]) → DecorationSet
239
- // Create a set of decorations, using the structure of the given
240
- // document.
241
- static create(doc, decorations) {
222
+ /// A set of attributes to add to a decorated node. Most properties
223
+ /// simply directly correspond to DOM attributes of the same name,
224
+ /// which will be set to the property's value. These are exceptions:
225
+ export type DecorationAttrs = {
226
+ /// When non-null, the target node is wrapped in a DOM element of
227
+ /// this type (and the other attributes are applied to this element).
228
+ nodeName?: string
229
+
230
+ /// A CSS class name or a space-separated set of class names to be
231
+ /// _added_ to the classes that the node already had.
232
+ class?: string
233
+
234
+ /// A string of CSS to be _added_ to the node's existing `style` property.
235
+ style?: string
236
+
237
+ /// Any other properties are treated as regular DOM attributes.
238
+ [attribute: string]: string | undefined
239
+ }
240
+
241
+ const none: readonly any[] = [], noSpec = {}
242
+
243
+ /// An object that can [provide](#view.EditorProps.decorations)
244
+ /// decorations. Implemented by [`DecorationSet`](#view.DecorationSet),
245
+ /// and passed to [node views](#view.EditorProps.nodeViews).
246
+ export interface DecorationSource {
247
+ /// Map the set of decorations in response to a change in the
248
+ /// document.
249
+ map: (mapping: Mapping, node: Node) => DecorationSource
250
+ /// @internal
251
+ locals(node: Node): readonly Decoration[]
252
+ /// @internal
253
+ forChild(offset: number, child: Node): DecorationSource
254
+ /// @internal
255
+ eq(other: DecorationSource): boolean
256
+ }
257
+
258
+ /// A collection of [decorations](#view.Decoration), organized in such
259
+ /// a way that the drawing algorithm can efficiently use and compare
260
+ /// them. This is a persistent data structure—it is not modified,
261
+ /// updates create a new value.
262
+ export class DecorationSet implements DecorationSource {
263
+ /// @internal
264
+ local: readonly Decoration[]
265
+ /// @internal
266
+ children: readonly (number | DecorationSet)[]
267
+
268
+ /// @internal
269
+ constructor(local: readonly Decoration[], children: readonly (number | DecorationSet)[]) {
270
+ this.local = local.length ? local : none
271
+ this.children = children.length ? children : none
272
+ }
273
+
274
+ /// Create a set of decorations, using the structure of the given
275
+ /// document.
276
+ static create(doc: Node, decorations: Decoration[]) {
242
277
  return decorations.length ? buildTree(decorations, doc, 0, noSpec) : empty
243
278
  }
244
279
 
245
- // :: (?number, ?number, ?(spec: Object) → bool) → [Decoration]
246
- // Find all decorations in this set which touch the given range
247
- // (including decorations that start or end directly at the
248
- // boundaries) and match the given predicate on their spec. When
249
- // `start` and `end` are omitted, all decorations in the set are
250
- // considered. When `predicate` isn't given, all decorations are
251
- // assumed to match.
252
- find(start, end, predicate) {
253
- let result = []
280
+ /// Find all decorations in this set which touch the given range
281
+ /// (including decorations that start or end directly at the
282
+ /// boundaries) and match the given predicate on their spec. When
283
+ /// `start` and `end` are omitted, all decorations in the set are
284
+ /// considered. When `predicate` isn't given, all decorations are
285
+ /// assumed to match.
286
+ find(start?: number, end?: number, predicate?: (spec: any) => boolean): Decoration[] {
287
+ let result: Decoration[] = []
254
288
  this.findInner(start == null ? 0 : start, end == null ? 1e9 : end, result, 0, predicate)
255
289
  return result
256
290
  }
257
291
 
258
- findInner(start, end, result, offset, predicate) {
292
+ private findInner(start: number, end: number, result: Decoration[], offset: number, predicate?: (spec: any) => boolean) {
259
293
  for (let i = 0; i < this.local.length; i++) {
260
294
  let span = this.local[i]
261
295
  if (span.from <= end && span.to >= start && (!predicate || predicate(span.spec)))
@@ -263,29 +297,30 @@ export class DecorationSet {
263
297
  }
264
298
  for (let i = 0; i < this.children.length; i += 3) {
265
299
  if (this.children[i] < end && this.children[i + 1] > start) {
266
- let childOff = this.children[i] + 1
267
- this.children[i + 2].findInner(start - childOff, end - childOff, result, offset + childOff, predicate)
300
+ let childOff = (this.children[i] as number) + 1
301
+ ;(this.children[i + 2] as DecorationSet).findInner(start - childOff, end - childOff,
302
+ result, offset + childOff, predicate)
268
303
  }
269
304
  }
270
305
  }
271
306
 
272
- // :: (Mapping, Node, ?Object) → DecorationSet
273
- // Map the set of decorations in response to a change in the
274
- // document.
275
- //
276
- // options::- An optional set of options.
277
- //
278
- // onRemove:: ?(decorationSpec: Object)
279
- // When given, this function will be called for each decoration
280
- // that gets dropped as a result of the mapping, passing the
281
- // spec of that decoration.
282
- map(mapping, doc, options) {
307
+ /// Map the set of decorations in response to a change in the
308
+ /// document.
309
+ map(mapping: Mapping, doc: Node, options?: {
310
+ /// When given, this function will be called for each decoration
311
+ /// that gets dropped as a result of the mapping, passing the
312
+ /// spec of that decoration.
313
+ onRemove?: (decorationSpec: any) => void
314
+ }) {
283
315
  if (this == empty || mapping.maps.length == 0) return this
284
316
  return this.mapInner(mapping, doc, 0, 0, options || noSpec)
285
317
  }
286
318
 
287
- mapInner(mapping, node, offset, oldOffset, options) {
288
- let newLocal
319
+ /// @internal
320
+ mapInner(mapping: Mapping, node: Node, offset: number, oldOffset: number, options: {
321
+ onRemove?: (decorationSpec: any) => void
322
+ }) {
323
+ let newLocal: Decoration[] | undefined
289
324
  for (let i = 0; i < this.local.length; i++) {
290
325
  let mapped = this.local[i].map(mapping, offset, oldOffset)
291
326
  if (mapped && mapped.type.valid(node, mapped)) (newLocal || (newLocal = [])).push(mapped)
@@ -293,23 +328,22 @@ export class DecorationSet {
293
328
  }
294
329
 
295
330
  if (this.children.length)
296
- return mapChildren(this.children, newLocal, mapping, node, offset, oldOffset, options)
331
+ return mapChildren(this.children, newLocal || [], mapping, node, offset, oldOffset, options)
297
332
  else
298
- return newLocal ? new DecorationSet(newLocal.sort(byPos)) : empty
333
+ return newLocal ? new DecorationSet(newLocal.sort(byPos), none) : empty
299
334
  }
300
335
 
301
- // :: (Node, [Decoration]) → DecorationSet
302
- // Add the given array of decorations to the ones in the set,
303
- // producing a new set. Needs access to the current document to
304
- // create the appropriate tree structure.
305
- add(doc, decorations) {
336
+ /// Add the given array of decorations to the ones in the set,
337
+ /// producing a new set. Needs access to the current document to
338
+ /// create the appropriate tree structure.
339
+ add(doc: Node, decorations: Decoration[]) {
306
340
  if (!decorations.length) return this
307
341
  if (this == empty) return DecorationSet.create(doc, decorations)
308
342
  return this.addInner(doc, decorations, 0)
309
343
  }
310
344
 
311
- addInner(doc, decorations, offset) {
312
- let children, childIndex = 0
345
+ private addInner(doc: Node, decorations: Decoration[], offset: number) {
346
+ let children: (number | DecorationSet)[] | undefined, childIndex = 0
313
347
  doc.forEach((childNode, childOffset) => {
314
348
  let baseOffset = childOffset + offset, found
315
349
  if (!(found = takeSpansForNode(decorations, childNode, baseOffset))) return
@@ -317,7 +351,7 @@ export class DecorationSet {
317
351
  if (!children) children = this.children.slice()
318
352
  while (childIndex < children.length && children[childIndex] < childOffset) childIndex += 3
319
353
  if (children[childIndex] == childOffset)
320
- children[childIndex + 2] = children[childIndex + 2].addInner(childNode, found, baseOffset + 1)
354
+ children[childIndex + 2] = (children[childIndex + 2] as DecorationSet).addInner(childNode, found, baseOffset + 1)
321
355
  else
322
356
  children.splice(childIndex, 0, childOffset, childOffset + childNode.nodeSize, buildTree(found, childNode, baseOffset + 1, noSpec))
323
357
  childIndex += 3
@@ -330,18 +364,18 @@ export class DecorationSet {
330
364
  children || this.children)
331
365
  }
332
366
 
333
- // :: ([Decoration]) → DecorationSet
334
- // Create a new set that contains the decorations in this set, minus
335
- // the ones in the given array.
336
- remove(decorations) {
367
+ /// Create a new set that contains the decorations in this set, minus
368
+ /// the ones in the given array.
369
+ remove(decorations: Decoration[]) {
337
370
  if (decorations.length == 0 || this == empty) return this
338
371
  return this.removeInner(decorations, 0)
339
372
  }
340
373
 
341
- removeInner(decorations, offset) {
342
- let children = this.children, local = this.local
374
+ private removeInner(decorations: (Decoration | null)[], offset: number) {
375
+ let children = this.children as (number | DecorationSet)[], local = this.local as Decoration[]
343
376
  for (let i = 0; i < children.length; i += 3) {
344
- let found, from = children[i] + offset, to = children[i + 1] + offset
377
+ let found: Decoration[] | undefined
378
+ let from = (children[i] as number) + offset, to = (children[i + 1] as number) + offset
345
379
  for (let j = 0, span; j < decorations.length; j++) if (span = decorations[j]) {
346
380
  if (span.from > from && span.to < to) {
347
381
  decorations[j] = null
@@ -350,7 +384,7 @@ export class DecorationSet {
350
384
  }
351
385
  if (!found) continue
352
386
  if (children == this.children) children = this.children.slice()
353
- let removed = children[i + 2].removeInner(found, from + 1)
387
+ let removed = (children[i + 2] as DecorationSet).removeInner(found, from + 1)
354
388
  if (removed != empty) {
355
389
  children[i + 2] = removed
356
390
  } else {
@@ -368,13 +402,14 @@ export class DecorationSet {
368
402
  return local.length || children.length ? new DecorationSet(local, children) : empty
369
403
  }
370
404
 
371
- forChild(offset, node) {
405
+ /// @internal
406
+ forChild(offset: number, node: Node): DecorationSet | DecorationGroup {
372
407
  if (this == empty) return this
373
408
  if (node.isLeaf) return DecorationSet.empty
374
409
 
375
- let child, local
410
+ let child, local: Decoration[] | undefined
376
411
  for (let i = 0; i < this.children.length; i += 3) if (this.children[i] >= offset) {
377
- if (this.children[i] == offset) child = this.children[i + 2]
412
+ if (this.children[i] == offset) child = this.children[i + 2] as DecorationSet
378
413
  break
379
414
  }
380
415
  let start = offset + 1, end = start + node.content.size
@@ -386,13 +421,14 @@ export class DecorationSet {
386
421
  }
387
422
  }
388
423
  if (local) {
389
- let localSet = new DecorationSet(local.sort(byPos))
424
+ let localSet = new DecorationSet(local.sort(byPos), none)
390
425
  return child ? new DecorationGroup([localSet, child]) : localSet
391
426
  }
392
427
  return child || empty
393
428
  }
394
429
 
395
- eq(other) {
430
+ /// @internal
431
+ eq(other: DecorationSet) {
396
432
  if (this == other) return true
397
433
  if (!(other instanceof DecorationSet) ||
398
434
  this.local.length != other.local.length ||
@@ -402,15 +438,18 @@ export class DecorationSet {
402
438
  for (let i = 0; i < this.children.length; i += 3)
403
439
  if (this.children[i] != other.children[i] ||
404
440
  this.children[i + 1] != other.children[i + 1] ||
405
- !this.children[i + 2].eq(other.children[i + 2])) return false
441
+ !(this.children[i + 2] as DecorationSet).eq(other.children[i + 2] as DecorationSet))
442
+ return false
406
443
  return true
407
444
  }
408
445
 
409
- locals(node) {
446
+ /// @internal
447
+ locals(node: Node) {
410
448
  return removeOverlap(this.localsInner(node))
411
449
  }
412
450
 
413
- localsInner(node) {
451
+ /// @internal
452
+ localsInner(node: Node): readonly Decoration[] {
414
453
  if (this == empty) return none
415
454
  if (node.inlineContent || !this.local.some(InlineType.is)) return this.local
416
455
  let result = []
@@ -420,43 +459,32 @@ export class DecorationSet {
420
459
  }
421
460
  return result
422
461
  }
423
- }
424
-
425
- // DecorationSource:: interface
426
- // An object that can [provide](#view.EditorProps.decorations)
427
- // decorations. Implemented by [`DecorationSet`](#view.DecorationSet),
428
- // and passed to [node views](#view.EditorProps.nodeViews).
429
- //
430
- // map:: (Mapping, Node) → DecorationSource
431
- // Map the set of decorations in response to a change in the
432
- // document.
433
462
 
434
- const empty = new DecorationSet()
463
+ /// The empty set of decorations.
464
+ static empty: DecorationSet = new DecorationSet([], [])
435
465
 
436
- // :: DecorationSet
437
- // The empty set of decorations.
438
- DecorationSet.empty = empty
466
+ /// @internal
467
+ static removeOverlap = removeOverlap
468
+ }
439
469
 
440
- DecorationSet.removeOverlap = removeOverlap
470
+ const empty = DecorationSet.empty
441
471
 
442
- // :- An abstraction that allows the code dealing with decorations to
472
+ // An abstraction that allows the code dealing with decorations to
443
473
  // treat multiple DecorationSet objects as if it were a single object
444
474
  // with (a subset of) the same interface.
445
- class DecorationGroup {
446
- constructor(members) {
447
- this.members = members
448
- }
475
+ class DecorationGroup implements DecorationSource {
476
+ constructor(readonly members: readonly DecorationSet[]) {}
449
477
 
450
- map(mapping, doc) {
478
+ map(mapping: Mapping, doc: Node) {
451
479
  const mappedDecos = this.members.map(
452
480
  member => member.map(mapping, doc, noSpec)
453
481
  )
454
482
  return DecorationGroup.from(mappedDecos)
455
483
  }
456
484
 
457
- forChild(offset, child) {
485
+ forChild(offset: number, child: Node) {
458
486
  if (child.isLeaf) return DecorationSet.empty
459
- let found = []
487
+ let found: DecorationSet[] = []
460
488
  for (let i = 0; i < this.members.length; i++) {
461
489
  let result = this.members[i].forChild(offset, child)
462
490
  if (result == empty) continue
@@ -466,7 +494,7 @@ class DecorationGroup {
466
494
  return DecorationGroup.from(found)
467
495
  }
468
496
 
469
- eq(other) {
497
+ eq(other: DecorationGroup) {
470
498
  if (!(other instanceof DecorationGroup) ||
471
499
  other.members.length != this.members.length) return false
472
500
  for (let i = 0; i < this.members.length; i++)
@@ -474,13 +502,13 @@ class DecorationGroup {
474
502
  return true
475
503
  }
476
504
 
477
- locals(node) {
478
- let result, sorted = true
505
+ locals(node: Node) {
506
+ let result: Decoration[] | undefined, sorted = true
479
507
  for (let i = 0; i < this.members.length; i++) {
480
508
  let locals = this.members[i].localsInner(node)
481
509
  if (!locals.length) continue
482
510
  if (!result) {
483
- result = locals
511
+ result = locals as Decoration[]
484
512
  } else {
485
513
  if (sorted) {
486
514
  result = result.slice()
@@ -492,10 +520,9 @@ class DecorationGroup {
492
520
  return result ? removeOverlap(sorted ? result : result.sort(byPos)) : none
493
521
  }
494
522
 
495
- // : ([DecorationSet]) → union<DecorationSet, DecorationGroup>
496
523
  // Create a group for the given array of decoration sets, or return
497
524
  // a single set when possible.
498
- static from(members) {
525
+ static from(members: readonly DecorationSet[]): DecorationSet | DecorationGroup {
499
526
  switch (members.length) {
500
527
  case 0: return empty
501
528
  case 1: return members[0]
@@ -504,21 +531,29 @@ class DecorationGroup {
504
531
  }
505
532
  }
506
533
 
507
- function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, options) {
508
- let children = oldChildren.slice()
534
+ function mapChildren(
535
+ oldChildren: readonly (number | DecorationSet)[],
536
+ newLocal: Decoration[],
537
+ mapping: Mapping,
538
+ node: Node,
539
+ offset: number,
540
+ oldOffset: number,
541
+ options: {onRemove?: (decorationSpec: any) => void}
542
+ ) {
543
+ let children = oldChildren.slice() as (number | DecorationSet)[]
509
544
 
510
545
  // Mark the children that are directly touched by changes, and
511
546
  // move those that are after the changes.
512
- let shift = (oldStart, oldEnd, newStart, newEnd) => {
547
+ let shift = (oldStart: number, oldEnd: number, newStart: number, newEnd: number) => {
513
548
  for (let i = 0; i < children.length; i += 3) {
514
- let end = children[i + 1], dSize
549
+ let end = children[i + 1] as number, dSize
515
550
  if (end < 0 || oldStart > end + oldOffset) continue
516
- let start = children[i] + oldOffset
551
+ let start = (children[i] as number) + oldOffset
517
552
  if (oldEnd >= start) {
518
553
  children[i + 1] = oldStart <= start ? -2 : -1
519
554
  } else if (newStart >= offset && (dSize = (newEnd - newStart) - (oldEnd - oldStart))) {
520
- children[i] += dSize
521
- children[i + 1] += dSize
555
+ ;(children[i] as number) += dSize
556
+ ;(children[i + 1] as number) += dSize
522
557
  }
523
558
  }
524
559
  }
@@ -533,17 +568,18 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
533
568
  children[i + 1] = -1
534
569
  continue
535
570
  }
536
- let from = mapping.map(oldChildren[i] + oldOffset), fromLocal = from - offset
571
+ let from = mapping.map((oldChildren[i] as number) + oldOffset), fromLocal = from - offset
537
572
  if (fromLocal < 0 || fromLocal >= node.content.size) {
538
573
  mustRebuild = true
539
574
  continue
540
575
  }
541
576
  // Must read oldChildren because children was tagged with -1
542
- let to = mapping.map(oldChildren[i + 1] + oldOffset, -1), toLocal = to - offset
577
+ let to = mapping.map((oldChildren[i + 1] as number) + oldOffset, -1), toLocal = to - offset
543
578
  let {index, offset: childOffset} = node.content.findIndex(fromLocal)
544
579
  let childNode = node.maybeChild(index)
545
580
  if (childNode && childOffset == fromLocal && childOffset + childNode.nodeSize == toLocal) {
546
- let mapped = children[i + 2].mapInner(mapping, childNode, from + 1, oldChildren[i] + oldOffset + 1, options)
581
+ let mapped = (children[i + 2] as DecorationSet)
582
+ .mapInner(mapping, childNode, from + 1, (oldChildren[i] as number) + oldOffset + 1, options)
547
583
  if (mapped != empty) {
548
584
  children[i] = fromLocal
549
585
  children[i + 1] = toLocal
@@ -559,10 +595,10 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
559
595
 
560
596
  // Remaining children must be collected and rebuilt into the appropriate structure
561
597
  if (mustRebuild) {
562
- let decorations = mapAndGatherRemainingDecorations(children, oldChildren, newLocal || [], mapping,
598
+ let decorations = mapAndGatherRemainingDecorations(children, oldChildren, newLocal, mapping,
563
599
  offset, oldOffset, options)
564
600
  let built = buildTree(decorations, node, 0, options)
565
- newLocal = built.local
601
+ newLocal = built.local as Decoration[]
566
602
  for (let i = 0; i < children.length; i += 3) if (children[i + 1] < 0) {
567
603
  children.splice(i, 3)
568
604
  i -= 3
@@ -574,10 +610,10 @@ function mapChildren(oldChildren, newLocal, mapping, node, offset, oldOffset, op
574
610
  }
575
611
  }
576
612
 
577
- return new DecorationSet(newLocal && newLocal.sort(byPos), children)
613
+ return new DecorationSet(newLocal.sort(byPos), children)
578
614
  }
579
615
 
580
- function moveSpans(spans, offset) {
616
+ function moveSpans(spans: Decoration[], offset: number) {
581
617
  if (!offset || !spans.length) return spans
582
618
  let result = []
583
619
  for (let i = 0; i < spans.length; i++) {
@@ -587,24 +623,32 @@ function moveSpans(spans, offset) {
587
623
  return result
588
624
  }
589
625
 
590
- function mapAndGatherRemainingDecorations(children, oldChildren, decorations, mapping, offset, oldOffset, options) {
626
+ function mapAndGatherRemainingDecorations(
627
+ children: (number | DecorationSet)[],
628
+ oldChildren: readonly (number | DecorationSet)[],
629
+ decorations: Decoration[],
630
+ mapping: Mapping,
631
+ offset: number,
632
+ oldOffset: number,
633
+ options: {onRemove?: (decorationSpec: any) => void}
634
+ ) {
591
635
  // Gather all decorations from the remaining marked children
592
- function gather(set, oldOffset) {
636
+ function gather(set: DecorationSet, oldOffset: number) {
593
637
  for (let i = 0; i < set.local.length; i++) {
594
638
  let mapped = set.local[i].map(mapping, offset, oldOffset)
595
639
  if (mapped) decorations.push(mapped)
596
640
  else if (options.onRemove) options.onRemove(set.local[i].spec)
597
641
  }
598
642
  for (let i = 0; i < set.children.length; i += 3)
599
- gather(set.children[i + 2], set.children[i] + oldOffset + 1)
643
+ gather(set.children[i + 2] as DecorationSet, set.children[i] as number + oldOffset + 1)
600
644
  }
601
645
  for (let i = 0; i < children.length; i += 3) if (children[i + 1] == -1)
602
- gather(children[i + 2], oldChildren[i] + oldOffset + 1)
646
+ gather(children[i + 2] as DecorationSet, oldChildren[i] as number + oldOffset + 1)
603
647
 
604
648
  return decorations
605
649
  }
606
650
 
607
- function takeSpansForNode(spans, node, offset) {
651
+ function takeSpansForNode(spans: (Decoration | null)[], node: Node, offset: number): Decoration[] | null {
608
652
  if (node.isLeaf) return null
609
653
  let end = offset + node.nodeSize, found = null
610
654
  for (let i = 0, span; i < spans.length; i++) {
@@ -616,20 +660,24 @@ function takeSpansForNode(spans, node, offset) {
616
660
  return found
617
661
  }
618
662
 
619
- function withoutNulls(array) {
620
- let result = []
663
+ function withoutNulls<T>(array: readonly (T | null)[]): T[] {
664
+ let result: T[] = []
621
665
  for (let i = 0; i < array.length; i++)
622
- if (array[i] != null) result.push(array[i])
666
+ if (array[i] != null) result.push(array[i]!)
623
667
  return result
624
668
  }
625
669
 
626
- // : ([Decoration], Node, number) → DecorationSet
627
670
  // Build up a tree that corresponds to a set of decorations. `offset`
628
671
  // is a base offset that should be subtracted from the `from` and `to`
629
672
  // positions in the spans (so that we don't have to allocate new spans
630
673
  // for recursive calls).
631
- function buildTree(spans, node, offset, options) {
632
- let children = [], hasNulls = false
674
+ function buildTree(
675
+ spans: Decoration[],
676
+ node: Node,
677
+ offset: number,
678
+ options: {onRemove?: (decorationSpec: any) => void}
679
+ ) {
680
+ let children: (DecorationSet | number)[] = [], hasNulls = false
633
681
  node.forEach((childNode, localStart) => {
634
682
  let found = takeSpansForNode(spans, childNode, localStart + offset)
635
683
  if (found) {
@@ -647,21 +695,19 @@ function buildTree(spans, node, offset, options) {
647
695
  return locals.length || children.length ? new DecorationSet(locals, children) : empty
648
696
  }
649
697
 
650
- // : (Decoration, Decoration) → number
651
698
  // Used to sort decorations so that ones with a low start position
652
699
  // come first, and within a set with the same start position, those
653
700
  // with an smaller end position come first.
654
- function byPos(a, b) {
701
+ function byPos(a: Decoration, b: Decoration) {
655
702
  return a.from - b.from || a.to - b.to
656
703
  }
657
704
 
658
- // : ([Decoration]) → [Decoration]
659
705
  // Scan a sorted array of decorations for partially overlapping spans,
660
706
  // and split those so that only fully overlapping spans are left (to
661
707
  // make subsequent rendering easier). Will return the input array if
662
708
  // no partially overlapping spans are found (the common case).
663
- function removeOverlap(spans) {
664
- let working = spans
709
+ function removeOverlap(spans: readonly Decoration[]): Decoration[] {
710
+ let working: Decoration[] = spans as Decoration[]
665
711
  for (let i = 0; i < working.length - 1; i++) {
666
712
  let span = working[i]
667
713
  if (span.from != span.to) for (let j = i + 1; j < working.length; j++) {
@@ -690,14 +736,13 @@ function removeOverlap(spans) {
690
736
  return working
691
737
  }
692
738
 
693
- function insertAhead(array, i, deco) {
739
+ function insertAhead(array: Decoration[], i: number, deco: Decoration) {
694
740
  while (i < array.length && byPos(deco, array[i]) > 0) i++
695
741
  array.splice(i, 0, deco)
696
742
  }
697
743
 
698
- // : (EditorView) → union<DecorationSet, DecorationGroup>
699
744
  // Get the decorations associated with the current props of a view.
700
- export function viewDecorations(view) {
745
+ export function viewDecorations(view: EditorView): DecorationSet | DecorationGroup {
701
746
  let found = []
702
747
  view.someProp("decorations", f => {
703
748
  let result = f(view.state)