donteatfriedrice
2025-04-16 04:27:39 +00:00
parent 828215f45a
commit bfec5dd594
5 changed files with 285 additions and 263 deletions

View File

@@ -3,25 +3,51 @@ import {
BlockMarkdownAdapterExtension,
type BlockMarkdownAdapterMatcher,
CODE_BLOCK_WRAP_KEY,
IN_PARAGRAPH_NODE_CONTEXT_KEY,
type MarkdownAST,
} from '@blocksuite/affine-shared/adapters';
import type { DeltaInsert } from '@blocksuite/store';
import { nanoid } from '@blocksuite/store';
import type { Code } from 'mdast';
import type { Code, Html } from 'mdast';
const isCodeNode = (node: MarkdownAST): node is Code => node.type === 'code';
const isHtmlNode = (node: MarkdownAST): node is Html => node.type === 'html';
const isCodeOrHtmlNode = (node: MarkdownAST): node is Code | Html =>
isCodeNode(node) || isHtmlNode(node);
export const codeBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = {
flavour: CodeBlockSchema.model.flavour,
toMatch: o => isCodeNode(o.node),
toMatch: o => isCodeOrHtmlNode(o.node),
fromMatch: o => o.node.flavour === 'affine:code',
toBlockSnapshot: {
enter: (o, context) => {
if (!isCodeNode(o.node)) {
if (!isCodeOrHtmlNode(o.node)) {
return;
}
const { walkerContext, configs } = context;
const wrap = configs.get(CODE_BLOCK_WRAP_KEY) === 'true';
let language = 'plain text';
switch (o.node.type) {
case 'code': {
if (o.node.lang) {
language = o.node.lang;
}
break;
}
case 'html': {
const inParagraphNode = !!walkerContext.getGlobalContext(
IN_PARAGRAPH_NODE_CONTEXT_KEY
);
// only handle top level html node
if (inParagraphNode) {
return;
}
language = 'html';
break;
}
}
walkerContext
.openNode(
{
@@ -29,7 +55,7 @@ export const codeBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher = {
id: nanoid(),
flavour: 'affine:code',
props: {
language: o.node.lang ?? 'Plain Text',
language,
wrap,
text: {
'$blocksuite:internal:text$': true,

View File

@@ -2,18 +2,14 @@ import { ParagraphBlockSchema } from '@blocksuite/affine-model';
import {
BlockMarkdownAdapterExtension,
type BlockMarkdownAdapterMatcher,
IN_PARAGRAPH_NODE_CONTEXT_KEY,
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 PARAGRAPH_MDAST_TYPE = new Set(['paragraph', 'heading', 'blockquote']);
const isParagraphMDASTType = (node: MarkdownAST) =>
PARAGRAPH_MDAST_TYPE.has(node.type);
@@ -27,32 +23,8 @@ export const paragraphBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher =
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.setGlobalContext(IN_PARAGRAPH_NODE_CONTEXT_KEY, true);
walkerContext
.openNode(
{
@@ -71,7 +43,6 @@ export const paragraphBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher =
'children'
)
.closeNode();
walkerContext.skipAllChildren();
break;
}
case 'heading': {
@@ -119,6 +90,12 @@ export const paragraphBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher =
}
}
},
leave: (o, context) => {
if (o.node.type === 'paragraph') {
const { walkerContext } = context;
walkerContext.setGlobalContext(IN_PARAGRAPH_NODE_CONTEXT_KEY, false);
}
},
},
fromBlockSnapshot: {
enter: (o, context) => {