Add a dynamic Table of Contents

Published with Share Note 🔸 Part of Obsidian guides

Create a toc.js file in your Obsidian vault, with this contents:

/*
Insert a table-of-contents anywhere with:
 
```dataviewjs
dv.view('toc')
```
 
You can specify some optional parameters:
 
```dataviewjs
dv.view('toc', {
    style: '-', // change to bullet style instead of number style
    level: 2, // start at level number X (ignore the levels preceeding that)
    heading: false // disable the "Table of contents" heading
})
```
*/
const startAtLevel = input?.level || 2
const content = await dv.io.load(dv.current().file.path)
const counter = [0, startAtLevel]
let numbers = [1]
const toc = content.match(new RegExp(`^#{${startAtLevel},} \\S.*`, 'mg'))
    .map(heading => {
        const [_, level, text] = heading.match(/^(#+) (.+)$/)
        const link = dv.current().file.path + '#' + text
        if (level.length > counter[1]) {
            counter[0]++
            numbers[counter[0]] = 1
        } else if (level.length < counter[1]) {
            counter[0] = Math.max(0, counter[0] - 1)
            numbers[counter[0]]++
            numbers = numbers.slice(0, counter[0] + 1)
        }
        counter[1] = level.length
        return '\t'.repeat(counter[0]) + `${input?.style || numbers[numbers.length - 1] + '.'} [[${link}|${text}]]`
    })
if (input?.heading !== false) {
    dv.header(2, 'Table of contents')
}
dv.paragraph(toc.join('\n'))

And then in any note which you wish to add a dynamic TOC, you just add this code:

```dataviewjs
dv.view('toc')
```

Change the numbering style

If you want a decimal number style, you can do that via a CSS snippet:

ol {
  list-style-type: none;
  counter-reset: item;
  margin: 0;
  padding: 0;
  padding-inline-start: 10px !important;
}
li {
  display: table;
  counter-increment: item;
  padding-bottom:20px;
}
li:before {
  content: counters(item, ".") ". ";
  display: table-cell;
  padding-right: 0.6em;
  padding-top: 0.2em;
}
li li {
  margin: 0;
}
li li:before {
  content: counters(item, ".") " ";
}

Asked in these threads: