Skip to content

Instantly share code, notes, and snippets.

@gladchinda
Last active September 13, 2022 13:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gladchinda/e6be11a2015f4cc08e18a6b36502b0ba to your computer and use it in GitHub Desktop.
Save gladchinda/e6be11a2015f4cc08e18a6b36502b0ba to your computer and use it in GitHub Desktop.
Hierarchy of Headings

Hierarchy of Headings

Markdown has become quite the standard for static contents like blog posts, notes, readmes, etc as popularized by static site generators (SSGs), with a plethora of packages that can parse and transform markdown content into HTML for rendering. Most content written in markdown have multiple layers of headings, hence it is often required that they be rendered alongside a table of contents (hierarchy of headings) to ease navigation through the content.

Consider a blog being developed using one of the popular SSGs for which all blog posts are written in markdown and a parser is used to transform all markdown content to flat (no nested elements) HTML markup for rendering. Given a markdown that has been transformed to HTML, you are required to build a hierarchy of headings that can be used to render a table of contents alongside the content of the markdown.

Flat list of headings

Since the HTML markup has a flat structure, it is easy to get all the heading elements (h1, h2, h3, h4, h5, h6) and store them in an array as a flat list. To keep things simple, each heading in the list will be stored as an array of two elements — the first being an integer in the range 1 - 6 (both inclusive) that represents the heading level (1 for h1, 2 for h2, etc), while the second is an object containing metadata about the heading like its title, id (for anchored navigation), etc.

Here is some sample code to build up the flat list of headings as described:

const listOfHeadings = Array.from(
  document.querySelectorAll("h1, h2, h3, h4, h5, h6"),
  elem => [
    parseInt(elem.tagName.slice(-1)), // (int) heading level
    { id: elem.id, title: elem.textContent } // (record) heading metadata
  ]
);

Nested list of headings

Given a flat list of headings, a function can be written that rebuilds the flat list into a nested list based on heading hierarchy. Rebuilding the flat list into the nested list can be done in-place (to reduce auxiliary space requirements).

function hierarchyOfHeadings(listOfHeadings) {
  // your code here
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment