From 4fe062085324c50f2cfa062258559cf31858ef5f Mon Sep 17 00:00:00 2001 From: Sheogorath Date: Wed, 4 Jul 2018 02:22:48 +0200 Subject: [PATCH 1/3] 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 --- public/vendor/md-toc.js | 100 ++++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/public/vendor/md-toc.js b/public/vendor/md-toc.js index 3457d46..5581783 100644 --- a/public/vendor/md-toc.js +++ b/public/vendor/md-toc.js @@ -44,59 +44,69 @@ } } - Toc.prototype._createTocContent = function () { - this._elTitleElementsLen = this.elTitleElements.length - if (!this._elTitleElementsLen) return + Toc.prototype._createTocContent = function recursiveToc(level = 0, titleElements = [], titleNames = [], ulClass = undefined) { + // Inititalize our elements from the toc object + // which is only available on level 0 + if (level === 0) { + titleElements = this.elTitleElements + titleNames = this._elTitlesNames + ulClass = this.ulClass + } + var titleElementsLen = titleElements.length + // No need to do anything for an empty ToC + if (!titleElementsLen) return + this.tocContent = '' - this._tempLists = [] + var content = '/gm, '') - var id = this._elTitleElement.getAttribute('id') - if (!id) { - this._elTitleElement.setAttribute('id', 'tip' + i) - id = '#tip' + i - } else { - id = '#' + id - } + for (var element; element = titleElements.shift();) { + var elementTag = element.tagName.toLowerCase() - this.tocContent += '
  • ' + this._elTitleElementText + '' - - if (j !== this._elTitleElementsLen) { - this._elNextTitleElementName = this.elTitleElements[j].tagName - if (this._elTitleElementName !== this._elNextTitleElementName) { - var checkColse = false - var y = 1 - for (var t = this._tempLists.length - 1; t >= 0; t--) { - if (this._tempLists[t].tagName === this._elNextTitleElementName) { - checkColse = true - break - } - y++ - } - if (checkColse) { - this.tocContent += new Array(y + 1).join('
  • ') - this._tempLists.length = this._tempLists.length - y - } else { - this._tempLists.push(this._elTitleElement) - if (this.ulClass) { this.tocContent += '
      ' } else { this.tocContent += '
        ' } - } + // We only care about tags on our level to add them as list item + if (elementTag == iterTag) { + // Let's do some cleaning + var elementTitle = element.textContent.replace(/"/g, '"') + var elementText = (typeof this.process === 'function' ? this.process(element) : element.innerHTML).replace(/<(?:.|\n)*?>/gm, '') + var id = element.getAttribute('id') + if (!id) { + element.setAttribute('id', 'tip' + i) + id = '#tip' + i } else { - this.tocContent += '' + id = '#' + id } + content += '
      • ' + elementText + '' + // Reset recursion. We need it for the next subsections + recurse = false + + // Check if the current element has a lower level than ours, if so, we have to go down the rabbithole! + } else if (!recurse && titleNames.indexOf(elementTag.toLowerCase()) > level) { + recurse = true + // This element is for the lower lever, we have to re-add it before we send the list down there. + titleElements.unshift(element) + // Let's call ourself and get to the next level + content += recursiveToc(level + 1, titleElements, titleNames, ulClass) } else { - if (this._tempLists.length) { - this.tocContent += new Array(this._tempLists.length + 1).join('
      ') - } else { - this.tocContent += '' - } + // When we end up here, met a higher level element + // This is not our business so back into the list with the element and let's end this loop + titleElements.unshift(element) + break } } - if (this.ulClass) { this.tocContent = '
        ' + this.tocContent + '
      ' } else { this.tocContent = '
        ' + this.tocContent + '
      ' } + + content += '
    ' + + // Set ToC content of the level 0 everything else pass things to the upper level! + if (level === 0) { + this.tocContent = content + } else { + return content + } } Toc.prototype._showToc = function () { From cf934a4e5120b6d62cc8798aed52be2c424de91f Mon Sep 17 00:00:00 2001 From: Sheogorath Date: Wed, 4 Jul 2018 11:20:59 +0200 Subject: [PATCH 2/3] Ignore h6 headers h6 headers are used for tags in CodiMD. So we should ignore them for the ToC generation. Signed-off-by: Sheogorath --- public/vendor/md-toc.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/vendor/md-toc.js b/public/vendor/md-toc.js index 5581783..661f7f8 100644 --- a/public/vendor/md-toc.js +++ b/public/vendor/md-toc.js @@ -28,7 +28,7 @@ Toc.prototype._collectTitleElements = function () { this._elTitlesNames = [] this.elTitleElements = [] - for (var i = 1; i < 7; i++) { + for (var i = 1; i < 6; i++) { if (this.el.getElementsByTagName('h' + i).length) { this._elTitlesNames.push('h' + i) } From df05bff82a32dc2f535cd72f4624006bdc10f904 Mon Sep 17 00:00:00 2001 From: Sheogorath Date: Wed, 4 Jul 2018 21:08:57 +0200 Subject: [PATCH 3/3] ToC: Some HTML improvements and style fixes The ToC generated broken HTML with unclosed `
  • ` tags. This got fixed as well as some minor optimisation and adding list elements for the subentries so the elements appear in the ToC while scrolling. Signed-off-by: Sheogorath --- public/css/extra.css | 4 ++++ public/vendor/md-toc.js | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/public/css/extra.css b/public/css/extra.css index 1b13290..3954c04 100644 --- a/public/css/extra.css +++ b/public/css/extra.css @@ -93,6 +93,10 @@ color: #777; } +.toc .invisable-node { + list-style-type: none; +} + .ui-toc { position: fixed; bottom: 20px; diff --git a/public/vendor/md-toc.js b/public/vendor/md-toc.js index 661f7f8..876978f 100644 --- a/public/vendor/md-toc.js +++ b/public/vendor/md-toc.js @@ -52,18 +52,17 @@ titleNames = this._elTitlesNames ulClass = this.ulClass } - var titleElementsLen = titleElements.length // No need to do anything for an empty ToC - if (!titleElementsLen) return + if (!titleElements.length) return - this.tocContent = '' var content = '' + elementText + '' // Reset recursion. We need it for the next subsections recurse = false - + openTag = true // Check if the current element has a lower level than ours, if so, we have to go down the rabbithole! } else if (!recurse && titleNames.indexOf(elementTag.toLowerCase()) > level) { recurse = true + if (!openTag) { + content += '
  • ' + openTag = true + } // This element is for the lower lever, we have to re-add it before we send the list down there. titleElements.unshift(element) // Let's call ourself and get to the next level @@ -99,7 +106,10 @@ } } - content += '' + if (openTag) { + content += '
  • \n' + } + content += '\n' // Set ToC content of the level 0 everything else pass things to the upper level! if (level === 0) {