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')
```
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, ".") " ";
}