feat: add clipboardEvent2Blocks for white board to paste

This commit is contained in:
QiShaoXuan
2022-08-24 16:39:29 +08:00
parent ce0c021c5e
commit c20288ce76
3 changed files with 30 additions and 39 deletions
@@ -10,7 +10,6 @@ export class Clipboard {
private _clipboardEventDispatcher: ClipboardEventDispatcher; private _clipboardEventDispatcher: ClipboardEventDispatcher;
private _copy: Copy; private _copy: Copy;
private _paste: Paste; private _paste: Paste;
private readonly _supportMarkdownPaste = true;
public clipboardUtils: ClipboardUtils; public clipboardUtils: ClipboardUtils;
private _clipboardTarget: HTMLElement; private _clipboardTarget: HTMLElement;
@@ -19,7 +18,7 @@ export class Clipboard {
this._clipboardTarget = clipboardTarget; this._clipboardTarget = clipboardTarget;
this._copy = new Copy(editor); this._copy = new Copy(editor);
this._paste = new Paste(editor, this._supportMarkdownPaste); this._paste = new Paste(editor);
this._clipboardEventDispatcher = new ClipboardEventDispatcher( this._clipboardEventDispatcher = new ClipboardEventDispatcher(
editor, editor,
@@ -49,7 +48,9 @@ export class Clipboard {
return this._clipboardTarget; return this._clipboardTarget;
} }
setEditorContainer(container: HTMLElement) {} public clipboardEvent2Blocks(e: ClipboardEvent) {
return this._paste.clipboardEvent2Blocks(e);
}
public dispose() { public dispose() {
this._clipboardEventDispatcher.dispose(this.clipboardTarget); this._clipboardEventDispatcher.dispose(this.clipboardTarget);
@@ -147,14 +147,14 @@ export class ClipboardUtils {
).join(''); ).join('');
} }
async convertHTMLString2Blocks(html: string) { async convertHTMLString2Blocks(html: string): Promise<ClipBlockInfo[]> {
const htmlEl = document.createElement('html'); const htmlEl = document.createElement('html');
htmlEl.innerHTML = html; htmlEl.innerHTML = html;
htmlEl.querySelector('head')?.remove(); htmlEl.querySelector('head')?.remove();
return this.convertHtml2Block(htmlEl); return this.convertHtml2Blocks(htmlEl);
} }
async convertHtml2Block(element: Element): Promise<ClipBlockInfo[]> { async convertHtml2Blocks(element: Element): Promise<ClipBlockInfo[]> {
const editableViews = this._editor.getEditableViews(); const editableViews = this._editor.getEditableViews();
// 如果block能够捕捉htmlElement则返回block的html2block // 如果block能够捕捉htmlElement则返回block的html2block
const [clipBlockInfos] = ( const [clipBlockInfos] = (
@@ -174,7 +174,7 @@ export class ClipboardUtils {
return ( return (
await Promise.all( await Promise.all(
Array.from(element.children).map(async childElement => { Array.from(element.children).map(async childElement => {
const clipBlockInfos = await this.convertHtml2Block( const clipBlockInfos = await this.convertHtml2Blocks(
childElement childElement
); );
@@ -19,13 +19,10 @@ type TextValueItem = {
export class Paste { export class Paste {
private _editor: Editor; private _editor: Editor;
private _markdownParse: MarkdownParser; private _markdownParse: MarkdownParser;
private readonly _supportMarkdownPaste: boolean = true;
private _utils: ClipboardUtils; private _utils: ClipboardUtils;
constructor(editor: Editor, supportMarkdownPaste?: boolean) { constructor(editor: Editor) {
this._markdownParse = new MarkdownParser(); this._markdownParse = new MarkdownParser();
this._editor = editor; this._editor = editor;
this._supportMarkdownPaste =
supportMarkdownPaste ?? this._supportMarkdownPaste;
this._utils = new ClipboardUtils(editor); this._utils = new ClipboardUtils(editor);
this.handlePaste = this.handlePaste.bind(this); this.handlePaste = this.handlePaste.bind(this);
@@ -37,17 +34,21 @@ export class Paste {
OFFICE_CLIPBOARD_MIMETYPE.TEXT, OFFICE_CLIPBOARD_MIMETYPE.TEXT,
]; ];
public handlePaste(e: ClipboardEvent) { public async handlePaste(e: ClipboardEvent) {
e.stopPropagation(); e.stopPropagation();
const clipboardData = e.clipboardData; const blocks = await this.clipboardEvent2Blocks(e);
await this._insertBlocks(blocks);
}
public async clipboardEvent2Blocks(e: ClipboardEvent) {
const clipboardData = e.clipboardData;
const isPureFile = Paste._isPureFileInClipboard(clipboardData); const isPureFile = Paste._isPureFileInClipboard(clipboardData);
if (isPureFile) { if (isPureFile) {
this._pasteFile(clipboardData); return this._file2Blocks(clipboardData);
} else {
this._pasteContent(clipboardData);
} }
return this._clipboardData2Blocks(clipboardData);
} }
// Get the most needed clipboard data based on `_optimalMimeTypes` order // Get the most needed clipboard data based on `_optimalMimeTypes` order
public getOptimalClip(clipboardData: ClipboardEvent['clipboardData']) { public getOptimalClip(clipboardData: ClipboardEvent['clipboardData']) {
@@ -66,43 +67,41 @@ export class Paste {
return null; return null;
} }
private _pasteContent(clipboardData: ClipboardEvent['clipboardData']) { private async _clipboardData2Blocks(
clipboardData: ClipboardEvent['clipboardData']
): Promise<ClipBlockInfo[]> {
const optimalClip = this.getOptimalClip(clipboardData); const optimalClip = this.getOptimalClip(clipboardData);
if ( if (
optimalClip?.type === optimalClip?.type ===
OFFICE_CLIPBOARD_MIMETYPE.DOCS_DOCUMENT_SLICE_CLIP_WRAPPED OFFICE_CLIPBOARD_MIMETYPE.DOCS_DOCUMENT_SLICE_CLIP_WRAPPED
) { ) {
return this._firePasteEditAction(optimalClip.data); const clipInfo: InnerClipInfo = JSON.parse(optimalClip.data);
return clipInfo.data;
} }
const textClipData = escape( const textClipData = escape(
clipboardData.getData(OFFICE_CLIPBOARD_MIMETYPE.TEXT) clipboardData.getData(OFFICE_CLIPBOARD_MIMETYPE.TEXT)
); );
const shouldConvertMarkdown = const shouldConvertMarkdown =
this._supportMarkdownPaste &&
this._markdownParse.checkIfTextContainsMd(textClipData); this._markdownParse.checkIfTextContainsMd(textClipData);
if ( if (
optimalClip?.type === OFFICE_CLIPBOARD_MIMETYPE.HTML && optimalClip?.type === OFFICE_CLIPBOARD_MIMETYPE.HTML &&
!shouldConvertMarkdown !shouldConvertMarkdown
) { ) {
return this._pasteHtml(optimalClip.data); return this._utils.convertHTMLString2Blocks(optimalClip.data);
} }
if (shouldConvertMarkdown) { if (shouldConvertMarkdown) {
const md2html = marked.parse(textClipData); const md2html = marked.parse(textClipData);
return this._pasteHtml(md2html); return this._utils.convertHTMLString2Blocks(md2html);
} }
return this._pasteText(textClipData); return this._utils.textToBlock(textClipData);
} }
private async _firePasteEditAction(clipboardData: string) { private async _file2Blocks(clipboardData: any): Promise<ClipBlockInfo[]> {
const clipInfo: InnerClipInfo = JSON.parse(clipboardData);
clipInfo && this._insertBlocks(clipInfo.data);
}
private async _pasteFile(clipboardData: any) {
const file = Paste._getImageFile(clipboardData); const file = Paste._getImageFile(clipboardData);
if (file) { if (file) {
const result = await services.api.file.create({ const result = await services.api.file.create({
@@ -121,8 +120,9 @@ export class Paste {
}, },
children: [] as ClipBlockInfo[], children: [] as ClipBlockInfo[],
}; };
await this._insertBlocks([blockInfo]); return [blockInfo];
} }
return [];
} }
private static _isPureFileInClipboard(clipboardData: DataTransfer) { private static _isPureFileInClipboard(clipboardData: DataTransfer) {
const types = clipboardData.types; const types = clipboardData.types;
@@ -423,16 +423,6 @@ export class Paste {
); );
} }
private async _pasteHtml(clipData: string) {
const block2 = await this._utils.convertHTMLString2Blocks(clipData);
await this._insertBlocks(block2);
}
private async _pasteText(clipData: string) {
const blocks = this._utils.textToBlock(clipData);
await this._insertBlocks(blocks);
}
private static _getImageFile(clipboardData: any) { private static _getImageFile(clipboardData: any) {
const files = clipboardData.files; const files = clipboardData.files;
if (files && files[0] && files[0].type.indexOf('image') > -1) { if (files && files[0] && files[0].type.indexOf('image') > -1) {