avycado13 / Quill Paste Fix + Spellcheck Enabler

// ==UserScript==
// @name         Quill Paste Fix + Spellcheck Enabler
// @description  Enables spellcheck and fixes paste handling for .connect-text-area elements
// @match        *://*.quill.org/*
// @grant        none
// @updateURL https://openuserjs.org/meta/avycado13/Quill_Paste_Fix_+_Spellcheck_Enabler.meta.js
// @downloadURL https://openuserjs.org/install/avycado13/Quill_Paste_Fix_+_Spellcheck_Enabler.user.js
// @copyright 2026, avycado13 (https://openuserjs.org/users/avycado13)
// @license MIT
// ==/UserScript==

(function () {
  'use strict';

  function enablePasteFix() {
    const div = document.querySelector('.connect-text-area');
    if (!div) return;

    // Enable spellcheck
    div.setAttribute('spellcheck', 'true');
    div.setAttribute('autocorrect', 'true');
    div.setAttribute('autocapitalize', 'true');

    // Don't attach the paste handler more than once
    if (div.dataset.pasteFixAttached === 'true') return;
    div.dataset.pasteFixAttached = 'true';

    div.addEventListener('paste', (event) => {
      event.preventDefault();

      const text = event.clipboardData.getData('text/plain');

      // Remove things like (begin bold) and (end bold)
      const cleanText = text.replace(/\([^)]*\)/g, "");

      const start = div.selectionStart;
      const end = div.selectionEnd;

      div.setRangeText(cleanText, start, end, 'end');

      div.dispatchEvent(new Event('input', {
        bubbles: true
      }));
    });
  }

  // Run immediately if DOM is ready
  if (document.readyState === 'complete' ||
    document.readyState === 'interactive') {
    enablePasteFix();
  }
  else {
    document.addEventListener('DOMContentLoaded', enablePasteFix);
  }

  // Handle dynamically added elements
  const observer = new MutationObserver(() => {
    enablePasteFix();
  });

  observer.observe(document.body, {
    childList: true,
    subtree: true
  });
})();