Quill的设计考虑了定制化和扩展性。这是通过实现一个小型的编辑器核心,并通过一个粒度细致、定义明确的API公开实现的。核心通过模块进行增强,使用与您相同的API。
一般来说,常见的定制在配置,用户界面由主题和CSS处理,功能由模块处理,编辑器内容由Parchment处理。
配置
Quill倾向于代码优于配置,但对于非常常见的需求,特别是等价代码会很长或复杂的情况下,Quill提供了配置选项。这是一个很好的起点,用来确定您是否需要实现任何自定义功能。
两个最强大的选项是模块和主题。您可以通过简单地添加或删除单个模块或使用不同的主题,来极大地改变或扩展Quill能够和已经做的事情。
主题
Quill官方支持标准工具栏主题Snow和浮动提示主题Bubble。由于Quill不像许多传统编辑器那样局限于iframe内,许多视觉修改只需使用CSS即可完成,使用现有的主题之一。
如果您想大幅度改变UI交互,您可以省略主题配置选项,这将给您一个未经过样式化的Quill编辑器。您仍然需要包含一个最小的样式表,例如,确保所有浏览器中空格都能渲染,有序列表正确编号。
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/quill@2.0.0-rc.4/dist/quill.core.css">
从那里开始,您可以实现并附加您自己的UI元素,如自定义下拉菜单或提示。在“使用Parchment克隆Medium”的最后一部分提供了一个实际示例。
模块
Quill采用了模块化架构设计,由一个小型编辑核心和增强其功能的模块组成。其中一些功能对于编辑非常重要,例如历史模块,它管理撤销和重做。因为所有模块都使用与开发者公开的相同公共API,所以即使是互换核心模块也是可能的,当有必要时。
像Quill的核心本身一样,许多模块都公开了额外的配置选项和API。在决定替换一个模块之前,先看看它的文档。通常,您想要的定制已经作为配置或API调用实现。
否则,如果您想大幅度改变现有模块已经涵盖的功能,您可以简单地不包括它——或者明确排除它,当主题默认包含它时——并在Quill外部实现您喜欢的功能性,使用默认模块使用的相同API。
const quill = new Quill('#editor', {
modules: {
toolbar: false // Snow默认包含工具栏
},
theme: 'snow'
});
一些模块——剪贴板、键盘和历史——需要作为核心功能包含,因为核心功能依赖于它们提供的API。例如,尽管撤销和重做是基本的、预期的编辑功能,但浏览器原生处理这些功能的原生行为是不一致和不可预测的。历史模块通过实现自己的撤销管理器,并公开undo()和redo()作为API,来弥合这一差距。
尽管如此,Quill仍然坚持模块化设计,您仍然可以通过实现自己的撤销管理器来大幅度改变撤销和重做——或任何其他核心功能——的工作方式。只要您实现相同的API接口,Quill就会很高兴地使用您的替代模块。这最容易通过继承现有模块,并覆盖您想要更改的方法来完成。看看模块文档,了解一个非常简单的覆盖核心剪贴板模块的示例。
最后,如果您想添加现有模块未提供的功能。在这种情况下,将其组织为Quill模块可能很方便,构建自定义模块指南涵盖了这一点。当然,将这个逻辑与Quill分开,保留在您的应用程序代码中,也完全是有效的。
内容和格式
Quill允许通过其文档模型Parchment修改和扩展它理解的内容和格式。内容和格式在Parchment中被表示为Blots或Attributors,大致对应于DOM中的节点或属性。
class vs inline
Quill尽可能使用class
,而不是inline
样式属性,但两者都为您实现,供您选择。
const ColorClass = Quill.import('attributors/class/color');
const SizeStyle = Quill.import('attributors/style/size');
Quill.register(ColorClass, true);
Quill.register(SizeStyle, true);
// 像通常一样初始化
const quill = new Quill('#editor', {
modules: {
toolbar: true
},
theme: 'snow'
});
自定义Attributors
除了选择特定的Attributor之外,您还可以自定义现有的Attributors。以下是一个添加额外字体的字体白名单的示例。如果不配置白名单该属性无法被注册到Blots上和生效。
const FontAttributor = Quill.import('attributors/class/font');
FontAttributor.whitelist = [
'sofia', 'slabo', 'roboto', 'inconsolata', 'ubuntu'
];
Quill.register(FontAttributor, true);
注意您仍然需要在CSS文件中为这些类添加样式。
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<style>
.ql-font-roboto {
font-family: 'Roboto', sans-serif;
}
</style>
自定义Blots
由Blots表示的格式也可以定制。以下是您如何更改用于表示加粗格式的DOM节点的示例。
const Bold = Quill.import('formats/bold');
Bold.tagName = 'B'; // Quill默认使用<strong>
Quill.register(Bold, true);
// 像通常一样初始化
const quill = new Quill('#editor', {
modules: {
toolbar: true
},
theme: 'snow'
});
const Delta = Quill.import('delta');
quill.setContents(
new Delta()
.insert('Rendered with <b>!', { bold: true })
.insert('\n')
);
扩展Blots
您还可以扩展现有格式。以下是一个不允许对其内容进行格式化的列表项的快速ES6实现。代码块正是以这种方式实现的。
const ListItem = Quill.import('formats/list/item');
class PlainListItem extends ListItem {
formatAt(index, length, name, value) {
if (name === 'list') {
// 允许更改或删除列表格式
super.formatAt(name, value);
}
// 否则忽略
}
}
Quill.register(PlainListItem, true);
// 像通常一样初始化
const quill = new Quill('#editor', {
modules: {
toolbar: true
},
theme: 'snow'
});
您可以通过调用console.log(Quill.imports);查看可用的Blots和Attributors列表。直接修改此对象是不支持的。使用Quill.register代替。
关于Parchment、Blots和Attributors的完整参考可以在Parchment自己的README上找到。要进行深入的演练,请查看使用Parchment克隆Medium,它从Quill只理解纯文本开始,到添加Medium支持的所有格式。大多数时候,您不需要从头开始构建格式,因为大多数格式已经在Quill中实现,但了解Quill在这个更深层次上的工作原理仍然很有用。