@zipify/wysiwyg 1.0.0-dev.3 → 1.0.0-dev.32

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 (152) hide show
  1. package/.eslintignore +1 -0
  2. package/.github/dependabot.yaml +1 -0
  3. package/.release-it.json +3 -1
  4. package/.stylelintignore +1 -0
  5. package/README.md +3 -1
  6. package/config/jest/setupTests.js +7 -1
  7. package/config/webpack/example.config.js +2 -0
  8. package/config/webpack/lib.config.js +46 -0
  9. package/config/webpack/loaders/style-loader.js +3 -1
  10. package/config/webpack/loaders/svg-loader.js +1 -1
  11. package/dist/wysiwyg.css +1118 -0
  12. package/dist/wysiwyg.js +2 -0
  13. package/dist/wysiwyg.js.LICENSE.txt +1 -0
  14. package/example/ExampleApp.vue +51 -32
  15. package/example/example.js +26 -0
  16. package/example/pageBlocks.js +31 -0
  17. package/example/presets.js +4 -2
  18. package/lib/Wysiwyg.vue +41 -21
  19. package/lib/assets/icons/alignment-center.svg +3 -0
  20. package/lib/assets/icons/alignment-justify.svg +3 -0
  21. package/lib/assets/icons/alignment-left.svg +3 -0
  22. package/lib/assets/icons/alignment-right.svg +3 -0
  23. package/lib/assets/icons/arrow.svg +3 -0
  24. package/lib/assets/icons/background-color.svg +3 -0
  25. package/lib/assets/icons/case-style.svg +3 -0
  26. package/lib/assets/icons/font-color.svg +5 -0
  27. package/lib/assets/icons/italic.svg +3 -0
  28. package/lib/assets/icons/line-height.svg +3 -0
  29. package/lib/assets/icons/link.svg +3 -0
  30. package/lib/assets/icons/list-circle.svg +3 -0
  31. package/lib/assets/icons/list-decimal.svg +3 -0
  32. package/lib/assets/icons/list-disc.svg +3 -0
  33. package/lib/assets/icons/list-latin.svg +3 -0
  34. package/lib/assets/icons/list-roman.svg +3 -0
  35. package/lib/assets/icons/list-square.svg +3 -0
  36. package/lib/assets/icons/remove-format.svg +3 -0
  37. package/lib/assets/icons/reset-styles.svg +3 -0
  38. package/lib/assets/icons/strike-through.svg +3 -0
  39. package/lib/assets/icons/superscript.svg +3 -0
  40. package/lib/assets/icons/underline.svg +3 -0
  41. package/lib/assets/icons/unlink.svg +3 -0
  42. package/lib/components/base/Button.vue +21 -1
  43. package/lib/components/base/Checkbox.vue +89 -0
  44. package/lib/components/base/FieldLabel.vue +2 -1
  45. package/lib/components/base/Icon.vue +18 -10
  46. package/lib/components/base/Modal.vue +0 -1
  47. package/lib/components/base/TextField.vue +106 -0
  48. package/lib/components/base/__tests__/Icon.test.js +6 -13
  49. package/lib/components/base/__tests__/TextField.test.js +57 -0
  50. package/lib/components/base/__tests__/__snapshots__/TextField.test.js.snap +9 -0
  51. package/lib/components/base/colorPicker/composables/usePickerHotkeys.js +2 -1
  52. package/lib/components/base/composables/index.js +1 -0
  53. package/lib/components/base/composables/useValidator.js +19 -0
  54. package/lib/components/base/dropdown/Dropdown.vue +15 -3
  55. package/lib/components/base/dropdown/DropdownActivator.vue +19 -3
  56. package/lib/components/base/index.js +3 -1
  57. package/lib/components/toolbar/Toolbar.vue +49 -9
  58. package/lib/components/toolbar/ToolbarFull.vue +10 -2
  59. package/lib/components/toolbar/__tests__/Toolbar.test.js +6 -0
  60. package/lib/components/toolbar/controls/FontSizeControl.vue +7 -0
  61. package/lib/components/toolbar/controls/ListControl.vue +1 -5
  62. package/lib/components/toolbar/controls/UnderlineControl.vue +2 -2
  63. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +4 -0
  64. package/lib/components/toolbar/controls/index.js +1 -0
  65. package/lib/components/toolbar/controls/link/LinkControl.vue +152 -0
  66. package/lib/components/toolbar/controls/link/LinkControlApply.vue +35 -0
  67. package/lib/components/toolbar/controls/link/LinkControlHeader.vue +67 -0
  68. package/lib/components/toolbar/controls/link/composables/index.js +1 -0
  69. package/lib/components/toolbar/controls/link/composables/useLink.js +61 -0
  70. package/lib/components/toolbar/controls/link/destination/LinkControlDestination.vue +103 -0
  71. package/lib/components/toolbar/controls/link/destination/LinkControlPageBlock.vue +54 -0
  72. package/lib/components/toolbar/controls/link/destination/LinkControlUrl.vue +52 -0
  73. package/lib/components/toolbar/controls/link/destination/index.js +1 -0
  74. package/lib/components/toolbar/controls/link/index.js +1 -0
  75. package/lib/composables/__tests__/useEditor.test.js +14 -5
  76. package/lib/composables/useEditor.js +13 -8
  77. package/lib/composables/useToolbar.js +14 -29
  78. package/lib/directives/outClick.js +20 -4
  79. package/lib/enums/LinkDestinations.js +4 -0
  80. package/lib/enums/LinkTargets.js +4 -0
  81. package/lib/enums/TextSettings.js +3 -1
  82. package/lib/enums/index.js +2 -0
  83. package/lib/extensions/Alignment.js +21 -3
  84. package/lib/extensions/BackgroundColor.js +16 -1
  85. package/lib/extensions/FontColor.js +16 -1
  86. package/lib/extensions/FontFamily.js +26 -2
  87. package/lib/extensions/FontSize.js +28 -3
  88. package/lib/extensions/FontStyle.js +23 -2
  89. package/lib/extensions/FontWeight.js +33 -1
  90. package/lib/extensions/LineHeight.js +29 -3
  91. package/lib/extensions/Link.js +101 -0
  92. package/lib/extensions/StylePreset.js +36 -6
  93. package/lib/extensions/TextDecoration.js +29 -3
  94. package/lib/extensions/__tests__/Alignment.test.js +30 -3
  95. package/lib/extensions/__tests__/BackgroundColor.test.js +38 -3
  96. package/lib/extensions/__tests__/CaseStyle.test.js +4 -3
  97. package/lib/extensions/__tests__/FontColor.test.js +38 -3
  98. package/lib/extensions/__tests__/FontFamily.test.js +59 -5
  99. package/lib/extensions/__tests__/FontSize.test.js +38 -3
  100. package/lib/extensions/__tests__/FontStyle.test.js +46 -3
  101. package/lib/extensions/__tests__/FontWeight.test.js +66 -3
  102. package/lib/extensions/__tests__/LineHeight.test.js +49 -3
  103. package/lib/extensions/__tests__/StylePreset.test.js +143 -4
  104. package/lib/extensions/__tests__/TextDecoration.test.js +87 -3
  105. package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +70 -2
  106. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +121 -1
  107. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +109 -1
  108. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +179 -1
  109. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +132 -2
  110. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +142 -1
  111. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +179 -1
  112. package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +118 -2
  113. package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +171 -2
  114. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +300 -3
  115. package/lib/extensions/core/CopyPasteProcessor.js +10 -0
  116. package/lib/extensions/core/TextProcessor.js +10 -0
  117. package/lib/extensions/core/__tests__/NodeProcessor.test.js +4 -3
  118. package/lib/extensions/core/__tests__/SelectionProcessor.test.js +9 -6
  119. package/lib/extensions/core/__tests__/TextProcessor.test.js +139 -10
  120. package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +26 -0
  121. package/lib/extensions/core/index.js +11 -2
  122. package/lib/extensions/core/plugins/PastePlugin.js +48 -0
  123. package/lib/extensions/core/plugins/ProseMirrorPlugin.js +20 -0
  124. package/lib/extensions/core/plugins/index.js +1 -0
  125. package/lib/extensions/index.js +41 -33
  126. package/lib/extensions/list/List.js +34 -0
  127. package/lib/extensions/list/__tests__/List.test.js +115 -5
  128. package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +481 -0
  129. package/lib/index.js +4 -1
  130. package/lib/injectionTokens.js +2 -1
  131. package/lib/services/ContentNormalizer.js +157 -0
  132. package/lib/services/ContextWidnow.js +23 -0
  133. package/lib/services/Storage.js +1 -13
  134. package/lib/services/__tests__/ContentNormalizer.test.js +74 -0
  135. package/lib/services/__tests__/FavoriteColors.test.js +20 -0
  136. package/lib/services/__tests__/JsonSerializer.test.js +23 -0
  137. package/lib/services/__tests__/Storage.test.js +79 -0
  138. package/lib/services/index.js +2 -0
  139. package/lib/styles/content.css +96 -9
  140. package/lib/styles/helpers/offsets.css +16 -0
  141. package/lib/styles/variables.css +6 -0
  142. package/lib/utils/__tests__/__snapshots__/renderInlineSetting.test.js.snap +4 -4
  143. package/lib/utils/__tests__/convertColor.test.js +19 -0
  144. package/lib/utils/__tests__/createKeyboardShortcut.test.js +25 -0
  145. package/lib/utils/__tests__/renderInlineSetting.test.js +26 -0
  146. package/lib/utils/convertColor.js +7 -0
  147. package/lib/utils/importIcon.js +12 -0
  148. package/lib/utils/index.js +2 -0
  149. package/lib/utils/renderInlineSetting.js +2 -2
  150. package/package.json +18 -14
  151. package/lib/assets/icons.svg +0 -69
  152. package/lib/composables/__tests__/useToolbar.test.js +0 -56
@@ -1,26 +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';
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
+ });
4
16
 
5
17
  const MockFontWeight = Mark.create({
6
- name: 'font_weight',
18
+ name: TextSettings.FONT_WEIGHT,
19
+
20
+ addAttributes: () => ({
21
+ value: { default: null }
22
+ }),
23
+
24
+ renderHTML: () => ['span', {}, 0]
25
+ });
26
+
27
+ const MockAlignment = Extension.create({
28
+ name: TextSettings.ALIGNMENT,
29
+
30
+ addGlobalAttributes: () => [
31
+ {
32
+ types: [NodeTypes.PARAGRAPH, NodeTypes.HEADING],
33
+ attributes: {
34
+ [TextSettings.ALIGNMENT]: {
35
+ default: null,
36
+ renderHTML: () => ({})
37
+ }
38
+ }
39
+ }
40
+ ]
41
+ });
42
+
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,
7
65
 
8
66
  addAttributes: () => ({
9
- value: { required: true }
67
+ value: { default: null }
10
68
  }),
11
69
 
12
- renderHTML(context) {
13
- const { value } = context.HTMLAttributes;
70
+ renderHTML: () => ['span', {}, 0]
71
+ });
72
+
73
+ const MockFontStyle = Mark.create({
74
+ name: TextSettings.FONT_STYLE,
75
+
76
+ addAttributes: () => ({
77
+ value: { default: null }
78
+ }),
14
79
 
15
- return ['span', { style: `font-weight: ${value}` }, 0];
16
- }
80
+ renderHTML: () => ['span', {}, 0]
81
+ });
82
+
83
+ const MockTextDecoration = Mark.create({
84
+ name: TextSettings.TEXT_DECORATION,
85
+
86
+ addAttributes: () => ({
87
+ value: { default: null }
88
+ }),
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]
17
101
  });
18
102
 
19
103
  function createEditor({ content }) {
20
104
  return new Editor({
21
- content,
105
+ content: ContentNormalizer.normalize(content),
22
106
  element: document.createElement('div'),
23
- extensions: CORE_EXTENSIONS.concat(MockFontWeight)
107
+ extensions: buildCoreExtensions().concat(
108
+ MockFontSize,
109
+ MockFontWeight,
110
+ MockAlignment,
111
+ MockBackgroundColor,
112
+ MockFontColor,
113
+ MockFontFamily,
114
+ MockFontStyle,
115
+ MockTextDecoration,
116
+ MockSuperscript
117
+ )
24
118
  });
25
119
  }
26
120
 
@@ -59,3 +153,38 @@ describe('transform text', () => {
59
153
  expect(editor.getJSON()).toMatchSnapshot();
60
154
  });
61
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 CORE_EXTENSIONS = [
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';
@@ -1,5 +1,3 @@
1
- import History from '@tiptap/extension-history';
2
- import { CORE_EXTENSIONS } from './core';
3
1
  import { FontFamily } from './FontFamily';
4
2
  import { StylePreset } from './StylePreset';
5
3
  import { FontWeight } from './FontWeight';
@@ -13,37 +11,47 @@ import { CaseStyle } from './CaseStyle';
13
11
  import { Alignment } from './Alignment';
14
12
  import { LineHeight } from './LineHeight';
15
13
  import { List } from './list';
14
+ import { Link } from './Link';
16
15
  import { Superscript } from './Superscript';
16
+ import { buildCoreExtensions } from './core';
17
17
 
18
- export { CORE_EXTENSIONS };
18
+ export function buildExtensions(options) {
19
+ const getPresetById = (id) => options.presetsRef.value.find((preset) => preset.id === id);
20
+ const defaultPreset = getPresetById(options.defaultPresetId);
19
21
 
20
- export const getExtensions = (options) => CORE_EXTENSIONS.concat([
21
- History,
22
- StylePreset.configure({
23
- presetsRef: options.presetsRef,
24
- defaultId: options.defaultPresetId,
25
- makeVariable: options.makePresetVariable
26
- }),
27
- List.configure({
28
- baseClass: options.baseListClass
29
- }),
30
- DeviceManager.configure({
31
- deviceRef: options.deviceRef
32
- }),
33
- FontFamily.configure({
34
- fonts: options.fonts
35
- }),
36
- FontWeight,
37
- FontSize.configure({
38
- minSize: options.minFontSize,
39
- maxSize: options.maxFontSize
40
- }),
41
- FontColor,
42
- BackgroundColor,
43
- FontStyle,
44
- TextDecoration,
45
- CaseStyle,
46
- Superscript,
47
- Alignment,
48
- LineHeight
49
- ]);
22
+ return buildCoreExtensions(options).concat([
23
+ StylePreset.configure({
24
+ presetsRef: options.presetsRef,
25
+ defaultId: options.defaultPresetId,
26
+ baseClass: options.basePresetClass,
27
+ makeVariable: options.makePresetVariable
28
+ }),
29
+ List.configure({
30
+ baseClass: options.baseListClass
31
+ }),
32
+ DeviceManager.configure({
33
+ deviceRef: options.deviceRef
34
+ }),
35
+ FontFamily.configure({
36
+ fonts: options.fonts,
37
+ defaultFont: defaultPreset.common.font_family
38
+ }),
39
+ FontWeight,
40
+ FontSize.configure({
41
+ minSize: options.minFontSize,
42
+ maxSize: options.maxFontSize
43
+ }),
44
+ FontColor,
45
+ BackgroundColor,
46
+ FontStyle,
47
+ TextDecoration,
48
+ CaseStyle,
49
+ Superscript,
50
+ Alignment,
51
+ LineHeight,
52
+ Link.configure({
53
+ preset: options.linkPreset,
54
+ basePresetClass: options.basePresetClass,
55
+ pageBlocks: options.pageBlocks
56
+ })]);
57
+ }
@@ -21,6 +21,40 @@ export const List = Node.create({
21
21
  bullet: { isRequired: true }
22
22
  }),
23
23
 
24
+ parseHTML() {
25
+ const HTML_TYPES = {
26
+ a: ListTypes.ROMAN,
27
+ i: ListTypes.LATIN,
28
+ '1': ListTypes.DECIMAL
29
+ };
30
+
31
+ const getBulletType = (element) => {
32
+ for (const type of ListTypes.values) {
33
+ const bulletClass = `.${this.options.baseClass}${type}`;
34
+
35
+ if (element.matches(bulletClass)) return type;
36
+ if (HTML_TYPES[element.type.toLowerCase()] === type) return type;
37
+ }
38
+ };
39
+
40
+ return [
41
+ {
42
+ tag: 'ol',
43
+
44
+ getAttrs: (element) => ({
45
+ bullet: { type: getBulletType(element) || ListTypes.DECIMAL }
46
+ })
47
+ },
48
+ {
49
+ tag: 'ul',
50
+
51
+ getAttrs: (element) => ({
52
+ bullet: { type: getBulletType(element) || ListTypes.DISC }
53
+ })
54
+ }
55
+ ];
56
+ },
57
+
24
58
  renderHTML({ HTMLAttributes: attrs }) {
25
59
  const isOrdered = ListTypes.ordered.includes(attrs.bullet.type);
26
60
  const tag = isOrdered ? 'ol' : 'ul';
@@ -2,16 +2,19 @@ import { Editor } from '@tiptap/vue-2';
2
2
  import { ref } from '@vue/composition-api';
3
3
  import { NodeFactory } from '../../../__tests__/utils';
4
4
  import { ListTypes } from '../../../enums';
5
- import { CORE_EXTENSIONS } from '../../core';
6
5
  import { StylePreset } from '../../StylePreset';
7
6
  import { List } from '../List';
7
+ import { ContentNormalizer } from '../../../services';
8
+ import { buildCoreExtensions } from '../../core';
8
9
 
9
10
  function createEditor({ content }) {
10
11
  return new Editor({
11
- content,
12
+ content: ContentNormalizer.normalize(content),
12
13
  element: document.createElement('div'),
13
- extensions: CORE_EXTENSIONS.concat(
14
- List,
14
+ extensions: buildCoreExtensions().concat(
15
+ List.configure({
16
+ baseClass: 'zw-list--'
17
+ }),
15
18
  StylePreset.configure({
16
19
  presetsRef: ref([
17
20
  {
@@ -22,7 +25,8 @@ function createEditor({ content }) {
22
25
  desktop: {}
23
26
  }
24
27
  ]),
25
- defaultId: 'regular-1'
28
+ defaultId: 'regular-1',
29
+ baseClass: 'zw ts-'
26
30
  })
27
31
  )
28
32
  });
@@ -128,3 +132,109 @@ describe('apply list', () => {
128
132
  expect(editor.getJSON()).toMatchSnapshot();
129
133
  });
130
134
  });
135
+
136
+ describe('parsing html', () => {
137
+ test('should parse disc type by class', () => {
138
+ const editor = createEditor({
139
+ content: '<ul class="zw-list--disc"><li>lorem ipsum</li></ul>'
140
+ });
141
+
142
+ expect(editor.getJSON()).toMatchSnapshot();
143
+ });
144
+
145
+ test('should parse disc as default', () => {
146
+ const editor = createEditor({
147
+ content: '<ul><li>lorem ipsum</li></ul>'
148
+ });
149
+
150
+ expect(editor.getJSON()).toMatchSnapshot();
151
+ });
152
+
153
+ test('should parse circle type by class', () => {
154
+ const editor = createEditor({
155
+ content: '<ul class="zw-list--circle"><li>lorem ipsum</li></ul>'
156
+ });
157
+
158
+ expect(editor.getJSON()).toMatchSnapshot();
159
+ });
160
+
161
+ test('should parse square type by class', () => {
162
+ const editor = createEditor({
163
+ content: '<ul class="zw-list--square"><li>lorem ipsum</li></ul>'
164
+ });
165
+
166
+ expect(editor.getJSON()).toMatchSnapshot();
167
+ });
168
+
169
+ test('should parse decimal type by class', () => {
170
+ const editor = createEditor({
171
+ content: '<ol class="zw-list--decimal"><li>lorem ipsum</li></ol>'
172
+ });
173
+
174
+ expect(editor.getJSON()).toMatchSnapshot();
175
+ });
176
+
177
+ test('should parse decimal as default', () => {
178
+ const editor = createEditor({
179
+ content: '<ol><li>lorem ipsum</li></ol>'
180
+ });
181
+
182
+ expect(editor.getJSON()).toMatchSnapshot();
183
+ });
184
+
185
+ test('should parse decimal type by attribute', () => {
186
+ const editor = createEditor({
187
+ content: '<ol type="1"><li>lorem ipsum</li></ol>'
188
+ });
189
+
190
+ expect(editor.getJSON()).toMatchSnapshot();
191
+ });
192
+
193
+ test('should parse roman type by class', () => {
194
+ const editor = createEditor({
195
+ content: '<ol class="zw-list--roman"><li>lorem ipsum</li></ol>'
196
+ });
197
+
198
+ expect(editor.getJSON()).toMatchSnapshot();
199
+ });
200
+
201
+ test('should parse roman type by lower attribute', () => {
202
+ const editor = createEditor({
203
+ content: '<ol type="a"><li>lorem ipsum</li></ol>'
204
+ });
205
+
206
+ expect(editor.getJSON()).toMatchSnapshot();
207
+ });
208
+
209
+ test('should parse roman type by upper attribute', () => {
210
+ const editor = createEditor({
211
+ content: '<ol type="A"><li>lorem ipsum</li></ol>'
212
+ });
213
+
214
+ expect(editor.getJSON()).toMatchSnapshot();
215
+ });
216
+
217
+ test('should parse latin type by class', () => {
218
+ const editor = createEditor({
219
+ content: '<ol class="zw-list--latin"><li>lorem ipsum</li></ol>'
220
+ });
221
+
222
+ expect(editor.getJSON()).toMatchSnapshot();
223
+ });
224
+
225
+ test('should parse latin type by lower attribute', () => {
226
+ const editor = createEditor({
227
+ content: '<ol type="i"><li>lorem ipsum</li></ol>'
228
+ });
229
+
230
+ expect(editor.getJSON()).toMatchSnapshot();
231
+ });
232
+
233
+ test('should parse latin type by upper attribute', () => {
234
+ const editor = createEditor({
235
+ content: '<ol type="I"><li>lorem ipsum</li></ol>'
236
+ });
237
+
238
+ expect(editor.getJSON()).toMatchSnapshot();
239
+ });
240
+ });