@handlewithcare/react-prosemirror 2.8.0-tiptap.10 → 2.8.0-tiptap.12

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.
Files changed (63) hide show
  1. package/dist/cjs/tiptap/TiptapEditorView.js +2 -1
  2. package/dist/cjs/tiptap/tiptapNodeView.js +26 -13
  3. package/dist/esm/tiptap/TiptapEditorView.js +2 -1
  4. package/dist/esm/tiptap/tiptapNodeView.js +27 -14
  5. package/dist/tsconfig.tsbuildinfo +1 -1
  6. package/dist/types/constants.d.ts +1 -1
  7. package/dist/types/props.d.ts +26 -26
  8. package/dist/types/tiptap/TiptapEditorView.d.ts +2 -1
  9. package/package.json +1 -1
  10. package/dist/esm/@jest/pattern/src/__tests__/TestPathPatterns.test.js +0 -241
  11. package/dist/esm/@swc/cli/lib/swc/__tests__/compile.test.js +0 -19
  12. package/dist/esm/@swc/cli/lib/swc/__tests__/options.test.js +0 -315
  13. package/dist/esm/@swc/cli/lib/swc/__tests__/sources.test.js +0 -161
  14. package/dist/esm/@uiw/react-codemirror/src/__tests__/index.test.js +0 -111
  15. package/dist/esm/cheerio/src/__tests__/deprecated.spec.js +0 -249
  16. package/dist/esm/cheerio/src/__tests__/xml.spec.js +0 -55
  17. package/dist/esm/components/__tests__/ProseMirror.composition.test.js +0 -395
  18. package/dist/esm/components/__tests__/ProseMirror.domchange.test.js +0 -266
  19. package/dist/esm/components/__tests__/ProseMirror.draw-decoration.test.js +0 -968
  20. package/dist/esm/components/__tests__/ProseMirror.draw.test.js +0 -335
  21. package/dist/esm/components/__tests__/ProseMirror.mobile.test.js +0 -54
  22. package/dist/esm/components/__tests__/ProseMirror.node-view.test.js +0 -553
  23. package/dist/esm/components/__tests__/ProseMirror.selection.test.js +0 -440
  24. package/dist/esm/components/__tests__/ProseMirror.test.js +0 -324
  25. package/dist/esm/contexts/__tests__/DeferredLayoutEffects.test.js +0 -98
  26. package/dist/esm/hooks/__tests__/useEditorEffect.test.js +0 -134
  27. package/dist/esm/jsx-ast-utils/__tests__/helper.js +0 -83
  28. package/dist/esm/jsx-ast-utils/__tests__/src/elementType-test.js +0 -76
  29. package/dist/esm/jsx-ast-utils/__tests__/src/eventHandlers-test.js +0 -98
  30. package/dist/esm/jsx-ast-utils/__tests__/src/getProp-parser-test.js +0 -188
  31. package/dist/esm/jsx-ast-utils/__tests__/src/getProp-test.js +0 -119
  32. package/dist/esm/jsx-ast-utils/__tests__/src/getPropLiteralValue-babelparser-test.js +0 -393
  33. package/dist/esm/jsx-ast-utils/__tests__/src/getPropLiteralValue-flowparser-test.js +0 -379
  34. package/dist/esm/jsx-ast-utils/__tests__/src/getPropValue-babelparser-test.js +0 -925
  35. package/dist/esm/jsx-ast-utils/__tests__/src/getPropValue-flowparser-test.js +0 -700
  36. package/dist/esm/jsx-ast-utils/__tests__/src/hasProp-test.js +0 -350
  37. package/dist/esm/jsx-ast-utils/__tests__/src/index-test.js +0 -24
  38. package/dist/esm/jsx-ast-utils/__tests__/src/propName-test.js +0 -37
  39. package/dist/esm/plugins/__tests__/reactKeys.test.js +0 -77
  40. package/dist/esm/tsconfig-paths/lib/__tests__/config-loader.test.d.js +0 -1
  41. package/dist/esm/tsconfig-paths/lib/__tests__/config-loader.test.js +0 -97
  42. package/dist/esm/tsconfig-paths/lib/__tests__/data/match-path-data.d.js +0 -1
  43. package/dist/esm/tsconfig-paths/lib/__tests__/data/match-path-data.js +0 -319
  44. package/dist/esm/tsconfig-paths/lib/__tests__/filesystem.test.d.js +0 -1
  45. package/dist/esm/tsconfig-paths/lib/__tests__/filesystem.test.js +0 -62
  46. package/dist/esm/tsconfig-paths/lib/__tests__/mapping-entry.test.d.js +0 -1
  47. package/dist/esm/tsconfig-paths/lib/__tests__/mapping-entry.test.js +0 -80
  48. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-async.test.d.js +0 -1
  49. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-async.test.js +0 -22
  50. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-sync.test.d.js +0 -1
  51. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-sync.test.js +0 -20
  52. package/dist/esm/tsconfig-paths/lib/__tests__/try-path.test.d.js +0 -1
  53. package/dist/esm/tsconfig-paths/lib/__tests__/try-path.test.js +0 -219
  54. package/dist/esm/tsconfig-paths/lib/__tests__/tsconfig-loader.test.d.js +0 -1
  55. package/dist/esm/tsconfig-paths/lib/__tests__/tsconfig-loader.test.js +0 -323
  56. package/dist/esm/tsconfig-paths/src/__tests__/config-loader.test.js +0 -89
  57. package/dist/esm/tsconfig-paths/src/__tests__/data/match-path-data.js +0 -314
  58. package/dist/esm/tsconfig-paths/src/__tests__/filesystem.test.js +0 -58
  59. package/dist/esm/tsconfig-paths/src/__tests__/mapping-entry.test.js +0 -76
  60. package/dist/esm/tsconfig-paths/src/__tests__/match-path-async.test.js +0 -12
  61. package/dist/esm/tsconfig-paths/src/__tests__/match-path-sync.test.js +0 -10
  62. package/dist/esm/tsconfig-paths/src/__tests__/try-path.test.js +0 -214
  63. package/dist/esm/tsconfig-paths/src/__tests__/tsconfig-loader.test.js +0 -296
@@ -1,968 +0,0 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-non-null-assertion */ // TODO: figure out whether it's possible to support native
2
- // widgets. Right now, I'm not sure how we'd do it without
3
- // wrapping them in another element, which would re-introduce
4
- // all of the issues we had before with node views.
5
- //
6
- // For now, we've updated the factory in this file to use
7
- // our React widgets.
8
- import { Schema } from "prosemirror-model";
9
- import { Plugin, TextSelection } from "prosemirror-state";
10
- import { blockquote, doc, em, h1, hr, img, p, schema, strong } from "prosemirror-test-builder";
11
- import { Decoration, DecorationSet } from "prosemirror-view";
12
- import React, { forwardRef, useEffect } from "react";
13
- import { widget } from "../../decorations/ReactWidgetType.js";
14
- import { useEditorEffect } from "../../hooks/useEditorEffect.js";
15
- import { tempEditor } from "../../testing/editorViewTestHelpers.js";
16
- const Widget = /*#__PURE__*/ forwardRef(function Widget(param, ref) {
17
- let { widget, getPos, ...props } = param;
18
- return /*#__PURE__*/ React.createElement("button", {
19
- ref: ref,
20
- ...props
21
- }, "ω");
22
- });
23
- function make(str) {
24
- if (typeof str != "string") return str;
25
- const match = /^(\d+)(?:-(\d+))?-(.+)$/.exec(str);
26
- if (match[3] == "widget") {
27
- return widget(+match[1], Widget, {
28
- key: str
29
- });
30
- }
31
- return Decoration.inline(+match[1], +match[2], {
32
- class: match[3]
33
- });
34
- }
35
- function decoPlugin(decos) {
36
- return new Plugin({
37
- state: {
38
- init (config) {
39
- return config.doc ? DecorationSet.create(config.doc, decos.map(make)) : DecorationSet.empty;
40
- },
41
- apply (tr, set, state) {
42
- if (tr.docChanged) set = set.map(tr.mapping, tr.doc);
43
- const change = tr.getMeta("updateDecorations");
44
- if (change) {
45
- if (change.remove) set = set.remove(change.remove);
46
- if (change.add) set = set.add(state.doc, change.add);
47
- }
48
- return set;
49
- }
50
- },
51
- props: {
52
- decorations (state) {
53
- return this.getState(state);
54
- }
55
- }
56
- });
57
- }
58
- function updateDeco(view, add, remove) {
59
- view.dispatch(view.state.tr.setMeta("updateDecorations", {
60
- add,
61
- remove
62
- }));
63
- }
64
- describe("Decoration drawing", ()=>{
65
- it("draws inline decorations", async ()=>{
66
- const { view } = tempEditor({
67
- doc: doc(p("foobar")),
68
- plugins: [
69
- decoPlugin([
70
- "2-5-foo"
71
- ])
72
- ]
73
- });
74
- const found = view.dom.querySelector(".foo");
75
- await expect(found).not.toBeNull();
76
- await expect(found.textContent).toBe("oob");
77
- });
78
- it("draws wrapping decorations", async ()=>{
79
- const { view } = tempEditor({
80
- doc: doc(p("foo")),
81
- plugins: [
82
- decoPlugin([
83
- Decoration.inline(1, 5, {
84
- nodeName: "i"
85
- })
86
- ])
87
- ]
88
- });
89
- const found = view.dom.querySelector("i");
90
- expect(found && found.innerHTML).toBe("foo");
91
- });
92
- it("draws node decorations", async ()=>{
93
- const { view } = tempEditor({
94
- doc: doc(p("foo"), p("bar")),
95
- plugins: [
96
- decoPlugin([
97
- Decoration.node(5, 10, {
98
- class: "cls"
99
- })
100
- ])
101
- ]
102
- });
103
- const found = view.dom.querySelectorAll(".cls");
104
- expect(found).toHaveLength(1);
105
- expect(found[0].nodeName).toBe("P");
106
- expect(found[0].previousSibling.nodeName).toBe("P");
107
- });
108
- it("can update multi-level wrapping decorations", async ()=>{
109
- const d2 = Decoration.inline(1, 5, {
110
- nodeName: "i",
111
- class: "b"
112
- });
113
- const { view } = tempEditor({
114
- doc: doc(p("hello")),
115
- plugins: [
116
- decoPlugin([
117
- Decoration.inline(1, 5, {
118
- nodeName: "i",
119
- class: "a"
120
- }),
121
- d2
122
- ])
123
- ]
124
- });
125
- expect(view.dom.querySelectorAll("i")).toHaveLength(2);
126
- updateDeco(view, [
127
- Decoration.inline(1, 5, {
128
- nodeName: "i",
129
- class: "c"
130
- })
131
- ], [
132
- d2
133
- ]);
134
- const iNodes = view.dom.querySelectorAll("i");
135
- expect(iNodes).toHaveLength(2);
136
- expect(Array.prototype.map.call(iNodes, (n)=>n.className).sort().join()).toBe("a,c");
137
- });
138
- it("draws overlapping inline decorations", async ()=>{
139
- const { view } = tempEditor({
140
- doc: doc(p("abcdef")),
141
- plugins: [
142
- decoPlugin([
143
- "3-5-foo",
144
- "4-6-bar",
145
- "1-7-baz"
146
- ])
147
- ]
148
- });
149
- const baz = view.dom.querySelectorAll(".baz");
150
- expect(baz).toHaveLength(5);
151
- expect(Array.prototype.map.call(baz, (x)=>x.textContent).join("-")).toBe("ab-c-d-e-f");
152
- function classes(n) {
153
- return n.className.split(" ").sort().join(" ");
154
- }
155
- expect(classes(baz[1])).toBe("baz foo");
156
- expect(classes(baz[2])).toBe("bar baz foo");
157
- expect(classes(baz[3])).toBe("bar baz");
158
- });
159
- it("draws multiple widgets", async ()=>{
160
- const { view } = tempEditor({
161
- doc: doc(p("foobar")),
162
- plugins: [
163
- decoPlugin([
164
- "1-widget",
165
- "4-widget",
166
- "7-widget"
167
- ])
168
- ]
169
- });
170
- const found = view.dom.querySelectorAll("button");
171
- expect(found).toHaveLength(3);
172
- expect(found[0].nextSibling.textContent).toBe("foo");
173
- expect(found[1].nextSibling.textContent).toBe("bar");
174
- expect(found[2].previousSibling.textContent).toBe("bar");
175
- });
176
- it("orders widgets by their side option", async ()=>{
177
- const { view } = tempEditor({
178
- doc: doc(p("foobar")),
179
- plugins: [
180
- decoPlugin([
181
- widget(4, /*#__PURE__*/ forwardRef(function B(param, ref) {
182
- let { widget, getPos, ...props } = param;
183
- return /*#__PURE__*/ React.createElement("span", {
184
- ref: ref,
185
- ...props
186
- }, "B");
187
- }), {
188
- key: "widget-b"
189
- }),
190
- widget(4, /*#__PURE__*/ forwardRef(function A(param, ref) {
191
- let { widget, getPos, ...props } = param;
192
- return /*#__PURE__*/ React.createElement("span", {
193
- ref: ref,
194
- ...props
195
- }, "A");
196
- }), {
197
- side: -100,
198
- key: "widget-a"
199
- }),
200
- widget(4, /*#__PURE__*/ forwardRef(function C(param, ref) {
201
- let { widget, getPos, ...props } = param;
202
- return /*#__PURE__*/ React.createElement("span", {
203
- ref: ref,
204
- ...props
205
- }, "C");
206
- }), {
207
- side: 2,
208
- key: "widget-c"
209
- })
210
- ])
211
- ]
212
- });
213
- expect(view.dom.textContent).toBe("fooABCbar");
214
- });
215
- it("draws a widget in an empty node", async ()=>{
216
- const { view } = tempEditor({
217
- doc: doc(p()),
218
- plugins: [
219
- decoPlugin([
220
- "1-widget"
221
- ])
222
- ]
223
- });
224
- expect(view.dom.querySelectorAll("button")).toHaveLength(1);
225
- });
226
- it("draws widgets on node boundaries", async ()=>{
227
- const { view } = tempEditor({
228
- doc: doc(p("foo", em("bar"))),
229
- plugins: [
230
- decoPlugin([
231
- "4-widget"
232
- ])
233
- ]
234
- });
235
- expect(view.dom.querySelectorAll("button")).toHaveLength(1);
236
- });
237
- it("draws decorations from multiple plugins", async ()=>{
238
- const { view } = tempEditor({
239
- doc: doc(p("foo", em("bar"))),
240
- plugins: [
241
- decoPlugin([
242
- "2-widget"
243
- ]),
244
- decoPlugin([
245
- "6-widget"
246
- ])
247
- ]
248
- });
249
- expect(view.dom.querySelectorAll("button")).toHaveLength(2);
250
- });
251
- it("calls widget destroy methods", async ()=>{
252
- let destroyed = false;
253
- const DestroyableWidget = /*#__PURE__*/ forwardRef(function DestroyableWidget(param, ref) {
254
- let { widget, getPos, ...props } = param;
255
- useEffect(()=>{
256
- destroyed = true;
257
- });
258
- return /*#__PURE__*/ React.createElement("button", {
259
- ref: ref,
260
- ...props
261
- });
262
- });
263
- const { view } = tempEditor({
264
- doc: doc(p("abc")),
265
- plugins: [
266
- decoPlugin([
267
- widget(2, DestroyableWidget, {
268
- key: "destroyable-widget"
269
- })
270
- ])
271
- ]
272
- });
273
- view.dispatch(view.state.tr.delete(1, 4));
274
- expect(destroyed).toBeTruthy();
275
- });
276
- it("draws inline decorations spanning multiple parents", async ()=>{
277
- const { view } = tempEditor({
278
- doc: doc(p("long first ", em("p"), "aragraph"), p("two")),
279
- plugins: [
280
- decoPlugin([
281
- "7-25-foo"
282
- ])
283
- ]
284
- });
285
- const foos = view.dom.querySelectorAll(".foo");
286
- expect(foos).toHaveLength(4);
287
- expect(foos[0].textContent).toBe("irst ");
288
- expect(foos[1].textContent).toBe("p");
289
- expect(foos[2].textContent).toBe("aragraph");
290
- expect(foos[3].textContent).toBe("tw");
291
- });
292
- it("draws inline decorations across empty paragraphs", async ()=>{
293
- const { view } = tempEditor({
294
- doc: doc(p("first"), p(), p("second")),
295
- plugins: [
296
- decoPlugin([
297
- "3-12-foo"
298
- ])
299
- ]
300
- });
301
- const foos = view.dom.querySelectorAll(".foo");
302
- expect(foos).toHaveLength(2);
303
- expect(foos[0].textContent).toBe("rst");
304
- expect(foos[1].textContent).toBe("se");
305
- });
306
- it("can handle inline decorations ending at the start or end of a node", async ()=>{
307
- const { view } = tempEditor({
308
- doc: doc(p(), p()),
309
- plugins: [
310
- decoPlugin([
311
- "1-3-foo"
312
- ])
313
- ]
314
- });
315
- expect(view.dom.querySelector(".foo")).toBeNull();
316
- });
317
- it("can draw decorations with multiple classes", async ()=>{
318
- const { view } = tempEditor({
319
- doc: doc(p("foo")),
320
- plugins: [
321
- decoPlugin([
322
- "1-4-foo bar"
323
- ])
324
- ]
325
- });
326
- expect(view.dom.querySelectorAll(".foo")).toHaveLength(1);
327
- expect(view.dom.querySelectorAll(".bar")).toHaveLength(1);
328
- });
329
- it("supports overlapping inline decorations", async ()=>{
330
- const { view } = tempEditor({
331
- doc: doc(p("foobar")),
332
- plugins: [
333
- decoPlugin([
334
- "1-3-foo",
335
- "2-5-bar"
336
- ])
337
- ]
338
- });
339
- const foos = view.dom.querySelectorAll(".foo");
340
- const bars = view.dom.querySelectorAll(".bar");
341
- expect(foos).toHaveLength(2);
342
- expect(bars).toHaveLength(2);
343
- expect(foos[0].textContent).toBe("f");
344
- expect(foos[1].textContent).toBe("o");
345
- expect(bars[0].textContent).toBe("o");
346
- expect(bars[1].textContent).toBe("ob");
347
- });
348
- it("doesn't redraw when irrelevant decorations change", async ()=>{
349
- const { view } = tempEditor({
350
- doc: doc(p("foo"), p("baz")),
351
- plugins: [
352
- decoPlugin([
353
- "7-8-foo"
354
- ])
355
- ]
356
- });
357
- const para2 = view.dom.lastChild;
358
- updateDeco(view, [
359
- make("2-3-bar")
360
- ]);
361
- expect(view.dom.lastChild).toBe(para2);
362
- expect(view.dom.querySelector(".bar")).not.toBeNull();
363
- });
364
- it("doesn't redraw when irrelevant content changes", async ()=>{
365
- const { view } = tempEditor({
366
- doc: doc(p("foo"), p("baz")),
367
- plugins: [
368
- decoPlugin([
369
- "7-8-foo"
370
- ])
371
- ]
372
- });
373
- const para2 = view.dom.lastChild;
374
- view.dispatch(view.state.tr.delete(2, 3));
375
- view.dispatch(view.state.tr.delete(2, 3));
376
- expect(view.dom.lastChild).toBe(para2);
377
- });
378
- it("can add a widget on a node boundary", async ()=>{
379
- const { view } = tempEditor({
380
- doc: doc(p("foo", em("bar"))),
381
- plugins: [
382
- decoPlugin([])
383
- ]
384
- });
385
- updateDeco(view, [
386
- make("4-widget")
387
- ]);
388
- expect(view.dom.querySelectorAll("button")).toHaveLength(1);
389
- });
390
- it("can remove a widget on a node boundary", async ()=>{
391
- const dec = make("4-widget");
392
- const { view } = tempEditor({
393
- doc: doc(p("foo", em("bar"))),
394
- plugins: [
395
- decoPlugin([
396
- dec
397
- ])
398
- ]
399
- });
400
- updateDeco(view, null, [
401
- dec
402
- ]);
403
- expect(view.dom.querySelector("button")).toBeNull();
404
- });
405
- it("can remove the class from a text node", async ()=>{
406
- const dec = make("1-4-foo");
407
- const { view } = tempEditor({
408
- doc: doc(p("abc")),
409
- plugins: [
410
- decoPlugin([
411
- dec
412
- ])
413
- ]
414
- });
415
- expect(view.dom.querySelector(".foo")).not.toBeNull();
416
- updateDeco(view, null, [
417
- dec
418
- ]);
419
- expect(view.dom.querySelector(".foo")).toBeNull();
420
- });
421
- it("can remove the class from part of a text node", async ()=>{
422
- const dec = make("2-4-foo");
423
- const { view } = tempEditor({
424
- doc: doc(p("abcd")),
425
- plugins: [
426
- decoPlugin([
427
- dec
428
- ])
429
- ]
430
- });
431
- expect(view.dom.querySelector(".foo")).not.toBeNull();
432
- updateDeco(view, null, [
433
- dec
434
- ]);
435
- expect(view.dom.querySelector(".foo")).toBeNull();
436
- expect(view.dom.firstChild.innerHTML).toBe("abcd");
437
- });
438
- it("can change the class for part of a text node", async ()=>{
439
- const dec = make("2-4-foo");
440
- const { view } = tempEditor({
441
- doc: doc(p("abcd")),
442
- plugins: [
443
- decoPlugin([
444
- dec
445
- ])
446
- ]
447
- });
448
- expect(view.dom.querySelector(".foo")).not.toBeNull();
449
- updateDeco(view, [
450
- make("2-4-bar")
451
- ], [
452
- dec
453
- ]);
454
- expect(view.dom.querySelector(".foo")).toBeNull();
455
- expect(view.dom.querySelector(".bar")).not.toBeNull();
456
- });
457
- it("draws a widget added in the middle of a text node", async ()=>{
458
- const { view } = tempEditor({
459
- doc: doc(p("foo")),
460
- plugins: [
461
- decoPlugin([])
462
- ]
463
- });
464
- updateDeco(view, [
465
- make("3-widget")
466
- ]);
467
- expect(view.dom.firstChild.textContent).toBe("foωo");
468
- });
469
- it("can update a text node around a widget", async ()=>{
470
- const { view } = tempEditor({
471
- doc: doc(p("bar")),
472
- plugins: [
473
- decoPlugin([
474
- "3-widget"
475
- ])
476
- ]
477
- });
478
- view.dispatch(view.state.tr.delete(1, 2));
479
- expect(view.dom.querySelectorAll("button")).toHaveLength(1);
480
- expect(view.dom.firstChild.textContent).toBe("aωr");
481
- });
482
- it("can update a text node with an inline decoration", async ()=>{
483
- const { view } = tempEditor({
484
- doc: doc(p("bar")),
485
- plugins: [
486
- decoPlugin([
487
- "1-3-foo"
488
- ])
489
- ]
490
- });
491
- view.dispatch(view.state.tr.delete(1, 2));
492
- const foo = view.dom.querySelector(".foo");
493
- expect(foo).not.toBeNull();
494
- expect(foo.textContent).toBe("a");
495
- expect(foo.nextSibling.textContent).toBe("r");
496
- });
497
- it("correctly redraws a partially decorated node when a widget is added", async ()=>{
498
- const { view } = tempEditor({
499
- doc: doc(p("one", em("two"))),
500
- plugins: [
501
- decoPlugin([
502
- "1-6-foo"
503
- ])
504
- ]
505
- });
506
- updateDeco(view, [
507
- make("6-widget")
508
- ]);
509
- const foos = view.dom.querySelectorAll(".foo");
510
- expect(foos).toHaveLength(2);
511
- expect(foos[0].textContent).toBe("one");
512
- expect(foos[1].textContent).toBe("tw");
513
- });
514
- it("correctly redraws when skipping split text node", async ()=>{
515
- const { view } = tempEditor({
516
- doc: doc(p("foo")),
517
- plugins: [
518
- decoPlugin([
519
- "3-widget",
520
- "3-4-foo"
521
- ])
522
- ]
523
- });
524
- updateDeco(view, [
525
- make("4-widget")
526
- ]);
527
- expect(view.dom.querySelectorAll("button")).toHaveLength(2);
528
- });
529
- it("drops removed node decorations from the view", async ()=>{
530
- const deco = Decoration.node(1, 6, {
531
- class: "cls"
532
- });
533
- const { view } = tempEditor({
534
- doc: doc(blockquote(p("foo"), p("bar"))),
535
- plugins: [
536
- decoPlugin([
537
- deco
538
- ])
539
- ]
540
- });
541
- updateDeco(view, null, [
542
- deco
543
- ]);
544
- expect(view.dom.querySelector(".cls")).toBeNull();
545
- });
546
- it("can update a node's attributes without replacing the node", async ()=>{
547
- const deco = Decoration.node(0, 5, {
548
- title: "title",
549
- class: "foo"
550
- });
551
- const { view } = tempEditor({
552
- doc: doc(p("foo")),
553
- plugins: [
554
- decoPlugin([
555
- deco
556
- ])
557
- ]
558
- });
559
- const para = view.dom.querySelector("p");
560
- updateDeco(view, [
561
- Decoration.node(0, 5, {
562
- class: "foo bar"
563
- })
564
- ], [
565
- deco
566
- ]);
567
- expect(view.dom.querySelector("p")).toBe(para);
568
- expect(para.className).toBe("foo bar");
569
- expect(para.title).toBeFalsy();
570
- });
571
- it("can add and remove CSS custom properties from a node", async ()=>{
572
- const deco = Decoration.node(0, 5, {
573
- style: "--my-custom-property:36px"
574
- });
575
- const { view } = tempEditor({
576
- doc: doc(p("foo")),
577
- plugins: [
578
- decoPlugin([
579
- deco
580
- ])
581
- ]
582
- });
583
- expect(view.dom.querySelector("p").style.getPropertyValue("--my-custom-property").trim()).toBe("36px");
584
- updateDeco(view, null, [
585
- deco
586
- ]);
587
- expect(view.dom.querySelector("p").style.getPropertyValue("--my-custom-property").trim()).toBe("");
588
- });
589
- it("updates decorated nodes even if a widget is added before them", async ()=>{
590
- const { view } = tempEditor({
591
- doc: doc(p("a"), p("b")),
592
- plugins: [
593
- decoPlugin([])
594
- ]
595
- });
596
- const lastP = view.dom.querySelectorAll("p")[1];
597
- updateDeco(view, [
598
- make("3-widget"),
599
- Decoration.node(3, 6, {
600
- style: "color: red"
601
- })
602
- ]);
603
- expect(lastP.style.color).toBe("red");
604
- });
605
- it("doesn't redraw nodes when a widget before them is replaced", async ()=>{
606
- const w0 = make("3-widget");
607
- const { view } = tempEditor({
608
- doc: doc(h1("a"), p("b")),
609
- plugins: [
610
- decoPlugin([
611
- w0
612
- ])
613
- ]
614
- });
615
- const initialP = view.dom.querySelector("p");
616
- view.dispatch(view.state.tr.setMeta("updateDecorations", {
617
- add: [
618
- make("3-widget")
619
- ],
620
- remove: [
621
- w0
622
- ]
623
- }).insertText("c", 5));
624
- expect(view.dom.querySelector("p")).toBe(initialP);
625
- });
626
- it("can add and remove inline style", async ()=>{
627
- const deco = Decoration.inline(1, 6, {
628
- style: "color: rgba(0,10,200,.4); text-decoration: underline"
629
- });
630
- const { view } = tempEditor({
631
- doc: doc(p("al", img(), "lo")),
632
- plugins: [
633
- decoPlugin([
634
- deco
635
- ])
636
- ]
637
- });
638
- expect(view.dom.querySelector("img").style.color).toMatch(/rgba/);
639
- expect(view.dom.querySelector("img").previousSibling.style.textDecoration).toBe("underline");
640
- updateDeco(view, null, [
641
- deco
642
- ]);
643
- expect(view.dom.querySelector("img").style.color).toBe("");
644
- expect(view.dom.querySelector("img").style.textDecoration).toBe("");
645
- });
646
- it("passes decorations to a node view", async ()=>{
647
- let current = "";
648
- const { view } = tempEditor({
649
- doc: doc(p("foo"), hr()),
650
- plugins: [
651
- decoPlugin([])
652
- ],
653
- nodeViews: {
654
- horizontal_rule: /*#__PURE__*/ forwardRef(function HR(param, ref) {
655
- let { nodeProps, children, ...props } = param;
656
- current = nodeProps.decorations.map((d)=>d.spec.name).join();
657
- return /*#__PURE__*/ React.createElement("hr", {
658
- ...props,
659
- ref: ref
660
- });
661
- })
662
- }
663
- });
664
- const a = Decoration.node(5, 6, {}, {
665
- name: "a"
666
- });
667
- updateDeco(view, [
668
- a
669
- ], []);
670
- expect(current).toBe("a");
671
- updateDeco(view, [
672
- Decoration.node(5, 6, {}, {
673
- name: "b"
674
- }),
675
- Decoration.node(5, 6, {}, {
676
- name: "c"
677
- })
678
- ], [
679
- a
680
- ]);
681
- expect(current).toBe("b,c");
682
- });
683
- it("draws the specified marks around a widget", async ()=>{
684
- const { view } = tempEditor({
685
- doc: doc(p("foobar")),
686
- plugins: [
687
- decoPlugin([
688
- widget(4, /*#__PURE__*/ forwardRef(function Img(param, ref) {
689
- let { widget, getPos, ...props } = param;
690
- return /*#__PURE__*/ React.createElement("img", {
691
- ...props,
692
- ref: ref
693
- });
694
- }), {
695
- marks: [
696
- schema.mark("em")
697
- ],
698
- key: "img-widget"
699
- })
700
- ])
701
- ]
702
- });
703
- expect(view.dom.querySelector("em img")).not.toBeNull();
704
- });
705
- it("draws widgets inside the marks for their side", async ()=>{
706
- const { view } = tempEditor({
707
- doc: doc(p(em("foo"), strong("bar"))),
708
- plugins: [
709
- decoPlugin([
710
- widget(4, /*#__PURE__*/ forwardRef(function Img(param, ref) {
711
- let { widget, getPos, ...props } = param;
712
- return /*#__PURE__*/ React.createElement("img", {
713
- ...props,
714
- ref: ref
715
- });
716
- }), {
717
- side: -1,
718
- key: "img-widget"
719
- })
720
- ]),
721
- decoPlugin([
722
- widget(4, /*#__PURE__*/ forwardRef(function BR(param, ref) {
723
- let { widget, getPos, ...props } = param;
724
- return /*#__PURE__*/ React.createElement("br", {
725
- ...props,
726
- ref: ref
727
- });
728
- }), {
729
- key: "br-widget"
730
- })
731
- ]),
732
- decoPlugin([
733
- widget(7, /*#__PURE__*/ forwardRef(function Span(param, ref) {
734
- let { widget, getPos, ...props } = param;
735
- return /*#__PURE__*/ React.createElement("span", {
736
- ...props,
737
- ref: ref
738
- });
739
- }), {
740
- side: 1,
741
- key: "span-widget"
742
- })
743
- ])
744
- ]
745
- });
746
- expect(view.dom.querySelector("em img")).not.toBeNull();
747
- expect(view.dom.querySelector("strong img")).toBeNull();
748
- expect(view.dom.querySelector("strong br")).not.toBeNull();
749
- expect(view.dom.querySelector("em br")).toBeNull();
750
- expect(view.dom.querySelector("strong span")).toBeNull();
751
- });
752
- it("draws decorations inside node views", async ()=>{
753
- const { view } = tempEditor({
754
- doc: doc(p("foo")),
755
- nodeViews: {
756
- paragraph: /*#__PURE__*/ forwardRef(function Paragraph(param, ref) {
757
- let { nodeProps, children, ...props } = param;
758
- return /*#__PURE__*/ React.createElement("p", {
759
- ...props,
760
- ref: ref
761
- }, children);
762
- })
763
- },
764
- plugins: [
765
- decoPlugin([
766
- widget(2, /*#__PURE__*/ forwardRef(function Img(param, ref) {
767
- let { widget, getPos, ...props } = param;
768
- return /*#__PURE__*/ React.createElement("img", {
769
- ...props,
770
- ref: ref
771
- });
772
- }), {
773
- key: "img-widget"
774
- })
775
- ])
776
- ]
777
- });
778
- expect(view.dom.querySelector("img")).not.toBeNull();
779
- });
780
- it("can delay widget drawing to render time", async ()=>{
781
- const { view } = tempEditor({
782
- doc: doc(p("hi")),
783
- decorations (state) {
784
- return DecorationSet.create(state.doc, [
785
- widget(3, /*#__PURE__*/ forwardRef(function Span(param, ref) {
786
- let { widget, getPos, ...props } = param;
787
- useEditorEffect((view)=>{
788
- expect(view.state).toBe(state);
789
- });
790
- return /*#__PURE__*/ React.createElement("span", {
791
- ...props,
792
- ref: ref
793
- }, "!");
794
- }), {
795
- key: "span-widget"
796
- })
797
- ]);
798
- }
799
- });
800
- expect(view.dom.textContent).toBe("hi!");
801
- });
802
- it("supports widgets querying their own position", async ()=>{
803
- tempEditor({
804
- doc: doc(p("hi")),
805
- decorations (state) {
806
- return DecorationSet.create(state.doc, [
807
- widget(3, /*#__PURE__*/ forwardRef(function Widget(param, ref) {
808
- let { widget, getPos, ...props } = param;
809
- expect(getPos()).toBe(3);
810
- return /*#__PURE__*/ React.createElement("button", {
811
- ref: ref,
812
- ...props
813
- }, "ω");
814
- }), {
815
- key: "button-widget"
816
- })
817
- ]);
818
- }
819
- });
820
- });
821
- it("doesn't redraw widgets with matching keys", async ()=>{
822
- const { view } = tempEditor({
823
- doc: doc(p("hi")),
824
- decorations (state) {
825
- return DecorationSet.create(state.doc, [
826
- widget(2, Widget, {
827
- key: "myButton"
828
- })
829
- ]);
830
- }
831
- });
832
- const widgetDOM = view.dom.querySelector("button");
833
- view.dispatch(view.state.tr.insertText("!", 2, 2));
834
- expect(view.dom.querySelector("button")).toBe(widgetDOM);
835
- });
836
- it("doesn't redraw widgets with identical specs", async ()=>{
837
- const { view } = tempEditor({
838
- doc: doc(p("hi")),
839
- decorations (state) {
840
- return DecorationSet.create(state.doc, [
841
- widget(2, Widget, {
842
- side: 1,
843
- key: "widget"
844
- })
845
- ]);
846
- }
847
- });
848
- const widgetDOM = view.dom.querySelector("button");
849
- view.dispatch(view.state.tr.insertText("!", 2, 2));
850
- expect(view.dom.querySelector("button")).toBe(widgetDOM);
851
- });
852
- it("doesn't get confused by split text nodes", async ()=>{
853
- const { view } = tempEditor({
854
- doc: doc(p("abab")),
855
- decorations (state) {
856
- return state.selection.from <= 1 ? null : DecorationSet.create(view.state.doc, [
857
- Decoration.inline(1, 2, {
858
- class: "foo"
859
- }),
860
- Decoration.inline(3, 4, {
861
- class: "foo"
862
- })
863
- ]);
864
- }
865
- });
866
- view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.doc, 5)));
867
- expect(view.dom.textContent).toBe("abab");
868
- });
869
- it("only draws inline decorations on the innermost level", async ()=>{
870
- const s = new Schema({
871
- nodes: {
872
- doc: {
873
- content: "(text | thing)*"
874
- },
875
- text: {},
876
- thing: {
877
- inline: true,
878
- content: "text*",
879
- toDOM: ()=>[
880
- "strong",
881
- 0
882
- ],
883
- parseDOM: [
884
- {
885
- tag: "strong"
886
- }
887
- ]
888
- }
889
- }
890
- });
891
- const { view } = tempEditor({
892
- doc: s.node("doc", null, [
893
- s.text("abc"),
894
- s.node("thing", null, [
895
- s.text("def")
896
- ]),
897
- s.text("ghi")
898
- ]),
899
- decorations: (s)=>DecorationSet.create(s.doc, [
900
- Decoration.inline(1, 10, {
901
- class: "dec"
902
- })
903
- ])
904
- });
905
- const styled = view.dom.querySelectorAll(".dec");
906
- expect(styled).toHaveLength(3);
907
- expect(Array.prototype.map.call(styled, (n)=>n.textContent).join()).toBe("bc,def,gh");
908
- expect(styled[1].parentNode.nodeName).toBe("STRONG");
909
- });
910
- it("can handle nodeName decoration overlapping with classes", async ()=>{
911
- const { view } = tempEditor({
912
- doc: doc(p("one two three")),
913
- plugins: [
914
- decoPlugin([
915
- Decoration.inline(2, 13, {
916
- class: "foo"
917
- }),
918
- Decoration.inline(5, 8, {
919
- nodeName: "em"
920
- })
921
- ])
922
- ]
923
- });
924
- expect(view.dom.firstChild.innerHTML).toBe('o<span class="foo">ne </span><em class="foo">two</em><span class="foo"> thre</span>e');
925
- });
926
- it("can handle combining decorations from parent editors in child editors", async ()=>{
927
- let decosFromFirstEditor;
928
- let { view } = tempEditor({
929
- doc: doc(p("one two three")),
930
- plugins: [
931
- decoPlugin([
932
- Decoration.inline(2, 13, {
933
- class: "foo"
934
- })
935
- ]),
936
- decoPlugin([
937
- Decoration.inline(2, 13, {
938
- class: "bar"
939
- })
940
- ])
941
- ],
942
- nodeViews: {
943
- paragraph: /*#__PURE__*/ forwardRef(function Paragraph(param, ref) {
944
- let { nodeProps, children, ...props } = param;
945
- decosFromFirstEditor = nodeProps.innerDecorations;
946
- return /*#__PURE__*/ React.createElement("p", {
947
- ...props,
948
- ref: ref
949
- }, children);
950
- })
951
- }
952
- });
953
- ({ view } = tempEditor({
954
- doc: doc(p("one two three")),
955
- plugins: [
956
- decoPlugin([
957
- Decoration.inline(1, 12, {
958
- class: "baz"
959
- })
960
- ])
961
- ],
962
- decorations: ()=>decosFromFirstEditor
963
- }));
964
- expect(view.dom.querySelectorAll(".foo")).toHaveLength(1);
965
- expect(view.dom.querySelectorAll(".bar")).toHaveLength(1);
966
- expect(view.dom.querySelectorAll(".baz")).toHaveLength(1);
967
- });
968
- });