Skip to content

Commit af26992

Browse files
authored
Merge pull request #886 from SISheogorath/fix/ToCHeader
Refactor generation of ToC
2 parents b1d1f46 + df05bff commit af26992

File tree

2 files changed

+70
-46
lines changed

2 files changed

+70
-46
lines changed

public/css/extra.css

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@
9393
color: #777;
9494
}
9595

96+
.toc .invisable-node {
97+
list-style-type: none;
98+
}
99+
96100
.ui-toc {
97101
position: fixed;
98102
bottom: 20px;

public/vendor/md-toc.js

Lines changed: 66 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
Toc.prototype._collectTitleElements = function () {
2929
this._elTitlesNames = []
3030
this.elTitleElements = []
31-
for (var i = 1; i < 7; i++) {
31+
for (var i = 1; i < 6; i++) {
3232
if (this.el.getElementsByTagName('h' + i).length) {
3333
this._elTitlesNames.push('h' + i)
3434
}
@@ -44,59 +44,79 @@
4444
}
4545
}
4646

47-
Toc.prototype._createTocContent = function () {
48-
this._elTitleElementsLen = this.elTitleElements.length
49-
if (!this._elTitleElementsLen) return
50-
this.tocContent = ''
51-
this._tempLists = []
47+
Toc.prototype._createTocContent = function recursiveToc(level = 0, titleElements = [], titleNames = [], ulClass = undefined) {
48+
// Inititalize our elements from the toc object
49+
// which is only available on level 0
50+
if (level === 0) {
51+
titleElements = this.elTitleElements
52+
titleNames = this._elTitlesNames
53+
ulClass = this.ulClass
54+
}
55+
// No need to do anything for an empty ToC
56+
if (!titleElements.length) return
5257

53-
for (var i = 0; i < this._elTitleElementsLen; i++) {
54-
var j = i + 1
55-
this._elTitleElement = this.elTitleElements[i]
56-
this._elTitleElementName = this._elTitleElement.tagName
57-
this._elTitleElementTitle = this._elTitleElement.textContent.replace(/"/g, '&quot;')
58-
this._elTitleElementText = (typeof this.process === 'function' ? this.process(this._elTitleElement) : this._elTitleElement.innerHTML).replace(/<(?:.|\n)*?>/gm, '')
59-
var id = this._elTitleElement.getAttribute('id')
60-
if (!id) {
61-
this._elTitleElement.setAttribute('id', 'tip' + i)
62-
id = '#tip' + i
63-
} else {
64-
id = '#' + id
65-
}
58+
var content = '<ul'
59+
if (ulClass) {
60+
content += ' class="' + ulClass + '"'
61+
}
62+
content += '>\n'
63+
var iterTag = titleNames[level]
64+
var recurse = false
65+
var openTag = false
6666

67-
this.tocContent += '<li><a href="' + id + '" title="'+ this._elTitleElementTitle +'">' + this._elTitleElementText + '</a>'
67+
for (var element; element = titleElements.shift();) {
68+
var elementTag = element.tagName.toLowerCase()
6869

69-
if (j !== this._elTitleElementsLen) {
70-
this._elNextTitleElementName = this.elTitleElements[j].tagName
71-
if (this._elTitleElementName !== this._elNextTitleElementName) {
72-
var checkColse = false
73-
var y = 1
74-
for (var t = this._tempLists.length - 1; t >= 0; t--) {
75-
if (this._tempLists[t].tagName === this._elNextTitleElementName) {
76-
checkColse = true
77-
break
78-
}
79-
y++
80-
}
81-
if (checkColse) {
82-
this.tocContent += new Array(y + 1).join('</li></ul>')
83-
this._tempLists.length = this._tempLists.length - y
84-
} else {
85-
this._tempLists.push(this._elTitleElement)
86-
if (this.ulClass) { this.tocContent += '<ul class="' + this.ulClass + '">' } else { this.tocContent += '<ul>' }
87-
}
70+
// We only care about tags on our level to add them as list item
71+
if (elementTag == iterTag) {
72+
// Let's do some cleaning
73+
var elementTitle = element.textContent.replace(/"/g, '&quot;')
74+
var elementText = (typeof this.process === 'function' ? this.process(element) : element.innerHTML).replace(/<(?:.|\n)*?>/gm, '')
75+
var id = element.getAttribute('id')
76+
if (!id) {
77+
element.setAttribute('id', 'tip' + i)
78+
id = '#tip' + i
8879
} else {
89-
this.tocContent += '</li>'
80+
id = '#' + id
9081
}
91-
} else {
92-
if (this._tempLists.length) {
93-
this.tocContent += new Array(this._tempLists.length + 1).join('</li></ul>')
94-
} else {
95-
this.tocContent += '</li>'
82+
if (openTag) {
83+
content += '</li>\n'
84+
openTag = false
85+
}
86+
content += '<li><a href="' + id + '" title="'+ elementTitle +'">' + elementText + '</a>'
87+
// Reset recursion. We need it for the next subsections
88+
recurse = false
89+
openTag = true
90+
// Check if the current element has a lower level than ours, if so, we have to go down the rabbithole!
91+
} else if (!recurse && titleNames.indexOf(elementTag.toLowerCase()) > level) {
92+
recurse = true
93+
if (!openTag) {
94+
content += '<li class="invisable-node">'
95+
openTag = true
9696
}
97+
// This element is for the lower lever, we have to re-add it before we send the list down there.
98+
titleElements.unshift(element)
99+
// Let's call ourself and get to the next level
100+
content += recursiveToc(level + 1, titleElements, titleNames, ulClass)
101+
} else {
102+
// When we end up here, met a higher level element
103+
// This is not our business so back into the list with the element and let's end this loop
104+
titleElements.unshift(element)
105+
break
97106
}
98107
}
99-
if (this.ulClass) { this.tocContent = '<ul class="' + this.ulClass + '">' + this.tocContent + '</ul>' } else { this.tocContent = '<ul>' + this.tocContent + '</ul>' }
108+
109+
if (openTag) {
110+
content += '</li>\n'
111+
}
112+
content += '</ul>\n'
113+
114+
// Set ToC content of the level 0 everything else pass things to the upper level!
115+
if (level === 0) {
116+
this.tocContent = content
117+
} else {
118+
return content
119+
}
100120
}
101121

102122
Toc.prototype._showToc = function () {

0 commit comments

Comments
 (0)