mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-19 07:17:00 +08:00
208 lines
5.9 KiB
TypeScript
208 lines
5.9 KiB
TypeScript
import { ParagraphBlockSchema } from '@blocksuite/affine-model';
|
|
import {
|
|
BlockMarkdownAdapterExtension,
|
|
type BlockMarkdownAdapterMatcher,
|
|
type MarkdownAST,
|
|
} from '@blocksuite/affine-shared/adapters';
|
|
import type { DeltaInsert } from '@blocksuite/store';
|
|
import { nanoid } from '@blocksuite/store';
|
|
import type { Heading } from 'mdast';
|
|
|
|
const PARAGRAPH_MDAST_TYPE = new Set([
|
|
'paragraph',
|
|
'html',
|
|
'heading',
|
|
'blockquote',
|
|
]);
|
|
|
|
const isParagraphMDASTType = (node: MarkdownAST) =>
|
|
PARAGRAPH_MDAST_TYPE.has(node.type);
|
|
|
|
export const paragraphBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher =
|
|
{
|
|
flavour: ParagraphBlockSchema.model.flavour,
|
|
toMatch: o => isParagraphMDASTType(o.node),
|
|
fromMatch: o => o.node.flavour === ParagraphBlockSchema.model.flavour,
|
|
toBlockSnapshot: {
|
|
enter: (o, context) => {
|
|
const { walkerContext, deltaConverter } = context;
|
|
switch (o.node.type) {
|
|
case 'html': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'block',
|
|
id: nanoid(),
|
|
flavour: 'affine:paragraph',
|
|
props: {
|
|
type: 'text',
|
|
text: {
|
|
'$blocksuite:internal:text$': true,
|
|
delta: [
|
|
{
|
|
insert: o.node.value,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
children: [],
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode();
|
|
break;
|
|
}
|
|
case 'paragraph': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'block',
|
|
id: nanoid(),
|
|
flavour: 'affine:paragraph',
|
|
props: {
|
|
type: 'text',
|
|
text: {
|
|
'$blocksuite:internal:text$': true,
|
|
delta: deltaConverter.astToDelta(o.node),
|
|
},
|
|
},
|
|
children: [],
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode();
|
|
walkerContext.skipAllChildren();
|
|
break;
|
|
}
|
|
case 'heading': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'block',
|
|
id: nanoid(),
|
|
flavour: 'affine:paragraph',
|
|
props: {
|
|
type: `h${o.node.depth}`,
|
|
text: {
|
|
'$blocksuite:internal:text$': true,
|
|
delta: deltaConverter.astToDelta(o.node),
|
|
},
|
|
},
|
|
children: [],
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode();
|
|
break;
|
|
}
|
|
case 'blockquote': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'block',
|
|
id: nanoid(),
|
|
flavour: 'affine:paragraph',
|
|
props: {
|
|
type: 'quote',
|
|
text: {
|
|
'$blocksuite:internal:text$': true,
|
|
delta: deltaConverter.astToDelta(o.node),
|
|
},
|
|
},
|
|
children: [],
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode();
|
|
walkerContext.skipAllChildren();
|
|
break;
|
|
}
|
|
}
|
|
},
|
|
},
|
|
fromBlockSnapshot: {
|
|
enter: (o, context) => {
|
|
const { walkerContext, deltaConverter } = context;
|
|
const paragraphDepth = (walkerContext.getGlobalContext(
|
|
'affine:paragraph:depth'
|
|
) ?? 0) as number;
|
|
const text = (o.node.props.text ?? { delta: [] }) as {
|
|
delta: DeltaInsert[];
|
|
};
|
|
switch (o.node.props.type) {
|
|
case 'h1':
|
|
case 'h2':
|
|
case 'h3':
|
|
case 'h4':
|
|
case 'h5':
|
|
case 'h6': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'heading',
|
|
depth: parseInt(o.node.props.type[1]) as Heading['depth'],
|
|
children: deltaConverter.deltaToAST(
|
|
text.delta,
|
|
paragraphDepth
|
|
),
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode();
|
|
break;
|
|
}
|
|
case 'text': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'paragraph',
|
|
children: deltaConverter.deltaToAST(
|
|
text.delta,
|
|
paragraphDepth
|
|
),
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode();
|
|
break;
|
|
}
|
|
case 'quote': {
|
|
walkerContext
|
|
.openNode(
|
|
{
|
|
type: 'blockquote',
|
|
children: [],
|
|
},
|
|
'children'
|
|
)
|
|
.openNode(
|
|
{
|
|
type: 'paragraph',
|
|
children: deltaConverter.deltaToAST(text.delta),
|
|
},
|
|
'children'
|
|
)
|
|
.closeNode()
|
|
.closeNode();
|
|
break;
|
|
}
|
|
}
|
|
walkerContext.setGlobalContext(
|
|
'affine:paragraph:depth',
|
|
paragraphDepth + 1
|
|
);
|
|
},
|
|
leave: (_, context) => {
|
|
const { walkerContext } = context;
|
|
walkerContext.setGlobalContext(
|
|
'affine:paragraph:depth',
|
|
(walkerContext.getGlobalContext('affine:paragraph:depth') as number) -
|
|
1
|
|
);
|
|
},
|
|
},
|
|
};
|
|
|
|
export const ParagraphBlockMarkdownAdapterExtension =
|
|
BlockMarkdownAdapterExtension(paragraphBlockMarkdownAdapterMatcher);
|