@zipify/wysiwyg 1.0.0-dev.9 → 1.0.0-dev.92

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 (232) hide show
  1. package/.editorconfig +1 -1
  2. package/.eslintrc.js +2 -2
  3. package/.github/dependabot.yaml +1 -0
  4. package/.lintstagedrc +2 -2
  5. package/.release-it.json +3 -1
  6. package/.stylelintrc +0 -4
  7. package/README.md +2 -2
  8. package/config/jest/setupTests.js +0 -3
  9. package/config/vite/example.config.js +25 -0
  10. package/config/vite/lib.config.js +30 -0
  11. package/config/{webpack → vite}/settings.js +0 -0
  12. package/dist/wysiwyg.css +404 -373
  13. package/dist/wysiwyg.mjs +26015 -0
  14. package/example/ExampleApp.vue +35 -4
  15. package/example/example.js +0 -3
  16. package/example/{example.html → index.html} +1 -0
  17. package/example/pageBlocks.js +31 -0
  18. package/example/presets.js +2 -2
  19. package/example/tooltip/Tooltip.js +1 -1
  20. package/jest.config.js +3 -1
  21. package/lib/Wysiwyg.vue +73 -14
  22. package/lib/__tests__/utils/index.js +0 -1
  23. package/lib/__tests__/utils/withComponentContext.js +1 -1
  24. package/lib/assets/icons/background-color.svg +3 -1
  25. package/lib/assets/icons/font-color.svg +1 -3
  26. package/lib/assets/icons/link.svg +3 -0
  27. package/lib/assets/icons/unlink.svg +3 -0
  28. package/lib/components/base/Button.vue +23 -2
  29. package/lib/components/base/Checkbox.vue +89 -0
  30. package/lib/components/base/FieldLabel.vue +2 -1
  31. package/lib/components/base/Icon.vue +3 -3
  32. package/lib/components/base/Modal.vue +1 -2
  33. package/lib/components/base/NumberField.vue +2 -2
  34. package/lib/components/base/Range.vue +1 -1
  35. package/lib/components/base/ScrollView.vue +1 -3
  36. package/lib/components/base/TextField.vue +108 -0
  37. package/lib/components/base/__tests__/Modal.test.js +7 -2
  38. package/lib/components/base/__tests__/TextField.test.js +57 -0
  39. package/lib/components/base/__tests__/__snapshots__/TextField.test.js.snap +9 -0
  40. package/lib/components/base/colorPicker/ColorPicker.vue +14 -12
  41. package/lib/components/base/colorPicker/composables/__tests__/usePickerApi.test.js +6 -6
  42. package/lib/components/base/colorPicker/composables/usePickerApi.js +15 -8
  43. package/lib/components/base/colorPicker/composables/usePickerHotkeys.js +3 -2
  44. package/lib/components/base/composables/__tests__/useActivatedListener.test.js +1 -1
  45. package/lib/components/base/composables/__tests__/useDeselectionLock.test.js +1 -1
  46. package/lib/components/base/composables/__tests__/useElementRef.test.js +1 -1
  47. package/lib/components/base/composables/__tests__/useModalToggler.test.js +1 -1
  48. package/lib/components/base/composables/__tests__/useNumberValue.test.js +1 -1
  49. package/lib/components/base/composables/__tests__/useScrollView.test.js +1 -1
  50. package/lib/components/base/composables/__tests__/useTempValue.test.js +1 -1
  51. package/lib/components/base/composables/__tests__/useValidator.test.js +44 -0
  52. package/lib/components/base/composables/index.js +1 -0
  53. package/lib/components/base/composables/useActivatedListener.js +1 -1
  54. package/lib/components/base/composables/useDeselectionLock.js +1 -1
  55. package/lib/components/base/composables/useElementRef.js +1 -1
  56. package/lib/components/base/composables/useModalToggler.js +6 -2
  57. package/lib/components/base/composables/useScrollView.js +1 -1
  58. package/lib/components/base/composables/useTempValue.js +1 -1
  59. package/lib/components/base/composables/useValidator.js +23 -0
  60. package/lib/components/base/dropdown/Dropdown.vue +16 -4
  61. package/lib/components/base/dropdown/DropdownActivator.vue +19 -3
  62. package/lib/components/base/dropdown/DropdownGroup.vue +1 -1
  63. package/lib/components/base/dropdown/DropdownMenu.vue +1 -1
  64. package/lib/components/base/dropdown/DropdownOption.vue +1 -1
  65. package/lib/components/base/dropdown/__tests__/DropdownActivator.test.js +1 -1
  66. package/lib/components/base/dropdown/__tests__/DropdownMenu.test.js +1 -1
  67. package/lib/components/base/dropdown/__tests__/DropdownOption.test.js +1 -1
  68. package/lib/components/base/dropdown/composables/__tests__/useActiveOptionManager.test.js +1 -1
  69. package/lib/components/base/dropdown/composables/__tests__/useDropdownEntityTitle.test.js +1 -1
  70. package/lib/components/base/dropdown/composables/useActiveOptionManager.js +1 -1
  71. package/lib/components/base/dropdown/composables/useDropdownEntityTitle.js +1 -1
  72. package/lib/components/base/index.js +3 -1
  73. package/lib/components/toolbar/Toolbar.vue +51 -9
  74. package/lib/components/toolbar/ToolbarDivider.vue +1 -1
  75. package/lib/components/toolbar/ToolbarFull.vue +41 -10
  76. package/lib/components/toolbar/ToolbarRow.vue +1 -0
  77. package/lib/components/toolbar/__tests__/Toolbar.test.js +6 -0
  78. package/lib/components/toolbar/controls/AlignmentControl.vue +1 -1
  79. package/lib/components/toolbar/controls/AlignmentDeviceControl.vue +1 -1
  80. package/lib/components/toolbar/controls/BackgroundColorControl.vue +1 -1
  81. package/lib/components/toolbar/controls/CaseStyleControl.vue +1 -1
  82. package/lib/components/toolbar/controls/FontColorControl.vue +1 -1
  83. package/lib/components/toolbar/controls/FontFamilyControl.vue +1 -1
  84. package/lib/components/toolbar/controls/FontSizeControl.vue +8 -1
  85. package/lib/components/toolbar/controls/FontWeightControl.vue +2 -2
  86. package/lib/components/toolbar/controls/ItalicControl.vue +1 -1
  87. package/lib/components/toolbar/controls/LineHeightControl.vue +1 -1
  88. package/lib/components/toolbar/controls/ListControl.vue +70 -36
  89. package/lib/components/toolbar/controls/RemoveFormatControl.vue +1 -1
  90. package/lib/components/toolbar/controls/StrikeThroughControl.vue +1 -1
  91. package/lib/components/toolbar/controls/StylePresetControl.vue +17 -4
  92. package/lib/components/toolbar/controls/SuperscriptControl.vue +1 -1
  93. package/lib/components/toolbar/controls/UnderlineControl.vue +1 -1
  94. package/lib/components/toolbar/controls/__tests__/AlignmentControl.test.js +1 -1
  95. package/lib/components/toolbar/controls/__tests__/AlignmentDeviceControl.test.js +1 -1
  96. package/lib/components/toolbar/controls/__tests__/BackgroundColorControl.test.js +1 -1
  97. package/lib/components/toolbar/controls/__tests__/CaseStyleControl.test.js +1 -1
  98. package/lib/components/toolbar/controls/__tests__/FontColorControl.test.js +1 -1
  99. package/lib/components/toolbar/controls/__tests__/FontFamilyControl.test.js +1 -1
  100. package/lib/components/toolbar/controls/__tests__/FontSizeControl.test.js +1 -1
  101. package/lib/components/toolbar/controls/__tests__/FontWeightControl.test.js +1 -1
  102. package/lib/components/toolbar/controls/__tests__/ItalicControl.test.js +1 -1
  103. package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +1 -1
  104. package/lib/components/toolbar/controls/__tests__/ListControl.test.js +18 -3
  105. package/lib/components/toolbar/controls/__tests__/StrikeThroughControl.test.js +1 -1
  106. package/lib/components/toolbar/controls/__tests__/StylePresetControl.test.js +17 -1
  107. package/lib/components/toolbar/controls/__tests__/UnderlineControl.test.js +5 -1
  108. package/lib/components/toolbar/controls/composables/useRecentFonts.js +1 -1
  109. package/lib/components/toolbar/controls/index.js +1 -0
  110. package/lib/components/toolbar/controls/link/LinkControl.vue +160 -0
  111. package/lib/components/toolbar/controls/link/LinkControlApply.vue +35 -0
  112. package/lib/components/toolbar/controls/link/LinkControlHeader.vue +69 -0
  113. package/lib/components/toolbar/controls/link/__tests__/LinkControl.test.js +79 -0
  114. package/lib/components/toolbar/controls/link/__tests__/LinkControlHeader.test.js +42 -0
  115. package/lib/components/toolbar/controls/link/composables/__tests__/__snapshots__/useLink.test.js.snap +15 -0
  116. package/lib/components/toolbar/controls/link/composables/__tests__/useLink.test.js +172 -0
  117. package/lib/components/toolbar/controls/link/composables/index.js +1 -0
  118. package/lib/components/toolbar/controls/link/composables/useLink.js +82 -0
  119. package/lib/components/toolbar/controls/link/destination/LinkControlDestination.vue +103 -0
  120. package/lib/components/toolbar/controls/link/destination/LinkControlPageBlock.vue +54 -0
  121. package/lib/components/toolbar/controls/link/destination/LinkControlUrl.vue +52 -0
  122. package/lib/components/toolbar/controls/link/destination/__tests__/LinkControlPageBlock.test.js +36 -0
  123. package/lib/components/toolbar/controls/link/destination/__tests__/LinkControlUrl.test.js +46 -0
  124. package/lib/components/toolbar/controls/link/destination/__tests__/__snapshots__/LinkControlPageBlock.test.js.snap +9 -0
  125. package/lib/components/toolbar/controls/link/destination/__tests__/__snapshots__/LinkControlUrl.test.js.snap +17 -0
  126. package/lib/components/toolbar/controls/link/destination/index.js +1 -0
  127. package/lib/components/toolbar/controls/link/index.js +1 -0
  128. package/lib/composables/__tests__/__snapshots__/useEditor.test.js.snap +1 -0
  129. package/lib/composables/__tests__/useEditor.test.js +5 -4
  130. package/lib/composables/useEditor.js +12 -9
  131. package/lib/composables/useToolbar.js +26 -19
  132. package/lib/directives/__tests__/outClick.test.js +6 -0
  133. package/lib/directives/outClick.js +19 -6
  134. package/lib/enums/Alignments.js +10 -1
  135. package/lib/enums/LinkDestinations.js +4 -0
  136. package/lib/enums/LinkTargets.js +4 -0
  137. package/lib/enums/TextSettings.js +3 -1
  138. package/lib/enums/index.js +2 -0
  139. package/lib/extensions/Alignment.js +25 -11
  140. package/lib/extensions/BackgroundColor.js +15 -7
  141. package/lib/extensions/DeviceManager.js +2 -5
  142. package/lib/extensions/FontColor.js +17 -9
  143. package/lib/extensions/FontFamily.js +30 -13
  144. package/lib/extensions/FontSize.js +38 -18
  145. package/lib/extensions/FontStyle.js +30 -20
  146. package/lib/extensions/FontWeight.js +34 -23
  147. package/lib/extensions/LineHeight.js +36 -32
  148. package/lib/extensions/Link.js +92 -0
  149. package/lib/extensions/StylePreset.js +23 -22
  150. package/lib/extensions/Superscript.js +5 -1
  151. package/lib/extensions/TextDecoration.js +52 -19
  152. package/lib/extensions/__tests__/Alignment.test.js +14 -9
  153. package/lib/extensions/__tests__/BackgroundColor.test.js +13 -8
  154. package/lib/extensions/__tests__/CaseStyle.test.js +4 -7
  155. package/lib/extensions/__tests__/FontColor.test.js +13 -8
  156. package/lib/extensions/__tests__/FontFamily.test.js +34 -10
  157. package/lib/extensions/__tests__/FontSize.test.js +16 -10
  158. package/lib/extensions/__tests__/FontStyle.test.js +13 -8
  159. package/lib/extensions/__tests__/FontWeight.test.js +21 -8
  160. package/lib/extensions/__tests__/LineHeight.test.js +25 -14
  161. package/lib/extensions/__tests__/Link.test.js +101 -0
  162. package/lib/extensions/__tests__/StylePreset.test.js +72 -10
  163. package/lib/extensions/__tests__/TextDecoration.test.js +53 -8
  164. package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +26 -2
  165. package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +30 -1
  166. package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +18 -1
  167. package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +88 -1
  168. package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +33 -2
  169. package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +25 -4
  170. package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +47 -1
  171. package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +26 -2
  172. package/lib/extensions/__tests__/__snapshots__/Link.test.js.snap +225 -0
  173. package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +6 -2
  174. package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +183 -3
  175. package/lib/extensions/core/CopyPasteProcessor.js +10 -0
  176. package/lib/extensions/core/NodeProcessor.js +2 -2
  177. package/lib/extensions/core/TextProcessor.js +11 -24
  178. package/lib/extensions/core/__tests__/NodeProcessor.test.js +4 -7
  179. package/lib/extensions/core/__tests__/SelectionProcessor.test.js +4 -7
  180. package/lib/extensions/core/__tests__/TextProcessor.test.js +139 -14
  181. package/lib/extensions/core/__tests__/__snapshots__/TextProcessor.test.js.snap +26 -0
  182. package/lib/extensions/core/index.js +11 -2
  183. package/lib/extensions/core/plugins/PastePlugin.js +57 -0
  184. package/lib/extensions/core/plugins/ProseMirrorPlugin.js +20 -0
  185. package/lib/extensions/core/plugins/index.js +1 -0
  186. package/lib/extensions/index.js +46 -34
  187. package/lib/extensions/list/List.js +7 -6
  188. package/lib/extensions/list/__tests__/List.test.js +6 -10
  189. package/lib/extensions/list/__tests__/__snapshots__/List.test.js.snap +60 -20
  190. package/lib/index.js +3 -0
  191. package/lib/injectionTokens.js +3 -1
  192. package/lib/services/ContentNormalizer.js +144 -28
  193. package/lib/services/ContextWidnow.js +23 -0
  194. package/lib/{__tests__/utils → services}/NodeFactory.js +5 -1
  195. package/lib/services/__tests__/ContentNormalizer.test.js +124 -8
  196. package/lib/services/__tests__/FavoriteColors.test.js +1 -1
  197. package/lib/services/index.js +2 -0
  198. package/lib/styles/content.css +108 -13
  199. package/lib/styles/helpers/offsets.css +16 -0
  200. package/lib/styles/variables.css +6 -0
  201. package/lib/utils/__tests__/__snapshots__/renderInlineSetting.test.js.snap +4 -4
  202. package/lib/utils/__tests__/convertAlignment.test.js +16 -0
  203. package/lib/utils/__tests__/convertFontSize.test.js +21 -0
  204. package/lib/utils/__tests__/convertLineHeight.test.js +21 -0
  205. package/lib/utils/convertAlignment.js +12 -0
  206. package/lib/utils/convertColor.js +1 -1
  207. package/lib/utils/convertFontSize.js +8 -0
  208. package/lib/utils/convertLineHeight.js +17 -0
  209. package/lib/utils/importIcon.js +7 -6
  210. package/lib/utils/index.js +4 -0
  211. package/lib/utils/isWysiwygContent.js +12 -0
  212. package/lib/utils/renderInlineSetting.js +1 -1
  213. package/package.json +26 -30
  214. package/config/webpack/example.config.js +0 -88
  215. package/config/webpack/lib.config.js +0 -44
  216. package/config/webpack/loaders/index.js +0 -6
  217. package/config/webpack/loaders/js-loader.js +0 -5
  218. package/config/webpack/loaders/style-loader.js +0 -9
  219. package/config/webpack/loaders/svg-loader.js +0 -4
  220. package/config/webpack/loaders/vue-loader.js +0 -4
  221. package/dist/wysiwyg.js +0 -2
  222. package/dist/wysiwyg.js.LICENSE.txt +0 -1
  223. package/lib/extensions/core/inputRules/closeDoubleQuote.js +0 -6
  224. package/lib/extensions/core/inputRules/closeSingleQuote.js +0 -6
  225. package/lib/extensions/core/inputRules/copyright.js +0 -6
  226. package/lib/extensions/core/inputRules/ellipsis.js +0 -6
  227. package/lib/extensions/core/inputRules/emDash.js +0 -6
  228. package/lib/extensions/core/inputRules/index.js +0 -9
  229. package/lib/extensions/core/inputRules/openDoubleQuote.js +0 -6
  230. package/lib/extensions/core/inputRules/openSingleQuote.js +0 -6
  231. package/lib/extensions/core/inputRules/registeredTrademark.js +0 -6
  232. package/lib/extensions/core/inputRules/trademark.js +0 -6
@@ -1,5 +1,5 @@
1
1
  import { Mark } from '@tiptap/vue-2';
2
- import { computed } from '@vue/composition-api';
2
+ import { computed, unref } from 'vue';
3
3
  import { createCommand, createKeyboardShortcut, renderMark } from '../utils';
4
4
  import { TextSettings } from '../enums';
5
5
 
@@ -14,7 +14,7 @@ export const FontWeight = Mark.create({
14
14
  return {
15
15
  applyFontWeight: createCommand(({ commands }, value) => {
16
16
  commands.setMark(this.name, { value });
17
- const font = commands.getFont().value;
17
+ const font = unref(commands.getFont());
18
18
 
19
19
  if (!font.isItalicSupported(value)) {
20
20
  commands.removeItalic();
@@ -22,8 +22,8 @@ export const FontWeight = Mark.create({
22
22
  }),
23
23
 
24
24
  toggleBold: createCommand(({ commands }) => {
25
- const currentWeight = commands.getFontWeight().value;
26
- const currentFont = commands.getFont().value;
25
+ const currentWeight = unref(commands.getFontWeight());
26
+ const currentFont = unref(commands.getFont());
27
27
  const isBold = Number(currentWeight) >= 600;
28
28
  const wantedWeight = isBold ? '400' : '700';
29
29
  const nextWeight = currentFont.findClosestWeight(wantedWeight);
@@ -33,23 +33,24 @@ export const FontWeight = Mark.create({
33
33
 
34
34
  getFontWeight: createCommand(({ editor, commands }) => {
35
35
  const defaultValue = commands.getDefaultFontWeight();
36
- const font = commands.getFont();
36
+ const fontRef = commands.getFont();
37
37
 
38
38
  return computed(() => {
39
- const weight = editor.getAttributes(this.name)?.value ?? defaultValue.value;
39
+ const weight = editor.getAttributes(this.name)?.value ?? unref(defaultValue);
40
+ const font = unref(fontRef);
40
41
 
41
- if (font.value.isWeightSupported(weight)) {
42
+ if (font.isWeightSupported(weight)) {
42
43
  return weight;
43
44
  }
44
45
 
45
- return font.value.findClosestWeight(weight);
46
+ return font.findClosestWeight(weight);
46
47
  });
47
48
  }),
48
49
 
49
50
  getDefaultFontWeight: createCommand(({ commands }) => {
50
51
  const preset = commands.getPreset();
51
52
 
52
- return computed(() => preset.value.common.font_weight);
53
+ return computed(() => unref(preset).common.font_weight);
53
54
  })
54
55
  };
55
56
  },
@@ -59,20 +60,30 @@ export const FontWeight = Mark.create({
59
60
  'Mod-B': createKeyboardShortcut('toggleBold')
60
61
  }),
61
62
 
62
- parseHTML: () => [
63
- {
64
- tag: 'b',
65
- attrs: { value: '700' }
66
- },
67
- {
68
- tag: 'strong',
69
- attrs: { value: '700' }
70
- },
71
- {
72
- style: 'font-weight',
73
- getAttrs: (value) => ({ value })
74
- }
75
- ],
63
+ parseHTML() {
64
+ const getAttrs = (value) => {
65
+ return Number(value) ? { value } : false;
66
+ };
67
+
68
+ return [
69
+ {
70
+ style: '--zw-font-weight',
71
+ getAttrs
72
+ },
73
+ {
74
+ style: 'font-weight',
75
+ getAttrs
76
+ },
77
+ {
78
+ tag: 'b',
79
+ attrs: { value: '700' }
80
+ },
81
+ {
82
+ tag: 'strong',
83
+ attrs: { value: '700' }
84
+ }
85
+ ];
86
+ },
76
87
 
77
88
  renderHTML({ HTMLAttributes: attrs }) {
78
89
  return renderMark({ font_weight: attrs.value });
@@ -1,6 +1,6 @@
1
1
  import { Extension } from '@tiptap/vue-2';
2
- import { computed } from '@vue/composition-api';
3
- import { createCommand, renderInlineSetting } from '../utils';
2
+ import { computed, unref } from 'vue';
3
+ import { createCommand, renderInlineSetting, convertLineHeight } from '../utils';
4
4
  import { NodeTypes, TextSettings } from '../enums';
5
5
 
6
6
  const DEFAULTS = {
@@ -12,43 +12,47 @@ const DEFAULTS = {
12
12
  export const LineHeight = Extension.create({
13
13
  name: TextSettings.LINE_HEIGHT,
14
14
 
15
- addGlobalAttributes: () => [
16
- {
17
- types: [NodeTypes.PARAGRAPH, NodeTypes.HEADING],
18
- attributes: {
19
- [TextSettings.LINE_HEIGHT]: {
20
- isRequired: false,
15
+ addGlobalAttributes() {
16
+ return [
17
+ {
18
+ types: [NodeTypes.PARAGRAPH, NodeTypes.HEADING],
19
+ attributes: {
20
+ [TextSettings.LINE_HEIGHT]: {
21
+ isRequired: false,
21
22
 
22
- parseHTML(element) {
23
- const value = element.style.lineHeight;
23
+ parseHTML: (element) => {
24
+ if (element.matches('[style*="--zw-line-height"]')) {
25
+ const mobile = element.style.getPropertyValue('--zw-line-height-mobile') || null;
26
+ const tablet = element.style.getPropertyValue('--zw-line-height-tablet') || null;
27
+ const desktop = element.style.getPropertyValue('--zw-line-height-desktop') || null;
24
28
 
25
- if (!value) return null;
29
+ return { mobile, tablet, desktop };
30
+ }
26
31
 
27
- if (!value.includes('px')) {
28
- return { desktop: value, tablet: value, mobile: value };
29
- }
32
+ const value = element.style.lineHeight;
33
+
34
+ if (!value) return null;
30
35
 
31
- // element is not connected to window so getComputedStyle is not working on element
32
- const childFontSize = element.firstElementChild.style.fontSize;
33
- const fontSize = childFontSize || window.getComputedStyle(document.body).fontSize;
34
- const relative = (parseFloat(value) / parseFloat(fontSize)).toFixed(2);
36
+ const wrapperEl = unref(this.options.wrapperRef);
37
+ const converted = convertLineHeight(value, element, wrapperEl);
35
38
 
36
- return { desktop: relative, tablet: relative, mobile: relative };
37
- },
39
+ return { desktop: converted, tablet: converted, mobile: converted };
40
+ },
38
41
 
39
- renderHTML(attrs) {
40
- if (!attrs.line_height) return null;
42
+ renderHTML(attrs) {
43
+ if (!attrs.line_height) return null;
41
44
 
42
- return renderInlineSetting({
43
- mobile_line_height: attrs.line_height.mobile,
44
- tablet_line_height: attrs.line_height.tablet,
45
- desktop_line_height: attrs.line_height.desktop
46
- });
45
+ return renderInlineSetting({
46
+ line_height_mobile: attrs.line_height.mobile,
47
+ line_height_tablet: attrs.line_height.tablet,
48
+ line_height_desktop: attrs.line_height.desktop
49
+ });
50
+ }
47
51
  }
48
52
  }
49
53
  }
50
- }
51
- ],
54
+ ];
55
+ },
52
56
 
53
57
  addCommands() {
54
58
  return {
@@ -57,18 +61,18 @@ export const LineHeight = Extension.create({
57
61
  const device = commands.getDevice();
58
62
  const defaultValue = commands.getDefaultLineHeight();
59
63
 
60
- return computed(() => attribute.value?.[device.value] ?? defaultValue.value);
64
+ return computed(() => unref(attribute)?.[unref(device)] ?? unref(defaultValue));
61
65
  }),
62
66
 
63
67
  getDefaultLineHeight: createCommand(({ commands }) => {
64
68
  const device = commands.getDevice();
65
69
  const preset = commands.getPreset();
66
70
 
67
- return computed(() => preset.value[device.value].line_height);
71
+ return computed(() => unref(preset)[unref(device)].line_height);
68
72
  }),
69
73
 
70
74
  applyLineHeight: createCommand(({ commands }, value) => {
71
- const device = commands.getDevice().value;
75
+ const device = unref(commands.getDevice());
72
76
 
73
77
  commands.setBlockAttributes(this.name, { [device]: value }, DEFAULTS);
74
78
  })
@@ -0,0 +1,92 @@
1
+ import Base from '@tiptap/extension-link';
2
+ import { unref } from 'vue';
3
+ import { createCommand } from '../utils';
4
+ import { LinkDestinations, LinkTargets } from '../enums';
5
+
6
+ export const Link = Base.extend({
7
+ name: 'link',
8
+
9
+ addOptions() {
10
+ return {
11
+ ...this.parent?.(),
12
+ openOnClick: false
13
+ };
14
+ },
15
+
16
+ addAttributes() {
17
+ return {
18
+ href: {
19
+ default: null,
20
+ parseHTML: (element) => {
21
+ const href = element.getAttribute('href');
22
+
23
+ if (!href.startsWith('#')) return href;
24
+
25
+ return parseFloat(element.getAttribute('href').replace('#', ''));
26
+ }
27
+ },
28
+
29
+ target: {
30
+ default: LinkTargets.SELF,
31
+ parseHTML: (element) => element.getAttribute('target') || LinkTargets.SELF
32
+ },
33
+
34
+ destination: {
35
+ default: LinkDestinations.URL,
36
+
37
+ parseHTML: (element) => {
38
+ const href = element.getAttribute('href');
39
+
40
+ if (!href.startsWith('#')) return LinkDestinations.URL;
41
+
42
+ const id = href.replace('#', '');
43
+ const blocks = unref(this.options.pageBlocks);
44
+ const block = blocks.find((block) => block.id === parseInt(id));
45
+
46
+ return block ? LinkDestinations.BLOCK : LinkDestinations.URL;
47
+ }
48
+ }
49
+ };
50
+ },
51
+
52
+ addCommands() {
53
+ return {
54
+ ...this.parent?.(),
55
+ applyLink: createCommand(({ commands, chain }, attributes) => {
56
+ if (!commands.getSelectedText()) {
57
+ return commands.insertContent({
58
+ type: 'text',
59
+ marks: [
60
+ {
61
+ type: 'link',
62
+ attrs: { ...attributes }
63
+ }
64
+ ],
65
+ text: attributes.text
66
+ });
67
+ }
68
+
69
+ return chain()
70
+ .setMark(this.name, attributes)
71
+ .transformText(() => attributes.text)
72
+ .extendMarkRange('link')
73
+ .run();
74
+ })
75
+ };
76
+ },
77
+
78
+ renderHTML({ HTMLAttributes: attrs }) {
79
+ const href = attrs.destination === LinkDestinations.BLOCK ? `#${attrs.href}` : attrs.href;
80
+
81
+ const presetClass = this.options.basePresetClass + this.options.preset.id;
82
+ const classes = `${presetClass} zw-style`;
83
+
84
+ const linkAttrs = {
85
+ href,
86
+ target: attrs.target,
87
+ class: classes
88
+ };
89
+
90
+ return ['a', linkAttrs, 0];
91
+ }
92
+ });
@@ -1,8 +1,9 @@
1
1
  import { Extension } from '@tiptap/vue-2';
2
- import { computed, toRef } from '@vue/composition-api';
2
+ import { computed, toRef, unref } from 'vue';
3
3
  import { Heading } from '@tiptap/extension-heading';
4
4
  import { createCommand } from '../utils';
5
5
  import { Devices, NodeTypes, TextSettings } from '../enums';
6
+ import { ContextWindow } from '../services';
6
7
 
7
8
  function makePresetClass(base, preset) {
8
9
  const baseClass = base.split(' ').map((part) => `.${part}`).join('');
@@ -20,13 +21,6 @@ export const StylePreset = Extension.create({
20
21
  })
21
22
  ],
22
23
 
23
- addOptions: () => ({
24
- presetsRef: null,
25
- defaultId: null,
26
- baseClass: null,
27
- makeVariable: null
28
- }),
29
-
30
24
  addStorage: () => ({
31
25
  presetStyleEl: null
32
26
  }),
@@ -38,10 +32,12 @@ export const StylePreset = Extension.create({
38
32
  attributes: {
39
33
  preset: {
40
34
  isRequired: false,
41
- default: null,
35
+ default: { id: this.options.defaultId },
42
36
 
43
37
  parseHTML: (element) => {
44
- const presets = this.options.presetsRef.value;
38
+ const presets = unref(this.options.presets);
39
+
40
+ if (element.parentElement.tagName === 'LI') return null;
45
41
 
46
42
  for (const { id, node, fallbackClass } of presets) {
47
43
  const isFallback = fallbackClass && element.classList.contains(fallbackClass);
@@ -76,18 +72,18 @@ export const StylePreset = Extension.create({
76
72
 
77
73
  return {
78
74
  getPresetList: createCommand(() => computed(() => {
79
- return this.options.presetsRef.value.filter((preset) => !preset.hidden);
75
+ return this.options.presets.filter((preset) => !preset.hidden);
80
76
  })),
81
77
 
82
78
  getPreset: createCommand(({ commands }) => {
83
79
  const selection = commands.getBlockAttributes('preset', { id: this.options.defaultId });
84
80
  const presets = commands.getPresetList();
85
81
 
86
- return computed(() => findPresetById(presets.value, selection.value.id));
82
+ return computed(() => findPresetById(unref(presets), unref(selection).id));
87
83
  }),
88
84
 
89
85
  applyPreset: createCommand(({ commands, chain }, presetId) => {
90
- const presets = commands.getPresetList().value;
86
+ const presets = unref(commands.getPresetList());
91
87
  const preset = findPresetById(presets, presetId);
92
88
  const nodeType = preset.node?.type ?? NodeTypes.PARAGRAPH;
93
89
 
@@ -100,7 +96,7 @@ export const StylePreset = Extension.create({
100
96
  }
101
97
 
102
98
  for (const textAttribute of TextSettings.attributes) {
103
- attrs[textAttribute] = commands.getBlockAttributes(textAttribute).value;
99
+ attrs[textAttribute] = unref(commands.getBlockAttributes(textAttribute));
104
100
  }
105
101
 
106
102
  chain().removeList().setNode(nodeType, attrs).run();
@@ -147,32 +143,37 @@ export const StylePreset = Extension.create({
147
143
  chain()
148
144
  .storeSelection()
149
145
  .expandSelectionToBlock()
150
- .unsetAllMarks()
146
+ .unsetMarks(TextSettings.marks)
151
147
  .resetAttributes(NodeTypes.PARAGRAPH, TextSettings.attributes)
152
148
  .resetAttributes(NodeTypes.HEADING, TextSettings.attributes)
153
149
  .restoreSelection()
154
150
  .run();
155
151
  }),
156
152
 
157
- removeFormat: createCommand(({ commands }) => {
158
- commands.removePresetCustomization();
159
- commands.applyDefaultPreset();
153
+ removeFormat: createCommand(({ chain }) => {
154
+ chain()
155
+ .storeSelection()
156
+ .expandSelectionToBlock()
157
+ .unsetAllMarks()
158
+ .applyDefaultPreset()
159
+ .restoreSelection()
160
+ .run();
160
161
  })
161
162
  };
162
163
  },
163
164
 
164
165
  onCreate() {
165
- const existingStyleEl = document.querySelector('[data-zw-styles]');
166
+ const existingStyleEl = ContextWindow.document.querySelector('[data-zw-styles]');
166
167
 
167
168
  if (existingStyleEl) {
168
169
  this.storage.presetStyleEl = existingStyleEl;
169
170
  return;
170
171
  }
171
172
 
172
- this.storage.presetStyleEl = document.createElement('style');
173
+ this.storage.presetStyleEl = ContextWindow.document.createElement('style');
173
174
  this.storage.presetStyleEl.dataset.zwStyles = '';
174
175
 
175
- for (const preset of this.options.presetsRef.value) {
176
+ for (const preset of this.options.presets) {
176
177
  const className = makePresetClass(this.options.baseClass, preset);
177
178
  const css = [` ${className} {`];
178
179
 
@@ -190,6 +191,6 @@ export const StylePreset = Extension.create({
190
191
  this.storage.presetStyleEl.innerHTML += css.join(' ');
191
192
  }
192
193
 
193
- document.head.append(this.storage.presetStyleEl);
194
+ ContextWindow.head.append(this.storage.presetStyleEl);
194
195
  }
195
196
  });
@@ -1,5 +1,9 @@
1
1
  import Base from '@tiptap/extension-superscript';
2
2
 
3
3
  export const Superscript = Base.extend({
4
- addKeyboardShortcuts: null
4
+ addKeyboardShortcuts: null,
5
+
6
+ addOptions: () => ({
7
+ HTMLAttributes: { class: 'zw-superscript' }
8
+ })
5
9
  });
@@ -1,5 +1,5 @@
1
1
  import { Mark } from '@tiptap/vue-2';
2
- import { computed } from '@vue/composition-api';
2
+ import { computed, unref } from 'vue';
3
3
  import { createCommand, createKeyboardShortcut, renderMark } from '../utils';
4
4
  import { TextSettings } from '../enums';
5
5
 
@@ -13,16 +13,16 @@ export const TextDecoration = Mark.create({
13
13
 
14
14
  addCommands() {
15
15
  return {
16
- isUnderline: createCommand(({ commands }) => {
16
+ isUnderline: createCommand(({ commands, editor }) => {
17
17
  const decoration = commands.getTextDecoration();
18
18
 
19
- return computed(() => decoration.value.underline);
19
+ return computed(() => editor.isActive('link') || unref(decoration).underline);
20
20
  }),
21
21
 
22
22
  isStrikeThrough: createCommand(({ commands }) => {
23
23
  const decoration = commands.getTextDecoration();
24
24
 
25
- return computed(() => decoration.value.strike_through);
25
+ return computed(() => unref(decoration).strike_through);
26
26
  }),
27
27
 
28
28
  getTextDecoration: createCommand(({ editor, commands }) => {
@@ -32,8 +32,8 @@ export const TextDecoration = Mark.create({
32
32
  const attrs = editor.getAttributes(this.name) ?? {};
33
33
 
34
34
  return {
35
- underline: attrs.underline ?? defaultValue.value.underline,
36
- strike_through: attrs.strike_through ?? defaultValue.value.strike_through
35
+ underline: attrs.underline ?? unref(defaultValue).underline,
36
+ strike_through: attrs.strike_through ?? unref(defaultValue).strike_through
37
37
  };
38
38
  });
39
39
  }),
@@ -42,7 +42,7 @@ export const TextDecoration = Mark.create({
42
42
  const preset = commands.getPreset();
43
43
 
44
44
  return computed(() => {
45
- const decoration = preset.value.common.text_decoration;
45
+ const decoration = unref(preset).common.text_decoration;
46
46
 
47
47
  return {
48
48
  underline: decoration.includes('underline'),
@@ -51,7 +51,9 @@ export const TextDecoration = Mark.create({
51
51
  });
52
52
  }),
53
53
 
54
- toggleUnderline: createCommand(({ commands }) => {
54
+ toggleUnderline: createCommand(({ commands, editor }) => {
55
+ if (editor.isActive('link')) return;
56
+
55
57
  commands.toggleTextDecoration('underline');
56
58
  }),
57
59
 
@@ -60,7 +62,7 @@ export const TextDecoration = Mark.create({
60
62
  }),
61
63
 
62
64
  toggleTextDecoration: createCommand(({ commands }, name) => {
63
- const isEnabled = commands.getTextDecoration().value[name];
65
+ const isEnabled = unref(commands.getTextDecoration())[name];
64
66
 
65
67
  isEnabled ? commands.removeTextDecoration(name) : commands.applyTextDecoration(name);
66
68
  }),
@@ -71,7 +73,7 @@ export const TextDecoration = Mark.create({
71
73
 
72
74
  removeTextDecoration: createCommand(({ commands }, name) => {
73
75
  const mark = {
74
- ...commands.getTextDecoration().value,
76
+ ...unref(commands.getTextDecoration()),
75
77
  [name]: false
76
78
  };
77
79
  const isRemoveMark = !mark.underline && !mark.strike_through;
@@ -86,16 +88,47 @@ export const TextDecoration = Mark.create({
86
88
  'Mod-U': createKeyboardShortcut('toggleUnderline')
87
89
  }),
88
90
 
89
- parseHTML: () => [
90
- {
91
- style: 'text-decoration-line',
91
+ parseHTML() {
92
+ const getAttrs = (value) => {
93
+ const underline = value.includes('underline');
94
+ const strike_through = value.includes('line-through');
92
95
 
93
- getAttrs: (value) => ({
94
- underline: value.includes('underline'),
95
- strike_through: value.includes('line-through')
96
- })
97
- }
98
- ],
96
+ if (!underline && !strike_through) {
97
+ return false;
98
+ }
99
+
100
+ return { underline, strike_through };
101
+ };
102
+
103
+ return [
104
+ {
105
+ style: '--zw-text-decoration',
106
+ getAttrs
107
+ },
108
+ {
109
+ style: 'text-decoration-line',
110
+ getAttrs
111
+ },
112
+ {
113
+ style: 'text-decoration',
114
+ getAttrs
115
+ },
116
+ {
117
+ tag: 's',
118
+ attrs: {
119
+ underline: false,
120
+ strike_through: true
121
+ }
122
+ },
123
+ {
124
+ tag: 'u',
125
+ attrs: {
126
+ underline: true,
127
+ strike_through: false
128
+ }
129
+ }
130
+ ];
131
+ },
99
132
 
100
133
  renderHTML({ HTMLAttributes: attrs }) {
101
134
  const decorations = [];
@@ -1,12 +1,11 @@
1
1
  import { Editor, Extension } from '@tiptap/vue-2';
2
- import { ref } from '@vue/composition-api';
3
- import { NodeFactory } from '../../__tests__/utils';
2
+ import { ref } from 'vue';
4
3
  import { createCommand } from '../../utils';
5
- import { CORE_EXTENSIONS } from '../core';
6
4
  import { Alignment } from '../Alignment';
7
5
  import { DeviceManager } from '../DeviceManager';
8
6
  import { Alignments } from '../../enums';
9
- import { ContentNormalizer } from '../../services';
7
+ import { ContentNormalizer, NodeFactory } from '../../services';
8
+ import { buildCoreExtensions } from '../core';
10
9
 
11
10
  const MockStylePreset = Extension.create({
12
11
  name: 'style_preset',
@@ -23,13 +22,11 @@ const MockStylePreset = Extension.create({
23
22
  });
24
23
 
25
24
  function createEditor({ content }) {
26
- const normalizer = new ContentNormalizer();
27
-
28
25
  return new Editor({
29
- content: normalizer.normalize(content),
30
- extensions: CORE_EXTENSIONS.concat(
26
+ content: ContentNormalizer.normalize(content),
27
+ extensions: buildCoreExtensions().concat(
31
28
  MockStylePreset,
32
- DeviceManager.configure({ deviceRef: ref('desktop') }),
29
+ DeviceManager.configure({ device: ref('desktop') }),
33
30
  Alignment
34
31
  )
35
32
  });
@@ -118,6 +115,14 @@ describe('parsing html', () => {
118
115
  expect(editor.getJSON()).toMatchSnapshot();
119
116
  });
120
117
 
118
+ test('should get alignment from rendered view', () => {
119
+ const editor = createEditor({
120
+ content: '<p style="--zw-text-align-mobile:center;--zw-text-align-desktop:right">test</p>'
121
+ });
122
+
123
+ expect(editor.getJSON()).toMatchSnapshot();
124
+ });
125
+
121
126
  test('should set null if no alignment', () => {
122
127
  const editor = createEditor({
123
128
  content: '<p>test</p>'
@@ -1,10 +1,9 @@
1
1
  import { Editor, Extension } from '@tiptap/vue-2';
2
- import { ref } from '@vue/composition-api';
3
- import { NodeFactory } from '../../__tests__/utils';
2
+ import { ref } from 'vue';
4
3
  import { createCommand } from '../../utils';
5
- import { CORE_EXTENSIONS } from '../core';
6
4
  import { BackgroundColor } from '../BackgroundColor';
7
- import { ContentNormalizer } from '../../services';
5
+ import { ContentNormalizer, NodeFactory } from '../../services';
6
+ import { buildCoreExtensions } from '../core';
8
7
 
9
8
  const MockStylePreset = Extension.create({
10
9
  name: 'style_preset',
@@ -19,11 +18,9 @@ const MockStylePreset = Extension.create({
19
18
  });
20
19
 
21
20
  function createEditor({ content }) {
22
- const normalizer = new ContentNormalizer();
23
-
24
21
  return new Editor({
25
- content: normalizer.normalize(content),
26
- extensions: CORE_EXTENSIONS.concat(MockStylePreset, BackgroundColor)
22
+ content: ContentNormalizer.normalize(content),
23
+ extensions: buildCoreExtensions().concat(MockStylePreset, BackgroundColor)
27
24
  });
28
25
  }
29
26
 
@@ -94,6 +91,14 @@ describe('parsing html', () => {
94
91
  expect(editor.getJSON()).toMatchSnapshot();
95
92
  });
96
93
 
94
+ test('should get value from rendered view', () => {
95
+ const editor = createEditor({
96
+ content: '<p><span style="--zw-background-color: red">lorem</span> ipsum</p>'
97
+ });
98
+
99
+ expect(editor.getJSON()).toMatchSnapshot();
100
+ });
101
+
97
102
  test('should merge paragraph and text settings', () => {
98
103
  const editor = createEditor({
99
104
  content: '<p style="background-color: red"><span style="background-color: #000">lorem</span> ipsum</p>'