菜单

Markdown 编辑器

相关源文件

本文档描述了 Joplin 的 Markdown 编辑器实现,该实现为桌面和移动平台提供了核心笔记编辑体验。Markdown 编辑器允许用户以 Markdown 格式编写笔记,支持语法高亮、格式化工具和实时预览。有关富文本编辑器的信息,请参阅 富文本编辑器

概述

Joplin 使用 CodeMirror 实现 Markdown 编辑器,这是一个浏览器中通用的文本编辑器。该编辑器旁边有一个笔记查看器组件,可实时渲染 Markdown 内容。桌面和移动平台的实现方式有所不同。

  • 桌面端:直接在 DOM 中使用 CodeMirror,有两种实现方式。
    • 基于 CodeMirror 6 的较新实现。
    • 基于 CodeMirror 5 的旧实现(正在逐步淘汰)。
  • 移动端:采用基于 WebView 的方法,在受控的 Web 环境中加载 CodeMirror。

该编辑器支持语法高亮、Markdown 格式化命令、搜索功能和插件扩展。

来源

编辑器架构

核心组件

编辑器实现围绕几个关键组件构建:

  1. CodeMirrorControl:一个核心类,提供 CodeMirror 功能的高级 API,负责处理命令、事件和状态管理。

  2. createEditor():一个工厂函数,用于初始化新的 CodeMirror 编辑器实例,并带有 Joplin 特定的扩展和配置。

  3. EditorSettings:一个配置接口,用于定义编辑器的行为、外观和功能。

  4. EditorCommandType:一个枚举,列出所有支持的编辑器命令,用于格式化、导航和内容操作。

  5. NoteBody 组件:特定于平台的 React 组件,将编辑器集成到 Joplin 的 UI 中。

来源

桌面实现

桌面端实现将 CodeMirror 直接集成到 React 组件树中。主要组件包括:

  1. CodeMirror.tsx:主要的 React 组件,将编辑器和查看器并排渲染,处理状态管理以及与应用程序其余部分的集成。

  2. Editor.tsx:一个内部组件,用于创建和配置 CodeMirror 编辑器实例。

桌面端实现的关键特性包括:

  • 分屏视图,编辑器和预览并排显示。
  • 通过 CodeMirror 扩展支持插件。
  • 与 Joplin 的命令系统集成。
  • 搜索功能
  • 自定义按键绑定。

来源

移动端实现

移动端实现使用 WebView 加载 CodeMirror,并通过自定义消息传递系统处理 React Native 层和 WebView 之间的通信。

  1. NoteEditor.tsx:一个 React Native 组件,负责创建 WebView 并将 CodeMirror 加载到其中。

  2. CodeMirror.ts:一个脚本,用于在 WebView 中初始化 CodeMirror 并设置与 React Native 层的通信。

移动端实现的关键方面:

  • 使用 WebView 托管 CodeMirror。
  • 保持 React Native 和 WebView 之间的状态同步。
  • 为触摸界面优化的自定义工具栏。
  • 支持资源附件和处理。

来源

编辑器功能

命令系统

编辑器提供了一系列丰富的命令来操作文本和格式化 Markdown 内容。这些命令在 EditorCommandType 枚举中定义,并在 editorCommands 模块中实现。

主要命令类别包括:

  1. 文本格式化

    • 粗体、斜体、代码格式化。
    • 标题
    • 列表(有序、无序、待办事项列表)。
    • 链接、水平分隔线。
  2. 编辑与导航。

    • 光标移动
    • 选择操作。
    • 缩进控制。
    • 行操作(删除、复制、交换)。
  3. 查找与替换。

    • 查找文本
    • 替换匹配项。
    • 正则表达式支持

命令系统允许通过多种来源触发命令:

  • 键盘快捷键
  • 工具栏按钮。
  • 上下文菜单。
  • 程序化 API 调用。

来源

搜索功能

编辑器提供搜索功能,包括编辑器内搜索和与 Joplin 全局搜索系统的集成。

  1. 编辑器内搜索:在当前笔记中进行搜索,并高亮显示匹配项。
  2. 全局搜索集成:高亮显示 Joplin 全局搜索的结果。

搜索实现的关键特性:

  • 实时高亮搜索匹配项。
  • 正则表达式支持
  • 区分大小写的选项。
  • 替换功能。
  • 在搜索结果之间导航。

来源

插件集成

编辑器通过内容脚本系统支持插件,允许扩展编辑器的功能。

插件系统支持:

  • 添加自定义命令。
  • 注册按键绑定。
  • 扩展自动完成功能。
  • 自定义编辑器样式。
  • 内容处理和转换。

来源

编辑器集成

与查看器同步

编辑器与渲染 Markdown 内容为 HTML 的查看器组件协同工作。这两个组件同步以提供分屏编辑体验。

  1. 内容同步:当编辑器中的内容发生更改时,会在查看器中进行渲染。
  2. 滚动同步:两个组件中的滚动会同步,以保持编辑器和预览对齐。
  3. 选择处理:编辑器中的选择可以触发查看器中的相应高亮。

来源

命令处理

编辑器与 Joplin 的命令系统集成,以响应来自各种来源的用户操作。

  1. 命令声明:编辑器命令通过标签、启用条件和图标进行声明。
  2. 命令执行:命令通过 execCommand 方法路由到编辑器。
  3. 命令实现:命令在编辑器控件或专门的命令模块中实现。

来源

技术实现细节

CodeMirror 集成

Markdown 编辑器的核心是与 CodeMirror 的集成,它提供了文本编辑功能。集成包括:

  1. CodeMirrorControl:一个包装类,提供用于与 CodeMirror 交互的更高级 API。
  2. 扩展系统:用于 Markdown 语法高亮、按键绑定和自定义的 CodeMirror 扩展。
  3. 事件系统:将 CodeMirror 事件转换为 Joplin 的事件系统。

为了兼容 CodeMirror 5,还有一个 CodeMirror5Emulation 层,它在 CodeMirror 6 之上提供了类似于 CodeMirror 5 的 API,从而简化了版本之间的迁移。

来源

移动编辑器实现

移动端实现由于 React Native 环境而面临独特的挑战。关键的实现细节包括:

  1. WebView 通信:一个用于在 React Native 和 WebView 之间通信的基于消息的系统。
  2. 编辑器状态管理:同步 WebView 和 React Native 之间的编辑器状态。
  3. 触摸界面适配:修改编辑器以使其能很好地处理触摸输入。

来源

事件处理

编辑器使用事件系统来沟通更改和用户交互。

  1. EditorEventType:所有可能事件类型的枚举。
  2. EditorEvent:事件的基类接口,具有针对不同事件的专门子类型。
  3. 事件流:事件从编辑器流向父组件并触发适当的操作。

关键事件类型包括:

  • 内容修改时的更改事件
  • 光标位置改变时的选择更改事件
  • 滚动事件,用于同步编辑器和查看器
  • 搜索事件,用于搜索相关的状态更改

来源

设置和配置

该编辑器可通过 EditorSettings 接口进行高度配置,该接口控制着编辑器的行为和外观的各个方面。

设置描述默认
language编辑器语言(Markdown 或 HTML)Markdown
readOnly编辑器是否处于只读模式false
themeData主题信息,包括颜色和字体基于 Joplin 主题
keymap键盘映射风格(Default, Vim, Emacs)默认
automatchBraces自动补全匹配的括号true
spellcheckEnabled启用拼写检查基于设置
markdownMarkEnabled启用 Markdown 标记语法支持基于设置
katexEnabled启用 KaTeX 数学语法支持基于设置

来源

此配置系统允许跨平台提供一致的编辑体验,同时也适应平台特定的需求和用户偏好。