@zipify/wysiwyg 2.0.0-9 → 2.1.0-builder-modes.0
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/dist/cli.js +2 -2
- package/dist/wysiwyg.css +9 -9
- package/dist/wysiwyg.mjs +2691 -2683
- package/lib/assets/icons/indicator.svg +1 -1
- package/lib/cli/commands/ToJsonCommand.js +15 -6
- package/lib/components/toolbar/controls/AlignmentControl.vue +1 -1
- package/lib/components/toolbar/controls/FontColorControl.vue +1 -1
- package/lib/components/toolbar/controls/FontFamilyControl.vue +1 -1
- package/lib/components/toolbar/controls/FontSizeControl.vue +1 -1
- package/lib/components/toolbar/controls/FontWeightControl.vue +1 -1
- package/lib/components/toolbar/controls/ItalicControl.vue +1 -1
- package/lib/components/toolbar/controls/LineHeightControl.vue +1 -1
- package/lib/entry-lib.js +1 -1
- package/lib/extensions/Alignment.js +2 -5
- package/lib/extensions/FontSize.js +24 -6
- package/lib/extensions/LineHeight.js +2 -8
- package/lib/extensions/StylePreset.js +2 -1
- package/lib/extensions/Superscript.js +25 -12
- package/lib/extensions/__tests__/StylePreset.test.js +4 -4
- package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +2 -2
- package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +5 -5
- package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +1 -1
- package/lib/extensions/__tests__/__snapshots__/Superscript.test.js.snap +5 -5
- package/lib/extensions/core/NodeProcessor.js +11 -7
- package/lib/extensions/core/index.js +16 -7
- package/lib/extensions/core/plugins/PastePlugin.js +4 -0
- package/lib/extensions/core/plugins/PlaceholderPlugin.js +30 -0
- package/lib/extensions/core/plugins/ProseMirrorPlugin.js +4 -3
- package/lib/extensions/core/plugins/index.js +1 -0
- package/lib/extensions/index.js +2 -1
- package/lib/extensions/list/List.js +7 -4
- package/lib/extensions/list/ListItem.js +35 -4
- package/lib/services/NodeFactory.js +1 -4
- package/lib/services/__tests__/__snapshots__/NodeFactory.test.js.snap +1 -1
- package/lib/styles/content.css +1 -1
- package/lib/utils/__tests__/isMarkAppliedToParent.test.js +5 -5
- package/lib/utils/isMarkAppliedToParent.js +7 -2
- package/package.json +9 -3
- package/lib/extensions/core/CopyPasteProcessor.js +0 -10
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 9 9">
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" style="width:var(--zw-icon-width);height:var(--zw-icon-height)" viewBox="0 0 9 9">
|
|
2
2
|
<path fill="#FFAB00" d="M0 4.5a4.5 4.5 0 1 1 9 0 4.5 4.5 0 0 1-9 0Z"/>
|
|
3
3
|
<path fill="#fff" fill-rule="evenodd" d="M5.063 2.25H3.938v3.375h1.124V2.25Zm-1.125 4.5a.562.562 0 1 1 1.123-.001.562.562 0 0 1-1.123.001Z" clip-rule="evenodd"/>
|
|
4
4
|
</svg>
|
|
@@ -9,19 +9,25 @@ export class ToJsonCommand extends Command {
|
|
|
9
9
|
|
|
10
10
|
options = [
|
|
11
11
|
{
|
|
12
|
-
flags: '--config <path>',
|
|
12
|
+
flags: '-c, --config <path>',
|
|
13
13
|
description: 'Generator config',
|
|
14
14
|
// Relative to dist folder
|
|
15
15
|
default: resolve(__dirname, '../bin/zp.config.json')
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
flags: '-f, --format <type>',
|
|
19
|
+
description: 'Set output format',
|
|
20
|
+
default: 'rb'
|
|
16
21
|
}
|
|
17
22
|
];
|
|
18
23
|
|
|
19
|
-
doCommand(html, { config }) {
|
|
24
|
+
doCommand(html, { config, format }) {
|
|
20
25
|
const configPath = resolve(process.cwd(), config);
|
|
21
26
|
const serializer = ContentSerializer.build(require(configPath).editor);
|
|
22
|
-
const
|
|
27
|
+
const content = serializer.toJSON(this.#formatInputHtml(html));
|
|
28
|
+
const json = this.#stringifyContent(content);
|
|
23
29
|
|
|
24
|
-
this.output(this.#
|
|
30
|
+
this.output(format === 'rb' ? this.#formatOutputRb(json) : json);
|
|
25
31
|
}
|
|
26
32
|
|
|
27
33
|
#formatInputHtml(html) {
|
|
@@ -32,10 +38,13 @@ export class ToJsonCommand extends Command {
|
|
|
32
38
|
});
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
#
|
|
41
|
+
#stringifyContent(content) {
|
|
36
42
|
const skipNullValue = (_, value) => value === null ? undefined : value;
|
|
37
|
-
const json = JSON.stringify(object, skipNullValue, 2);
|
|
38
43
|
|
|
44
|
+
return JSON.stringify(content, skipNullValue, 2);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#formatOutputRb(json) {
|
|
39
48
|
return json
|
|
40
49
|
.replace(/\\"/g, '"')
|
|
41
50
|
.replace(/font-family: ?'(.+)'/g, 'font-family: "$1"')
|
|
@@ -66,7 +66,7 @@ export default {
|
|
|
66
66
|
const editor = inject(InjectionTokens.EDITOR);
|
|
67
67
|
|
|
68
68
|
const currentValue = editor.commands.getAlignment();
|
|
69
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
69
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.ALIGNMENT);
|
|
70
70
|
|
|
71
71
|
function apply(value) {
|
|
72
72
|
editor.chain().focus().applyAlignment(value).run();
|
|
@@ -48,7 +48,7 @@ export default {
|
|
|
48
48
|
const editor = inject(InjectionTokens.EDITOR);
|
|
49
49
|
|
|
50
50
|
const currentValue = editor.commands.getFontColor();
|
|
51
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
51
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_COLOR);
|
|
52
52
|
|
|
53
53
|
const apply = (color) => editor.chain().applyFontColor(color).run();
|
|
54
54
|
|
|
@@ -69,7 +69,7 @@ export default {
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
const currentValue = editor.commands.getFontFamily();
|
|
72
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
72
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_FAMILY);
|
|
73
73
|
|
|
74
74
|
const apply = (fontFamily) => {
|
|
75
75
|
recentFontNames.add(fontFamily);
|
|
@@ -36,7 +36,7 @@ export default {
|
|
|
36
36
|
});
|
|
37
37
|
|
|
38
38
|
const currentValue = editor.commands.getFontSize();
|
|
39
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
39
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_SIZE);
|
|
40
40
|
|
|
41
41
|
const apply = (value) => editor.chain().focus().applyFontSize(value).run();
|
|
42
42
|
|
|
@@ -34,7 +34,7 @@ export default {
|
|
|
34
34
|
const options = computed(() => unref(font).weights.map((style) => ({ id: style })));
|
|
35
35
|
|
|
36
36
|
const currentValue = editor.commands.getFontWeight();
|
|
37
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
37
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_WEIGHT);
|
|
38
38
|
|
|
39
39
|
const apply = (value) => editor.chain().focus().applyFontWeight(value).run();
|
|
40
40
|
|
|
@@ -44,7 +44,7 @@ export default {
|
|
|
44
44
|
const editor = inject(InjectionTokens.EDITOR);
|
|
45
45
|
|
|
46
46
|
const currentValue = editor.commands.isItalic();
|
|
47
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
47
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_STYLE);
|
|
48
48
|
|
|
49
49
|
const isAvailable = editor.commands.isItalicAvailable();
|
|
50
50
|
const apply = () => editor.chain().focus().toggleItalic().run();
|
|
@@ -79,7 +79,7 @@ export default {
|
|
|
79
79
|
const toggler = useModalToggler({ wrapperRef, modalRef });
|
|
80
80
|
|
|
81
81
|
const currentValue = editor.commands.getLineHeight();
|
|
82
|
-
const isCustomized = editor.commands.isSettingCustomized(
|
|
82
|
+
const isCustomized = editor.commands.isSettingCustomized(TextSettings.LINE_HEIGHT);
|
|
83
83
|
|
|
84
84
|
const apply = (value) => editor.commands.applyLineHeight(String(value));
|
|
85
85
|
|
package/lib/entry-lib.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { default as Wysiwyg } from './Wysiwyg';
|
|
2
2
|
export { NodeFactory } from './services';
|
|
3
3
|
export { NodeTypes, TextSettings, Alignments } from './enums';
|
|
4
|
-
export { isWysiwygContent } from './utils';
|
|
4
|
+
export { isWysiwygContent, unmarkWysiwygContent, markWysiwygContent } from './utils';
|
|
@@ -52,12 +52,9 @@ export const Alignment = Extension.create({
|
|
|
52
52
|
addCommands() {
|
|
53
53
|
return {
|
|
54
54
|
applyAlignment: createCommand(({ commands }, value) => {
|
|
55
|
-
|
|
56
|
-
//
|
|
57
|
-
// commands.setBlockAttributes(this.name, { [device]: value }, DEFAULTS);
|
|
55
|
+
const device = unref(commands.getDevice());
|
|
58
56
|
|
|
59
|
-
|
|
60
|
-
commands.setBlockAttributes(this.name, { desktop: value, tablet: value, mobile: value });
|
|
57
|
+
commands.setBlockAttributes(this.name, { [device]: value }, DEFAULTS);
|
|
61
58
|
}),
|
|
62
59
|
|
|
63
60
|
getAlignment: createCommand(({ commands }) => {
|
|
@@ -2,6 +2,7 @@ import { Mark } from '@tiptap/vue-2';
|
|
|
2
2
|
import { computed, unref } from 'vue';
|
|
3
3
|
import { convertFontSize, createCommand, createKeyboardShortcut, renderMark } from '../utils';
|
|
4
4
|
import { MarkGroups, TextSettings } from '../enums';
|
|
5
|
+
import { AddNodeMarkStep } from './core';
|
|
5
6
|
|
|
6
7
|
export const FontSize = Mark.create({
|
|
7
8
|
name: TextSettings.FONT_SIZE,
|
|
@@ -34,12 +35,31 @@ export const FontSize = Mark.create({
|
|
|
34
35
|
}),
|
|
35
36
|
|
|
36
37
|
applyFontSize: createCommand(({ commands }, value) => {
|
|
37
|
-
|
|
38
|
+
const device = unref(commands.getDevice());
|
|
38
39
|
|
|
39
|
-
|
|
40
|
+
commands.applyMark(this.name, { [device]: value }, {
|
|
41
|
+
isAppliedToParent: (parentMark, mark) => {
|
|
42
|
+
if (parentMark.type.name !== mark.type.name) return false;
|
|
40
43
|
|
|
41
|
-
|
|
42
|
-
|
|
44
|
+
return parentMark.attrs[device] === mark.attrs[device];
|
|
45
|
+
},
|
|
46
|
+
|
|
47
|
+
onAppliedToParent: ({ tr, node, position, mark }) => {
|
|
48
|
+
const attrs = { ...mark.attrs, [device]: null };
|
|
49
|
+
const canRemove = !Object.values(attrs).some((value) => !!value);
|
|
50
|
+
|
|
51
|
+
if (canRemove) return false;
|
|
52
|
+
|
|
53
|
+
const updated = mark.type.create(attrs);
|
|
54
|
+
|
|
55
|
+
if (node.isText) {
|
|
56
|
+
tr.addMark(position, position + node.nodeSize, updated);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
tr.step(new AddNodeMarkStep(position, updated));
|
|
61
|
+
}
|
|
62
|
+
});
|
|
43
63
|
}),
|
|
44
64
|
|
|
45
65
|
increaseFontSize: createCommand(({ commands }) => {
|
|
@@ -89,8 +109,6 @@ export const FontSize = Mark.create({
|
|
|
89
109
|
getAttrs: (input) => {
|
|
90
110
|
const value = parseSize(input);
|
|
91
111
|
|
|
92
|
-
// return { desktop: value, tablet: value, mobile: value };
|
|
93
|
-
// Temporary until release BUILDER_MODES
|
|
94
112
|
return { desktop: value, tablet: value, mobile: null };
|
|
95
113
|
}
|
|
96
114
|
}
|
|
@@ -36,9 +36,6 @@ export const LineHeight = Extension.create({
|
|
|
36
36
|
const wrapperEl = unref(this.options.wrapperRef);
|
|
37
37
|
const converted = convertLineHeight(value, element, wrapperEl);
|
|
38
38
|
|
|
39
|
-
// return { desktop: converted, tablet: converted, mobile: converted };
|
|
40
|
-
|
|
41
|
-
// Temporary until release BUILDER_MODES
|
|
42
39
|
return { desktop: converted, tablet: converted, mobile: null };
|
|
43
40
|
},
|
|
44
41
|
|
|
@@ -75,12 +72,9 @@ export const LineHeight = Extension.create({
|
|
|
75
72
|
}),
|
|
76
73
|
|
|
77
74
|
applyLineHeight: createCommand(({ commands }, value) => {
|
|
78
|
-
|
|
79
|
-
//
|
|
80
|
-
// commands.setBlockAttributes(this.name, { [device]: value }, DEFAULTS);
|
|
75
|
+
const device = unref(commands.getDevice());
|
|
81
76
|
|
|
82
|
-
|
|
83
|
-
commands.setBlockAttributes(this.name, { desktop: value, tablet: value, mobile: null }, DEFAULTS);
|
|
77
|
+
commands.setBlockAttributes(this.name, { [device]: value }, DEFAULTS);
|
|
84
78
|
})
|
|
85
79
|
};
|
|
86
80
|
}
|
|
@@ -161,8 +161,9 @@ export const StylePreset = Extension.create({
|
|
|
161
161
|
});
|
|
162
162
|
}),
|
|
163
163
|
|
|
164
|
-
isSettingCustomized: createCommand(({ commands },
|
|
164
|
+
isSettingCustomized: createCommand(({ commands }, name) => {
|
|
165
165
|
const customization = commands.getPresetCustomization();
|
|
166
|
+
const group = TextSettings.attributes.includes(name) ? 'attributes' : 'marks';
|
|
166
167
|
|
|
167
168
|
return computed(() => unref(customization)[group]?.includes(name) ?? false);
|
|
168
169
|
}),
|
|
@@ -1,27 +1,25 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Mark } from '@tiptap/vue-2';
|
|
2
2
|
import { computed, unref } from 'vue';
|
|
3
3
|
import { createCommand } from '../utils';
|
|
4
4
|
import { TextSettings } from '../enums';
|
|
5
5
|
|
|
6
|
-
export const Superscript =
|
|
6
|
+
export const Superscript = Mark.create({
|
|
7
7
|
name: TextSettings.SUPERSCRIPT,
|
|
8
|
-
addKeyboardShortcuts: null,
|
|
9
|
-
|
|
10
|
-
addOptions: () => ({
|
|
11
|
-
HTMLAttributes: { class: 'zw-superscript' }
|
|
12
|
-
}),
|
|
13
8
|
|
|
14
9
|
addCommands() {
|
|
15
|
-
const { setSuperscript, unsetSuperscript } = this.parent();
|
|
16
|
-
|
|
17
10
|
return {
|
|
18
|
-
applySuperscript:
|
|
19
|
-
|
|
11
|
+
applySuperscript: createCommand(({ commands }) => {
|
|
12
|
+
commands.setMark(this.name);
|
|
13
|
+
}),
|
|
14
|
+
|
|
15
|
+
removeSuperscript: createCommand(({ commands }) => {
|
|
16
|
+
commands.unsetMark(this.name);
|
|
17
|
+
}),
|
|
20
18
|
|
|
21
19
|
toggleSuperscript: createCommand(({ commands }) => {
|
|
22
20
|
const isActive = unref(commands.isSuperscript());
|
|
23
21
|
|
|
24
|
-
isActive ? commands.
|
|
22
|
+
isActive ? commands.removeSuperscript() : commands.applySuperscript();
|
|
25
23
|
}),
|
|
26
24
|
|
|
27
25
|
isSuperscript: createCommand(({ commands }) => {
|
|
@@ -30,5 +28,20 @@ export const Superscript = Base.extend({
|
|
|
30
28
|
return computed(() => !!unref(selectionRef));
|
|
31
29
|
})
|
|
32
30
|
};
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
parseHTML() {
|
|
34
|
+
return [
|
|
35
|
+
{ tag: 'sup' },
|
|
36
|
+
|
|
37
|
+
{
|
|
38
|
+
style: 'vertical-align',
|
|
39
|
+
getAttrs: (value) => value !== 'super' ? false : null
|
|
40
|
+
}
|
|
41
|
+
];
|
|
42
|
+
},
|
|
43
|
+
|
|
44
|
+
renderHTML() {
|
|
45
|
+
return ['sup', { class: 'zw-superscript' }, 0];
|
|
33
46
|
}
|
|
34
47
|
});
|
|
@@ -413,8 +413,8 @@ describe('get preset customization', () => {
|
|
|
413
413
|
presets: [createPreset({ id: 'regular-1' })]
|
|
414
414
|
});
|
|
415
415
|
|
|
416
|
-
const isFontSizeCustomized = editor.commands.isSettingCustomized(
|
|
417
|
-
const isAlignmentCustomized = editor.commands.isSettingCustomized(
|
|
416
|
+
const isFontSizeCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_SIZE);
|
|
417
|
+
const isAlignmentCustomized = editor.commands.isSettingCustomized(TextSettings.ALIGNMENT);
|
|
418
418
|
|
|
419
419
|
expect(isFontSizeCustomized.value).toBe(false);
|
|
420
420
|
expect(isAlignmentCustomized.value).toBe(false);
|
|
@@ -454,7 +454,7 @@ describe('get preset customization', () => {
|
|
|
454
454
|
});
|
|
455
455
|
|
|
456
456
|
editor.commands.selectAll();
|
|
457
|
-
const isFontSizeCustomized = editor.commands.isSettingCustomized(
|
|
457
|
+
const isFontSizeCustomized = editor.commands.isSettingCustomized(TextSettings.FONT_SIZE);
|
|
458
458
|
|
|
459
459
|
expect(isFontSizeCustomized.value).toBe(true);
|
|
460
460
|
});
|
|
@@ -489,7 +489,7 @@ describe('get preset customization', () => {
|
|
|
489
489
|
});
|
|
490
490
|
|
|
491
491
|
editor.commands.selectAll();
|
|
492
|
-
const isAlignmentCustomized = editor.commands.isSettingCustomized(
|
|
492
|
+
const isAlignmentCustomized = editor.commands.isSettingCustomized(TextSettings.ALIGNMENT);
|
|
493
493
|
|
|
494
494
|
expect(isAlignmentCustomized.value).toBe(true);
|
|
495
495
|
});
|
|
@@ -15,7 +15,7 @@ Object {
|
|
|
15
15
|
"attrs": Object {
|
|
16
16
|
"desktop": "16",
|
|
17
17
|
"mobile": null,
|
|
18
|
-
"tablet":
|
|
18
|
+
"tablet": null,
|
|
19
19
|
},
|
|
20
20
|
"type": "font_size",
|
|
21
21
|
},
|
|
@@ -42,7 +42,7 @@ Object {
|
|
|
42
42
|
"attrs": Object {
|
|
43
43
|
"desktop": "13",
|
|
44
44
|
"mobile": null,
|
|
45
|
-
"tablet":
|
|
45
|
+
"tablet": null,
|
|
46
46
|
},
|
|
47
47
|
"type": "font_size",
|
|
48
48
|
},
|
|
@@ -69,7 +69,7 @@ Object {
|
|
|
69
69
|
"attrs": Object {
|
|
70
70
|
"desktop": "15",
|
|
71
71
|
"mobile": null,
|
|
72
|
-
"tablet":
|
|
72
|
+
"tablet": null,
|
|
73
73
|
},
|
|
74
74
|
"type": "font_size",
|
|
75
75
|
},
|
|
@@ -96,7 +96,7 @@ Object {
|
|
|
96
96
|
"attrs": Object {
|
|
97
97
|
"desktop": "5",
|
|
98
98
|
"mobile": null,
|
|
99
|
-
"tablet":
|
|
99
|
+
"tablet": null,
|
|
100
100
|
},
|
|
101
101
|
"type": "font_size",
|
|
102
102
|
},
|
|
@@ -123,7 +123,7 @@ Object {
|
|
|
123
123
|
"attrs": Object {
|
|
124
124
|
"desktop": "20",
|
|
125
125
|
"mobile": null,
|
|
126
|
-
"tablet":
|
|
126
|
+
"tablet": null,
|
|
127
127
|
},
|
|
128
128
|
"type": "font_size",
|
|
129
129
|
},
|
|
@@ -45,6 +45,11 @@ Object {
|
|
|
45
45
|
Object {
|
|
46
46
|
"content": Array [
|
|
47
47
|
Object {
|
|
48
|
+
"marks": Array [
|
|
49
|
+
Object {
|
|
50
|
+
"type": "superscript",
|
|
51
|
+
},
|
|
52
|
+
],
|
|
48
53
|
"text": "hello world",
|
|
49
54
|
"type": "text",
|
|
50
55
|
},
|
|
@@ -62,11 +67,6 @@ Object {
|
|
|
62
67
|
Object {
|
|
63
68
|
"content": Array [
|
|
64
69
|
Object {
|
|
65
|
-
"marks": Array [
|
|
66
|
-
Object {
|
|
67
|
-
"type": "superscript",
|
|
68
|
-
},
|
|
69
|
-
],
|
|
70
70
|
"text": "hello world",
|
|
71
71
|
"type": "text",
|
|
72
72
|
},
|
|
@@ -37,7 +37,7 @@ export const NodeProcessor = Extension.create({
|
|
|
37
37
|
return Object.keys(attrs).length ? attrs : null;
|
|
38
38
|
})),
|
|
39
39
|
|
|
40
|
-
applyMark: createCommand(({ state, commands }, name, value) => {
|
|
40
|
+
applyMark: createCommand(({ state, commands }, name, value, customizer = {}) => {
|
|
41
41
|
const { tr, doc, schema } = state;
|
|
42
42
|
const { $from, $to } = tr.selection;
|
|
43
43
|
const markType = getMarkType(name, schema);
|
|
@@ -50,6 +50,14 @@ export const NodeProcessor = Extension.create({
|
|
|
50
50
|
|
|
51
51
|
if ($from.pos === $to.pos) return;
|
|
52
52
|
|
|
53
|
+
const onAppliedToParent = (context) => {
|
|
54
|
+
if (!customizer.onAppliedToParent || customizer.onAppliedToParent(context) === false) {
|
|
55
|
+
const { tr, node, position, mark } = context;
|
|
56
|
+
|
|
57
|
+
commands._removeNodeMark({ tr, node, position, mark: mark.type });
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
|
|
53
61
|
doc.nodesBetween($from.pos, $to.pos, (node, position) => {
|
|
54
62
|
if (node.type.name === NodeTypes.LIST) return;
|
|
55
63
|
|
|
@@ -57,8 +65,8 @@ export const NodeProcessor = Extension.create({
|
|
|
57
65
|
const applyingMark = markType.create({ ...(initialMark?.attrs || {}), ...value });
|
|
58
66
|
const textPosition = resolveTextPosition($from, $to, node, position);
|
|
59
67
|
|
|
60
|
-
if (isMarkAppliedToParent(tr.doc, position, applyingMark)) {
|
|
61
|
-
return
|
|
68
|
+
if (isMarkAppliedToParent(tr.doc, position, applyingMark, customizer.isAppliedToParent)) {
|
|
69
|
+
return onAppliedToParent({ tr, node, position, mark: applyingMark });
|
|
62
70
|
}
|
|
63
71
|
|
|
64
72
|
if (node.isText) {
|
|
@@ -141,10 +149,6 @@ export const NodeProcessor = Extension.create({
|
|
|
141
149
|
});
|
|
142
150
|
}),
|
|
143
151
|
|
|
144
|
-
removeMark: createCommand(({ commands, state }, node, position, mark) => {
|
|
145
|
-
commands._removeNodeMark({ tr: state.tr, node, position, mark });
|
|
146
|
-
}),
|
|
147
|
-
|
|
148
152
|
_removeNodeMark: createCommand((context, { tr, node, position, mark }) => {
|
|
149
153
|
return node.isText
|
|
150
154
|
? tr.removeMark(position, position + node.nodeSize, mark)
|
|
@@ -1,20 +1,27 @@
|
|
|
1
|
+
import { Extension } from '@tiptap/vue-2';
|
|
1
2
|
import Text from '@tiptap/extension-text';
|
|
2
|
-
import Placeholder from '@tiptap/extension-placeholder';
|
|
3
3
|
import History from '@tiptap/extension-history';
|
|
4
4
|
import { NodeProcessor } from './NodeProcessor';
|
|
5
5
|
import { TextProcessor } from './TextProcessor';
|
|
6
6
|
import { SelectionProcessor } from './SelectionProcessor';
|
|
7
|
-
import { CopyPasteProcessor } from './CopyPasteProcessor';
|
|
8
7
|
import { Document } from './Document';
|
|
9
8
|
import { Paragraph } from './Paragraph';
|
|
10
9
|
import { Heading } from './Heading';
|
|
10
|
+
import { PastePlugin, PlaceholderPlugin } from './plugins';
|
|
11
|
+
|
|
12
|
+
const ProseMirrorPlugins = Extension.create({
|
|
13
|
+
name: 'prose_mirror_plugins',
|
|
14
|
+
|
|
15
|
+
addProseMirrorPlugins() {
|
|
16
|
+
return [
|
|
17
|
+
PastePlugin.create(this.editor),
|
|
18
|
+
PlaceholderPlugin.create(this.editor)
|
|
19
|
+
];
|
|
20
|
+
}
|
|
21
|
+
});
|
|
11
22
|
|
|
12
23
|
export const buildCoreExtensions = () => [
|
|
13
24
|
Document,
|
|
14
|
-
Placeholder.configure({
|
|
15
|
-
placeholder: 'Type your text here...',
|
|
16
|
-
emptyNodeClass: 'zw-wysiwyg__placeholder'
|
|
17
|
-
}),
|
|
18
25
|
Paragraph,
|
|
19
26
|
Heading,
|
|
20
27
|
Text,
|
|
@@ -22,5 +29,7 @@ export const buildCoreExtensions = () => [
|
|
|
22
29
|
NodeProcessor,
|
|
23
30
|
TextProcessor,
|
|
24
31
|
SelectionProcessor,
|
|
25
|
-
|
|
32
|
+
ProseMirrorPlugins
|
|
26
33
|
];
|
|
34
|
+
|
|
35
|
+
export * from './steps';
|
|
@@ -11,6 +11,10 @@ export class PastePlugin extends ProseMirrorPlugin {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
_transformPastedHTML(html) {
|
|
14
|
+
if (html.includes('data-pm-slice') && html.includes('zw-style')) {
|
|
15
|
+
return html;
|
|
16
|
+
}
|
|
17
|
+
|
|
14
18
|
const normalizer = ContentNormalizer.build(html);
|
|
15
19
|
|
|
16
20
|
normalizer.normalizeHTML();
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Decoration, DecorationSet } from 'prosemirror-view';
|
|
2
|
+
import { ProseMirrorPlugin } from './ProseMirrorPlugin';
|
|
3
|
+
|
|
4
|
+
export class PlaceholderPlugin extends ProseMirrorPlugin {
|
|
5
|
+
buildProps() {
|
|
6
|
+
return { decorations: this.#buildDecorations.bind(this) };
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
#buildDecorations({ doc }) {
|
|
10
|
+
const decorations = [];
|
|
11
|
+
|
|
12
|
+
if (!this.editor.isEditable) return null;
|
|
13
|
+
if (doc.childCount > 1) return;
|
|
14
|
+
|
|
15
|
+
doc.descendants((node, pos) => {
|
|
16
|
+
if (!node.childCount) {
|
|
17
|
+
const decoration = Decoration.node(pos, pos + node.nodeSize, {
|
|
18
|
+
class: 'zw-wysiwyg__placeholder',
|
|
19
|
+
'data-placeholder': 'Type your text here...'
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
decorations.push(decoration);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return false;
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
return DecorationSet.create(doc, decorations);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from 'prosemirror-state';
|
|
2
2
|
|
|
3
3
|
export class ProseMirrorPlugin {
|
|
4
|
-
static create(options) {
|
|
5
|
-
const plugin = new this(options || {});
|
|
4
|
+
static create(editor, options) {
|
|
5
|
+
const plugin = new this(editor, options || {});
|
|
6
6
|
|
|
7
7
|
return new Plugin({
|
|
8
8
|
key: new PluginKey(this.name),
|
|
@@ -10,8 +10,9 @@ export class ProseMirrorPlugin {
|
|
|
10
10
|
});
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
constructor(options) {
|
|
13
|
+
constructor(editor, options) {
|
|
14
14
|
this.options = options;
|
|
15
|
+
this.editor = editor;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
buildProps() {
|
package/lib/extensions/index.js
CHANGED
|
@@ -34,7 +34,8 @@ export function buildExtensions(options) {
|
|
|
34
34
|
makeVariable: options.makePresetVariable
|
|
35
35
|
}),
|
|
36
36
|
List.configure({
|
|
37
|
-
baseClass: options.baseListClass
|
|
37
|
+
baseClass: options.baseListClass,
|
|
38
|
+
presetClass: options.basePresetClass + options.defaultPresetId
|
|
38
39
|
}),
|
|
39
40
|
DeviceManager.configure({
|
|
40
41
|
device: options.deviceRef
|
|
@@ -16,7 +16,8 @@ export const List = Node.create({
|
|
|
16
16
|
],
|
|
17
17
|
|
|
18
18
|
addOptions: () => ({
|
|
19
|
-
baseClass: ''
|
|
19
|
+
baseClass: '',
|
|
20
|
+
presetClass: ''
|
|
20
21
|
}),
|
|
21
22
|
|
|
22
23
|
addAttributes: () => ({
|
|
@@ -60,11 +61,13 @@ export const List = Node.create({
|
|
|
60
61
|
},
|
|
61
62
|
|
|
62
63
|
renderHTML({ HTMLAttributes: attrs }) {
|
|
64
|
+
const classes = [
|
|
65
|
+
this.options.baseClass + attrs.bullet.type,
|
|
66
|
+
this.options.presetClass
|
|
67
|
+
];
|
|
63
68
|
const isOrdered = ListTypes.ordered.includes(attrs.bullet.type);
|
|
64
|
-
const tag = isOrdered ? 'ol' : 'ul';
|
|
65
|
-
const bulletClass = this.options.baseClass + attrs.bullet.type;
|
|
66
69
|
|
|
67
|
-
return [
|
|
70
|
+
return [isOrdered ? 'ol' : 'ul', { class: classes.join(' ') }, 0];
|
|
68
71
|
},
|
|
69
72
|
|
|
70
73
|
addCommands() {
|