Friday 1 January 2021

quilljs copyCode module - Failed to execute 'insertBefore' on 'Node'

I am creating a copyCode plugin for QuillJs. Everything seems to be working for the plugin, however, when a space is created between the text and the code-block, you get this error:

Failed to execute 'insertBefore' on 'Node'

Here is the code:

const copyContentIntoClipboard = (rawData: string) => {
  const encodedContent = encodeURIComponent(rawData);
  const filteredEncodedContent = encodedContent.replace(/%EF%BB%BF/g, "");
  const targetContent = decodeURIComponent(filteredEncodedContent);
  const tmpHolder = document.createElement("textarea");
  tmpHolder.value = targetContent;
  document.body.appendChild(tmpHolder);
  tmpHolder.select();
  document.execCommand("copy");
  document.body.removeChild(tmpHolder);
};

const CodeBlock = Quill.import("formats/code-block");

class CopyCode extends CodeBlock {
 copyBadge: HTMLDivElement | null;
  domNode: HTMLElement;
  container: HTMLElement | null;
  parent: HTMLElement;
  copyHandler: EventListener;

  _mountContainer() {
    const container = document.createElement("div");
    container.classList.add("ql-container");
    if (this.domNode.nextSibling) {
      this.domNode.parentElement?.insertBefore(
        container,
        this.domNode
      );
      container.appendChild(this.domNode); // <-- error starts here
      this.container = container;
    }
  }
  _dismountContainer() {

    if (this.container) {
      this.container.parentElement?.insertBefore(
        this.domNode,
        this.container.nextSibling
      );
      this.domNode.parentElement?.removeChild(this.container);
    }
    this.container = null;
  }

  _mountBadge() {
    const copyBadge = document.createElement("div");
    copyBadge.contentEditable = "false";
    copyBadge.classList.add("ql-badge", "ql-badge-copy");
    copyBadge.textContent = "copy";
    this.domNode.parentElement?.insertBefore(
      copyBadge,
      this.domNode.nextSibling
    );
    const copyHandler = (e: MouseEvent) => {
      e.stopPropagation();
      e.preventDefault();
      const target = e.target as HTMLElement;
      const codeArea = target.previousSibling;
      const copyCode = codeArea?.textContent?.trim() || '';
      if (!codeArea) {
        return;
      }
      copyBadge.textContent = "copied!";
      setTimeout(function() {
        copyBadge.textContent = "copy";
      }, 2000);
      copyContentIntoClipboard(copyCode);
    };
    copyBadge.addEventListener("click", copyHandler, true);
    this.copyHandler = copyHandler;
    this.copyBadge = copyBadge;
  }
  _dismountBadge() {
    const badgeIsInDom = this.domNode.parentElement?.contains(this.copyBadge);
    if (this.copyBadge && badgeIsInDom) {
      this.copyBadge.removeEventListener("click", this.copyHandler, true);
      this.copyBadge.parentElement?.removeChild(this.copyBadge);
    }
    this.copyBadge = null;
    this.copyHandler = () => {};
  }

  _mount() {
    this._mountContainer();
    this._mountBadge();
  }

  insertInto(...args: any) {
    super.insertInto(...args);
    const allowCustomMount = !this.copyBadge && !this.container && this.parent;
    if (allowCustomMount) {
      this._mount();
    }
  }
  remove() {
    this._dismountBadge();
    this._dismountContainer();
    super.remove();
  }
}

Here is the StackBlitz: https://stackblitz.com/edit/typescript-ggvuuy?file=index.html

I believe the error is caused by QuillJS believing the code-block should be a pre block instead of a div block containing a pre block. However, I don't know how to fix it...

Any ideas?



from quilljs copyCode module - Failed to execute 'insertBefore' on 'Node'

No comments:

Post a Comment