Quill 2.0 富文本编辑器上手:从 README 快速开始到源码级的构建产物与主题机制解析

发布时间:2026/9/6 18:57:51
Quill 2.0 富文本编辑器上手:从 README 快速开始到源码级的构建产物与主题机制解析 Quill 2.0 富文本编辑器上手从 README 快速开始到源码级的构建产物与主题机制解析【免费下载链接】quillQuill is a modern WYSIWYG editor built for compatibility and extensibility项目地址: https://gitcode.com/GitHub_Trending/qu/quill本文基于 Quill 仓库根目录的 README 文档展开覆盖其核心内容——编辑器初始化、npm 安装与 CDN 引入、两种主题与核心构建的区别并结合packages/quill下的源码与构建配置深入解析new Quill()背后的初始化流程、quill.js/quill.core.js两个入口的产物差异、snow/bubble 主题的默认工具栏配置以及仓库的测试与开发约定。读完你可以独立完成 Quill 的接入并理解每个配置项在源码中的落点。项目定位面向兼容性与可扩展性的现代 WYSIWYG 编辑器README 开宗明义Quill 是一个为兼容性与可扩展性而构建的现代富文本编辑器由 Jason Chen 与 Byron Milligan 创建当前由 Slab 团队积极维护。仓库关键词见 根 package.json包含wysiwyg、rich text、operational transformation、ot这提示了 Quill 的核心设计取向文档内容以 Delta操作序列为数据模型编辑器 DOM 只是其呈现层。从依赖看packages/quill/package.jsonQuill 本体只依赖四个运行时库parchmentDOM 与文档之间的抽象层blot 注册表体系quill-deltaDelta 数据模型eventemitter3事件系统lodash-es通用工具函数。这一极简依赖结构也是其兼容性承诺的一部分——编辑器没有强制绑定任何 UI 框架。快速开始一个容器、一个工具栏、一行 new QuillREADME 的 Quickstart 给出了最小可运行示例。这里完整保留原示例CDN 引用来展示最直接的接入方式!-- 引入 Quill 主题样式 -- link hrefhttps://cdn.jsdelivr.net/npm/quill2/dist/quill.snow.css relstylesheet / !-- 创建工具栏容器 -- div idtoolbar button classql-boldBold/button button classql-italicItalic/button /div !-- 创建编辑器容器初始内容会由 Quill 接管 -- div ideditor pHello World!/p pSome initial strongbold/strong text/p pbr //p /div !-- 引入 Quill 库 -- script srchttps://cdn.jsdelivr.net/npm/quill2/dist/quill.js/script !-- 初始化 Quill 编辑器 -- script const quill new Quill(#editor, { theme: snow, }); /script示例中有三个关键点值得注意编辑器容器#editor内的初始 HTML 会被 Quill 读取并转换为内部 Delta 表示。从源码看packages/quill/src/core/quill.ts构造函数会保存容器的innerHTML清空容器随后通过clipboard.convert()把初始 HTML 转成内容并setContents()同时清空历史记录history.clear()。工具栏容器README 示例中#toolbar在编辑器容器外部按钮通过ql-bold、ql-italic这类 class 与工具模块关联。主题在构建按钮时会扫描ql-*class 并注入对应图标见 BaseTheme.buildButtons。theme 选项theme: snow决定了 UI 形态。若不传 theme默认值为default见下文选项表对应不带样式增强、不带默认工具栏的基础主题。new Quill() 做了什么初始化流程源码走读构造函数 Quill.constructor 的执行顺序可以归纳为expandConfig()展开配置解析容器选择器、按名称导入主题类、合并模块配置见下文配置系统给容器加ql-containerclass内部创建ql-editor根节点并加ql-blankclass通过注册表取出ScrollBlot实例化出scroll编辑器根 blot、Editor、Selection、Composition实例化主题对象并强制初始化四个核心模块keyboard、clipboard、history、uploader随后再挂载input、uiNode并调用theme.init()其余模块如 toolbar 在此阶段由主题按需创建监听SCROLL_UPDATE等事件将 DOM 变化MutationObserver 结果归一化为 Delta 变更并触发TEXT_CHANGE若有初始 HTML则经 clipboard 转换后写入若配置了placeholder写入data-placeholder属性若readOnly: true调用disable()禁用编辑。理解这个流程的意义在于README 中传一个 CSS 选择器这么简单的一行调用背后实际完成了注册表查询、模块装配与 DOM 观察器挂载这也是 Quill 能同时支持自定义注册表/自定义格式的扩展入口。两种安装方式npm 与 CDNnpm 安装README 给出的标准命令npm install quillpackages/quill/package.json中声明了main: quill.js与type: module即打包后的dist目录既是 UMD 全局构建浏览器script标签场景也提供 ES 模块形态可直接被 webpack、Vite 等打包器消费。仓库要求npm 8.2.3engines字段engineStrict: true。CDN 引入README 列出了全部 CDN 产物这里原样保留并补充每个产物的用途!-- 主库包含全部内置格式、模块与主题 -- script srchttps://cdn.jsdelivr.net/npm/quill2/dist/quill.js/script !-- 主题样式按所选 theme 选项引入其一 -- link hrefhttps://cdn.jsdelivr.net/npm/quill2/dist/quill.snow.css relstylesheet / link hrefhttps://cdn.jsdelivr.net/npm/quill2/dist/quill.bubble.css relstylesheet / !-- 核心构建无主题、无内置格式、无非必要模块 -- link hrefhttps://cdn.jsdelivr.net/npm/quill2/dist/quill.core.css relstylesheet / script srchttps://cdn.jsdelivr.net/npm/quill2/dist/quill.core.js/script三个构建产物从哪来webpack 入口与注册清单这些文件名并非约定俗成而是由 packages/quill/webpack.common.cjs 的entry字段直接决定entry: { quill: ./src/quill.ts, quill.core: ./src/core.ts, quill.core.css: ./src/assets/core.styl, quill.bubble.css: ./src/assets/bubble.styl, quill.snow.css: ./src/assets/snow.styl, }也就是说完整版与核心版的差异完全体现在两个 TS 入口分别注册了什么packages/quill/src/core.tsquill.core.js只注册基础 blotBlock/Container/Scroll/Text等与核心模块clipboard/history/keyboard/uploader/input/uiNode。选择这个构建意味着你要自己用Quill.register()注册需要的格式与模块体积最小、可控性最高。packages/quill/src/quill.tsquill.js在 core 之上再注册一批开箱即用内容包括attributors 与格式类align、background、color、direction、font、size、indent、blockquote、code-block、header、list、bold、italic、link、script、strike、underline、formula、image、video等src/quill.ts#L53-L116模块syntax代码高亮、table、toolbarUI 组件Icons、Picker、ColorPicker、IconPicker、Tooltip主题themes/bubble、themes/snow。注册机制本身也值得看一眼Quill.register 以blots/、formats/、modules/、themes/为路径命名空间存储到Quill.imports对 blot/格式还会同步注册进全局 Parchment 注册表。Quill.import(name)则按路径取出组件主题与模块的动态加载都依赖它。配置项解析README 未列全的选项源码里的完整清单README 只演示了theme一个选项。真实的选项定义在 QuillOptions 接口 与Quill.DEFAULTSquill.ts#L80-L92中整理如下选项类型默认值说明themestringdefault主题名按themes/name从注册表导入未注册时抛错debugDebugLevel \| boolean未设置日志级别false、error、warn、log、true视为logregistryParchment.Registry全局注册表自定义 blot 注册表指定后将忽略formats选项readOnlybooleanfalse只读模式初始化时调用disable()placeholderstring编辑器为空时显示的占位文本写入data-placeholderboundsHTMLElement \| string \| nullnull悬浮 UI如 tooltip的坐标参照容器modulesRecordstring, unknown见下各模块配置true表示启用并采用模块默认配置formatsstring[] \| nullnull白名单式格式过滤null表示允许全部格式默认启用的核心模块DEFAULTS.modules为clipboard、keyboard、history、uploader且均为true即用各自默认配置。注意toolbar不在core 默认模块里——它由主题或用户在modules中显式启用。配置合并逻辑在 expandConfig主题类静态DEFAULTS→ 用户options.modules逐层合并模块配置值为true时展开为空对象再与模块自身的DEFAULTS合并配置值为 falsy 的模块会被剔除即可以modules: { history: false }禁用模块。另外有一个实用捷径modules.toolbar若传的是选择器字符串或 DOM 节点而非普通对象会被自动改写为{ container: 该值 }——这就是 README 示例中工具栏自动挂载的原因。formats选项与registry互斥若同时指定registry源码会打印警告并忽略formatsquill.ts#L840-L849。若只传formats则通过 createRegistryWithFormats 基于全局注册表派生一个只包含白名单格式的注册表——这是做受限编辑器例如只允许加粗/斜体/链接的官方手段。主题机制snow 与 bubble 在源码中的真实差异README 的 CDN 清单暗示了两个主题样式quill.snow.css与quill.bubble.css。它们的实现分别在 packages/quill/src/themes/snow.ts 与 packages/quill/src/themes/bubble.ts共同继承 BaseTheme。各自的默认工具栏两个主题在构造时若发现toolbar已启用但未指定container会填入各自内置的工具栏布局snow常驻式工具栏置于编辑器上方// src/themes/snow.ts const TOOLBAR_CONFIG: ToolbarConfig [ [{ header: [1, 2, 3, false] }], [bold, italic, underline, link], [{ list: ordered }, { list: bullet }], [clean], ];bubble选中文字时浮起的悬浮工具栏// src/themes/bubble.ts const TOOLBAR_CONFIG: ToolbarConfig [ [bold, italic, link], [{ header: 1 }, { header: 2 }, blockquote], ];snow 主题还会把工具栏容器加ql-snowclass、构建按钮/选择器图标并为.ql-link按钮追加Ctrl/⌘K快捷键绑定snow.ts#L106-L122bubble 主题的 tooltip 则在用户选中文字时出现于选区上方BubbleTooltip 监听SELECTION_CHANGE用getBounds()定位。主题默认 handler链接、图片、公式、视频BaseTheme.DEFAULTS 预置了三个工具栏 handlerimage动态创建input[typefile]accept取自uploader模块的mimetypes配置选中文件后调用quill.uploader.upload(range, files)走上传流程formula/video调起 tooltip 的编辑模式tooltip.edit(formula | video)在浮层中粘贴内容或 URL 后回车插入。snow 主题在其上覆盖了linkhandler选中文字点链接按钮时弹出输入框并内置了看起来像邮箱就自动补mailto:的判断snow.ts#L124-L149。bubble 的link则直接调起 tooltip 编辑。这些 handler 都可以通过modules.toolbar.handlers覆盖——这是 Quill 扩展自定义按钮行为的标准做法。常用 API 速查对照核心源码README 未展开 API但结合 Quill 类 的公开方法日常开发最常用的有const quill new Quill(#editor, { theme: snow }); // 监听内容变化change 是 DeltaoldContents 是旧内容 Delta quill.on(text-change, (delta, oldDelta, source) { const json quill.getContents().ops; // 序列化为 ops便于存库/协作 }); // 读写内容 quill.getContents(); // 全量 Delta quill.getText(); // 纯文本 quill.setContents([{ insert: Hello\n }]); quill.updateContents(new Quill.Delta().retain(1).delete(5)); // 应用 Delta // 选区 quill.getSelection(); // { index, length } | null quill.setSelection(2, 4); // 格式化 quill.format(bold, true); // 作用于当前选区 quill.formatText(0, 5, { header: 1 }); // 指定区间 quill.formatLine(0, 1, align, center); // 状态控制 quill.enable(false); // 等价 disable()加 ql-disabled class quill.disable();这些方法的共同骨架是文件底部的 modify()记录变更前 Delta、执行变更、按变更内容移动选区shiftRange、最后以text-change与editor-change双事件派发且sourceuser/api/silent区分了触发来源——这是理解 Quill 事件流的钥匙。另外Quill.version、Quill.import(delta)、Quill.debug(log)等静态成员也定义在同一文件方便调试与取用 Delta 类。仓库工程结构开发、测试与许可README 尾部还交代了社区入口Issues / Discussions与 BSD 3-clause 许可与 根 package.json 及 packages/quill/package.json 中的BSD-3-Clause一致。从仓库结构看开发侧的几个事实供继续深入者参考这是 npm workspaces monorepopackages/quill编辑器本体v2.0.3与packages/website文档站点与 playground。根package.json的start会并行启动两者的 dev serverwebpack 端口 9080、网站 9000。packages/quill的脚本buildproduction 打包、lintESLint tsc、test:unitVitest配置在 test/unit/vitest.config.ts、test:e2ePlaywrightplaywright.config.ts、test:fuzz模糊测试test/fuzz。单元测试覆盖面与源码模块一一对应例如test/unit/formats/、test/unit/modules/、test/unit/blots/e2e 用例位于test/e2e/如 full.spec.ts。图标资源src/assets/icons/*.svg经html-loader内联进 JS 构建见 webpack.common.cjs 的 svgRules。小结接入路径很简单一个容器 new Quill(selector, { theme })样式与脚本按主题引入quill.snow或quill.bubble。产物分quill.js全量格式、模块、主题与quill.core.js最小核心blot 核心模块由 webpack 入口 明确定义按需选型。配置面theme/modules/formats/registry/placeholder/readOnly/bounds/debug以 QuillOptions 与 expandConfig 为准formats白名单与自定义registry是受限编辑与完全定制的两条路线。snow/bubble 主题的默认工具栏、链接/图片/公式 handler 均可通过modules.toolbar与 handler 覆盖进行二次开发入口类在 themes/snow.ts 与 themes/bubble.ts。【免费下载链接】quillQuill is a modern WYSIWYG editor built for compatibility and extensibility项目地址: https://gitcode.com/GitHub_Trending/qu/quill创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考