javascriptwikiconfluence

How can I get automatically numbered headings in confluence?


Currently it is not possible in confluence to have the headings of the document structure numbered automatically. I am aware that there are (paid) 3rd party plugins available.

How can I achieve continuous numbered headings?


Solution

  • TL;DR

    Create a bookmark for the following javascript and click it in edit mode in confluence to renumber your headings.

    javascript:(function()%7Bfunction%20addIndex()%20%7Bvar%20indices%20%3D%20%5B%5D%3BjQuery(%22.ak-editor-content-area%20.ProseMirror%22).find(%22h1%2Ch2%2Ch3%2Ch4%2Ch5%2Ch6%22).each(function(i%2Ce)%20%7Bvar%20hIndex%20%3D%20parseInt(this.nodeName.substring(1))%20-%201%3Bif%20(indices.length%20-%201%20%3E%20hIndex)%20%7Bindices%3D%20indices.slice(0%2C%20hIndex%20%2B%201%20)%3B%7Dif%20(indices%5BhIndex%5D%20%3D%3D%20undefined)%20%7Bindices%5BhIndex%5D%20%3D%200%3B%7Dindices%5BhIndex%5D%2B%2B%3BjQuery(this).html(indices.join(%22.%22)%2B%22.%20%22%20%2B%20removeNo(jQuery(this).html()))%3B%7D)%3B%7Dfunction%20removeNo(str)%20%7Blet%20newstr%20%3D%20str.trim()%3Bnewstr%20%3D%20newstr.replace(%2F%5B%5Cu00A0%5Cu1680%E2%80%8B%5Cu180e%5Cu2000-%5Cu2009%5Cu200a%E2%80%8B%5Cu200b%E2%80%8B%5Cu202f%5Cu205f%E2%80%8B%5Cu3000%5D%2Fg%2C'%20')%3Bif(IsNumeric(newstr.substring(0%2Cnewstr.indexOf('%20'))))%7Breturn%20newstr.substring(newstr.indexOf('%20')%2B1).trim()%3B%7Dreturn%20newstr%3B%7Dfunction%20IsNumeric(num)%20%7Bnum%20%3D%20num.split('.').join(%22%22)%3Breturn%20(num%20%3E%3D0%20%7C%7C%20num%20%3C%200)%3B%7DaddIndex()%7D)()
    

    Result

    initial structure numbered structure

    How to use

    After changes to the structure have been made, clicking the bookmarked javascript renumbers the document.

    Limitations are that it only provides n.n.n. numbering, but for many cases that's sufficient. The script can also be customized as required.

    Background, explanation and disclosure

    I tried this TaperMonkey script that apparently resulted from this post, but it didn't work as is. So I took its source code and stripped it of the integration code, old version compatibility and made some minor adjustments to get this:

    function addIndex() {
            var indices = [];
    
                jQuery(".ak-editor-content-area .ProseMirror").find("h1,h2,h3,h4,h5,h6").each(function(i,e) {
                    var hIndex = parseInt(this.nodeName.substring(1)) - 1;
                    if (indices.length - 1 > hIndex) {
                        indices= indices.slice(0, hIndex + 1 );
                    }
                    if (indices[hIndex] == undefined) {
                        indices[hIndex] = 0;
                    }
                    indices[hIndex]++;
                    jQuery(this).html(indices.join(".")+". " + removeNo(jQuery(this).html()));
                });
        }
    
        function removeNo(str) {
            let newstr = str.trim();
            newstr = newstr.replace(/[\u00A0\u1680​\u180e\u2000-\u2009\u200a​\u200b​\u202f\u205f​\u3000]/g,' ');
            if(IsNumeric(newstr.substring(0,newstr.indexOf(' ')))){
                return newstr.substring(newstr.indexOf(' ')+1).trim();
            }
            return newstr;
        }
    
        function IsNumeric(num) {
            num = num.split('.').join("");
            return (num >=0 || num < 0);
        }
        
    addIndex();
    

    (I'm not a JavaScript developer, I'm sure it can be written nicer/better)

    Then I used bookmarklet to convert it into the javascript bookmark at the top, which can be clicked to trigger the functionality.