@zipify/wysiwyg 3.1.0-2 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.js +17 -235
- package/.github/actions/setup/action.yaml +1 -1
- package/README.md +2 -0
- package/config/build/cli.config.js +6 -6
- package/config/build/lib.config.js +5 -3
- package/config/svgo.js +6 -3
- package/dist/cli.js +5 -4
- package/dist/wysiwyg.css +18 -18
- package/dist/wysiwyg.mjs +12496 -11732
- package/example/tooltip/Tooltip.js +92 -69
- package/example/tooltip/modifiers/TooltipCloseOnScrollModifier.js +2 -5
- package/example/tooltip/tooltip.css +8 -31
- package/lib/Wysiwyg.vue +3 -0
- package/lib/cli/commands/ToJsonCommand.js +6 -6
- package/lib/components/base/__tests__/Button.test.js +1 -1
- package/lib/components/base/composables/__tests__/useDeselectionLock.test.js +2 -2
- package/lib/components/base/composables/__tests__/useElementRef.test.js +1 -1
- package/lib/components/base/composables/__tests__/useModalToggler.test.js +0 -2
- package/lib/components/base/composables/__tests__/useValidator.test.js +2 -2
- package/lib/components/base/composables/useModalToggler.js +30 -24
- package/lib/components/toolbar/Toolbar.vue +1 -1
- package/lib/components/toolbar/base/__tests__/ToolbarDivider.test.js +1 -1
- package/lib/components/toolbar/controls/StylePresetControl.vue +1 -1
- package/lib/components/toolbar/controls/__tests__/LineHeightControl.test.js +0 -2
- package/lib/components/toolbar/controls/composables/__tests__/useRecentFonts.test.js +1 -1
- package/lib/components/toolbar/controls/link/composables/__tests__/useLink.test.js +2 -2
- package/lib/composables/useToolbar.js +24 -19
- package/lib/extensions/FontSize.js +1 -2
- package/lib/extensions/Link.js +2 -0
- package/lib/extensions/__tests__/BackgroundColor.test.js +2 -2
- package/lib/extensions/__tests__/FontColor.test.js +3 -3
- package/lib/extensions/__tests__/FontFamily.test.js +3 -3
- package/lib/extensions/__tests__/FontSize.test.js +3 -3
- package/lib/extensions/__tests__/FontWeight.test.js +4 -4
- package/lib/extensions/__tests__/LineHeight.test.js +2 -2
- package/lib/extensions/__tests__/Link.test.js +33 -5
- package/lib/extensions/__tests__/__snapshots__/Link.test.js.snap +27 -0
- package/lib/extensions/core/NodeProcessor.js +3 -4
- package/lib/extensions/core/__tests__/NodeProcessor.test.js +6 -8
- package/lib/extensions/core/__tests__/TextProcessor.test.js +1 -1
- package/lib/extensions/core/index.js +0 -2
- package/lib/extensions/core/plugins/PlaceholderPlugin.js +2 -2
- package/lib/extensions/list/List.js +4 -5
- package/lib/extensions/list/ListItem.js +1 -2
- package/lib/extensions/list/__tests__/List.test.js +1 -1
- package/lib/models/Font.js +2 -2
- package/lib/models/__tests__/Font.test.js +3 -9
- package/lib/services/ContentSerializer.js +8 -8
- package/lib/services/HtmlToJsonParser.js +3 -3
- package/lib/services/NodeFactory.js +6 -6
- package/lib/services/StylePresetRenderer.js +11 -11
- package/lib/services/__tests__/JsonSerializer.test.js +1 -1
- package/lib/services/__tests__/Storage.test.js +1 -1
- package/lib/services/__tests__/StylePresetRenderer.test.js +1 -1
- package/lib/services/normalizer/BrowserDomParser.js +2 -2
- package/lib/services/normalizer/ContentNormalizer.js +3 -3
- package/lib/services/normalizer/HtmlNormalizer.js +52 -52
- package/lib/services/normalizer/JsonNormalizer.js +21 -21
- package/lib/utils/__tests__/convertAlignment.test.js +1 -1
- package/lib/utils/__tests__/renderInlineSetting.test.js +2 -2
- package/package.json +50 -48
- package/lib/extensions/core/steps/AddNodeMarkStep.js +0 -66
- package/lib/extensions/core/steps/AttrStep.js +0 -60
- package/lib/extensions/core/steps/RemoveNodeMarkStep.js +0 -56
- package/lib/extensions/core/steps/index.js +0 -3
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import './tooltip.css';
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { popperGenerator, defaultModifiers } from '@popperjs/core/lib/popper-lite';
|
|
4
|
+
import arrow from '@popperjs/core/lib/modifiers/arrow';
|
|
5
|
+
import flip from '@popperjs/core/lib/modifiers/flip';
|
|
6
|
+
import offset from '@popperjs/core/lib/modifiers/offset';
|
|
7
|
+
import preventOverflow from '@popperjs/core/lib/modifiers/preventOverflow';
|
|
4
8
|
import { TooltipCloseOnScrollModifier } from './modifiers';
|
|
5
9
|
|
|
6
10
|
export class Tooltip {
|
|
@@ -14,11 +18,11 @@ export class Tooltip {
|
|
|
14
18
|
static get animationOptions() {
|
|
15
19
|
return {
|
|
16
20
|
enterDuration: 150,
|
|
17
|
-
leaveDuration:
|
|
21
|
+
leaveDuration: 200
|
|
18
22
|
};
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
static get
|
|
25
|
+
static get popperStyles() {
|
|
22
26
|
return {
|
|
23
27
|
willChange: 'transform',
|
|
24
28
|
zIndex: 999999
|
|
@@ -31,17 +35,17 @@ export class Tooltip {
|
|
|
31
35
|
/** @type {string} tooltip's content */
|
|
32
36
|
message = '';
|
|
33
37
|
|
|
34
|
-
/** @type {object} options for
|
|
35
|
-
|
|
38
|
+
/** @type {object} options for Popper.js instance */
|
|
39
|
+
popperOptions = {};
|
|
36
40
|
|
|
37
41
|
/** @type {object} styles for tooltip's wrapper element */
|
|
38
|
-
|
|
42
|
+
popperStyles = {};
|
|
39
43
|
|
|
40
44
|
/** @type {{ enterDuration: number, leaveDuration: number }} tooltip's fade in / fade out durations */
|
|
41
45
|
animationOptions = {};
|
|
42
46
|
|
|
43
|
-
/** @type {
|
|
44
|
-
|
|
47
|
+
/** @type {object | null} created Popper.js instance */
|
|
48
|
+
popperInstance = null;
|
|
45
49
|
|
|
46
50
|
/** @type {{ tooltip: HTMLElement, container: HTMLElement, contentEl: HTMLElement, arrow: HTMLElement }} elements of tooltip */
|
|
47
51
|
elements = {};
|
|
@@ -51,25 +55,25 @@ export class Tooltip {
|
|
|
51
55
|
* @param params {object}
|
|
52
56
|
* @param params.triggerEl {HTMLElement}
|
|
53
57
|
* @param params.message {string}
|
|
54
|
-
* @param [params.
|
|
55
|
-
* @param [params.
|
|
58
|
+
* @param [params.popperOptions] {{ placement: string, size: string }}
|
|
59
|
+
* @param [params.popperStyles] {object}
|
|
56
60
|
* @param [params.animationOptions] {{ enterDuration: number, leaveDuration: number }}
|
|
57
61
|
*/
|
|
58
|
-
constructor({ triggerEl, message,
|
|
62
|
+
constructor({ triggerEl, message, popperOptions, popperStyles, animationOptions }) {
|
|
59
63
|
this.triggerEl = triggerEl;
|
|
60
64
|
this.message = message;
|
|
61
65
|
|
|
62
|
-
this.
|
|
63
|
-
this.
|
|
66
|
+
this.popperOptions = Object.assign({}, Tooltip.defaultOptions, popperOptions);
|
|
67
|
+
this.popperStyles = Object.assign({}, Tooltip.popperStyles, popperStyles);
|
|
64
68
|
this.animationOptions = Object.assign({}, Tooltip.animationOptions, animationOptions);
|
|
65
69
|
|
|
66
70
|
this._isMacOS = window.navigator.userAgent.toLowerCase().includes('mac os');
|
|
67
71
|
|
|
68
|
-
this
|
|
72
|
+
this._initialize();
|
|
69
73
|
}
|
|
70
74
|
|
|
71
|
-
|
|
72
|
-
let tooltip = this
|
|
75
|
+
_initialize() {
|
|
76
|
+
let tooltip = this._createTooltip();
|
|
73
77
|
|
|
74
78
|
this.elements = {
|
|
75
79
|
tooltip,
|
|
@@ -79,15 +83,13 @@ export class Tooltip {
|
|
|
79
83
|
};
|
|
80
84
|
}
|
|
81
85
|
|
|
82
|
-
|
|
86
|
+
_createTooltip() {
|
|
83
87
|
let element = document.createElement('div');
|
|
84
88
|
|
|
85
|
-
Object.keys(this.
|
|
86
|
-
|
|
87
|
-
element.classList.add('zpa-tooltip__wrapper');
|
|
89
|
+
Object.keys(this.popperStyles).forEach((style) => (element.style[style] = this.popperStyles[style]));
|
|
88
90
|
|
|
89
91
|
element.innerHTML = `
|
|
90
|
-
<div class="zpa-tooltip zpa-tooltip--${this.
|
|
92
|
+
<div class="zpa-tooltip zpa-tooltip--${this.popperOptions.size}" data-container>
|
|
91
93
|
<div class="zpa-tooltip__content" data-content></div>
|
|
92
94
|
<div class="zpa-tooltip__arrow" data-arrow></div>
|
|
93
95
|
</div>`;
|
|
@@ -95,20 +97,20 @@ export class Tooltip {
|
|
|
95
97
|
return element;
|
|
96
98
|
}
|
|
97
99
|
|
|
98
|
-
|
|
100
|
+
_renderContent(message) {
|
|
99
101
|
// Do not use .innerHTML, it will break tooltips in Scripts section!
|
|
100
102
|
this.elements.contentEl.textContent = message;
|
|
101
103
|
|
|
102
104
|
this.elements.hotkey?.remove();
|
|
103
|
-
this
|
|
105
|
+
this._renderHotkeyTip();
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
|
|
108
|
+
_renderHotkeyTip() {
|
|
107
109
|
const raw = this.triggerEl.dataset.tooltipHotkey;
|
|
108
110
|
|
|
109
111
|
if (!raw) return;
|
|
110
112
|
|
|
111
|
-
const parts = raw.split(' ').map(this
|
|
113
|
+
const parts = raw.split(' ').map(this._formatHotkeyPart.bind(this));
|
|
112
114
|
const tipEl = document.createElement('span');
|
|
113
115
|
|
|
114
116
|
tipEl.classList.add('zpa-tooltip__hotkey');
|
|
@@ -117,7 +119,7 @@ export class Tooltip {
|
|
|
117
119
|
this.elements.contentEl.append(tipEl);
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
|
|
122
|
+
_formatHotkeyPart(part) {
|
|
121
123
|
switch (part.toLowerCase()) {
|
|
122
124
|
case 'mod':
|
|
123
125
|
return this._isMacOS ? '⌘' : 'Ctrl';
|
|
@@ -129,90 +131,111 @@ export class Tooltip {
|
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
|
|
134
|
+
_getModifiers() {
|
|
133
135
|
return [
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
136
|
+
{
|
|
137
|
+
name: 'arrow',
|
|
138
|
+
options: {
|
|
139
|
+
element: '[data-arrow]'
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
name: 'offset',
|
|
144
|
+
options: {
|
|
145
|
+
offset: [0, 8]
|
|
146
|
+
}
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
name: 'preventOverflow',
|
|
150
|
+
options: {
|
|
151
|
+
padding: {
|
|
152
|
+
top: 4,
|
|
153
|
+
bottom: 4,
|
|
154
|
+
left: 8,
|
|
155
|
+
right: 8
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
name: 'customAttributes',
|
|
161
|
+
enabled: true,
|
|
162
|
+
phase: 'beforeWrite',
|
|
163
|
+
requires: ['computeStyles'],
|
|
164
|
+
fn: ({ state }) => {
|
|
165
|
+
this.elements.arrow.classList.add(`zpa-tooltip__arrow--${state.placement}`);
|
|
166
|
+
state.attributes.popper = {};
|
|
167
|
+
}
|
|
168
|
+
},
|
|
138
169
|
TooltipCloseOnScrollModifier.init({ tooltip: this })
|
|
139
170
|
];
|
|
140
171
|
}
|
|
141
172
|
|
|
142
|
-
|
|
173
|
+
_setTooltipDuration(duration = 0) {
|
|
143
174
|
this.elements.container.style.transitionDuration = `${duration}ms`;
|
|
144
175
|
}
|
|
145
176
|
|
|
146
|
-
|
|
147
|
-
const modifiers = this
|
|
148
|
-
|
|
149
|
-
this.floatingInstance = autoUpdate(this.triggerEl, this.elements.tooltip, async () => {
|
|
150
|
-
const positioning = await computePosition(this.triggerEl, this.elements.tooltip, {
|
|
151
|
-
placement: this.tooltipOptions.placement,
|
|
152
|
-
middleware: [...modifiers]
|
|
153
|
-
});
|
|
154
|
-
|
|
155
|
-
const { x, y, middlewareData, placement } = positioning;
|
|
156
|
-
|
|
157
|
-
if (middlewareData.arrow) this.#renderArrow(placement, middlewareData.arrow);
|
|
177
|
+
_renderPopper() {
|
|
178
|
+
const modifiers = this._getModifiers();
|
|
158
179
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
top: `${y}px`
|
|
162
|
-
});
|
|
180
|
+
const createPopper = popperGenerator({
|
|
181
|
+
defaultModifiers: [...defaultModifiers, arrow, flip, offset, preventOverflow]
|
|
163
182
|
});
|
|
164
183
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
#renderArrow(placement, { x, y }) {
|
|
169
|
-
this.elements.tooltip.classList.add(`zpa-tooltip--${placement}`);
|
|
170
|
-
|
|
171
|
-
Object.assign(this.elements.arrow.style, {
|
|
172
|
-
left: x != null ? `${x}px` : '',
|
|
173
|
-
top: y != null ? `${y}px` : ''
|
|
184
|
+
this.popperInstance = createPopper(this.triggerEl, this.elements.tooltip, {
|
|
185
|
+
placement: this.popperOptions.placement,
|
|
186
|
+
modifiers
|
|
174
187
|
});
|
|
188
|
+
|
|
189
|
+
return this.popperInstance;
|
|
175
190
|
}
|
|
176
191
|
|
|
177
|
-
|
|
192
|
+
_toggle(makeVisible) {
|
|
178
193
|
const { enterDuration, leaveDuration } = this.animationOptions;
|
|
179
194
|
|
|
180
|
-
this
|
|
195
|
+
this._setTooltipDuration(makeVisible ? enterDuration : leaveDuration);
|
|
181
196
|
this.elements.container.classList.toggle('zpa-tooltip--open', makeVisible);
|
|
182
197
|
}
|
|
183
198
|
|
|
184
199
|
open() {
|
|
185
|
-
if (this.
|
|
200
|
+
if (this.popperInstance) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
186
203
|
|
|
187
204
|
document.body.appendChild(this.elements.tooltip);
|
|
188
|
-
this.popperInstance = this
|
|
205
|
+
this.popperInstance = this._renderPopper();
|
|
189
206
|
|
|
190
|
-
this
|
|
191
|
-
this
|
|
207
|
+
this._renderContent(this.message);
|
|
208
|
+
this._toggle(true);
|
|
192
209
|
}
|
|
193
210
|
|
|
194
211
|
close() {
|
|
195
|
-
if (!this.
|
|
212
|
+
if (!this.popperInstance) {
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
196
215
|
|
|
197
|
-
this
|
|
216
|
+
this._toggle(false);
|
|
198
217
|
|
|
199
218
|
return setTimeout(() => {
|
|
200
219
|
this.destroy();
|
|
201
220
|
}, this.animationOptions.leaveDuration);
|
|
202
221
|
}
|
|
203
222
|
|
|
223
|
+
update() {
|
|
224
|
+
this.popperInstance?.update();
|
|
225
|
+
}
|
|
226
|
+
|
|
204
227
|
updateContent(content) {
|
|
205
228
|
this.message = content;
|
|
206
|
-
this
|
|
229
|
+
this._renderContent(this.message);
|
|
230
|
+
this.update();
|
|
207
231
|
}
|
|
208
232
|
|
|
209
233
|
destroy() {
|
|
210
234
|
this.elements.tooltip.remove();
|
|
211
235
|
|
|
212
236
|
if (this.popperInstance) {
|
|
213
|
-
|
|
214
|
-
this.
|
|
215
|
-
this.floatingInstance = null;
|
|
237
|
+
this.popperInstance.destroy();
|
|
238
|
+
this.popperInstance = null;
|
|
216
239
|
}
|
|
217
240
|
}
|
|
218
241
|
}
|
|
@@ -21,7 +21,7 @@ export class TooltipCloseOnScrollModifier {
|
|
|
21
21
|
/**
|
|
22
22
|
* @param {Tooltip} tooltip - tooltip element
|
|
23
23
|
*
|
|
24
|
-
* @return {Partial<Modifier<any, any>>} -
|
|
24
|
+
* @return {Partial<Modifier<any, any>>} - Popper modifier
|
|
25
25
|
* */
|
|
26
26
|
static init({ tooltip }) {
|
|
27
27
|
const modifier = new TooltipCloseOnScrollModifier(tooltip);
|
|
@@ -30,10 +30,7 @@ export class TooltipCloseOnScrollModifier {
|
|
|
30
30
|
name: 'closeOnScroll',
|
|
31
31
|
enabled: true,
|
|
32
32
|
phase: 'main',
|
|
33
|
-
fn: (
|
|
34
|
-
modifier.closeOnScroll();
|
|
35
|
-
return { x, y };
|
|
36
|
-
}
|
|
33
|
+
fn: () => modifier.closeOnScroll()
|
|
37
34
|
};
|
|
38
35
|
}
|
|
39
36
|
|
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
.zpa-tooltip__wrapper {
|
|
2
|
-
position: absolute;
|
|
3
|
-
top: 0;
|
|
4
|
-
left: 0;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
1
|
.zpa-tooltip {
|
|
8
2
|
position: relative;
|
|
9
3
|
background-color: #36404C;
|
|
@@ -37,7 +31,6 @@
|
|
|
37
31
|
}
|
|
38
32
|
|
|
39
33
|
.zpa-tooltip__arrow {
|
|
40
|
-
position: absolute;
|
|
41
34
|
width: 16px;
|
|
42
35
|
height: 16px;
|
|
43
36
|
color: #36404C;
|
|
@@ -50,15 +43,11 @@
|
|
|
50
43
|
border-style: solid;
|
|
51
44
|
}
|
|
52
45
|
|
|
53
|
-
.zpa-
|
|
54
|
-
transform-origin: center bottom;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.zpa-tooltip--top .zpa-tooltip__arrow {
|
|
46
|
+
.zpa-tooltip__arrow--top {
|
|
58
47
|
bottom: 0;
|
|
59
48
|
}
|
|
60
49
|
|
|
61
|
-
.zpa-
|
|
50
|
+
.zpa-tooltip__arrow--top::before {
|
|
62
51
|
bottom: -7px;
|
|
63
52
|
left: 0;
|
|
64
53
|
border-width: 8px 8px 0;
|
|
@@ -66,15 +55,11 @@
|
|
|
66
55
|
transform-origin: center top;
|
|
67
56
|
}
|
|
68
57
|
|
|
69
|
-
.zpa-
|
|
70
|
-
transform-origin: center top;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
.zpa-tooltip--bottom .zpa-tooltip__arrow {
|
|
58
|
+
.zpa-tooltip__arrow--bottom {
|
|
74
59
|
top: 0;
|
|
75
60
|
}
|
|
76
61
|
|
|
77
|
-
.zpa-
|
|
62
|
+
.zpa-tooltip__arrow--bottom::before {
|
|
78
63
|
top: -7px;
|
|
79
64
|
left: 0;
|
|
80
65
|
border-width: 0 8px 8px;
|
|
@@ -82,30 +67,22 @@
|
|
|
82
67
|
transform-origin: center bottom;
|
|
83
68
|
}
|
|
84
69
|
|
|
85
|
-
.zpa-
|
|
86
|
-
transform-origin: center right;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
.zpa-tooltip--left .zpa-tooltip__arrow {
|
|
70
|
+
.zpa-tooltip__arrow--left {
|
|
90
71
|
right: 0;
|
|
91
72
|
}
|
|
92
73
|
|
|
93
|
-
.zpa-
|
|
74
|
+
.zpa-tooltip__arrow--left::before {
|
|
94
75
|
border-width: 8px 0 8px 8px;
|
|
95
76
|
border-left-color: initial;
|
|
96
77
|
right: -7px;
|
|
97
78
|
transform-origin: center left;
|
|
98
79
|
}
|
|
99
80
|
|
|
100
|
-
.zpa-
|
|
101
|
-
transform-origin: center left;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.zpa-tooltip--right .zpa-tooltip__arrow {
|
|
81
|
+
.zpa-tooltip__arrow--right {
|
|
105
82
|
left: 0;
|
|
106
83
|
}
|
|
107
84
|
|
|
108
|
-
.zpa-
|
|
85
|
+
.zpa-tooltip__arrow--right::before {
|
|
109
86
|
left: -7px;
|
|
110
87
|
border-width: 8px 8px 8px 0;
|
|
111
88
|
border-right-color: initial;
|
package/lib/Wysiwyg.vue
CHANGED
|
@@ -155,9 +155,11 @@ export default {
|
|
|
155
155
|
isActiveRef: isToolbarActiveRef,
|
|
156
156
|
offsets: props.toolbarOffsets
|
|
157
157
|
});
|
|
158
|
+
const updateToolbar = () => toolbar.update();
|
|
158
159
|
|
|
159
160
|
function onChange(content) {
|
|
160
161
|
emit('input', content);
|
|
162
|
+
updateToolbar();
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
const pageBlocks = toRef(props, 'pageBlocks');
|
|
@@ -206,6 +208,7 @@ export default {
|
|
|
206
208
|
toolbarRef,
|
|
207
209
|
wysiwygRef,
|
|
208
210
|
toolbar,
|
|
211
|
+
updateToolbar,
|
|
209
212
|
getContent,
|
|
210
213
|
getContentCustomization
|
|
211
214
|
};
|
|
@@ -32,14 +32,14 @@ export class ToJsonCommand extends Command {
|
|
|
32
32
|
nodeDomParser: new NodeDomParser()
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
const jsonList = htmlList.map((html) => serializer.toJSON(this
|
|
35
|
+
const jsonList = htmlList.map((html) => serializer.toJSON(this._formatInputHtml(html)));
|
|
36
36
|
const content = jsonList.length === 1 ? jsonList[0] : jsonList;
|
|
37
|
-
const json = this
|
|
37
|
+
const json = this._stringifyContent(content);
|
|
38
38
|
|
|
39
|
-
this.output(format === 'rb' ? this
|
|
39
|
+
this.output(format === 'rb' ? this._formatOutputRb(json) : json);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
_formatInputHtml(html) {
|
|
43
43
|
return html
|
|
44
44
|
.replace(/\\(["'])/g, '$1')
|
|
45
45
|
.replace(/rgba\(\d{1,3}, ?\d{1,3}, ?\d{1,3}, (\d{1,2}%)\)/g, (substring, alpha) => {
|
|
@@ -47,13 +47,13 @@ export class ToJsonCommand extends Command {
|
|
|
47
47
|
});
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
50
|
+
_stringifyContent(content) {
|
|
51
51
|
const skipNullValue = (_, value) => value === null ? undefined : value;
|
|
52
52
|
|
|
53
53
|
return JSON.stringify(content, skipNullValue, 2);
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
_formatOutputRb(json) {
|
|
57
57
|
return json
|
|
58
58
|
.replace(/\\"/g, '"')
|
|
59
59
|
.replace(/font-family: ?'(.+)'/g, 'font-family: "$1"')
|
|
@@ -42,7 +42,7 @@ describe('rendering', () => {
|
|
|
42
42
|
expect(wrapper.classes('zw-button--icon')).toBeTruthy();
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
test('should render
|
|
45
|
+
test('should render iconless style', () => {
|
|
46
46
|
const wrapper = createComponent({ icon: false });
|
|
47
47
|
|
|
48
48
|
expect(wrapper.classes('zw-button--icon')).toBeFalsy();
|
|
@@ -33,8 +33,8 @@ describe('prevent deselection', () => {
|
|
|
33
33
|
function click(el, { target } = {}) {
|
|
34
34
|
const event = new MouseEvent('mousedown');
|
|
35
35
|
|
|
36
|
-
event
|
|
37
|
-
event
|
|
36
|
+
jest.spyOn(event, 'preventDefault').mockImplementation();
|
|
37
|
+
jest.spyOn(event, 'stopPropagation').mockImplementation();
|
|
38
38
|
setReadonlyProperty(event, 'target', target || { tagName: 'DIV' });
|
|
39
39
|
|
|
40
40
|
el.dispatchEvent(event);
|
|
@@ -10,7 +10,7 @@ describe('resolve element from ref', () => {
|
|
|
10
10
|
test('should return null if no element', () => {
|
|
11
11
|
const elementRef = useElementRef(ref(null));
|
|
12
12
|
|
|
13
|
-
expect(elementRef.value).
|
|
13
|
+
expect(elementRef.value).toBeNull();
|
|
14
14
|
});
|
|
15
15
|
|
|
16
16
|
test('should return element if dom ref', () => {
|
|
@@ -4,8 +4,6 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { useModalToggler } from '../useModalToggler';
|
|
5
5
|
import { useElementRef } from '../useElementRef';
|
|
6
6
|
|
|
7
|
-
jest.mock('@floating-ui/dom');
|
|
8
|
-
|
|
9
7
|
const createEditor = () => ({
|
|
10
8
|
commands: {
|
|
11
9
|
storeSelection: jest.fn(),
|
|
@@ -24,7 +24,7 @@ describe('validation', () => {
|
|
|
24
24
|
|
|
25
25
|
validator.validate();
|
|
26
26
|
|
|
27
|
-
expect(validator.error.value).
|
|
27
|
+
expect(validator.error.value).toBeNull();
|
|
28
28
|
});
|
|
29
29
|
|
|
30
30
|
test('should reset error', () => {
|
|
@@ -39,6 +39,6 @@ describe('validation', () => {
|
|
|
39
39
|
expect(validator.error.value).toBe('Can\'t be empty');
|
|
40
40
|
|
|
41
41
|
validator.reset();
|
|
42
|
-
expect(validator.error.value).
|
|
42
|
+
expect(validator.error.value).toBeNull();
|
|
43
43
|
});
|
|
44
44
|
});
|
|
@@ -1,55 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { createPopper } from '@popperjs/core';
|
|
2
|
+
import { inject, nextTick, ref, onUnmounted } from 'vue';
|
|
3
3
|
import { InjectionTokens } from '../../../injectionTokens';
|
|
4
4
|
import { useElementRef } from './useElementRef';
|
|
5
5
|
|
|
6
6
|
export function useModalToggler({ onBeforeOpened, onClosed, wrapperRef, modalRef } = {}) {
|
|
7
7
|
const editor = inject(InjectionTokens.EDITOR);
|
|
8
8
|
const isOpened = ref(false);
|
|
9
|
-
let
|
|
9
|
+
let popper;
|
|
10
10
|
|
|
11
|
-
function
|
|
11
|
+
function initPopper() {
|
|
12
12
|
const wrapperEl = useElementRef(wrapperRef);
|
|
13
13
|
const modalEl = useElementRef(modalRef);
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
15
|
+
popper = createPopper(wrapperEl.value, modalEl.value, {
|
|
16
|
+
placement: 'bottom',
|
|
17
|
+
strategy: 'fixed',
|
|
18
|
+
modifiers: [
|
|
19
|
+
{
|
|
20
|
+
name: 'offset',
|
|
21
|
+
options: {
|
|
22
|
+
offset: [0, 4]
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
name: 'preventOverflow',
|
|
27
|
+
options: {
|
|
28
|
+
padding: 16
|
|
29
|
+
}
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
name: 'flip',
|
|
33
|
+
enabled: false
|
|
34
|
+
}
|
|
35
|
+
]
|
|
31
36
|
});
|
|
32
37
|
}
|
|
33
38
|
|
|
34
39
|
async function open() {
|
|
35
|
-
if (isOpened.value) return;
|
|
36
|
-
|
|
37
40
|
onBeforeOpened?.();
|
|
38
41
|
editor.commands.storeSelection();
|
|
39
42
|
isOpened.value = true;
|
|
40
43
|
|
|
41
44
|
await nextTick();
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
initPopper();
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
function close() {
|
|
47
50
|
isOpened.value = false;
|
|
48
|
-
floatingInstance?.();
|
|
49
51
|
editor.commands.restoreSelection();
|
|
50
52
|
onClosed?.();
|
|
51
53
|
}
|
|
52
54
|
|
|
55
|
+
onUnmounted(() => {
|
|
56
|
+
popper?.destroy();
|
|
57
|
+
});
|
|
58
|
+
|
|
53
59
|
const toggle = (toOpen) => toOpen ? open() : close();
|
|
54
60
|
|
|
55
61
|
return { isOpened, open, close, toggle };
|
|
@@ -18,7 +18,7 @@ describe('rendering', () => {
|
|
|
18
18
|
});
|
|
19
19
|
|
|
20
20
|
|
|
21
|
-
test('should render
|
|
21
|
+
test('should render horizontal divider', () => {
|
|
22
22
|
const wrapper = createComponent({ isHorizontal: true });
|
|
23
23
|
|
|
24
24
|
expect(wrapper.classes('zw-toolbar__divider--horizontal')).toBeTruthy();
|
|
@@ -73,7 +73,7 @@ export default {
|
|
|
73
73
|
.run();
|
|
74
74
|
};
|
|
75
75
|
|
|
76
|
-
const tooltip = computed(() => isCustomized.value ? 'Reset Styles to
|
|
76
|
+
const tooltip = computed(() => isCustomized.value ? 'Reset Styles to Page Styles' : '');
|
|
77
77
|
|
|
78
78
|
const removeCustomization = () => editor.chain().focus().removePresetCustomization().run();
|
|
79
79
|
|
|
@@ -4,8 +4,6 @@ import { InjectionTokens } from '../../../../injectionTokens';
|
|
|
4
4
|
import { Button, Modal, NumberField, Range } from '../../../base';
|
|
5
5
|
import LineHeightControl from '../LineHeightControl';
|
|
6
6
|
|
|
7
|
-
jest.mock('@floating-ui/dom');
|
|
8
|
-
|
|
9
7
|
const createEditor = ({ height } = {}) => {
|
|
10
8
|
const heightRef = ref(height ?? '1.2');
|
|
11
9
|
|
|
@@ -57,7 +57,7 @@ describe('list of fonts', () => {
|
|
|
57
57
|
expect(recentFonts.fonts.value).toEqual(['Lato', 'Roboto', 'Source Sans']);
|
|
58
58
|
});
|
|
59
59
|
|
|
60
|
-
test('should move up font in list', () => {
|
|
60
|
+
test('should move up font in list new font', () => {
|
|
61
61
|
const recentFonts = createWrapper({
|
|
62
62
|
initial: ['Roboto', 'Source Sans', 'Times New Roman']
|
|
63
63
|
});
|
|
@@ -97,7 +97,7 @@ describe('actions with link', () => {
|
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
|
|
100
|
-
test('should apply link target', () => {
|
|
100
|
+
test('should apply link target to new window', () => {
|
|
101
101
|
const link = useComposable();
|
|
102
102
|
|
|
103
103
|
link.updateTarget(false);
|
|
@@ -105,7 +105,7 @@ describe('actions with link', () => {
|
|
|
105
105
|
expect(link.linkData.value.target).toBe(LinkTargets.SELF);
|
|
106
106
|
});
|
|
107
107
|
|
|
108
|
-
test('should apply link target', () => {
|
|
108
|
+
test('should apply link target to current window', () => {
|
|
109
109
|
const link = useComposable();
|
|
110
110
|
|
|
111
111
|
link.updateTarget(true);
|