This is a one-liner that displays an automatically-updating table of contents inside the note, rather than in the sidebar and/or manually copy/pasting.
Maybe i didn’t explain very well.
My suggestion is very simple and doable, we only need a copy button in the core Outline plugin tab
This way we could paste a nicely formatted toc into our notes. I myself wrote a script copying a table of content to the clipboard. Then i copy this wiki-links into my note. It’s a bit manually but hey, i think adding a toc is something you do at the end of the day, basically for your readers and less, for yourself
I’d like to have this one integrated in Obsidian
I love your solution and am using it widely.
I’m not very savvy when it comes to js though and I’d like to remove the numbering. Is that possible within the script, or would I have to do it with css?
There’s not a specific class to the TOC, and I don’t want to hide the numbering everywhere…
Thank you for the dataview script!
Here is a little improvement to handle links that are within headers.
// initially from AlanG (https://forum.obsidian.md/t/new-maintainer-needed-for-dynamic-toc/42381/4)
// 2024/05/02, Sourigna: Added support for links within headers
// Set this to 1 if you want to include level 1 headers,
// or set it to 2 if you want to ignore level 1 headers
const startAtLevel = 1;
const content = await dv.io.load(dv.current().file.path);
const toc = content.match(new RegExp(`^#{${startAtLevel},} \\S.*`, 'mg'))
.map(heading => {
var [_, level, text] = heading.match(/^(#+) (.+)$/);
// Transform links that are inside `text` as their displayed text only ([[my link|displayed text]] => displayed text)
var displayed_text = text;
displayed_text = displayed_text.replace(/\[\[([^\|\[\]]+)\|([^\|\[\]]+)\]\]/g, `$2`);
displayed_text = displayed_text.replace(/\[\[([^\|\[\]]+)\]\]/g, "$1");
// Obsidian strips links characters ("[", "|" and "]") that are within headers
// e.g. ## my header [[lvl2|level 2]]
// becomes [my_file#my header lvl2 level 2]
// For the sake of readability, let's keep only the displayed texts:
// [my_file#my header lvl2 level 2|my header level 2]
text = text.replace(/([\[\]])/g, "");
text = text.replace(/([\|])/g, " ");
const link = dv.current().file.path + '#' + text;
const result = '\t'.repeat(level.length - startAtLevel) + `1. [[${link}|${displayed_text}]]`;
return result;
});
dv.header(2, 'Table of contents');
dv.paragraph(toc.join('\n'));