Vanilla JS - Converting all headings of a page into a list
by slawe
HTML
<article class="box-w-18 zero-m">
<h2>deAI - Part 2: Decentralized Training</h2>
<div class="writing">
<p>Written by:</p>
<div class="writers">
<div class="__wis"><img src="/article_manager/storage/images/users/2_avatar.jpg" alt="marija"> <img src="/article_manager/storage/images/users/3_avatar.jpg" alt="root"> <img src="/article_manager/storage/images/users/1_avatar.jpeg" alt="admin"></div>
<div class="__wns"><strong><span>marija</span>, <span>root</span> </strong><em>and</em><strong> <span>admin</span></strong></div>
</div><!-- /.writers -->
<div>
<span>DECEMBER 6TH, 2024</span> | <span class="eta">36 minute read</span>
</div>
</div> <!-- /.writing -->
<p></p><p><i>Special thanks to Sam Kim, the team at FortyTwo Network (Vlad Larin, Alex Firsov, Ivan Nikitin), Travis Good (Ambient), Alexander Long (Pluralis), Dillon Rolnick (Nous Research), Flower Labs, Anand Iyer for incredibly valuable discussions, insights and feedback of this report. </i></p><p><i><strong>If you are unfamiliar with the premise of how transformers work in the context of Machine Learning, please read through “Transformers 101” in order to better understand the rest of this report. Feel free to skip around the report as you choose, most sections are agnostic to each other until it all comes together at the very end of the report.</strong></i></p><h1>The Bottleneck</h1><h2>Hardware</h2><p>The multi-headed attention mechanism in transformers, which scales linearly with context length, enables the processing of vast amounts of data in parallel. This groundbreaking approach, while highly efficient, demands extraordinarily large amounts of computational resources. Training large-scale models such as Llama 3 has already pushed boundaries by utilizing...
JavaScript
let aside =
{
headings: null,
hTags: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
article: document.querySelector('article'),
sideNav: document.querySelector('aside'),
init: function ()
{
this.headings = this.article.querySelectorAll(this.hTags.join());
this.sideNav.innerHTML = this.buildTree(this.getHeadings());
},
getHeadings: function ()
{
let headers = [];
this.headings.forEach(el => {
let text = el.innerText,
id = text
.toLowerCase()
.replaceAll(' ', '_')
.replace(/\W/g, '');
if (id === '')
return;
el.setAttribute('id', id);
headers.push({
id,
text,
level: this.hTags.indexOf(el.tagName.toLowerCase())
});
});
return headers;
},
buildTree: function (headers)
{
let list = [],
nextLevelHeaders = [],
lastLevel = -1;
if (headers.length === 0)
return;
let buildSubTree = () => {
if (nextLevelHeaders.length > 0) {
list[list.length - 1] += this.buildTree(nextLevelHeaders);
}
};
headers.forEach(h => {
if (lastLevel !== -1 && lastLevel < h.level) {
nextLevelHeaders.push(h);
return;
}
buildSubTree();
lastLevel = h.level;
list.push(`<a href="#${h.id}">${h.text}</a>`);
nextLevelHeaders = [];
});
buildSubTree();
let listHTML = list.map(i => `<li>${i}</li>`).join("");
return `<ul>${listHTML}</ul>`;
},
};
aside.init();