Skip to content

Commit 4fe0620

Browse files
committed
Refactor generation of ToC
This replaces the existing iterative implementation of the ToC generation with an recursive one. This also solves the problem of skipped headers which causes wrong leveling of them. Signed-off-by: Sheogorath <[email protected]>
1 parent 4e38d18 commit 4fe0620

File tree

1 file changed

+55
-45
lines changed

1 file changed

+55
-45
lines changed

public/vendor/md-toc.js

Lines changed: 55 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -44,59 +44,69 @@
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+
var titleElementsLen = titleElements.length
56+
// No need to do anything for an empty ToC
57+
if (!titleElementsLen) return
5258

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-
}
59+
this.tocContent = ''
60+
var content = '<ul'
61+
if (ulClass) {
62+
content += ' class="' + ulClass + '"'
63+
}
64+
content += '>'
65+
var iterTag = titleNames[level]
66+
var recurse = false
6667

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

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-
}
71+
// We only care about tags on our level to add them as list item
72+
if (elementTag == iterTag) {
73+
// Let's do some cleaning
74+
var elementTitle = element.textContent.replace(/"/g, '&quot;')
75+
var elementText = (typeof this.process === 'function' ? this.process(element) : element.innerHTML).replace(/<(?:.|\n)*?>/gm, '')
76+
var id = element.getAttribute('id')
77+
if (!id) {
78+
element.setAttribute('id', 'tip' + i)
79+
id = '#tip' + i
8880
} else {
89-
this.tocContent += '</li>'
81+
id = '#' + id
9082
}
83+
content += '<li><a href="' + id + '" title="'+ elementTitle +'">' + elementText + '</a>'
84+
// Reset recursion. We need it for the next subsections
85+
recurse = false
86+
87+
// Check if the current element has a lower level than ours, if so, we have to go down the rabbithole!
88+
} else if (!recurse && titleNames.indexOf(elementTag.toLowerCase()) > level) {
89+
recurse = true
90+
// This element is for the lower lever, we have to re-add it before we send the list down there.
91+
titleElements.unshift(element)
92+
// Let's call ourself and get to the next level
93+
content += recursiveToc(level + 1, titleElements, titleNames, ulClass)
9194
} else {
92-
if (this._tempLists.length) {
93-
this.tocContent += new Array(this._tempLists.length + 1).join('</li></ul>')
94-
} else {
95-
this.tocContent += '</li>'
96-
}
95+
// When we end up here, met a higher level element
96+
// This is not our business so back into the list with the element and let's end this loop
97+
titleElements.unshift(element)
98+
break
9799
}
98100
}
99-
if (this.ulClass) { this.tocContent = '<ul class="' + this.ulClass + '">' + this.tocContent + '</ul>' } else { this.tocContent = '<ul>' + this.tocContent + '</ul>' }
101+
102+
content += '</ul>'
103+
104+
// Set ToC content of the level 0 everything else pass things to the upper level!
105+
if (level === 0) {
106+
this.tocContent = content
107+
} else {
108+
return content
109+
}
100110
}
101111

102112
Toc.prototype._showToc = function () {

0 commit comments

Comments
 (0)