mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-25 02:13:00 +08:00
feat(editor): support markdown adapter preprocessed with latex delimiters (#11431)
To close [BS-2870](https://linear.app/affine-design/issue/BS-2870/支持识别-和-[-包裹内容为公式) ## Add Markdown Preprocessor Extension and Enhanced LaTeX Support ### Markdown Preprocessor Extension This PR introduces a new preprocessor extension for Markdown adapters that allows preprocessing of content before conversion: Adds a new PreprocessorManager for handling text transformations Introduces extensible preprocessor interface that supports different processing levels (block/slice/doc) Integrates preprocessor extension into the existing Markdown adapter workflow ### LaTeX Support Enhancement Extends LaTeX support to handle both traditional and alternative syntax: Adds support for backslash LaTeX syntax: Block math: ```\[...\] ``` alongside existing ```$$...$$``` Inline math: ```\(...\) ``` alongside existing ```$...$``` Implements LaTeX preprocessor to standardize syntax before conversion Updates tests to cover both syntax variants
This commit is contained in:
@@ -1,13 +1,13 @@
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { CodeBlockHtmlAdapterExtension } from './html.js';
|
||||
import { CodeBlockMarkdownAdapterExtension } from './markdown.js';
|
||||
import { CodeBlockMarkdownAdapterExtensions } from './markdown/index.js';
|
||||
import { CodeBlockNotionHtmlAdapterExtension } from './notion-html.js';
|
||||
import { CodeBlockPlainTextAdapterExtension } from './plain-text.js';
|
||||
|
||||
export const CodeBlockAdapterExtensions: ExtensionType[] = [
|
||||
CodeBlockHtmlAdapterExtension,
|
||||
CodeBlockMarkdownAdapterExtension,
|
||||
CodeBlockMarkdownAdapterExtensions,
|
||||
CodeBlockPlainTextAdapterExtension,
|
||||
CodeBlockNotionHtmlAdapterExtension,
|
||||
];
|
||||
].flat();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export * from './html.js';
|
||||
export * from './markdown.js';
|
||||
export * from './markdown/index.js';
|
||||
export * from './notion-html.js';
|
||||
export * from './plain-text.js';
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import type { ExtensionType } from '@blocksuite/store';
|
||||
|
||||
import { CodeBlockMarkdownAdapterExtension } from './markdown.js';
|
||||
import { CodeMarkdownPreprocessorExtension } from './preprocessor.js';
|
||||
|
||||
export * from './markdown.js';
|
||||
export * from './preprocessor.js';
|
||||
|
||||
export const CodeBlockMarkdownAdapterExtensions: ExtensionType[] = [
|
||||
CodeMarkdownPreprocessorExtension,
|
||||
CodeBlockMarkdownAdapterExtension,
|
||||
];
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
type MarkdownAdapterPreprocessor,
|
||||
MarkdownPreprocessorExtension,
|
||||
} from '@blocksuite/affine-shared/adapters';
|
||||
|
||||
const codePreprocessor: MarkdownAdapterPreprocessor = {
|
||||
name: 'code',
|
||||
levels: ['slice'],
|
||||
preprocess: content => {
|
||||
let codeFence = '';
|
||||
const lines = content
|
||||
.split('\n')
|
||||
.map(line => {
|
||||
if (line.trimStart().startsWith('-')) {
|
||||
return line;
|
||||
}
|
||||
let trimmedLine = line.trimStart();
|
||||
if (!codeFence && trimmedLine.startsWith('```')) {
|
||||
codeFence = trimmedLine.substring(
|
||||
0,
|
||||
trimmedLine.lastIndexOf('```') + 3
|
||||
);
|
||||
if (codeFence.split('').every(c => c === '`')) {
|
||||
return line;
|
||||
}
|
||||
codeFence = '';
|
||||
}
|
||||
if (!codeFence && trimmedLine.startsWith('~~~')) {
|
||||
codeFence = trimmedLine.substring(
|
||||
0,
|
||||
trimmedLine.lastIndexOf('~~~') + 3
|
||||
);
|
||||
if (codeFence.split('').every(c => c === '~')) {
|
||||
return line;
|
||||
}
|
||||
codeFence = '';
|
||||
}
|
||||
if (
|
||||
!!codeFence &&
|
||||
trimmedLine.startsWith(codeFence) &&
|
||||
trimmedLine.lastIndexOf(codeFence) === 0
|
||||
) {
|
||||
codeFence = '';
|
||||
}
|
||||
if (codeFence) {
|
||||
return line;
|
||||
}
|
||||
|
||||
trimmedLine = trimmedLine.trimEnd();
|
||||
if (!trimmedLine.startsWith('<') && !trimmedLine.endsWith('>')) {
|
||||
// check if it is a url link and wrap it with the angle brackets
|
||||
// sometimes the url includes emphasis `_` that will break URL parsing
|
||||
//
|
||||
// eg. /MuawcBMT1Mzvoar09-_66?mode=page&blockIds=rL2_GXbtLU2SsJVfCSmh_
|
||||
// https://www.markdownguide.org/basic-syntax/#urls-and-email-addresses
|
||||
try {
|
||||
const valid =
|
||||
URL.canParse?.(trimmedLine) ?? Boolean(new URL(trimmedLine));
|
||||
if (valid) {
|
||||
return `<${trimmedLine}>`;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
return line.replace(/^ /, ' ');
|
||||
})
|
||||
.join('\n');
|
||||
|
||||
return lines;
|
||||
},
|
||||
};
|
||||
|
||||
export const CodeMarkdownPreprocessorExtension =
|
||||
MarkdownPreprocessorExtension(codePreprocessor);
|
||||
Reference in New Issue
Block a user