Skip to content

Commit 6e3b258

Browse files
authored
Merge pull request luciopaiva#1 from dnchu/patch-1
Support setext-style headers
2 parents 1a19ce6 + 2c83383 commit 6e3b258

File tree

1 file changed

+53
-5
lines changed

1 file changed

+53
-5
lines changed

index.js

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,20 +33,65 @@ class MarkdownToc {
3333
const menus = ["# Table of contents", ""];
3434
let isCodeBlock = false;
3535
let topLevel = NaN;
36+
let previous = null;
3637

3738
for (let line of input.split("\n")) {
3839

39-
if (line.startsWith("```")) {
40+
const trimmed = line.trim();
41+
42+
if (trimmed.startsWith("```")) {
4043
isCodeBlock = !isCodeBlock;
4144
}
4245

4346
if (isCodeBlock) {
4447
continue;
4548
}
4649

47-
if (line.startsWith("#")) {
48-
const match = line.match(/(#+)\s*(.*?)#*\s*$/);
49-
const level = match[1].length;
50+
let level = NaN;
51+
let title = null;
52+
53+
// Check for:
54+
// 1. ATX-style headers: ## My Header
55+
//
56+
// 2. Setext-style headers:
57+
// a) Level 1 header: My Header
58+
// =========
59+
//
60+
// b) Level 2 header: My Header
61+
// ---------
62+
//
63+
// Edge cases that do not count as headers:
64+
// i) Horizontal rule ("Underline" preceded by empty line):
65+
//
66+
// Some paragraph 1
67+
// <empty line>
68+
// -----
69+
// Some paragraph 2
70+
//
71+
// ii) Two or more horizontal rules:
72+
//
73+
// Some paragraph 1
74+
//
75+
// -----
76+
// -----
77+
// -----
78+
// Some paragraph 2
79+
80+
if (trimmed.startsWith("#")) {
81+
const match = trimmed.match(/(#+)\s*(.*?)#*\s*$/);
82+
level = match[1].length;
83+
title = match[2].trim();
84+
} else if (previous != null && previous.length > 0 && trimmed.length > 0) {
85+
if (trimmed.match(/[^=]/g) == null) {
86+
level = 1;
87+
title = previous;
88+
} else if (trimmed.match(/[^-]/g) == null && previous.match(/[^-]/g) != null) {
89+
level = 2;
90+
title = previous;
91+
}
92+
}
93+
94+
if (!isNaN(level) && title != null) {
5095
if (isNaN(topLevel)) {
5196
topLevel = level;
5297
}
@@ -55,12 +100,15 @@ class MarkdownToc {
55100
continue;
56101
}
57102

58-
const title = match[2].trim();
59103
const link = title.toLocaleLowerCase()
60104
.replace(/\s/g, "-")
61105
.replace(/[^A-Za-z0-9-]/g, "");
62106
const menu = `${" ".repeat(level - topLevel)}- [${title}](#${link})`;
63107
menus.push(menu);
108+
109+
previous = null;
110+
} else {
111+
previous = trimmed;
64112
}
65113
}
66114

0 commit comments

Comments
 (0)