refactor: refactor block2html in clipboard

This commit is contained in:
QiShaoXuan
2022-08-22 22:03:11 +08:00
parent 065f833564
commit 4b904ef762
27 changed files with 284 additions and 450 deletions
@@ -153,7 +153,7 @@ export class BlockHelper {
public async getEditableBlockPropertiesBySelectInfo(
block: AsyncBlock,
selectInfo: SelectBlock
selectInfo?: SelectBlock
) {
const properties = block.getProperties();
if (properties.text.value.length === 0) {
@@ -169,13 +169,13 @@ export class BlockHelper {
// Use deepClone method will throw incomprehensible error
let textValue = JSON.parse(JSON.stringify(originTextValue));
if (selectInfo.endInfo) {
if (selectInfo?.endInfo) {
textValue = textValue.slice(0, selectInfo.endInfo.arrayIndex + 1);
textValue[textValue.length - 1].text = text_value[
textValue.length - 1
].text.substring(0, selectInfo.endInfo.offset);
}
if (selectInfo.startInfo) {
if (selectInfo?.startInfo) {
textValue = textValue.slice(selectInfo.startInfo.arrayIndex);
textValue[0].text = textValue[0].text.substring(
selectInfo.startInfo.offset
@@ -1,31 +1,7 @@
import { Protocol, BlockFlavorKeys } from '@toeverything/datasource/db-service';
import { escape } from '@toeverything/utils';
import { Editor } from '../editor';
import { SelectBlock } from '../selection';
import { ClipBlockInfo } from './types';
class DefaultBlockParse {
public static html2block(el: Element): ClipBlockInfo[] | undefined | null {
const tag_name = el.tagName;
if (tag_name === 'DIV' || el instanceof Text) {
return el.textContent?.split('\n').map(str => {
const data = {
text: escape(str),
};
return {
type: 'text',
properties: {
text: { value: [data] },
},
children: [],
};
});
}
return null;
}
}
export default class ClipboardParse {
private editor: Editor;
private static block_types: BlockFlavorKeys[] = [
@@ -82,7 +58,7 @@ export default class ClipboardParse {
constructor(editor: Editor) {
this.editor = editor;
this.generate_html = this.generate_html.bind(this);
// this.generate_html = this.generate_html.bind(this);
this.parse_dom = this.parse_dom.bind(this);
}
// TODO: escape
@@ -152,55 +128,6 @@ export default class ClipboardParse {
return blocks;
}
public async generateHtml(): Promise<string> {
const select_info = await this.editor.selectionManager.getSelectInfo();
return await this.generate_html(select_info.blocks);
}
public async page2html(): Promise<string> {
const root_block_id = this.editor.getRootBlockId();
if (!root_block_id) {
return '';
}
const block_info = await this.get_select_info(root_block_id);
return await this.generate_html([block_info]);
}
private async get_select_info(blockId: string) {
const block = await this.editor.getBlockById(blockId);
if (!block) return null;
const block_info: SelectBlock = {
blockId: block.id,
children: [],
};
const children_ids = block.childrenIds;
for (let i = 0; i < children_ids.length; i++) {
block_info.children.push(
await this.get_select_info(children_ids[i])
);
}
return block_info;
}
private async generate_html(selectBlocks: SelectBlock[]): Promise<string> {
let result = '';
for (let i = 0; i < selectBlocks.length; i++) {
const sel_block = selectBlocks[i];
if (!sel_block || !sel_block.blockId) continue;
const block = await this.editor.getBlockById(sel_block.blockId);
if (!block) continue;
const block_utils = this.editor.getView(block.type);
const html = await block_utils.block2html(
block,
sel_block.children,
this.generate_html
);
result += html;
}
return result;
}
public dispose() {
this.editor = null;
}
@@ -1,5 +1,9 @@
import { Editor } from '../editor';
import { SelectBlock, SelectInfo } from '@toeverything/components/editor-core';
import {
AsyncBlock,
SelectBlock,
SelectInfo,
} from '@toeverything/components/editor-core';
import { ClipBlockInfo, OFFICE_CLIPBOARD_MIMETYPE } from './types';
import { Clip } from './clip';
@@ -83,4 +87,76 @@ export class ClipboardUtils {
})
);
}
async convertTextValue2HtmlBySelectInfo(
blockOrBlockId: AsyncBlock | string,
selectBlockInfo?: SelectBlock
) {
const block =
typeof blockOrBlockId === 'string'
? await this._editor.getBlockById(blockOrBlockId)
: blockOrBlockId;
const selectedProperties =
await this._editor.blockHelper.getEditableBlockPropertiesBySelectInfo(
block,
selectBlockInfo
);
return this._editor.blockHelper.convertTextValue2Html(
block.id,
selectedProperties.text.value
);
}
async convertBlock2HtmlBySelectInfos(
blockOrBlockId: AsyncBlock | string,
selectBlockInfos?: SelectBlock[]
) {
if (!selectBlockInfos) {
const block =
typeof blockOrBlockId === 'string'
? await this._editor.getBlockById(blockOrBlockId)
: blockOrBlockId;
const children = await block?.children();
return (
await Promise.all(
children.map(async childBlock => {
const blockView = this._editor.getView(childBlock.type);
return await blockView.block2html({
editor: this._editor,
block: childBlock,
});
})
)
).join('');
}
return (
await Promise.all(
selectBlockInfos.map(async selectBlockInfo => {
const block = await this._editor.getBlockById(
selectBlockInfo.blockId
);
const blockView = this._editor.getView(block.type);
return await blockView.block2html({
editor: this._editor,
block,
selectInfo: selectBlockInfo,
});
})
)
).join('');
}
async page2html() {
const rootBlockId = this._editor.getRootBlockId();
if (!rootBlockId) {
return '';
}
const rootBlock = await this._editor.getBlockById(rootBlockId);
const blockView = this._editor.getView(rootBlock.type);
return await blockView.block2html({
editor: this._editor,
block: rootBlock,
});
}
}
@@ -50,62 +50,38 @@ class Copy {
const textClip = await this._getTextClip();
clips.push(textClip);
// const htmlClip = await this._getHtmlClip();
// clips.push(htmlClip);
const htmlClip = await this._clipboardParse.generateHtml();
htmlClip &&
clips.push(new Clip(OFFICE_CLIPBOARD_MIMETYPE.HTML, htmlClip));
const htmlClip = await this._getHtmlClip();
clips.push(htmlClip);
// const htmlClip = await this._clipboardParse.generateHtml();
// htmlClip &&
// clips.push(new Clip(OFFICE_CLIPBOARD_MIMETYPE.HTML, htmlClip));
return clips;
}
// private async _getHtmlClip(): Promise<Clip> {
// const selectInfo: SelectInfo =
// await this._editor.selectionManager.getSelectInfo();
//
// if (selectInfo.type === 'Range') {
// const html = (
// await Promise.all(
// selectInfo.blocks.map(async selectBlockInfo => {
// const block = await this._editor.getBlockById(
// selectBlockInfo.blockId
// );
// const blockView = this._editor.getView(block.type);
// const block2html = await blockView.block2html({
// editor: this._editor,
// block,
// selectInfo: selectBlockInfo,
// });
//
// if (
// await this._editor.blockHelper.isBlockEditable(
// block
// )
// ) {
// const selectedProperties =
// await this._editor.blockHelper.getEditableBlockPropertiesBySelectInfo(
// block,
// selectBlockInfo
// );
//
// return (
// block2html ||
// this._editor.blockHelper.convertTextValue2Html(
// block.id,
// selectedProperties.text.value
// )
// );
// }
//
// return block2html;
// })
// )
// ).join('');
// console.log('html', html);
// }
//
// return new Clip(OFFICE_CLIPBOARD_MIMETYPE.HTML, 'blockText');
// }
private async _getHtmlClip(): Promise<Clip> {
const selectInfo: SelectInfo =
await this._editor.selectionManager.getSelectInfo();
const htmlStr = (
await Promise.all(
selectInfo.blocks.map(async selectBlockInfo => {
const block = await this._editor.getBlockById(
selectBlockInfo.blockId
);
const blockView = this._editor.getView(block.type);
return await blockView.block2html({
editor: this._editor,
block,
selectInfo: selectBlockInfo,
});
})
)
).join('');
return new Clip(OFFICE_CLIPBOARD_MIMETYPE.HTML, htmlStr);
}
private async _getAffineClip(): Promise<Clip> {
const selectInfo: SelectInfo =
@@ -502,13 +502,7 @@ export class Editor implements Virgo {
}
public async page2html(): Promise<string> {
return '';
// const parse = this.clipboard?.getClipboardParse();
// if (!parse) {
// return '';
// }
// const html_str = await parse.page2html();
// return html_str;
return this.clipboard?.clipboardUtils?.page2html?.();
}
dispose() {
@@ -8,5 +8,5 @@ export { Editor as BlockEditor } from './editor';
export * from './selection';
export { BlockDropPlacement, HookType, GroupDirection } from './types';
export type { Plugin, PluginCreator, PluginHooks, Virgo } from './types';
export { BaseView, getTextHtml } from './views/base-view';
export { BaseView } from './views/base-view';
export type { ChildrenView, CreateView } from './views/base-view';
@@ -135,13 +135,6 @@ export abstract class BaseView {
return null;
}
async block2html(
block: AsyncBlock,
children: SelectBlock[],
generateHtml: (el: any[]) => Promise<string>
): Promise<string> {
return '';
}
async block2Text(
block: AsyncBlock,
// The selectInfo parameter is not passed when the block is selected in ful, the selectInfo.type is Range
@@ -151,45 +144,12 @@ export abstract class BaseView {
}
// TODO: Try using new methods
// async block2html2(props: {
// editor: Editor;
// block: AsyncBlock;
// // The selectInfo parameter is not passed when the block is selected in ful, the selectInfo.type is Range
// selectInfo?: SelectBlock;
// }) {
// return '';
// }
async block2html(props: {
editor: Editor;
block: AsyncBlock;
// The selectInfo parameter is not passed when the block is selected in ful, the selectInfo.type is Range
selectInfo?: SelectBlock;
}) {
return '';
}
}
export const getTextHtml = (block: AsyncBlock) => {
const generate = (textList: any[]) => {
let content = '';
textList.forEach(text_obj => {
let text = text_obj.text || '';
if (text_obj.bold) {
text = `<strong>${text}</strong>`;
}
if (text_obj.italic) {
text = `<em>${text}</em>`;
}
if (text_obj.underline) {
text = `<u>${text}</u>`;
}
if (text_obj.inlinecode) {
text = `<code>${text}</code>`;
}
if (text_obj.strikethrough) {
text = `<s>${text}</s>`;
}
if (text_obj.type === 'link') {
text = `<a href='${text_obj.url}'>${generate(
text_obj.children
)}</a>`;
}
content += text;
});
return content;
};
const text_list: any[] = block.getProperty('text').value;
return generate(text_list);
};