@designcrowd/library.brand-page 5.10.6-sanitise-hyperlink-15 → 5.10.6
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/lib/src/brand-page/models/index.d.ts +0 -5
- package/lib/src/brand-page/models/index.js +0 -4
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.js +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.js +0 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.d.ts +1 -1
- package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.js +1 -2
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/font.js +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/formatting.js +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/spacing.js +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.d.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/textAlign.js +1 -0
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.d.ts +3 -19
- package/lib/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.js +21 -111
- package/lib/src/brand-page-maker/models/button-group.model.d.ts +0 -2
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.d.ts +1 -15
- package/lib/src/brand-page-maker/utils/rich-text-editor.util.js +1 -282
- package/lib/src/css/library.brand-page-brandCrowd.min.css +57 -83
- package/lib/src/css/library.brand-page-brandPage.min.css +57 -83
- package/lib/src/css/library.brand-page-designCom.min.css +57 -83
- package/lib/src/css/library.brand-page-preview.min.css +57 -83
- package/lib/src/index.d.ts +0 -1
- package/lib/src/index.mjs +22383 -24521
- package/lib/src/lib.js +0 -1
- package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.d.ts +1 -11
- package/lib/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.js +0 -4
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.d.ts +0 -2
- package/lib/src/shared/content-settings/components/url-field/UrlField.mixin.js +7 -12
- package/lib/src/shared/page-settings/components/page-settings-section-styles/PageSettingsSectionStyles.mixin.d.ts +0 -2
- package/lib/src/shared/shape-library/ShapeLibrary.mixin.js +1 -1
- package/package.json +11 -19
- package/src/brand-page/components/banner-section/BannerSection.vue +0 -6
- package/src/brand-page/components/text/Text.vue +0 -2
- package/src/brand-page/components/text-wrapper/TextWrapper.vue +8 -26
- package/src/brand-page/models/index.ts +0 -6
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/brand-page-examples.ts +1 -1
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/content-settings-items.fixture.ts +0 -1
- package/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.ts +0 -2
- package/src/brand-page-maker/components/rich-text-editor/RichTextEditor.vue +46 -339
- package/src/brand-page-maker/composables/rich-text-editor/extensions/MaxLength.test.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/font.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/formatting.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/spacing.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/textAlign.ts +1 -1
- package/src/brand-page-maker/composables/rich-text-editor/useRichTextEditor.ts +23 -162
- package/src/brand-page-maker/models/button-group.model.ts +0 -2
- package/src/brand-page-maker/stores/brandpage-maker/__snapshots__/brandpage-maker-store.test.ts.snap +0 -1
- package/src/brand-page-maker/utils/rich-text-editor.util.test.ts +0 -359
- package/src/brand-page-maker/utils/rich-text-editor.util.ts +1 -361
- package/src/lib.ts +0 -1
- package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.mixin.ts +0 -4
- package/src/shared/content-settings/components/page-dropdown-field/PageDropdownField.vue +2 -2
- package/src/shared/content-settings/components/personalisation-role-field/PersonalisationRoleField.vue +1 -0
- package/src/shared/content-settings/components/text-field/TextField.vue +1 -1
- package/src/shared/content-settings/components/text-items-field/TextItemsField.vue +2 -2
- package/src/shared/content-settings/components/textarea-field/TextareaField.vue +3 -3
- package/src/shared/content-settings/components/url-field/UrlField.mixin.ts +10 -15
- package/src/shared/content-settings/components/url-field/UrlField.vue +0 -1
- package/src/shared/shape-library/ShapeLibrary.mixin.ts +1 -1
- package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.d.ts +0 -19
- package/lib/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.js +0 -31
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.d.ts +0 -2
- package/lib/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.js +0 -161
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.d.ts +0 -19
- package/lib/src/brand-page-maker/composables/rich-text-editor/hyperlink.js +0 -87
- package/src/brand-page-maker/composables/rich-text-editor/bubbleMenu.ts +0 -42
- package/src/brand-page-maker/composables/rich-text-editor/extensions/AutoLink.ts +0 -226
- package/src/brand-page-maker/composables/rich-text-editor/hyperlink.ts +0 -114
|
@@ -207,11 +207,6 @@ export declare const BUTTON_LINK_TYPE: {
|
|
|
207
207
|
readonly tel: "tel";
|
|
208
208
|
};
|
|
209
209
|
export type ButtonLinkType = keyof typeof BUTTON_LINK_TYPE;
|
|
210
|
-
export declare const HYPERLINK_TYPE: {
|
|
211
|
-
readonly url: "url";
|
|
212
|
-
readonly page: "page";
|
|
213
|
-
};
|
|
214
|
-
export type HyperlinkType = keyof typeof HYPERLINK_TYPE;
|
|
215
210
|
export declare const URL_TYPE: {
|
|
216
211
|
readonly url: "url";
|
|
217
212
|
readonly email: "email";
|
package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const brandPageContentsSampleData: (import("../../../../brand-page").ButtonContent | import("../../../../brand-page").ProfileContent | import("../../../../brand-page").
|
|
1
|
+
export declare const brandPageContentsSampleData: (import("../../../../brand-page").ButtonContent | import("../../../../brand-page").ProfileContent | import("../../../../brand-page").LogoContent)[];
|
|
2
2
|
export declare const brandPageContentsSampleDataStarterKit: (import("../../../../brand-page").ButtonContent | import("../../../../brand-page").ProfileContent | import("../../../../brand-page").LogoContent)[];
|
package/lib/src/brand-page-maker/components/brand-page-maker/__fixtures__/page-content-items.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { logoContent, profileContent, generalLink, facebookLink, websiteLink, emailLink, phoneLink, twitterLink, instagramLink, youtubeLink, linkedinLink, pinterestLink, twitchLink, tiktokLink,
|
|
1
|
+
import { logoContent, profileContent, generalLink, facebookLink, websiteLink, emailLink, phoneLink, twitterLink, instagramLink, youtubeLink, linkedinLink, pinterestLink, twitchLink, tiktokLink, } from './content-settings-items.fixture';
|
|
2
2
|
export const brandPageContentsSampleData = [
|
|
3
3
|
logoContent,
|
|
4
4
|
profileContent,
|
|
5
|
-
textContent,
|
|
6
5
|
generalLink,
|
|
7
6
|
websiteLink,
|
|
8
7
|
emailLink,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Editor } from '@tiptap/vue-3';
|
|
2
2
|
export declare const useSpacing: (editor: Editor) => {
|
|
3
3
|
letterSpacingValue: import("vue").WritableComputedRef<string, string>;
|
|
4
4
|
lineHeightValue: import("vue").WritableComputedRef<string, string>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ref, computed } from 'vue';
|
|
2
|
+
import { Editor } from '@tiptap/vue-3';
|
|
2
3
|
import debounce from 'lodash/debounce';
|
|
3
4
|
import { letterSpacingValueConvertor } from '../../../brand-page-maker/convertors';
|
|
4
5
|
import { skipStyleDetection } from '../../../brand-page-maker/utils';
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { type ModelRef, type ComputedRef, type Ref, type WritableComputedRef } from 'vue';
|
|
2
2
|
import { Editor } from '@tiptap/vue-3';
|
|
3
3
|
import type { StyleTextFontFamilyOption } from '../../../shared/style-settings/models';
|
|
4
|
-
import
|
|
5
|
-
import { type TextItem, type TextStyleDeclaration } from '../../../brand-page';
|
|
4
|
+
import { TextStyles, type TextItem, type TextStyleDeclaration } from '../../../brand-page';
|
|
6
5
|
import type { ButtonGroupOption } from '../../../brand-page-maker/models/button-group.model';
|
|
7
6
|
interface UseRichTextEditorReturn {
|
|
8
7
|
editor: Editor;
|
|
@@ -29,27 +28,12 @@ interface UseRichTextEditorReturn {
|
|
|
29
28
|
setInitialStyleSettings: (selectedTextStyle?: BrandPageCssStyle) => void;
|
|
30
29
|
copyGlobalStyleSettings: (selectedTextStyle?: BrandPageCssStyle) => void;
|
|
31
30
|
unsetAllMarks: () => void;
|
|
32
|
-
handleHyperlink: (action: 'toggle' | 'apply' | 'remove', data?: {
|
|
33
|
-
href?: string;
|
|
34
|
-
text?: string;
|
|
35
|
-
}) => void;
|
|
36
|
-
hyperlinkValue: ComputedRef<{
|
|
37
|
-
id: string;
|
|
38
|
-
name: string;
|
|
39
|
-
value: string;
|
|
40
|
-
}>;
|
|
41
|
-
setHyperlinkUrlValue: (url: string) => void;
|
|
42
|
-
shouldShow: ({ editor, state }: {
|
|
43
|
-
editor: any;
|
|
44
|
-
state: any;
|
|
45
|
-
}) => boolean;
|
|
46
|
-
tippyOptions: Record<string, any>;
|
|
47
31
|
}
|
|
48
32
|
interface DropdownInstance {
|
|
49
33
|
hideMenu: () => void;
|
|
50
34
|
}
|
|
51
35
|
interface EditorOptionType {
|
|
52
|
-
type: '
|
|
36
|
+
type: 'fontFamily' | 'fontSize' | 'fontWeight' | 'fontStyle' | 'textDecorationLine' | 'textDecorationStrike' | 'textColor' | 'backgroundColor' | 'lineHeight' | 'letterSpacing' | 'textAlign';
|
|
53
37
|
value: string | StyleTextFontFamilyOption;
|
|
54
38
|
}
|
|
55
39
|
export declare const useExternalRichTextEditor: () => {
|
|
@@ -72,5 +56,5 @@ export declare const useRichTextEditor: (model: ModelRef<any>, props: {
|
|
|
72
56
|
selectedFontSizePx: number;
|
|
73
57
|
selectedTextColor: string;
|
|
74
58
|
selectedBackgroundColor: string;
|
|
75
|
-
}, fontStyleDropdownRef: Ref<DropdownInstance | undefined, DropdownInstance | undefined>, selectedGlobalTextStyles: WritableComputedRef<TextStyles, string>, onSelectTextStyleType: (option: ButtonGroupOption) => void, updateRichTextEditor: Ref<boolean>, textStyleTypeOptions: ButtonGroupOption[]
|
|
59
|
+
}, fontStyleDropdownRef: Ref<DropdownInstance | undefined, DropdownInstance | undefined>, selectedGlobalTextStyles: WritableComputedRef<TextStyles, string>, onSelectTextStyleType: (option: ButtonGroupOption) => void, updateRichTextEditor: Ref<boolean>, textStyleTypeOptions: ButtonGroupOption[]) => UseRichTextEditorReturn;
|
|
76
60
|
export {};
|
|
@@ -11,22 +11,18 @@ import { LetterSpacing } from './extensions/LetterSpacing';
|
|
|
11
11
|
import { LineHeight } from './extensions/LineHeight';
|
|
12
12
|
import Highlight from '@tiptap/extension-highlight';
|
|
13
13
|
import Placeholder from '@tiptap/extension-placeholder';
|
|
14
|
-
import Link from '@tiptap/extension-link';
|
|
15
14
|
import { createFormattingActions } from './formatting';
|
|
16
15
|
import { useTextAlign } from './textAlign';
|
|
17
16
|
import { useFont } from './font';
|
|
18
17
|
import { useSpacing } from './spacing';
|
|
19
18
|
import Color from 'color';
|
|
20
|
-
import { buildInitialMarks, emToPx, isStyleChanged, pxToEm,
|
|
21
|
-
import {
|
|
19
|
+
import { buildInitialMarks, emToPx, isStyleChanged, pxToEm, skipStyleDetection, } from '../../../brand-page-maker/utils';
|
|
20
|
+
import { TextStyles, } from '../../../brand-page';
|
|
22
21
|
import { letterSpacingValueConvertor } from '../../../brand-page-maker/convertors';
|
|
23
22
|
import { useUiContentSettingsStore } from '../../../shared/content-settings/store';
|
|
24
23
|
import { DOMSerializer } from 'prosemirror-model';
|
|
25
24
|
import { AllSelection } from 'prosemirror-state';
|
|
26
25
|
import { MaxLength } from './extensions/MaxLength';
|
|
27
|
-
import { AutoLink } from './extensions/AutoLink';
|
|
28
|
-
import { useHyperlink } from './hyperlink';
|
|
29
|
-
import { useBubbleMenu } from './bubbleMenu';
|
|
30
26
|
export const useExternalRichTextEditor = () => {
|
|
31
27
|
const externalEditor = new Editor({
|
|
32
28
|
editable: false,
|
|
@@ -49,19 +45,13 @@ export const useExternalRichTextEditor = () => {
|
|
|
49
45
|
Highlight.configure({
|
|
50
46
|
multicolor: true,
|
|
51
47
|
}),
|
|
52
|
-
Link.configure({
|
|
53
|
-
openOnClick: false,
|
|
54
|
-
defaultProtocol: 'https',
|
|
55
|
-
autolink: true,
|
|
56
|
-
}),
|
|
57
|
-
AutoLink,
|
|
58
48
|
],
|
|
59
49
|
});
|
|
60
50
|
return {
|
|
61
51
|
externalEditor,
|
|
62
52
|
};
|
|
63
53
|
};
|
|
64
|
-
export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDropdownRef, selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyleTypeOptions
|
|
54
|
+
export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDropdownRef, selectedGlobalTextStyles, onSelectTextStyleType, updateRichTextEditor, textStyleTypeOptions) => {
|
|
65
55
|
const editor = new Editor({
|
|
66
56
|
content: model.value ?? '',
|
|
67
57
|
editable: !props.readOnly,
|
|
@@ -88,12 +78,6 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
88
78
|
placeholder: props.placeholder,
|
|
89
79
|
}),
|
|
90
80
|
MaxLength.configure({ maxLength: props.maxLength }),
|
|
91
|
-
Link.configure({
|
|
92
|
-
openOnClick: false,
|
|
93
|
-
defaultProtocol: 'https',
|
|
94
|
-
autolink: true,
|
|
95
|
-
}),
|
|
96
|
-
AutoLink,
|
|
97
81
|
],
|
|
98
82
|
editorProps: {
|
|
99
83
|
handleDOMEvents: {
|
|
@@ -116,31 +100,32 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
116
100
|
return false;
|
|
117
101
|
},
|
|
118
102
|
copy(view, event) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
103
|
+
// Prevent the browser’s default so we can inject our own blobs
|
|
104
|
+
event.preventDefault();
|
|
105
|
+
// 1) Plain text (already have this)
|
|
106
|
+
const selectedText = view.state.doc.textBetween(view.state.selection.from, view.state.selection.to, '\n');
|
|
107
|
+
event.clipboardData?.setData('text/plain', selectedText);
|
|
108
|
+
// 2) custom style blob to add
|
|
123
109
|
const styleData = JSON.stringify(props.styles);
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
110
|
+
event.clipboardData?.setData('application/x-rte-styles', styleData);
|
|
111
|
+
// 3) HTML serialization via ProseMirror’s DOMSerializer
|
|
112
|
+
const { from, to } = view.state.selection;
|
|
113
|
+
const slice = view.state.doc.slice(from, to);
|
|
114
|
+
const serializer = DOMSerializer.fromSchema(view.state.schema);
|
|
115
|
+
const fragment = serializer.serializeFragment(slice.content);
|
|
116
|
+
// Wrap in a container DIV so we can grab `innerHTML`
|
|
117
|
+
const wrapper = document.createElement('div');
|
|
118
|
+
wrapper.appendChild(fragment);
|
|
119
|
+
event.clipboardData?.setData('text/html', wrapper.innerHTML);
|
|
133
120
|
return true;
|
|
134
121
|
},
|
|
135
122
|
paste(view, event) {
|
|
136
123
|
// Unified paste handler: strip styles if no styleData, enforce maxLength, handle selection
|
|
137
124
|
const styleData = event.clipboardData?.getData('application/x-rte-styles');
|
|
138
125
|
const pastedText = event.clipboardData?.getData('text/plain') || '';
|
|
139
|
-
// const pastedHtml = event.clipboardData?.getData('text/html') || '';
|
|
140
126
|
const { state, dispatch } = view;
|
|
141
127
|
const { from, to } = state.selection;
|
|
142
128
|
let tr = state.tr;
|
|
143
|
-
// console.log(pastedHtml);
|
|
144
129
|
if (styleData) {
|
|
145
130
|
try {
|
|
146
131
|
const pastedStyles = JSON.parse(styleData);
|
|
@@ -174,32 +159,14 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
174
159
|
dispatch(tr);
|
|
175
160
|
return true;
|
|
176
161
|
},
|
|
177
|
-
click(view, event) {
|
|
178
|
-
if (isHyperlinkPopupOpen?.value)
|
|
179
|
-
return false;
|
|
180
|
-
const target = event.target;
|
|
181
|
-
const linkElement = target.closest('a');
|
|
182
|
-
if (linkElement) {
|
|
183
|
-
const pos = view.posAtDOM(linkElement, 0);
|
|
184
|
-
if (pos !== null) {
|
|
185
|
-
editor.commands.setTextSelection(pos);
|
|
186
|
-
editor.commands.extendMarkRange('link');
|
|
187
|
-
return true; // Prevent default
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
return false;
|
|
191
|
-
},
|
|
192
162
|
},
|
|
193
163
|
},
|
|
194
164
|
});
|
|
195
|
-
window.editor = editor;
|
|
196
165
|
const contentSettingStore = useUiContentSettingsStore();
|
|
197
166
|
const { toggleBold, toggleItalic, toggleUnderline, toggleStrike, toggleTextColor, toggleBackgroundColor, toggleBoldAll, toggleItalicAll, toggleUnderlineAll, toggleStrikeAll, toggleTextColorAll, unsetAllMarks, } = createFormattingActions(editor);
|
|
198
167
|
const { currentAlignment, toggleTextAlign, idx: currentAlignmentIndex, keys: alignmentKeys, } = useTextAlign(editor);
|
|
199
168
|
const { selectedFont, toggleFont, toggleFontSize, toggleFontAll, toggleFontSizeAll, } = useFont(editor, fontSettings, fontStyleDropdownRef);
|
|
200
169
|
const { letterSpacingValue, lineHeightValue, letterSpacing, lineHeight, setLetterSpaceAll, setLineHeightAll, } = useSpacing(editor);
|
|
201
|
-
const { hyperlinkValue, setHyperlinkUrl, setHyperlinkUrlValue, removeHyperlink: removeHyperlinkFromComposable, applyHyperlinkToEditor, } = useHyperlink(editor);
|
|
202
|
-
const { shouldShow, tippyOptions } = useBubbleMenu(editor, isHyperlinkPopupOpen);
|
|
203
170
|
watch(() => props.styles.textAlign, (newAlignment) => {
|
|
204
171
|
if (newAlignment && newAlignment !== currentAlignment.value.alignment) {
|
|
205
172
|
skipStyleDetection(editor.chain().selectAll().setTextAlign(newAlignment)).run();
|
|
@@ -229,8 +196,8 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
229
196
|
});
|
|
230
197
|
// Update model when editor content changes
|
|
231
198
|
editor.on('update', () => {
|
|
232
|
-
const
|
|
233
|
-
emit('update:modelValue',
|
|
199
|
+
const html = editor.getHTML();
|
|
200
|
+
emit('update:modelValue', html);
|
|
234
201
|
});
|
|
235
202
|
editor.on('selectionUpdate', () => {
|
|
236
203
|
const textStyleAttributes = editor.getAttributes('textStyle');
|
|
@@ -443,9 +410,6 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
443
410
|
toggleTextAlign();
|
|
444
411
|
fontStyleChanges.textAlign = currentAlignment.value.alignment;
|
|
445
412
|
break;
|
|
446
|
-
case 'hyperlink':
|
|
447
|
-
setHyperlinkUrl(editorOption.value);
|
|
448
|
-
break;
|
|
449
413
|
}
|
|
450
414
|
syncContentSettings(fontStyleChanges);
|
|
451
415
|
};
|
|
@@ -477,55 +441,6 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
477
441
|
const onBlur = () => {
|
|
478
442
|
emit('blur');
|
|
479
443
|
};
|
|
480
|
-
const handleHyperlink = (action, data) => {
|
|
481
|
-
switch (action) {
|
|
482
|
-
case 'toggle':
|
|
483
|
-
isHyperlinkPopupOpen.value = !isHyperlinkPopupOpen.value;
|
|
484
|
-
if (isHyperlinkPopupOpen.value) {
|
|
485
|
-
if (data?.href && data?.text) {
|
|
486
|
-
setHyperlinkUrlValue(data.href);
|
|
487
|
-
markedText.value = data.text;
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
const linkAttrs = editor.getAttributes('link');
|
|
491
|
-
const selection = editor.state.selection;
|
|
492
|
-
if (linkAttrs.href) {
|
|
493
|
-
editor.commands.extendMarkRange('link');
|
|
494
|
-
const linkText = editor.state.doc.textBetween(selection.from, selection.to);
|
|
495
|
-
setHyperlinkUrlValue(linkAttrs.href);
|
|
496
|
-
markedText.value = linkText;
|
|
497
|
-
}
|
|
498
|
-
else {
|
|
499
|
-
const selectedText = selection.empty
|
|
500
|
-
? ''
|
|
501
|
-
: editor.state.doc.textBetween(selection.from, selection.to);
|
|
502
|
-
setHyperlinkUrlValue('');
|
|
503
|
-
markedText.value = selectedText;
|
|
504
|
-
}
|
|
505
|
-
}
|
|
506
|
-
editor.commands.focus(); // Hide bubble menu
|
|
507
|
-
}
|
|
508
|
-
break;
|
|
509
|
-
case 'apply':
|
|
510
|
-
const url = hyperlinkValue.value.value;
|
|
511
|
-
const text = markedText.value;
|
|
512
|
-
if (!url.trim()) {
|
|
513
|
-
isHyperlinkPopupOpen.value = false;
|
|
514
|
-
return;
|
|
515
|
-
}
|
|
516
|
-
const selection = editor.state?.selection;
|
|
517
|
-
const selectionRange = selection
|
|
518
|
-
? { from: selection.from, to: selection.to }
|
|
519
|
-
: undefined;
|
|
520
|
-
applyHyperlinkToEditor(url, text, selectionRange);
|
|
521
|
-
isHyperlinkPopupOpen.value = false;
|
|
522
|
-
break;
|
|
523
|
-
case 'remove':
|
|
524
|
-
removeHyperlinkFromComposable();
|
|
525
|
-
isHyperlinkPopupOpen.value = false;
|
|
526
|
-
break;
|
|
527
|
-
}
|
|
528
|
-
};
|
|
529
444
|
onBeforeUnmount(() => {
|
|
530
445
|
editor.destroy();
|
|
531
446
|
});
|
|
@@ -550,10 +465,5 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
550
465
|
setInitialStyleSettings,
|
|
551
466
|
copyGlobalStyleSettings,
|
|
552
467
|
unsetAllMarks,
|
|
553
|
-
handleHyperlink,
|
|
554
|
-
hyperlinkValue,
|
|
555
|
-
setHyperlinkUrlValue,
|
|
556
|
-
shouldShow,
|
|
557
|
-
tippyOptions,
|
|
558
468
|
};
|
|
559
469
|
};
|
|
@@ -3,7 +3,6 @@ export interface ButtonGroupBasicOption {
|
|
|
3
3
|
label: string;
|
|
4
4
|
isSelected: boolean;
|
|
5
5
|
dataAttribute?: string;
|
|
6
|
-
disabled?: boolean;
|
|
7
6
|
}
|
|
8
7
|
export type ButtonGroupOption = ButtonGroupBasicOption | {
|
|
9
8
|
label?: string;
|
|
@@ -14,5 +13,4 @@ export type ButtonGroupOption = ButtonGroupBasicOption | {
|
|
|
14
13
|
iconViewBox?: string;
|
|
15
14
|
iconSize?: string;
|
|
16
15
|
dataAttribute?: string;
|
|
17
|
-
disabled?: boolean;
|
|
18
16
|
};
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import type { ChainedCommands, Editor } from '@tiptap/vue-3';
|
|
2
|
-
import
|
|
2
|
+
import { EditorState, Transaction, Selection } from 'prosemirror-state';
|
|
3
3
|
import type { Content, TextStyleDeclaration, TextStyleType } from '../../brand-page';
|
|
4
4
|
import type { PageSettingsState } from '../../shared/page-settings/store';
|
|
5
5
|
import type { StyleSettingsState } from '../../shared/style-settings/store';
|
|
6
6
|
import type { Mark } from 'prosemirror-model';
|
|
7
|
-
import { type DOMPurify } from 'dompurify';
|
|
8
7
|
export declare const isStyleChanged: (tr: Transaction) => boolean;
|
|
9
8
|
export declare const skipStyleDetection: (chain: ChainedCommands, marks?: Mark[]) => ChainedCommands;
|
|
10
9
|
export declare const hasRTEContent: (content: string) => boolean;
|
|
@@ -13,16 +12,3 @@ export declare const switchAllContentToRTE: (uiPageSettingStore: PageSettingsSta
|
|
|
13
12
|
export declare const getUpdatedHTMLFromEditor: (externalEditor: Editor, contentText: string, newContentStyle: TextStyleDeclaration) => string;
|
|
14
13
|
export declare const buildInitialMarks: (state: EditorState, style: TextStyleDeclaration) => any[];
|
|
15
14
|
export declare const retainStyleOnEmptyLine: (editor: Editor, selection: Selection) => void;
|
|
16
|
-
export interface SanitizationResult {
|
|
17
|
-
sanitizedHtml: string;
|
|
18
|
-
removedElements: string[];
|
|
19
|
-
}
|
|
20
|
-
export declare const sanitiseClientSideRTE: (html: string) => SanitizationResult;
|
|
21
|
-
/**
|
|
22
|
-
* Sanitize HTML string using DOMPurify.
|
|
23
|
-
* Only allow tags and attributes that correspond to the enabled Tiptap extensions.
|
|
24
|
-
* Forbid dangerous tags and attributes.
|
|
25
|
-
* @param html HTML string to sanitize
|
|
26
|
-
* @returns sanitization result with sanitized HTML and removed elements info
|
|
27
|
-
*/
|
|
28
|
-
export declare const sanitizeRTEHtml: (html: string, domPurify: DOMPurify) => SanitizationResult;
|