@zipify/wysiwyg 2.0.0-0 → 2.0.0-10

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 (118) hide show
  1. package/.eslintrc.js +1 -1
  2. package/config/build/cli.config.js +8 -2
  3. package/config/build/lib.config.js +4 -2
  4. package/dist/cli.js +10 -2
  5. package/dist/wysiwyg.css +53 -37
  6. package/dist/wysiwyg.mjs +2131 -405
  7. package/example/ExampleApp.vue +13 -2
  8. package/lib/Wysiwyg.vue +3 -2
  9. package/lib/__tests__/utils/buildTestExtensions.js +2 -1
  10. package/lib/assets/icons/indicator.svg +4 -0
  11. package/lib/cli/commands/Command.js +39 -0
  12. package/lib/cli/commands/ToJsonCommand.js +46 -0
  13. package/lib/cli/commands/VersionCommand.js +11 -0
  14. package/lib/cli/commands/index.js +2 -0
  15. package/lib/cli/index.js +1 -0
  16. package/lib/components/base/Button.vue +6 -0
  17. package/lib/components/base/dropdown/Dropdown.vue +7 -1
  18. package/lib/components/base/dropdown/DropdownActivator.vue +25 -4
  19. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +23 -1
  20. package/lib/components/toolbar/controls/AlignmentControl.vue +12 -1
  21. package/lib/components/toolbar/controls/FontColorControl.vue +14 -0
  22. package/lib/components/toolbar/controls/FontFamilyControl.vue +4 -0
  23. package/lib/components/toolbar/controls/FontSizeControl.vue +6 -1
  24. package/lib/components/toolbar/controls/FontWeightControl.vue +12 -0
  25. package/lib/components/toolbar/controls/ItalicControl.vue +14 -0
  26. package/lib/components/toolbar/controls/LineHeightControl.vue +15 -0
  27. package/lib/components/toolbar/controls/StylePresetControl.vue +1 -1
  28. package/lib/components/toolbar/controls/UnderlineControl.vue +13 -0
  29. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +72 -5
  30. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +22 -1
  31. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +1 -0
  32. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +1 -0
  33. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +1 -0
  34. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +23 -1
  35. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +23 -1
  36. package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +6 -6
  37. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +25 -1
  38. package/lib/composables/__tests__/useEditor.test.js +1 -1
  39. package/lib/composables/useEditor.js +9 -8
  40. package/lib/directives/__tests__/tooltip.test.js +22 -4
  41. package/lib/directives/tooltip.js +4 -1
  42. package/lib/entry-cli.js +7 -20
  43. package/lib/entry-lib.js +1 -1
  44. package/lib/enums/MarkGroups.js +4 -0
  45. package/lib/enums/TextSettings.js +5 -5
  46. package/lib/enums/index.js +1 -0
  47. package/lib/extensions/BackgroundColor.js +0 -1
  48. package/lib/extensions/FontColor.js +2 -2
  49. package/lib/extensions/FontFamily.js +3 -3
  50. package/lib/extensions/FontSize.js +2 -2
  51. package/lib/extensions/FontStyle.js +2 -2
  52. package/lib/extensions/FontWeight.js +2 -2
  53. package/lib/extensions/Link.js +1 -1
  54. package/lib/extensions/StylePreset.js +9 -3
  55. package/lib/extensions/Superscript.js +5 -2
  56. package/lib/extensions/TextDecoration.js +19 -29
  57. package/lib/extensions/__tests__/Alignment.test.js +2 -2
  58. package/lib/extensions/__tests__/BackgroundColor.test.js +4 -3
  59. package/lib/extensions/__tests__/FontColor.test.js +4 -3
  60. package/lib/extensions/__tests__/FontFamily.test.js +6 -6
  61. package/lib/extensions/__tests__/FontSize.test.js +9 -8
  62. package/lib/extensions/__tests__/FontStyle.test.js +6 -5
  63. package/lib/extensions/__tests__/FontWeight.test.js +2 -2
  64. package/lib/extensions/__tests__/LineHeight.test.js +2 -1
  65. package/lib/extensions/__tests__/StylePreset.test.js +51 -0
  66. package/lib/extensions/__tests__/Superscript.test.js +102 -0
  67. package/lib/extensions/__tests__/TextDecoration.test.js +40 -24
  68. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +24 -24
  69. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +1 -1
  70. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +19 -23
  71. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +2 -2
  72. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +1 -1
  73. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +13 -17
  74. package/lib/extensions/__tests__/__snapshots__/Superscript.test.js.snap +107 -0
  75. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +102 -102
  76. package/lib/extensions/core/Document.js +2 -1
  77. package/lib/extensions/core/Heading.js +2 -1
  78. package/lib/extensions/core/NodeProcessor.js +63 -20
  79. package/lib/extensions/core/Paragraph.js +2 -1
  80. package/lib/extensions/core/TextProcessor.js +0 -5
  81. package/lib/extensions/core/__tests__/NodeProcessor.test.js +364 -11
  82. package/lib/extensions/core/__tests__/TextProcessor.test.js +1 -22
  83. package/lib/extensions/core/__tests__/__snapshots__/NodeProcessor.test.js.snap +309 -0
  84. package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +7 -27
  85. package/lib/extensions/core/steps/AddNodeMarkStep.js +6 -0
  86. package/lib/extensions/core/steps/AttrStep.js +60 -0
  87. package/lib/extensions/core/steps/RemoveNodeMarkStep.js +6 -0
  88. package/lib/extensions/core/steps/index.js +1 -0
  89. package/lib/extensions/list/List.js +70 -9
  90. package/lib/extensions/list/ListItem.js +2 -2
  91. package/lib/extensions/list/__tests__/List.test.js +26 -17
  92. package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +36 -36
  93. package/lib/services/NodeFactory.js +73 -13
  94. package/lib/services/__tests__/NodeFactory.test.js +124 -0
  95. package/lib/services/__tests__/__snapshots__/NodeFactory.test.js.snap +326 -0
  96. package/lib/services/index.js +1 -1
  97. package/lib/services/normalizer/BaseNormalizer.js +11 -0
  98. package/lib/services/{BrowserDomParser.js → normalizer/BrowserDomParser.js} +0 -0
  99. package/lib/services/normalizer/ContentNormalizer.js +24 -0
  100. package/lib/services/normalizer/HtmlNormalizer.js +297 -0
  101. package/lib/services/normalizer/JsonNormalizer.js +82 -0
  102. package/lib/services/{__tests__/ContentNormalizer.test.js → normalizer/__tests__/HtmlNormalizer.test.js} +42 -4
  103. package/lib/services/normalizer/__tests__/JsonNormalizer.test.js +87 -0
  104. package/lib/services/normalizer/__tests__/__snapshots__/JsonNormalizer.test.js.snap +196 -0
  105. package/lib/services/normalizer/index.js +1 -0
  106. package/lib/styles/content.css +8 -0
  107. package/lib/utils/__tests__/findMarkByType.test.js +17 -0
  108. package/lib/utils/__tests__/isMarkAppliedToParent.test.js +53 -0
  109. package/lib/utils/__tests__/isNodeFullySelected.test.js +44 -0
  110. package/lib/utils/__tests__/resolveTextPosition.test.js +39 -0
  111. package/lib/utils/copyMark.js +5 -0
  112. package/lib/utils/index.js +1 -1
  113. package/lib/utils/isMarkAppliedToParent.js +2 -7
  114. package/lib/utils/isNodeFullySelected.js +4 -7
  115. package/lib/utils/resolveTextPosition.js +4 -6
  116. package/package.json +31 -27
  117. package/lib/services/ContentNormalizer.js +0 -194
  118. package/lib/utils/resolveNodePosition.js +0 -6
@@ -1,10 +1,16 @@
1
- import { Editor } from '@tiptap/vue-2';
1
+ import { Editor, Mark } from '@tiptap/vue-2';
2
2
  import { buildTestExtensions } from '../../../__tests__/utils';
3
- import { ListTypes } from '../../../enums';
3
+ import { ListTypes, TextSettings } from '../../../enums';
4
4
  import { StylePreset } from '../../StylePreset';
5
5
  import { ContentNormalizer, NodeFactory } from '../../../services';
6
6
  import { List } from '../List';
7
7
 
8
+ const MockFontWeight = Mark.create({
9
+ name: TextSettings.FONT_WEIGHT,
10
+ renderHTML: () => ['span', {}, 0],
11
+ addAttributes: () => ({ value: { required: true } })
12
+ });
13
+
8
14
  function createEditor({ content }) {
9
15
  return new Editor({
10
16
  content: ContentNormalizer.normalize(content),
@@ -24,7 +30,8 @@ function createEditor({ content }) {
24
30
  ],
25
31
  defaultId: 'regular-1',
26
32
  baseClass: 'zw ts-'
27
- })
33
+ }),
34
+ MockFontWeight
28
35
  ]
29
36
  })
30
37
  });
@@ -73,7 +80,7 @@ describe('apply list', () => {
73
80
  expect(editor.getJSON()).toMatchSnapshot();
74
81
  });
75
82
 
76
- test('should remove list', () => {
83
+ test('should toggle list', () => {
77
84
  const editor = createEditor({
78
85
  content: NodeFactory.doc([
79
86
  NodeFactory.list(ListTypes.LATIN, [
@@ -84,12 +91,12 @@ describe('apply list', () => {
84
91
  });
85
92
 
86
93
  editor.commands.selectAll();
87
- editor.commands.removeList();
94
+ editor.commands.applyList(ListTypes.LATIN);
88
95
 
89
96
  expect(editor.getJSON()).toMatchSnapshot();
90
97
  });
91
98
 
92
- test('should toggle list', () => {
99
+ test('should change list type', () => {
93
100
  const editor = createEditor({
94
101
  content: NodeFactory.doc([
95
102
  NodeFactory.list(ListTypes.LATIN, [
@@ -100,37 +107,39 @@ describe('apply list', () => {
100
107
  });
101
108
 
102
109
  editor.commands.selectAll();
103
- editor.commands.applyList(ListTypes.LATIN);
110
+ editor.commands.applyList(ListTypes.ROMAN);
104
111
 
105
112
  expect(editor.getJSON()).toMatchSnapshot();
106
113
  });
107
114
 
108
- test('should change list type', () => {
115
+ test('should remove preset', () => {
109
116
  const editor = createEditor({
110
117
  content: NodeFactory.doc([
111
- NodeFactory.list(ListTypes.LATIN, [
112
- NodeFactory.paragraph('Item 1'),
113
- NodeFactory.paragraph('Item 2')
114
- ])
118
+ NodeFactory.paragraph({ preset: { id: 'regular-1' } }, 'Item 1'),
119
+ NodeFactory.paragraph({ preset: { id: 'regular-1' } }, 'Item 2')
115
120
  ])
116
121
  });
117
122
 
118
123
  editor.commands.selectAll();
119
- editor.commands.applyList(ListTypes.ROMAN);
124
+ editor.commands.applyList(ListTypes.LATIN);
120
125
 
121
126
  expect(editor.getJSON()).toMatchSnapshot();
122
127
  });
128
+ });
123
129
 
124
- test('should remove preset', () => {
130
+ describe('remove list', () => {
131
+ test('should remove list', () => {
125
132
  const editor = createEditor({
126
133
  content: NodeFactory.doc([
127
- NodeFactory.paragraph({ preset: { id: 'regular-1' } }, 'Item 1'),
128
- NodeFactory.paragraph({ preset: { id: 'regular-1' } }, 'Item 2')
134
+ NodeFactory.list(ListTypes.LATIN, [
135
+ NodeFactory.paragraph('Item 1'),
136
+ NodeFactory.paragraph('Item 2')
137
+ ])
129
138
  ])
130
139
  });
131
140
 
132
141
  editor.commands.selectAll();
133
- editor.commands.applyList(ListTypes.LATIN);
142
+ editor.commands.removeList();
134
143
 
135
144
  expect(editor.getJSON()).toMatchSnapshot();
136
145
  });
@@ -93,42 +93,6 @@ Object {
93
93
  }
94
94
  `;
95
95
 
96
- exports[`apply list should remove list 1`] = `
97
- Object {
98
- "content": Array [
99
- Object {
100
- "attrs": Object {
101
- "preset": Object {
102
- "id": "regular-1",
103
- },
104
- },
105
- "content": Array [
106
- Object {
107
- "text": "Item 1",
108
- "type": "text",
109
- },
110
- ],
111
- "type": "paragraph",
112
- },
113
- Object {
114
- "attrs": Object {
115
- "preset": Object {
116
- "id": "regular-1",
117
- },
118
- },
119
- "content": Array [
120
- Object {
121
- "text": "Item 2",
122
- "type": "text",
123
- },
124
- ],
125
- "type": "paragraph",
126
- },
127
- ],
128
- "type": "doc",
129
- }
130
- `;
131
-
132
96
  exports[`apply list should remove preset 1`] = `
133
97
  Object {
134
98
  "content": Array [
@@ -701,3 +665,39 @@ Object {
701
665
  "type": "doc",
702
666
  }
703
667
  `;
668
+
669
+ exports[`remove list should remove list 1`] = `
670
+ Object {
671
+ "content": Array [
672
+ Object {
673
+ "attrs": Object {
674
+ "preset": Object {
675
+ "id": "regular-1",
676
+ },
677
+ },
678
+ "content": Array [
679
+ Object {
680
+ "text": "Item 1",
681
+ "type": "text",
682
+ },
683
+ ],
684
+ "type": "paragraph",
685
+ },
686
+ Object {
687
+ "attrs": Object {
688
+ "preset": Object {
689
+ "id": "regular-1",
690
+ },
691
+ },
692
+ "content": Array [
693
+ Object {
694
+ "text": "Item 2",
695
+ "type": "text",
696
+ },
697
+ ],
698
+ "type": "paragraph",
699
+ },
700
+ ],
701
+ "type": "doc",
702
+ }
703
+ `;
@@ -1,44 +1,90 @@
1
1
  import { NodeTypes } from '../enums';
2
2
 
3
+ /**
4
+ * @typedef {Object} NodeJson
5
+ * @property {String} type
6
+ * @property {Array<MarkJson>} [marks]
7
+ * @property {AttrsJson} [attrs]
8
+ *
9
+ * @typedef {Object} MarkJson
10
+ * @property {String} type
11
+ * @property {AttrsJson} attrs
12
+ *
13
+ * @typedef {Object} AttrsJson
14
+ */
15
+
3
16
  export class NodeFactory {
17
+ /**
18
+ * @param {Array<NodeJson>} content
19
+ * @returns {NodeJson}
20
+ */
4
21
  static doc(content) {
5
- return {
6
- type: NodeTypes.DOCUMENT,
7
- content
8
- };
22
+ return { type: NodeTypes.DOCUMENT, content };
9
23
  }
10
24
 
25
+ /**
26
+ * @param {String} type
27
+ * @param {Array<String | NodeJson>} items
28
+ * @returns {NodeJson}
29
+ */
11
30
  static list(type, items) {
12
31
  return {
13
32
  type: NodeTypes.LIST,
14
33
  attrs: { bullet: { type } },
15
- content: items.map((item) => this.listItem([].concat(item)))
34
+
35
+ content: items.map((item) => {
36
+ return item.type === NodeTypes.LIST_ITEM ? item : this.listItem([].concat(item));
37
+ })
16
38
  };
17
39
  }
18
40
 
19
- static listItem(content) {
41
+ /**
42
+ * @type {{
43
+ * ((content: String | NodeJson) => NodeJson);
44
+ * ((attrs: AttrsJson, content: String | NodeJson) => NodeJson);
45
+ * ((attrs: AttrsJson, marks: Array<MarkJson>, content: String | NodeJson) => NodeJson);
46
+ * }}
47
+ */
48
+ static listItem(...args) {
49
+ const { attrs, content: children, marks } = this.#normalizeTextBlockArgs(args);
50
+
20
51
  return {
21
52
  type: NodeTypes.LIST_ITEM,
22
- content
53
+ ...(attrs ? { attrs } : {}),
54
+ ...(marks ? { marks } : {}),
55
+ content: [].concat(children).map((content) => {
56
+ return typeof content === 'string' ? this.paragraph(content) : content;
57
+ })
23
58
  };
24
59
  }
25
60
 
61
+ /**
62
+ * @type {{
63
+ * ((level: Number, content: String | NodeJson) => NodeJson);
64
+ * ((level: Number, attrs: AttrsJson, content: String | NodeJson) => NodeJson);
65
+ * ((level: Number, attrs: AttrsJson, marks: Array<MarkJson>, content: String | NodeJson) => NodeJson);
66
+ * }}
67
+ */
26
68
  static heading(level, ...args) {
27
- const config = this.#textBlock(args);
69
+ const config = this.#textBlock(args, this.text);
28
70
 
29
71
  config.attrs ??= {};
30
72
  config.attrs.level = level;
31
73
 
32
- return {
33
- type: NodeTypes.HEADING,
34
- ...config
35
- };
74
+ return { type: NodeTypes.HEADING, ...config };
36
75
  }
37
76
 
77
+ /**
78
+ * @type {{
79
+ * ((content: String | NodeJson) => NodeJson);
80
+ * ((attrs: AttrsJson, content: String | NodeJson) => NodeJson);
81
+ * ((attrs: AttrsJson, marks: Array<MarkJson>, content: String | NodeJson) => NodeJson);
82
+ * }}
83
+ */
38
84
  static paragraph(...args) {
39
85
  return {
40
86
  type: NodeTypes.PARAGRAPH,
41
- ...this.#textBlock(args)
87
+ ...this.#textBlock(args, this.text)
42
88
  };
43
89
  }
44
90
 
@@ -63,6 +109,11 @@ export class NodeFactory {
63
109
  return { attrs: args[0], marks: args[1], content: args[2] };
64
110
  }
65
111
 
112
+ /**
113
+ * @param {String} text
114
+ * @param {Array<MarkJson>} marks
115
+ * @returns {NodeJson}
116
+ */
66
117
  static text(text, marks) {
67
118
  return {
68
119
  type: NodeTypes.TEXT,
@@ -71,10 +122,19 @@ export class NodeFactory {
71
122
  };
72
123
  }
73
124
 
125
+ /**
126
+ * @param {String} type
127
+ * @param {AttrsJson} attrs
128
+ * @returns {MarkJson}
129
+ */
74
130
  static mark(type, attrs) {
75
131
  return { type, attrs };
76
132
  }
77
133
 
134
+ /**
135
+ * @param {*} value
136
+ * @returns {{tablet, desktop, mobile}}
137
+ */
78
138
  static populateAllDevices(value) {
79
139
  // return { mobile: value, tablet: value, desktop: value };
80
140
 
@@ -0,0 +1,124 @@
1
+ import { NodeFactory } from '../NodeFactory';
2
+ import { ListTypes, TextSettings } from '../../enums';
3
+
4
+ describe('build node', () => {
5
+ test('should build doc node', () => {
6
+ expect(NodeFactory.doc([])).toMatchSnapshot();
7
+ });
8
+
9
+ test('should build list node with text items', () => {
10
+ const node = NodeFactory.list(ListTypes.DISC, [
11
+ 'lorem ipsum 1',
12
+ 'lorem ipsum 2'
13
+ ]);
14
+
15
+ expect(node).toMatchSnapshot();
16
+ });
17
+
18
+ test('should build list node with node items', () => {
19
+ const node = NodeFactory.list(ListTypes.DISC, [
20
+ NodeFactory.paragraph('lorem ipsum 1'),
21
+ NodeFactory.paragraph('lorem ipsum 2')
22
+ ]);
23
+
24
+ expect(node).toMatchSnapshot();
25
+ });
26
+
27
+ test('should build list node with custom list item nodes', () => {
28
+ const node = NodeFactory.list(ListTypes.DISC, [
29
+ NodeFactory.listItem(null, [
30
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })
31
+ ], 'lorem ipsum 1'),
32
+
33
+ NodeFactory.listItem(null, [
34
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })
35
+ ], 'lorem ipsum 2')
36
+ ]);
37
+
38
+ expect(node).toMatchSnapshot();
39
+ });
40
+
41
+ test('should build heading node', () => {
42
+ const node = NodeFactory.heading(1, 'lorem ipsum');
43
+
44
+ expect(node).toMatchSnapshot();
45
+ });
46
+
47
+ test('should build heading node with attrs', () => {
48
+ const node = NodeFactory.heading(1, { preset: { id: 'h1' } }, 'lorem ipsum');
49
+
50
+ expect(node).toMatchSnapshot();
51
+ });
52
+
53
+ test('should build heading node with marks', () => {
54
+ const node = NodeFactory.heading(1, null, [
55
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })
56
+ ], 'lorem ipsum');
57
+
58
+ expect(node).toMatchSnapshot();
59
+ });
60
+
61
+ test('should build heading with custom text node', () => {
62
+ const node = NodeFactory.heading(1, [
63
+ NodeFactory.text('lorem ipsum', [
64
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })
65
+ ])
66
+ ]);
67
+
68
+ expect(node).toMatchSnapshot();
69
+ });
70
+
71
+ test('should build paragraph node', () => {
72
+ const node = NodeFactory.paragraph('lorem ipsum');
73
+
74
+ expect(node).toMatchSnapshot();
75
+ });
76
+
77
+ test('should build paragraph node with attrs', () => {
78
+ const node = NodeFactory.paragraph({ preset: { id: 'regular-1' } }, 'lorem ipsum');
79
+
80
+ expect(node).toMatchSnapshot();
81
+ });
82
+
83
+ test('should build paragraph node with marks', () => {
84
+ const node = NodeFactory.paragraph(null, [
85
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })
86
+ ], 'lorem ipsum');
87
+
88
+ expect(node).toMatchSnapshot();
89
+ });
90
+
91
+ test('should build paragraph with custom text node', () => {
92
+ const node = NodeFactory.paragraph([
93
+ NodeFactory.text('lorem ipsum', [
94
+ NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' })
95
+ ])
96
+ ]);
97
+
98
+ expect(node).toMatchSnapshot();
99
+ });
100
+
101
+ test('should build text node', () => {
102
+ const node = NodeFactory.text('lorem ipsum');
103
+
104
+ expect(node).toMatchSnapshot();
105
+ });
106
+
107
+ test('should build text node with marks', () => {
108
+ const node = NodeFactory.text('lorem ipsum');
109
+
110
+ expect(node).toMatchSnapshot();
111
+ });
112
+
113
+ test('should build mark', () => {
114
+ const mark = NodeFactory.mark(TextSettings.FONT_WEIGHT, { value: '700' });
115
+
116
+ expect(mark).toMatchSnapshot();
117
+ });
118
+
119
+ test('should populate value to all devices', () => {
120
+ const value = NodeFactory.populateAllDevices('18');
121
+
122
+ expect(value).toMatchSnapshot();
123
+ });
124
+ });