@zipify/wysiwyg 1.3.0-0 → 2.0.0-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.
Files changed (84) hide show
  1. package/dist/cli.js +2 -2
  2. package/dist/wysiwyg.css +31 -42
  3. package/dist/wysiwyg.mjs +454 -399
  4. package/lib/__tests__/utils/buildTestExtensions.js +14 -0
  5. package/lib/__tests__/utils/index.js +1 -0
  6. package/lib/components/base/Button.vue +0 -7
  7. package/lib/components/base/dropdown/Dropdown.vue +1 -7
  8. package/lib/components/base/dropdown/DropdownActivator.vue +4 -19
  9. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +1 -23
  10. package/lib/components/toolbar/controls/AlignmentControl.vue +1 -11
  11. package/lib/components/toolbar/controls/FontColorControl.vue +0 -13
  12. package/lib/components/toolbar/controls/FontFamilyControl.vue +0 -4
  13. package/lib/components/toolbar/controls/FontSizeControl.vue +1 -6
  14. package/lib/components/toolbar/controls/FontWeightControl.vue +0 -12
  15. package/lib/components/toolbar/controls/ItalicControl.vue +0 -13
  16. package/lib/components/toolbar/controls/LineHeightControl.vue +0 -14
  17. package/lib/components/toolbar/controls/SuperscriptControl.vue +2 -2
  18. package/lib/components/toolbar/controls/UnderlineControl.vue +0 -12
  19. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +5 -72
  20. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +1 -22
  21. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +0 -1
  22. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +0 -1
  23. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +0 -1
  24. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +1 -23
  25. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +1 -23
  26. package/lib/components/toolbar/controls/__tests__/SuperscriptControl.test.js +2 -2
  27. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +1 -25
  28. package/lib/composables/__tests__/useEditor.test.js +2 -2
  29. package/lib/extensions/BackgroundColor.js +4 -4
  30. package/lib/extensions/FontColor.js +4 -5
  31. package/lib/extensions/FontFamily.js +4 -5
  32. package/lib/extensions/FontSize.js +5 -7
  33. package/lib/extensions/FontStyle.js +13 -11
  34. package/lib/extensions/FontWeight.js +6 -9
  35. package/lib/extensions/StylePreset.js +0 -14
  36. package/lib/extensions/Superscript.js +23 -1
  37. package/lib/extensions/TextDecoration.js +33 -20
  38. package/lib/extensions/__tests__/Alignment.test.js +10 -7
  39. package/lib/extensions/__tests__/BackgroundColor.test.js +6 -3
  40. package/lib/extensions/__tests__/CaseStyle.test.js +11 -7
  41. package/lib/extensions/__tests__/FontColor.test.js +6 -3
  42. package/lib/extensions/__tests__/FontFamily.test.js +29 -22
  43. package/lib/extensions/__tests__/FontSize.test.js +24 -17
  44. package/lib/extensions/__tests__/FontStyle.test.js +22 -16
  45. package/lib/extensions/__tests__/FontWeight.test.js +26 -19
  46. package/lib/extensions/__tests__/LineHeight.test.js +14 -11
  47. package/lib/extensions/__tests__/Link.test.js +14 -10
  48. package/lib/extensions/__tests__/Margin.test.js +2 -2
  49. package/lib/extensions/__tests__/StylePreset.test.js +49 -100
  50. package/lib/extensions/__tests__/TextDecoration.test.js +72 -46
  51. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +24 -24
  52. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +24 -24
  53. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +86 -82
  54. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +70 -70
  55. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +53 -45
  56. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +64 -60
  57. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +148 -83
  58. package/lib/extensions/core/Document.js +5 -0
  59. package/lib/extensions/core/Heading.js +10 -0
  60. package/lib/extensions/core/NodeProcessor.js +84 -4
  61. package/lib/extensions/core/Paragraph.js +9 -0
  62. package/lib/extensions/core/TextProcessor.js +10 -12
  63. package/lib/extensions/core/__tests__/NodeProcessor.test.js +82 -10
  64. package/lib/extensions/core/__tests__/SelectionProcessor.test.js +2 -2
  65. package/lib/extensions/core/__tests__/TextProcessor.test.js +18 -20
  66. package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +132 -0
  67. package/lib/extensions/core/index.js +5 -5
  68. package/lib/extensions/core/steps/AddNodeMarkStep.js +60 -0
  69. package/lib/extensions/core/steps/RemoveNodeMarkStep.js +50 -0
  70. package/lib/extensions/core/steps/index.js +2 -0
  71. package/lib/extensions/list/List.js +1 -0
  72. package/lib/extensions/list/ListItem.js +5 -0
  73. package/lib/extensions/list/__tests__/List.test.js +30 -25
  74. package/lib/services/ContentNormalizer.js +1 -100
  75. package/lib/services/NodeFactory.js +16 -6
  76. package/lib/services/__tests__/ContentNormalizer.test.js +0 -64
  77. package/lib/utils/findMarkByType.js +5 -0
  78. package/lib/utils/index.js +5 -0
  79. package/lib/utils/isMarkAppliedToParent.js +15 -0
  80. package/lib/utils/isNodeFullySelected.js +10 -0
  81. package/lib/utils/resolveNodePosition.js +6 -0
  82. package/lib/utils/resolveTextPosition.js +6 -0
  83. package/package.json +1 -1
  84. package/lib/assets/icons/indicator.svg +0 -5
@@ -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',
@@ -13,30 +13,28 @@ export const TextProcessor = Extension.create({
13
13
  }),
14
14
 
15
15
  unsetMarks: createCommand(({ commands }, marks) => {
16
+ // TODO check unset mark
16
17
  marks.forEach((mark) => commands.unsetMark(mark));
17
18
  }),
18
19
 
19
20
  transformText: createCommand(({ state }, transform) => {
20
- const { selection } = state.tr;
21
+ const { $from, $to } = state.tr.selection;
21
22
 
22
- if (selection.from === selection.to) return;
23
+ if ($from.pos === $to.pos) return;
23
24
 
24
- state.doc.nodesBetween(selection.from, selection.to, (node, position) => {
25
+ state.doc.nodesBetween($from.pos, $to.pos, (node, position) => {
25
26
  if (!node.isText) return;
26
27
 
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);
28
+ const textPosition = resolveTextPosition($from, $to, node, position);
29
+ const substringFrom = Math.max(0, $from.pos - position);
30
+ const substringTo = Math.max(0, $to.pos - position);
32
31
 
33
32
  const updatedText = transform({
34
- text: node.textContent.substring(substringFrom, substringTo),
35
- position: { start: startPosition, end: endPosition }
33
+ text: node.textContent.substring(substringFrom, substringTo)
36
34
  });
37
35
  const updatedNode = state.schema.text(updatedText, node.marks);
38
36
 
39
- state.tr.replaceWith(startPosition, endPosition, updatedNode);
37
+ state.tr.replaceWith(textPosition.from, textPosition.to, updatedNode);
40
38
  });
41
39
  })
42
40
  };
@@ -1,10 +1,10 @@
1
- import { Editor, Extension } from '@tiptap/vue-2';
2
- import { NodeTypes } from '../../../enums';
1
+ import { Editor, Extension, Mark } from '@tiptap/vue-2';
2
+ import { buildTestExtensions } from '../../../__tests__/utils';
3
+ import { NodeTypes, TextSettings } from '../../../enums';
3
4
  import { ContentNormalizer, NodeFactory } from '../../../services';
4
- import { buildCoreExtensions } from '../index';
5
5
 
6
- const LineHeight = Extension.create({
7
- name: 'line_height',
6
+ const MockLineHeight = Extension.create({
7
+ name: TextSettings.LINE_HEIGHT,
8
8
 
9
9
  addGlobalAttributes: () => [
10
10
  {
@@ -19,10 +19,19 @@ const LineHeight = Extension.create({
19
19
  ]
20
20
  });
21
21
 
22
+ const MockFontWeight = Mark.create({
23
+ name: TextSettings.FONT_WEIGHT,
24
+ group: 'settings',
25
+ renderHTML: () => ['span', {}, 0],
26
+ addAttributes: () => ({ value: { required: true } })
27
+ });
28
+
22
29
  function createEditor({ content }) {
23
30
  return new Editor({
24
31
  content: ContentNormalizer.normalize(content),
25
- extensions: buildCoreExtensions().concat(LineHeight) // Included to core extensions
32
+ extensions: buildTestExtensions({
33
+ include: [MockLineHeight, MockFontWeight]
34
+ })
26
35
  });
27
36
  }
28
37
 
@@ -79,7 +88,8 @@ describe('block attributes', () => {
79
88
  content: createContent({ line_height: null })
80
89
  });
81
90
 
82
- editor.chain().selectAll().setBlockAttributes('line_height', { mobile: '1.3' }).run();
91
+ editor.commands.selectAll();
92
+ editor.commands.setBlockAttributes('line_height', { mobile: '1.3' });
83
93
 
84
94
  expect(editor.getJSON()).toMatchSnapshot();
85
95
  });
@@ -89,7 +99,8 @@ describe('block attributes', () => {
89
99
  content: createContent({ line_height: null })
90
100
  });
91
101
 
92
- editor.chain().selectAll().setBlockAttributes('line_height', { mobile: '1.3' }, DEFAULTS).run();
102
+ editor.commands.selectAll();
103
+ editor.commands.setBlockAttributes('line_height', { mobile: '1.3' }, DEFAULTS);
93
104
 
94
105
  expect(editor.getJSON()).toMatchSnapshot();
95
106
  });
@@ -101,7 +112,8 @@ describe('block attributes', () => {
101
112
  })
102
113
  });
103
114
 
104
- editor.chain().selectAll().setBlockAttributes('line_height', { mobile: '1.3' }).run();
115
+ editor.commands.selectAll();
116
+ editor.commands.setBlockAttributes('line_height', { mobile: '1.3' });
105
117
 
106
118
  expect(editor.getJSON()).toMatchSnapshot();
107
119
  });
@@ -113,7 +125,67 @@ describe('block attributes', () => {
113
125
  })
114
126
  });
115
127
 
116
- editor.chain().selectAll().setBlockAttributes('line_height', { mobile: '1.3' }, DEFAULTS).run();
128
+ editor.commands.selectAll();
129
+ editor.commands.setBlockAttributes('line_height', { mobile: '1.3' }, DEFAULTS);
130
+
131
+ expect(editor.getJSON()).toMatchSnapshot();
132
+ });
133
+ });
134
+
135
+ describe('apply mark', () => {
136
+ test('should apply mark to word', () => {
137
+ const editor = createEditor({
138
+ content: NodeFactory.doc([NodeFactory.paragraph('lorem ipsum')])
139
+ });
140
+
141
+ editor.commands.setTextSelection({ from: 1, to: 6 });
142
+ editor.commands.applyMark(TextSettings.FONT_WEIGHT, { value: '700' });
143
+
144
+ expect(editor.getJSON()).toMatchSnapshot();
145
+ });
146
+
147
+ test('should merge marks', () => {
148
+ const editor = createEditor({
149
+ content: NodeFactory.doc([
150
+ NodeFactory.paragraph([
151
+ NodeFactory.text('lorem', [
152
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '900' })
153
+ ]),
154
+ NodeFactory.text(' ipsum')
155
+ ])
156
+ ])
157
+ });
158
+
159
+ editor.commands.setTextSelection({ from: 1, to: 10 });
160
+ editor.commands.applyMark(TextSettings.FONT_WEIGHT, { value: '700' });
161
+
162
+ expect(editor.getJSON()).toMatchSnapshot();
163
+ });
164
+
165
+ test('should apply mark to block', () => {
166
+ const editor = createEditor({
167
+ content: NodeFactory.doc([NodeFactory.paragraph('lorem ipsum')])
168
+ });
169
+
170
+ editor
171
+ .chain()
172
+ .selectAll()
173
+ .applyMark(TextSettings.FONT_WEIGHT, { value: '700' })
174
+ .run();
175
+
176
+ expect(editor.getJSON()).toMatchSnapshot();
177
+ });
178
+
179
+ test('should apply text mark to paragraph with mark', () => {
180
+ const editor = createEditor({
181
+ content: NodeFactory.doc([
182
+ NodeFactory.paragraph(null, [NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })], 'lorem impum')
183
+ ])
184
+ });
185
+
186
+
187
+ editor.commands.setTextSelection({ from: 1, to: 6 });
188
+ editor.commands.applyMark(TextSettings.FONT_WEIGHT, { value: '400' });
117
189
 
118
190
  expect(editor.getJSON()).toMatchSnapshot();
119
191
  });
@@ -1,6 +1,6 @@
1
1
  import { Editor } from '@tiptap/vue-2';
2
+ import { buildTestExtensions } from '../../../__tests__/utils';
2
3
  import { ContentNormalizer, NodeFactory } from '../../../services';
3
- import { buildCoreExtensions } from '../index';
4
4
 
5
5
  function createEditor() {
6
6
  const content = NodeFactory.doc([
@@ -10,7 +10,7 @@ function createEditor() {
10
10
 
11
11
  return new Editor({
12
12
  content: ContentNormalizer.normalize(content),
13
- extensions: buildCoreExtensions() // included to core
13
+ extensions: buildTestExtensions()
14
14
  });
15
15
  }
16
16
 
@@ -1,7 +1,7 @@
1
1
  import { Editor, Mark, Extension } from '@tiptap/vue-2';
2
+ import { buildTestExtensions } from '../../../__tests__/utils';
2
3
  import { ContentNormalizer, NodeFactory } from '../../../services';
3
4
  import { NodeTypes, TextSettings } from '../../../enums';
4
- import { buildCoreExtensions } from '../index';
5
5
 
6
6
  const MockFontSize = Mark.create({
7
7
  name: TextSettings.FONT_SIZE,
@@ -103,17 +103,19 @@ function createEditor({ content }) {
103
103
  return new Editor({
104
104
  content: ContentNormalizer.normalize(content),
105
105
  element: document.createElement('div'),
106
- extensions: buildCoreExtensions().concat(
107
- MockFontSize,
108
- MockFontWeight,
109
- MockAlignment,
110
- MockBackgroundColor,
111
- MockFontColor,
112
- MockFontFamily,
113
- MockFontStyle,
114
- MockTextDecoration,
115
- MockSuperscript
116
- )
106
+ extensions: buildTestExtensions({
107
+ include: [
108
+ MockFontSize,
109
+ MockFontWeight,
110
+ MockAlignment,
111
+ MockBackgroundColor,
112
+ MockFontColor,
113
+ MockFontFamily,
114
+ MockFontStyle,
115
+ MockTextDecoration,
116
+ MockSuperscript
117
+ ]
118
+ })
117
119
  });
118
120
  }
119
121
 
@@ -125,10 +127,8 @@ describe('transform text', () => {
125
127
  ])
126
128
  });
127
129
 
128
- editor.chain()
129
- .setTextSelection({ from: 2, to: 6 })
130
- .transformText(({ text }) => text.toUpperCase())
131
- .run();
130
+ editor.commands.setTextSelection({ from: 2, to: 6 });
131
+ editor.commands.transformText(({ text }) => text.toUpperCase());
132
132
 
133
133
  expect(editor.getJSON()).toMatchSnapshot();
134
134
  });
@@ -144,10 +144,8 @@ describe('transform text', () => {
144
144
  ])
145
145
  });
146
146
 
147
- editor.chain()
148
- .setTextSelection({ from: 2, to: 6 })
149
- .transformText(({ text }) => text.toUpperCase())
150
- .run();
147
+ editor.commands.setTextSelection({ from: 2, to: 6 });
148
+ editor.commands.transformText(({ text }) => text.toUpperCase());
151
149
 
152
150
  expect(editor.getJSON()).toMatchSnapshot();
153
151
  });
@@ -1,5 +1,137 @@
1
1
  // Jest Snapshot v1, https://goo.gl/fbAQLP
2
2
 
3
+ exports[`apply mark should apply mark to block 1`] = `
4
+ Object {
5
+ "content": Array [
6
+ Object {
7
+ "attrs": Object {
8
+ "line_height": null,
9
+ },
10
+ "content": Array [
11
+ Object {
12
+ "text": "lorem ipsum",
13
+ "type": "text",
14
+ },
15
+ ],
16
+ "marks": Array [
17
+ Object {
18
+ "attrs": Object {
19
+ "value": "700",
20
+ },
21
+ "type": "font_weight",
22
+ },
23
+ ],
24
+ "type": "paragraph",
25
+ },
26
+ ],
27
+ "type": "doc",
28
+ }
29
+ `;
30
+
31
+ exports[`apply mark should apply mark to word 1`] = `
32
+ Object {
33
+ "content": Array [
34
+ Object {
35
+ "attrs": Object {
36
+ "line_height": null,
37
+ },
38
+ "content": Array [
39
+ Object {
40
+ "marks": Array [
41
+ Object {
42
+ "attrs": Object {
43
+ "value": "700",
44
+ },
45
+ "type": "font_weight",
46
+ },
47
+ ],
48
+ "text": "lorem",
49
+ "type": "text",
50
+ },
51
+ Object {
52
+ "text": " ipsum",
53
+ "type": "text",
54
+ },
55
+ ],
56
+ "type": "paragraph",
57
+ },
58
+ ],
59
+ "type": "doc",
60
+ }
61
+ `;
62
+
63
+ exports[`apply mark should apply text mark to paragraph with mark 1`] = `
64
+ Object {
65
+ "content": Array [
66
+ Object {
67
+ "attrs": Object {
68
+ "line_height": null,
69
+ },
70
+ "content": Array [
71
+ Object {
72
+ "marks": Array [
73
+ Object {
74
+ "attrs": Object {
75
+ "value": "400",
76
+ },
77
+ "type": "font_weight",
78
+ },
79
+ ],
80
+ "text": "lorem",
81
+ "type": "text",
82
+ },
83
+ Object {
84
+ "text": " impum",
85
+ "type": "text",
86
+ },
87
+ ],
88
+ "marks": Array [
89
+ Object {
90
+ "attrs": Object {
91
+ "value": "700",
92
+ },
93
+ "type": "font_weight",
94
+ },
95
+ ],
96
+ "type": "paragraph",
97
+ },
98
+ ],
99
+ "type": "doc",
100
+ }
101
+ `;
102
+
103
+ exports[`apply mark should merge marks 1`] = `
104
+ Object {
105
+ "content": Array [
106
+ Object {
107
+ "attrs": Object {
108
+ "line_height": null,
109
+ },
110
+ "content": Array [
111
+ Object {
112
+ "marks": Array [
113
+ Object {
114
+ "attrs": Object {
115
+ "value": "700",
116
+ },
117
+ "type": "font_weight",
118
+ },
119
+ ],
120
+ "text": "lorem ips",
121
+ "type": "text",
122
+ },
123
+ Object {
124
+ "text": "um",
125
+ "type": "text",
126
+ },
127
+ ],
128
+ "type": "paragraph",
129
+ },
130
+ ],
131
+ "type": "doc",
132
+ }
133
+ `;
134
+
3
135
  exports[`block attributes should set attributes 1`] = `
4
136
  Object {
5
137
  "content": Array [
@@ -1,5 +1,3 @@
1
- import Document from '@tiptap/extension-document';
2
- import Paragraph from '@tiptap/extension-paragraph';
3
1
  import Text from '@tiptap/extension-text';
4
2
  import Placeholder from '@tiptap/extension-placeholder';
5
3
  import History from '@tiptap/extension-history';
@@ -7,16 +5,18 @@ import { NodeProcessor } from './NodeProcessor';
7
5
  import { TextProcessor } from './TextProcessor';
8
6
  import { SelectionProcessor } from './SelectionProcessor';
9
7
  import { CopyPasteProcessor } from './CopyPasteProcessor';
8
+ import { Document } from './Document';
9
+ import { Paragraph } from './Paragraph';
10
+ import { Heading } from './Heading';
10
11
 
11
12
  export const buildCoreExtensions = () => [
12
13
  Document,
13
- Paragraph.configure({
14
- HTMLAttributes: { class: 'zw-style' }
15
- }),
16
14
  Placeholder.configure({
17
15
  placeholder: 'Type your text here...',
18
16
  emptyNodeClass: 'zw-wysiwyg__placeholder'
19
17
  }),
18
+ Paragraph,
19
+ Heading,
20
20
  Text,
21
21
  History,
22
22
  NodeProcessor,
@@ -0,0 +1,60 @@
1
+ import { Step, StepResult } from 'prosemirror-transform';
2
+ import { Slice, Fragment } from 'prosemirror-model';
3
+ import { RemoveNodeMarkStep } from './RemoveNodeMarkStep';
4
+
5
+ export class AddNodeMarkStep extends Step {
6
+ static fromJSON(schema, json) {
7
+ if (typeof json.pos != 'number') {
8
+ throw new RangeError('Invalid input for AddNodeMarkStep.fromJSON');
9
+ }
10
+
11
+ return new AddNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
12
+ }
13
+
14
+ constructor(pos, mark) {
15
+ super();
16
+ this.pos = pos;
17
+ this.mark = mark;
18
+ }
19
+
20
+ apply(doc) {
21
+ const node = doc.nodeAt(this.pos);
22
+
23
+ if (!node) return StepResult.fail('No node at mark step\'s position');
24
+
25
+ const updated = node.type.create(node.attrs, null, this.mark.addToSet(node.marks));
26
+ const slice = new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1);
27
+
28
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, slice);
29
+ }
30
+
31
+ invert(doc) {
32
+ const node = doc.nodeAt(this.pos);
33
+
34
+ if (node) {
35
+ const newSet = this.mark.addToSet(node.marks);
36
+
37
+ if (newSet.length === node.marks.length) {
38
+ for (const mark of node.marks) {
39
+ if (!mark.isInSet(newSet)) {
40
+ return new AddNodeMarkStep(this.pos, mark);
41
+ }
42
+ }
43
+ return new AddNodeMarkStep(this.pos, this.mark);
44
+ }
45
+ }
46
+ return new RemoveNodeMarkStep(this.pos, this.mark);
47
+ }
48
+
49
+ map(mapping) {
50
+ const pos = mapping.mapResult(this.pos, 1);
51
+
52
+ return pos.deletedAfter ? null : new AddNodeMarkStep(pos.pos, this.mark);
53
+ }
54
+
55
+ toJSON() {
56
+ return { stepType: 'addNodeMark', pos: this.pos, mark: this.mark.toJSON() };
57
+ }
58
+ }
59
+
60
+ Step.jsonID('addNodeMark', AddNodeMarkStep);
@@ -0,0 +1,50 @@
1
+ import { Step, StepResult } from 'prosemirror-transform';
2
+ import { Slice, Fragment } from 'prosemirror-model';
3
+ import { AddNodeMarkStep } from './AddNodeMarkStep';
4
+
5
+ export class RemoveNodeMarkStep extends Step {
6
+ static fromJSON(schema, json) {
7
+ if (typeof json.pos != 'number') {
8
+ throw new RangeError('Invalid input for RemoveNodeMarkStep.fromJSON');
9
+ }
10
+
11
+ return new RemoveNodeMarkStep(json.pos, schema.markFromJSON(json.mark));
12
+ }
13
+
14
+ constructor(pos, mark) {
15
+ super();
16
+ this.pos = pos;
17
+ this.mark = mark;
18
+ }
19
+
20
+ apply(doc) {
21
+ const node = doc.nodeAt(this.pos);
22
+
23
+ if (!node) return StepResult.fail('No node at mark step\'s position');
24
+
25
+ const updated = node.type.create(node.attrs, null, this.mark.removeFromSet(node.marks));
26
+ const slice = new Slice(Fragment.from(updated), 0, node.isLeaf ? 0 : 1);
27
+
28
+ return StepResult.fromReplace(doc, this.pos, this.pos + 1, slice);
29
+ }
30
+
31
+ invert(doc) {
32
+ const node = doc.nodeAt(this.pos);
33
+
34
+ if (!node || !this.mark.isInSet(node.marks)) return this;
35
+
36
+ return new AddNodeMarkStep(this.pos, this.mark);
37
+ }
38
+
39
+ map(mapping) {
40
+ const pos = mapping.mapResult(this.pos, 1);
41
+
42
+ return pos.deletedAfter ? null : new RemoveNodeMarkStep(pos.pos, this.mark);
43
+ }
44
+
45
+ toJSON() {
46
+ return { stepType: 'removeNodeMark', pos: this.pos, mark: this.mark.toJSON() };
47
+ }
48
+ }
49
+
50
+ Step.jsonID('removeNodeMark', RemoveNodeMarkStep);
@@ -0,0 +1,2 @@
1
+ export { AddNodeMarkStep } from './AddNodeMarkStep';
2
+ export { RemoveNodeMarkStep } from './RemoveNodeMarkStep';
@@ -8,6 +8,7 @@ export const List = Node.create({
8
8
  name: NodeTypes.LIST,
9
9
  content: `${NodeTypes.LIST_ITEM}+`,
10
10
  group: 'block list',
11
+ marks: 'settings',
11
12
 
12
13
  addExtensions: () => [
13
14
  ListItem
@@ -3,6 +3,11 @@ import { NodeTypes } from '../../enums';
3
3
 
4
4
  export const ListItem = Base.extend({
5
5
  name: NodeTypes.LIST_ITEM,
6
+ marks: 'settings',
7
+
8
+ addOptions: () => ({
9
+ HTMLAttributes: { class: 'zw-style' }
10
+ }),
6
11
 
7
12
  addKeyboardShortcuts() {
8
13
  const { Enter } = this.parent();
@@ -1,32 +1,32 @@
1
1
  import { Editor } from '@tiptap/vue-2';
2
+ import { buildTestExtensions } from '../../../__tests__/utils';
2
3
  import { ListTypes } from '../../../enums';
3
4
  import { StylePreset } from '../../StylePreset';
4
- import { List } from '../List';
5
5
  import { ContentNormalizer, NodeFactory } from '../../../services';
6
- import { buildCoreExtensions } from '../../core';
6
+ import { List } from '../List';
7
7
 
8
8
  function createEditor({ content }) {
9
9
  return new Editor({
10
10
  content: ContentNormalizer.normalize(content),
11
11
  element: document.createElement('div'),
12
- extensions: buildCoreExtensions().concat(
13
- List.configure({
14
- baseClass: 'zw-list--'
15
- }),
16
- StylePreset.configure({
17
- presets: [
18
- {
19
- id: 'regular-1',
20
- common: {},
21
- mobile: {},
22
- tablet: {},
23
- desktop: {}
24
- }
25
- ],
26
- defaultId: 'regular-1',
27
- baseClass: 'zw ts-'
28
- })
29
- )
12
+ extensions: buildTestExtensions({
13
+ include: [
14
+ List.configure({ baseClass: 'zw-list--' }),
15
+ StylePreset.configure({
16
+ presets: [
17
+ {
18
+ id: 'regular-1',
19
+ common: {},
20
+ mobile: {},
21
+ tablet: {},
22
+ desktop: {}
23
+ }
24
+ ],
25
+ defaultId: 'regular-1',
26
+ baseClass: 'zw ts-'
27
+ })
28
+ ]
29
+ })
30
30
  });
31
31
  }
32
32
 
@@ -67,7 +67,8 @@ describe('apply list', () => {
67
67
  ])
68
68
  });
69
69
 
70
- editor.chain().selectAll().applyList(ListTypes.LATIN).run();
70
+ editor.commands.selectAll();
71
+ editor.commands.applyList(ListTypes.LATIN);
71
72
 
72
73
  expect(editor.getJSON()).toMatchSnapshot();
73
74
  });
@@ -82,7 +83,8 @@ describe('apply list', () => {
82
83
  ])
83
84
  });
84
85
 
85
- editor.chain().selectAll().removeList().run();
86
+ editor.commands.selectAll();
87
+ editor.commands.removeList();
86
88
 
87
89
  expect(editor.getJSON()).toMatchSnapshot();
88
90
  });
@@ -97,7 +99,8 @@ describe('apply list', () => {
97
99
  ])
98
100
  });
99
101
 
100
- editor.chain().selectAll().applyList(ListTypes.LATIN).run();
102
+ editor.commands.selectAll();
103
+ editor.commands.applyList(ListTypes.LATIN);
101
104
 
102
105
  expect(editor.getJSON()).toMatchSnapshot();
103
106
  });
@@ -112,7 +115,8 @@ describe('apply list', () => {
112
115
  ])
113
116
  });
114
117
 
115
- editor.chain().selectAll().applyList(ListTypes.ROMAN).run();
118
+ editor.commands.selectAll();
119
+ editor.commands.applyList(ListTypes.ROMAN);
116
120
 
117
121
  expect(editor.getJSON()).toMatchSnapshot();
118
122
  });
@@ -125,7 +129,8 @@ describe('apply list', () => {
125
129
  ])
126
130
  });
127
131
 
128
- editor.chain().selectAll().applyList(ListTypes.LATIN).run();
132
+ editor.commands.selectAll();
133
+ editor.commands.applyList(ListTypes.LATIN);
129
134
 
130
135
  expect(editor.getJSON()).toMatchSnapshot();
131
136
  });