javascriptquilltableofcontents

how to create table of contents with quill js


Is there any way to automatically list header tags as a table of content (TOC) in quilljs? I searched it but couldn't find anything useful.

One can add id to header tags with the folloing code but how to create links to them?

let Header = Quill.import('formats/header');
Header.create = function(value) {
let header = document.createElement('h1');
header.id = 'some-unique-id';
  return header;
};

Solution

  • After lots of document reading and effort, I wrote simple, straightforward and also not-optimized JavaScript codes to automatically create a table of contents (TOC) from Quill editor. The main point is that accomplishing this needs two things:

    And thanks to Quill, It is so customizable that these requirements can be implemented.

    Here is the customization of Link module:

                var Link = Quill.import('formats/link');
    
            class MyLink extends Link {
                static create(value) {
                    let node = Link.create(value);
                    value = Link.sanitize(value);
                    node.setAttribute('href', value);
                    if (value.startsWith("#")) {
                        node.removeAttribute('target');
                    } else {
                        node.setAttribute("target", "_blank");
                    }
                    return node;
                }
    
                format(name, value) {
                    super.format(name, value);
    
                    if (name !== this.statics.blotName || !value) {
                        return;
                    }
    
                    if (value.startsWith("#")) {
                        this.domNode.removeAttribute("target");
                    } else {
                        this.domNode.setAttribute("target", "_blank");
                    }
                }
            }
    
            Quill.register(MyLink);
    

    And the following is customized header tag:

                var ids = [];
    
            function getRandomId(domNode) {
                let _id = Math.random().toString(16).slice(2, 9);
                ids.push(_id);
                return _id;
            }
    
            class MyHeader extends Header {
    
                constructor(domNode) {
                    let a = super(domNode);
                    domNode.setAttribute('id', getRandomId(domNode));
                    this.cache = {};
                }
    
                static create(value) {
                    const node = super.create();
                    return node;
                }
    
                static formats(domNode) {
                    return {
                        id: domNode.getAttribute("id")
                    };
                }
            }
    
            Quill.register("formats/header", MyHeader);
            MyHeader.blotName = "header"
    

    Having these new modules, note that in order to create TOC we need several more steps: finding all header tags, add some meaningful id attributes to them and put their list at the beginning of the post.

    For detailed explanation and completed implementation in Laravel, look at this story and for a demo look at this blog post.