Overlapping Inline Annotations with Quill

六眼飞鱼酱① 提交于 2019-11-28 06:35:33

问题


In my application, users can create margin-comments anywhere in the document body, and the comment-anchor ranges can overlap arbitrarily, like this:

This [abc]is a set of [xyz]overlapping[/xyz] comments[/abc]

I'm defining my comment-anchor blot like this:

let Inline = Quill.import('blots/inline');

class CommentAnchorBlot extends Inline  {
  static create(commentId) {
    let node = super.create();
    node.setAttribute("class", "comment-anchor comment-anchor-" + commentId);
    return node;
  }

  static formats(node) {
    var classNames = node.getAttribute('class').split(/\s+/);
    for (var i = 0, len = classNames.length; i < len; i++) {
      var className = classNames[i];
      if (className.indexOf("comment-anchor-") === 0) {
        return className.replace("comment-anchor-", "");
      }
    }
    return null;
  }
}
CommentAnchorBlot.blotName = 'comment';
CommentAnchorBlot.className = 'comment-anchor';
CommentAnchorBlot.tagName = 'span';
Quill.register(CommentAnchorBlot);

But when I test it out in a running Quill instance, it generates parchment like this:

{
  "ops" : [
    { "insert" : "This " },
    { "insert" : "is a set of ", "attributes" : { "comment" : "abc" } },
    { "insert" : "overlapping ", "attributes" : { "comment" : "xyz" } },
    { "insert" : " comments", "attributes" : { "comment" : "abc" } }
  ]
}

Which is problematic, because the word "overlapping" should actually have both "abc" and "xyz" as its comment anchor IDs.

How would you recommend changing the CommentAnchorBlot definition, to accommodate this requirement? I haven't seen any other examples in the Quill documentation that work quite like this.


回答1:


First, I would use a class attributor instead, as it seems unnecessary that a comment get its own DOM node and instead could just be a class applied to other nodes.

Secondly and to your point, most of the time formatting is an overwriting behavior (formatting text color to red, and then blue, makes it blue, not [red, blue]) but you can change this with something like this:

class Comment extends Parchment.Attributor.Class {
  constructor(attrName = 'comment', keyName = 'comment') {
    super(attrName, keyName, { scope: Parchment.Scope.INLINE_ATTRIBUTE });
  }

  add(node, value) {
    if (!this.canAdd(node, value)) return false;
    const array = Array.isArray(value) ? value : [value];
    array.forEach((id) => {
      node.classList.add(`${this.keyName}-${id}`);
    });
    return true;
  }

  remove(node, id) {
    if (id == null) {
      super.remove(node);
    } else {
      node.classList.remove(`${this.keyName}-${id}`);
      if (node.classList.length === 0) {
        node.removeAttribute('class');
      }
    }
  }

  value(node) {
    const prefix = `${this.keyName}-`;
    const list = _.filter(node.classList, (c) => {
      return c.startsWith(prefix);
    }).map((c) => {
      return c.slice(prefix.length);
    });
    return (list.length > 0) ? list : null;
  }
}

Quill.register({ 'formats/comment': new Comment() });


来源:https://stackoverflow.com/questions/45359148/overlapping-inline-annotations-with-quill

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!