Skip to content

Commit 3529fbf

Browse files
committed
feat: add auto-generated toc
1 parent c534520 commit 3529fbf

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed

src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
export { preprocessReadme } from "./preprocessReadme";
2-
export { default as default } from "./createConfig";
2+
export { default } from "./createConfig";

src/preprocessReadme.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,24 @@ export function preprocessReadme(opts) {
5555
return {
5656
markup: ({ content, filename }) => {
5757
if (/node_modules/.test(filename) || !filename.endsWith(".md")) return null;
58+
59+
content = content.replace(
60+
"<!-- TOC -->",
61+
`
62+
## Table of Contents
63+
`
64+
);
65+
5866
let script_content = "";
5967
let style_content = "";
6068
let result = md.render(content);
6169
let cursor = 0;
6270

6371
const ast = parse(result);
6472

73+
let headings = [];
74+
let prev;
75+
6576
walk(ast, {
6677
enter(node, parent) {
6778
if (node.type === "Attribute" && node.name === "href") {
@@ -81,6 +92,34 @@ export function preprocessReadme(opts) {
8192
cursor -= replace_style.length;
8293
}
8394

95+
if (node.type === "Element" && node.name === "h2") {
96+
const id = node.attributes.find((attr) => attr.name === "id").value[0].raw;
97+
98+
if (id === "table-of-contents") return;
99+
100+
const text = node.children[0].raw;
101+
if (prev === "h3") {
102+
headings.push(`</ul><li><a href="#${id}">${text}</a></li>`);
103+
} else {
104+
headings.push(`<li><a href="#${id}">${text}</a></li>`);
105+
}
106+
107+
prev = "h2";
108+
}
109+
110+
if (node.type === "Element" && node.name === "h3") {
111+
const id = node.attributes.find((attr) => attr.name === "id").value[0].raw;
112+
const text = node.children[0].raw;
113+
114+
if (prev === "h2") {
115+
headings.push(`<ul><li><a href="#${id}">${text}</a></li>`);
116+
} else {
117+
headings.push(`<li><a href="#${id}">${text}</a></li>`);
118+
}
119+
120+
prev = "h3";
121+
}
122+
84123
if (node.type === "Attribute" && node.name === "data-svelte") {
85124
const raw_value = node.value[0].raw;
86125
const value = decodeURI(raw_value);
@@ -102,6 +141,15 @@ export function preprocessReadme(opts) {
102141
},
103142
});
104143

144+
if (prev === "h3") {
145+
headings.push("</ul>");
146+
}
147+
148+
result = result.replace(
149+
`<h2 id="table-of-contents">Table of Contents</h2>`,
150+
`<p><strong>Table of Contents</strong></p><ul>${headings.join("\n")}</ul>`
151+
);
152+
105153
return {
106154
code: `
107155
<script>${script_content}</script>

test/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# my-svelte-component
22

3+
<!-- TOC -->
4+
35
Relative URL: [Readme](./)
46

57
Relative URL (anchor): [Usage](#usage)
@@ -8,8 +10,13 @@ Absolute URL: [svelte-readme](https://github.com/metonym/svelte-readme)
810

911
Check out my cool component library.
1012

13+
- level 1
14+
- level 2
15+
1116
## Usage
1217

18+
### Basic
19+
1320
```svelte
1421
<script>
1522
import Button from "my-svelte-component";
@@ -31,10 +38,19 @@ Check out my cool component library.
3138
{/each}
3239
```
3340

41+
### Usage with X
42+
43+
## Local storage
44+
45+
**Note**
46+
3447
```js
3548
localStorage.getItem("custom-theme-key");
3649
```
3750

51+
3852
[package.json](package.json)
3953

54+
## License
55+
4056
[MIT](../LICENSE)

0 commit comments

Comments
 (0)