Search code examples
quill

Quill.js: Making custom link formats -or- Custom formats with the same tag name


I'm using Quill 1.0.0-rc.1. How can I make several different types of link formats? I've made three different types of link formats that add a data-link-type attribute. When I create the links, it's fine. However, when I reload the content into the editor using pasteHTML, the last registered format wins since the tagNames are all 'A', and so all the data-link-types get set to resource.

So this:

<p>These are the links: 
  <a href="http://www.google.com" data-link-type="external">External</a> 
  <a href="/resources/3" data-link-type="resource">Resource</a>
  <a href="/pages/12" data-link-type="internal">Internal</a>
</p>

Becomes this:

<p>These are the links: 
  <a href="http://www.google.com" data-link-type="resource">External</a> 
  <a href="/resources/3" data-link-type="resource">Resource</a>
  <a href="/pages/12" data-link-type="resource">Internal</a>
</p>

I've included a code pen:

http://codepen.io/anon/pen/akxNNK

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

class ExternalLink extends Inline {
  static create(value) {
    let node = super.create(value);
    value = value.trim();
    if (!value.match(/^http|mailto/)) {
      value = 'http://' + value
    }
    node.setAttribute('href', value);
    node.setAttribute('data-link-type', 'external');
    return node;
  }

  static formats(domNode) {
    return domNode.getAttribute('href');
  }
}

ExternalLink.blotName = 'external_link';
ExternalLink.tagName = 'A';


class InternalLink extends Inline {
  static create(value) {
    let node = super.create(value);
    if (!value.match(/^\/pages\//)) {
      value = '/pages/' + value
    }
    node.setAttribute('href', value);
    node.setAttribute('data-link-type', 'internal');
    return node;
  }

  static formats(domNode) {
    return domNode.getAttribute('href');
  }
}

InternalLink.blotName = 'internal_link';
InternalLink.tagName = 'A';


class ResourceLink extends Inline {
  static create(value) {
    let node = super.create(value);
    if (!value.match(/^\/resources\//)) {
      value = '/resources/' + value
    }
    node.setAttribute('href', value);
    node.setAttribute('data-link-type', 'resource');
    return node;
  }

  static formats(domNode) {
    return domNode.getAttribute('href');
  }
}

ResourceLink.blotName = 'resource_link';
ResourceLink.tagName = 'A';


Quill.register({
  'formats/internal_link': InternalLink,
  'formats/external_link': ExternalLink,
  'formats/resource_link': ResourceLink
});


var quill = new Quill(
  '#editor-container',
  { theme: 'snow' }
);

quill.pasteHTML('<p>These are the links: <a href="http://www.google.com" data-link-type="external">External</a> <a href="/resources/3" data-link-type="resource">Resource</a> <a href="/pages/12" data-link-type="internal">Internal</a></p>');

Solution

  • Quill can use tagName and/or className to map DOM nodes to its document model. Simply setting an attribute in create is not sufficient. This is intentional to allow extraneous attributes like target or rel to be set without that do not contribute meaningful content to the document (if an attribute was meaningful, then you would use an Attributor).

    This forked CodePen has your example working with className. Note when no classname is present, it will use the tagName, which depends on registration order.