-
Notifications
You must be signed in to change notification settings - Fork 146
/
Paste.ts
119 lines (108 loc) · 4.91 KB
/
Paste.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import convertPasteContentForSingleImage from './imageConverter/convertPasteContentForSingleImage';
import convertPastedContentForLI from './commonConverter/convertPastedContentForLI';
import convertPastedContentFromExcel from './excelConverter/convertPastedContentFromExcel';
import convertPastedContentFromOfficeOnline from './officeOnlineConverter/convertPastedContentFromOfficeOnline';
import convertPastedContentFromPowerPoint from './pptConverter/convertPastedContentFromPowerPoint';
import convertPastedContentFromWord from './wordConverter/convertPastedContentFromWord';
import handleLineMerge from './lineMerge/handleLineMerge';
import sanitizeHtmlColorsFromPastedContent from './sanitizeHtmlColorsFromPastedContent/sanitizeHtmlColorsFromPastedContent';
import sanitizeLinks from './sanitizeLinks/sanitizeLinks';
import { chainSanitizerCallback, getPasteSource } from 'roosterjs-editor-dom';
import { KnownPasteSourceType, PasteType, PluginEventType } from 'roosterjs-editor-types';
import type {
HtmlSanitizerOptions,
EditorPlugin,
IEditor,
PluginEvent,
} from 'roosterjs-editor-types';
const GOOGLE_SHEET_NODE_NAME = 'google-sheets-html-origin';
/**
* Paste plugin, handles BeforePaste event and reformat some special content, including:
* 1. Content copied from Word
* 2. Content copied from Excel
* 3. Content copied from Word Online or OneNote Online
*/
export default class Paste implements EditorPlugin {
private editor: IEditor | null = null;
/**
* Construct a new instance of Paste class
* @param unknownTagReplacement Replace solution of unknown tags, default behavior is to replace with SPAN
* @param convertSingleImageBody When enabled, if clipboard HTML contains a single image, we reuse the image without modifying the src attribute.
* When disabled, pasted image src attribute will use the dataUri from clipboard data -- By Default disabled.
*/
constructor(
private unknownTagReplacement: string = 'SPAN',
private convertSingleImageBody: boolean = false
) {}
/**
* Get a friendly name of this plugin
*/
getName() {
return 'Paste';
}
/**
* Initialize this plugin. This should only be called from Editor
* @param editor Editor instance
*/
initialize(editor: IEditor) {
this.editor = editor;
}
/**
* Dispose this plugin
*/
dispose() {
this.editor = null;
}
/**
* Handle events triggered from editor
* @param event PluginEvent object
*/
onPluginEvent(event: PluginEvent) {
if (this.editor && event.eventType == PluginEventType.BeforePaste) {
const { fragment, sanitizingOption } = event;
const trustedHTMLHandler = this.editor.getTrustedHTMLHandler();
switch (getPasteSource(event, this.convertSingleImageBody)) {
case KnownPasteSourceType.WordDesktop:
// Handle HTML copied from Word
convertPastedContentFromWord(event);
break;
case KnownPasteSourceType.ExcelDesktop:
case KnownPasteSourceType.ExcelOnline:
if (
event.pasteType === PasteType.Normal ||
event.pasteType === PasteType.MergeFormat
) {
// Handle HTML copied from Excel
convertPastedContentFromExcel(event, trustedHTMLHandler);
}
break;
case KnownPasteSourceType.PowerPointDesktop:
convertPastedContentFromPowerPoint(event, trustedHTMLHandler);
break;
case KnownPasteSourceType.WacComponents:
convertPastedContentFromOfficeOnline(fragment, sanitizingOption);
break;
case KnownPasteSourceType.GoogleSheets:
sanitizingOption.additionalTagReplacements[GOOGLE_SHEET_NODE_NAME] = '*';
break;
case KnownPasteSourceType.SingleImage:
convertPasteContentForSingleImage(event, trustedHTMLHandler);
break;
case KnownPasteSourceType.Default:
convertPastedContentForLI(fragment);
handleLineMerge(fragment);
break;
}
sanitizeLinks(sanitizingOption);
sanitizeHtmlColorsFromPastedContent(sanitizingOption);
sanitizeBlockStyles(sanitizingOption);
// Replace unknown tags with SPAN
sanitizingOption.unknownTagReplacement = this.unknownTagReplacement;
}
}
}
function sanitizeBlockStyles(sanitizingOption: Required<HtmlSanitizerOptions>) {
chainSanitizerCallback(sanitizingOption.cssStyleCallbacks, 'display', (value: string) => {
return value != 'flex'; // return whether we keep the style
});
}