源码分析:一款开源在线文档编辑器

0. 整体架构流程图

分割线
1.关键阶段说明
(1)初始化阶段
●入口:通过 new Editor(容器, 数据, 配置) 实例化编辑器;
●配置合并:融合默认配置与用户配置,生成最终运行配置;
●数据格式化:formatElementList 标准化页眉/正文/页脚等元素数据结构;
●核心模块实例化:创建位置计算(Position)、绘制引擎(Draw)、选区管理(RangeManager)等核心模块,完成依赖注入。
(2)布局计算阶段
●核心:由 Position 类主导,完成元素/行/页面的坐标、尺寸计算;
●细分逻辑:基础位置计算:遍历行列表,计算每个元素的坐标、宽高、行偏移;
○表格嵌套计算:递归计算表格内单元格的元素位置,支持垂直对齐;
○浮动元素计算:单独维护浮动元素(图片/公式)的位置列表;
○区域定位:区分页眉/页脚/正文区域,返回对应区域的位置列表。
(3)渲染阶段
●绘制引擎(Draw)统筹渲染逻辑,分层次绘制:页面框架层:页眉(Header)、页脚(Footer)、页面边框(PageBorder);
○内容渲染层:文本、LaTex 公式、块元素(视频/IFrame/表格);
○交互层:选区高亮、水印、批注、自定义区域(Area)。
(4)交互响应阶段
●事件监听:监听鼠标/键盘事件,解析光标位置、选区范围;
●命令执行:通过 Command 类封装编辑操作(如插入公式、修改样式);
●重绘触发:交互操作后触发布局重新计算 + Canvas 重绘,保证视图一致性。
2.核心模块与实现逻辑
2.1 核心模块拆解
|
模块名 |
核心文件路径 |
核心职责 |
|
Editor |
src/editor/index.ts |
编辑器入口,聚合所有模块,对外暴露 API(实例化、插件、命令执行) |
|
Position |
src/editor/core/position/Position.ts |
位置计算核心,负责元素/行/页面的坐标、尺寸计算,区分页眉/页脚/表格区域 |
|
RangeManager |
src/editor/core/range/RangeManager.ts |
选区管理,计算光标/选区对应的段落、行信息,支撑文本选择、编辑范围界定 |
|
Draw |
src/editor/core/draw/Draw.ts(隐含) |
绘制引擎,统筹布局计算、Canvas 渲染、交互联动 |
|
LaTexUtils |
src/editor/core/draw/particle/latex/utils/LaTexUtils.ts |
公式渲染工具,解析 LaTex 语法,生成 SVG/PDF/Canvas 可渲染的公式数据 |
|
Area |
src/editor/core/draw/interactive/Area.ts |
自定义区域管理,支持区域级别的只读/编辑控制、背景/边框/占位符渲染 |
|
Event Handlers |
src/editor/core/event/handlers/click.ts 等 |
交互事件解析,如光标选单词、点击选区识别等 |
|
Command |
src/editor/index.ts(Command 类) |
命令系统,封装所有编辑操作,统一执行/撤销逻辑 |
|
Plugin |
src/editor/index.ts(Plugin 类) |
插件管理器,提供 use 方法扩展编辑器功能(如 Word 导入导出) |
2.2 核心模块实现逻辑
(1)Position(位置计算)
●核心属性:维护 positionList(普通元素位置)、floatPositionList(浮动元素位置)、cursorPosition(光标位置);
●核心方法:computePageRowPosition:核心计算逻辑,遍历行列表,计算每个元素的坐标、行偏移,支持表格嵌套递归计算;
○getPositionList:根据当前激活区域(页眉/页脚/正文/表格)返回对应位置列表;
○computePositionList:初始化/更新位置列表,按页面行批量计算。
(2)RangeManager(选区管理)
●核心能力:解析光标/选区对应的段落范围,支持“向上/向下查找”匹配连续段落(按 listId/titleId 分组);
●核心方法:getRangeParagraph,返回选区覆盖的页面-行映射关系,支撑段落级编辑操作(如批量样式修改)。
(3)LaTexUtils(公式渲染)
●核心流程:解析:将 LaTex 字符串分词(tokenize)、语法解析(parse)、生成语法树;
○布局:plan 方法根据公式类型(分式/根式/组合式)计算布局策略;
○渲染:生成多段线(polylines),支持导出 SVG/PDF/Canvas 路径,适配缩放、最大宽高限制。
(4)Area(自定义区域)
●核心能力:区域管理:维护 areaInfoMap,关联区域 ID 与元素/位置列表;
○渲染控制:支持区域背景色、边框、占位符渲染;
○编辑控制:区分 EDIT/READONLY/FORM 模式,控制区域编辑权限;
○数据操作:支持区域值的获取、设置,批量替换区域内元素。
(5)Command(命令系统)
●核心设计:封装所有编辑操作(如插入公式、导入 Word、修改字体),统一入口;
●扩展能力:支持撤销/重做(记录命令执行历史)、插件扩展命令(如 docx 导入导出)。
3. 核心设计模式
3.1 面向对象:封装/继承/多态
●封装:核心模块(Position/Area/LaTexUtils)将状态与逻辑封装在类内部,对外暴露最小化 API(如 compute/render/getXXX);
●继承/多态:块元素基类 BaseBlock 定义通用接口(render/snapshot),VideoBlock/IFrameBlock 继承并实现各自逻辑;
○位置计算区分页眉/页脚/正文,通过 getPositionList 统一返回,底层逻辑不同但接口一致。
3.2 命令模式(Command Pattern)
●应用场景:所有编辑操作(如插入 LaTex 公式、导入 Word、修改文本样式)均封装为命令;
●核心:解耦操作发起者(快捷键/菜单)与执行者(Draw/Position);
○支持撤销/重做(记录命令执行栈);
○统一操作入口,便于扩展和权限控制。
3.3 组合模式(Composite Pattern)
●应用场景:元素渲染体系中,将“单个文本元素”“块元素”“表格/公式”统一抽象为 IElement 数据结构;
●核心:Draw 层通过统一的 computeRowList/drawRow 方法处理不同类型元素,忽略“个体/组合”差异,简化渲染逻辑。
3.4 观察者模式(Observer Pattern)
●应用场景:基于 EventBus 实现模块间通信;
●核心:交互事件(如光标移动、选区变化)发布事件,渲染层监听后触发重绘;
○插件通过订阅事件扩展功能,不侵入核心逻辑;
○解耦事件发起者与响应者,提升模块独立性。
3.5 策略模式(Strategy Pattern)
●应用场景:LaTex 公式渲染:plan 方法根据不同公式指令(\frac/\sqrt)选择不同布局计算策略;
●位置计算:区分页眉/页脚/正文/表格,选择不同的位置列表获取策略;
●核心:统一入口下适配不同场景,便于扩展新策略(如新增公式类型、新区域类型)。
3.6 享元模式(Flyweight Pattern)
●应用场景:BaseBlock 中的 blockCache 缓存已创建的块元素实例;
●核心:避免重复创建 DOM/计算资源,降低渲染性能开销。
3.7 插件模式(Plugin Pattern)
●应用场景:通过 Plugin 类的 use 方法扩展编辑器能力
●核心:核心逻辑与扩展逻辑解耦,官方仅提供核心包,扩展功能通过插件实现。
4. 核心特性与扩展能力
|
功能分类 |
具体能力 |
|
富文本操作 |
撤销/重做、字体/字号/样式(加粗/斜体/下划线)、对齐、标题、列表 |
|
元素插入 |
表格、图片、链接、代码块、分页符、LaTex 公式、日期选择器、自定义控件 |
|
页面排版 |
页眉/页脚/页码、页边距、分页、水印、批注、目录 |
|
交互能力 |
光标/选区控制、拖拽(文本/元素/控件)、右键菜单、自定义快捷键 |
|
导出/打印 |
Canvas 转图片 |
4.2 扩展能力
(1)插件扩展
●自定义插件:通过 editor.use(插件) 扩展,支持新增命令、监听事件、自定义渲染。
(2)自定义交互
●自定义快捷键:覆盖/新增快捷键映射,绑定命令执行;
●自定义右键菜单:扩展右键菜单项,关联自定义命令;
●事件监听:通过 EventBus 订阅编辑器生命周期事件(如光标移动、重绘完成)。
(3)渲染扩展
●多底层支持:默认 Canvas 渲染,可切换至 SVG 渲染(feature/svg 分支);
●PDF 扩展:基于 pdfjs 实现 PDF 绘制(feature/pdf 分支)。
5. 待优化方向
●计算性能:大规模文档下的布局计算性能优化;
●表格能力:表格分页、复杂表格样式(合并单元格、边框定制);
喜欢就关注我吧!
夜雨聆风
