在对contenteditable元素进行了大量试验之后,我最终 Select 了Quill在聊天应用程序上创建了一个富文本消息框,因为它正确地处理了 Select ,而当直接处理contenteditable元素时, Select 似乎是一团糟.

在我的实验中,我使用了解析innerHTML并将一些字符串替换为对应的emoji Unicode(例如:'<3': '❤️'),并使用Autolinker库将找到的链接替换为我的可编辑元素中的链接标记.

google.com --> <a href="https://www.google.com">google.com</a>

I want to avoid Quill toolbar and replace automatically emojis and links.

所以,我想我必须在某个地方替换编辑的内容…

我对Quill非常陌生,但我知道它使用的是一种名为deltas的特定内部模型,它允许operational transform(如果我错了,请纠正我).

假设这样做了,我将如何判断/解析这些增量,并以保留 Select 和插入符号位置的方式替换其中的特定内容?

References:

https://quilljs.com/guides/designing-the-delta-format/

https://github.com/nadar/quill-delta-parser

推荐答案

您说得对,奎尔使用Delta来描述其内容.要获得当前的增量,可以使用quill.getContents,要设置新的增量,可以使用quill.setContents.

要保留插入符号的位置,可以使用getSelectionsetSelection.

然而,问题是text-change事件发生在DOM更新之后.目前还没有真正内置的,比如before-text-change.这similar Issue有更多关于在text-change事件期间修改内容的问题的详细信息.一种方法是将更新包装在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.replaceAll('<3', '❤️');
      }
      return op;
    });

  queueMicrotask(() => {
    //getSelection be queued after DOM update to get copy-paste position updates  
    const selection = quill.getSelection();
    quill.setContents(newContents, 'silent');
    //don't set caret position if the editor wasn't focused before
    if (selection)
      quill.setSelection(selection.index, 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 <3 </strong> text <3 <3</p>
  <p><br></p>
</div>
<script src="https://cdn.quilljs.com/1.3.6/quill.js"></script>

Javascript相关问答推荐

如何修复循环HTML元素附加函数中的问题?

确定MutationRecord中removedNodes的索引

Vue:ref不会创建react 性属性

按钮未放置在html dis位置

Javascript,部分重排序数组

当作为表达式调用时,如何解析方法decorator 的签名?

覆盖TypeScrip中的Lit-Element子类的属性类型

基于props 类型的不同props ,根据来自接口的值扩展类型

在数组中查找重叠对象并仅返回那些重叠对象

无法避免UV:flat的插值:非法使用保留字"

如何为仅有数据可用的点显示X轴标签?

将Auth0用户对象存储在nextjs类型脚本的Reaction上下文中

用另一个带有类名的div包装元素

如何使用[ModelJSON,ArrayBuffer]调用tf.loadGraphModelSync

如何使用puppeteer操作所有选项

TypeORM QueryBuilder限制联接到一条记录

从异步操作返回对象

当达到高度限制时,如何裁剪图像?使用html和css

如何在函数组件中保留对计时器的引用

正在发出错误的URL请求