Transformer & Adapter
Overview
In BlockSuite, we use transformers and adapters to serialize and deserialize data.
This system is used mainly in scenarios like:
-
Copy and Paste
-
Import and Export
-
Drag and Drop
Snapshot and Transformer
The current editor data can be converted to and from a JSON data structure known as the BlockSuite Snapshot.
A snapshot can represent data in one of the following forms:
This process can be illustrated as follows:
// Pseudo code
DocSnapshot = Transformer.Export(Doc)
SliceSnapshot = Transformer.Export(Slice)
BlockSnapshot = Transformer.Export(Block)
Each snapshot can be converted back to its original form (Doc, Slice, or Block) without any data loss:
// Pseudo code
Doc = Transformer.Import(DocSnapshot)
Slice = Transformer.Import(SliceSnapshot)
Block = Transformer.Import(BlockSnapshot)
Snapshot and Adapter
An adapter is used to convert a BlockSuite Snapshot into other data formats, such as Markdown, HTML, or plain text. Unlike transformers, adapters may result in data loss during the conversion process, as the target format might not support all the structures present in the original data. For example, background colors cannot be represented in a plain text editor like VS Code.
The conversion process can be illustrated as follows:
// Pseudo code
DocMarkdown = MarkdownAdapter.Export(DocSnapshot)
SliceMarkdown = MarkdownAdapter.Export(SliceSnapshot)
BlockMarkdown = MarkdownAdapter.Export(BlockSnapshot)
Similarly, there are APIs available for importing data from the target format back into BlockSuite:
// Pseudo code
DocSnapshot = MarkdownAdapter.Import(DocMarkdown)
SliceSnapshot = MarkdownAdapter.Import(SliceMarkdown)
BlockSnapshot = MarkdownAdapter.Import(BlockMarkdown)
Using Transformer and Adapter
You'll need to have a store before starting to use the transformer and adapter.
Here're some examples to export with markdown adatper:
import { MarkdownAdapter } from '@blocksuite/affine/shared/adapters';
import { Slice } from '@blocksuite/affine/store';
const transformer = store.getTransformer([aMiddleware, bMiddleware]);
const markdownAdapter = new MarkdownAdapter(transformer, store.provider);
// export a block to markdown
const block = store.getBlock('block-id');
const result = await markdownAdapter.fromBlock(block.model);
const markdownString = result.file;
// export some blocks to markdown
const block1 = store.getBlock('block-id-1');
const block2 = store.getBlock('block-id-2');
const slice = Slice.fromModels(store, [block1.model, block2.model]);
const result = await markdownAdapter.fromSlice(slice);
const markdownString = result.file;
// export the whole doc
const result = await markdownAdapter.fromDoc(store);
const markdownString = result.file;
Here're some examples to import with markdown adapter:
import { MarkdownAdapter } from '@blocksuite/affine/shared/adapters';
const transformer = store.getTransformer([aMiddleware, bMiddleware]);
const markdownAdapter = new MarkdownAdapter(transformer, store.provider);
// import markdown to a block
const block = await markdownAdapter.toBlock({ file: someContent })
// import markdown to a slice
const slice = await markdownAdapter.toSlice({ file: someContent })
// import markdown to a doc
const store = await markdownAdapter.toSlice({ file: someContent })
Transformer Middleware
Transformer can use middleware to customize the behavior when importing/exporting contents.
To learn more about middleware, read the following document:
null