@zipify/wysiwyg 1.3.0-0 → 2.0.0-1

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 (103) hide show
  1. package/.eslintrc.js +1 -1
  2. package/config/build/lib.config.js +4 -2
  3. package/dist/cli.js +10 -2
  4. package/dist/wysiwyg.css +43 -48
  5. package/dist/wysiwyg.mjs +1928 -787
  6. package/example/ExampleApp.vue +3 -1
  7. package/lib/__tests__/utils/buildTestExtensions.js +14 -0
  8. package/lib/__tests__/utils/index.js +1 -0
  9. package/lib/components/base/Button.vue +0 -7
  10. package/lib/components/base/dropdown/Dropdown.vue +1 -7
  11. package/lib/components/base/dropdown/DropdownActivator.vue +4 -19
  12. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +1 -23
  13. package/lib/components/toolbar/controls/AlignmentControl.vue +1 -11
  14. package/lib/components/toolbar/controls/FontColorControl.vue +0 -13
  15. package/lib/components/toolbar/controls/FontFamilyControl.vue +0 -4
  16. package/lib/components/toolbar/controls/FontSizeControl.vue +1 -6
  17. package/lib/components/toolbar/controls/FontWeightControl.vue +0 -12
  18. package/lib/components/toolbar/controls/ItalicControl.vue +0 -13
  19. package/lib/components/toolbar/controls/LineHeightControl.vue +0 -14
  20. package/lib/components/toolbar/controls/StylePresetControl.vue +1 -1
  21. package/lib/components/toolbar/controls/SuperscriptControl.vue +2 -2
  22. package/lib/components/toolbar/controls/UnderlineControl.vue +0 -12
  23. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +5 -72
  24. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +1 -22
  25. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +0 -1
  26. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +0 -1
  27. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +0 -1
  28. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +1 -23
  29. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +1 -23
  30. package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +2 -2
  31. package/lib/components/toolbar/controls/__tests__/SuperscriptControl.test.js +2 -2
  32. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +1 -25
  33. package/lib/composables/__tests__/useEditor.test.js +2 -2
  34. package/lib/enums/TextSettings.js +5 -5
  35. package/lib/extensions/BackgroundColor.js +4 -4
  36. package/lib/extensions/FontColor.js +4 -5
  37. package/lib/extensions/FontFamily.js +4 -5
  38. package/lib/extensions/FontSize.js +5 -7
  39. package/lib/extensions/FontStyle.js +13 -11
  40. package/lib/extensions/FontWeight.js +6 -9
  41. package/lib/extensions/Link.js +1 -1
  42. package/lib/extensions/StylePreset.js +1 -15
  43. package/lib/extensions/Superscript.js +23 -1
  44. package/lib/extensions/TextDecoration.js +16 -20
  45. package/lib/extensions/__tests__/Alignment.test.js +10 -7
  46. package/lib/extensions/__tests__/BackgroundColor.test.js +6 -3
  47. package/lib/extensions/__tests__/CaseStyle.test.js +11 -7
  48. package/lib/extensions/__tests__/FontColor.test.js +6 -3
  49. package/lib/extensions/__tests__/FontFamily.test.js +29 -22
  50. package/lib/extensions/__tests__/FontSize.test.js +24 -17
  51. package/lib/extensions/__tests__/FontStyle.test.js +22 -16
  52. package/lib/extensions/__tests__/FontWeight.test.js +28 -21
  53. package/lib/extensions/__tests__/LineHeight.test.js +14 -11
  54. package/lib/extensions/__tests__/Link.test.js +14 -10
  55. package/lib/extensions/__tests__/Margin.test.js +2 -2
  56. package/lib/extensions/__tests__/StylePreset.test.js +49 -100
  57. package/lib/extensions/__tests__/TextDecoration.test.js +59 -37
  58. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +25 -25
  59. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +25 -25
  60. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +105 -105
  61. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +72 -72
  62. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +54 -46
  63. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +77 -77
  64. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +68 -3
  65. package/lib/extensions/core/Document.js +5 -0
  66. package/lib/extensions/core/Heading.js +10 -0
  67. package/lib/extensions/core/NodeProcessor.js +112 -10
  68. package/lib/extensions/core/Paragraph.js +9 -0
  69. package/lib/extensions/core/TextProcessor.js +9 -16
  70. package/lib/extensions/core/__tests__/NodeProcessor.test.js +137 -10
  71. package/lib/extensions/core/__tests__/SelectionProcessor.test.js +2 -2
  72. package/lib/extensions/core/__tests__/TextProcessor.test.js +18 -41
  73. package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +192 -0
  74. package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +7 -27
  75. package/lib/extensions/core/index.js +5 -5
  76. package/lib/extensions/core/steps/AddNodeMarkStep.js +60 -0
  77. package/lib/extensions/core/steps/AttrStep.js +54 -0
  78. package/lib/extensions/core/steps/RemoveNodeMarkStep.js +50 -0
  79. package/lib/extensions/core/steps/index.js +3 -0
  80. package/lib/extensions/list/List.js +1 -0
  81. package/lib/extensions/list/ListItem.js +5 -0
  82. package/lib/extensions/list/__tests__/List.test.js +30 -25
  83. package/lib/services/NodeFactory.js +25 -21
  84. package/lib/services/index.js +1 -1
  85. package/lib/services/normalizer/BaseNormalizer.js +11 -0
  86. package/lib/services/{BrowserDomParser.js → normalizer/BrowserDomParser.js} +0 -0
  87. package/lib/services/normalizer/ContentNormalizer.js +24 -0
  88. package/lib/services/normalizer/HtmlNormalizer.js +245 -0
  89. package/lib/services/normalizer/JsonNormalizer.js +81 -0
  90. package/lib/services/{__tests__/ContentNormalizer.test.js → normalizer/__tests__/HtmlNormalizer.test.js} +27 -67
  91. package/lib/services/normalizer/__tests__/JsonNormalizer.test.js +70 -0
  92. package/lib/services/normalizer/__tests__/__snapshots__/JsonNormalizer.test.js.snap +159 -0
  93. package/lib/services/normalizer/index.js +1 -0
  94. package/lib/styles/content.css +8 -0
  95. package/lib/utils/findMarkByType.js +5 -0
  96. package/lib/utils/index.js +5 -0
  97. package/lib/utils/isMarkAppliedToParent.js +10 -0
  98. package/lib/utils/isNodeFullySelected.js +10 -0
  99. package/lib/utils/resolveNodePosition.js +6 -0
  100. package/lib/utils/resolveTextPosition.js +6 -0
  101. package/package.json +3 -1
  102. package/lib/assets/icons/indicator.svg +0 -5
  103. package/lib/services/ContentNormalizer.js +0 -293
@@ -6,18 +6,18 @@ Object {
6
6
  Object {
7
7
  "content": Array [
8
8
  Object {
9
- "marks": Array [
10
- Object {
11
- "attrs": Object {
12
- "value": "700",
13
- },
14
- "type": "font_weight",
15
- },
16
- ],
17
9
  "text": "hello world",
18
10
  "type": "text",
19
11
  },
20
12
  ],
13
+ "marks": Array [
14
+ Object {
15
+ "attrs": Object {
16
+ "value": "700",
17
+ },
18
+ "type": "font_weight",
19
+ },
20
+ ],
21
21
  "type": "paragraph",
22
22
  },
23
23
  ],
@@ -31,18 +31,18 @@ Object {
31
31
  Object {
32
32
  "content": Array [
33
33
  Object {
34
- "marks": Array [
35
- Object {
36
- "attrs": Object {
37
- "value": "700",
38
- },
39
- "type": "font_weight",
40
- },
41
- ],
42
34
  "text": "hello world",
43
35
  "type": "text",
44
36
  },
45
37
  ],
38
+ "marks": Array [
39
+ Object {
40
+ "attrs": Object {
41
+ "value": "700",
42
+ },
43
+ "type": "font_weight",
44
+ },
45
+ ],
46
46
  "type": "paragraph",
47
47
  },
48
48
  ],
@@ -56,24 +56,24 @@ Object {
56
56
  Object {
57
57
  "content": Array [
58
58
  Object {
59
- "marks": Array [
60
- Object {
61
- "attrs": Object {
62
- "value": "Bungee",
63
- },
64
- "type": "font_family",
65
- },
66
- Object {
67
- "attrs": Object {
68
- "value": "800",
69
- },
70
- "type": "font_weight",
71
- },
72
- ],
73
59
  "text": "hello world",
74
60
  "type": "text",
75
61
  },
76
62
  ],
63
+ "marks": Array [
64
+ Object {
65
+ "attrs": Object {
66
+ "value": "Bungee",
67
+ },
68
+ "type": "font_family",
69
+ },
70
+ Object {
71
+ "attrs": Object {
72
+ "value": "800",
73
+ },
74
+ "type": "font_weight",
75
+ },
76
+ ],
77
77
  "type": "paragraph",
78
78
  },
79
79
  ],
@@ -87,24 +87,24 @@ Object {
87
87
  Object {
88
88
  "content": Array [
89
89
  Object {
90
- "marks": Array [
91
- Object {
92
- "attrs": Object {
93
- "value": "Bungee",
94
- },
95
- "type": "font_family",
96
- },
97
- Object {
98
- "attrs": Object {
99
- "value": "300",
100
- },
101
- "type": "font_weight",
102
- },
103
- ],
104
90
  "text": "hello world",
105
91
  "type": "text",
106
92
  },
107
93
  ],
94
+ "marks": Array [
95
+ Object {
96
+ "attrs": Object {
97
+ "value": "Bungee",
98
+ },
99
+ "type": "font_family",
100
+ },
101
+ Object {
102
+ "attrs": Object {
103
+ "value": "300",
104
+ },
105
+ "type": "font_weight",
106
+ },
107
+ ],
108
108
  "type": "paragraph",
109
109
  },
110
110
  ],
@@ -118,18 +118,18 @@ Object {
118
118
  Object {
119
119
  "content": Array [
120
120
  Object {
121
- "marks": Array [
122
- Object {
123
- "attrs": Object {
124
- "value": "400",
125
- },
126
- "type": "font_weight",
127
- },
128
- ],
129
121
  "text": "hello world",
130
122
  "type": "text",
131
123
  },
132
124
  ],
125
+ "marks": Array [
126
+ Object {
127
+ "attrs": Object {
128
+ "value": "400",
129
+ },
130
+ "type": "font_weight",
131
+ },
132
+ ],
133
133
  "type": "paragraph",
134
134
  },
135
135
  ],
@@ -172,18 +172,18 @@ Object {
172
172
  Object {
173
173
  "content": Array [
174
174
  Object {
175
- "marks": Array [
176
- Object {
177
- "attrs": Object {
178
- "value": "700",
179
- },
180
- "type": "font_weight",
181
- },
182
- ],
183
175
  "text": "test",
184
176
  "type": "text",
185
177
  },
186
178
  ],
179
+ "marks": Array [
180
+ Object {
181
+ "attrs": Object {
182
+ "value": "700",
183
+ },
184
+ "type": "font_weight",
185
+ },
186
+ ],
187
187
  "type": "paragraph",
188
188
  },
189
189
  ],
@@ -313,18 +313,18 @@ Object {
313
313
  "type": "text",
314
314
  },
315
315
  Object {
316
- "marks": Array [
317
- Object {
318
- "attrs": Object {
319
- "value": "500",
320
- },
321
- "type": "font_weight",
322
- },
323
- ],
324
316
  "text": " ipsum",
325
317
  "type": "text",
326
318
  },
327
319
  ],
320
+ "marks": Array [
321
+ Object {
322
+ "attrs": Object {
323
+ "value": "500",
324
+ },
325
+ "type": "font_weight",
326
+ },
327
+ ],
328
328
  "type": "paragraph",
329
329
  },
330
330
  ],
@@ -338,18 +338,18 @@ Object {
338
338
  Object {
339
339
  "content": Array [
340
340
  Object {
341
- "marks": Array [
342
- Object {
343
- "attrs": Object {
344
- "value": "700",
345
- },
346
- "type": "font_weight",
347
- },
348
- ],
349
341
  "text": "test",
350
342
  "type": "text",
351
343
  },
352
344
  ],
345
+ "marks": Array [
346
+ Object {
347
+ "attrs": Object {
348
+ "value": "700",
349
+ },
350
+ "type": "font_weight",
351
+ },
352
+ ],
353
353
  "type": "paragraph",
354
354
  },
355
355
  ],
@@ -357,4 +357,4 @@ Object {
357
357
  }
358
358
  `;
359
359
 
360
- exports[`rendering should render html 1`] = `"<p class="zw-style"><span style="--zw-font-weight:700;" class="zw-style">hello world</span></p>"`;
360
+ exports[`rendering should render html 1`] = `"<span style="--zw-font-weight:700;" class="zw-style"><p class="zw-style">hello world</p></span>"`;
@@ -26,6 +26,71 @@ Object {
26
26
  }
27
27
  `;
28
28
 
29
+ exports[`apply decoration should apply decoration with decorated parent false value 1`] = `
30
+ Object {
31
+ "content": Array [
32
+ Object {
33
+ "content": Array [
34
+ Object {
35
+ "marks": Array [
36
+ Object {
37
+ "attrs": Object {
38
+ "strike_through": false,
39
+ "underline": true,
40
+ },
41
+ "type": "text_decoration",
42
+ },
43
+ ],
44
+ "text": "hello",
45
+ "type": "text",
46
+ },
47
+ Object {
48
+ "text": " world",
49
+ "type": "text",
50
+ },
51
+ ],
52
+ "marks": Array [
53
+ Object {
54
+ "attrs": Object {
55
+ "strike_through": false,
56
+ "underline": false,
57
+ },
58
+ "type": "text_decoration",
59
+ },
60
+ ],
61
+ "type": "paragraph",
62
+ },
63
+ ],
64
+ "type": "doc",
65
+ }
66
+ `;
67
+
68
+ exports[`apply decoration should not apply decoration with decorated parent 1`] = `
69
+ Object {
70
+ "content": Array [
71
+ Object {
72
+ "content": Array [
73
+ Object {
74
+ "marks": Array [
75
+ Object {
76
+ "attrs": Object {
77
+ "strike_through": false,
78
+ "underline": true,
79
+ },
80
+ "type": "text_decoration",
81
+ },
82
+ ],
83
+ "text": "hello world",
84
+ "type": "text",
85
+ },
86
+ ],
87
+ "type": "paragraph",
88
+ },
89
+ ],
90
+ "type": "doc",
91
+ }
92
+ `;
93
+
29
94
  exports[`apply decoration should second decoration 1`] = `
30
95
  Object {
31
96
  "content": Array [
@@ -62,7 +127,7 @@ Object {
62
127
  Object {
63
128
  "attrs": Object {
64
129
  "strike_through": false,
65
- "underline": true,
130
+ "underline": false,
66
131
  },
67
132
  "type": "text_decoration",
68
133
  },
@@ -113,7 +178,7 @@ Object {
113
178
  "marks": Array [
114
179
  Object {
115
180
  "attrs": Object {
116
- "strike_through": true,
181
+ "strike_through": false,
117
182
  "underline": false,
118
183
  },
119
184
  "type": "text_decoration",
@@ -454,7 +519,7 @@ Object {
454
519
  Object {
455
520
  "attrs": Object {
456
521
  "strike_through": true,
457
- "underline": false,
522
+ "underline": true,
458
523
  },
459
524
  "type": "text_decoration",
460
525
  },
@@ -0,0 +1,5 @@
1
+ import { Document as Base } from '@tiptap/extension-document';
2
+
3
+ export const Document = Base.extend({
4
+ marks: 'settings'
5
+ });
@@ -0,0 +1,10 @@
1
+ import { Heading as Base } from '@tiptap/extension-heading';
2
+
3
+ export const Heading = Base.extend({
4
+ marks: '_',
5
+
6
+ addOptions: () => ({
7
+ levels: [1, 2, 3, 4],
8
+ HTMLAttributes: { class: 'zw-style' }
9
+ })
10
+ });
@@ -1,21 +1,31 @@
1
- import { Extension } from '@tiptap/vue-2';
2
- import { computed, unref } from 'vue';
3
- import { createCommand } from '../../utils';
1
+ import { Extension, getMarkType } from '@tiptap/vue-2';
2
+ import { computed, toRef, unref } from 'vue';
3
+ import {
4
+ createCommand,
5
+ findMarkByType,
6
+ isMarkAppliedToParent,
7
+ isNodeFullySelected,
8
+ resolveTextPosition
9
+ } from '../../utils';
4
10
  import { NodeTypes } from '../../enums';
11
+ import { AddNodeMarkStep, AttrStep, RemoveNodeMarkStep } from './steps';
5
12
 
6
13
  export const NodeProcessor = Extension.create({
7
14
  name: 'node_processor',
8
15
 
9
16
  addCommands() {
10
17
  return {
11
- setBlockAttributes: createCommand(({ commands }, name, attrs, defaults = {}) => {
18
+ setBlockAttributes: createCommand(({ commands, state }, name, attrs, defaults = {}) => {
12
19
  const current = unref(commands.getBlockAttributes(name)) ?? {};
20
+ const { doc, tr } = state;
21
+ const { selection } = tr;
22
+ const { from, to } = selection;
13
23
 
14
- for (const type of NodeTypes.blocks) {
15
- commands.updateAttributes(type, {
16
- [name]: { ...defaults, ...current, ...attrs }
17
- });
18
- }
24
+ doc.nodesBetween(from, to, (node, position) => {
25
+ if (!NodeTypes.blocks.includes(node.type.name)) return;
26
+
27
+ tr.step(new AttrStep(position, name, { ...defaults, ...current, ...attrs }));
28
+ });
19
29
  }),
20
30
 
21
31
  getBlockAttributes: createCommand(({ editor }, name, defaults) => computed(() => {
@@ -26,7 +36,99 @@ export const NodeProcessor = Extension.create({
26
36
  }
27
37
 
28
38
  return Object.keys(attrs).length ? attrs : null;
29
- }))
39
+ })),
40
+
41
+ applyMark: createCommand(({ state, commands }, name, value) => {
42
+ const { tr, doc, schema } = state;
43
+ const { $from, $to } = tr.selection;
44
+ const markType = getMarkType(name, schema);
45
+ const markGroup = markType.spec.group || '';
46
+
47
+ if (!markGroup.includes('settings')) {
48
+ // Apply inline mark if block level not supported
49
+ return commands.setMark(name, value);
50
+ }
51
+
52
+ if ($from.pos === $to.pos) return;
53
+
54
+ doc.nodesBetween($from.pos, $to.pos, (node, position) => {
55
+ if (node.type.name === NodeTypes.LIST) return;
56
+
57
+ const initialMark = findMarkByType(node.marks, name);
58
+ const applyingMark = markType.create({ ...(initialMark?.attrs || {}), ...value });
59
+ const textPosition = resolveTextPosition($from, $to, node, position);
60
+
61
+ if (isMarkAppliedToParent(tr, position, applyingMark)) {
62
+ tr.removeMark(textPosition.from, textPosition.to, applyingMark.type);
63
+ return;
64
+ }
65
+
66
+ if (node.isText) {
67
+ tr.addMark(textPosition.from, textPosition.to, applyingMark);
68
+ return;
69
+ }
70
+
71
+ if (isNodeFullySelected($from, $to, node, position)) {
72
+ tr.step(new AddNodeMarkStep(position, applyingMark));
73
+ }
74
+ });
75
+ }),
76
+
77
+ getMarks: createCommand(({ editor }, name) => {
78
+ const stateRef = toRef(editor, 'state');
79
+
80
+ return computed(() => {
81
+ const { selection, doc } = unref(stateRef);
82
+ const { from, to } = unref(selection);
83
+ const marks = [];
84
+
85
+ doc.nodesBetween(from, to, (node) => {
86
+ for (const mark of node.marks) {
87
+ if (mark.type.name === name) marks.unshift(mark.attrs);
88
+ }
89
+ });
90
+
91
+ return marks;
92
+ });
93
+ }),
94
+
95
+ getMark: createCommand(({ commands }, name) => {
96
+ const marksRef = commands.getMarks(name);
97
+
98
+ return computed(() => unref(marksRef)[0] ?? null);
99
+ }),
100
+
101
+ getCommonSettingMark: createCommand(({ commands }, name, defaultRef) => {
102
+ const selectionRef = commands.getMark(name);
103
+
104
+ return computed(() => unref(selectionRef)?.value ?? unref(defaultRef));
105
+ }),
106
+
107
+ getDeviceSettingMark: createCommand(({ commands }, name, defaultRef) => {
108
+ const selectionRef = commands.getMark(name);
109
+ const deviceRef = commands.getDevice();
110
+
111
+ return computed(() => unref(selectionRef)?.[unref(deviceRef)] ?? unref(defaultRef));
112
+ }),
113
+
114
+ removeMarks: createCommand(({ state }, marks) => {
115
+ const { tr, selection, doc } = state;
116
+ const { $from, $to } = selection;
117
+
118
+ if ($from.pos === $to.pos) return;
119
+
120
+ doc.nodesBetween($from.pos, $to.pos, (node, position) => {
121
+ const textPosition = resolveTextPosition($from, $to, node, position);
122
+
123
+ const removeMark = (mark) => node.isText
124
+ ? tr.removeMark(textPosition.from, textPosition.to, mark)
125
+ : tr.step(new RemoveNodeMarkStep(position, mark));
126
+
127
+ for (const mark of node.marks) {
128
+ if (marks.includes(mark.type.name)) removeMark(mark);
129
+ }
130
+ });
131
+ })
30
132
  };
31
133
  }
32
134
  });
@@ -0,0 +1,9 @@
1
+ import { Paragraph as Base } from '@tiptap/extension-paragraph';
2
+
3
+ export const Paragraph = Base.extend({
4
+ marks: '_',
5
+
6
+ addOptions: () => ({
7
+ HTMLAttributes: { class: 'zw-style' }
8
+ })
9
+ });
@@ -1,5 +1,5 @@
1
1
  import { Extension } from '@tiptap/vue-2';
2
- import { createCommand } from '../../utils';
2
+ import { createCommand, resolveTextPosition } from '../../utils';
3
3
 
4
4
  export const TextProcessor = Extension.create({
5
5
  name: 'text_processor',
@@ -12,31 +12,24 @@ export const TextProcessor = Extension.create({
12
12
  return state.doc.textBetween(from, to, ' ');
13
13
  }),
14
14
 
15
- unsetMarks: createCommand(({ commands }, marks) => {
16
- marks.forEach((mark) => commands.unsetMark(mark));
17
- }),
18
-
19
15
  transformText: createCommand(({ state }, transform) => {
20
- const { selection } = state.tr;
16
+ const { $from, $to } = state.tr.selection;
21
17
 
22
- if (selection.from === selection.to) return;
18
+ if ($from.pos === $to.pos) return;
23
19
 
24
- state.doc.nodesBetween(selection.from, selection.to, (node, position) => {
20
+ state.doc.nodesBetween($from.pos, $to.pos, (node, position) => {
25
21
  if (!node.isText) return;
26
22
 
27
- const startPosition = Math.max(position, selection.from);
28
- const endPosition = Math.min(position + node.nodeSize, selection.to);
29
-
30
- const substringFrom = Math.max(0, selection.from - position);
31
- const substringTo = Math.max(0, selection.to - position);
23
+ const textPosition = resolveTextPosition($from, $to, node, position);
24
+ const substringFrom = Math.max(0, $from.pos - position);
25
+ const substringTo = Math.max(0, $to.pos - position);
32
26
 
33
27
  const updatedText = transform({
34
- text: node.textContent.substring(substringFrom, substringTo),
35
- position: { start: startPosition, end: endPosition }
28
+ text: node.textContent.substring(substringFrom, substringTo)
36
29
  });
37
30
  const updatedNode = state.schema.text(updatedText, node.marks);
38
31
 
39
- state.tr.replaceWith(startPosition, endPosition, updatedNode);
32
+ state.tr.replaceWith(textPosition.from, textPosition.to, updatedNode);
40
33
  });
41
34
  })
42
35
  };