mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-18 06:47:02 +08:00
refactor(editor): extensionalize plain text adapter (#9330)
This commit is contained in:
@@ -2,6 +2,8 @@ import {
|
||||
DEFAULT_NOTE_BACKGROUND_COLOR,
|
||||
NoteDisplayMode,
|
||||
} from '@blocksuite/affine-model';
|
||||
import { PlainTextAdapter } from '@blocksuite/affine-shared/adapters';
|
||||
import { Container } from '@blocksuite/global/di';
|
||||
import type {
|
||||
BlockSnapshot,
|
||||
DocSnapshot,
|
||||
@@ -9,10 +11,20 @@ import type {
|
||||
} from '@blocksuite/store';
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { PlainTextAdapter } from '../../_common/adapters/plain-text/plain-text.js';
|
||||
import { defaultBlockPlainTextAdapterMatchers } from '../../_common/adapters/plain-text/block-matcher.js';
|
||||
import { inlineDeltaToPlainTextAdapterMatchers } from '../../_common/adapters/plain-text/delta-converter/inline-delta.js';
|
||||
import { embedSyncedDocMiddleware } from '../../_common/transformers/middlewares.js';
|
||||
import { createJob } from '../utils/create-job.js';
|
||||
|
||||
const container = new Container();
|
||||
[
|
||||
...defaultBlockPlainTextAdapterMatchers,
|
||||
...inlineDeltaToPlainTextAdapterMatchers,
|
||||
].forEach(ext => {
|
||||
ext.setup(container);
|
||||
});
|
||||
const provider = container.provider();
|
||||
|
||||
describe('snapshot to plain text', () => {
|
||||
test('paragraph', async () => {
|
||||
const blockSnapshot: BlockSnapshot = {
|
||||
@@ -157,7 +169,7 @@ describe('snapshot to plain text', () => {
|
||||
};
|
||||
|
||||
const plainText = 'aaabbbccc\nddd\neee\nfff\nggg\n';
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
@@ -316,7 +328,7 @@ describe('snapshot to plain text', () => {
|
||||
|
||||
const plainText = 'aaa\nbbb\nccc\nddd\neee\n';
|
||||
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
@@ -386,7 +398,7 @@ describe('snapshot to plain text', () => {
|
||||
};
|
||||
|
||||
const plainText = 'aaa\n---\n';
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
@@ -449,7 +461,7 @@ describe('snapshot to plain text', () => {
|
||||
};
|
||||
|
||||
const plainText = 'import this\n';
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
@@ -568,7 +580,10 @@ describe('snapshot to plain text', () => {
|
||||
adapterConfigs.set('title:deadbeef', 'test');
|
||||
adapterConfigs.set('docLinkBaseUrl', 'https://example.com');
|
||||
};
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob([middleware]));
|
||||
const plainTextAdapter = new PlainTextAdapter(
|
||||
createJob([middleware]),
|
||||
provider
|
||||
);
|
||||
|
||||
const plainText =
|
||||
'aaa: https://affine.pro/\ntest: https://example.com/deadbeef?mode=page&blockIds=abc%2C123&elementIds=def%2C456&databaseId=deadbeef&databaseRowId=123\nE=mc^2\n';
|
||||
@@ -670,7 +685,7 @@ describe('snapshot to plain text', () => {
|
||||
],
|
||||
};
|
||||
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
@@ -750,7 +765,10 @@ describe('snapshot to plain text', () => {
|
||||
};
|
||||
const plainText =
|
||||
'test: https://example.com/4T5ObMgEIMII-4Bexyta1?mode=page&blockIds=abc%2C123&elementIds=def%2C456&databaseId=deadbeef&databaseRowId=123\n';
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob([middleware]));
|
||||
const plainTextAdapter = new PlainTextAdapter(
|
||||
createJob([middleware]),
|
||||
provider
|
||||
);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapShot,
|
||||
});
|
||||
@@ -1146,7 +1164,7 @@ describe('snapshot to plain text', () => {
|
||||
await job.snapshotToDoc(syncedDocSnapshot);
|
||||
await job.snapshotToDoc(docSnapShot);
|
||||
|
||||
const mdAdapter = new PlainTextAdapter(job);
|
||||
const mdAdapter = new PlainTextAdapter(job, provider);
|
||||
const target = await mdAdapter.fromDocSnapshot({
|
||||
snapshot: docSnapShot,
|
||||
});
|
||||
@@ -1180,7 +1198,7 @@ describe('snapshot to plain text', () => {
|
||||
};
|
||||
|
||||
const plainText = 'LaTex, with value: E=mc^2\n';
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
@@ -1405,7 +1423,7 @@ describe('snapshot to plain text', () => {
|
||||
| Task 1 | TODO | 2023-12-15 | 1 | 65 | test1,test2 | test2: https://google.com | https://google.com | true |
|
||||
| Task 2 | In Progress | 2023-12-20 | | | | test1 | | |
|
||||
`;
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob());
|
||||
const plainTextAdapter = new PlainTextAdapter(createJob(), provider);
|
||||
const target = await plainTextAdapter.fromBlockSnapshot({
|
||||
snapshot: blockSnapshot,
|
||||
});
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
import { HtmlAdapterFactoryExtension } from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
HtmlAdapterFactoryExtension,
|
||||
PlainTextAdapterFactoryExtension,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
|
||||
import { AttachmentAdapterFactoryExtension } from './attachment.js';
|
||||
@@ -10,12 +13,13 @@ import { MixTextAdapterFactoryExtension } from './mix-text.js';
|
||||
import { notionHtmlInlineToDeltaMatchers } from './notion-html/delta-converter/html-inline.js';
|
||||
import { NotionHtmlAdapterFactoryExtension } from './notion-html/notion-html.js';
|
||||
import { NotionTextAdapterFactoryExtension } from './notion-text.js';
|
||||
import { PlainTextAdapterFactoryExtension } from './plain-text/plain-text.js';
|
||||
import { inlineDeltaToPlainTextAdapterMatchers } from './plain-text/delta-converter/inline-delta.js';
|
||||
|
||||
export const AdapterFactoryExtensions: ExtensionType[] = [
|
||||
...htmlInlineToDeltaMatchers,
|
||||
...inlineDeltaToHtmlAdapterMatchers,
|
||||
...notionHtmlInlineToDeltaMatchers,
|
||||
...inlineDeltaToPlainTextAdapterMatchers,
|
||||
AttachmentAdapterFactoryExtension,
|
||||
ImageAdapterFactoryExtension,
|
||||
MarkdownAdapterFactoryExtension,
|
||||
|
||||
@@ -5,4 +5,3 @@ export * from './markdown/index.js';
|
||||
export * from './mix-text.js';
|
||||
export * from './notion-html/index.js';
|
||||
export * from './notion-text.js';
|
||||
export * from './plain-text/plain-text.js';
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
import { bookmarkBlockPlainTextAdapterMatcher } from '@blocksuite/affine-block-bookmark';
|
||||
import { BookmarkBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-bookmark';
|
||||
import {
|
||||
embedFigmaBlockPlainTextAdapterMatcher,
|
||||
embedGithubBlockPlainTextAdapterMatcher,
|
||||
embedLinkedDocBlockPlainTextAdapterMatcher,
|
||||
embedLoomBlockPlainTextAdapterMatcher,
|
||||
embedSyncedDocBlockPlainTextAdapterMatcher,
|
||||
embedYoutubeBlockPlainTextAdapterMatcher,
|
||||
EmbedFigmaBlockPlainTextAdapterExtension,
|
||||
EmbedGithubBlockPlainTextAdapterExtension,
|
||||
EmbedLinkedDocBlockPlainTextAdapterExtension,
|
||||
EmbedLoomBlockPlainTextAdapterExtension,
|
||||
EmbedSyncedDocBlockPlainTextAdapterExtension,
|
||||
EmbedYoutubeBlockPlainTextAdapterExtension,
|
||||
} from '@blocksuite/affine-block-embed';
|
||||
import { latexBlockPlainTextAdapterMatcher } from '@blocksuite/affine-block-latex';
|
||||
import { listBlockPlainTextAdapterMatcher } from '@blocksuite/affine-block-list';
|
||||
import { paragraphBlockPlainTextAdapterMatcher } from '@blocksuite/affine-block-paragraph';
|
||||
import type { BlockPlainTextAdapterMatcher } from '@blocksuite/affine-shared/adapters';
|
||||
import { LatexBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-latex';
|
||||
import { ListBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-list';
|
||||
import { ParagraphBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-paragraph';
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
|
||||
import { codeBlockPlainTextAdapterMatcher } from '../../../code-block/adapters/plain-text.js';
|
||||
import { databaseBlockPlainTextAdapterMatcher } from '../../../database-block/adapters/plain-text.js';
|
||||
import { dividerBlockPlainTextAdapterMatcher } from '../../../divider-block/adapters/plain-text.js';
|
||||
import { CodeBlockPlainTextAdapterExtension } from '../../../code-block/adapters/plain-text.js';
|
||||
import { DatabaseBlockPlainTextAdapterExtension } from '../../../database-block/adapters/plain-text.js';
|
||||
import { DividerBlockPlainTextAdapterExtension } from '../../../divider-block/adapters/plain-text.js';
|
||||
|
||||
export const defaultBlockPlainTextAdapterMatchers: BlockPlainTextAdapterMatcher[] =
|
||||
[
|
||||
paragraphBlockPlainTextAdapterMatcher,
|
||||
listBlockPlainTextAdapterMatcher,
|
||||
dividerBlockPlainTextAdapterMatcher,
|
||||
codeBlockPlainTextAdapterMatcher,
|
||||
bookmarkBlockPlainTextAdapterMatcher,
|
||||
embedFigmaBlockPlainTextAdapterMatcher,
|
||||
embedGithubBlockPlainTextAdapterMatcher,
|
||||
embedLoomBlockPlainTextAdapterMatcher,
|
||||
embedYoutubeBlockPlainTextAdapterMatcher,
|
||||
embedLinkedDocBlockPlainTextAdapterMatcher,
|
||||
embedSyncedDocBlockPlainTextAdapterMatcher,
|
||||
latexBlockPlainTextAdapterMatcher,
|
||||
databaseBlockPlainTextAdapterMatcher,
|
||||
];
|
||||
export const defaultBlockPlainTextAdapterMatchers: ExtensionType[] = [
|
||||
ParagraphBlockPlainTextAdapterExtension,
|
||||
ListBlockPlainTextAdapterExtension,
|
||||
DividerBlockPlainTextAdapterExtension,
|
||||
CodeBlockPlainTextAdapterExtension,
|
||||
BookmarkBlockPlainTextAdapterExtension,
|
||||
EmbedFigmaBlockPlainTextAdapterExtension,
|
||||
EmbedGithubBlockPlainTextAdapterExtension,
|
||||
EmbedLoomBlockPlainTextAdapterExtension,
|
||||
EmbedYoutubeBlockPlainTextAdapterExtension,
|
||||
EmbedLinkedDocBlockPlainTextAdapterExtension,
|
||||
EmbedSyncedDocBlockPlainTextAdapterExtension,
|
||||
LatexBlockPlainTextAdapterExtension,
|
||||
DatabaseBlockPlainTextAdapterExtension,
|
||||
];
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { generateDocUrl } from '@blocksuite/affine-block-embed';
|
||||
import type {
|
||||
InlineDeltaToPlainTextAdapterMatcher,
|
||||
TextBuffer,
|
||||
import {
|
||||
InlineDeltaToPlainTextAdapterExtension,
|
||||
type TextBuffer,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
|
||||
export const referenceDeltaMarkdownAdapterMatch: InlineDeltaToPlainTextAdapterMatcher =
|
||||
{
|
||||
export const referenceDeltaMarkdownAdapterMatch =
|
||||
InlineDeltaToPlainTextAdapterExtension({
|
||||
name: 'reference',
|
||||
match: delta => !!delta.attributes?.reference,
|
||||
toAST: (delta, context) => {
|
||||
@@ -30,10 +31,10 @@ export const referenceDeltaMarkdownAdapterMatch: InlineDeltaToPlainTextAdapterMa
|
||||
content,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const linkDeltaMarkdownAdapterMatch: InlineDeltaToPlainTextAdapterMatcher =
|
||||
{
|
||||
export const linkDeltaMarkdownAdapterMatch =
|
||||
InlineDeltaToPlainTextAdapterExtension({
|
||||
name: 'link',
|
||||
match: delta => !!delta.attributes?.link,
|
||||
toAST: delta => {
|
||||
@@ -51,10 +52,10 @@ export const linkDeltaMarkdownAdapterMatch: InlineDeltaToPlainTextAdapterMatcher
|
||||
content,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const latexDeltaMarkdownAdapterMatch: InlineDeltaToPlainTextAdapterMatcher =
|
||||
{
|
||||
export const latexDeltaMarkdownAdapterMatch =
|
||||
InlineDeltaToPlainTextAdapterExtension({
|
||||
name: 'inlineLatex',
|
||||
match: delta => !!delta.attributes?.latex,
|
||||
toAST: delta => {
|
||||
@@ -68,11 +69,10 @@ export const latexDeltaMarkdownAdapterMatch: InlineDeltaToPlainTextAdapterMatche
|
||||
content: delta.attributes?.latex,
|
||||
};
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export const inlineDeltaToPlainTextAdapterMatchers: InlineDeltaToPlainTextAdapterMatcher[] =
|
||||
[
|
||||
referenceDeltaMarkdownAdapterMatch,
|
||||
linkDeltaMarkdownAdapterMatch,
|
||||
latexDeltaMarkdownAdapterMatch,
|
||||
];
|
||||
export const inlineDeltaToPlainTextAdapterMatchers: ExtensionType[] = [
|
||||
referenceDeltaMarkdownAdapterMatch,
|
||||
linkDeltaMarkdownAdapterMatch,
|
||||
latexDeltaMarkdownAdapterMatch,
|
||||
];
|
||||
|
||||
@@ -1,321 +0,0 @@
|
||||
import {
|
||||
DEFAULT_NOTE_BACKGROUND_COLOR,
|
||||
NoteDisplayMode,
|
||||
} from '@blocksuite/affine-model';
|
||||
import {
|
||||
type AdapterContext,
|
||||
AdapterFactoryIdentifier,
|
||||
type BlockPlainTextAdapterMatcher,
|
||||
BlockPlainTextAdapterMatcherIdentifier,
|
||||
type PlainText,
|
||||
PlainTextDeltaConverter,
|
||||
type TextBuffer,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
import {
|
||||
type AssetsManager,
|
||||
ASTWalker,
|
||||
BaseAdapter,
|
||||
type BlockSnapshot,
|
||||
BlockSnapshotSchema,
|
||||
type DocSnapshot,
|
||||
type FromBlockSnapshotPayload,
|
||||
type FromBlockSnapshotResult,
|
||||
type FromDocSnapshotPayload,
|
||||
type FromDocSnapshotResult,
|
||||
type FromSliceSnapshotPayload,
|
||||
type FromSliceSnapshotResult,
|
||||
type Job,
|
||||
nanoid,
|
||||
type SliceSnapshot,
|
||||
type ToBlockSnapshotPayload,
|
||||
type ToDocSnapshotPayload,
|
||||
} from '@blocksuite/store';
|
||||
|
||||
import { defaultBlockPlainTextAdapterMatchers } from './block-matcher.js';
|
||||
import { inlineDeltaToPlainTextAdapterMatchers } from './delta-converter/inline-delta.js';
|
||||
|
||||
type PlainTextToSliceSnapshotPayload = {
|
||||
file: PlainText;
|
||||
assets?: AssetsManager;
|
||||
blockVersions: Record<string, number>;
|
||||
workspaceId: string;
|
||||
pageId: string;
|
||||
};
|
||||
|
||||
export class PlainTextAdapter extends BaseAdapter<PlainText> {
|
||||
deltaConverter: PlainTextDeltaConverter;
|
||||
|
||||
constructor(
|
||||
job: Job,
|
||||
readonly blockMatchers: BlockPlainTextAdapterMatcher[] = defaultBlockPlainTextAdapterMatchers
|
||||
) {
|
||||
super(job);
|
||||
this.deltaConverter = new PlainTextDeltaConverter(
|
||||
job.adapterConfigs,
|
||||
inlineDeltaToPlainTextAdapterMatchers,
|
||||
[]
|
||||
);
|
||||
}
|
||||
|
||||
private async _traverseSnapshot(
|
||||
snapshot: BlockSnapshot
|
||||
): Promise<{ plaintext: string }> {
|
||||
const textBuffer: TextBuffer = {
|
||||
content: '',
|
||||
};
|
||||
const walker = new ASTWalker<BlockSnapshot, TextBuffer>();
|
||||
walker.setONodeTypeGuard(
|
||||
(node): node is BlockSnapshot =>
|
||||
BlockSnapshotSchema.safeParse(node).success
|
||||
);
|
||||
walker.setEnter(async (o, context) => {
|
||||
for (const matcher of this.blockMatchers) {
|
||||
if (matcher.fromMatch(o)) {
|
||||
const adapterContext: AdapterContext<BlockSnapshot, TextBuffer> = {
|
||||
walker,
|
||||
walkerContext: context,
|
||||
configs: this.configs,
|
||||
job: this.job,
|
||||
deltaConverter: this.deltaConverter,
|
||||
textBuffer,
|
||||
};
|
||||
await matcher.fromBlockSnapshot.enter?.(o, adapterContext);
|
||||
}
|
||||
}
|
||||
});
|
||||
walker.setLeave(async (o, context) => {
|
||||
for (const matcher of this.blockMatchers) {
|
||||
if (matcher.fromMatch(o)) {
|
||||
const adapterContext: AdapterContext<BlockSnapshot, TextBuffer> = {
|
||||
walker,
|
||||
walkerContext: context,
|
||||
configs: this.configs,
|
||||
job: this.job,
|
||||
deltaConverter: this.deltaConverter,
|
||||
textBuffer,
|
||||
};
|
||||
await matcher.fromBlockSnapshot.leave?.(o, adapterContext);
|
||||
}
|
||||
}
|
||||
});
|
||||
await walker.walkONode(snapshot);
|
||||
return {
|
||||
plaintext: textBuffer.content,
|
||||
};
|
||||
}
|
||||
|
||||
async fromBlockSnapshot({
|
||||
snapshot,
|
||||
}: FromBlockSnapshotPayload): Promise<FromBlockSnapshotResult<PlainText>> {
|
||||
const { plaintext } = await this._traverseSnapshot(snapshot);
|
||||
return {
|
||||
file: plaintext,
|
||||
assetsIds: [],
|
||||
};
|
||||
}
|
||||
|
||||
async fromDocSnapshot({
|
||||
snapshot,
|
||||
assets,
|
||||
}: FromDocSnapshotPayload): Promise<FromDocSnapshotResult<PlainText>> {
|
||||
let buffer = '';
|
||||
if (snapshot.meta.title) {
|
||||
buffer += `${snapshot.meta.title}\n\n`;
|
||||
}
|
||||
const { file, assetsIds } = await this.fromBlockSnapshot({
|
||||
snapshot: snapshot.blocks,
|
||||
assets,
|
||||
});
|
||||
buffer += file;
|
||||
return {
|
||||
file: buffer,
|
||||
assetsIds,
|
||||
};
|
||||
}
|
||||
|
||||
async fromSliceSnapshot({
|
||||
snapshot,
|
||||
}: FromSliceSnapshotPayload): Promise<FromSliceSnapshotResult<PlainText>> {
|
||||
let buffer = '';
|
||||
const sliceAssetsIds: string[] = [];
|
||||
for (const contentSlice of snapshot.content) {
|
||||
const { plaintext } = await this._traverseSnapshot(contentSlice);
|
||||
buffer += plaintext;
|
||||
}
|
||||
const plaintext =
|
||||
buffer.match(/\n/g)?.length === 1 ? buffer.trimEnd() : buffer;
|
||||
return {
|
||||
file: plaintext,
|
||||
assetsIds: sliceAssetsIds,
|
||||
};
|
||||
}
|
||||
|
||||
toBlockSnapshot(payload: ToBlockSnapshotPayload<PlainText>): BlockSnapshot {
|
||||
payload.file = payload.file.replaceAll('\r', '');
|
||||
return {
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DEFAULT_NOTE_BACKGROUND_COLOR,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
children: payload.file.split('\n').map((line): BlockSnapshot => {
|
||||
return {
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{
|
||||
insert: line,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
};
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
toDocSnapshot(payload: ToDocSnapshotPayload<PlainText>): DocSnapshot {
|
||||
payload.file = payload.file.replaceAll('\r', '');
|
||||
return {
|
||||
type: 'page',
|
||||
meta: {
|
||||
id: nanoid(),
|
||||
title: 'Untitled',
|
||||
createDate: Date.now(),
|
||||
tags: [],
|
||||
},
|
||||
blocks: {
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:page',
|
||||
props: {
|
||||
title: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{
|
||||
insert: 'Untitled',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:surface',
|
||||
props: {
|
||||
elements: {},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DEFAULT_NOTE_BACKGROUND_COLOR,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
children: payload.file.split('\n').map((line): BlockSnapshot => {
|
||||
return {
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{
|
||||
insert: line,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
};
|
||||
}),
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
toSliceSnapshot(
|
||||
payload: PlainTextToSliceSnapshotPayload
|
||||
): SliceSnapshot | null {
|
||||
if (payload.file.trim().length === 0) {
|
||||
return null;
|
||||
}
|
||||
payload.file = payload.file.replaceAll('\r', '');
|
||||
const contentSlice = {
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:note',
|
||||
props: {
|
||||
xywh: '[0,0,800,95]',
|
||||
background: DEFAULT_NOTE_BACKGROUND_COLOR,
|
||||
index: 'a0',
|
||||
hidden: false,
|
||||
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||
},
|
||||
children: payload.file.split('\n').map((line): BlockSnapshot => {
|
||||
return {
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{
|
||||
insert: line,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
};
|
||||
}),
|
||||
} as BlockSnapshot;
|
||||
return {
|
||||
type: 'slice',
|
||||
content: [contentSlice],
|
||||
workspaceId: payload.workspaceId,
|
||||
pageId: payload.pageId,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export const PlainTextAdapterFactoryIdentifier =
|
||||
AdapterFactoryIdentifier('PlainText');
|
||||
|
||||
export const PlainTextAdapterFactoryExtension: ExtensionType = {
|
||||
setup: di => {
|
||||
di.addImpl(PlainTextAdapterFactoryIdentifier, provider => ({
|
||||
get: (job: Job) =>
|
||||
new PlainTextAdapter(
|
||||
job,
|
||||
Array.from(
|
||||
provider.getAll(BlockPlainTextAdapterMatcherIdentifier).values()
|
||||
)
|
||||
),
|
||||
}));
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,7 @@
|
||||
import { HtmlAdapter } from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
HtmlAdapter,
|
||||
PlainTextAdapter,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import {
|
||||
type BlockComponent,
|
||||
Clipboard,
|
||||
@@ -6,7 +9,6 @@ import {
|
||||
} from '@blocksuite/block-std';
|
||||
import { assertExists, DisposableGroup } from '@blocksuite/global/utils';
|
||||
|
||||
import { PlainTextAdapter } from '../../_common/adapters/index.js';
|
||||
import { pasteMiddleware } from '../../root-block/clipboard/middlewares/index.js';
|
||||
|
||||
export class CodeClipboardController {
|
||||
|
||||
@@ -103,6 +103,9 @@ export {
|
||||
HtmlAdapter,
|
||||
HtmlAdapterFactoryExtension,
|
||||
HtmlAdapterFactoryIdentifier,
|
||||
PlainTextAdapter,
|
||||
PlainTextAdapterFactoryExtension,
|
||||
PlainTextAdapterFactoryIdentifier,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
export * from '@blocksuite/affine-shared/services';
|
||||
export { scrollbarStyle } from '@blocksuite/affine-shared/styles';
|
||||
|
||||
Reference in New Issue
Block a user