Converting all headings of a page into a list

by slawe

HTML

<article>
                <h2>Dymension: A New Paradigm for Cosmos and the Internet of Rollapps</h2>
                <div class="writing">
                    <p>Written by:</p>

                    <div class="writers">
                        <div class="__wis"><img src="/article_manager/storage/images/users/7_avatar.jpeg" alt="SAM KIM"> <img src="/article_manager/storage/images/users/6_avatar.jpg" alt="JON WONG"> <img src="/article_manager/storage/images/users/5_avatar.jpg" alt="JASMINE WANG"> <img src="/article_manager/storage/images/users/4_avatar.jpg" alt="RIVER FIELDS"></div>
                        <div class="__wns"><strong><span><a href="https://twitter.com/ReliableNarr" target="_blank">SAM KIM</a></span>, <span>JON WONG</span>, <span>JASMINE WANG</span> </strong><em>and</em><strong> <span>RIVER FIELDS</span></strong></div>
                    </div><!-- /.writers -->
                    <div>
                        <span>MARCH 14TH, 2023</span> | <span class="eta">12 minute read</span>
                    </div>
                </div> <!-- /.writing -->
                <p></p><h3>Key Insights</h3><ul><li>Dymension, a Cosmos appchain, is a settlement layer (anchor of a blockchain ecosystem) for Cosmos rollups called RollApps, intending to build the “Internet of RollApps” similar to Cosmos’ goal of developing the “Internet of blockchains”.</li><li>Dymension is a modular blockchain that segregates consensus to its own chain, execution to RollApps, and data availability to DA layers such as Celestia.</li><li>Dymension enables the deployment of enshrined optimistic rollups and plans to implement enshrined validity rollups in the future. Enshrined rollups boast important advantages over non-enshrined rollups including trust minimization, the avoidance of malicious governance attacks and multisig upgrades, and minimization of smart contract risk.</li><li>RollApps deployed on Dymension realize multiple significant benefits relative to other scaling solutions:...

JavaScript

let aside =
{
    nav: function () {
        let result = $('<div/>'),
            headings = $('article > h1,h2,h3,h4,h5,h6'),
            curDepth = 0;

        headings.addClass('bbh_heading');
        $('.bbh_heading').each(function() {

            let title = $(this).text(),
                elId = title.toLowerCase().replaceAll(' ', '_');

            elId = elId.replace(/\W/g, '');
            $(this).attr('id', elId);

            let aHref = $('<a/>').attr('href', '#'+elId).text(title),
                li = $('<li/>').append(aHref),
                depth = parseInt(this.tagName.substring(1));

            if(depth > curDepth) { // going deeper
                result.append($('<ul/>').append(li));
                result = li;
            } else if (depth < curDepth) { // going shallower
                result.parents('ul:eq(' + (curDepth - depth) + ')').append(li);
                result = li;
            } else { // same level
                result.parent().append(li);
                result = li;
            }
            curDepth = depth;
        });

        result = result.parents('ul:last');
        // clean up
        headings.removeClass('bbh_heading');
        // put in element
        $('aside').html(result);
    },
};

aside.nav();