mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-01 09:30:01 +08:00
chore: merge blocksuite source code (#9213)
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
import {
|
||||
createIdentifier,
|
||||
type ServiceIdentifier,
|
||||
} from '@blocksuite/global/di';
|
||||
|
||||
import type { BlockAdapterMatcher } from '../types/adapter.js';
|
||||
import type { MarkdownDeltaConverter } from './delta-converter.js';
|
||||
import type { MarkdownAST } from './type.js';
|
||||
|
||||
export type BlockMarkdownAdapterMatcher = BlockAdapterMatcher<
|
||||
MarkdownAST,
|
||||
MarkdownDeltaConverter
|
||||
>;
|
||||
|
||||
export const BlockMarkdownAdapterMatcherIdentifier =
|
||||
createIdentifier<BlockMarkdownAdapterMatcher>('BlockMarkdownAdapterMatcher');
|
||||
|
||||
export function BlockMarkdownAdapterExtension(
|
||||
matcher: BlockMarkdownAdapterMatcher
|
||||
): ExtensionType & {
|
||||
identifier: ServiceIdentifier<BlockMarkdownAdapterMatcher>;
|
||||
} {
|
||||
const identifier = BlockMarkdownAdapterMatcherIdentifier(matcher.flavour);
|
||||
return {
|
||||
setup: di => {
|
||||
di.addImpl(identifier, () => matcher);
|
||||
},
|
||||
identifier,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
import type { ExtensionType } from '@blocksuite/block-std';
|
||||
import {
|
||||
createIdentifier,
|
||||
type ServiceIdentifier,
|
||||
} from '@blocksuite/global/di';
|
||||
import type { DeltaInsert } from '@blocksuite/inline/types';
|
||||
import type { PhrasingContent } from 'mdast';
|
||||
|
||||
import type { AffineTextAttributes } from '../../types/index.js';
|
||||
import {
|
||||
type ASTToDeltaMatcher,
|
||||
DeltaASTConverter,
|
||||
type InlineDeltaMatcher,
|
||||
} from '../types/adapter.js';
|
||||
import type { MarkdownAST } from './type.js';
|
||||
|
||||
export type InlineDeltaToMarkdownAdapterMatcher =
|
||||
InlineDeltaMatcher<PhrasingContent>;
|
||||
|
||||
export const InlineDeltaToMarkdownAdapterMatcherIdentifier =
|
||||
createIdentifier<InlineDeltaToMarkdownAdapterMatcher>(
|
||||
'InlineDeltaToMarkdownAdapterMatcher'
|
||||
);
|
||||
|
||||
export function InlineDeltaToMarkdownAdapterExtension(
|
||||
matcher: InlineDeltaToMarkdownAdapterMatcher
|
||||
): ExtensionType & {
|
||||
identifier: ServiceIdentifier<InlineDeltaToMarkdownAdapterMatcher>;
|
||||
} {
|
||||
const identifier = InlineDeltaToMarkdownAdapterMatcherIdentifier(
|
||||
matcher.name
|
||||
);
|
||||
return {
|
||||
setup: di => {
|
||||
di.addImpl(identifier, () => matcher);
|
||||
},
|
||||
identifier,
|
||||
};
|
||||
}
|
||||
|
||||
export type MarkdownASTToDeltaMatcher = ASTToDeltaMatcher<MarkdownAST>;
|
||||
|
||||
export const MarkdownASTToDeltaMatcherIdentifier =
|
||||
createIdentifier<MarkdownASTToDeltaMatcher>('MarkdownASTToDeltaMatcher');
|
||||
|
||||
export function MarkdownASTToDeltaExtension(
|
||||
matcher: MarkdownASTToDeltaMatcher
|
||||
): ExtensionType & {
|
||||
identifier: ServiceIdentifier<MarkdownASTToDeltaMatcher>;
|
||||
} {
|
||||
const identifier = MarkdownASTToDeltaMatcherIdentifier(matcher.name);
|
||||
return {
|
||||
setup: di => {
|
||||
di.addImpl(identifier, () => matcher);
|
||||
},
|
||||
identifier,
|
||||
};
|
||||
}
|
||||
|
||||
export class MarkdownDeltaConverter extends DeltaASTConverter<
|
||||
AffineTextAttributes,
|
||||
MarkdownAST
|
||||
> {
|
||||
constructor(
|
||||
readonly configs: Map<string, string>,
|
||||
readonly inlineDeltaMatchers: InlineDeltaToMarkdownAdapterMatcher[],
|
||||
readonly markdownASTToDeltaMatchers: MarkdownASTToDeltaMatcher[]
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
applyTextFormatting(
|
||||
delta: DeltaInsert<AffineTextAttributes>
|
||||
): PhrasingContent {
|
||||
let mdast: PhrasingContent = {
|
||||
type: 'text',
|
||||
value: delta.attributes?.underline
|
||||
? `<u>${delta.insert}</u>`
|
||||
: delta.insert,
|
||||
};
|
||||
|
||||
const context: {
|
||||
configs: Map<string, string>;
|
||||
current: PhrasingContent;
|
||||
} = {
|
||||
configs: this.configs,
|
||||
current: mdast,
|
||||
};
|
||||
for (const matcher of this.inlineDeltaMatchers) {
|
||||
if (matcher.match(delta)) {
|
||||
mdast = matcher.toAST(delta, context);
|
||||
context.current = mdast;
|
||||
}
|
||||
}
|
||||
|
||||
return mdast;
|
||||
}
|
||||
|
||||
astToDelta(ast: MarkdownAST): DeltaInsert<AffineTextAttributes>[] {
|
||||
const context = {
|
||||
configs: this.configs,
|
||||
options: Object.create(null),
|
||||
toDelta: (ast: MarkdownAST) => this.astToDelta(ast),
|
||||
};
|
||||
for (const matcher of this.markdownASTToDeltaMatchers) {
|
||||
if (matcher.match(ast)) {
|
||||
return matcher.toDelta(ast, context);
|
||||
}
|
||||
}
|
||||
return 'children' in ast
|
||||
? ast.children.flatMap(child => this.astToDelta(child))
|
||||
: [];
|
||||
}
|
||||
|
||||
deltaToAST(
|
||||
deltas: DeltaInsert<AffineTextAttributes>[],
|
||||
depth = 0
|
||||
): PhrasingContent[] {
|
||||
if (depth > 0) {
|
||||
deltas.unshift({ insert: ' '.repeat(4).repeat(depth) });
|
||||
}
|
||||
|
||||
return deltas.map(delta => this.applyTextFormatting(delta));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export * from './block-adapter.js';
|
||||
export * from './delta-converter.js';
|
||||
export * from './type.js';
|
||||
@@ -0,0 +1,17 @@
|
||||
import type { Root, RootContentMap } from 'mdast';
|
||||
|
||||
export type Markdown = string;
|
||||
|
||||
type MdastUnionType<
|
||||
K extends keyof RootContentMap,
|
||||
V extends RootContentMap[K],
|
||||
> = V;
|
||||
|
||||
export type MarkdownAST =
|
||||
| MdastUnionType<keyof RootContentMap, RootContentMap[keyof RootContentMap]>
|
||||
| Root;
|
||||
|
||||
export const isMarkdownAST = (node: unknown): node is MarkdownAST =>
|
||||
!Array.isArray(node) &&
|
||||
'type' in (node as object) &&
|
||||
(node as MarkdownAST).type !== undefined;
|
||||
Reference in New Issue
Block a user