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.
package/src/index.js DELETED
@@ -1,668 +0,0 @@
1
- import {NodeSelection} from "prosemirror-state"
2
-
3
- import {scrollRectIntoView, posAtCoords, coordsAtPos, endOfTextblock, storeScrollPos,
4
- resetScrollPos, focusPreventScroll} from "./domcoords"
5
- import {docViewDesc} from "./viewdesc"
6
- import {initInput, destroyInput, dispatchEvent, ensureListeners, clearComposition} from "./input"
7
- import {selectionToDOM, anchorInRightPlace, syncNodeSelection} from "./selection"
8
- import {Decoration, viewDecorations} from "./decoration"
9
- import browser from "./browser"
10
-
11
- export {Decoration, DecorationSet} from "./decoration"
12
-
13
- // Exported for testing
14
- export {serializeForClipboard as __serializeForClipboard, parseFromClipboard as __parseFromClipboard} from "./clipboard"
15
- export {endComposition as __endComposition} from "./input"
16
-
17
- // ::- An editor view manages the DOM structure that represents an
18
- // editable document. Its state and behavior are determined by its
19
- // [props](#view.DirectEditorProps).
20
- export class EditorView {
21
- // :: (?union<dom.Node, (dom.Node), {mount: dom.Node}>, DirectEditorProps)
22
- // Create a view. `place` may be a DOM node that the editor should
23
- // be appended to, a function that will place it into the document,
24
- // or an object whose `mount` property holds the node to use as the
25
- // document container. If it is `null`, the editor will not be added
26
- // to the document.
27
- constructor(place, props) {
28
- this._props = props
29
- // :: EditorState
30
- // The view's current [state](#state.EditorState).
31
- this.state = props.state
32
-
33
- this.directPlugins = props.plugins || []
34
- this.directPlugins.forEach(checkStateComponent)
35
-
36
- this.dispatch = this.dispatch.bind(this)
37
-
38
- this._root = null
39
- this.focused = false
40
- // Kludge used to work around a Chrome bug
41
- this.trackWrites = null
42
-
43
- // :: dom.Element
44
- // An editable DOM node containing the document. (You probably
45
- // should not directly interfere with its content.)
46
- this.dom = (place && place.mount) || document.createElement("div")
47
- if (place) {
48
- if (place.appendChild) place.appendChild(this.dom)
49
- else if (place.apply) place(this.dom)
50
- else if (place.mount) this.mounted = true
51
- }
52
-
53
- // :: bool
54
- // Indicates whether the editor is currently [editable](#view.EditorProps.editable).
55
- this.editable = getEditable(this)
56
- this.markCursor = null
57
- this.cursorWrapper = null
58
- updateCursorWrapper(this)
59
- this.nodeViews = buildNodeViews(this)
60
- this.docView = docViewDesc(this.state.doc, computeDocDeco(this), viewDecorations(this), this.dom, this)
61
-
62
- this.lastSelectedViewDesc = null
63
- // :: ?{slice: Slice, move: bool}
64
- // When editor content is being dragged, this object contains
65
- // information about the dragged slice and whether it is being
66
- // copied or moved. At any other time, it is null.
67
- this.dragging = null
68
-
69
- initInput(this)
70
-
71
- this.prevDirectPlugins = []
72
- this.pluginViews = []
73
- this.updatePluginViews()
74
- }
75
-
76
- // composing:: boolean
77
- // Holds `true` when a
78
- // [composition](https://w3c.github.io/uievents/#events-compositionevents)
79
- // is active.
80
-
81
- // :: DirectEditorProps
82
- // The view's current [props](#view.EditorProps).
83
- get props() {
84
- if (this._props.state != this.state) {
85
- let prev = this._props
86
- this._props = {}
87
- for (let name in prev) this._props[name] = prev[name]
88
- this._props.state = this.state
89
- }
90
- return this._props
91
- }
92
-
93
- // :: (DirectEditorProps)
94
- // Update the view's props. Will immediately cause an update to
95
- // the DOM.
96
- update(props) {
97
- if (props.handleDOMEvents != this._props.handleDOMEvents) ensureListeners(this)
98
- this._props = props
99
- if (props.plugins) {
100
- props.plugins.forEach(checkStateComponent)
101
- this.directPlugins = props.plugins
102
- }
103
- this.updateStateInner(props.state, true)
104
- }
105
-
106
- // :: (DirectEditorProps)
107
- // Update the view by updating existing props object with the object
108
- // given as argument. Equivalent to `view.update(Object.assign({},
109
- // view.props, props))`.
110
- setProps(props) {
111
- let updated = {}
112
- for (let name in this._props) updated[name] = this._props[name]
113
- updated.state = this.state
114
- for (let name in props) updated[name] = props[name]
115
- this.update(updated)
116
- }
117
-
118
- // :: (EditorState)
119
- // Update the editor's `state` prop, without touching any of the
120
- // other props.
121
- updateState(state) {
122
- this.updateStateInner(state, this.state.plugins != state.plugins)
123
- }
124
-
125
- updateStateInner(state, reconfigured) {
126
- let prev = this.state, redraw = false, updateSel = false
127
- // When stored marks are added, stop composition, so that they can
128
- // be displayed.
129
- if (state.storedMarks && this.composing) {
130
- clearComposition(this)
131
- updateSel = true
132
- }
133
- this.state = state
134
- if (reconfigured) {
135
- let nodeViews = buildNodeViews(this)
136
- if (changedNodeViews(nodeViews, this.nodeViews)) {
137
- this.nodeViews = nodeViews
138
- redraw = true
139
- }
140
- ensureListeners(this)
141
- }
142
-
143
- this.editable = getEditable(this)
144
- updateCursorWrapper(this)
145
- let innerDeco = viewDecorations(this), outerDeco = computeDocDeco(this)
146
-
147
- let scroll = reconfigured ? "reset"
148
- : state.scrollToSelection > prev.scrollToSelection ? "to selection" : "preserve"
149
- let updateDoc = redraw || !this.docView.matchesNode(state.doc, outerDeco, innerDeco)
150
- if (updateDoc || !state.selection.eq(prev.selection)) updateSel = true
151
- let oldScrollPos = scroll == "preserve" && updateSel && this.dom.style.overflowAnchor == null && storeScrollPos(this)
152
-
153
- if (updateSel) {
154
- this.domObserver.stop()
155
- // Work around an issue in Chrome, IE, and Edge where changing
156
- // the DOM around an active selection puts it into a broken
157
- // state where the thing the user sees differs from the
158
- // selection reported by the Selection object (#710, #973,
159
- // #1011, #1013, #1035).
160
- let forceSelUpdate = updateDoc && (browser.ie || browser.chrome) && !this.composing &&
161
- !prev.selection.empty && !state.selection.empty && selectionContextChanged(prev.selection, state.selection)
162
- if (updateDoc) {
163
- // If the node that the selection points into is written to,
164
- // Chrome sometimes starts misreporting the selection, so this
165
- // tracks that and forces a selection reset when our update
166
- // did write to the node.
167
- let chromeKludge = browser.chrome ? (this.trackWrites = this.root.getSelection().focusNode) : null
168
- if (redraw || !this.docView.update(state.doc, outerDeco, innerDeco, this)) {
169
- this.docView.updateOuterDeco([])
170
- this.docView.destroy()
171
- this.docView = docViewDesc(state.doc, outerDeco, innerDeco, this.dom, this)
172
- }
173
- if (chromeKludge && !this.trackWrites) forceSelUpdate = true
174
- }
175
- // Work around for an issue where an update arriving right between
176
- // a DOM selection change and the "selectionchange" event for it
177
- // can cause a spurious DOM selection update, disrupting mouse
178
- // drag selection.
179
- if (forceSelUpdate ||
180
- !(this.mouseDown && this.domObserver.currentSelection.eq(this.root.getSelection()) && anchorInRightPlace(this))) {
181
- selectionToDOM(this, forceSelUpdate)
182
- } else {
183
- syncNodeSelection(this, state.selection)
184
- this.domObserver.setCurSelection()
185
- }
186
- this.domObserver.start()
187
- }
188
-
189
- this.updatePluginViews(prev)
190
-
191
- if (scroll == "reset") {
192
- this.dom.scrollTop = 0
193
- } else if (scroll == "to selection") {
194
- let startDOM = this.root.getSelection().focusNode
195
- if (this.someProp("handleScrollToSelection", f => f(this)))
196
- {} // Handled
197
- else if (state.selection instanceof NodeSelection)
198
- scrollRectIntoView(this, this.docView.domAfterPos(state.selection.from).getBoundingClientRect(), startDOM)
199
- else
200
- scrollRectIntoView(this, this.coordsAtPos(state.selection.head, 1), startDOM)
201
- } else if (oldScrollPos) {
202
- resetScrollPos(oldScrollPos)
203
- }
204
- }
205
-
206
- destroyPluginViews() {
207
- let view
208
- while (view = this.pluginViews.pop()) if (view.destroy) view.destroy()
209
- }
210
-
211
- updatePluginViews(prevState) {
212
- if (!prevState || prevState.plugins != this.state.plugins || this.directPlugins != this.prevDirectPlugins) {
213
- this.prevDirectPlugins = this.directPlugins
214
- this.destroyPluginViews()
215
- for (let i = 0; i < this.directPlugins.length; i++) {
216
- let plugin = this.directPlugins[i]
217
- if (plugin.spec.view) this.pluginViews.push(plugin.spec.view(this))
218
- }
219
- for (let i = 0; i < this.state.plugins.length; i++) {
220
- let plugin = this.state.plugins[i]
221
- if (plugin.spec.view) this.pluginViews.push(plugin.spec.view(this))
222
- }
223
- } else {
224
- for (let i = 0; i < this.pluginViews.length; i++) {
225
- let pluginView = this.pluginViews[i]
226
- if (pluginView.update) pluginView.update(this, prevState)
227
- }
228
- }
229
- }
230
-
231
- // :: (string, ?(prop: *) → *) → *
232
- // Goes over the values of a prop, first those provided directly,
233
- // then those from plugins given to the view, then from plugins in
234
- // the state (in order), and calls `f` every time a non-undefined
235
- // value is found. When `f` returns a truthy value, that is
236
- // immediately returned. When `f` isn't provided, it is treated as
237
- // the identity function (the prop value is returned directly).
238
- someProp(propName, f) {
239
- let prop = this._props && this._props[propName], value
240
- if (prop != null && (value = f ? f(prop) : prop)) return value
241
- for (let i = 0; i < this.directPlugins.length; i++) {
242
- let prop = this.directPlugins[i].props[propName]
243
- if (prop != null && (value = f ? f(prop) : prop)) return value
244
- }
245
- let plugins = this.state.plugins
246
- if (plugins) for (let i = 0; i < plugins.length; i++) {
247
- let prop = plugins[i].props[propName]
248
- if (prop != null && (value = f ? f(prop) : prop)) return value
249
- }
250
- }
251
-
252
- // :: () → bool
253
- // Query whether the view has focus.
254
- hasFocus() {
255
- return this.root.activeElement == this.dom
256
- }
257
-
258
- // :: ()
259
- // Focus the editor.
260
- focus() {
261
- this.domObserver.stop()
262
- if (this.editable) focusPreventScroll(this.dom)
263
- selectionToDOM(this)
264
- this.domObserver.start()
265
- }
266
-
267
- // :: union<dom.Document, dom.DocumentFragment>
268
- // Get the document root in which the editor exists. This will
269
- // usually be the top-level `document`, but might be a [shadow
270
- // DOM](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Shadow_DOM)
271
- // root if the editor is inside one.
272
- get root() {
273
- let cached = this._root
274
- if (cached == null) for (let search = this.dom.parentNode; search; search = search.parentNode) {
275
- if (search.nodeType == 9 || (search.nodeType == 11 && search.host)) {
276
- if (!search.getSelection) Object.getPrototypeOf(search).getSelection = () => document.getSelection()
277
- return this._root = search
278
- }
279
- }
280
- return cached || document
281
- }
282
-
283
- // :: ({left: number, top: number}) → ?{pos: number, inside: number}
284
- // Given a pair of viewport coordinates, return the document
285
- // position that corresponds to them. May return null if the given
286
- // coordinates aren't inside of the editor. When an object is
287
- // returned, its `pos` property is the position nearest to the
288
- // coordinates, and its `inside` property holds the position of the
289
- // inner node that the position falls inside of, or -1 if it is at
290
- // the top level, not in any node.
291
- posAtCoords(coords) {
292
- return posAtCoords(this, coords)
293
- }
294
-
295
- // :: (number, number) → {left: number, right: number, top: number, bottom: number}
296
- // Returns the viewport rectangle at a given document position.
297
- // `left` and `right` will be the same number, as this returns a
298
- // flat cursor-ish rectangle. If the position is between two things
299
- // that aren't directly adjacent, `side` determines which element is
300
- // used. When < 0, the element before the position is used,
301
- // otherwise the element after.
302
- coordsAtPos(pos, side = 1) {
303
- return coordsAtPos(this, pos, side)
304
- }
305
-
306
- // :: (number, number) → {node: dom.Node, offset: number}
307
- // Find the DOM position that corresponds to the given document
308
- // position. When `side` is negative, find the position as close as
309
- // possible to the content before the position. When positive,
310
- // prefer positions close to the content after the position. When
311
- // zero, prefer as shallow a position as possible.
312
- //
313
- // Note that you should **not** mutate the editor's internal DOM,
314
- // only inspect it (and even that is usually not necessary).
315
- domAtPos(pos, side = 0) {
316
- return this.docView.domFromPos(pos, side)
317
- }
318
-
319
- // :: (number) → ?dom.Node
320
- // Find the DOM node that represents the document node after the
321
- // given position. May return `null` when the position doesn't point
322
- // in front of a node or if the node is inside an opaque node view.
323
- //
324
- // This is intended to be able to call things like
325
- // `getBoundingClientRect` on that DOM node. Do **not** mutate the
326
- // editor DOM directly, or add styling this way, since that will be
327
- // immediately overriden by the editor as it redraws the node.
328
- nodeDOM(pos) {
329
- let desc = this.docView.descAt(pos)
330
- return desc ? desc.nodeDOM : null
331
- }
332
-
333
- // :: (dom.Node, number, ?number) → number
334
- // Find the document position that corresponds to a given DOM
335
- // position. (Whenever possible, it is preferable to inspect the
336
- // document structure directly, rather than poking around in the
337
- // DOM, but sometimes—for example when interpreting an event
338
- // target—you don't have a choice.)
339
- //
340
- // The `bias` parameter can be used to influence which side of a DOM
341
- // node to use when the position is inside a leaf node.
342
- posAtDOM(node, offset, bias = -1) {
343
- let pos = this.docView.posFromDOM(node, offset, bias)
344
- if (pos == null) throw new RangeError("DOM position not inside the editor")
345
- return pos
346
- }
347
-
348
- // :: (union<"up", "down", "left", "right", "forward", "backward">, ?EditorState) → bool
349
- // Find out whether the selection is at the end of a textblock when
350
- // moving in a given direction. When, for example, given `"left"`,
351
- // it will return true if moving left from the current cursor
352
- // position would leave that position's parent textblock. Will apply
353
- // to the view's current state by default, but it is possible to
354
- // pass a different state.
355
- endOfTextblock(dir, state) {
356
- return endOfTextblock(this, state || this.state, dir)
357
- }
358
-
359
- // :: ()
360
- // Removes the editor from the DOM and destroys all [node
361
- // views](#view.NodeView).
362
- destroy() {
363
- if (!this.docView) return
364
- destroyInput(this)
365
- this.destroyPluginViews()
366
- if (this.mounted) {
367
- this.docView.update(this.state.doc, [], viewDecorations(this), this)
368
- this.dom.textContent = ""
369
- } else if (this.dom.parentNode) {
370
- this.dom.parentNode.removeChild(this.dom)
371
- }
372
- this.docView.destroy()
373
- this.docView = null
374
- }
375
-
376
- // :: boolean
377
- // This is true when the view has been
378
- // [destroyed](#view.EditorView.destroy) (and thus should not be
379
- // used anymore).
380
- get isDestroyed() {
381
- return this.docView == null
382
- }
383
-
384
- // Used for testing.
385
- dispatchEvent(event) {
386
- return dispatchEvent(this, event)
387
- }
388
-
389
- // :: (Transaction)
390
- // Dispatch a transaction. Will call
391
- // [`dispatchTransaction`](#view.DirectEditorProps.dispatchTransaction)
392
- // when given, and otherwise defaults to applying the transaction to
393
- // the current state and calling
394
- // [`updateState`](#view.EditorView.updateState) with the result.
395
- // This method is bound to the view instance, so that it can be
396
- // easily passed around.
397
- dispatch(tr) {
398
- let dispatchTransaction = this._props.dispatchTransaction
399
- if (dispatchTransaction) dispatchTransaction.call(this, tr)
400
- else this.updateState(this.state.apply(tr))
401
- }
402
- }
403
-
404
- function computeDocDeco(view) {
405
- let attrs = Object.create(null)
406
- attrs.class = "ProseMirror"
407
- attrs.contenteditable = String(view.editable)
408
- attrs.translate = "no"
409
-
410
- view.someProp("attributes", value => {
411
- if (typeof value == "function") value = value(view.state)
412
- if (value) for (let attr in value) {
413
- if (attr == "class")
414
- attrs.class += " " + value[attr]
415
- if (attr == "style") {
416
- attrs.style = (attrs.style ? attrs.style + ";" : "") + value[attr]
417
- }
418
- else if (!attrs[attr] && attr != "contenteditable" && attr != "nodeName")
419
- attrs[attr] = String(value[attr])
420
- }
421
- })
422
-
423
- return [Decoration.node(0, view.state.doc.content.size, attrs)]
424
- }
425
-
426
- function updateCursorWrapper(view) {
427
- if (view.markCursor) {
428
- let dom = document.createElement("img")
429
- dom.className = "ProseMirror-separator"
430
- dom.setAttribute("mark-placeholder", "true")
431
- dom.setAttribute("alt", "")
432
- view.cursorWrapper = {dom, deco: Decoration.widget(view.state.selection.head, dom, {raw: true, marks: view.markCursor})}
433
- } else {
434
- view.cursorWrapper = null
435
- }
436
- }
437
-
438
- function getEditable(view) {
439
- return !view.someProp("editable", value => value(view.state) === false)
440
- }
441
-
442
- function selectionContextChanged(sel1, sel2) {
443
- let depth = Math.min(sel1.$anchor.sharedDepth(sel1.head), sel2.$anchor.sharedDepth(sel2.head))
444
- return sel1.$anchor.start(depth) != sel2.$anchor.start(depth)
445
- }
446
-
447
- function buildNodeViews(view) {
448
- let result = {}
449
- view.someProp("nodeViews", obj => {
450
- for (let prop in obj) if (!Object.prototype.hasOwnProperty.call(result, prop))
451
- result[prop] = obj[prop]
452
- })
453
- return result
454
- }
455
-
456
- function changedNodeViews(a, b) {
457
- let nA = 0, nB = 0
458
- for (let prop in a) {
459
- if (a[prop] != b[prop]) return true
460
- nA++
461
- }
462
- for (let _ in b) nB++
463
- return nA != nB
464
- }
465
-
466
- function checkStateComponent(plugin) {
467
- if (plugin.spec.state || plugin.spec.filterTransaction || plugin.spec.appendTransaction)
468
- throw new RangeError("Plugins passed directly to the view must not have a state component")
469
- }
470
-
471
- // EditorProps:: interface
472
- //
473
- // Props are configuration values that can be passed to an editor view
474
- // or included in a plugin. This interface lists the supported props.
475
- //
476
- // The various event-handling functions may all return `true` to
477
- // indicate that they handled the given event. The view will then take
478
- // care to call `preventDefault` on the event, except with
479
- // `handleDOMEvents`, where the handler itself is responsible for that.
480
- //
481
- // How a prop is resolved depends on the prop. Handler functions are
482
- // called one at a time, starting with the base props and then
483
- // searching through the plugins (in order of appearance) until one of
484
- // them returns true. For some props, the first plugin that yields a
485
- // value gets precedence.
486
- //
487
- // handleDOMEvents:: ?Object<(view: EditorView, event: dom.Event) → bool>
488
- // Can be an object mapping DOM event type names to functions that
489
- // handle them. Such functions will be called before any handling
490
- // ProseMirror does of events fired on the editable DOM element.
491
- // Contrary to the other event handling props, when returning true
492
- // from such a function, you are responsible for calling
493
- // `preventDefault` yourself (or not, if you want to allow the
494
- // default behavior).
495
- //
496
- // handleKeyDown:: ?(view: EditorView, event: dom.KeyboardEvent) → bool
497
- // Called when the editor receives a `keydown` event.
498
- //
499
- // handleKeyPress:: ?(view: EditorView, event: dom.KeyboardEvent) → bool
500
- // Handler for `keypress` events.
501
- //
502
- // handleTextInput:: ?(view: EditorView, from: number, to: number, text: string) → bool
503
- // Whenever the user directly input text, this handler is called
504
- // before the input is applied. If it returns `true`, the default
505
- // behavior of actually inserting the text is suppressed.
506
- //
507
- // handleClickOn:: ?(view: EditorView, pos: number, node: Node, nodePos: number, event: dom.MouseEvent, direct: bool) → bool
508
- // Called for each node around a click, from the inside out. The
509
- // `direct` flag will be true for the inner node.
510
- //
511
- // handleClick:: ?(view: EditorView, pos: number, event: dom.MouseEvent) → bool
512
- // Called when the editor is clicked, after `handleClickOn` handlers
513
- // have been called.
514
- //
515
- // handleDoubleClickOn:: ?(view: EditorView, pos: number, node: Node, nodePos: number, event: dom.MouseEvent, direct: bool) → bool
516
- // Called for each node around a double click.
517
- //
518
- // handleDoubleClick:: ?(view: EditorView, pos: number, event: dom.MouseEvent) → bool
519
- // Called when the editor is double-clicked, after `handleDoubleClickOn`.
520
- //
521
- // handleTripleClickOn:: ?(view: EditorView, pos: number, node: Node, nodePos: number, event: dom.MouseEvent, direct: bool) → bool
522
- // Called for each node around a triple click.
523
- //
524
- // handleTripleClick:: ?(view: EditorView, pos: number, event: dom.MouseEvent) → bool
525
- // Called when the editor is triple-clicked, after `handleTripleClickOn`.
526
- //
527
- // handlePaste:: ?(view: EditorView, event: dom.ClipboardEvent, slice: Slice) → bool
528
- // Can be used to override the behavior of pasting. `slice` is the
529
- // pasted content parsed by the editor, but you can directly access
530
- // the event to get at the raw content.
531
- //
532
- // handleDrop:: ?(view: EditorView, event: dom.Event, slice: Slice, moved: bool) → bool
533
- // Called when something is dropped on the editor. `moved` will be
534
- // true if this drop moves from the current selection (which should
535
- // thus be deleted).
536
- //
537
- // handleScrollToSelection:: ?(view: EditorView) → bool
538
- // Called when the view, after updating its state, tries to scroll
539
- // the selection into view. A handler function may return false to
540
- // indicate that it did not handle the scrolling and further
541
- // handlers or the default behavior should be tried.
542
- //
543
- // createSelectionBetween:: ?(view: EditorView, anchor: ResolvedPos, head: ResolvedPos) → ?Selection
544
- // Can be used to override the way a selection is created when
545
- // reading a DOM selection between the given anchor and head.
546
- //
547
- // domParser:: ?DOMParser
548
- // The [parser](#model.DOMParser) to use when reading editor changes
549
- // from the DOM. Defaults to calling
550
- // [`DOMParser.fromSchema`](#model.DOMParser^fromSchema) on the
551
- // editor's schema.
552
- //
553
- // transformPastedHTML:: ?(html: string) → string
554
- // Can be used to transform pasted HTML text, _before_ it is parsed,
555
- // for example to clean it up.
556
- //
557
- // clipboardParser:: ?DOMParser
558
- // The [parser](#model.DOMParser) to use when reading content from
559
- // the clipboard. When not given, the value of the
560
- // [`domParser`](#view.EditorProps.domParser) prop is used.
561
- //
562
- // transformPastedText:: ?(text: string, plain: bool) → string
563
- // Transform pasted plain text. The `plain` flag will be true when
564
- // the text is pasted as plain text.
565
- //
566
- // clipboardTextParser:: ?(text: string, $context: ResolvedPos, plain: bool) → Slice
567
- // A function to parse text from the clipboard into a document
568
- // slice. Called after
569
- // [`transformPastedText`](#view.EditorProps.transformPastedText).
570
- // The default behavior is to split the text into lines, wrap them
571
- // in `<p>` tags, and call
572
- // [`clipboardParser`](#view.EditorProps.clipboardParser) on it.
573
- // The `plain` flag will be true when the text is pasted as plain text.
574
- //
575
- // transformPasted:: ?(Slice) → Slice
576
- // Can be used to transform pasted content before it is applied to
577
- // the document.
578
- //
579
- // nodeViews:: ?Object<(node: Node, view: EditorView, getPos: () → number, decorations: [Decoration], innerDecorations: DecorationSource) → NodeView>
580
- // Allows you to pass custom rendering and behavior logic for nodes
581
- // and marks. Should map node and mark names to constructor
582
- // functions that produce a [`NodeView`](#view.NodeView) object
583
- // implementing the node's display behavior. For nodes, the third
584
- // argument `getPos` is a function that can be called to get the
585
- // node's current position, which can be useful when creating
586
- // transactions to update it. For marks, the third argument is a
587
- // boolean that indicates whether the mark's content is inline.
588
- //
589
- // `decorations` is an array of node or inline decorations that are
590
- // active around the node. They are automatically drawn in the
591
- // normal way, and you will usually just want to ignore this, but
592
- // they can also be used as a way to provide context information to
593
- // the node view without adding it to the document itself.
594
- //
595
- // `innerDecorations` holds the decorations for the node's content.
596
- // You can safely ignore this if your view has no content or a
597
- // `contentDOM` property, since the editor will draw the decorations
598
- // on the content. But if you, for example, want to create a nested
599
- // editor with the content, it may make sense to provide it with the
600
- // inner decorations.
601
- //
602
- // clipboardSerializer:: ?DOMSerializer
603
- // The DOM serializer to use when putting content onto the
604
- // clipboard. If not given, the result of
605
- // [`DOMSerializer.fromSchema`](#model.DOMSerializer^fromSchema)
606
- // will be used. This object will only have its
607
- // [`serializeFragment`](#model.DOMSerializer.serializeFragment)
608
- // method called, and you may provide an alternative object type
609
- // implementing a compatible method.
610
- //
611
- // clipboardTextSerializer:: ?(Slice) → string
612
- // A function that will be called to get the text for the current
613
- // selection when copying text to the clipboard. By default, the
614
- // editor will use [`textBetween`](#model.Node.textBetween) on the
615
- // selected range.
616
- //
617
- // decorations:: ?(state: EditorState) → ?DecorationSource
618
- // A set of [document decorations](#view.Decoration) to show in the
619
- // view.
620
- //
621
- // editable:: ?(state: EditorState) → bool
622
- // When this returns false, the content of the view is not directly
623
- // editable.
624
- //
625
- // attributes:: ?union<Object<string>, (EditorState) → ?Object<string>>
626
- // Control the DOM attributes of the editable element. May be either
627
- // an object or a function going from an editor state to an object.
628
- // By default, the element will get a class `"ProseMirror"`, and
629
- // will have its `contentEditable` attribute determined by the
630
- // [`editable` prop](#view.EditorProps.editable). Additional classes
631
- // provided here will be added to the class. For other attributes,
632
- // the value provided first (as in
633
- // [`someProp`](#view.EditorView.someProp)) will be used.
634
- //
635
- // scrollThreshold:: ?union<number, {top: number, right: number, bottom: number, left: number}>
636
- // Determines the distance (in pixels) between the cursor and the
637
- // end of the visible viewport at which point, when scrolling the
638
- // cursor into view, scrolling takes place. Defaults to 0.
639
- //
640
- // scrollMargin:: ?union<number, {top: number, right: number, bottom: number, left: number}>
641
- // Determines the extra space (in pixels) that is left above or
642
- // below the cursor when it is scrolled into view. Defaults to 5.
643
-
644
- // DirectEditorProps:: interface extends EditorProps
645
- //
646
- // The props object given directly to the editor view supports some
647
- // fields that can't be used in plugins:
648
- //
649
- // state:: EditorState
650
- // The current state of the editor.
651
- //
652
- // plugins:: [Plugin]
653
- // A set of plugins to use in the view, applying their [plugin
654
- // view](#state.PluginSpec.view) and
655
- // [props](#state.PluginSpec.props). Passing plugins with a state
656
- // component (a [state field](#state.PluginSpec.state) field or a
657
- // [transaction](#state.PluginSpec.filterTransaction) filter or
658
- // appender) will result in an error, since such plugins must be
659
- // present in the state to work.
660
- //
661
- // dispatchTransaction:: ?(tr: Transaction)
662
- // The callback over which to send transactions (state updates)
663
- // produced by the view. If you specify this, you probably want to
664
- // make sure this ends up calling the view's
665
- // [`updateState`](#view.EditorView.updateState) method with a new
666
- // state that has the transaction
667
- // [applied](#state.EditorState.apply). The callback will be bound to have
668
- // the view instance as its `this` binding.