From 96b2f5f8ae7ba8369b32ef0dcf94727cf4d4c4a5 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Thu, 13 Nov 2025 14:46:47 +0800 Subject: [PATCH] refactor: Refactor duplicated code in theme.js (#655) * Initial plan * Refactor duplicated code in theme.js - Extract highlight text logic into _applyHighlightToText helper method - Extract search UI reset logic into _resetSearchUI helper method - Extract content initialization logic into _initContentComponents helper method - Extract encrypted class toggling into _toggleEncryptedClass helper method - Reduce code duplication in initSearch, initFixItDecryptor, and init methods Co-authored-by: Lruihao <33419593+Lruihao@users.noreply.github.com> * Simplify _toggleEncryptedClass with boolean parameter - Replace fromClass and toClass parameters with a single show boolean - Hardcode class names 'encrypted-hidden' and 'decrypted-shown' in function body - More semantic API: true to show decrypted content, false to hide - Simplifies all 3 call sites with clearer intent Co-authored-by: Lruihao <33419593+Lruihao@users.noreply.github.com> * refactor: remove redundant DOMContentLoaded checks in aplayer and mermaid initialization --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Lruihao <33419593+Lruihao@users.noreply.github.com> Co-authored-by: Cell <1024@lruihao.cn> --- assets/js/lib/aplayer.js | 6 -- assets/js/lib/mermaid.js | 6 -- assets/js/theme.js | 163 ++++++++++++++++++++------------------- 3 files changed, 85 insertions(+), 90 deletions(-) diff --git a/assets/js/lib/aplayer.js b/assets/js/lib/aplayer.js index f72136de..05e9d45b 100644 --- a/assets/js/lib/aplayer.js +++ b/assets/js/lib/aplayer.js @@ -11,9 +11,3 @@ window.FixItAPlayer = { }) }, } - -if (document.readyState !== 'loading') { - window.FixItAPlayer.init() -} else { - document.addEventListener('DOMContentLoaded', window.FixItAPlayer.init, false) -} diff --git a/assets/js/lib/mermaid.js b/assets/js/lib/mermaid.js index 4304e9d8..ccf5b553 100644 --- a/assets/js/lib/mermaid.js +++ b/assets/js/lib/mermaid.js @@ -116,9 +116,3 @@ window.FixItMermaid = { init: initMermaid, } window.mermaid = mermaid - -if (document.readyState !== 'loading') { - initMermaid() -} else { - document.addEventListener('DOMContentLoaded', initMermaid, false) -} diff --git a/assets/js/theme.js b/assets/js/theme.js index b8412c42..eb34b209 100644 --- a/assets/js/theme.js +++ b/assets/js/theme.js @@ -49,7 +49,7 @@ class FixIt { }); } - initTwemoji(target = document.body) { + initTwemoji(target = document) { this.config.twemoji && twemoji.parse(target); } @@ -100,6 +100,38 @@ class FixIt { }); } + /** + * Helper method to apply highlight tags to text based on match indices + * @param {String} text - The text to highlight + * @param {Array} indices - Array of match indices + * @param {String} highlightTag - The HTML tag to use for highlighting + * @returns {String} The highlighted text + */ + _applyHighlightToText(text, indices, highlightTag) { + let offset = 0; + for (let i = 0; i < indices.length; i++) { + const substr = text.substring(indices[i][0] + offset, indices[i][1] + 1 + offset); + const tag = `<${highlightTag}>` + substr + ``; + text = text.substring(0, indices[i][0] + offset) + tag + text.substring(indices[i][1] + 1 + offset, text.length); + offset += highlightTag.length * 2 + 5; + } + return text; + } + + /** + * Helper method to reset search UI elements + * @param {Element} $header - The header element + * @param {Element} $searchLoading - The loading indicator element + * @param {Element} $searchClear - The clear button element + * @param {Object} searchInstance - The search autocomplete instance + */ + _resetSearchUI($header, $searchLoading, $searchClear, searchInstance) { + $header.classList.remove('open'); + $searchLoading.style.display = 'none'; + $searchClear.style.display = 'none'; + searchInstance && searchInstance.autocomplete.setVal(''); + } + initSearch() { const searchConfig = this.config.search; const isMobile = this.util.isMobile(); @@ -150,23 +182,17 @@ class FixIt { }, false); $searchCancel.addEventListener('click', () => { this.disableScrollEvent = false; - $header.classList.remove('open'); document.body.classList.remove('blur'); document.getElementById('menu-toggle-mobile').classList.remove('active'); document.getElementById('menu-mobile').classList.remove('active'); - $searchLoading.style.display = 'none'; - $searchClear.style.display = 'none'; - this._searchMobile && this._searchMobile.autocomplete.setVal(''); + this._resetSearchUI($header, $searchLoading, $searchClear, this._searchMobile); }, false); $searchClear.addEventListener('click', () => { $searchClear.style.display = 'none'; this._searchMobile && this._searchMobile.autocomplete.setVal(''); }, false); this._searchMobileOnClickMask = this._searchMobileOnClickMask || (() => { - $header.classList.remove('open'); - $searchLoading.style.display = 'none'; - $searchClear.style.display = 'none'; - this._searchMobile && this._searchMobile.autocomplete.setVal(''); + this._resetSearchUI($header, $searchLoading, $searchClear, this._searchMobile); }); this.clickMaskEventSet.add(this._searchMobileOnClickMask); } else { @@ -183,10 +209,7 @@ class FixIt { this._searchDesktop && this._searchDesktop.autocomplete.setVal(''); }, false); this._searchDesktopOnClickMask = this._searchDesktopOnClickMask ||(() => { - $header.classList.remove('open'); - $searchLoading.style.display = 'none'; - $searchClear.style.display = 'none'; - this._searchDesktop && this._searchDesktop.autocomplete.setVal(''); + this._resetSearchUI($header, $searchLoading, $searchClear, this._searchDesktop); }); this.clickMaskEventSet.add(this._searchDesktopOnClickMask); } @@ -254,21 +277,9 @@ class FixIt { let content = item.content.replace(/&/g, '&').replace(//g, '>') matches.forEach(({ indices, value, key }) => { if (key === 'content') { - let offset = 0; - for (let i = 0; i < indices.length; i++) { - const substr = content.substring(indices[i][0] + offset, indices[i][1] + 1 + offset); - const tag = `<${highlightTag}>` + substr + ``; - content = content.substring(0, indices[i][0] + offset) + tag + content.substring(indices[i][1] + 1 + offset, content.length); - offset += highlightTag.length * 2 + 5; - } + content = this._applyHighlightToText(content, indices, highlightTag); } else if (key === 'title') { - let offset = 0; - for (let i = 0; i < indices.length; i++) { - const substr = title.substring(indices[i][0] + offset, indices[i][1] + 1 + offset); - const tag = `<${highlightTag}>` + substr + ``; - title = title.substring(0, indices[i][0] + offset) + tag + title.substring(indices[i][1] + 1 + offset, content.length); - offset += highlightTag.length * 2 + 5; - } + title = this._applyHighlightToText(title, indices, highlightTag); } }); results[item.uri] = { @@ -1099,53 +1110,58 @@ class FixIt { this._jsonViewerOnSwitchTheme(); } + /** + * Helper method to initialize content components + * @param {Element} target - The target element (optional, defaults to document) + * @param {Boolean} includeToc - Whether to initialize TOC-related components + */ + _initContentComponents(target = document, includeToc = false) { + this.initTwemoji(target); + this.initDetails(target); + this.initLightGallery(); + this.initCodeWrapper(); + this.initDiagramCopyBtn(); + this.initTable(target); + this.initEcharts(); + this.initTypeit(target); + this.initMapbox(); + if (includeToc) { + this.fixTocScroll(); + this.initToc(); + this.initTocListener(); + } + this.initPangu(); + this.initMathJax(); + this.initJsonViewer(); + window.FixItMermaid?.init?.(); + window.FixItAPlayer?.init?.(); + } + + /** + * Helper method to toggle encrypted content visibility + * @param {Element} container - The container element + * @param {Boolean} show - true to show decrypted content, false to hide + */ + _toggleEncryptedClass(container, show) { + const fromClass = show ? 'encrypted-hidden' : 'decrypted-shown'; + const toClass = show ? 'decrypted-shown' : 'encrypted-hidden'; + this.util.forEach(container.querySelectorAll(`.${fromClass}`), ($element) => { + $element.classList.replace(fromClass, toClass); + }); + } + initFixItDecryptor() { this.decryptor = new FixItDecryptor({ decrypted: () => { - this.initTwemoji(); - this.initDetails(); - this.initLightGallery(); - this.initCodeWrapper(); - this.initDiagramCopyBtn(); - this.initTable(); - this.initEcharts(); - this.initTypeit(); - this.initMapbox(); - this.fixTocScroll(); - this.initToc(); - this.initTocListener(); - this.initPangu(); - this.initMathJax(); - this.initJsonViewer(); - window.FixItMermaid?.init?.(); - window.FixItAPlayer?.init?.(); - this.util.forEach(document.querySelectorAll('.encrypted-hidden'), ($element) => { - $element.classList.replace('encrypted-hidden', 'decrypted-shown'); - }); + this._initContentComponents(document, true); + this._toggleEncryptedClass(document, true); }, partialDecrypted: ($content) => { - this.initTwemoji($content); - this.initDetails($content); - this.initLightGallery(); - this.initCodeWrapper(); - this.initDiagramCopyBtn(); - this.initTable($content); - this.initEcharts(); - this.initTypeit($content); - this.initMapbox(); - this.initPangu(); - this.initMathJax(); - this.initJsonViewer(); - window.FixItMermaid?.init?.(); - window.FixItAPlayer?.init?.(); - this.util.forEach($content.querySelectorAll('.encrypted-hidden'), ($element) => { - $element.classList.replace('encrypted-hidden', 'decrypted-shown'); - }); + this._initContentComponents($content, false); + this._toggleEncryptedClass($content, true); }, reset: () => { - this.util.forEach(document.querySelectorAll('.decrypted-shown'), ($element) => { - $element.classList.replace('decrypted-shown', 'encrypted-hidden'); - }); + this._toggleEncryptedClass(document, false); } }); this.decryptor.init(this.config.encryption); @@ -1328,17 +1344,7 @@ class FixIt { this.initFixItDecryptor(); } if (!this.config.encryption?.all) { - this.initTwemoji(); - this.initDetails(); - this.initLightGallery(); - this.initCodeWrapper(); - this.initDiagramCopyBtn(); - this.initTable(); - this.initEcharts(); - this.initTypeit(); - this.initMapbox(); - this.initPangu(); - this.initJsonViewer(); + this._initContentComponents(document, false); } this.initThemeColor(); this.initSVGIcon(); @@ -1354,6 +1360,7 @@ class FixIt { this.initReward(); this.initPostChatUser(); + // 【todo] refactor async init toc window.setTimeout(() => { this.initComment(); if (!this.config.encryption?.all) {