Skip to content

Commit 3f90739

Browse files
authored
Add files via upload
1 parent 11d63f9 commit 3f90739

File tree

11 files changed

+387
-122
lines changed

11 files changed

+387
-122
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,11 @@
33

44
Client-side tool to automatically generate a table of contents for your Markdown document. Simply paste it and a ToC will instantaneously be generated.
55

6-
Check it online [here](//luciopaiva.com/markdown-toc).
6+
Original author [here](//luciopaiva.com/markdown-toc).
7+
8+
# Modifications
9+
- External imports made local [Google Analytics](https://www.google-analytics.com/analytics.js), located /assets/js/analytics.js.
10+
11+
- CSS moved from index.html into style.css with a reference to the styling file.
12+
13+
- Added favicon to index.html

assets/css/style.css

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
:root{
2+
/* Custom Scrollbar - WebKit */
3+
--scrollbarWidthSlim: 6px;
4+
--scrollbarBgColourGradient: linear-gradient(180deg, #d0368a 0%, #708ad4 99%);
5+
}
6+
body {
7+
padding: 0;
8+
margin: 0;
9+
font-family: sans-serif;
10+
background-color: #3b3b3b;
11+
color: white;
12+
}
13+
a, a:hover, a:active, a:visited {
14+
color: #8cd4a8;
15+
text-decoration: none;
16+
margin: 0 5px;
17+
}
18+
.container {
19+
display: grid;
20+
grid-template-columns: 50% 50%;
21+
grid-template-rows: 50px 50px auto 10px;
22+
grid-gap: 10px;
23+
padding: 10px;
24+
width: calc(100vw - 3 * 10px);
25+
height: calc(100vh - 2 * 10px);
26+
}
27+
.header {
28+
display: flex;
29+
justify-content: center;
30+
align-items: flex-end;
31+
font-size: 22px;
32+
}
33+
.area {
34+
resize: none;
35+
background-color: #5b5b5b;
36+
color: #c8c8c8;
37+
border: 1px solid #4e4e4e;
38+
padding: 10px;
39+
font-size: 10px;
40+
font-family: monospace;
41+
}
42+
#title {
43+
grid-column: 1 / 3;
44+
justify-content: flex-start;
45+
align-items: center;
46+
font-size: 32px;
47+
text-align: center;
48+
}
49+
#input-header {
50+
grid-column: 1 / 2;
51+
grid-row: 2 / 3;
52+
}
53+
.output-box {
54+
grid-column: 2 / 3;
55+
grid-row: 3 / 4;
56+
display: flex;
57+
flex-direction: column;
58+
}
59+
.output-level-bar {
60+
display: flex;
61+
flex-direction: row;
62+
border: 1px solid #666;
63+
border-radius: 5px;
64+
padding: 10px;
65+
margin-bottom: 10px;
66+
}
67+
.output-level-bar > * {
68+
margin-right: 4px;
69+
}
70+
.form-component {
71+
box-shadow: inset 0 1px 3px 0 #91b8b3;
72+
border: 1px solid #566963;
73+
border-radius: 5px;
74+
display: inline-block;
75+
font-size: 15px;
76+
font-weight: bold;
77+
padding: 4px 20px;
78+
}
79+
#levels-to-show {
80+
padding: 0 10px;
81+
width: 30px;
82+
}
83+
.button {
84+
background-color: #768d87;
85+
cursor: pointer;
86+
color: #ffffff;
87+
text-decoration: none;
88+
text-shadow: 0 -1px 0 #2b665e;
89+
}
90+
.button:hover {
91+
background-color: #6c7c7c;
92+
}
93+
.button:active {
94+
position: relative;
95+
top: 1px;
96+
}
97+
.label {
98+
display: flex;
99+
align-items: center;
100+
margin-right: 8px;
101+
}
102+
#output-header {
103+
grid-column: 2 / 3;
104+
grid-row: 2 / 3;
105+
}
106+
#input-area {
107+
grid-column: 1 / 2;
108+
grid-row: 3 / 4;
109+
}
110+
#output-area {
111+
height: 100%;
112+
}
113+
.footer {
114+
grid-column: 1 / 3;
115+
grid-row: 4 / 5;
116+
/* display: flex;
117+
justify-content: flex-end;
118+
align-items: center; */
119+
font-size: 11px;
120+
}
121+
122+
.footer #modified
123+
{
124+
float: left;
125+
width: 33%;
126+
text-align: left;
127+
}
128+
129+
.footer #center
130+
{
131+
float: center;
132+
width: 34%;
133+
text-align: center;
134+
}
135+
136+
.footer #original
137+
{
138+
float: right;
139+
width: 33%;
140+
text-align: right;
141+
}
12.8 KB
Loading
42.7 KB
Loading
11.4 KB
Loading
620 Bytes
Loading
1.39 KB
Loading

assets/images/favicon/favicon.ico

15 KB
Binary file not shown.

assets/js/analytics.js

Lines changed: 100 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

assets/js/index.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
2+
class MarkdownToc {
3+
4+
constructor () {
5+
this.inputArea = document.getElementById("input-area");
6+
this.outputArea = document.getElementById("output-area");
7+
this.levelUpButton = document.getElementById("level-up");
8+
this.levelUpButton.addEventListener("click", this.changeLevel.bind(this, +1));
9+
this.levelDownButton = document.getElementById("level-down");
10+
this.levelDownButton.addEventListener("click", this.changeLevel.bind(this, -1));
11+
this.levelsToShowElement = document.getElementById("levels-to-show");
12+
this.levelsToShow = 2;
13+
14+
this.inputArea.addEventListener("input", this.process.bind(this));
15+
this.process();
16+
}
17+
18+
changeLevel(delta) {
19+
this.levelsToShow += delta;
20+
if (this.levelsToShow < 1) {
21+
this.levelsToShow = 1;
22+
} else if (this.levelsToShow > 10) {
23+
this.levelsToShow = 10;
24+
} else if (typeof this.levelsToShow !== "number") {
25+
this.levelsToShow = 2;
26+
}
27+
this.levelsToShowElement.setAttribute("value", this.levelsToShow);
28+
this.process();
29+
}
30+
31+
process() {
32+
const input = this.inputArea.value;
33+
const menus = ["# Table of Contents", ""];
34+
let isCodeBlock = false;
35+
let topLevel = NaN;
36+
let previous = null;
37+
38+
for (let line of input.split("\n")) {
39+
40+
const trimmed = line.trim();
41+
42+
if (trimmed.startsWith("```")) {
43+
isCodeBlock = !isCodeBlock;
44+
}
45+
46+
if (isCodeBlock) {
47+
continue;
48+
}
49+
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) {
95+
if (isNaN(topLevel)) {
96+
topLevel = level;
97+
}
98+
99+
if (level - topLevel >= this.levelsToShow) {
100+
continue;
101+
}
102+
103+
const link = title.toLocaleLowerCase()
104+
.replace(/\s/g, "-")
105+
.replace(/[^A-Za-z0-9-_]/g, "");
106+
const menu = `${" ".repeat(level - topLevel)}- [${title}](#${link})`;
107+
menus.push(menu);
108+
109+
previous = null;
110+
} else {
111+
previous = trimmed;
112+
}
113+
}
114+
115+
this.outputArea.value = menus.join("\n");
116+
}
117+
}

0 commit comments

Comments
 (0)