@zipify/wysiwyg 1.0.0-dev.17 → 1.0.0-dev.18
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/.github/dependabot.yaml +1 -0
- package/dist/wysiwyg.css +199 -12
- package/dist/wysiwyg.js +1 -1
- package/example/ExampleApp.vue +6 -2
- package/example/pageBlocks.js +31 -0
- package/example/presets.js +2 -2
- package/lib/Wysiwyg.vue +14 -3
- package/lib/assets/icons/link.svg +3 -0
- package/lib/assets/icons/unlink.svg +3 -0
- package/lib/components/base/Button.vue +21 -1
- package/lib/components/base/Checkbox.vue +89 -0
- package/lib/components/base/FieldLabel.vue +2 -1
- package/lib/components/base/Icon.vue +2 -2
- package/lib/components/base/Modal.vue +0 -1
- package/lib/components/base/TextField.vue +106 -0
- package/lib/components/base/__tests__/TextField.test.js +57 -0
- package/lib/components/base/__tests__/__snapshots__/TextField.test.js.snap +9 -0
- package/lib/components/base/composables/index.js +1 -0
- package/lib/components/base/composables/useValidator.js +19 -0
- package/lib/components/base/dropdown/Dropdown.vue +15 -3
- package/lib/components/base/dropdown/DropdownActivator.vue +19 -3
- package/lib/components/base/index.js +2 -0
- package/lib/components/toolbar/Toolbar.vue +5 -5
- package/lib/components/toolbar/ToolbarFull.vue +10 -2
- package/lib/components/toolbar/controls/FontSizeControl.vue +7 -0
- package/lib/components/toolbar/controls/UnderlineControl.vue +2 -2
- package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +4 -0
- package/lib/components/toolbar/controls/index.js +1 -0
- package/lib/components/toolbar/controls/link/LinkControl.vue +152 -0
- package/lib/components/toolbar/controls/link/LinkControlApply.vue +35 -0
- package/lib/components/toolbar/controls/link/LinkControlHeader.vue +67 -0
- package/lib/components/toolbar/controls/link/composables/index.js +1 -0
- package/lib/components/toolbar/controls/link/composables/useLink.js +61 -0
- package/lib/components/toolbar/controls/link/destination/LinkControlDestination.vue +103 -0
- package/lib/components/toolbar/controls/link/destination/LinkControlPageBlock.vue +54 -0
- package/lib/components/toolbar/controls/link/destination/LinkControlUrl.vue +52 -0
- package/lib/components/toolbar/controls/link/destination/index.js +1 -0
- package/lib/components/toolbar/controls/link/index.js +1 -0
- package/lib/composables/__tests__/useEditor.test.js +2 -2
- package/lib/composables/useEditor.js +2 -4
- package/lib/enums/LinkDestinations.js +4 -0
- package/lib/enums/LinkTargets.js +4 -0
- package/lib/enums/TextSettings.js +3 -1
- package/lib/enums/index.js +2 -0
- package/lib/extensions/Alignment.js +18 -6
- package/lib/extensions/BackgroundColor.js +14 -6
- package/lib/extensions/FontColor.js +14 -6
- package/lib/extensions/FontFamily.js +25 -8
- package/lib/extensions/FontSize.js +26 -13
- package/lib/extensions/FontStyle.js +23 -13
- package/lib/extensions/FontWeight.js +22 -14
- package/lib/extensions/LineHeight.js +11 -3
- package/lib/extensions/Link.js +101 -0
- package/lib/extensions/StylePreset.js +4 -2
- package/lib/extensions/TextDecoration.js +27 -12
- package/lib/extensions/__tests__/Alignment.test.js +11 -5
- package/lib/extensions/__tests__/BackgroundColor.test.js +11 -5
- package/lib/extensions/__tests__/CaseStyle.test.js +3 -5
- package/lib/extensions/__tests__/FontColor.test.js +11 -5
- package/lib/extensions/__tests__/FontFamily.test.js +32 -7
- package/lib/extensions/__tests__/FontSize.test.js +11 -5
- package/lib/extensions/__tests__/FontStyle.test.js +11 -5
- package/lib/extensions/__tests__/FontWeight.test.js +11 -5
- package/lib/extensions/__tests__/LineHeight.test.js +11 -5
- package/lib/extensions/__tests__/StylePreset.test.js +70 -6
- package/lib/extensions/__tests__/TextDecoration.test.js +27 -5
- package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +26 -2
- package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +30 -1
- package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +18 -1
- package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +88 -1
- package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +33 -2
- package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +25 -4
- package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +30 -1
- package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +26 -2
- package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +6 -2
- package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +93 -3
- package/lib/extensions/core/CopyPasteProcessor.js +10 -0
- package/lib/extensions/core/TextProcessor.js +10 -0
- package/lib/extensions/core/__tests__/NodeProcessor.test.js +3 -5
- package/lib/extensions/core/__tests__/SelectionProcessor.test.js +3 -5
- package/lib/extensions/core/__tests__/TextProcessor.test.js +138 -12
- package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +26 -0
- package/lib/extensions/core/index.js +11 -2
- package/lib/extensions/core/plugins/PastePlugin.js +48 -0
- package/lib/extensions/core/plugins/ProseMirrorPlugin.js +20 -0
- package/lib/extensions/core/plugins/index.js +1 -0
- package/lib/extensions/index.js +41 -34
- package/lib/extensions/list/__tests__/List.test.js +3 -5
- package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +45 -15
- package/lib/injectionTokens.js +2 -1
- package/lib/services/ContentNormalizer.js +62 -20
- package/lib/services/__tests__/ContentNormalizer.test.js +40 -7
- package/lib/styles/content.css +17 -9
- package/lib/styles/helpers/offsets.css +16 -0
- package/lib/styles/variables.css +6 -0
- package/lib/utils/__tests__/__snapshots__/renderInlineSetting.test.js.snap +4 -4
- package/lib/utils/renderInlineSetting.js +1 -1
- package/package.json +11 -9
|
@@ -138,7 +138,7 @@ Object {
|
|
|
138
138
|
}
|
|
139
139
|
`;
|
|
140
140
|
|
|
141
|
-
exports[`parsing html should get value from
|
|
141
|
+
exports[`parsing html should get value from rendered view 1`] = `
|
|
142
142
|
Object {
|
|
143
143
|
"content": Array [
|
|
144
144
|
Object {
|
|
@@ -167,7 +167,7 @@ Object {
|
|
|
167
167
|
}
|
|
168
168
|
`;
|
|
169
169
|
|
|
170
|
-
exports[`parsing html should
|
|
170
|
+
exports[`parsing html should get value from text 1`] = `
|
|
171
171
|
Object {
|
|
172
172
|
"content": Array [
|
|
173
173
|
Object {
|
|
@@ -176,7 +176,7 @@ Object {
|
|
|
176
176
|
"marks": Array [
|
|
177
177
|
Object {
|
|
178
178
|
"attrs": Object {
|
|
179
|
-
"italic":
|
|
179
|
+
"italic": true,
|
|
180
180
|
},
|
|
181
181
|
"type": "font_style",
|
|
182
182
|
},
|
|
@@ -184,6 +184,27 @@ Object {
|
|
|
184
184
|
"text": "lorem",
|
|
185
185
|
"type": "text",
|
|
186
186
|
},
|
|
187
|
+
Object {
|
|
188
|
+
"text": " ipsum",
|
|
189
|
+
"type": "text",
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
"type": "paragraph",
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
"type": "doc",
|
|
196
|
+
}
|
|
197
|
+
`;
|
|
198
|
+
|
|
199
|
+
exports[`parsing html should merge paragraph and text settings 1`] = `
|
|
200
|
+
Object {
|
|
201
|
+
"content": Array [
|
|
202
|
+
Object {
|
|
203
|
+
"content": Array [
|
|
204
|
+
Object {
|
|
205
|
+
"text": "lorem",
|
|
206
|
+
"type": "text",
|
|
207
|
+
},
|
|
187
208
|
Object {
|
|
188
209
|
"marks": Array [
|
|
189
210
|
Object {
|
|
@@ -204,4 +225,4 @@ Object {
|
|
|
204
225
|
}
|
|
205
226
|
`;
|
|
206
227
|
|
|
207
|
-
exports[`rendering should render html 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-font-style:
|
|
228
|
+
exports[`rendering should render html 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-font-style:italic;\\" class=\\"zw-style\\">hello world</span></p>"`;
|
|
@@ -191,6 +191,35 @@ Object {
|
|
|
191
191
|
}
|
|
192
192
|
`;
|
|
193
193
|
|
|
194
|
+
exports[`parsing html should get value from rendered view 1`] = `
|
|
195
|
+
Object {
|
|
196
|
+
"content": Array [
|
|
197
|
+
Object {
|
|
198
|
+
"content": Array [
|
|
199
|
+
Object {
|
|
200
|
+
"marks": Array [
|
|
201
|
+
Object {
|
|
202
|
+
"attrs": Object {
|
|
203
|
+
"value": "700",
|
|
204
|
+
},
|
|
205
|
+
"type": "font_weight",
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
"text": "lorem",
|
|
209
|
+
"type": "text",
|
|
210
|
+
},
|
|
211
|
+
Object {
|
|
212
|
+
"text": " ipsum",
|
|
213
|
+
"type": "text",
|
|
214
|
+
},
|
|
215
|
+
],
|
|
216
|
+
"type": "paragraph",
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
"type": "doc",
|
|
220
|
+
}
|
|
221
|
+
`;
|
|
222
|
+
|
|
194
223
|
exports[`parsing html should get value from strong tag 1`] = `
|
|
195
224
|
Object {
|
|
196
225
|
"content": Array [
|
|
@@ -286,4 +315,4 @@ Object {
|
|
|
286
315
|
}
|
|
287
316
|
`;
|
|
288
317
|
|
|
289
|
-
exports[`rendering should render html 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-font-weight:
|
|
318
|
+
exports[`rendering should render html 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-font-weight:700;\\" class=\\"zw-style\\">hello world</span></p>"`;
|
|
@@ -24,6 +24,30 @@ Object {
|
|
|
24
24
|
}
|
|
25
25
|
`;
|
|
26
26
|
|
|
27
|
+
exports[`parsing html should get value from rendered view 1`] = `
|
|
28
|
+
Object {
|
|
29
|
+
"content": Array [
|
|
30
|
+
Object {
|
|
31
|
+
"attrs": Object {
|
|
32
|
+
"line_height": Object {
|
|
33
|
+
"desktop": "1.4",
|
|
34
|
+
"mobile": "1.2",
|
|
35
|
+
"tablet": null,
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
"content": Array [
|
|
39
|
+
Object {
|
|
40
|
+
"text": "test",
|
|
41
|
+
"type": "text",
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
"type": "paragraph",
|
|
45
|
+
},
|
|
46
|
+
],
|
|
47
|
+
"type": "doc",
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
|
|
27
51
|
exports[`parsing html should get value from text in px units with font size 1`] = `
|
|
28
52
|
Object {
|
|
29
53
|
"content": Array [
|
|
@@ -116,6 +140,6 @@ Object {
|
|
|
116
140
|
}
|
|
117
141
|
`;
|
|
118
142
|
|
|
119
|
-
exports[`rendering should render all devices 1`] = `"<p class=\\"zw-style\\" style=\\"--zw-
|
|
143
|
+
exports[`rendering should render all devices 1`] = `"<p class=\\"zw-style\\" style=\\"--zw-line-height-mobile:1.21;--zw-line-height-tablet:1.4;--zw-line-height-desktop:1.6;\\">hello world</p>"`;
|
|
120
144
|
|
|
121
|
-
exports[`rendering should render only desktop 1`] = `"<p class=\\"zw-style\\" style=\\"--zw-
|
|
145
|
+
exports[`rendering should render only desktop 1`] = `"<p class=\\"zw-style\\" style=\\"--zw-line-height-desktop:1.3;\\">hello world</p>"`;
|
|
@@ -349,7 +349,9 @@ Object {
|
|
|
349
349
|
Object {
|
|
350
350
|
"attrs": Object {
|
|
351
351
|
"alignment": null,
|
|
352
|
-
"preset":
|
|
352
|
+
"preset": Object {
|
|
353
|
+
"id": "regular-1",
|
|
354
|
+
},
|
|
353
355
|
},
|
|
354
356
|
"content": Array [
|
|
355
357
|
Object {
|
|
@@ -385,7 +387,9 @@ Object {
|
|
|
385
387
|
Object {
|
|
386
388
|
"attrs": Object {
|
|
387
389
|
"alignment": null,
|
|
388
|
-
"preset":
|
|
390
|
+
"preset": Object {
|
|
391
|
+
"id": "regular-1",
|
|
392
|
+
},
|
|
389
393
|
},
|
|
390
394
|
"content": Array [
|
|
391
395
|
Object {
|
|
@@ -225,6 +225,36 @@ Object {
|
|
|
225
225
|
}
|
|
226
226
|
`;
|
|
227
227
|
|
|
228
|
+
exports[`parsing html should get both from rendered view 1`] = `
|
|
229
|
+
Object {
|
|
230
|
+
"content": Array [
|
|
231
|
+
Object {
|
|
232
|
+
"content": Array [
|
|
233
|
+
Object {
|
|
234
|
+
"marks": Array [
|
|
235
|
+
Object {
|
|
236
|
+
"attrs": Object {
|
|
237
|
+
"strike_through": true,
|
|
238
|
+
"underline": true,
|
|
239
|
+
},
|
|
240
|
+
"type": "text_decoration",
|
|
241
|
+
},
|
|
242
|
+
],
|
|
243
|
+
"text": "lorem",
|
|
244
|
+
"type": "text",
|
|
245
|
+
},
|
|
246
|
+
Object {
|
|
247
|
+
"text": " ipsum",
|
|
248
|
+
"type": "text",
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
"type": "paragraph",
|
|
252
|
+
},
|
|
253
|
+
],
|
|
254
|
+
"type": "doc",
|
|
255
|
+
}
|
|
256
|
+
`;
|
|
257
|
+
|
|
228
258
|
exports[`parsing html should get both from text 1`] = `
|
|
229
259
|
Object {
|
|
230
260
|
"content": Array [
|
|
@@ -281,6 +311,36 @@ Object {
|
|
|
281
311
|
}
|
|
282
312
|
`;
|
|
283
313
|
|
|
314
|
+
exports[`parsing html should get strike through from rendered view 1`] = `
|
|
315
|
+
Object {
|
|
316
|
+
"content": Array [
|
|
317
|
+
Object {
|
|
318
|
+
"content": Array [
|
|
319
|
+
Object {
|
|
320
|
+
"marks": Array [
|
|
321
|
+
Object {
|
|
322
|
+
"attrs": Object {
|
|
323
|
+
"strike_through": true,
|
|
324
|
+
"underline": false,
|
|
325
|
+
},
|
|
326
|
+
"type": "text_decoration",
|
|
327
|
+
},
|
|
328
|
+
],
|
|
329
|
+
"text": "lorem",
|
|
330
|
+
"type": "text",
|
|
331
|
+
},
|
|
332
|
+
Object {
|
|
333
|
+
"text": " ipsum",
|
|
334
|
+
"type": "text",
|
|
335
|
+
},
|
|
336
|
+
],
|
|
337
|
+
"type": "paragraph",
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
"type": "doc",
|
|
341
|
+
}
|
|
342
|
+
`;
|
|
343
|
+
|
|
284
344
|
exports[`parsing html should get strike through from text 1`] = `
|
|
285
345
|
Object {
|
|
286
346
|
"content": Array [
|
|
@@ -337,6 +397,36 @@ Object {
|
|
|
337
397
|
}
|
|
338
398
|
`;
|
|
339
399
|
|
|
400
|
+
exports[`parsing html should get underline from rendered view 1`] = `
|
|
401
|
+
Object {
|
|
402
|
+
"content": Array [
|
|
403
|
+
Object {
|
|
404
|
+
"content": Array [
|
|
405
|
+
Object {
|
|
406
|
+
"marks": Array [
|
|
407
|
+
Object {
|
|
408
|
+
"attrs": Object {
|
|
409
|
+
"strike_through": false,
|
|
410
|
+
"underline": true,
|
|
411
|
+
},
|
|
412
|
+
"type": "text_decoration",
|
|
413
|
+
},
|
|
414
|
+
],
|
|
415
|
+
"text": "lorem",
|
|
416
|
+
"type": "text",
|
|
417
|
+
},
|
|
418
|
+
Object {
|
|
419
|
+
"text": " ipsum",
|
|
420
|
+
"type": "text",
|
|
421
|
+
},
|
|
422
|
+
],
|
|
423
|
+
"type": "paragraph",
|
|
424
|
+
},
|
|
425
|
+
],
|
|
426
|
+
"type": "doc",
|
|
427
|
+
}
|
|
428
|
+
`;
|
|
429
|
+
|
|
340
430
|
exports[`parsing html should get underline from text 1`] = `
|
|
341
431
|
Object {
|
|
342
432
|
"content": Array [
|
|
@@ -406,8 +496,8 @@ Object {
|
|
|
406
496
|
}
|
|
407
497
|
`;
|
|
408
498
|
|
|
409
|
-
exports[`rendering should render both 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-text-decoration:
|
|
499
|
+
exports[`rendering should render both 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-text-decoration:underline line-through;\\" class=\\"zw-style\\">hello world</span></p>"`;
|
|
410
500
|
|
|
411
|
-
exports[`rendering should render strike through only 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-text-decoration:
|
|
501
|
+
exports[`rendering should render strike through only 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-text-decoration:line-through;\\" class=\\"zw-style\\">hello world</span></p>"`;
|
|
412
502
|
|
|
413
|
-
exports[`rendering should render underline only 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-text-decoration:
|
|
503
|
+
exports[`rendering should render underline only 1`] = `"<p class=\\"zw-style\\"><span style=\\"--zw-text-decoration:underline;\\" class=\\"zw-style\\">hello world</span></p>"`;
|
|
@@ -17,6 +17,16 @@ export const TextProcessor = Extension.create({
|
|
|
17
17
|
|
|
18
18
|
addCommands() {
|
|
19
19
|
return {
|
|
20
|
+
getSelectedText: createCommand(({ state }) => {
|
|
21
|
+
const { from, to } = state.selection;
|
|
22
|
+
|
|
23
|
+
return state.doc.textBetween(from, to, ' ');
|
|
24
|
+
}),
|
|
25
|
+
|
|
26
|
+
unsetMarks: createCommand(({ commands }, marks) => {
|
|
27
|
+
marks.forEach((mark) => commands.unsetMark(mark));
|
|
28
|
+
}),
|
|
29
|
+
|
|
20
30
|
transformText: createCommand(({ state }, transform) => {
|
|
21
31
|
const { selection } = state.tr;
|
|
22
32
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Editor, Extension } from '@tiptap/vue-2';
|
|
2
2
|
import { NodeFactory } from '../../../__tests__/utils';
|
|
3
|
-
import { CORE_EXTENSIONS } from '../index';
|
|
4
3
|
import { NodeTypes } from '../../../enums';
|
|
5
4
|
import { ContentNormalizer } from '../../../services';
|
|
5
|
+
import { buildCoreExtensions } from '../index';
|
|
6
6
|
|
|
7
7
|
const LineHeight = Extension.create({
|
|
8
8
|
name: 'line_height',
|
|
@@ -21,11 +21,9 @@ const LineHeight = Extension.create({
|
|
|
21
21
|
});
|
|
22
22
|
|
|
23
23
|
function createEditor({ content }) {
|
|
24
|
-
const normalizer = new ContentNormalizer();
|
|
25
|
-
|
|
26
24
|
return new Editor({
|
|
27
|
-
content:
|
|
28
|
-
extensions:
|
|
25
|
+
content: ContentNormalizer.normalize(content),
|
|
26
|
+
extensions: buildCoreExtensions().concat(LineHeight) // Included to core extensions
|
|
29
27
|
});
|
|
30
28
|
}
|
|
31
29
|
|
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/vue-2';
|
|
2
|
-
import { CORE_EXTENSIONS } from '../index';
|
|
3
2
|
import { NodeFactory } from '../../../__tests__/utils';
|
|
4
3
|
import { ContentNormalizer } from '../../../services';
|
|
4
|
+
import { buildCoreExtensions } from '../index';
|
|
5
5
|
|
|
6
6
|
function createEditor() {
|
|
7
|
-
const normalizer = new ContentNormalizer();
|
|
8
|
-
|
|
9
7
|
const content = NodeFactory.doc([
|
|
10
8
|
NodeFactory.paragraph('Lorem ipsum dolor sit amet'),
|
|
11
9
|
NodeFactory.paragraph('consectetur adipisicing elit')
|
|
12
10
|
]);
|
|
13
11
|
|
|
14
12
|
return new Editor({
|
|
15
|
-
content:
|
|
16
|
-
extensions:
|
|
13
|
+
content: ContentNormalizer.normalize(content),
|
|
14
|
+
extensions: buildCoreExtensions() // included to core
|
|
17
15
|
});
|
|
18
16
|
}
|
|
19
17
|
|
|
@@ -1,29 +1,120 @@
|
|
|
1
|
-
import { Editor, Mark } from '@tiptap/vue-2';
|
|
1
|
+
import { Editor, Mark, Extension } from '@tiptap/vue-2';
|
|
2
2
|
import { NodeFactory } from '../../../__tests__/utils';
|
|
3
|
-
import { CORE_EXTENSIONS } from '../index';
|
|
4
3
|
import { ContentNormalizer } from '../../../services';
|
|
4
|
+
import { NodeTypes, TextSettings } from '../../../enums';
|
|
5
|
+
import { buildCoreExtensions } from '../index';
|
|
6
|
+
|
|
7
|
+
const MockFontSize = Mark.create({
|
|
8
|
+
name: TextSettings.FONT_SIZE,
|
|
9
|
+
|
|
10
|
+
addAttributes: () => ({
|
|
11
|
+
value: { default: null }
|
|
12
|
+
}),
|
|
13
|
+
|
|
14
|
+
renderHTML: () => ['span', {}, 0]
|
|
15
|
+
});
|
|
5
16
|
|
|
6
17
|
const MockFontWeight = Mark.create({
|
|
7
|
-
name:
|
|
18
|
+
name: TextSettings.FONT_WEIGHT,
|
|
8
19
|
|
|
9
20
|
addAttributes: () => ({
|
|
10
|
-
value: {
|
|
21
|
+
value: { default: null }
|
|
11
22
|
}),
|
|
12
23
|
|
|
13
|
-
renderHTML(
|
|
14
|
-
|
|
24
|
+
renderHTML: () => ['span', {}, 0]
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const MockAlignment = Extension.create({
|
|
28
|
+
name: TextSettings.ALIGNMENT,
|
|
15
29
|
|
|
16
|
-
|
|
17
|
-
|
|
30
|
+
addGlobalAttributes: () => [
|
|
31
|
+
{
|
|
32
|
+
types: [NodeTypes.PARAGRAPH, NodeTypes.HEADING],
|
|
33
|
+
attributes: {
|
|
34
|
+
[TextSettings.ALIGNMENT]: {
|
|
35
|
+
default: null,
|
|
36
|
+
renderHTML: () => ({})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
]
|
|
18
41
|
});
|
|
19
42
|
|
|
20
|
-
|
|
21
|
-
|
|
43
|
+
const MockBackgroundColor = Mark.create({
|
|
44
|
+
name: TextSettings.BACKGROUND_COLOR,
|
|
45
|
+
|
|
46
|
+
addAttributes: () => ({
|
|
47
|
+
value: { default: null }
|
|
48
|
+
}),
|
|
49
|
+
|
|
50
|
+
renderHTML: () => ['span', {}, 0]
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const MockFontColor = Mark.create({
|
|
54
|
+
name: TextSettings.FONT_COLOR,
|
|
55
|
+
|
|
56
|
+
addAttributes: () => ({
|
|
57
|
+
value: { default: null }
|
|
58
|
+
}),
|
|
59
|
+
|
|
60
|
+
renderHTML: () => ['span', {}, 0]
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
const MockFontFamily = Mark.create({
|
|
64
|
+
name: TextSettings.FONT_FAMILY,
|
|
65
|
+
|
|
66
|
+
addAttributes: () => ({
|
|
67
|
+
value: { default: null }
|
|
68
|
+
}),
|
|
69
|
+
|
|
70
|
+
renderHTML: () => ['span', {}, 0]
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const MockFontStyle = Mark.create({
|
|
74
|
+
name: TextSettings.FONT_STYLE,
|
|
75
|
+
|
|
76
|
+
addAttributes: () => ({
|
|
77
|
+
value: { default: null }
|
|
78
|
+
}),
|
|
79
|
+
|
|
80
|
+
renderHTML: () => ['span', {}, 0]
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const MockTextDecoration = Mark.create({
|
|
84
|
+
name: TextSettings.TEXT_DECORATION,
|
|
85
|
+
|
|
86
|
+
addAttributes: () => ({
|
|
87
|
+
value: { default: null }
|
|
88
|
+
}),
|
|
22
89
|
|
|
90
|
+
renderHTML: () => ['span', {}, 0]
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const MockSuperscript = Mark.create({
|
|
94
|
+
name: TextSettings.SUPERSCRIPT,
|
|
95
|
+
|
|
96
|
+
addAttributes: () => ({
|
|
97
|
+
value: { default: null }
|
|
98
|
+
}),
|
|
99
|
+
|
|
100
|
+
renderHTML: () => ['span', {}, 0]
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
function createEditor({ content }) {
|
|
23
104
|
return new Editor({
|
|
24
|
-
content:
|
|
105
|
+
content: ContentNormalizer.normalize(content),
|
|
25
106
|
element: document.createElement('div'),
|
|
26
|
-
extensions:
|
|
107
|
+
extensions: buildCoreExtensions().concat(
|
|
108
|
+
MockFontSize,
|
|
109
|
+
MockFontWeight,
|
|
110
|
+
MockAlignment,
|
|
111
|
+
MockBackgroundColor,
|
|
112
|
+
MockFontColor,
|
|
113
|
+
MockFontFamily,
|
|
114
|
+
MockFontStyle,
|
|
115
|
+
MockTextDecoration,
|
|
116
|
+
MockSuperscript
|
|
117
|
+
)
|
|
27
118
|
});
|
|
28
119
|
}
|
|
29
120
|
|
|
@@ -62,3 +153,38 @@ describe('transform text', () => {
|
|
|
62
153
|
expect(editor.getJSON()).toMatchSnapshot();
|
|
63
154
|
});
|
|
64
155
|
});
|
|
156
|
+
|
|
157
|
+
describe('selected text', () => {
|
|
158
|
+
test('should return selected text', () => {
|
|
159
|
+
const editor = createEditor({
|
|
160
|
+
content: NodeFactory.doc([
|
|
161
|
+
NodeFactory.paragraph('hello world')
|
|
162
|
+
])
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
editor.commands.setTextSelection({ from: 5, to: 11 });
|
|
166
|
+
|
|
167
|
+
expect(editor.commands.getSelectedText()).toEqual('o worl');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
describe('unset marks', () => {
|
|
172
|
+
test('should reset all marks', () => {
|
|
173
|
+
const editor = createEditor({
|
|
174
|
+
content: NodeFactory.doc([
|
|
175
|
+
NodeFactory.paragraph([
|
|
176
|
+
NodeFactory.text('hello world', [
|
|
177
|
+
NodeFactory.mark('font_weight', { value: '700' })
|
|
178
|
+
])
|
|
179
|
+
])
|
|
180
|
+
])
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
editor.chain()
|
|
184
|
+
.selectAll()
|
|
185
|
+
.unsetMarks(TextSettings.marks)
|
|
186
|
+
.run();
|
|
187
|
+
|
|
188
|
+
expect(editor.getJSON()).toMatchSnapshot();
|
|
189
|
+
});
|
|
190
|
+
});
|
|
@@ -4,6 +4,9 @@ exports[`transform text should keep text marks 1`] = `
|
|
|
4
4
|
Object {
|
|
5
5
|
"content": Array [
|
|
6
6
|
Object {
|
|
7
|
+
"attrs": Object {
|
|
8
|
+
"alignment": null,
|
|
9
|
+
},
|
|
7
10
|
"content": Array [
|
|
8
11
|
Object {
|
|
9
12
|
"marks": Array [
|
|
@@ -29,6 +32,9 @@ exports[`transform text should transform selected text 1`] = `
|
|
|
29
32
|
Object {
|
|
30
33
|
"content": Array [
|
|
31
34
|
Object {
|
|
35
|
+
"attrs": Object {
|
|
36
|
+
"alignment": null,
|
|
37
|
+
},
|
|
32
38
|
"content": Array [
|
|
33
39
|
Object {
|
|
34
40
|
"text": "hELLO world",
|
|
@@ -41,3 +47,23 @@ Object {
|
|
|
41
47
|
"type": "doc",
|
|
42
48
|
}
|
|
43
49
|
`;
|
|
50
|
+
|
|
51
|
+
exports[`unset marks should reset all marks 1`] = `
|
|
52
|
+
Object {
|
|
53
|
+
"content": Array [
|
|
54
|
+
Object {
|
|
55
|
+
"attrs": Object {
|
|
56
|
+
"alignment": null,
|
|
57
|
+
},
|
|
58
|
+
"content": Array [
|
|
59
|
+
Object {
|
|
60
|
+
"text": "hello world",
|
|
61
|
+
"type": "text",
|
|
62
|
+
},
|
|
63
|
+
],
|
|
64
|
+
"type": "paragraph",
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
"type": "doc",
|
|
68
|
+
}
|
|
69
|
+
`;
|
|
@@ -1,17 +1,26 @@
|
|
|
1
1
|
import Document from '@tiptap/extension-document';
|
|
2
2
|
import Paragraph from '@tiptap/extension-paragraph';
|
|
3
3
|
import Text from '@tiptap/extension-text';
|
|
4
|
+
import Placeholder from '@tiptap/extension-placeholder';
|
|
5
|
+
import History from '@tiptap/extension-history';
|
|
4
6
|
import { NodeProcessor } from './NodeProcessor';
|
|
5
7
|
import { TextProcessor } from './TextProcessor';
|
|
6
8
|
import { SelectionProcessor } from './SelectionProcessor';
|
|
9
|
+
import { CopyPasteProcessor } from './CopyPasteProcessor';
|
|
7
10
|
|
|
8
|
-
export const
|
|
11
|
+
export const buildCoreExtensions = () => [
|
|
9
12
|
Document,
|
|
10
13
|
Paragraph.configure({
|
|
11
14
|
HTMLAttributes: { class: 'zw-style' }
|
|
12
15
|
}),
|
|
13
16
|
Text,
|
|
17
|
+
Placeholder.configure({
|
|
18
|
+
placeholder: 'Type your text here...',
|
|
19
|
+
emptyNodeClass: 'zw-wysiwyg__placeholder'
|
|
20
|
+
}),
|
|
21
|
+
History,
|
|
14
22
|
NodeProcessor,
|
|
15
23
|
TextProcessor,
|
|
16
|
-
SelectionProcessor
|
|
24
|
+
SelectionProcessor,
|
|
25
|
+
CopyPasteProcessor
|
|
17
26
|
];
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ContentNormalizer } from '../../../services';
|
|
2
|
+
import { ProseMirrorPlugin } from './ProseMirrorPlugin';
|
|
3
|
+
|
|
4
|
+
export class PastePlugin extends ProseMirrorPlugin {
|
|
5
|
+
buildProps() {
|
|
6
|
+
return {
|
|
7
|
+
transformPastedHTML: ContentNormalizer.normalize,
|
|
8
|
+
handlePaste: this._handlePaste.bind(this)
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
_handlePaste(view, _, slice) {
|
|
13
|
+
const transaction = this._insertPastedContent(view, slice)
|
|
14
|
+
.scrollIntoView()
|
|
15
|
+
.setMeta('paste', true)
|
|
16
|
+
.setMeta('uiEvent', 'paste');
|
|
17
|
+
|
|
18
|
+
view.dispatch(transaction);
|
|
19
|
+
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
_insertPastedContent({ state, input }, slice) {
|
|
24
|
+
if (!this._isSingleNode(slice)) {
|
|
25
|
+
return state.tr.replaceSelection(slice);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const { $from, $to } = state.selection;
|
|
29
|
+
const isSingleNodeReplacing = $from.sharedDepth($to.pos) === $from.depth;
|
|
30
|
+
|
|
31
|
+
if (!isSingleNodeReplacing) {
|
|
32
|
+
return state.tr.replaceSelection(slice);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const selectionSize = Math.abs($from.pos - $to.pos);
|
|
36
|
+
const { nodeSize } = $to.path.reverse().find((step) => typeof step === 'object');
|
|
37
|
+
|
|
38
|
+
if (nodeSize - selectionSize > 5) {
|
|
39
|
+
return state.tr.replaceSelection(slice);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return state.tr.replaceSelectionWith(slice.content.firstChild, input.shiftKey);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_isSingleNode({ openStart, openEnd, content }) {
|
|
46
|
+
return openStart === 1 && openEnd === 1 && content.childCount === 1;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
2
|
+
|
|
3
|
+
export class ProseMirrorPlugin {
|
|
4
|
+
static create(options) {
|
|
5
|
+
const plugin = new this(options || {});
|
|
6
|
+
|
|
7
|
+
return new Plugin({
|
|
8
|
+
key: new PluginKey(this.name),
|
|
9
|
+
props: plugin.buildProps()
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
constructor(options) {
|
|
14
|
+
this.options = options;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
buildProps() {
|
|
18
|
+
return {};
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { PastePlugin } from './PastePlugin';
|