@zipify/wysiwyg 1.0.0-dev.43 → 1.0.0-dev.46

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.
@@ -122,6 +122,9 @@ export default {
122
122
  </script>
123
123
 
124
124
  <style>
125
+ @import url("zipify-colorpicker/dist/zipify-colorpicker.css");
126
+ @import url("simplebar/dist/simplebar.css");
127
+
125
128
  body {
126
129
  padding: 50px 20px;
127
130
  max-width: 1200px;
package/jest.config.js CHANGED
@@ -3,8 +3,10 @@ module.exports = {
3
3
  moduleFileExtensions: ['js', 'json', 'vue', 'scss'],
4
4
  transform: {
5
5
  '^.+\\.js$': 'babel-jest',
6
- '^.+\\.vue$': '@vue/vue2-jest'
6
+ '^.+\\.vue$': '@vue/vue2-jest',
7
+ 'node_modules/zipify-colorpicker.+': 'babel-jest'
7
8
  },
9
+ transformIgnorePatterns: ['node_modules/(?!zipify-colorpicker)/'],
8
10
  moduleNameMapper: {
9
11
  '^.+\\.svg$': '<rootDir>/lib/__mocks__/svgMock.js'
10
12
  },
package/lib/Wysiwyg.vue CHANGED
@@ -12,7 +12,7 @@
12
12
 
13
13
  <script>
14
14
  import { EditorContent } from '@tiptap/vue-2';
15
- import { provide, toRef, ref } from 'vue';
15
+ import { provide, toRef, ref, computed } from 'vue';
16
16
  import { Toolbar } from './components';
17
17
  import { useToolbar, useEditor } from './composables';
18
18
  import { buildExtensions } from './extensions';
@@ -116,6 +116,7 @@ export default {
116
116
  const fonts = props.fonts.map((font) => new Font(font));
117
117
  const toolbarRef = ref(null);
118
118
  const wysiwygRef = ref(null);
119
+ const wrapperRef = computed(() => wysiwygRef.value?.$el || document.body);
119
120
 
120
121
  const toolbar = useToolbar({
121
122
  wrapperRef: wysiwygRef,
@@ -144,7 +145,8 @@ export default {
144
145
  basePresetClass: props.basePresetClass,
145
146
  baseListClass: props.baseListClass,
146
147
  deviceRef: toRef(props, 'device'),
147
- pageBlocksRef: pageBlocks
148
+ pageBlocksRef: pageBlocks,
149
+ wrapperRef
148
150
  })
149
151
  });
150
152
 
@@ -31,8 +31,6 @@ export default {
31
31
  </script>
32
32
 
33
33
  <style scoped>
34
- @import url("simplebar/dist/simplebar.css");
35
-
36
34
  .zw-scroll-view::v-deep .simplebar-placeholder {
37
35
  display: none;
38
36
  }
@@ -17,10 +17,9 @@ export function useToolbar({ wrapperRef, offsets, isActiveRef }) {
17
17
  name: 'preventOverflow',
18
18
  options: {
19
19
  altAxis: true,
20
- padding: 8
20
+ padding: 2
21
21
  }
22
22
  },
23
-
24
23
  {
25
24
  name: 'flip',
26
25
  enabled: false
@@ -2,5 +2,14 @@ export const Alignments = Object.freeze({
2
2
  LEFT: 'left',
3
3
  CENTER: 'center',
4
4
  RIGHT: 'right',
5
- JUSTIFY: 'justify'
5
+ JUSTIFY: 'justify',
6
+
7
+ get values() {
8
+ return [
9
+ this.LEFT,
10
+ this.CENTER,
11
+ this.RIGHT,
12
+ this.JUSTIFY
13
+ ];
14
+ }
6
15
  });
@@ -1,6 +1,6 @@
1
1
  import { Extension } from '@tiptap/vue-2';
2
2
  import { computed } from 'vue';
3
- import { createCommand, createKeyboardShortcut, renderInlineSetting } from '../utils';
3
+ import { convertAlignment, createCommand, createKeyboardShortcut, renderInlineSetting } from '../utils';
4
4
  import { Alignments, NodeTypes, TextSettings } from '../enums';
5
5
 
6
6
  const DEFAULTS = {
@@ -20,11 +20,13 @@ export const Alignment = Extension.create({
20
20
  isRequired: false,
21
21
 
22
22
  parseHTML({ style }) {
23
- if (style.textAlign) {
23
+ const textAlign = convertAlignment(style.textAlign);
24
+
25
+ if (textAlign) {
24
26
  return {
25
- desktop: style.textAlign,
26
- tablet: style.textAlign,
27
- mobile: style.textAlign
27
+ desktop: textAlign,
28
+ tablet: textAlign,
29
+ mobile: textAlign
28
30
  };
29
31
  }
30
32
 
@@ -1,6 +1,6 @@
1
1
  import { Mark } from '@tiptap/vue-2';
2
2
  import { computed } from 'vue';
3
- import { createCommand, createKeyboardShortcut, renderMark } from '../utils';
3
+ import { convertFontSize, createCommand, createKeyboardShortcut, renderMark } from '../utils';
4
4
  import { TextSettings } from '../enums';
5
5
 
6
6
  export const FontSize = Mark.create({
@@ -63,7 +63,13 @@ export const FontSize = Mark.create({
63
63
  }),
64
64
 
65
65
  parseHTML() {
66
- const parseSize = (value) => value ? String(parseInt(value)) : null;
66
+ const parseSize = (value) => {
67
+ if (!value) return null;
68
+
69
+ const converted = convertFontSize(value, this.options.wrapperRef.value);
70
+
71
+ return String(converted);
72
+ };
67
73
 
68
74
  return [
69
75
  {
@@ -1,8 +1,7 @@
1
1
  import { Extension } from '@tiptap/vue-2';
2
2
  import { computed } from 'vue';
3
- import { createCommand, renderInlineSetting } from '../utils';
3
+ import { createCommand, renderInlineSetting, convertLineHeight } from '../utils';
4
4
  import { NodeTypes, TextSettings } from '../enums';
5
- import { ContextWindow } from '../services';
6
5
 
7
6
  const DEFAULTS = {
8
7
  mobile: null,
@@ -13,52 +12,46 @@ const DEFAULTS = {
13
12
  export const LineHeight = Extension.create({
14
13
  name: TextSettings.LINE_HEIGHT,
15
14
 
16
- addGlobalAttributes: () => [
17
- {
18
- types: [NodeTypes.PARAGRAPH, NodeTypes.HEADING],
19
- attributes: {
20
- [TextSettings.LINE_HEIGHT]: {
21
- isRequired: false,
15
+ addGlobalAttributes() {
16
+ return [
17
+ {
18
+ types: [NodeTypes.PARAGRAPH, NodeTypes.HEADING],
19
+ attributes: {
20
+ [TextSettings.LINE_HEIGHT]: {
21
+ isRequired: false,
22
22
 
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;
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;
28
28
 
29
- return { mobile, tablet, desktop };
30
- }
31
-
32
- const value = element.style.lineHeight;
29
+ return { mobile, tablet, desktop };
30
+ }
33
31
 
34
- if (!value) return null;
32
+ const value = element.style.lineHeight;
35
33
 
36
- if (!value.includes('px')) {
37
- return { desktop: value, tablet: value, mobile: value };
38
- }
34
+ if (!value) return null;
39
35
 
40
- // element is not connected to window so getComputedStyle is not working on element
41
- const source = element.firstElementChild || element;
42
- const sourceSize = source.style.fontSize;
43
- const fontSize = sourceSize || ContextWindow.getComputedStyle(ContextWindow.body).fontSize;
44
- const relative = (parseFloat(value) / parseFloat(fontSize)).toFixed(2);
36
+ const converted = convertLineHeight(value, element, this.options.wrapperRef.value);
45
37
 
46
- return { desktop: relative, tablet: relative, mobile: relative };
47
- },
38
+ return { desktop: converted, tablet: converted, mobile: converted };
39
+ },
48
40
 
49
- renderHTML(attrs) {
50
- if (!attrs.line_height) return null;
41
+ renderHTML(attrs) {
42
+ if (!attrs.line_height) return null;
51
43
 
52
- return renderInlineSetting({
53
- line_height_mobile: attrs.line_height.mobile,
54
- line_height_tablet: attrs.line_height.tablet,
55
- line_height_desktop: attrs.line_height.desktop
56
- });
44
+ return renderInlineSetting({
45
+ line_height_mobile: attrs.line_height.mobile,
46
+ line_height_tablet: attrs.line_height.tablet,
47
+ line_height_desktop: attrs.line_height.desktop
48
+ });
49
+ }
57
50
  }
58
51
  }
59
52
  }
60
- }
61
- ],
53
+ ];
54
+ },
62
55
 
63
56
  addCommands() {
64
57
  return {
@@ -31,7 +31,8 @@ function createEditor({ content }) {
31
31
  }),
32
32
  FontSize.configure({
33
33
  minSize: 5,
34
- maxSize: 20
34
+ maxSize: 20,
35
+ wrapperRef: ref(document.createElement('div'))
35
36
  })
36
37
  )
37
38
  });
@@ -21,13 +21,17 @@ const MockStylePreset = Extension.create({
21
21
  }
22
22
  });
23
23
 
24
- function createEditor({ content }) {
24
+ function createEditor({ content, wrapperEl }) {
25
25
  return new Editor({
26
26
  content: ContentNormalizer.normalize(content),
27
27
  extensions: buildCoreExtensions().concat(
28
28
  MockStylePreset,
29
- DeviceManager.configure({ device: ref('desktop') }),
30
- LineHeight
29
+ DeviceManager.configure({
30
+ device: ref('desktop')
31
+ }),
32
+ LineHeight.configure({
33
+ wrapperRef: ref(wrapperEl ?? document.createElement('div'))
34
+ })
31
35
  )
32
36
  });
33
37
  }
@@ -124,14 +128,16 @@ describe('parsing html', () => {
124
128
  });
125
129
 
126
130
  test('should get value from text in px units with no font size', () => {
127
- global.document.body.style.fontSize = '20px';
131
+ const wrapperEl = document.createElement('div');
132
+
133
+ wrapperEl.style.fontSize = '20px';
128
134
 
129
135
  const editor = createEditor({
130
- content: '<p style="line-height: 24px">test</p>'
136
+ content: '<p style="line-height: 24px">test</p>',
137
+ wrapperEl
131
138
  });
132
139
 
133
140
  expect(editor.getJSON()).toMatchSnapshot();
134
- global.document.body.style.removeProperty('font-size');
135
141
  });
136
142
 
137
143
  test('should get value from rendered view', () => {
@@ -40,7 +40,8 @@ export function buildExtensions(options) {
40
40
  FontWeight,
41
41
  FontSize.configure({
42
42
  minSize: options.minFontSize,
43
- maxSize: options.maxFontSize
43
+ maxSize: options.maxFontSize,
44
+ wrapperRef: options.wrapperRef
44
45
  }),
45
46
  FontColor,
46
47
  BackgroundColor,
@@ -49,7 +50,9 @@ export function buildExtensions(options) {
49
50
  CaseStyle,
50
51
  Superscript,
51
52
  Alignment,
52
- LineHeight,
53
+ LineHeight.configure({
54
+ wrapperRef: options.wrapperRef
55
+ }),
53
56
  Link.configure({
54
57
  preset: linkPreset,
55
58
  basePresetClass: options.basePresetClass,
@@ -0,0 +1,16 @@
1
+ import { convertAlignment } from '../convertAlignment';
2
+ import { Alignments } from '../../enums';
3
+
4
+ describe('convert alignment', () => {
5
+ test('should try convert non supported value', () => {
6
+ expect(convertAlignment('start')).toBe(Alignments.LEFT);
7
+ });
8
+
9
+ test('should not change supported value', () => {
10
+ expect(convertAlignment('center')).toBe(Alignments.CENTER);
11
+ });
12
+
13
+ test('should return null if cannot convert', () => {
14
+ expect(convertAlignment('test-test')).toBe(null);
15
+ });
16
+ });
@@ -0,0 +1,21 @@
1
+ import { convertFontSize } from '../convertFontSize';
2
+
3
+ describe('convert font size', () => {
4
+ const createWrapper = ({ fontSize }) => {
5
+ const wrapperEl = document.createElement('div');
6
+
7
+ wrapperEl.style.fontSize = `${fontSize}px`;
8
+
9
+ return wrapperEl;
10
+ };
11
+
12
+ test('should format px values', () => {
13
+ expect(convertFontSize('20px')).toBe(20);
14
+ });
15
+
16
+ test('should parse em value', () => {
17
+ const wrapperEl = createWrapper({ fontSize: 24 });
18
+
19
+ expect(convertFontSize('1.5em', wrapperEl)).toBe(36);
20
+ });
21
+ });
@@ -0,0 +1,21 @@
1
+ import { convertLineHeight } from '../convertLineHeight';
2
+
3
+ describe('convert line height', () => {
4
+ const createWrapper = ({ fontSize }) => {
5
+ const wrapperEl = document.createElement('div');
6
+
7
+ wrapperEl.style.fontSize = `${fontSize}px`;
8
+
9
+ return wrapperEl;
10
+ };
11
+
12
+ test('should allow relative values', () => {
13
+ expect(convertLineHeight('1.2')).toBe('1.2');
14
+ });
15
+
16
+ test('should convert px to relative', () => {
17
+ const wrapperEl = createWrapper({ fontSize: 20 });
18
+
19
+ expect(convertLineHeight('24px', wrapperEl)).toBe('1.20');
20
+ });
21
+ });
@@ -0,0 +1,12 @@
1
+ import { Alignments } from '../enums';
2
+
3
+ const MAPPING = {
4
+ start: Alignments.LEFT,
5
+ end: Alignments.RIGHT
6
+ };
7
+
8
+ export function convertAlignment(alignment) {
9
+ const mapped = MAPPING[alignment] || alignment;
10
+
11
+ return Alignments.values.includes(mapped) ? mapped : null;
12
+ }
@@ -0,0 +1,8 @@
1
+ export function convertFontSize(value, wrapperEl) {
2
+ if (!value.includes('em')) return parseInt(value);
3
+
4
+ const containerValue = window.getComputedStyle(wrapperEl).fontSize;
5
+ const size = parseFloat(value) * parseFloat(containerValue);
6
+
7
+ return Math.round(size);
8
+ }
@@ -0,0 +1,17 @@
1
+ import { convertFontSize } from './convertFontSize';
2
+
3
+ function getFontSize(sourceEl, wrapperEl) {
4
+ const source = sourceEl.firstElementChild || sourceEl;
5
+ const fontSize = source.style.fontSize;
6
+
7
+ return fontSize || window.getComputedStyle(wrapperEl).fontSize;
8
+ }
9
+
10
+ export function convertLineHeight(value, sourceEl, wrapperEl) {
11
+ if (!value.includes('px')) return value;
12
+
13
+ const rawFontSize = getFontSize(sourceEl, wrapperEl);
14
+ const fontSize = convertFontSize(rawFontSize, wrapperEl);
15
+
16
+ return (parseInt(value) / fontSize).toFixed(2);
17
+ }
@@ -3,4 +3,7 @@ export { renderInlineSetting, renderMark } from './renderInlineSetting';
3
3
  export { capitalize } from './capitalize';
4
4
  export { createKeyboardShortcut } from './createKeyboardShortcut';
5
5
  export { convertColor } from './convertColor';
6
+ export { convertLineHeight } from './convertLineHeight';
7
+ export { convertFontSize } from './convertFontSize';
8
+ export { convertAlignment } from './convertAlignment';
6
9
  export { importIcon } from './importIcon';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zipify/wysiwyg",
3
- "version": "1.0.0-dev.43",
3
+ "version": "1.0.0-dev.46",
4
4
  "description": "Zipify modification of TipTap text editor",
5
5
  "main": "dist/wysiwyg.mjs",
6
6
  "repository": {
@@ -15,13 +15,13 @@
15
15
  },
16
16
  "scripts": {
17
17
  "lib:build": "vite build --config ./config/vite/lib.config.js",
18
+ "lib:release": "export $(cat ./.env | xargs) && npm run lib:build && release-it",
18
19
  "example:start": "NODE_ENV=development vite serve --config ./config/vite/example.config.js",
19
20
  "example:build": "NODE_ENV=production vite build --config ./config/vite/example.config.js",
20
21
  "test:unit": "jest .",
21
22
  "optimize-svg": "svgo --config ./config/svgo.js",
22
23
  "gzip": "gzipper compress",
23
- "prepare": "husky install",
24
- "release": "export $(cat ./.env | xargs) && npm run lib:build && release-it"
24
+ "prepare": "husky install"
25
25
  },
26
26
  "dependencies": {
27
27
  "@popperjs/core": "^2.11.5",
@@ -40,7 +40,7 @@
40
40
  },
41
41
  "peerDependencies": {
42
42
  "vue": "2.7.*",
43
- "zipify-colorpicker": "*"
43
+ "zipify-colorpicker": "2.*"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@babel/core": "^7.18.9",
@@ -67,6 +67,6 @@
67
67
  "vite-plugin-vue2": "^2.0.2",
68
68
  "vue": "^2.7.8",
69
69
  "vue-template-compiler": "^2.7.8",
70
- "zipify-colorpicker": "^1.0.28"
70
+ "zipify-colorpicker": "2.0.0-dev.1"
71
71
  }
72
72
  }