mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-18 18:41:52 +08:00
refactor(editor): unify directories naming (#11516)
**Directory Structure Changes** - Renamed multiple block-related directories by removing the "block-" prefix: - `block-attachment` → `attachment` - `block-bookmark` → `bookmark` - `block-callout` → `callout` - `block-code` → `code` - `block-data-view` → `data-view` - `block-database` → `database` - `block-divider` → `divider` - `block-edgeless-text` → `edgeless-text` - `block-embed` → `embed`
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { ParagraphBlockHtmlAdapterExtension } from './html.js';
|
||||
import { ParagraphBlockMarkdownAdapterExtension } from './markdown.js';
|
||||
import { ParagraphBlockNotionHtmlAdapterExtension } from './notion-html.js';
|
||||
import { ParagraphBlockPlainTextAdapterExtension } from './plain-text.js';
|
||||
|
||||
export const ParagraphBlockAdapterExtensions: ExtensionType[] = [
|
||||
ParagraphBlockHtmlAdapterExtension,
|
||||
ParagraphBlockMarkdownAdapterExtension,
|
||||
ParagraphBlockPlainTextAdapterExtension,
|
||||
ParagraphBlockNotionHtmlAdapterExtension,
|
||||
];
|
||||
@@ -0,0 +1,359 @@
|
||||
import { ParagraphBlockSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
BlockHtmlAdapterExtension,
|
||||
type BlockHtmlAdapterMatcher,
|
||||
HastUtils,
|
||||
type HtmlAST,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { DeltaInsert, NodeProps } from '@blocksuite/store';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
|
||||
const paragraphBlockMatchTags = new Set([
|
||||
'p',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'blockquote',
|
||||
'body',
|
||||
'div',
|
||||
'span',
|
||||
'footer',
|
||||
]);
|
||||
|
||||
const tagsInAncestor = (o: NodeProps<HtmlAST>, tagNames: Array<string>) => {
|
||||
let parent = o.parent;
|
||||
while (parent) {
|
||||
if (
|
||||
HastUtils.isElement(parent.node) &&
|
||||
tagNames.includes(parent.node.tagName)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.parent;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
export const paragraphBlockHtmlAdapterMatcher: BlockHtmlAdapterMatcher = {
|
||||
flavour: ParagraphBlockSchema.model.flavour,
|
||||
toMatch: o =>
|
||||
HastUtils.isElement(o.node) && paragraphBlockMatchTags.has(o.node.tagName),
|
||||
fromMatch: o => o.node.flavour === ParagraphBlockSchema.model.flavour,
|
||||
toBlockSnapshot: {
|
||||
enter: (o, context) => {
|
||||
if (!HastUtils.isElement(o.node)) {
|
||||
return;
|
||||
}
|
||||
const { walkerContext, deltaConverter } = context;
|
||||
switch (o.node.tagName) {
|
||||
case 'blockquote': {
|
||||
walkerContext.setGlobalContext('hast:blockquote', true);
|
||||
// Special case for no paragraph in blockquote
|
||||
const texts = HastUtils.getTextChildren(o.node);
|
||||
// check if only blank text
|
||||
const onlyBlankText = texts.every(text => !text.value.trim());
|
||||
if (texts && !onlyBlankText) {
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'quote',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(
|
||||
HastUtils.getTextChildrenOnlyAst(o.node)
|
||||
),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'body':
|
||||
case 'div':
|
||||
case 'span':
|
||||
case 'footer': {
|
||||
if (
|
||||
o.parent?.node.type === 'element' &&
|
||||
!tagsInAncestor(o, ['p', 'li']) &&
|
||||
HastUtils.isParagraphLike(o.node)
|
||||
) {
|
||||
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 'p': {
|
||||
walkerContext.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: walkerContext.getGlobalContext('hast:blockquote')
|
||||
? 'quote'
|
||||
: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(o.node),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'h1':
|
||||
case 'h2':
|
||||
case 'h3':
|
||||
case 'h4':
|
||||
case 'h5':
|
||||
case 'h6': {
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: o.node.tagName,
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(o.node),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode();
|
||||
walkerContext.skipAllChildren();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
leave: (o, context) => {
|
||||
if (!HastUtils.isElement(o.node)) {
|
||||
return;
|
||||
}
|
||||
const { walkerContext } = context;
|
||||
switch (o.node.tagName) {
|
||||
case 'div': {
|
||||
// eslint-disable-next-line sonarjs/no-collapsible-if
|
||||
if (
|
||||
o.parent?.node.type === 'element' &&
|
||||
o.parent.node.tagName !== 'li' &&
|
||||
Array.isArray(o.node.properties?.className)
|
||||
) {
|
||||
if (
|
||||
o.node.properties.className.includes(
|
||||
'affine-paragraph-block-container'
|
||||
) ||
|
||||
o.node.properties.className.includes(
|
||||
'affine-block-children-container'
|
||||
) ||
|
||||
o.node.properties.className.includes('indented')
|
||||
) {
|
||||
walkerContext.closeNode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'blockquote': {
|
||||
walkerContext.setGlobalContext('hast:blockquote', false);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
if (
|
||||
o.next?.type === 'element' &&
|
||||
o.next.tagName === 'div' &&
|
||||
Array.isArray(o.next.properties?.className) &&
|
||||
(o.next.properties.className.includes(
|
||||
'affine-block-children-container'
|
||||
) ||
|
||||
o.next.properties.className.includes('indented'))
|
||||
) {
|
||||
// Close the node when leaving div indented
|
||||
break;
|
||||
}
|
||||
walkerContext.closeNode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
fromBlockSnapshot: {
|
||||
enter: (o, context) => {
|
||||
const text = (o.node.props.text ?? { delta: [] }) as {
|
||||
delta: DeltaInsert[];
|
||||
};
|
||||
const { walkerContext, deltaConverter } = context;
|
||||
switch (o.node.props.type) {
|
||||
case 'text': {
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['affine-paragraph-block-container'],
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'p',
|
||||
properties: {},
|
||||
children: deltaConverter.deltaToAST(text.delta),
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode()
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['affine-block-children-container'],
|
||||
style: 'padding-left: 26px;',
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'h1':
|
||||
case 'h2':
|
||||
case 'h3':
|
||||
case 'h4':
|
||||
case 'h5':
|
||||
case 'h6': {
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['affine-paragraph-block-container'],
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: o.node.props.type,
|
||||
properties: {},
|
||||
children: deltaConverter.deltaToAST(text.delta),
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode()
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['affine-block-children-container'],
|
||||
style: 'padding-left: 26px;',
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'quote': {
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['affine-paragraph-block-container'],
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'blockquote',
|
||||
properties: {
|
||||
className: ['quote'],
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'p',
|
||||
properties: {},
|
||||
children: deltaConverter.deltaToAST(text.delta),
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode()
|
||||
.closeNode()
|
||||
.openNode(
|
||||
{
|
||||
type: 'element',
|
||||
tagName: 'div',
|
||||
properties: {
|
||||
className: ['affine-block-children-container'],
|
||||
style: 'padding-left: 26px;',
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
leave: (_, context) => {
|
||||
const { walkerContext } = context;
|
||||
walkerContext.closeNode().closeNode();
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ParagraphBlockHtmlAdapterExtension = BlockHtmlAdapterExtension(
|
||||
paragraphBlockHtmlAdapterMatcher
|
||||
);
|
||||
@@ -0,0 +1,4 @@
|
||||
export * from './html.js';
|
||||
export * from './markdown.js';
|
||||
export * from './notion-html.js';
|
||||
export * from './plain-text.js';
|
||||
@@ -0,0 +1,206 @@
|
||||
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();
|
||||
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);
|
||||
@@ -0,0 +1,239 @@
|
||||
import { ParagraphBlockSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
BlockNotionHtmlAdapterExtension,
|
||||
type BlockNotionHtmlAdapterMatcher,
|
||||
HastUtils,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import { nanoid } from '@blocksuite/store';
|
||||
|
||||
const paragraphBlockMatchTags = new Set([
|
||||
'p',
|
||||
'h1',
|
||||
'h2',
|
||||
'h3',
|
||||
'h4',
|
||||
'h5',
|
||||
'h6',
|
||||
'blockquote',
|
||||
'div',
|
||||
'span',
|
||||
'figure',
|
||||
]);
|
||||
|
||||
const NotionDatabaseTitleToken = '.collection-title';
|
||||
const NotionPageLinkToken = '.link-to-page';
|
||||
const NotionCalloutToken = '.callout';
|
||||
const NotionCheckboxToken = '.checkbox';
|
||||
|
||||
export const paragraphBlockNotionHtmlAdapterMatcher: BlockNotionHtmlAdapterMatcher =
|
||||
{
|
||||
flavour: ParagraphBlockSchema.model.flavour,
|
||||
toMatch: o =>
|
||||
HastUtils.isElement(o.node) &&
|
||||
paragraphBlockMatchTags.has(o.node.tagName),
|
||||
fromMatch: () => false,
|
||||
toBlockSnapshot: {
|
||||
enter: (o, context) => {
|
||||
if (!HastUtils.isElement(o.node)) {
|
||||
return;
|
||||
}
|
||||
const { walkerContext, deltaConverter, pageMap } = context;
|
||||
switch (o.node.tagName) {
|
||||
case 'blockquote': {
|
||||
walkerContext.setGlobalContext('hast:blockquote', true);
|
||||
walkerContext.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'quote',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(
|
||||
HastUtils.getInlineOnlyElementAST(o.node),
|
||||
{ pageMap, removeLastBr: true }
|
||||
),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
// Workaround for Notion's bug
|
||||
// https://html.spec.whatwg.org/multipage/grouping-content.html#the-p-element
|
||||
if (!o.node.properties.id) {
|
||||
break;
|
||||
}
|
||||
walkerContext.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: walkerContext.getGlobalContext('hast:blockquote')
|
||||
? 'quote'
|
||||
: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(o.node, { pageMap }),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
);
|
||||
break;
|
||||
}
|
||||
case 'h1':
|
||||
case 'h2':
|
||||
case 'h3':
|
||||
case 'h4':
|
||||
case 'h5':
|
||||
case 'h6': {
|
||||
if (HastUtils.querySelector(o.node, NotionDatabaseTitleToken)) {
|
||||
break;
|
||||
}
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: o.node.tagName,
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(o.node, { pageMap }),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode();
|
||||
break;
|
||||
}
|
||||
case 'figure':
|
||||
{
|
||||
// Notion page link
|
||||
if (HastUtils.querySelector(o.node, NotionPageLinkToken)) {
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'text',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: deltaConverter.astToDelta(o.node, { pageMap }),
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode();
|
||||
walkerContext.skipAllChildren();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Notion callout
|
||||
if (HastUtils.querySelector(o.node, NotionCalloutToken)) {
|
||||
const firstElementChild = HastUtils.getElementChildren(o.node)[0];
|
||||
const secondElementChild = HastUtils.getElementChildren(
|
||||
o.node
|
||||
)[1];
|
||||
|
||||
const iconSpan = HastUtils.querySelector(
|
||||
firstElementChild,
|
||||
'.icon'
|
||||
);
|
||||
const iconText = iconSpan
|
||||
? HastUtils.getTextContent(iconSpan)
|
||||
: '';
|
||||
walkerContext
|
||||
.openNode(
|
||||
{
|
||||
type: 'block',
|
||||
id: nanoid(),
|
||||
flavour: 'affine:paragraph',
|
||||
props: {
|
||||
type: 'quote',
|
||||
text: {
|
||||
'$blocksuite:internal:text$': true,
|
||||
delta: [
|
||||
{ insert: iconText + '\n' },
|
||||
...deltaConverter.astToDelta(secondElementChild, {
|
||||
pageMap,
|
||||
}),
|
||||
],
|
||||
},
|
||||
},
|
||||
children: [],
|
||||
},
|
||||
'children'
|
||||
)
|
||||
.closeNode();
|
||||
walkerContext.skipAllChildren();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
leave: (o, context) => {
|
||||
if (!HastUtils.isElement(o.node)) {
|
||||
return;
|
||||
}
|
||||
const { walkerContext } = context;
|
||||
switch (o.node.tagName) {
|
||||
case 'div': {
|
||||
// eslint-disable-next-line sonarjs/no-collapsible-if
|
||||
if (
|
||||
o.parent?.node.type === 'element' &&
|
||||
!(
|
||||
o.parent.node.tagName === 'li' &&
|
||||
HastUtils.querySelector(o.parent.node, NotionCheckboxToken)
|
||||
) &&
|
||||
Array.isArray(o.node.properties?.className)
|
||||
) {
|
||||
if (o.node.properties.className.includes('indented')) {
|
||||
walkerContext.closeNode();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 'blockquote': {
|
||||
walkerContext.closeNode();
|
||||
walkerContext.setGlobalContext('hast:blockquote', false);
|
||||
break;
|
||||
}
|
||||
case 'p': {
|
||||
if (!o.node.properties.id) {
|
||||
break;
|
||||
}
|
||||
if (
|
||||
o.next?.type === 'element' &&
|
||||
o.next.tagName === 'div' &&
|
||||
Array.isArray(o.next.properties?.className) &&
|
||||
o.next.properties.className.includes('indented')
|
||||
) {
|
||||
// Close the node when leaving div indented
|
||||
break;
|
||||
}
|
||||
walkerContext.closeNode();
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
fromBlockSnapshot: {},
|
||||
};
|
||||
|
||||
export const ParagraphBlockNotionHtmlAdapterExtension =
|
||||
BlockNotionHtmlAdapterExtension(paragraphBlockNotionHtmlAdapterMatcher);
|
||||
@@ -0,0 +1,28 @@
|
||||
import { ParagraphBlockSchema } from '@blocksuite/affine-model';
|
||||
import {
|
||||
BlockPlainTextAdapterExtension,
|
||||
type BlockPlainTextAdapterMatcher,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
import type { DeltaInsert } from '@blocksuite/store';
|
||||
|
||||
export const paragraphBlockPlainTextAdapterMatcher: BlockPlainTextAdapterMatcher =
|
||||
{
|
||||
flavour: ParagraphBlockSchema.model.flavour,
|
||||
toMatch: () => false,
|
||||
fromMatch: o => o.node.flavour === ParagraphBlockSchema.model.flavour,
|
||||
toBlockSnapshot: {},
|
||||
fromBlockSnapshot: {
|
||||
enter: (o, context) => {
|
||||
const text = (o.node.props.text ?? { delta: [] }) as {
|
||||
delta: DeltaInsert[];
|
||||
};
|
||||
const { deltaConverter } = context;
|
||||
const buffer = deltaConverter.deltaToAST(text.delta).join('');
|
||||
context.textBuffer.content += buffer;
|
||||
context.textBuffer.content += '\n';
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const ParagraphBlockPlainTextAdapterExtension =
|
||||
BlockPlainTextAdapterExtension(paragraphBlockPlainTextAdapterMatcher);
|
||||
Reference in New Issue
Block a user