Search code examples
quill

Implement custom editor for Quill blot


I'm trying to customize the Quill editor for my needs. I managed to implement and insert custom blots, as described in https://quilljs.com/guides/cloning-medium-with-parchment/ But I need to edit data, which is attached to my blots, like the URL of a link for example. The default implementation of Quill displays a small "inline" edit box for links. I want to implement something like that myself, but just don't get it. I did not find any hints in the docs and guides. Reading the source code of Quill, I was not able to figure out where the editing dialog for links is implemented. Any starting point would be very appreciated.


Solution

  • I've tried something similar. Proper way of doing it should be creating a module. Unfortunately as you already know it is not as easy as it seems.

    Let me point you to some useful resources that helped me a lot with understanding how to create extensions for quill. Quills maintainer is curating Awesome quill list.

    I recommend looking especially into

    • quill-emoji it contains code to display tooltip emoji while writing
    • quill-form maybe some form extension has some code that will point you in the right direction

    Here is my try on to it using custom quill module.

    const InlineBlot = Quill.import('blots/inline');
    
    class NamedLinkBlot extends InlineBlot {
      static create(value) {
        const node = super.create(value);
    
        node.setAttribute('href', value);
        node.setAttribute('target', '_blank');
        return node;
      }
    }
    NamedLinkBlot.blotName = 'namedlink';
    NamedLinkBlot.tagName = 'A';
    
    Quill.register('formats/namedlink', NamedLinkBlot);
    
    const Tooltip = Quill.import('ui/tooltip');
    
    
    class NamedLinkTooltip extends Tooltip {
      show() {
        super.show();
        this.root.classList.add('ql-editing');
      }
    
    
    }
    
    NamedLinkTooltip.TEMPLATE = [
      '<a class="ql-preview" target="_blank" href="about:blank"></a>',
      '<input type="text" data-link="https://quilljs.com">',
      'Url displayed',
      '<input type="text" data-name="Link name">',
      '<a class="ql-action"></a>',
      '<a class="ql-remove"></a>',
    ].join('');
    
    
    const QuillModule = Quill.import('core/module');
    
    class NamedLinkModule extends QuillModule {
      constructor(quill, options) {
        super(quill, options);
        this.tooltip = new NamedLinkTooltip(this.quill, options.bounds);
        this.quill.getModule('toolbar').addHandler('namedlink', this.namedLinkHandler.bind(this));
      }
    
      namedLinkHandler(value) {
        if (value) {
          var range = this.quill.getSelection();
          if (range == null || range.length === 0) return;
          var preview = this.quill.getText(range);
          this.tooltip.show();
        }
      }
    }
    
    Quill.register('modules/namedlink', NamedLinkModule);
    
    const quill = new Quill('#editor', {
        theme: 'snow',
        modules: {
          namedlink: {},
          toolbar: {
            container: [
              'bold',
              'link',
              'namedlink'
            ]
          }
        }
      });
    

    CodePen Demo

    To see the tooltip:

    1. Select any word
    2. Click invisible button on the right of link button, your cursor will turn to hand.

    Main issues that need to be addressed:

    • in order to customize the tooltip you will need to copy majority of the code from SnowTooltip Main pain point is that you cannot easily extend That tooltip.
    • you need to also adapt the code of event listeners but it should be straightforward