@designcrowd/library.brand-page 5.10.6-sanitise-hyperlink-16 → 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/extensions/MaxLength.js +3 -3
- 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 +22 -109
- 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 +22396 -24523
- 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/extensions/MaxLength.ts +15 -4
- 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 +24 -160
- 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/common/SideBarSettingsHeader.vue +1 -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 -227
- 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,
|
|
@@ -42,7 +42,7 @@ export const MaxLength = Extension.create({
|
|
|
42
42
|
const text = node.text ?? '';
|
|
43
43
|
const piece = text.slice(0, remaining);
|
|
44
44
|
if (piece.length > 0) {
|
|
45
|
-
nodes.push(node.type.schema.text(piece, node.marks));
|
|
45
|
+
nodes.push(node.type.create(node.attrs, node.type.schema.text(piece), node.marks));
|
|
46
46
|
remaining -= piece.length;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
@@ -64,7 +64,7 @@ export const MaxLength = Extension.create({
|
|
|
64
64
|
const piece = (subNode.text ?? '').slice(0, remaining);
|
|
65
65
|
if (piece.length === 0)
|
|
66
66
|
return null;
|
|
67
|
-
const newText = subNode.type.schema.text(piece, subNode.marks);
|
|
67
|
+
const newText = subNode.type.create(subNode.attrs, subNode.type.schema.text(piece), subNode.marks);
|
|
68
68
|
remaining -= piece.length;
|
|
69
69
|
return newText;
|
|
70
70
|
}
|
|
@@ -77,7 +77,7 @@ export const MaxLength = Extension.create({
|
|
|
77
77
|
});
|
|
78
78
|
if (children.length === 0)
|
|
79
79
|
return null;
|
|
80
|
-
return subNode.
|
|
80
|
+
return subNode.type.create(subNode.attrs, Fragment.fromArray(children), subNode.marks);
|
|
81
81
|
}
|
|
82
82
|
return null;
|
|
83
83
|
};
|
|
@@ -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,21 +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';
|
|
23
|
+
import { DOMSerializer } from 'prosemirror-model';
|
|
24
24
|
import { AllSelection } from 'prosemirror-state';
|
|
25
25
|
import { MaxLength } from './extensions/MaxLength';
|
|
26
|
-
import { AutoLink } from './extensions/AutoLink';
|
|
27
|
-
import { useHyperlink } from './hyperlink';
|
|
28
|
-
import { useBubbleMenu } from './bubbleMenu';
|
|
29
26
|
export const useExternalRichTextEditor = () => {
|
|
30
27
|
const externalEditor = new Editor({
|
|
31
28
|
editable: false,
|
|
@@ -48,19 +45,13 @@ export const useExternalRichTextEditor = () => {
|
|
|
48
45
|
Highlight.configure({
|
|
49
46
|
multicolor: true,
|
|
50
47
|
}),
|
|
51
|
-
Link.configure({
|
|
52
|
-
openOnClick: false,
|
|
53
|
-
defaultProtocol: 'https',
|
|
54
|
-
autolink: true,
|
|
55
|
-
}),
|
|
56
|
-
AutoLink,
|
|
57
48
|
],
|
|
58
49
|
});
|
|
59
50
|
return {
|
|
60
51
|
externalEditor,
|
|
61
52
|
};
|
|
62
53
|
};
|
|
63
|
-
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) => {
|
|
64
55
|
const editor = new Editor({
|
|
65
56
|
content: model.value ?? '',
|
|
66
57
|
editable: !props.readOnly,
|
|
@@ -87,12 +78,6 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
87
78
|
placeholder: props.placeholder,
|
|
88
79
|
}),
|
|
89
80
|
MaxLength.configure({ maxLength: props.maxLength }),
|
|
90
|
-
Link.configure({
|
|
91
|
-
openOnClick: false,
|
|
92
|
-
defaultProtocol: 'https',
|
|
93
|
-
autolink: true,
|
|
94
|
-
}),
|
|
95
|
-
AutoLink,
|
|
96
81
|
],
|
|
97
82
|
editorProps: {
|
|
98
83
|
handleDOMEvents: {
|
|
@@ -115,20 +100,23 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
115
100
|
return false;
|
|
116
101
|
},
|
|
117
102
|
copy(view, event) {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
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
|
|
122
109
|
const styleData = JSON.stringify(props.styles);
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
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);
|
|
132
120
|
return true;
|
|
133
121
|
},
|
|
134
122
|
paste(view, event) {
|
|
@@ -171,32 +159,14 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
171
159
|
dispatch(tr);
|
|
172
160
|
return true;
|
|
173
161
|
},
|
|
174
|
-
click(view, event) {
|
|
175
|
-
if (isHyperlinkPopupOpen?.value)
|
|
176
|
-
return false;
|
|
177
|
-
const target = event.target;
|
|
178
|
-
const linkElement = target.closest('a');
|
|
179
|
-
if (linkElement) {
|
|
180
|
-
const pos = view.posAtDOM(linkElement, 0);
|
|
181
|
-
if (pos !== null) {
|
|
182
|
-
editor.commands.setTextSelection(pos);
|
|
183
|
-
editor.commands.extendMarkRange('link');
|
|
184
|
-
return true; // Prevent default
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
return false;
|
|
188
|
-
},
|
|
189
162
|
},
|
|
190
163
|
},
|
|
191
164
|
});
|
|
192
|
-
window.editor = editor;
|
|
193
165
|
const contentSettingStore = useUiContentSettingsStore();
|
|
194
166
|
const { toggleBold, toggleItalic, toggleUnderline, toggleStrike, toggleTextColor, toggleBackgroundColor, toggleBoldAll, toggleItalicAll, toggleUnderlineAll, toggleStrikeAll, toggleTextColorAll, unsetAllMarks, } = createFormattingActions(editor);
|
|
195
167
|
const { currentAlignment, toggleTextAlign, idx: currentAlignmentIndex, keys: alignmentKeys, } = useTextAlign(editor);
|
|
196
168
|
const { selectedFont, toggleFont, toggleFontSize, toggleFontAll, toggleFontSizeAll, } = useFont(editor, fontSettings, fontStyleDropdownRef);
|
|
197
169
|
const { letterSpacingValue, lineHeightValue, letterSpacing, lineHeight, setLetterSpaceAll, setLineHeightAll, } = useSpacing(editor);
|
|
198
|
-
const { hyperlinkValue, setHyperlinkUrl, setHyperlinkUrlValue, removeHyperlink: removeHyperlinkFromComposable, applyHyperlinkToEditor, } = useHyperlink(editor);
|
|
199
|
-
const { shouldShow, tippyOptions } = useBubbleMenu(editor, isHyperlinkPopupOpen);
|
|
200
170
|
watch(() => props.styles.textAlign, (newAlignment) => {
|
|
201
171
|
if (newAlignment && newAlignment !== currentAlignment.value.alignment) {
|
|
202
172
|
skipStyleDetection(editor.chain().selectAll().setTextAlign(newAlignment)).run();
|
|
@@ -226,8 +196,8 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
226
196
|
});
|
|
227
197
|
// Update model when editor content changes
|
|
228
198
|
editor.on('update', () => {
|
|
229
|
-
const
|
|
230
|
-
emit('update:modelValue',
|
|
199
|
+
const html = editor.getHTML();
|
|
200
|
+
emit('update:modelValue', html);
|
|
231
201
|
});
|
|
232
202
|
editor.on('selectionUpdate', () => {
|
|
233
203
|
const textStyleAttributes = editor.getAttributes('textStyle');
|
|
@@ -440,9 +410,6 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
440
410
|
toggleTextAlign();
|
|
441
411
|
fontStyleChanges.textAlign = currentAlignment.value.alignment;
|
|
442
412
|
break;
|
|
443
|
-
case 'hyperlink':
|
|
444
|
-
setHyperlinkUrl(editorOption.value);
|
|
445
|
-
break;
|
|
446
413
|
}
|
|
447
414
|
syncContentSettings(fontStyleChanges);
|
|
448
415
|
};
|
|
@@ -474,55 +441,6 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
474
441
|
const onBlur = () => {
|
|
475
442
|
emit('blur');
|
|
476
443
|
};
|
|
477
|
-
const handleHyperlink = (action, data) => {
|
|
478
|
-
switch (action) {
|
|
479
|
-
case 'toggle':
|
|
480
|
-
isHyperlinkPopupOpen.value = !isHyperlinkPopupOpen.value;
|
|
481
|
-
if (isHyperlinkPopupOpen.value) {
|
|
482
|
-
if (data?.href && data?.text) {
|
|
483
|
-
setHyperlinkUrlValue(data.href);
|
|
484
|
-
markedText.value = data.text;
|
|
485
|
-
}
|
|
486
|
-
else {
|
|
487
|
-
const linkAttrs = editor.getAttributes('link');
|
|
488
|
-
const selection = editor.state.selection;
|
|
489
|
-
if (linkAttrs.href) {
|
|
490
|
-
editor.commands.extendMarkRange('link');
|
|
491
|
-
const linkText = editor.state.doc.textBetween(selection.from, selection.to);
|
|
492
|
-
setHyperlinkUrlValue(linkAttrs.href);
|
|
493
|
-
markedText.value = linkText;
|
|
494
|
-
}
|
|
495
|
-
else {
|
|
496
|
-
const selectedText = selection.empty
|
|
497
|
-
? ''
|
|
498
|
-
: editor.state.doc.textBetween(selection.from, selection.to);
|
|
499
|
-
setHyperlinkUrlValue('');
|
|
500
|
-
markedText.value = selectedText;
|
|
501
|
-
}
|
|
502
|
-
}
|
|
503
|
-
editor.commands.focus(); // Hide bubble menu
|
|
504
|
-
}
|
|
505
|
-
break;
|
|
506
|
-
case 'apply':
|
|
507
|
-
const url = hyperlinkValue.value.value;
|
|
508
|
-
const text = markedText.value;
|
|
509
|
-
if (!url.trim()) {
|
|
510
|
-
isHyperlinkPopupOpen.value = false;
|
|
511
|
-
return;
|
|
512
|
-
}
|
|
513
|
-
const selection = editor.state?.selection;
|
|
514
|
-
const selectionRange = selection
|
|
515
|
-
? { from: selection.from, to: selection.to }
|
|
516
|
-
: undefined;
|
|
517
|
-
applyHyperlinkToEditor(url, text, selectionRange);
|
|
518
|
-
isHyperlinkPopupOpen.value = false;
|
|
519
|
-
break;
|
|
520
|
-
case 'remove':
|
|
521
|
-
removeHyperlinkFromComposable();
|
|
522
|
-
isHyperlinkPopupOpen.value = false;
|
|
523
|
-
break;
|
|
524
|
-
}
|
|
525
|
-
};
|
|
526
444
|
onBeforeUnmount(() => {
|
|
527
445
|
editor.destroy();
|
|
528
446
|
});
|
|
@@ -547,10 +465,5 @@ export const useRichTextEditor = (model, props, emit, fontSettings, fontStyleDro
|
|
|
547
465
|
setInitialStyleSettings,
|
|
548
466
|
copyGlobalStyleSettings,
|
|
549
467
|
unsetAllMarks,
|
|
550
|
-
handleHyperlink,
|
|
551
|
-
hyperlinkValue,
|
|
552
|
-
setHyperlinkUrlValue,
|
|
553
|
-
shouldShow,
|
|
554
|
-
tippyOptions,
|
|
555
468
|
};
|
|
556
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;
|