@xiee/utils 1.2.14 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/css/article.css +140 -0
- package/css/article.min.css +1 -0
- package/js/appendix.js +15 -0
- package/js/appendix.min.js +1 -0
- package/js/key-buttons.js +6 -6
- package/js/key-buttons.min.js +1 -1
- package/js/number-sections.js +39 -0
- package/js/number-sections.min.js +1 -0
- package/js/right-quote.js +1 -1
- package/js/right-quote.min.js +1 -1
- package/js/sidenotes.js +31 -0
- package/js/sidenotes.min.js +1 -0
- package/js/toc.js +49 -0
- package/js/toc.min.js +1 -0
- package/package.json +1 -1
package/css/article.css
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
body, blockquote, .side, .menu { background: #fafafa; }
|
|
2
|
+
.article, .body, .appendix { position: relative; }
|
|
3
|
+
.article-list, .body, .single main, .single .appendix, .body ~ .appendix, .frontmatter, .fullwidth, .embed-left, .embed-right {
|
|
4
|
+
margin-top: 2em;
|
|
5
|
+
padding: 1em;
|
|
6
|
+
box-shadow: 0 0 8px #ccc;
|
|
7
|
+
background: #fff;
|
|
8
|
+
}
|
|
9
|
+
.article-meta { background: #f8f8f8; }
|
|
10
|
+
.article-meta .terms, .appendix, .footnotes, main .side > *, .body .side, figcaption, .caption { font-size: .9em; }
|
|
11
|
+
.single .appendix, .body ~ .appendix, .frontmatter { background: none; }
|
|
12
|
+
.appendix h2 { border-bottom: 1px dashed #666; }
|
|
13
|
+
#TOC { top: 0; }
|
|
14
|
+
#TOC ul { list-style-position: inside; }
|
|
15
|
+
#TOC > ul {
|
|
16
|
+
padding: 0;
|
|
17
|
+
margin: 0;
|
|
18
|
+
}
|
|
19
|
+
#TOC li > ul { padding-left: 1em; }
|
|
20
|
+
#TOC .numbered { list-style: none; }
|
|
21
|
+
.bg-number {
|
|
22
|
+
padding: 1px 5px;
|
|
23
|
+
border-radius: 5px;
|
|
24
|
+
background: lightslategray;
|
|
25
|
+
color: #fff;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/* left/right elements*/
|
|
29
|
+
.side {
|
|
30
|
+
width: 200px;
|
|
31
|
+
margin: 0 auto;
|
|
32
|
+
}
|
|
33
|
+
.side-left {
|
|
34
|
+
float: left;
|
|
35
|
+
clear: left;
|
|
36
|
+
margin-left: calc(-200px - 2em);
|
|
37
|
+
position: sticky;
|
|
38
|
+
}
|
|
39
|
+
.side-right {
|
|
40
|
+
float: right;
|
|
41
|
+
clear: right;
|
|
42
|
+
margin-right: calc(-200px - 2em);
|
|
43
|
+
}
|
|
44
|
+
.quote-left, .quote-right { width: 45%; }
|
|
45
|
+
.embed-left, .embed-right {
|
|
46
|
+
margin-top: auto;
|
|
47
|
+
padding: 0;
|
|
48
|
+
}
|
|
49
|
+
.quote-left, .embed-left {
|
|
50
|
+
float: left;
|
|
51
|
+
margin-right: 1em;
|
|
52
|
+
}
|
|
53
|
+
.quote-right, .embed-right {
|
|
54
|
+
float: right;
|
|
55
|
+
margin-left: 1em;
|
|
56
|
+
}
|
|
57
|
+
.embed-left { margin-left: calc(-200px - 2em); }
|
|
58
|
+
.embed-right { margin-right: calc(-200px - 2em); }
|
|
59
|
+
.side > :first-child, .embed-left > :first-child, .embed-right > :first-child { margin-top: 0; }
|
|
60
|
+
.embed-left > :last-child, .embed-right > :last-child { margin-bottom: 0; }
|
|
61
|
+
.quote-left > :first-child, .quote-right > :first-child { padding-top: .1px; }
|
|
62
|
+
.quote-left > :last-child, .quote-right > :last-child { padding-bottom: .1px; }
|
|
63
|
+
|
|
64
|
+
/* wide elements */
|
|
65
|
+
.fullwidth, .fullwidth * { margin: auto 0; }
|
|
66
|
+
.fullwidth * { max-width: calc(100vw - 4em); }
|
|
67
|
+
.fullscroll * { max-width: initial; }
|
|
68
|
+
.fullwidth {
|
|
69
|
+
max-width: calc(100vw - 2em);
|
|
70
|
+
margin: 1em 0 1em 50%;
|
|
71
|
+
transform: translateX(-50%);
|
|
72
|
+
float: left;
|
|
73
|
+
min-width: 100%;
|
|
74
|
+
background: #fff;
|
|
75
|
+
}
|
|
76
|
+
.fullscroll, .fullscroll figure, .fullscroll .figure { overflow-x: auto; }
|
|
77
|
+
.fullwidth figcaption, .fullwidth .caption {
|
|
78
|
+
margin-left: calc(50% - 400px);
|
|
79
|
+
width: 800px;
|
|
80
|
+
padding: 1em 1em 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@media (min-width: 1280px) {
|
|
84
|
+
.note-ref { cursor: pointer; }
|
|
85
|
+
.note-ref:hover ~ .side {
|
|
86
|
+
display: inline-block;
|
|
87
|
+
background-color: #f8f8f8;
|
|
88
|
+
position: absolute;
|
|
89
|
+
margin-left: 1em;
|
|
90
|
+
padding: .5em;
|
|
91
|
+
box-sizing: content-box;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
@media (max-width: 1280px) {
|
|
95
|
+
#TOC {
|
|
96
|
+
border: 1px solid #eee;
|
|
97
|
+
border-radius: 5px;
|
|
98
|
+
padding: 1em;
|
|
99
|
+
position: initial;
|
|
100
|
+
}
|
|
101
|
+
.side { width: 100%; }
|
|
102
|
+
main .side, .body .side {
|
|
103
|
+
padding: 0 2em;
|
|
104
|
+
color: darkslategray;
|
|
105
|
+
}
|
|
106
|
+
.side-left, .side-right {
|
|
107
|
+
clear: both;
|
|
108
|
+
margin: 1em auto;
|
|
109
|
+
background: none;
|
|
110
|
+
}
|
|
111
|
+
.note-ref ~ .side { margin-left: 100vw; }
|
|
112
|
+
.side > :last-child { margin-bottom: 0; }
|
|
113
|
+
.embed-left, .embed-right {
|
|
114
|
+
float: inherit;
|
|
115
|
+
margin: auto;
|
|
116
|
+
padding: 1em;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
@media (max-width: 800px) {
|
|
120
|
+
body { padding: initial; }
|
|
121
|
+
main, .body { padding: 0 .5em 0; }
|
|
122
|
+
.quote-left, .quote-right {
|
|
123
|
+
width: inherit;
|
|
124
|
+
float: inherit;
|
|
125
|
+
margin: auto;
|
|
126
|
+
}
|
|
127
|
+
.fullwidth:not(.fullscroll) * { max-width: 100%; }
|
|
128
|
+
.fullwidth {
|
|
129
|
+
margin: initial;
|
|
130
|
+
transform: initial;
|
|
131
|
+
float: none;
|
|
132
|
+
min-width: initial;
|
|
133
|
+
background: none;
|
|
134
|
+
border: none;
|
|
135
|
+
}
|
|
136
|
+
.fullwidth figcaption, .fullwidth .caption {
|
|
137
|
+
margin: initial;
|
|
138
|
+
padding: initial;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.menu,.side,blockquote,body{background:#fafafa}.appendix,.article,.body{position:relative}.article-list,.body,.body~.appendix,.embed-left,.embed-right,.frontmatter,.fullwidth,.single .appendix,.single main{margin-top:2em;padding:1em;box-shadow:0 0 8px #ccc;background:#fff}.article-meta{background:#f8f8f8}.appendix,.article-meta .terms,.body .side,.caption,.footnotes,figcaption,main .side>*{font-size:.9em}.body~.appendix,.frontmatter,.single .appendix{background:0 0}.appendix h2{border-bottom:1px dashed #666}#TOC{top:0}#TOC ul{list-style-position:inside}#TOC>ul{padding:0;margin:0}#TOC li>ul{padding-left:1em}#TOC .numbered{list-style:none}.bg-number{padding:1px 5px;border-radius:5px;background:#778899;color:#fff}.side{width:200px;margin:0 auto}.side-left{float:left;clear:left;margin-left:calc(-200px - 2em);position:sticky}.side-right{float:right;clear:right;margin-right:calc(-200px - 2em)}.quote-left,.quote-right{width:45%}.embed-left,.embed-right{margin-top:auto;padding:0}.embed-left,.quote-left{float:left;margin-right:1em}.embed-right,.quote-right{float:right;margin-left:1em}.embed-left{margin-left:calc(-200px - 2em)}.embed-right{margin-right:calc(-200px - 2em)}.embed-left>:first-child,.embed-right>:first-child,.side>:first-child{margin-top:0}.embed-left>:last-child,.embed-right>:last-child{margin-bottom:0}.quote-left>:first-child,.quote-right>:first-child{padding-top:.1px}.quote-left>:last-child,.quote-right>:last-child{padding-bottom:.1px}.fullwidth,.fullwidth *{margin:auto 0}.fullwidth *{max-width:calc(100vw - 4em)}.fullscroll *{max-width:initial}.fullwidth{max-width:calc(100vw - 2em);margin:1em 0 1em 50%;transform:translateX(-50%);float:left;min-width:100%;background:#fff}.fullscroll,.fullscroll .figure,.fullscroll figure{overflow-x:auto}.fullwidth .caption,.fullwidth figcaption{margin-left:calc(50% - 400px);width:800px;padding:1em 1em 0}@media (min-width:1280px){.note-ref{cursor:pointer}.note-ref:hover~.side{display:inline-block;background-color:#f8f8f8;position:absolute;margin-left:1em;padding:.5em;box-sizing:content-box}}@media (max-width:1280px){#TOC{border:1px solid #eee;border-radius:5px;padding:1em;position:initial}.side{width:100%}.body .side,main .side{padding:0 2em;color:#2f4f4f}.side-left,.side-right{clear:both;margin:1em auto;background:0 0}.note-ref~.side{margin-left:100vw}.side>:last-child{margin-bottom:0}.embed-left,.embed-right{float:inherit;margin:auto;padding:1em}}@media (max-width:800px){body{padding:initial}.body,main{padding:0 .5em 0}.quote-left,.quote-right{width:inherit;float:inherit;margin:auto}.fullwidth:not(.fullscroll) *{max-width:100%}.fullwidth{margin:initial;transform:initial;float:none;min-width:initial;background:0 0;border:none}.fullwidth .caption,.fullwidth figcaption{margin:initial;padding:initial}}
|
package/js/appendix.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// find <h[1-6] class="appendix"> and create a new <div> next to the parent
|
|
2
|
+
// element to hold all appendix elements
|
|
3
|
+
(d => {
|
|
4
|
+
const h = d.querySelector([1, 2, 3, 4, 5, 6].map(i => `h${i}.appendix`).join(','));
|
|
5
|
+
if (!h) return;
|
|
6
|
+
h.classList.remove('appendix');
|
|
7
|
+
const a = d.createElement('div');
|
|
8
|
+
a.className = 'appendix';
|
|
9
|
+
a.append(h.cloneNode(true));
|
|
10
|
+
h.parentNode.after(a);
|
|
11
|
+
while(h.nextSibling) {
|
|
12
|
+
a.append(h.nextSibling);
|
|
13
|
+
}
|
|
14
|
+
h.remove();
|
|
15
|
+
})(document);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(e=>{const n=e.querySelector([1,2,3,4,5,6].map((e=>`h${e}.appendix`)).join(","));if(!n)return;n.classList.remove("appendix");const a=e.createElement("div");for(a.className="appendix",a.append(n.cloneNode(!0)),n.parentNode.after(a);n.nextSibling;)a.append(n.nextSibling);n.remove()})(document);
|
package/js/key-buttons.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
(
|
|
1
|
+
(d => {
|
|
2
2
|
const a1 = ['Enter', 'Up', 'Down', 'Left', 'Right'];
|
|
3
3
|
const a2 = ['↵', '↑', '↓', '←', '→'];
|
|
4
4
|
function drawArrows(x) {
|
|
5
|
-
a1.map((v, i) => x = x.replace(new RegExp(
|
|
5
|
+
a1.map((v, i) => x = x.replace(new RegExp(`>${v}<`, 'g'), ` title="${v + (i ? ' Arrow' : '')}">${a2[i]}<`));
|
|
6
6
|
return x;
|
|
7
7
|
}
|
|
8
8
|
// 1. individual keys; 2. modifiers; 3. normal keys
|
|
@@ -10,14 +10,14 @@
|
|
|
10
10
|
Array(12).fill().map((v, i) => 'F' + (i + 1)).concat(a1).join('|'),
|
|
11
11
|
k2 = 'Ctrl|Control|Shift|Alt|Cmd|Command|fn',
|
|
12
12
|
k3 = '[a-zA-Z0-9]|Click',
|
|
13
|
-
r1 = new RegExp(
|
|
14
|
-
r2 = new RegExp(
|
|
15
|
-
r3 = new RegExp(
|
|
13
|
+
r1 = new RegExp(`^(${k1}|${k2})$`),
|
|
14
|
+
r2 = new RegExp(`^(${k2}) [/+] `),
|
|
15
|
+
r3 = new RegExp(`^(${k1}|${k2}|${k3})( [/+] )(.*)`);
|
|
16
16
|
d.querySelectorAll(':not(pre) > code').forEach(el => {
|
|
17
17
|
if (el.childElementCount > 0) return;
|
|
18
18
|
let t = el.innerText;
|
|
19
19
|
if (r1.test(t)) {
|
|
20
|
-
el.outerHTML = drawArrows(
|
|
20
|
+
el.outerHTML = drawArrows(`<kbd>${t}</kbd>`);
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
if (!r2.test(t)) return;
|
package/js/key-buttons.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
(e=>{const r=["Enter","Up","Down","Left","Right"],t=["↵","↑","↓","←","→"];function n(e){return r.map(((r,n)=>e=e.replace(new RegExp(`>${r}<`,"g"),` title="${r+(n?" Arrow":"")}">${t[n]}<`))),e}const o="Esc|Tab|PageUp|PageDown|Space|Delete|Home|End|PrtScr?|PrintScreen|"+Array(12).fill().map(((e,r)=>"F"+(r+1))).concat(r).join("|"),a="Ctrl|Control|Shift|Alt|Cmd|Command|fn",c=new RegExp(`^(${o}|${a})$`),l=new RegExp(`^(${a}) [/+] `),i=new RegExp(`^(${o}|${a}|[a-zA-Z0-9]|Click)( [/+] )(.*)`);e.querySelectorAll(":not(pre) > code").forEach((e=>{if(e.childElementCount>0)return;let r=e.innerText;if(c.test(r))return void(e.outerHTML=n(`<kbd>${r}</kbd>`));if(!l.test(r))return;let t="";for(r+=" + ";i.test(r);)t+=r.replace(i,"<kbd>$1</kbd>$2"),r=r.replace(i,"$3");""===r&&(e.outerHTML=n(t.replace(/ \+ $/,"")))}))})(document);
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
// add section numbers to headings
|
|
2
|
+
(d => {
|
|
3
|
+
// find the body of the article
|
|
4
|
+
const b = d.querySelector('.article, .body, article, body');
|
|
5
|
+
if (!b) return;
|
|
6
|
+
const hs = b.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
|
7
|
+
if (hs.length === 0) return;
|
|
8
|
+
// normalize Pandoc's .header-section-number class to .section-number
|
|
9
|
+
b.querySelectorAll('span.header-section-number').forEach(el => {
|
|
10
|
+
el.classList.add('section-number');
|
|
11
|
+
});
|
|
12
|
+
// already numbered?
|
|
13
|
+
if (b.querySelector('span.section-number')) {
|
|
14
|
+
// avoid Pandoc's numbering from 0 (e.g., 0.1, 0.1.1, 0.2, ...) when top-level heading is not h1
|
|
15
|
+
b.querySelectorAll('span.section-number').forEach(s => {
|
|
16
|
+
s.innerText = s.innerText.replace(/^(0\.)+/, '');
|
|
17
|
+
});
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
let t0 = 0, t1, dict = [0, 0, 0, 0, 0, 0];
|
|
21
|
+
// generate section numbers x.x.x
|
|
22
|
+
function number_section(i) {
|
|
23
|
+
dict[i]++;
|
|
24
|
+
const n = dict.join('.').replace(/^(0\.)+|(\.0)+$/g, '').replace(/^([0-9]+)$/, '$1.');
|
|
25
|
+
return `<span class="section-number">${n}</span> `;
|
|
26
|
+
};
|
|
27
|
+
hs.forEach(h => {
|
|
28
|
+
// header level: <hN> -> N
|
|
29
|
+
t1 = parseInt(h.tagName.replace(/^h/i, ''));
|
|
30
|
+
// when moving to a higher-level heading, reset lower-level counters to 0
|
|
31
|
+
if (t1 < t0) {
|
|
32
|
+
for (let j = t1; j < dict.length; j++) {
|
|
33
|
+
dict[j] = 0;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
h.insertAdjacentHTML('afterbegin', number_section(t1 - 1));
|
|
37
|
+
t0 = t1;
|
|
38
|
+
});
|
|
39
|
+
})(document);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(e=>{const r=document.querySelector(".article, .body, article, body");if(!r)return;const n=r.querySelectorAll("h1, h2, h3, h4, h5, h6");if(0===n.length)return;if(r.querySelectorAll("span.header-section-number").forEach((e=>{e.classList.add("section-number")})),r.querySelector("span.section-number"))return void r.querySelectorAll("span.section-number").forEach((e=>{e.innerText=e.innerText.replace(/^(0\.)+/,"")}));let t,c=0,a=[0,0,0,0,0,0];n.forEach((e=>{if(t=parseInt(e.tagName.replace(/^h/i,"")),t<c)for(let e=t;e<a.length;e++)a[e]=0;e.insertAdjacentHTML("afterbegin",(a[t-1]++,`<span class="section-number">${a.join(".").replace(/^(0\.)+|(\.0)+$/g,"").replace(/^([0-9]+)$/,"$1.")}</span> `)),c=t}))})();
|
package/js/right-quote.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// right-align a quote footer if it starts with ---
|
|
2
2
|
[...document.getElementsByTagName('blockquote')].forEach(quote => {
|
|
3
3
|
const el = quote.lastElementChild;
|
|
4
|
-
if (el?.tagName === 'P' &&
|
|
4
|
+
if (el?.tagName === 'P' && /^(—|---)/.test(el.textContent)) el.style.textAlign = 'right';
|
|
5
5
|
});
|
package/js/right-quote.min.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
[...document.getElementsByTagName("blockquote")].forEach((t=>{const e=t.lastElementChild;"P"===e?.tagName
|
|
1
|
+
[...document.getElementsByTagName("blockquote")].forEach((t=>{const e=t.lastElementChild;"P"===e?.tagName&&/^(—|---)/.test(e.textContent)&&(e.style.textAlign="right")}));
|
package/js/sidenotes.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// move footnotes (ids start with fn) and citations (ids start with ref-) to sidenotes
|
|
2
|
+
(d => {
|
|
3
|
+
d.querySelectorAll('.footnotes > ol > li[id^="fn"], #refs > div[id^="ref-"]').forEach(el => {
|
|
4
|
+
// find <a> that points to note id in body
|
|
5
|
+
const h = `a[href="#${el.id}"]`,
|
|
6
|
+
a = d.querySelector(`${h} > sup, sup > ${h}, .citation > ${h}`);
|
|
7
|
+
if (!a) return;
|
|
8
|
+
const a2 = a.parentNode;
|
|
9
|
+
(a.tagName === 'A' ? a : a2).removeAttribute('href');
|
|
10
|
+
const s = d.createElement('div'); // insert a side div next to a2 in body
|
|
11
|
+
s.className = 'side side-right';
|
|
12
|
+
if (/^fn/.test(el.id)) {
|
|
13
|
+
s.innerHTML = el.innerHTML;
|
|
14
|
+
// add footnote number
|
|
15
|
+
s.firstElementChild.insertAdjacentHTML('afterbegin', `<span class="bg-number">${a.innerText}</span> `);
|
|
16
|
+
s.querySelector('a[href^="#fnref"]')?.remove(); // remove backreference
|
|
17
|
+
} else {
|
|
18
|
+
s.innerHTML = el.outerHTML;
|
|
19
|
+
}
|
|
20
|
+
// insert note after the <sup> or <span> that contains a
|
|
21
|
+
a2.after(s);
|
|
22
|
+
a2.classList.add('note-ref');
|
|
23
|
+
el.remove();
|
|
24
|
+
});
|
|
25
|
+
// remove the footnote/citation section if it's empty now
|
|
26
|
+
d.querySelectorAll('.footnotes, #refs').forEach(el => {
|
|
27
|
+
/^\s*$/.test(el.innerText) && el.remove();
|
|
28
|
+
});
|
|
29
|
+
// also add side classes to TOC
|
|
30
|
+
d.getElementById('TOC')?.classList.add('side', 'side-left');
|
|
31
|
+
})(document);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(e=>{e.querySelectorAll('.footnotes > ol > li[id^="fn"], #refs > div[id^="ref-"]').forEach((t=>{const r=`a[href="#${t.id}"]`,n=e.querySelector(`${r} > sup, sup > ${r}, .citation > ${r}`);if(!n)return;const s=n.parentNode;("A"===n.tagName?n:s).removeAttribute("href");const i=e.createElement("div");i.className="side side-right",/^fn/.test(t.id)?(i.innerHTML=t.innerHTML,i.firstElementChild.insertAdjacentHTML("afterbegin",`<span class="bg-number">${n.innerText}</span> `),i.querySelector('a[href^="#fnref"]')?.remove()):i.innerHTML=t.outerHTML,s.after(i),s.classList.add("note-ref"),t.remove()})),e.querySelectorAll(".footnotes, #refs").forEach((e=>{/^\s*$/.test(e.innerText)&&e.remove()})),e.getElementById("TOC")?.classList.add("side","side-left")})(document);
|
package/js/toc.js
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// build TOC using headings
|
|
2
|
+
(d => {
|
|
3
|
+
// find the body of the article
|
|
4
|
+
const b = d.querySelector('.article, .body, article, body');
|
|
5
|
+
if (!b) return;
|
|
6
|
+
const hs = b.querySelectorAll('h1, h2, h3, h4, h5, h6');
|
|
7
|
+
if (hs.length === 0) return;
|
|
8
|
+
|
|
9
|
+
var toc = b.getElementById('TOC');
|
|
10
|
+
toc?.remove(); // delete and rebuild TOC if it has been generated (e.g., by Pandoc)
|
|
11
|
+
toc = d.createElement('div');
|
|
12
|
+
toc.id = 'TOC';
|
|
13
|
+
|
|
14
|
+
let li, ul;
|
|
15
|
+
let p = toc; // the current parent into which we insert child TOC items
|
|
16
|
+
let t1, t0 = 0; // pretend there is a top-level <h0> for the sake of convenience
|
|
17
|
+
hs.forEach(h => {
|
|
18
|
+
t1 = parseInt(h.tagName.replace(/^h/i, ''));
|
|
19
|
+
li = d.createElement('li');
|
|
20
|
+
if (t1 > t0) {
|
|
21
|
+
// lower-level header: create a new ul
|
|
22
|
+
ul = d.createElement('ul');
|
|
23
|
+
ul.appendChild(li);
|
|
24
|
+
p.appendChild(ul);
|
|
25
|
+
} else if (t1 < t0) {
|
|
26
|
+
// higher-level header: go back to upper-level ul
|
|
27
|
+
for (let j = 0; j < t0 - t1; j++) {
|
|
28
|
+
p = p.parentNode.parentNode;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (t1 <= t0) p.parentNode.appendChild(li);
|
|
32
|
+
p = li;
|
|
33
|
+
const a = d.createElement('a');
|
|
34
|
+
a.innerHTML = h.innerHTML;
|
|
35
|
+
if (h.id) {
|
|
36
|
+
a.href = '#' + h.id;
|
|
37
|
+
} else {
|
|
38
|
+
// Pandoc's section divs
|
|
39
|
+
const s = h.parentNode;
|
|
40
|
+
if (s.classList.contains('section') && s.id) a.href = '#' + s.id;
|
|
41
|
+
}
|
|
42
|
+
p.appendChild(a);
|
|
43
|
+
t0 = t1;
|
|
44
|
+
});
|
|
45
|
+
b.insertBefore(toc, b.firstChild);
|
|
46
|
+
|
|
47
|
+
// check if headings are numbered
|
|
48
|
+
toc.querySelector('span.section-number') && toc.classList.add('numbered');
|
|
49
|
+
})(document);
|
package/js/toc.min.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(e=>{const t=e.querySelector(".article, .body, article, body");if(!t)return;const r=t.querySelectorAll("h1, h2, h3, h4, h5, h6");if(0===r.length)return;var n=t.getElementById("TOC");let i,l;n?.remove(),(n=e.createElement("div")).id="TOC";let a,d=n,c=0;r.forEach((t=>{if(a=parseInt(t.tagName.replace(/^h/i,"")),i=e.createElement("li"),a>c)l=e.createElement("ul"),l.appendChild(i),d.appendChild(l);else if(a<c)for(let e=0;e<c-a;e++)d=d.parentNode.parentNode;a<=c&&d.parentNode.appendChild(i),d=i;const r=e.createElement("a");if(r.innerHTML=t.innerHTML,t.id)r.href="#"+t.id;else{const e=t.parentNode;e.classList.contains("section")&&e.id&&(r.href="#"+e.id)}d.appendChild(r),c=a})),t.insertBefore(n,t.firstChild),n.querySelector("span.section-number")&&n.classList.add("numbered")})(document);
|