From 4b904ef76204655e6253deabfab22d47d98feec4 Mon Sep 17 00:00:00 2001 From: QiShaoXuan Date: Mon, 22 Aug 2022 22:03:11 +0800 Subject: [PATCH] refactor: refactor block2html in clipboard --- libs/components/affine-board/src/Board.tsx | 13 ++- .../common/src/lib/text/slate-utils.ts | 2 +- .../editor-blocks/src/blocks/bullet/index.ts | 30 ++----- .../editor-blocks/src/blocks/code/index.ts | 28 ++----- .../editor-blocks/src/blocks/divider/index.ts | 10 +-- .../src/blocks/embed-link/index.ts | 12 +-- .../editor-blocks/src/blocks/figma/index.ts | 12 +-- .../editor-blocks/src/blocks/file/index.ts | 23 +++--- .../editor-blocks/src/blocks/group/Group.tsx | 19 +++-- .../src/blocks/groupDvider/index.ts | 10 +-- .../editor-blocks/src/blocks/image/index.ts | 26 +++--- .../src/blocks/numbered/index.ts | 29 ++----- .../editor-blocks/src/blocks/page/index.ts | 37 ++++----- .../src/blocks/text/QuoteBlock.tsx | 33 +++----- .../src/blocks/text/TextBlock.tsx | 51 +++--------- .../editor-blocks/src/blocks/todo/index.ts | 28 ++----- .../editor-blocks/src/blocks/youtube/index.ts | 12 +-- .../src/utils/commonBlockClip.ts | 30 +++++++ .../src/editor/block/block-helper.ts | 6 +- .../src/editor/clipboard/clipboard-parse.ts | 75 +---------------- .../src/editor/clipboard/clipboardUtils.ts | 78 +++++++++++++++++- .../editor-core/src/editor/clipboard/copy.ts | 80 +++++++------------ .../editor-core/src/editor/editor.ts | 8 +- .../editor-core/src/editor/index.ts | 2 +- .../editor-core/src/editor/views/base-view.ts | 56 ++----------- .../layout/src/header/PageSettingPortal.tsx | 8 +- .../Settings/util/handle-export.ts | 16 ++-- 27 files changed, 284 insertions(+), 450 deletions(-) create mode 100644 libs/components/editor-blocks/src/utils/commonBlockClip.ts diff --git a/libs/components/affine-board/src/Board.tsx b/libs/components/affine-board/src/Board.tsx index 4e99d6bbb0..5730649545 100644 --- a/libs/components/affine-board/src/Board.tsx +++ b/libs/components/affine-board/src/Board.tsx @@ -5,10 +5,7 @@ import { getSession } from '@toeverything/components/board-sessions'; import { deepCopy, TldrawApp } from '@toeverything/components/board-state'; import { tools } from '@toeverything/components/board-tools'; import { TDShapeType } from '@toeverything/components/board-types'; -import { - RecastBlockProvider, - getClipDataOfBlocksById, -} from '@toeverything/components/editor-core'; +import { RecastBlockProvider } from '@toeverything/components/editor-core'; import { services } from '@toeverything/datasource/db-service'; import { AsyncBlock, BlockEditor } from '@toeverything/framework/virgo'; import { useEffect, useState } from 'react'; @@ -70,10 +67,10 @@ const AffineBoard = ({ set_app(app); }, async onCopy(e, groupIds) { - const clip = await getClipDataOfBlocksById( - editor, - groupIds - ); + const clip = + await editor.clipboard.clipboardUtils.getClipDataOfBlocksById( + groupIds + ); e.clipboardData?.setData( clip.getMimeType(), diff --git a/libs/components/common/src/lib/text/slate-utils.ts b/libs/components/common/src/lib/text/slate-utils.ts index fb183a7c35..160f1a416b 100644 --- a/libs/components/common/src/lib/text/slate-utils.ts +++ b/libs/components/common/src/lib/text/slate-utils.ts @@ -993,7 +993,7 @@ class SlateUtils { textValue.children )}`; } - return `${text}>`; + return `${text}`; } public getStartSelection() { diff --git a/libs/components/editor-blocks/src/blocks/bullet/index.ts b/libs/components/editor-blocks/src/blocks/bullet/index.ts index 58360954ce..1577263af3 100644 --- a/libs/components/editor-blocks/src/blocks/bullet/index.ts +++ b/libs/components/editor-blocks/src/blocks/bullet/index.ts @@ -1,18 +1,10 @@ -import { - AsyncBlock, - BaseView, - CreateView, - SelectBlock, - getTextHtml, -} from '@toeverything/framework/virgo'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; -// import { withTreeViewChildren } from '../../utils/with-tree-view-children'; +import { AsyncBlock, BaseView } from '@toeverything/framework/virgo'; +import { Protocol } from '@toeverything/datasource/db-service'; import { defaultBulletProps, BulletView } from './BulletView'; -import { IndentWrapper } from '../../components/IndentWrapper'; - +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class BulletBlock extends BaseView { public type = Protocol.Block.Type.bullet; @@ -71,13 +63,7 @@ export class BulletBlock extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `
  • ${content}
`; + override async block2html(props: Block2HtmlProps) { + return `
  • ${await commonBlock2HtmlContent(props)}
`; } } diff --git a/libs/components/editor-blocks/src/blocks/code/index.ts b/libs/components/editor-blocks/src/blocks/code/index.ts index 1fc84f1df8..a204779656 100644 --- a/libs/components/editor-blocks/src/blocks/code/index.ts +++ b/libs/components/editor-blocks/src/blocks/code/index.ts @@ -1,16 +1,10 @@ -import { - BaseView, - AsyncBlock, - CreateView, - SelectBlock, - getTextHtml, -} from '@toeverything/framework/virgo'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; +import { BaseView, AsyncBlock } from '@toeverything/framework/virgo'; +import { Protocol } from '@toeverything/datasource/db-service'; import { CodeView } from './CodeView'; -import { ComponentType } from 'react'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class CodeBlock extends BaseView { type = Protocol.Block.Type.code; @@ -62,13 +56,7 @@ export class CodeBlock extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `${content}`; + override async block2html(props: Block2HtmlProps) { + return `${await commonBlock2HtmlContent(props)}`; } } diff --git a/libs/components/editor-blocks/src/blocks/divider/index.ts b/libs/components/editor-blocks/src/blocks/divider/index.ts index 6d67611cda..eb4615963c 100644 --- a/libs/components/editor-blocks/src/blocks/divider/index.ts +++ b/libs/components/editor-blocks/src/blocks/divider/index.ts @@ -5,6 +5,7 @@ import { } from '@toeverything/framework/virgo'; import { Protocol } from '@toeverything/datasource/db-service'; import { DividerView } from './divider-view'; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class DividerBlock extends BaseView { type = Protocol.Block.Type.divider; @@ -28,12 +29,7 @@ export class DividerBlock extends BaseView { return null; } - - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - return `
`; + override async block2html(props: Block2HtmlProps) { + return `
`; } } diff --git a/libs/components/editor-blocks/src/blocks/embed-link/index.ts b/libs/components/editor-blocks/src/blocks/embed-link/index.ts index 731ae801d6..7674c71c3e 100644 --- a/libs/components/editor-blocks/src/blocks/embed-link/index.ts +++ b/libs/components/editor-blocks/src/blocks/embed-link/index.ts @@ -5,6 +5,7 @@ import { } from '@toeverything/framework/virgo'; import { Protocol } from '@toeverything/datasource/db-service'; import { EmbedLinkView } from './EmbedLinkView'; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class EmbedLinkBlock extends BaseView { public override selectable = true; @@ -35,13 +36,8 @@ export class EmbedLinkBlock extends BaseView { return null; } - - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - const figma_url = block.getProperty('embedLink')?.value; - return `

${figma_url}

`; + override async block2html({ block }: Block2HtmlProps) { + const url = block.getProperty('embedLink')?.value; + return `

${url}

`; } } diff --git a/libs/components/editor-blocks/src/blocks/figma/index.ts b/libs/components/editor-blocks/src/blocks/figma/index.ts index 3ed44c9c85..652abfbc1d 100644 --- a/libs/components/editor-blocks/src/blocks/figma/index.ts +++ b/libs/components/editor-blocks/src/blocks/figma/index.ts @@ -5,6 +5,7 @@ import { SelectBlock, } from '@toeverything/framework/virgo'; import { FigmaView } from './FigmaView'; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class FigmaBlock extends BaseView { public override selectable = true; @@ -41,13 +42,8 @@ export class FigmaBlock extends BaseView { return null; } - - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - const figma_url = block.getProperty('embedLink')?.value; - return `

${figma_url}

`; + override async block2html({ block }: Block2HtmlProps) { + const figmaUrl = block.getProperty('embedLink')?.value; + return `

${figmaUrl}

`; } } diff --git a/libs/components/editor-blocks/src/blocks/file/index.ts b/libs/components/editor-blocks/src/blocks/file/index.ts index e55eed7721..42c2bee1f6 100644 --- a/libs/components/editor-blocks/src/blocks/file/index.ts +++ b/libs/components/editor-blocks/src/blocks/file/index.ts @@ -9,25 +9,22 @@ import { services, } from '@toeverything/datasource/db-service'; import { FileView } from './FileView'; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class FileBlock extends BaseView { public override selectable = true; public override activatable = false; type = Protocol.Block.Type.file; View = FileView; + override async block2html({ block }: Block2HtmlProps) { + const fileProperty = block.getProperty('file'); + const fileId = fileProperty?.value; + const fileInfo = fileId + ? await services.api.file.get(fileId, block.workspace) + : null; - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - const file_property = - block.getProperty('file') || ({} as FileColumnValue); - const file_id = file_property.value; - let file_info = null; - if (file_id) { - file_info = await services.api.file.get(file_id, block.workspace); - } - return `

${file_property?.name}

`; + return fileInfo + ? `

${fileProperty?.name}

` + : ''; } } diff --git a/libs/components/editor-blocks/src/blocks/group/Group.tsx b/libs/components/editor-blocks/src/blocks/group/Group.tsx index ac194d7eab..b5fdcac58c 100644 --- a/libs/components/editor-blocks/src/blocks/group/Group.tsx +++ b/libs/components/editor-blocks/src/blocks/group/Group.tsx @@ -6,6 +6,10 @@ import { SelectBlock, } from '@toeverything/framework/virgo'; import { GroupView } from './GroupView'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class Group extends BaseView { public override selectable = true; @@ -25,13 +29,12 @@ export class Group extends BaseView { override async onCreate(block: AsyncBlock): Promise { return block; } - - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - const content = await generateHtml(children); - return `
${content}
`; + override async block2html({ editor, selectInfo, block }: Block2HtmlProps) { + const childrenHtml = + await editor.clipboard.clipboardUtils.convertBlock2HtmlBySelectInfos( + block, + selectInfo?.children + ); + return `
${childrenHtml}`; } } diff --git a/libs/components/editor-blocks/src/blocks/groupDvider/index.ts b/libs/components/editor-blocks/src/blocks/groupDvider/index.ts index 4120f1a525..52940173e6 100644 --- a/libs/components/editor-blocks/src/blocks/groupDvider/index.ts +++ b/libs/components/editor-blocks/src/blocks/groupDvider/index.ts @@ -5,6 +5,7 @@ import { } from '@toeverything/framework/virgo'; import { Protocol } from '@toeverything/datasource/db-service'; import { GroupDividerView } from './groupDividerView'; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class GroupDividerBlock extends BaseView { type = Protocol.Block.Type.groupDivider; @@ -28,12 +29,7 @@ export class GroupDividerBlock extends BaseView { return null; } - - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - return `
`; + override async block2html(props: Block2HtmlProps) { + return `
`; } } diff --git a/libs/components/editor-blocks/src/blocks/image/index.ts b/libs/components/editor-blocks/src/blocks/image/index.ts index 8f56468b41..190f83d72a 100644 --- a/libs/components/editor-blocks/src/blocks/image/index.ts +++ b/libs/components/editor-blocks/src/blocks/image/index.ts @@ -1,10 +1,7 @@ -import { - AsyncBlock, - BaseView, - SelectBlock, -} from '@toeverything/framework/virgo'; +import { BaseView } from '@toeverything/framework/virgo'; import { Protocol } from '@toeverything/datasource/db-service'; import { ImageView } from './ImageView'; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class ImageBlock extends BaseView { public override selectable = true; @@ -37,18 +34,13 @@ export class ImageBlock extends BaseView { return null; } - // TODO: - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - const text = block.getProperty('text'); + override async block2html({ block, editor }: Block2HtmlProps) { + const textValue = block.getProperty('text'); const content = ''; - if (text) { - text.value.map(text => `${text}`).join(''); - } - // TODO: child - return `

`; + // TODO: text.value should export with style?? + const figcaption = (textValue?.value ?? []) + .map(({ text }) => `${text}`) + .join(''); + return `
${figcaption}
${figcaption}
`; } } diff --git a/libs/components/editor-blocks/src/blocks/numbered/index.ts b/libs/components/editor-blocks/src/blocks/numbered/index.ts index 37295e026f..d6eb9c1839 100644 --- a/libs/components/editor-blocks/src/blocks/numbered/index.ts +++ b/libs/components/editor-blocks/src/blocks/numbered/index.ts @@ -1,16 +1,10 @@ -import { - AsyncBlock, - BaseView, - SelectBlock, - getTextHtml, -} from '@toeverything/framework/virgo'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; -// import { withTreeViewChildren } from '../../utils/with-tree-view-children'; +import { AsyncBlock, BaseView } from '@toeverything/framework/virgo'; +import { Protocol } from '@toeverything/datasource/db-service'; import { defaultTodoProps, NumberedView } from './NumberedView'; -import { IndentWrapper } from '../../components/IndentWrapper'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class NumberedBlock extends BaseView { public type = Protocol.Block.Type.numbered; @@ -77,14 +71,7 @@ export class NumberedBlock extends BaseView { return null; } - - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `
  1. ${content}
`; + override async block2html(props: Block2HtmlProps) { + return `
  1. ${await commonBlock2HtmlContent(props)}
`; } } diff --git a/libs/components/editor-blocks/src/blocks/page/index.ts b/libs/components/editor-blocks/src/blocks/page/index.ts index 06151bc481..4209cbbdb6 100644 --- a/libs/components/editor-blocks/src/blocks/page/index.ts +++ b/libs/components/editor-blocks/src/blocks/page/index.ts @@ -1,20 +1,9 @@ import { withRecastBlock } from '@toeverything/components/editor-core'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; -import { - AsyncBlock, - BaseView, - ChildrenView, - getTextHtml, - SelectBlock, -} from '@toeverything/framework/virgo'; +import { Protocol } from '@toeverything/datasource/db-service'; +import { AsyncBlock, BaseView } from '@toeverything/framework/virgo'; import { PageView } from './PageView'; - -export const PageChildrenView: (prop: ChildrenView) => JSX.Element = props => - props.children; +import { Block2HtmlProps } from '../../utils/commonBlockClip'; export class PageBlock extends BaseView { type = Protocol.Block.Type.page; @@ -34,13 +23,17 @@ export class PageBlock extends BaseView { return this.get_decoration(content, 'text')?.value?.[0].text; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - const content = getTextHtml(block); - const childrenContent = await generateHtml(children); - return `

${content}

${childrenContent}`; + override async block2html({ block, editor, selectInfo }: Block2HtmlProps) { + const header = + await editor.clipboard.clipboardUtils.convertTextValue2HtmlBySelectInfo( + block, + selectInfo + ); + const childrenHtml = + await editor.clipboard.clipboardUtils.convertBlock2HtmlBySelectInfos( + block, + selectInfo?.children + ); + return `

${header}

${childrenHtml}`; } } diff --git a/libs/components/editor-blocks/src/blocks/text/QuoteBlock.tsx b/libs/components/editor-blocks/src/blocks/text/QuoteBlock.tsx index 94938aa595..c3613f585d 100644 --- a/libs/components/editor-blocks/src/blocks/text/QuoteBlock.tsx +++ b/libs/components/editor-blocks/src/blocks/text/QuoteBlock.tsx @@ -1,14 +1,13 @@ -import { - DefaultColumnsValue, - Protocol, -} from '@toeverything/datasource/db-service'; +import { Protocol } from '@toeverything/datasource/db-service'; import { AsyncBlock, BaseView, CreateView, - getTextHtml, - SelectBlock, } from '@toeverything/framework/virgo'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; import { TextView } from './TextView'; @@ -60,14 +59,10 @@ export class QuoteBlock extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `
${content}
`; + override async block2html(props: Block2HtmlProps) { + return `
${await commonBlock2HtmlContent( + props + )}
`; } } @@ -135,13 +130,7 @@ export class CalloutBlock extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return ``; + override async block2html(props: Block2HtmlProps) { + return ``; } } diff --git a/libs/components/editor-blocks/src/blocks/text/TextBlock.tsx b/libs/components/editor-blocks/src/blocks/text/TextBlock.tsx index 74085db922..7161d0ec9e 100644 --- a/libs/components/editor-blocks/src/blocks/text/TextBlock.tsx +++ b/libs/components/editor-blocks/src/blocks/text/TextBlock.tsx @@ -2,16 +2,15 @@ import { BaseView, CreateView, AsyncBlock, - SelectBlock, - getTextHtml, } from '@toeverything/framework/virgo'; -import { - DefaultColumnsValue, - Protocol, -} from '@toeverything/datasource/db-service'; +import { Protocol } from '@toeverything/datasource/db-service'; import { TextView } from './TextView'; import { getRandomString } from '@toeverything/components/common'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class TextBlock extends BaseView { type = Protocol.Block.Type.text; @@ -111,14 +110,8 @@ export class TextBlock extends BaseView { : null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `

${content}

`; + override async block2html(props: Block2HtmlProps) { + return `

${await commonBlock2HtmlContent(props)}

`; } } @@ -168,14 +161,8 @@ export class Heading1Block extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `

${content}

`; + override async block2html(props: Block2HtmlProps) { + return `

${await commonBlock2HtmlContent(props)}

`; } } @@ -225,14 +212,8 @@ export class Heading2Block extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `

${content}

`; + override async block2html(props: Block2HtmlProps) { + return `

${await commonBlock2HtmlContent(props)}

`; } } @@ -282,13 +263,7 @@ export class Heading3Block extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `

${content}

`; + override async block2html(props: Block2HtmlProps) { + return `

${await commonBlock2HtmlContent(props)}

`; } } diff --git a/libs/components/editor-blocks/src/blocks/todo/index.ts b/libs/components/editor-blocks/src/blocks/todo/index.ts index db4187a890..9ea9bbccad 100644 --- a/libs/components/editor-blocks/src/blocks/todo/index.ts +++ b/libs/components/editor-blocks/src/blocks/todo/index.ts @@ -1,18 +1,12 @@ -import { - BaseView, - AsyncBlock, - SelectBlock, - getTextHtml, -} from '@toeverything/framework/virgo'; -// import type { CreateView } from '@toeverything/framework/virgo'; -import { - Protocol, - DefaultColumnsValue, -} from '@toeverything/datasource/db-service'; -// import { withTreeViewChildren } from '../../utils/with-tree-view-children'; +import { BaseView } from '@toeverything/framework/virgo'; +import { Protocol } from '@toeverything/datasource/db-service'; import { withTreeViewChildren } from '../../utils/WithTreeViewChildren'; import { TodoView, defaultTodoProps } from './TodoView'; import type { TodoAsyncBlock } from './types'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class TodoBlock extends BaseView { type = Protocol.Block.Type.todo; @@ -78,13 +72,7 @@ export class TodoBlock extends BaseView { return null; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - let content = getTextHtml(block); - content += await generateHtml(children); - return `
  • [ ] ${content}
`; + override async block2html(props: Block2HtmlProps) { + return `
  • [ ] ${await commonBlock2HtmlContent(props)}
`; } } diff --git a/libs/components/editor-blocks/src/blocks/youtube/index.ts b/libs/components/editor-blocks/src/blocks/youtube/index.ts index 94ad3ac59d..f1f6e1faa3 100644 --- a/libs/components/editor-blocks/src/blocks/youtube/index.ts +++ b/libs/components/editor-blocks/src/blocks/youtube/index.ts @@ -5,6 +5,10 @@ import { SelectBlock, } from '@toeverything/framework/virgo'; import { YoutubeView } from './YoutubeView'; +import { + Block2HtmlProps, + commonBlock2HtmlContent, +} from '../../utils/commonBlockClip'; export class YoutubeBlock extends BaseView { public override selectable = true; @@ -44,12 +48,8 @@ export class YoutubeBlock extends BaseView { override async block2Text(block: AsyncBlock, selectInfo: SelectBlock) { return block.getProperty('embedLink')?.value ?? ''; } - override async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { + override async block2html({ block }: Block2HtmlProps) { const url = block.getProperty('embedLink')?.value; - return `

${url}

`; + return `

${url}

`; } } diff --git a/libs/components/editor-blocks/src/utils/commonBlockClip.ts b/libs/components/editor-blocks/src/utils/commonBlockClip.ts new file mode 100644 index 0000000000..b381f465de --- /dev/null +++ b/libs/components/editor-blocks/src/utils/commonBlockClip.ts @@ -0,0 +1,30 @@ +import { + AsyncBlock, + BlockEditor, + SelectBlock, +} from '@toeverything/components/editor-core'; + +export type Block2HtmlProps = { + editor: BlockEditor; + block: AsyncBlock; + // The selectInfo parameter is not passed when the block is selected in ful, the selectInfo.type is Range + selectInfo?: SelectBlock; +}; + +export const commonBlock2HtmlContent = async ({ + editor, + block, + selectInfo, +}: Block2HtmlProps) => { + const html = + await editor.clipboard.clipboardUtils.convertTextValue2HtmlBySelectInfo( + block, + selectInfo + ); + const childrenHtml = + await editor.clipboard.clipboardUtils.convertBlock2HtmlBySelectInfos( + block, + selectInfo?.children + ); + return `${html}${childrenHtml}`; +}; diff --git a/libs/components/editor-core/src/editor/block/block-helper.ts b/libs/components/editor-core/src/editor/block/block-helper.ts index 70238c4be5..947e7eafe6 100644 --- a/libs/components/editor-core/src/editor/block/block-helper.ts +++ b/libs/components/editor-core/src/editor/block/block-helper.ts @@ -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 diff --git a/libs/components/editor-core/src/editor/clipboard/clipboard-parse.ts b/libs/components/editor-core/src/editor/clipboard/clipboard-parse.ts index 43b72ed6e7..04d976612d 100644 --- a/libs/components/editor-core/src/editor/clipboard/clipboard-parse.ts +++ b/libs/components/editor-core/src/editor/clipboard/clipboard-parse.ts @@ -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 { - const select_info = await this.editor.selectionManager.getSelectInfo(); - return await this.generate_html(select_info.blocks); - } - - public async page2html(): Promise { - 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 { - 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; } diff --git a/libs/components/editor-core/src/editor/clipboard/clipboardUtils.ts b/libs/components/editor-core/src/editor/clipboard/clipboardUtils.ts index d50b2fbdae..f4e9665b7e 100644 --- a/libs/components/editor-core/src/editor/clipboard/clipboardUtils.ts +++ b/libs/components/editor-core/src/editor/clipboard/clipboardUtils.ts @@ -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, + }); + } } diff --git a/libs/components/editor-core/src/editor/clipboard/copy.ts b/libs/components/editor-core/src/editor/clipboard/copy.ts index 3056091cd3..4d89a500b6 100644 --- a/libs/components/editor-core/src/editor/clipboard/copy.ts +++ b/libs/components/editor-core/src/editor/clipboard/copy.ts @@ -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 { - // 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 { + 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 { const selectInfo: SelectInfo = diff --git a/libs/components/editor-core/src/editor/editor.ts b/libs/components/editor-core/src/editor/editor.ts index 9253ab2cbe..acdf4233c5 100644 --- a/libs/components/editor-core/src/editor/editor.ts +++ b/libs/components/editor-core/src/editor/editor.ts @@ -502,13 +502,7 @@ export class Editor implements Virgo { } public async page2html(): Promise { - return ''; - // const parse = this.clipboard?.getClipboardParse(); - // if (!parse) { - // return ''; - // } - // const html_str = await parse.page2html(); - // return html_str; + return this.clipboard?.clipboardUtils?.page2html?.(); } dispose() { diff --git a/libs/components/editor-core/src/editor/index.ts b/libs/components/editor-core/src/editor/index.ts index d03326f386..2525fe5683 100644 --- a/libs/components/editor-core/src/editor/index.ts +++ b/libs/components/editor-core/src/editor/index.ts @@ -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'; diff --git a/libs/components/editor-core/src/editor/views/base-view.ts b/libs/components/editor-core/src/editor/views/base-view.ts index f9db79fbc5..d632f6e70a 100644 --- a/libs/components/editor-core/src/editor/views/base-view.ts +++ b/libs/components/editor-core/src/editor/views/base-view.ts @@ -135,13 +135,6 @@ export abstract class BaseView { return null; } - async block2html( - block: AsyncBlock, - children: SelectBlock[], - generateHtml: (el: any[]) => Promise - ): Promise { - 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 = `${text}`; - } - if (text_obj.italic) { - text = `${text}`; - } - if (text_obj.underline) { - text = `${text}`; - } - if (text_obj.inlinecode) { - text = `${text}`; - } - if (text_obj.strikethrough) { - text = `${text}`; - } - if (text_obj.type === 'link') { - text = `${generate( - text_obj.children - )}`; - } - content += text; - }); - return content; - }; - const text_list: any[] = block.getProperty('text').value; - return generate(text_list); -}; diff --git a/libs/components/layout/src/header/PageSettingPortal.tsx b/libs/components/layout/src/header/PageSettingPortal.tsx index 452734ff3c..9defcf754d 100644 --- a/libs/components/layout/src/header/PageSettingPortal.tsx +++ b/libs/components/layout/src/header/PageSettingPortal.tsx @@ -153,9 +153,7 @@ function PageSettingPortal() { const handleExportHtml = async () => { //@ts-ignore - const htmlContent = await virgo.clipboard - .getClipboardParse() - .page2html(); + const htmlContent = await virgo.clipboard.clipboardUtils.page2html(); const htmlTitle = pageBlock.title; FileExporter.exportHtml(htmlTitle, htmlContent); @@ -163,9 +161,7 @@ function PageSettingPortal() { const handleExportMarkdown = async () => { //@ts-ignore - const htmlContent = await virgo.clipboard - .getClipboardParse() - .page2html(); + const htmlContent = await virgo.clipboard.clipboardUtils.page2html(); const htmlTitle = pageBlock.title; FileExporter.exportMarkdown(htmlTitle, htmlContent); }; diff --git a/libs/components/layout/src/settings-sidebar/Settings/util/handle-export.ts b/libs/components/layout/src/settings-sidebar/Settings/util/handle-export.ts index fe284b986c..d329701f25 100644 --- a/libs/components/layout/src/settings-sidebar/Settings/util/handle-export.ts +++ b/libs/components/layout/src/settings-sidebar/Settings/util/handle-export.ts @@ -1,5 +1,4 @@ import { createEditor } from '@toeverything/components/affine-editor'; -import { ClipboardParse } from '@toeverything/components/editor-core'; import { fileExporter } from './file-exporter'; interface CreateClipboardParseProps { @@ -7,13 +6,12 @@ interface CreateClipboardParseProps { rootBlockId: string; } -const createClipboardParse = ({ +const createClipboardUtils = ({ workspaceId, rootBlockId, }: CreateClipboardParseProps) => { const editor = createEditor(workspaceId, rootBlockId); - - return new ClipboardParse(editor); + return editor.clipboard.clipboardUtils; }; interface ExportHandlerProps extends CreateClipboardParseProps { @@ -25,9 +23,8 @@ export const exportHtml = async ({ rootBlockId, title, }: ExportHandlerProps) => { - const clipboardParse = createClipboardParse({ workspaceId, rootBlockId }); - const htmlContent = await clipboardParse.page2html(); - fileExporter.exportHtml(title, htmlContent); + const clipboardUtils = createClipboardUtils({ workspaceId, rootBlockId }); + fileExporter.exportHtml(title, await clipboardUtils.page2html()); }; export const exportMarkdown = async ({ @@ -35,7 +32,6 @@ export const exportMarkdown = async ({ rootBlockId, title, }: ExportHandlerProps) => { - const clipboardParse = createClipboardParse({ workspaceId, rootBlockId }); - const htmlContent = await clipboardParse.page2html(); - fileExporter.exportMarkdown(title, htmlContent); + const clipboardUtils = createClipboardUtils({ workspaceId, rootBlockId }); + fileExporter.exportMarkdown(title, await clipboardUtils.page2html()); };