5分钟上手Docmost富文本编辑器:从TipTap到企业级扩展开发
Docmost作为开源协作文档平台,其核心竞争力在于基于TipTap构建的高度可扩展富文本编辑器。本文将带你从基础配置到高级扩展,掌握如何在Docmost中开发自定义编辑器功能,解决团队协作中的文档编辑痛点。
编辑器架构概览
Docmost编辑器采用模块化设计,核心扩展位于packages/editor-ext/src/lib目录,包含30+功能模块。通过分析list_code_definition_names的输出结果,可将扩展分为四大类型:
快速开始:基础扩展开发
1. 扩展结构模板
所有编辑器扩展遵循统一的类结构,以custom-code-block.ts为例:
import { Node, mergeAttributes } from '@tiptap/core';
import { ReactNodeViewRenderer } from '@tiptap/react';
export interface CustomExtensionOptions {
HTMLAttributes: Record<string, any>;
view: any; // React组件视图
}
export const CustomExtension = Node.create<CustomExtensionOptions>({
name: 'custom-extension',
priority: 100,
group: 'block',
atom: true,
addOptions() {
return {
HTMLAttributes: {},
view: null
};
},
addAttributes() {
return {
// 定义自定义属性
};
},
parseHTML() {
return [{ tag: `div[data-type="${this.name}"]` }];
},
renderHTML({ HTMLAttributes }) {
return [
'div',
mergeAttributes({ 'data-type': this.name }, HTMLAttributes),
// 渲染内容
];
},
addNodeView() {
return ReactNodeViewRenderer(this.options.view);
}
});
2. 注册扩展到编辑器
在编辑器初始化文件中注册自定义扩展:
import { Editor } from '@tiptap/react';
import { CustomCodeBlock } from './custom-code-block';
const editor = new Editor({
extensions: [
// 基础扩展
CustomCodeBlock.configure({
view: CodeBlockView // 自定义React组件
}),
// 其他扩展...
]
});
核心功能扩展实战
自定义代码块:支持语法高亮与一键复制
custom-code-block.ts扩展了TipTap的code-block-lowlight,实现两大增强功能:
- Tab键缩进:第26-37行通过重写键盘快捷键,在代码块内按Tab键插入两个非断空格
- 全选功能:第38-73行实现
Mod+a快捷键选中整个代码块内容
关键代码片段:
addKeyboardShortcuts() {
return {
Tab: () => {
if (this.editor.isActive("codeBlock")) {
this.editor.chain().insertText("\u00A0\u00A0").run();
return true;
}
},
"Mod-a": () => {
// 实现代码块内容全选逻辑
}
};
}
@提及功能:打通用户协作
mention.ts实现了类似Notion的@提及功能,支持用户和页面两种实体类型。其核心机制是通过@tiptap/suggestion插件实现实时搜索:
suggestion: {
char: "@",
pluginKey: MentionPluginKey,
command: ({ editor, range, props }) => {
editor.chain()
.insertContentAt(range, [
{
type: this.name,
attrs: {
entityType: props.entityType,
entityId: props.entityId,
label: props.label
}
},
{ type: "text", text: " " }
])
.run();
}
}
可视化扩展开发:Excalidraw集成
excalidraw.ts实现了在线绘图功能,通过自定义Node类型支持矢量图的嵌入与编辑:
addCommands() {
return {
setExcalidraw: (attrs) => ({ commands }) => {
return commands.insertContent({
type: 'excalidraw',
attrs: {
src: attrs.src,
title: attrs.title,
attachmentId: attrs.attachmentId
}
});
}
};
}
使用方法:
// 在编辑器中插入绘图
editor.commands.setExcalidraw({
src: 'data:image/svg+xml;base64,...',
title: '系统架构图',
attachmentId: 'att_123456'
});
高级扩展技巧
1. 自定义属性与DOM渲染
所有扩展支持自定义HTML属性,如excalidraw.ts定义的绘图属性:
addAttributes() {
return {
src: {
default: '',
parseHTML: (el) => el.getAttribute('data-src'),
renderHTML: (attrs) => ({ 'data-src': attrs.src })
},
// 其他属性...
};
}
2. React组件视图
通过ReactNodeViewRenderer可以将复杂React组件集成到编辑器中,如代码块的复制按钮、Excalidraw的编辑按钮等:
addNodeView() {
return ReactNodeViewRenderer(CodeBlockView);
}
// React组件示例
const CodeBlockView = (props) => {
return (
<div className="code-block">
<pre>{props.node.attrs.code}</pre>
<button onClick={handleCopy}>复制</button>
</div>
);
};
扩展注册与管理
所有扩展在packages/editor-ext/src/lib/index.ts中统一导出,形成完整的扩展集合:
export * from './custom-code-block';
export * from './excalidraw';
export * from './mention';
// 其他扩展...
在客户端应用中,通过src/components/editor/Editor.tsx集成这些扩展:
import { Editor } from '@tiptap/react';
import * as DocmostExtensions from '@docmost/editor-ext';
const extensions = [
DocmostExtensions.CustomCodeBlock.configure({ view: CodeBlockView }),
DocmostExtensions.Mention.configure({
suggestion: {
items: fetchUsers // 自定义数据源
}
})
];
实战案例:开发流程图扩展
假设需要添加一个新的流程图扩展,可以参考drawio.ts的实现模式,主要步骤:
- 创建
flowchart.ts文件,定义Node类型 - 实现流程图编辑器的React组件视图
- 添加文件上传和数据持久化逻辑
- 在扩展中注册命令和快捷键
扩展开发最佳实践
- 属性设计:所有自定义属性使用
data-*前缀,避免与标准属性冲突 - 性能优化:复杂视图使用React.memo包装,如excalidraw.ts
- 测试覆盖:为关键功能编写单元测试,参考comment.service.spec.ts
- 文档生成:为扩展添加JSDoc注释,便于自动生成API文档
通过本文介绍的方法,你可以为Docmost开发各种自定义编辑器功能。无论是复杂的可视化工具还是简单的交互优化,Docmost的模块化架构都能支持你快速实现。查看editor-ext README获取更多扩展示例和API参考。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



