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

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 (60) hide show
  1. package/dist/cjs/tiptap/tiptapNodeView.js +26 -13
  2. package/dist/esm/tiptap/tiptapNodeView.js +27 -14
  3. package/dist/tsconfig.tsbuildinfo +1 -1
  4. package/dist/types/constants.d.ts +1 -1
  5. package/dist/types/props.d.ts +26 -26
  6. package/package.json +1 -1
  7. package/dist/esm/@jest/pattern/src/__tests__/TestPathPatterns.test.js +0 -241
  8. package/dist/esm/@swc/cli/lib/swc/__tests__/compile.test.js +0 -19
  9. package/dist/esm/@swc/cli/lib/swc/__tests__/options.test.js +0 -315
  10. package/dist/esm/@swc/cli/lib/swc/__tests__/sources.test.js +0 -161
  11. package/dist/esm/@uiw/react-codemirror/src/__tests__/index.test.js +0 -111
  12. package/dist/esm/cheerio/src/__tests__/deprecated.spec.js +0 -249
  13. package/dist/esm/cheerio/src/__tests__/xml.spec.js +0 -55
  14. package/dist/esm/components/__tests__/ProseMirror.composition.test.js +0 -395
  15. package/dist/esm/components/__tests__/ProseMirror.domchange.test.js +0 -266
  16. package/dist/esm/components/__tests__/ProseMirror.draw-decoration.test.js +0 -968
  17. package/dist/esm/components/__tests__/ProseMirror.draw.test.js +0 -335
  18. package/dist/esm/components/__tests__/ProseMirror.mobile.test.js +0 -54
  19. package/dist/esm/components/__tests__/ProseMirror.node-view.test.js +0 -553
  20. package/dist/esm/components/__tests__/ProseMirror.selection.test.js +0 -440
  21. package/dist/esm/components/__tests__/ProseMirror.test.js +0 -324
  22. package/dist/esm/contexts/__tests__/DeferredLayoutEffects.test.js +0 -98
  23. package/dist/esm/hooks/__tests__/useEditorEffect.test.js +0 -134
  24. package/dist/esm/jsx-ast-utils/__tests__/helper.js +0 -83
  25. package/dist/esm/jsx-ast-utils/__tests__/src/elementType-test.js +0 -76
  26. package/dist/esm/jsx-ast-utils/__tests__/src/eventHandlers-test.js +0 -98
  27. package/dist/esm/jsx-ast-utils/__tests__/src/getProp-parser-test.js +0 -188
  28. package/dist/esm/jsx-ast-utils/__tests__/src/getProp-test.js +0 -119
  29. package/dist/esm/jsx-ast-utils/__tests__/src/getPropLiteralValue-babelparser-test.js +0 -393
  30. package/dist/esm/jsx-ast-utils/__tests__/src/getPropLiteralValue-flowparser-test.js +0 -379
  31. package/dist/esm/jsx-ast-utils/__tests__/src/getPropValue-babelparser-test.js +0 -925
  32. package/dist/esm/jsx-ast-utils/__tests__/src/getPropValue-flowparser-test.js +0 -700
  33. package/dist/esm/jsx-ast-utils/__tests__/src/hasProp-test.js +0 -350
  34. package/dist/esm/jsx-ast-utils/__tests__/src/index-test.js +0 -24
  35. package/dist/esm/jsx-ast-utils/__tests__/src/propName-test.js +0 -37
  36. package/dist/esm/plugins/__tests__/reactKeys.test.js +0 -77
  37. package/dist/esm/tsconfig-paths/lib/__tests__/config-loader.test.d.js +0 -1
  38. package/dist/esm/tsconfig-paths/lib/__tests__/config-loader.test.js +0 -97
  39. package/dist/esm/tsconfig-paths/lib/__tests__/data/match-path-data.d.js +0 -1
  40. package/dist/esm/tsconfig-paths/lib/__tests__/data/match-path-data.js +0 -319
  41. package/dist/esm/tsconfig-paths/lib/__tests__/filesystem.test.d.js +0 -1
  42. package/dist/esm/tsconfig-paths/lib/__tests__/filesystem.test.js +0 -62
  43. package/dist/esm/tsconfig-paths/lib/__tests__/mapping-entry.test.d.js +0 -1
  44. package/dist/esm/tsconfig-paths/lib/__tests__/mapping-entry.test.js +0 -80
  45. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-async.test.d.js +0 -1
  46. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-async.test.js +0 -22
  47. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-sync.test.d.js +0 -1
  48. package/dist/esm/tsconfig-paths/lib/__tests__/match-path-sync.test.js +0 -20
  49. package/dist/esm/tsconfig-paths/lib/__tests__/try-path.test.d.js +0 -1
  50. package/dist/esm/tsconfig-paths/lib/__tests__/try-path.test.js +0 -219
  51. package/dist/esm/tsconfig-paths/lib/__tests__/tsconfig-loader.test.d.js +0 -1
  52. package/dist/esm/tsconfig-paths/lib/__tests__/tsconfig-loader.test.js +0 -323
  53. package/dist/esm/tsconfig-paths/src/__tests__/config-loader.test.js +0 -89
  54. package/dist/esm/tsconfig-paths/src/__tests__/data/match-path-data.js +0 -314
  55. package/dist/esm/tsconfig-paths/src/__tests__/filesystem.test.js +0 -58
  56. package/dist/esm/tsconfig-paths/src/__tests__/mapping-entry.test.js +0 -76
  57. package/dist/esm/tsconfig-paths/src/__tests__/match-path-async.test.js +0 -12
  58. package/dist/esm/tsconfig-paths/src/__tests__/match-path-sync.test.js +0 -10
  59. package/dist/esm/tsconfig-paths/src/__tests__/try-path.test.js +0 -214
  60. 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
- });