在对
contenteditable
元素进行了大量实验之后,我最终选择 Quill 在聊天应用程序上创建富文本消息框,因为它正确处理选择,而直接处理 contenteditable
时,这似乎很混乱元素。
在我的实验中,我用来解析innerHTML并用它们的emoji unicode对应项替换一些字符串(例如:
'<3': '❤️'
),并使用Autolinker库用我的可编辑元素中的链接标签替换找到的链接。
google.com --> <a href="https://www.google.com">google.com</a>
我想避免使用 Quill 工具栏并自动替换表情符号和链接。
所以,我想我必须在某个地方替换编辑器的内容......
我对 Quill 还很陌生,但我知道它正在使用一个名为 deltas 的特定内部模型,该模型允许 操作转换(如果我错了,请纠正我)。
完成这个假设后,我将如何检查/解析这些增量并以保留选择和插入符号位置的方式替换其中的特定内容?
参考资料:
要获取当前的 Delta,您可以使用
quill.getSelection
,要设置新的 Delta,您可以使用 quill.setSelection
。
要保留光标位置,您可以使用
getSelection
和 setSelection
。
但是,问题是
text-change
事件发生在 DOM 更新之后。目前还没有真正内置的,例如before-text-change
。 类似问题有更多关于在text-change
活动期间修改内容问题的详细信息。一种方法是将 DOM 的更新包装在 queueMicrotask
中。
这是一个结合了上述方法的工作示例,将
<3
替换为 ❤️
,尽管它可能存在问题,如问题中所述。
var quill = new Quill('#editor', {
theme: 'snow'
});
quill.on('text-change', update);
update(); //update for initial texts
function update(delta, oldContents, source) {
if (source === 'silent') return;
const newContents = quill.getContents()
.map((op) => {
if (typeof op.insert === 'string') {
op.insert = op.insert.replace('<3', '❤️');
return op;
} else {
return op;
}
})
queueMicrotask(() => {
//won't work with copy-paste if getSelection is not queued after DOM update
const selection = quill.getSelection();
quill.setContents(newContents, 'silent');
quill.setSelection(selection ? selection.index : 0, 0, 'silent');
});
}
<link href="https://cdn.quilljs.com/1.3.6/quill.snow.css" rel="stylesheet">
<div id="editor">
<p>Hello World!</p>
<p>Some initial <strong>bold</strong> text</p>
<p><br></p>
</div>
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>