@zipify/wysiwyg 1.1.1 → 1.2.1-1
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/.github/actions/lint-css/action.yaml +1 -3
- package/.release-it.json +2 -1
- package/dist/cli.js +3 -3
- package/dist/wysiwyg.css +24 -25
- package/dist/wysiwyg.mjs +641 -618
- package/jest.config.js +3 -0
- package/lib/components/base/Modal.vue +21 -2
- package/lib/components/base/__tests__/Modal.test.js +1 -0
- package/lib/components/toolbar/controls/link/LinkControl.vue +22 -10
- package/lib/components/toolbar/controls/link/LinkControlHeader.vue +3 -3
- package/lib/components/toolbar/controls/link/__tests__/LinkControl.test.js +8 -8
- package/lib/components/toolbar/controls/link/__tests__/LinkControlHeader.test.js +1 -1
- package/lib/components/toolbar/controls/link/composables/useLink.js +10 -6
- package/lib/composables/__tests__/__snapshots__/useEditor.test.js.snap +1 -1
- package/lib/composables/useEditor.js +4 -3
- package/lib/enums/TextSettings.js +2 -0
- package/lib/extensions/FontStyle.js +2 -2
- package/lib/extensions/FontWeight.js +2 -0
- package/lib/extensions/Link.js +13 -15
- package/lib/extensions/StylePreset.js +33 -3
- package/lib/extensions/TextDecoration.js +6 -12
- package/lib/extensions/__tests__/FontFamily.test.js +7 -6
- package/lib/extensions/__tests__/FontWeight.test.js +19 -10
- package/lib/extensions/__tests__/StylePreset.test.js +52 -2
- package/lib/extensions/__tests__/TextDecoration.test.js +11 -40
- package/lib/extensions/__tests__/__snapshots__/Alignment.test.js.snap +2 -2
- package/lib/extensions/__tests__/__snapshots__/BackgroundColor.test.js.snap +1 -1
- package/lib/extensions/__tests__/__snapshots__/FontColor.test.js.snap +1 -1
- package/lib/extensions/__tests__/__snapshots__/FontFamily.test.js.snap +19 -1
- package/lib/extensions/__tests__/__snapshots__/FontSize.test.js.snap +2 -2
- package/lib/extensions/__tests__/__snapshots__/FontStyle.test.js.snap +17 -1
- package/lib/extensions/__tests__/__snapshots__/FontWeight.test.js.snap +26 -1
- package/lib/extensions/__tests__/__snapshots__/LineHeight.test.js.snap +2 -2
- package/lib/extensions/__tests__/__snapshots__/Margin.test.js.snap +2 -2
- package/lib/extensions/__tests__/__snapshots__/StylePreset.test.js.snap +22 -2
- package/lib/extensions/__tests__/__snapshots__/TextDecoration.test.js.snap +3 -46
- package/package.json +22 -22
- package/lib/components/toolbar/controls/link/LinkControlApply.vue +0 -35
- package/node_modules_lambda/acorn-globals/node_modules/.bin/acorn +0 -4
- package/node_modules_lambda/acorn-globals/node_modules/acorn/CHANGELOG.md +0 -620
- package/node_modules_lambda/acorn-globals/node_modules/acorn/LICENSE +0 -21
- package/node_modules_lambda/acorn-globals/node_modules/acorn/README.md +0 -269
- package/node_modules_lambda/acorn-globals/node_modules/acorn/bin/acorn +0 -4
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/acorn.d.ts +0 -209
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/acorn.js +0 -5186
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/acorn.js.map +0 -1
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/acorn.mjs +0 -5155
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/acorn.mjs.d.ts +0 -2
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/acorn.mjs.map +0 -1
- package/node_modules_lambda/acorn-globals/node_modules/acorn/dist/bin.js +0 -64
- package/node_modules_lambda/acorn-globals/node_modules/acorn/package.json +0 -35
- package/node_modules_lambda/cssstyle/node_modules/cssom/LICENSE.txt +0 -20
- package/node_modules_lambda/cssstyle/node_modules/cssom/README.mdown +0 -67
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSDocumentRule.js +0 -39
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSFontFaceRule.js +0 -36
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSHostRule.js +0 -37
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSImportRule.js +0 -132
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSKeyframeRule.js +0 -37
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSKeyframesRule.js +0 -39
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSMediaRule.js +0 -41
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSOM.js +0 -3
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSRule.js +0 -43
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSStyleDeclaration.js +0 -148
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSStyleRule.js +0 -190
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSStyleSheet.js +0 -88
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSSupportsRule.js +0 -36
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSValue.js +0 -43
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/CSSValueExpression.js +0 -344
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/MatcherList.js +0 -62
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/MediaList.js +0 -61
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/StyleSheet.js +0 -17
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/clone.js +0 -82
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/index.js +0 -21
- package/node_modules_lambda/cssstyle/node_modules/cssom/lib/parse.js +0 -464
- package/node_modules_lambda/cssstyle/node_modules/cssom/package.json +0 -18
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/LICENSE.txt +0 -21
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/README.md +0 -106
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/index.js +0 -27
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/Function.js +0 -42
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/URL-impl.js +0 -209
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/URL.js +0 -442
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/URLSearchParams-impl.js +0 -130
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/URLSearchParams.js +0 -472
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/VoidFunction.js +0 -26
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/encoding.js +0 -16
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/infra.js +0 -26
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/percent-encoding.js +0 -142
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/url-state-machine.js +0 -1244
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/urlencoded.js +0 -106
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/lib/utils.js +0 -190
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/package.json +0 -58
- package/node_modules_lambda/data-urls/node_modules/whatwg-url/webidl2js-wrapper.js +0 -7
- package/node_modules_lambda/escodegen/node_modules/estraverse/.jshintrc +0 -16
- package/node_modules_lambda/escodegen/node_modules/estraverse/LICENSE.BSD +0 -19
- package/node_modules_lambda/escodegen/node_modules/estraverse/README.md +0 -153
- package/node_modules_lambda/escodegen/node_modules/estraverse/estraverse.js +0 -805
- package/node_modules_lambda/escodegen/node_modules/estraverse/gulpfile.js +0 -70
- package/node_modules_lambda/escodegen/node_modules/estraverse/package.json +0 -40
- package/node_modules_lambda/escodegen/node_modules/levn/LICENSE +0 -22
- package/node_modules_lambda/escodegen/node_modules/levn/README.md +0 -196
- package/node_modules_lambda/escodegen/node_modules/levn/lib/cast.js +0 -298
- package/node_modules_lambda/escodegen/node_modules/levn/lib/coerce.js +0 -285
- package/node_modules_lambda/escodegen/node_modules/levn/lib/index.js +0 -22
- package/node_modules_lambda/escodegen/node_modules/levn/lib/parse-string.js +0 -113
- package/node_modules_lambda/escodegen/node_modules/levn/lib/parse.js +0 -102
- package/node_modules_lambda/escodegen/node_modules/levn/package.json +0 -47
- package/node_modules_lambda/escodegen/node_modules/optionator/CHANGELOG.md +0 -56
- package/node_modules_lambda/escodegen/node_modules/optionator/LICENSE +0 -22
- package/node_modules_lambda/escodegen/node_modules/optionator/README.md +0 -238
- package/node_modules_lambda/escodegen/node_modules/optionator/lib/help.js +0 -260
- package/node_modules_lambda/escodegen/node_modules/optionator/lib/index.js +0 -465
- package/node_modules_lambda/escodegen/node_modules/optionator/lib/util.js +0 -54
- package/node_modules_lambda/escodegen/node_modules/optionator/package.json +0 -44
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/CHANGELOG.md +0 -99
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/LICENSE +0 -22
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/README.md +0 -15
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/lib/Func.js +0 -65
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/lib/List.js +0 -686
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/lib/Num.js +0 -130
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/lib/Obj.js +0 -154
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/lib/Str.js +0 -92
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/lib/index.js +0 -178
- package/node_modules_lambda/escodegen/node_modules/prelude-ls/package.json +0 -52
- package/node_modules_lambda/escodegen/node_modules/source-map/CHANGELOG.md +0 -301
- package/node_modules_lambda/escodegen/node_modules/source-map/LICENSE +0 -28
- package/node_modules_lambda/escodegen/node_modules/source-map/README.md +0 -742
- package/node_modules_lambda/escodegen/node_modules/source-map/dist/source-map.debug.js +0 -3234
- package/node_modules_lambda/escodegen/node_modules/source-map/dist/source-map.js +0 -3233
- package/node_modules_lambda/escodegen/node_modules/source-map/dist/source-map.min.js +0 -2
- package/node_modules_lambda/escodegen/node_modules/source-map/dist/source-map.min.js.map +0 -1
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/array-set.js +0 -121
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/base64-vlq.js +0 -140
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/base64.js +0 -67
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/binary-search.js +0 -111
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/mapping-list.js +0 -79
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/quick-sort.js +0 -114
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/source-map-consumer.js +0 -1145
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/source-map-generator.js +0 -425
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/source-node.js +0 -413
- package/node_modules_lambda/escodegen/node_modules/source-map/lib/util.js +0 -488
- package/node_modules_lambda/escodegen/node_modules/source-map/package.json +0 -73
- package/node_modules_lambda/escodegen/node_modules/source-map/source-map.d.ts +0 -98
- package/node_modules_lambda/escodegen/node_modules/source-map/source-map.js +0 -8
- package/node_modules_lambda/escodegen/node_modules/type-check/LICENSE +0 -22
- package/node_modules_lambda/escodegen/node_modules/type-check/README.md +0 -210
- package/node_modules_lambda/escodegen/node_modules/type-check/lib/check.js +0 -126
- package/node_modules_lambda/escodegen/node_modules/type-check/lib/index.js +0 -16
- package/node_modules_lambda/escodegen/node_modules/type-check/lib/parse-type.js +0 -196
- package/node_modules_lambda/escodegen/node_modules/type-check/package.json +0 -40
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/.github/dependabot.yml +0 -11
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/Changelog.md +0 -212
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/LICENSE +0 -21
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/README.md +0 -130
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/dbcs-codec.js +0 -597
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/dbcs-data.js +0 -188
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/index.js +0 -23
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/internal.js +0 -198
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/sbcs-codec.js +0 -72
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/sbcs-data-generated.js +0 -451
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/sbcs-data.js +0 -179
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/big5-added.json +0 -122
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/cp936.json +0 -264
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/cp949.json +0 -273
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/cp950.json +0 -177
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/eucjp.json +0 -182
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/gb18030-ranges.json +0 -1
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/gbk-added.json +0 -56
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/tables/shiftjis.json +0 -125
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/utf16.js +0 -197
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/utf32.js +0 -319
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/encodings/utf7.js +0 -290
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/lib/bom-handling.js +0 -52
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/lib/index.d.ts +0 -41
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/lib/index.js +0 -180
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/lib/streams.js +0 -109
- package/node_modules_lambda/whatwg-encoding/node_modules/iconv-lite/package.json +0 -44
package/jest.config.js
CHANGED
|
@@ -10,6 +10,9 @@ module.exports = {
|
|
|
10
10
|
moduleNameMapper: {
|
|
11
11
|
'^.+\\.svg$': '<rootDir>/lib/__mocks__/svgMock.js'
|
|
12
12
|
},
|
|
13
|
+
snapshotFormat: {
|
|
14
|
+
printBasicPrototype: true
|
|
15
|
+
},
|
|
13
16
|
testEnvironment: '<rootDir>/config/jest/TestEnvironment.js',
|
|
14
17
|
setupFilesAfterEnv: ['<rootDir>/config/jest/setupMatchers.js'],
|
|
15
18
|
setupFiles: ['<rootDir>/config/jest/setupTests.js'],
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
<div
|
|
4
4
|
class="zw-modal"
|
|
5
5
|
ref="hostRef"
|
|
6
|
+
tabindex="-1"
|
|
6
7
|
:style="modalStyles"
|
|
7
8
|
v-if="isOpened"
|
|
8
9
|
v-out-click="close"
|
|
@@ -13,9 +14,9 @@
|
|
|
13
14
|
</template>
|
|
14
15
|
|
|
15
16
|
<script>
|
|
16
|
-
import { computed, ref } from 'vue';
|
|
17
|
+
import { computed, nextTick, ref, watch } from 'vue';
|
|
17
18
|
import { outClick } from '../../directives';
|
|
18
|
-
import { useDeselectionLock, useModalToggler } from './composables';
|
|
19
|
+
import { useDeselectionLock, useElementRef, useModalToggler } from './composables';
|
|
19
20
|
|
|
20
21
|
export default {
|
|
21
22
|
name: 'Modal',
|
|
@@ -46,12 +47,19 @@ export default {
|
|
|
46
47
|
type: [Number, String],
|
|
47
48
|
required: false,
|
|
48
49
|
default: 1000
|
|
50
|
+
},
|
|
51
|
+
|
|
52
|
+
focusFirstControl: {
|
|
53
|
+
type: Boolean,
|
|
54
|
+
required: false,
|
|
55
|
+
default: false
|
|
49
56
|
}
|
|
50
57
|
},
|
|
51
58
|
|
|
52
59
|
setup(props) {
|
|
53
60
|
const toggler = props.toggler || useModalToggler();
|
|
54
61
|
const hostRef = ref(null);
|
|
62
|
+
const hostEl = useElementRef(hostRef);
|
|
55
63
|
|
|
56
64
|
const modalStyles = computed(() => ({
|
|
57
65
|
'--zw-modal-max-height': `${props.maxHeight}px`,
|
|
@@ -63,6 +71,17 @@ export default {
|
|
|
63
71
|
hostRef
|
|
64
72
|
});
|
|
65
73
|
|
|
74
|
+
if (props.focusFirstControl) {
|
|
75
|
+
watch(toggler.isOpened, async (_, wasOpened) => {
|
|
76
|
+
if (wasOpened) return;
|
|
77
|
+
|
|
78
|
+
await nextTick();
|
|
79
|
+
const focusableEl = hostEl.value.querySelector(':where(a, button, input):not(:disabled, [data-initial-focus="false"])');
|
|
80
|
+
|
|
81
|
+
(focusableEl || hostEl.value).focus();
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
|
|
66
85
|
return {
|
|
67
86
|
hostRef,
|
|
68
87
|
modalStyles,
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
<Icon name="link" size="28px" auto-color />
|
|
5
5
|
</Button>
|
|
6
6
|
|
|
7
|
-
<Modal class="zw-link-modal" :toggler="toggler" ref="modalRef">
|
|
7
|
+
<Modal class="zw-link-modal" :toggler="toggler" ref="modalRef" focus-first-control>
|
|
8
8
|
<LinkControlHeader @remove-link="removeLink" />
|
|
9
9
|
|
|
10
|
-
<
|
|
10
|
+
<form class="zw-link-modal__body" @submit.prevent="applyLink" data-test-selector="form">
|
|
11
11
|
<TextField
|
|
12
12
|
class="zw-margin-bottom--sm"
|
|
13
13
|
:value="link.linkData.value.text"
|
|
@@ -24,21 +24,28 @@
|
|
|
24
24
|
@reset-errors="resetErrors"
|
|
25
25
|
/>
|
|
26
26
|
|
|
27
|
-
<
|
|
28
|
-
|
|
27
|
+
<div class="zw-link-modal__actions">
|
|
28
|
+
<Button class="zw-margin-right--xs" skin="secondary" @click="toggler.close">
|
|
29
|
+
Cancel
|
|
30
|
+
</Button>
|
|
31
|
+
|
|
32
|
+
<Button type="submit" skin="primary">
|
|
33
|
+
Save
|
|
34
|
+
</Button>
|
|
35
|
+
</div>
|
|
36
|
+
</form>
|
|
29
37
|
</Modal>
|
|
30
38
|
</div>
|
|
31
39
|
</template>
|
|
32
40
|
|
|
33
41
|
<script>
|
|
34
|
-
import { computed, ref, inject } from 'vue';
|
|
35
|
-
import { LinkDestinations } from '../../../../enums';
|
|
42
|
+
import { computed, ref, inject, unref } from 'vue';
|
|
43
|
+
import { LinkDestinations, TextSettings } from '../../../../enums';
|
|
36
44
|
import { InjectionTokens } from '../../../../injectionTokens';
|
|
37
45
|
import { tooltip } from '../../../../directives';
|
|
38
46
|
import { useValidator } from '../../../base/composables';
|
|
39
47
|
import { Button, Icon, Modal, TextField, useModalToggler } from '../../../base';
|
|
40
48
|
import LinkControlHeader from './LinkControlHeader';
|
|
41
|
-
import LinkControlApply from './LinkControlApply';
|
|
42
49
|
import { useLink } from './composables';
|
|
43
50
|
import { LinkControlDestination } from './destination';
|
|
44
51
|
|
|
@@ -47,7 +54,6 @@ export default {
|
|
|
47
54
|
|
|
48
55
|
components: {
|
|
49
56
|
LinkControlDestination,
|
|
50
|
-
LinkControlApply,
|
|
51
57
|
LinkControlHeader,
|
|
52
58
|
TextField,
|
|
53
59
|
Modal,
|
|
@@ -94,7 +100,7 @@ export default {
|
|
|
94
100
|
};
|
|
95
101
|
|
|
96
102
|
const onBeforeOpened = () => {
|
|
97
|
-
editor.commands.extendMarkRange(
|
|
103
|
+
editor.commands.extendMarkRange(TextSettings.LINK);
|
|
98
104
|
resetErrors();
|
|
99
105
|
link.prepareInitialFields();
|
|
100
106
|
};
|
|
@@ -105,7 +111,8 @@ export default {
|
|
|
105
111
|
modalRef
|
|
106
112
|
});
|
|
107
113
|
|
|
108
|
-
const
|
|
114
|
+
const isLink = editor.commands.isLink();
|
|
115
|
+
const isActive = computed(() => unref(toggler.isOpened) || unref(isLink));
|
|
109
116
|
|
|
110
117
|
const updateLinkText = (value) => {
|
|
111
118
|
resetErrors();
|
|
@@ -154,6 +161,11 @@ export default {
|
|
|
154
161
|
padding: var(--zw-offset-sm);
|
|
155
162
|
}
|
|
156
163
|
|
|
164
|
+
.zw-link-modal__actions {
|
|
165
|
+
display: flex;
|
|
166
|
+
justify-content: flex-end;
|
|
167
|
+
}
|
|
168
|
+
|
|
157
169
|
::v-deep .zw-link-modal-dropdown__option {
|
|
158
170
|
width: 234px;
|
|
159
171
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
<div class="zw-link-modal-header">
|
|
3
3
|
<span class="zw-link-modal-header__title">Link</span>
|
|
4
4
|
|
|
5
|
-
<Button class="zw-link-modal-header__unlink-button" :disabled="!isLink" @click="removeLink">
|
|
5
|
+
<Button class="zw-link-modal-header__unlink-button" :disabled="!isLink" data-initial-focus="false" @click="removeLink">
|
|
6
6
|
<Icon class="zw-link-modal-header__unlink-icon" name="unlink" size="14px" auto-color />
|
|
7
7
|
Remove
|
|
8
8
|
</Button>
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
</template>
|
|
11
11
|
|
|
12
12
|
<script>
|
|
13
|
-
import {
|
|
13
|
+
import { inject } from 'vue';
|
|
14
14
|
import { Icon, Button } from '../../../base';
|
|
15
15
|
import { InjectionTokens } from '../../../../injectionTokens';
|
|
16
16
|
|
|
@@ -21,7 +21,7 @@ export default {
|
|
|
21
21
|
|
|
22
22
|
setup(_, { emit }) {
|
|
23
23
|
const editor = inject(InjectionTokens.EDITOR);
|
|
24
|
-
const isLink =
|
|
24
|
+
const isLink = editor.commands.isLink();
|
|
25
25
|
|
|
26
26
|
const removeLink = () => emit('remove-link');
|
|
27
27
|
|
|
@@ -3,11 +3,10 @@ import { ref, nextTick } from 'vue';
|
|
|
3
3
|
import LinkControl from '../LinkControl';
|
|
4
4
|
import { InjectionTokens } from '../../../../../injectionTokens';
|
|
5
5
|
import { Button, TextField } from '../../../../base';
|
|
6
|
-
import LinkControlApply from '../LinkControlApply';
|
|
7
6
|
import { LinkControlDestination } from '../destination';
|
|
8
7
|
|
|
9
8
|
const createEditor = (isActive) => ({
|
|
10
|
-
|
|
9
|
+
commands: { isLink: () => isActive ?? false }
|
|
11
10
|
});
|
|
12
11
|
|
|
13
12
|
function createComponent({ editor }) {
|
|
@@ -19,6 +18,10 @@ function createComponent({ editor }) {
|
|
|
19
18
|
});
|
|
20
19
|
}
|
|
21
20
|
|
|
21
|
+
const SELECTORS = {
|
|
22
|
+
FORM: '[data-test-selector="form"]'
|
|
23
|
+
};
|
|
24
|
+
|
|
22
25
|
describe('selection value', () => {
|
|
23
26
|
test('should render link status', () => {
|
|
24
27
|
const editor = createEditor(true );
|
|
@@ -35,9 +38,8 @@ describe('validation', () => {
|
|
|
35
38
|
const wrapper = createComponent({ editor });
|
|
36
39
|
const textFieldWrapper = wrapper.findComponent(TextField);
|
|
37
40
|
const linkControlDestinationWrapper = wrapper.findComponent(LinkControlDestination);
|
|
38
|
-
const applyWrapper = wrapper.findComponent(LinkControlApply);
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
await wrapper.find(SELECTORS.FORM).trigger('submit');
|
|
41
43
|
await nextTick();
|
|
42
44
|
|
|
43
45
|
expect(textFieldWrapper.props('error')).toBe('Can\'t be empty');
|
|
@@ -49,9 +51,8 @@ describe('validation', () => {
|
|
|
49
51
|
const wrapper = createComponent({ editor });
|
|
50
52
|
const textFieldWrapper = wrapper.findComponent(TextField);
|
|
51
53
|
const linkControlDestinationWrapper = wrapper.findComponent(LinkControlDestination);
|
|
52
|
-
const applyWrapper = wrapper.findComponent(LinkControlApply);
|
|
53
54
|
|
|
54
|
-
|
|
55
|
+
await wrapper.find(SELECTORS.FORM).trigger('submit');
|
|
55
56
|
textFieldWrapper.vm.$emit('input', 'hello');
|
|
56
57
|
|
|
57
58
|
await nextTick();
|
|
@@ -65,9 +66,8 @@ describe('validation', () => {
|
|
|
65
66
|
const wrapper = createComponent({ editor });
|
|
66
67
|
const textFieldWrapper = wrapper.findComponent(TextField);
|
|
67
68
|
const linkControlDestinationWrapper = wrapper.findComponent(LinkControlDestination);
|
|
68
|
-
const applyWrapper = wrapper.findComponent(LinkControlApply);
|
|
69
69
|
|
|
70
|
-
|
|
70
|
+
await wrapper.find(SELECTORS.FORM).trigger('submit');
|
|
71
71
|
linkControlDestinationWrapper.vm.$emit('reset-errors');
|
|
72
72
|
|
|
73
73
|
await nextTick();
|
|
@@ -4,7 +4,7 @@ import { Button } from '../../../../base';
|
|
|
4
4
|
import LinkControlHeader from '../LinkControlHeader';
|
|
5
5
|
|
|
6
6
|
const createEditor = (isActive) => ({
|
|
7
|
-
|
|
7
|
+
commands: { isLink: () => isActive ?? false }
|
|
8
8
|
});
|
|
9
9
|
|
|
10
10
|
function createComponent({ editor }) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ref, inject } from 'vue';
|
|
2
|
-
import { LinkTargets, LinkDestinations } from '../../../../../enums';
|
|
2
|
+
import { LinkTargets, LinkDestinations, TextSettings } from '../../../../../enums';
|
|
3
3
|
import { InjectionTokens } from '../../../../../injectionTokens';
|
|
4
4
|
|
|
5
5
|
export function useLink() {
|
|
@@ -15,12 +15,14 @@ export function useLink() {
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
function prepareInitialFields() {
|
|
18
|
+
const link = editor.getAttributes(TextSettings.LINK);
|
|
19
|
+
|
|
18
20
|
linkData.value.text = editor.commands.getSelectedText();
|
|
19
|
-
currentDestination.value.id =
|
|
20
|
-
linkData.value.target =
|
|
21
|
+
currentDestination.value.id = link.destination || LinkDestinations.URL;
|
|
22
|
+
linkData.value.target = link.target || LinkTargets.SELF;
|
|
21
23
|
|
|
22
|
-
if (
|
|
23
|
-
destinationHrefs.value[currentDestination.value.id] =
|
|
24
|
+
if (link.href) {
|
|
25
|
+
destinationHrefs.value[currentDestination.value.id] = link.href;
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -35,7 +37,7 @@ export function useLink() {
|
|
|
35
37
|
const isRelative = !!url.startsWith('/');
|
|
36
38
|
const hasProtocol = /^https?:\/\/.+$/i.test(url);
|
|
37
39
|
|
|
38
|
-
return
|
|
40
|
+
return isRelative || hasProtocol ? url : `https://${url}`;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
43
|
return destinationHrefs.value[currentDestination.value.id];
|
|
@@ -56,6 +58,8 @@ export function useLink() {
|
|
|
56
58
|
|
|
57
59
|
function removeLink() {
|
|
58
60
|
editor.chain().focus().unsetLink().run();
|
|
61
|
+
resetDestinations();
|
|
62
|
+
updateTarget(false);
|
|
59
63
|
}
|
|
60
64
|
|
|
61
65
|
function updateLink(value) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Editor } from '@tiptap/vue-2';
|
|
2
|
-
import { onUnmounted, watch, reactive } from 'vue';
|
|
2
|
+
import { onUnmounted, watch, reactive, unref } from 'vue';
|
|
3
3
|
import { ContentNormalizer } from '../services';
|
|
4
4
|
import { markWysiwygContent, unmarkWysiwygContent } from '../utils';
|
|
5
5
|
|
|
@@ -8,7 +8,8 @@ export function useEditor({ content, onChange, extensions, isReadonlyRef }) {
|
|
|
8
8
|
content: ContentNormalizer.normalize(content.value),
|
|
9
9
|
onUpdate: () => onChange(markWysiwygContent(editor.getJSON())),
|
|
10
10
|
extensions,
|
|
11
|
-
injectCSS: false
|
|
11
|
+
injectCSS: false,
|
|
12
|
+
editable: !unref(isReadonlyRef)
|
|
12
13
|
}));
|
|
13
14
|
|
|
14
15
|
onUnmounted(() => editor.destroy());
|
|
@@ -24,7 +25,7 @@ export function useEditor({ content, onChange, extensions, isReadonlyRef }) {
|
|
|
24
25
|
}
|
|
25
26
|
});
|
|
26
27
|
|
|
27
|
-
watch(isReadonlyRef, (isReadonly) => editor.setEditable(!isReadonly)
|
|
28
|
+
watch(isReadonlyRef, (isReadonly) => editor.setEditable(!isReadonly));
|
|
28
29
|
|
|
29
30
|
return editor;
|
|
30
31
|
}
|
|
@@ -46,7 +46,7 @@ export const FontStyle = Mark.create({
|
|
|
46
46
|
}),
|
|
47
47
|
|
|
48
48
|
removeItalic: createCommand(({ commands }) => {
|
|
49
|
-
commands.
|
|
49
|
+
commands.setMark(this.name, { italic: false });
|
|
50
50
|
})
|
|
51
51
|
};
|
|
52
52
|
},
|
|
@@ -76,7 +76,7 @@ export const FontStyle = Mark.create({
|
|
|
76
76
|
},
|
|
77
77
|
|
|
78
78
|
renderHTML({ HTMLAttributes: attrs }) {
|
|
79
|
-
const font_style = attrs.italic ? 'italic' :
|
|
79
|
+
const font_style = attrs.italic ? 'italic' : 'normal';
|
|
80
80
|
|
|
81
81
|
return renderMark({ font_style });
|
|
82
82
|
}
|
package/lib/extensions/Link.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import Base from '@tiptap/extension-link';
|
|
2
|
-
import { unref } from 'vue';
|
|
2
|
+
import { computed, unref } from 'vue';
|
|
3
3
|
import { createCommand } from '../utils';
|
|
4
|
-
import { LinkDestinations, LinkTargets } from '../enums';
|
|
4
|
+
import { LinkDestinations, LinkTargets, TextSettings } from '../enums';
|
|
5
|
+
import { NodeFactory } from '../services';
|
|
5
6
|
|
|
6
7
|
export const Link = Base.extend({
|
|
7
|
-
name:
|
|
8
|
+
name: TextSettings.LINK,
|
|
8
9
|
|
|
9
10
|
addOptions() {
|
|
10
11
|
return {
|
|
@@ -52,26 +53,23 @@ export const Link = Base.extend({
|
|
|
52
53
|
addCommands() {
|
|
53
54
|
return {
|
|
54
55
|
...this.parent?.(),
|
|
56
|
+
|
|
55
57
|
applyLink: createCommand(({ commands, chain }, attributes) => {
|
|
56
58
|
if (!commands.getSelectedText()) {
|
|
57
|
-
return commands.insertContent(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
{
|
|
61
|
-
type: 'link',
|
|
62
|
-
attrs: { ...attributes }
|
|
63
|
-
}
|
|
64
|
-
],
|
|
65
|
-
text: attributes.text
|
|
66
|
-
});
|
|
59
|
+
return commands.insertContent(NodeFactory.text(attributes.text, [
|
|
60
|
+
NodeFactory.mark(TextSettings.LINK, attributes)
|
|
61
|
+
]));
|
|
67
62
|
}
|
|
68
63
|
|
|
69
64
|
return chain()
|
|
70
65
|
.setMark(this.name, attributes)
|
|
71
66
|
.transformText(() => attributes.text)
|
|
72
|
-
.extendMarkRange(
|
|
67
|
+
.extendMarkRange(TextSettings.LINK)
|
|
73
68
|
.run();
|
|
74
|
-
})
|
|
69
|
+
}),
|
|
70
|
+
|
|
71
|
+
isLink: createCommand(({ editor }) => computed(() => editor.isActive(TextSettings.LINK))),
|
|
72
|
+
getLinkPreset: createCommand(() => computed(() => this.options.preset))
|
|
75
73
|
};
|
|
76
74
|
},
|
|
77
75
|
|
|
@@ -70,16 +70,46 @@ export const StylePreset = Extension.create({
|
|
|
70
70
|
return presets.find((preset) => id === preset.id);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
function mergeSettings(source, target) {
|
|
74
|
+
const settings = {};
|
|
75
|
+
|
|
76
|
+
for (const name of Object.keys(source)) {
|
|
77
|
+
const sourceValue = source[name];
|
|
78
|
+
const targetValue = target[name];
|
|
79
|
+
const isInherit = !targetValue || targetValue === 'inherit';
|
|
80
|
+
|
|
81
|
+
settings[name] = isInherit ? sourceValue : targetValue;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return settings;
|
|
85
|
+
}
|
|
86
|
+
|
|
73
87
|
return {
|
|
74
88
|
getPresetList: createCommand(() => computed(() => {
|
|
75
89
|
return this.options.presets.filter((preset) => !preset.hidden);
|
|
76
90
|
})),
|
|
77
91
|
|
|
78
92
|
getPreset: createCommand(({ commands }) => {
|
|
79
|
-
const
|
|
80
|
-
const
|
|
93
|
+
const selectionRef = commands.getBlockAttributes('preset', { id: this.options.defaultId });
|
|
94
|
+
const presetsRef = commands.getPresetList();
|
|
95
|
+
const isLinkRef = commands.isLink();
|
|
96
|
+
const linkPresetRef = commands.getLinkPreset();
|
|
81
97
|
|
|
82
|
-
return computed(() =>
|
|
98
|
+
return computed(() => {
|
|
99
|
+
const preset = findPresetById(unref(presetsRef), unref(selectionRef).id);
|
|
100
|
+
|
|
101
|
+
if (!unref(isLinkRef)) return preset;
|
|
102
|
+
|
|
103
|
+
const linkPreset = unref(linkPresetRef);
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
id: preset.id,
|
|
107
|
+
common: mergeSettings(preset.common, linkPreset.common),
|
|
108
|
+
mobile: mergeSettings(preset.mobile, linkPreset.mobile),
|
|
109
|
+
tablet: mergeSettings(preset.tablet, linkPreset.tablet),
|
|
110
|
+
desktop: mergeSettings(preset.desktop, linkPreset.desktop)
|
|
111
|
+
};
|
|
112
|
+
});
|
|
83
113
|
}),
|
|
84
114
|
|
|
85
115
|
applyPreset: createCommand(({ commands, chain }, presetId) => {
|
|
@@ -5,6 +5,7 @@ import { TextSettings } from '../enums';
|
|
|
5
5
|
|
|
6
6
|
export const TextDecoration = Mark.create({
|
|
7
7
|
name: TextSettings.TEXT_DECORATION,
|
|
8
|
+
priority: 1000,
|
|
8
9
|
|
|
9
10
|
addAttributes: () => ({
|
|
10
11
|
underline: { default: false },
|
|
@@ -13,10 +14,10 @@ export const TextDecoration = Mark.create({
|
|
|
13
14
|
|
|
14
15
|
addCommands() {
|
|
15
16
|
return {
|
|
16
|
-
isUnderline: createCommand(({ commands
|
|
17
|
+
isUnderline: createCommand(({ commands }) => {
|
|
17
18
|
const decoration = commands.getTextDecoration();
|
|
18
19
|
|
|
19
|
-
return computed(() =>
|
|
20
|
+
return computed(() => unref(decoration).underline);
|
|
20
21
|
}),
|
|
21
22
|
|
|
22
23
|
isStrikeThrough: createCommand(({ commands }) => {
|
|
@@ -51,9 +52,7 @@ export const TextDecoration = Mark.create({
|
|
|
51
52
|
});
|
|
52
53
|
}),
|
|
53
54
|
|
|
54
|
-
toggleUnderline: createCommand(({ commands
|
|
55
|
-
if (editor.isActive('link')) return;
|
|
56
|
-
|
|
55
|
+
toggleUnderline: createCommand(({ commands }) => {
|
|
57
56
|
commands.toggleTextDecoration('underline');
|
|
58
57
|
}),
|
|
59
58
|
|
|
@@ -72,13 +71,7 @@ export const TextDecoration = Mark.create({
|
|
|
72
71
|
}),
|
|
73
72
|
|
|
74
73
|
removeTextDecoration: createCommand(({ commands }, name) => {
|
|
75
|
-
|
|
76
|
-
...unref(commands.getTextDecoration()),
|
|
77
|
-
[name]: false
|
|
78
|
-
};
|
|
79
|
-
const isRemoveMark = !mark.underline && !mark.strike_through;
|
|
80
|
-
|
|
81
|
-
isRemoveMark ? commands.unsetMark(this.name) : commands.setMark(this.name, mark);
|
|
74
|
+
commands.setMark(this.name, { ...unref(commands.getTextDecoration()), [name]: false });
|
|
82
75
|
})
|
|
83
76
|
};
|
|
84
77
|
},
|
|
@@ -135,6 +128,7 @@ export const TextDecoration = Mark.create({
|
|
|
135
128
|
|
|
136
129
|
if (attrs.underline) decorations.push('underline');
|
|
137
130
|
if (attrs.strike_through) decorations.push('line-through');
|
|
131
|
+
if (!decorations.length) decorations.push('none');
|
|
138
132
|
|
|
139
133
|
return renderMark({ text_decoration: decorations.join(' ') });
|
|
140
134
|
}
|
|
@@ -6,10 +6,11 @@ import { FontFamily } from '../FontFamily';
|
|
|
6
6
|
import { FontWeight } from '../FontWeight';
|
|
7
7
|
import { FontStyle } from '../FontStyle';
|
|
8
8
|
import { ContentNormalizer, NodeFactory } from '../../services';
|
|
9
|
+
import { TextSettings } from '../../enums';
|
|
9
10
|
import { buildCoreExtensions } from '../core';
|
|
10
11
|
|
|
11
12
|
const MockStylePreset = Extension.create({
|
|
12
|
-
name:
|
|
13
|
+
name: TextSettings.STYLE_PRESET,
|
|
13
14
|
|
|
14
15
|
addCommands() {
|
|
15
16
|
return {
|
|
@@ -30,10 +31,10 @@ function createEditor({ content }) {
|
|
|
30
31
|
MockStylePreset,
|
|
31
32
|
FontFamily.configure({
|
|
32
33
|
fonts: [
|
|
33
|
-
new Font({ name: 'Lato', styles: ['400', '700', '700i'] }),
|
|
34
|
+
new Font({ name: 'Lato', styles: ['400', '400i', '700', '700i'] }),
|
|
34
35
|
new Font({ name: 'Bungee', styles: ['400'] }),
|
|
35
|
-
new Font({ name: 'Roboto', styles: ['400'] }),
|
|
36
|
-
new Font({ name: 'Josefin Slab', styles: ['400'] })
|
|
36
|
+
new Font({ name: 'Roboto', styles: ['400', '400i'] }),
|
|
37
|
+
new Font({ name: 'Josefin Slab', styles: ['400', '400i'] })
|
|
37
38
|
],
|
|
38
39
|
defaultFont: 'Lato'
|
|
39
40
|
}),
|
|
@@ -51,7 +52,7 @@ describe('get font family', () => {
|
|
|
51
52
|
test('should get from selection', () => {
|
|
52
53
|
const editor = createEditor({
|
|
53
54
|
content: createContent(NodeFactory.text('hello world', [
|
|
54
|
-
NodeFactory.mark(
|
|
55
|
+
NodeFactory.mark(TextSettings.FONT_FAMILY, { value: 'Bungee' })
|
|
55
56
|
]))
|
|
56
57
|
});
|
|
57
58
|
|
|
@@ -165,7 +166,7 @@ describe('rendering', () => {
|
|
|
165
166
|
test('should render html', () => {
|
|
166
167
|
const editor = createEditor({
|
|
167
168
|
content: createContent(NodeFactory.text('hello world', [
|
|
168
|
-
NodeFactory.mark(
|
|
169
|
+
NodeFactory.mark(TextSettings.FONT_FAMILY, { value: 'Bungee' })
|
|
169
170
|
]))
|
|
170
171
|
});
|
|
171
172
|
|