如何调整Lexical的Markdown快捷方式插件以保留Markdown语法(而非替换)
如何调整Lexical的Markdown快捷方式插件以保留Markdown语法(而非替换)
我之前也碰到过类似的需求,Lexical默认的Markdown转换逻辑确实是把语法标记直接替换成对应节点的纯文本内容,但其实不用完全重写整套逻辑,有几个更轻量的调整方向可以尝试:
1. 覆盖对应元素的Markdown Transformer(推荐)
Lexical的Markdown插件允许自定义转换规则,你可以针对需要保留语法的元素(比如标题),替换掉默认的Transformer,修改它的文本处理逻辑:
比如针对标题,我们可以重新写一个Heading Transformer,捕获到#符号后不把它移除,而是和标题文本一起保留:
import { HeadingNode, createHeadingNode } from '@lexical/rich-text'; import { TRANSFORMERS } from '@lexical/markdown'; import { createTextNode } from 'lexical'; // 自定义标题转换规则 const CustomHeadingTransformer = { ...TRANSFORMERS.heading, transform: (text, match, state) => { const level = match[1].length; // 获取标题级别(#的数量) // 保留#符号和后续的标题文本,不做截断 const headingContent = match[1] + match[2].trim(); // 创建标题节点并传入完整内容 const headingNode = createHeadingNode(level); headingNode.append(createTextNode(headingContent)); state.addNode(headingNode); state.consumeUntilEndOfLine(); }, }; // 替换默认的标题Transformer const customTransformers = TRANSFORMERS.map(transformer => transformer.type === 'heading' ? CustomHeadingTransformer : transformer ); // 在Markdown插件中使用自定义转换规则 <MarkdownPlugin transformers={customTransformers} />
2. 自定义Lexical节点(适合复杂需求)
如果需要更深度的定制(比如后续要单独处理这些带语法标记的内容),可以创建一个继承自HeadingNode的自定义节点,在节点的解析和序列化逻辑里保留Markdown符号:
import { HeadingNode } from '@lexical/rich-text'; export class CustomHeadingNode extends HeadingNode { static getType() { return 'custom-heading'; } // 重写createDOM方法,确保渲染时保留#符号 createDOM(config) { const dom = super.createDOM(config); // 这里因为我们已经在节点内容里保留了#,所以直接渲染即可 return dom; } // 重写从Markdown解析的逻辑(如果需要) static importDOM() { const domImporter = super.importDOM(); // 调整解析逻辑,确保#符号被保留 return domImporter; } } // 记得在编辑器配置里注册这个节点 const editorConfig = { nodes: [CustomHeadingNode], // 其他配置... };
3. 注意事项
- 只需要针对你需要保留语法的元素做修改,不用替换所有Transformer,比如只改标题就够了,其他元素保持默认逻辑。
- 如果使用自定义节点,必须在编辑器的
nodes配置数组里注册,否则Lexical会识别不了这个节点类型。 - 后续导出HTML的时候,因为我们已经把#符号包含在节点文本里,所以会直接输出
<h1># Heading</h1>,正好符合你的需求。
如果之后要对粗体、斜体等元素做类似处理,逻辑也是一样的——找到对应的默认Transformer,修改它的文本处理逻辑,保留**或*符号即可。
备注:内容来源于stack exchange,提问作者Shaun Fattig




