Last active
June 25, 2025 06:09
-
-
Save stavarengo/4d62c425b43f877df39351ad3158b64e to your computer and use it in GitHub Desktop.
π Obsidian TOC Generator (DataviewJS snippet)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
try { | |
/** | |
* @typedef {Object} HeadingCache - Extends [CacheItem](https://docs.obsidian.md/Reference/TypeScript+API/CacheItem) | |
* @see https://docs.obsidian.md/Reference/TypeScript+API/HeadingCache | |
* @property {string} heading - The heading text. | |
* @property {number} level - Heading level (1β6). | |
* @property {number} position - Offset of this item in the note (inherited from CacheItem). | |
*/ | |
/** | |
* @typedef {Object} TitleType | |
* @property {number} level - The heading level. | |
* @property {string} text - The original heading text. | |
* @property {string} textToDisplay - The heading text to display. | |
*/ | |
/** @typedef {TitleType[]} TitleTuple */ | |
/** | |
* Extract headings and their levels from the current note. | |
* | |
* @returns {TitleTuple} Array of title objects. | |
*/ | |
const extractHeadings = () => { | |
/** @type {TitleTuple} */ | |
const titles = []; | |
/** @type {HeadingCache[]} */ | |
const headings = | |
dv.app.metadataCache.getFileCache(dv.current().file).headings || []; | |
for (const heading of headings) { | |
let textToDisplay = heading.heading; | |
// If the text is a markdown link, extract the link text. | |
const match = textToDisplay.match(/\[(.*?)]/); | |
if (match) textToDisplay = match[1]; | |
titles.push({ | |
level: heading.level, | |
text: heading.heading, | |
textToDisplay, | |
}); | |
} | |
return titles; | |
}; | |
/** | |
* Render the Table of Contents from the given titles. | |
* | |
* @param {TitleTuple} titles - The titles to render. | |
* @param {string} ident - The indentation string. | |
* @returns {string} | |
*/ | |
const generateTocMarkdown = (titles, ident) => { | |
/** @type {string[]} */ | |
const toc = []; | |
// Find the minimum heading level to adjust indentation. | |
const baseLevel = Math.min(...titles.map((t) => t.level)); | |
for (const title of titles) { | |
const listLevel = title.level - baseLevel + 1; | |
const listMarker = `${ident.repeat(listLevel - 1)}-`; | |
const link = `[[#${title.text}|${title.textToDisplay}]]`; | |
toc.push(`${listMarker} ${link}`); | |
} | |
return toc.join('\n'); | |
}; | |
const identUseTab = dv.app.vault?.config?.useTab ?? true; | |
const ident = identUseTab | |
? '\t' | |
: ' '.repeat(dv.app.vault?.config?.tabSize ?? 4); | |
const titles = extractHeadings(); | |
dv.paragraph('## Table of Contents'); | |
dv.paragraph(generateTocMarkdown(titles, ident)); | |
} catch (e) { | |
dv.paragraph('## Table of Contents [ERROR]'); | |
dv.paragraph(`\`\`\`\n${e.message || e.toString()}\n\`\`\``); | |
// Alternatively, using JSON.stringify() for a more detailed output | |
dv.paragraph("```\n"+JSON.stringify(e, Object.getOwnPropertyNames(e), 2)+"\n```"); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
π Obsidian TOC Generator (DataviewJS)
Creates an in-note Table of Contents from all headings in the current file.
Features
[Text](url) β Text
)[[#Heading|Label]]
)Dependencies
Thatβs itβno additional libraries. Paste once, reuse everywhere.
Usage
toc.js
) anywhere visible to Obsidian β many users keep custom views in aviews/
ordataviewjs/
folder at vault-root.dv.view()
: