From b617cbe2328f5cae1e3141565eb69c9a455e8907 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sun, 10 Nov 2019 03:14:33 +0800 Subject: [PATCH 1/3] refactor(toc_helper): relpace cheerio with htmlparser2 --- lib/plugins/helper/toc.js | 30 ++++++++++++++++++------------ package.json | 2 +- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/lib/plugins/helper/toc.js b/lib/plugins/helper/toc.js index 51d0ef33e..01aa7c9fb 100644 --- a/lib/plugins/helper/toc.js +++ b/lib/plugins/helper/toc.js @@ -1,15 +1,21 @@ 'use strict'; -let cheerio; const { escapeHTML } = require('hexo-util'); +const { DomHandler, DomUtils, Parser } = require('htmlparser2'); + +const parseHtml = (html) => { + const handler = new DomHandler(null, {}); + new Parser(handler, {}).end(html); + return handler.dom; +}; function tocHelper(str, options = {}) { - if (!cheerio) cheerio = require('cheerio'); + const dom = parseHtml(str); - const $ = cheerio.load(str); const headingsMaxDepth = Object.prototype.hasOwnProperty.call(options, 'max_depth') ? options.max_depth : 6; const headingsSelector = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].slice(0, headingsMaxDepth).join(','); - const headings = $(headingsSelector); + + const headings = DomUtils.find(el => headingsSelector.includes(el.tagName), dom, true); if (!headings.length) return ''; @@ -21,15 +27,15 @@ function tocHelper(str, options = {}) { let lastLevel = 0; function getId(ele) { - const id = $(ele).attr('id'); - const $parent = $(ele).parent(); - return id || ($parent.length < 1 ? null : getId($parent)); + const { id } = ele.attribs; + const { parent } = ele; + return id || (parent.length < 1 ? null : getId(parent)); } - headings.each(function() { - const level = +this.name[1]; - const id = getId(this); - const text = escapeHTML($(this).text()); + for (const el of headings) { + const level = +el.name[1]; + const id = getId(el); + const text = escapeHTML(DomUtils.getText(el)); lastNumber[level - 1]++; @@ -67,7 +73,7 @@ function tocHelper(str, options = {}) { result += `${text}`; lastLevel = level; - }); + } for (let i = firstLevel - 1; i < lastLevel; i++) { result += ''; diff --git a/package.json b/package.json index 1c088b017..6cc13bd40 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,6 @@ "archy": "^1.0.0", "bluebird": "^3.5.2", "chalk": "^3.0.0", - "cheerio": "0.22.0", "hexo-cli": "^3.0.0", "hexo-front-matter": "^1.0.0", "hexo-fs": "^2.0.0", @@ -71,6 +70,7 @@ "@easyops/git-exec-and-restage": "^1.0.4", "chai": "^4.1.2", "chai-as-promised": "^7.1.1", + "cheerio": "0.22.0", "eslint": "^6.0.1", "eslint-config-hexo": "^4.0.0", "hexo-renderer-marked": "^2.0.0", From bf30257437275af9ef1ebe95adee2f3fdfcd82dd Mon Sep 17 00:00:00 2001 From: SukkaW Date: Fri, 22 Nov 2019 18:07:02 +0800 Subject: [PATCH 2/3] test(toc_helper): use classic for loop --- lib/plugins/helper/toc.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/plugins/helper/toc.js b/lib/plugins/helper/toc.js index 01aa7c9fb..52b5f2848 100644 --- a/lib/plugins/helper/toc.js +++ b/lib/plugins/helper/toc.js @@ -32,7 +32,9 @@ function tocHelper(str, options = {}) { return id || (parent.length < 1 ? null : getId(parent)); } - for (const el of headings) { + const headingLen = headings.length; + for (let i = 0; i < headingLen; i++) { + const el = headings[i]; const level = +el.name[1]; const id = getId(el); const text = escapeHTML(DomUtils.getText(el)); From df7ebcbefedbefe55aff7dd470ce0d73895b0323 Mon Sep 17 00:00:00 2001 From: SukkaW Date: Sat, 7 Dec 2019 13:23:56 +0800 Subject: [PATCH 3/3] refactor(toc_helper): utilize tocObj --- lib/plugins/helper/toc.js | 40 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/lib/plugins/helper/toc.js b/lib/plugins/helper/toc.js index 52b5f2848..4eb5093e8 100644 --- a/lib/plugins/helper/toc.js +++ b/lib/plugins/helper/toc.js @@ -1,43 +1,29 @@ 'use strict'; -const { escapeHTML } = require('hexo-util'); -const { DomHandler, DomUtils, Parser } = require('htmlparser2'); - -const parseHtml = (html) => { - const handler = new DomHandler(null, {}); - new Parser(handler, {}).end(html); - return handler.dom; -}; +const { tocObj } = require('hexo-util'); function tocHelper(str, options = {}) { - const dom = parseHtml(str); + options = Object.assign({ + max_depth: 6, + class: 'toc', + list_number: true + }, options); - const headingsMaxDepth = Object.prototype.hasOwnProperty.call(options, 'max_depth') ? options.max_depth : 6; - const headingsSelector = ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].slice(0, headingsMaxDepth).join(','); + const data = tocObj(str, { max_depth: options.max_depth }); - const headings = DomUtils.find(el => headingsSelector.includes(el.tagName), dom, true); + if (!data.length) return ''; - if (!headings.length) return ''; + const className = options.class; + const listNumber = options.list_number; - const className = options.class || 'toc'; - const listNumber = Object.prototype.hasOwnProperty.call(options, 'list_number') ? options.list_number : true; let result = `
    `; const lastNumber = [0, 0, 0, 0, 0, 0]; let firstLevel = 0; let lastLevel = 0; - function getId(ele) { - const { id } = ele.attribs; - const { parent } = ele; - return id || (parent.length < 1 ? null : getId(parent)); - } - - const headingLen = headings.length; - for (let i = 0; i < headingLen; i++) { - const el = headings[i]; - const level = +el.name[1]; - const id = getId(el); - const text = escapeHTML(DomUtils.getText(el)); + for (let i = 0, len = data.length; i < len; i++) { + const el = data[i]; + const { level, id, text } = el; lastNumber[level - 1]++;