-
-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathtable_of_contents.ts
69 lines (60 loc) · 2.19 KB
/
table_of_contents.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
/**
* notion-enhancer
* (c) 2022 dragonwocky <thedragonring.bod@gmail.com> (https://dragonwocky.me/)
* (https://notion-enhancer.github.io/) under the MIT license
*/
import { slugify } from "https://deno.land/x/psyche@v0.3.0/indexers/shared.ts";
import type { Site } from "https://deno.land/x/lume@v1.9.1/core.ts";
import type { Element } from "https://deno.land/x/lume@v1.9.1/deps/dom.ts";
import { stringToDocument } from "https://deno.land/x/lume@v1.9.1/core/utils.ts";
interface Heading {
slug: string;
text: string;
}
const crawlSlugs = ($: Element) => {
const slugs: string[] = [],
cache = ($: Element) => {
if ($.hasAttribute("id")) slugs.push($.id);
for (const $child of $.children) cache($child);
};
cache($);
return slugs;
};
// for sidebar toc
export default () => {
return (site: Site) => {
site.preprocess([".html"], (page) => {
// deno-lint-ignore no-explicit-any
const md = <any> site.formats.get(".md")!.engine,
filename = page.src.path + page.src.ext;
if (page.data.table_of_contents || !filename.endsWith(".md")) return;
const content = <string> page.data.content,
headings: Heading[] = [],
document = stringToDocument(
// ignore frontmatter
md.render(content.replace(/^---[\s\S]+?---/, "")),
),
slugs: string[] = crawlSlugs(document.body);
const hSelector = "h1, h2, h3, h4, h5, h6";
for (const node of document.querySelectorAll(hSelector)) {
const $h = <Element> node;
headings.push({
slug: $h.getAttribute("id") ?? slugify($h.innerText, slugs),
text: $h.innerText.replace(/[\n\s]+/, " ").trim(),
});
}
page.data.table_of_contents = headings;
});
site.process([".html"], (page) => {
if (!page.document) return;
const slugs: string[] = crawlSlugs(page.document.body),
hSelector =
".prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6";
for (const node of page.document.querySelectorAll(hSelector)) {
const $h = <Element> node,
id = $h.getAttribute("id") ?? slugify($h.innerText, slugs);
$h.setAttribute("id", id);
}
});
};
};