mirror of
https://github.com/jerryc127/hexo-theme-butterfly.git
synced 2026-08-08 11:38:42 +08:00
update
This commit is contained in:
+5
-5
@@ -659,7 +659,7 @@ artalk:
|
|||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|
||||||
chat:
|
chat:
|
||||||
# Choose: chatra/tidio/crisp/knocket
|
# Choose: chatra/tidio/crisp/knocket
|
||||||
# Leave it empty if you don't need chat
|
# Leave it empty if you don't need chat
|
||||||
use:
|
use:
|
||||||
# Chat Button [recommend]
|
# Chat Button [recommend]
|
||||||
@@ -680,10 +680,10 @@ tidio:
|
|||||||
crisp:
|
crisp:
|
||||||
website_id:
|
website_id:
|
||||||
|
|
||||||
# https://trtc.io/solutions/knocket
|
# https://trtc.io/solutions/knocket
|
||||||
knocket:
|
knocket:
|
||||||
identifier:
|
identifier:
|
||||||
|
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
# Analysis
|
# Analysis
|
||||||
# --------------------------------------
|
# --------------------------------------
|
||||||
|
|||||||
+5
-2
@@ -2,8 +2,11 @@ script.
|
|||||||
(() => {
|
(() => {
|
||||||
const abcjsInit = () => {
|
const abcjsInit = () => {
|
||||||
const abcjsFn = () => {
|
const abcjsFn = () => {
|
||||||
|
const $article = document.getElementById("article-container")
|
||||||
|
if (!$article || $article.querySelector(".hbe-container")) return
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
const sheets = document.querySelectorAll(".abc-music-sheet")
|
const sheets = $article.querySelectorAll(".abc-music-sheet")
|
||||||
for (let i = 0; i < sheets.length; i++) {
|
for (let i = 0; i < sheets.length; i++) {
|
||||||
const ele = sheets[i]
|
const ele = sheets[i]
|
||||||
if (ele.children.length > 0) continue
|
if (ele.children.length > 0) continue
|
||||||
@@ -29,7 +32,7 @@ script.
|
|||||||
}, 100)
|
}, 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof ABCJS === "object") {
|
if (typeof ABCJS === "object" && ABCJS !== null) {
|
||||||
abcjsFn()
|
abcjsFn()
|
||||||
} else {
|
} else {
|
||||||
btf.getScript("!{url_for(theme.asset.abcjs_basic_js)}").then(abcjsFn)
|
btf.getScript("!{url_for(theme.asset.abcjs_basic_js)}").then(abcjsFn)
|
||||||
|
|||||||
+4
-4
@@ -3,7 +3,7 @@ case theme.chat.use
|
|||||||
include ./chatra.pug
|
include ./chatra.pug
|
||||||
when 'tidio'
|
when 'tidio'
|
||||||
include ./tidio.pug
|
include ./tidio.pug
|
||||||
when 'crisp'
|
when 'crisp'
|
||||||
include ./crisp.pug
|
include ./crisp.pug
|
||||||
when 'knocket'
|
when 'knocket'
|
||||||
include ./knocket.pug
|
include ./knocket.pug
|
||||||
|
|||||||
+10
-12
@@ -1,14 +1,15 @@
|
|||||||
//- Knocket live chat — https://trtc.io/solutions/knocket
|
//- Knocket live chat — https://trtc.io/solutions/knocket
|
||||||
script.
|
script.
|
||||||
(() => {
|
(() => {
|
||||||
const id = '#{theme.knocket.identifier}'
|
const identifier = !{JSON.stringify(theme.knocket.identifier || '').replace(/</g, '\\u003c')}
|
||||||
if (!id) return
|
if (!identifier) return
|
||||||
|
|
||||||
btf.getScript(`https://trtc.io/knocket-sdk/sdk.js?identifier=${id}`).then(() => {
|
btf.getScript(`https://trtc.io/knocket-sdk/sdk.js?identifier=${encodeURIComponent(identifier)}`).then(() => {
|
||||||
const isChatBtn = !{theme.chat.rightside_button}
|
const isChatBtn = !{theme.chat.rightside_button}
|
||||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||||
|
|
||||||
const getWidget = () => document.getElementById('contact-widget-auto')
|
let widget = null
|
||||||
|
const getWidget = () => widget || (widget = document.getElementById('contact-widget-auto'))
|
||||||
|
|
||||||
if (isChatBtn) {
|
if (isChatBtn) {
|
||||||
const hide = () => { const w = getWidget(); if (w) w.style.display = 'none' }
|
const hide = () => { const w = getWidget(); if (w) w.style.display = 'none' }
|
||||||
@@ -24,21 +25,18 @@ script.
|
|||||||
window.chatBtnFn = () => {
|
window.chatBtnFn = () => {
|
||||||
const w = getWidget()
|
const w = getWidget()
|
||||||
if (!w) return
|
if (!w) return
|
||||||
if (w.style.display === 'none') show()
|
w.style.display = w.style.display === 'none' ? '' : 'none'
|
||||||
else hide()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
document.getElementById('chat-btn').style.display = 'block'
|
const chatBtn = document.getElementById('chat-btn')
|
||||||
|
if (chatBtn) chatBtn.style.display = 'block'
|
||||||
} else if (isChatHideShow) {
|
} else if (isChatHideShow) {
|
||||||
const observer = new MutationObserver(() => {
|
|
||||||
if (getWidget()) observer.disconnect()
|
|
||||||
})
|
|
||||||
observer.observe(document.body, { childList: true, subtree: true })
|
|
||||||
|
|
||||||
window.chatBtn = {
|
window.chatBtn = {
|
||||||
hide: () => { const w = getWidget(); if (w) w.style.display = 'none' },
|
hide: () => { const w = getWidget(); if (w) w.style.display = 'none' },
|
||||||
show: () => { const w = getWidget(); if (w) w.style.display = '' }
|
show: () => { const w = getWidget(); if (w) w.style.display = '' }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.warn('[Knocket] Failed to load the chat SDK.', error)
|
||||||
})
|
})
|
||||||
})()
|
})()
|
||||||
|
|||||||
+1
-1
@@ -15,7 +15,7 @@ script.
|
|||||||
|
|
||||||
const loadMathjax = () => {
|
const loadMathjax = () => {
|
||||||
const article = document.getElementById('article-container')
|
const article = document.getElementById('article-container')
|
||||||
if (!article) return
|
if (!article || article.querySelector('.hbe-container')) return
|
||||||
changeScriptToMath(article)
|
changeScriptToMath(article)
|
||||||
|
|
||||||
if (!window.MathJax) {
|
if (!window.MathJax) {
|
||||||
|
|||||||
+7
-4
@@ -330,8 +330,8 @@ script.
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const codeToMermaid = () => {
|
const codeToMermaid = $article => {
|
||||||
const codeMermaidEle = document.querySelectorAll('pre > code.mermaid')
|
const codeMermaidEle = $article.querySelectorAll('pre > code.mermaid')
|
||||||
if (codeMermaidEle.length === 0) return
|
if (codeMermaidEle.length === 0) return
|
||||||
|
|
||||||
codeMermaidEle.forEach(ele => {
|
codeMermaidEle.forEach(ele => {
|
||||||
@@ -347,8 +347,11 @@ script.
|
|||||||
}
|
}
|
||||||
|
|
||||||
const loadMermaid = () => {
|
const loadMermaid = () => {
|
||||||
if (!{theme.mermaid.code_write}) codeToMermaid()
|
const $article = document.getElementById('article-container')
|
||||||
const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap')
|
if (!$article) return
|
||||||
|
|
||||||
|
if (!{theme.mermaid.code_write}) codeToMermaid($article)
|
||||||
|
const $mermaid = $article.querySelectorAll('.mermaid-wrap')
|
||||||
if ($mermaid.length === 0) return
|
if ($mermaid.length === 0) return
|
||||||
|
|
||||||
const runMermaidFn = () => runMermaid($mermaid)
|
const runMermaidFn = () => runMermaid($mermaid)
|
||||||
|
|||||||
Vendored
+5
-4
@@ -65,12 +65,13 @@ script.
|
|||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener('pjax:error', e => {
|
document.addEventListener('pjax:error', e => {
|
||||||
if (e.request.status === 404) {
|
const responseURL = e.request && e.request.responseURL
|
||||||
|
if (e.request && e.request.status === 404) {
|
||||||
!{theme.error_404 && theme.error_404.enable}
|
!{theme.error_404 && theme.error_404.enable}
|
||||||
? pjax.loadUrl('!{url_for("/404.html")}')
|
? pjax.loadUrl('!{url_for("/404.html")}')
|
||||||
: window.location.href = e.request.responseURL
|
: responseURL && (window.location.href = responseURL)
|
||||||
} else {
|
} else if (responseURL) {
|
||||||
window.location.href = e.request.responseURL
|
window.location.href = responseURL
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
+5
-1
@@ -5,11 +5,15 @@
|
|||||||
if (syntax_highlighter === 'prismjs' || enable) && !preprocess
|
if (syntax_highlighter === 'prismjs' || enable) && !preprocess
|
||||||
script.
|
script.
|
||||||
(() => {
|
(() => {
|
||||||
|
const $article = document.getElementById('article-container')
|
||||||
|
if (!$article || $article.querySelector('.hbe-container')) return
|
||||||
|
|
||||||
window.Prism = window.Prism || {}
|
window.Prism = window.Prism || {}
|
||||||
window.Prism.manual = true
|
window.Prism.manual = true
|
||||||
|
|
||||||
const highlightAll = () => {
|
const highlightAll = () => {
|
||||||
window.Prism.highlightAll()
|
// window.Prism.highlightAll()
|
||||||
|
window.Prism.highlightAllUnder($article, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('load', highlightAll)
|
window.addEventListener('load', highlightAll)
|
||||||
|
|||||||
+5
-5
@@ -44,7 +44,7 @@ script.
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy')
|
btf.addGlobalFn('pjaxSendOnce', () => { typed && typed.destroy() }, 'typedDestroy')
|
||||||
|
|
||||||
case source
|
case source
|
||||||
when 1
|
when 1
|
||||||
@@ -53,8 +53,8 @@ case source
|
|||||||
fetch('https://v1.hitokoto.cn')
|
fetch('https://v1.hitokoto.cn')
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(data => {
|
.then(data => {
|
||||||
const from = '出自 ' + data.from
|
const from = data.from ? '出自 ' + data.from : ''
|
||||||
typedJSFn.processSubtitle(data.hitokoto, [from])
|
typedJSFn.processSubtitle(data.hitokoto, from ? [from] : [])
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error('Failed to get the Hitokoto API:', err)
|
console.error('Failed to get the Hitokoto API:', err)
|
||||||
@@ -79,7 +79,7 @@ case source
|
|||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error('Failed to get the Yiyan API:', err)
|
console.error('Failed to get the Yiyan API:', err)
|
||||||
typedJSFn.processSubtitle(!{JSON.stringify(subContent.length)})
|
typedJSFn.processSubtitle(!{JSON.stringify(subContent)})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
typedJSFn.run(subtitleType)
|
typedJSFn.run(subtitleType)
|
||||||
@@ -99,7 +99,7 @@ case source
|
|||||||
})
|
})
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
console.error('Failed to get the Jinrishici API:', err)
|
console.error('Failed to get the Jinrishici API:', err)
|
||||||
typedJSFn.processSubtitle(!{JSON.stringify(subContent.length)})
|
typedJSFn.processSubtitle(!{JSON.stringify(subContent)})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
typedJSFn.run(subtitleType)
|
typedJSFn.run(subtitleType)
|
||||||
|
|||||||
+116
-110
@@ -1,110 +1,116 @@
|
|||||||
- let { serverURL, script_name, website_id, option, UV_PV } = theme.umami_analytics
|
- let { serverURL, script_name, website_id, option, UV_PV } = theme.umami_analytics
|
||||||
- const isServerURL = !!serverURL
|
- const isServerURL = !!serverURL
|
||||||
- const baseURL = serverURL ? serverURL.replace(/\/$/, '') : 'https://cloud.umami.is'
|
- const baseURL = serverURL ? serverURL.replace(/\/$/, '') : 'https://cloud.umami.is'
|
||||||
- const apiUrl = serverURL ? serverURL.replace(/\/$/, '') + '/api' : 'https://api.umami.is/v1'
|
- const apiUrl = serverURL ? serverURL.replace(/\/$/, '') + '/api' : 'https://api.umami.is/v1'
|
||||||
|
|
||||||
script.
|
script.
|
||||||
(() => {
|
(() => {
|
||||||
const option = !{JSON.stringify(option)}
|
const option = !{JSON.stringify(option)}
|
||||||
const config = !{JSON.stringify(UV_PV)}
|
const config = !{JSON.stringify(UV_PV)}
|
||||||
|
|
||||||
const runTrack = () => {
|
const runTrack = () => {
|
||||||
if (typeof umami !== 'undefined' && typeof umami.track === 'function') {
|
if (typeof umami !== 'undefined' && typeof umami.track === 'function') {
|
||||||
umami.track(props => ({ ...props, url: window.location.pathname, title: GLOBAL_CONFIG_SITE.title }))
|
umami.track(props => ({ ...props, url: window.location.pathname, title: GLOBAL_CONFIG_SITE.title }))
|
||||||
} else {
|
} else {
|
||||||
console.warn('Umami Analytics: umami.track is not available')
|
console.warn('Umami Analytics: umami.track is not available')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadUmamiJS = () => {
|
const loadUmamiJS = () => {
|
||||||
btf.getScript('!{baseURL}/!{script_name}', {
|
btf.getScript('!{baseURL}/!{script_name}', {
|
||||||
'data-website-id': '!{website_id}',
|
'data-website-id': '!{website_id}',
|
||||||
'data-auto-track': 'false',
|
'data-auto-track': 'false',
|
||||||
...option
|
...option
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
runTrack()
|
runTrack()
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
console.error('Umami Analytics: Error loading script', error)
|
console.error('Umami Analytics: Error loading script', error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const getData = async (isPost) => {
|
const extractValue = stat => (stat && typeof stat.value !== 'undefined') ? stat.value : stat
|
||||||
try {
|
|
||||||
const now = Date.now()
|
const getData = async (isPost) => {
|
||||||
const keyUrl = isPost ? `&url=${window.location.pathname}&path=${window.location.pathname}` : ''
|
try {
|
||||||
const headerList = { 'Accept': 'application/json' }
|
const now = Date.now()
|
||||||
|
const pathQuery = isPost ? `&url=${window.location.pathname}&path=${window.location.pathname}` : ''
|
||||||
if (!{isServerURL}) {
|
const headers = {
|
||||||
headerList['Authorization'] = `Bearer ${config.token}`
|
'Accept': 'application/json',
|
||||||
} else {
|
[!{isServerURL} ? 'Authorization' : 'x-umami-api-key']: !{isServerURL} ? `Bearer ${config.token}` : config.token
|
||||||
headerList['x-umami-api-key'] = config.token
|
}
|
||||||
}
|
|
||||||
|
const res = await fetch(`!{apiUrl}/websites/!{website_id}/stats?startAt=0000000000&endAt=${now}${pathQuery}`, {
|
||||||
const res = await fetch(`!{apiUrl}/websites/!{website_id}/stats?startAt=0000000000&endAt=${now}${keyUrl}`, {
|
method: 'GET',
|
||||||
method: "GET",
|
headers
|
||||||
headers: headerList
|
})
|
||||||
})
|
|
||||||
|
if (!res.ok) {
|
||||||
if (!res.ok) {
|
throw new Error(`HTTP error! status: ${res.status}`)
|
||||||
throw new Error(`HTTP error! status: ${res.status}`)
|
}
|
||||||
}
|
|
||||||
|
return await res.json()
|
||||||
return await res.json()
|
} catch (error) {
|
||||||
} catch (error) {
|
console.error('Umami Analytics: Failed to fetch data', error)
|
||||||
console.error('Umami Analytics: Failed to fetch data', error)
|
throw error
|
||||||
throw error
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
const insertData = async () => {
|
||||||
const insertData = async () => {
|
try {
|
||||||
try {
|
const tasks = []
|
||||||
if (GLOBAL_CONFIG_SITE.pageType === 'post' && config.page_pv) {
|
|
||||||
const pagePV = document.getElementById('umamiPV')
|
if (GLOBAL_CONFIG_SITE.pageType === 'post' && config.page_pv) {
|
||||||
if (pagePV) {
|
tasks.push((async () => {
|
||||||
const data = await getData(true)
|
const pagePV = document.getElementById('umamiPV')
|
||||||
if (data && data.pageviews) {
|
if (pagePV) {
|
||||||
pagePV.textContent = typeof data.pageviews.value !== 'undefined' ? data.pageviews.value : data.pageviews
|
const data = await getData(true)
|
||||||
} else {
|
if (data && data.pageviews) {
|
||||||
console.warn('Umami Analytics: Invalid page view data received')
|
pagePV.textContent = extractValue(data.pageviews)
|
||||||
}
|
} else {
|
||||||
}
|
console.warn('Umami Analytics: Invalid page view data received')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (config.site_uv || config.site_pv) {
|
})())
|
||||||
const data = await getData(false)
|
}
|
||||||
|
|
||||||
if (config.site_uv) {
|
if (config.site_uv || config.site_pv) {
|
||||||
const siteUV = document.getElementById('umami-site-uv')
|
tasks.push((async () => {
|
||||||
if (siteUV && data && data.visitors) {
|
const data = await getData(false)
|
||||||
siteUV.textContent = typeof data.visitors.value !== 'undefined' ? data.visitors.value : data.visitors
|
|
||||||
} else if (siteUV) {
|
if (config.site_uv) {
|
||||||
console.warn('Umami Analytics: Invalid site UV data received')
|
const siteUV = document.getElementById('umami-site-uv')
|
||||||
}
|
if (siteUV && data && data.visitors) {
|
||||||
}
|
siteUV.textContent = extractValue(data.visitors)
|
||||||
|
} else if (siteUV) {
|
||||||
if (config.site_pv) {
|
console.warn('Umami Analytics: Invalid site UV data received')
|
||||||
const sitePV = document.getElementById('umami-site-pv')
|
}
|
||||||
if (sitePV && data && data.pageviews) {
|
}
|
||||||
sitePV.textContent = typeof data.pageviews.value !== 'undefined' ? data.pageviews.value : data.pageviews
|
|
||||||
} else if (sitePV) {
|
if (config.site_pv) {
|
||||||
console.warn('Umami Analytics: Invalid site PV data received')
|
const sitePV = document.getElementById('umami-site-pv')
|
||||||
}
|
if (sitePV && data && data.pageviews) {
|
||||||
}
|
sitePV.textContent = extractValue(data.pageviews)
|
||||||
}
|
} else if (sitePV) {
|
||||||
} catch (error) {
|
console.warn('Umami Analytics: Invalid site PV data received')
|
||||||
console.error('Umami Analytics: Failed to insert data', error)
|
}
|
||||||
}
|
}
|
||||||
}
|
})())
|
||||||
|
}
|
||||||
btf.addGlobalFn('pjaxComplete', runTrack, 'umami_analytics_run_track')
|
|
||||||
btf.addGlobalFn('pjaxComplete', insertData, 'umami_analytics_insert')
|
await Promise.all(tasks)
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Umami Analytics: Failed to insert data', error)
|
||||||
loadUmamiJS()
|
}
|
||||||
|
}
|
||||||
if (document.readyState === 'loading') {
|
|
||||||
document.addEventListener('DOMContentLoaded', insertData)
|
btf.addGlobalFn('pjaxComplete', runTrack, 'umami_analytics_run_track')
|
||||||
} else {
|
btf.addGlobalFn('pjaxComplete', insertData, 'umami_analytics_insert')
|
||||||
setTimeout(insertData, 100)
|
|
||||||
}
|
loadUmamiJS()
|
||||||
})()
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', insertData)
|
||||||
|
} else {
|
||||||
|
setTimeout(insertData, 100)
|
||||||
|
}
|
||||||
|
})()
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hexo-theme-butterfly",
|
"name": "hexo-theme-butterfly",
|
||||||
"version": "5.5.5",
|
"version": "5.6.0",
|
||||||
"description": "A Simple and Card UI Design theme for Hexo",
|
"description": "A Simple and Card UI Design theme for Hexo",
|
||||||
"main": "package.json",
|
"main": "package.json",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
+6
-6
@@ -1,7 +1,7 @@
|
|||||||
abcjs_basic_js:
|
abcjs_basic_js:
|
||||||
name: abcjs
|
name: abcjs
|
||||||
file: dist/abcjs-basic-min.js
|
file: dist/abcjs-basic-min.js
|
||||||
version: 6.6.3
|
version: 6.6.4
|
||||||
activate_power_mode:
|
activate_power_mode:
|
||||||
name: butterfly-extsrc
|
name: butterfly-extsrc
|
||||||
file: dist/activate-power-mode.min.js
|
file: dist/activate-power-mode.min.js
|
||||||
@@ -9,7 +9,7 @@ activate_power_mode:
|
|||||||
algolia_search:
|
algolia_search:
|
||||||
name: algoliasearch
|
name: algoliasearch
|
||||||
file: dist/lite/builds/browser.umd.js
|
file: dist/lite/builds/browser.umd.js
|
||||||
version: 5.53.0
|
version: 5.56.0
|
||||||
aplayer_css:
|
aplayer_css:
|
||||||
name: aplayer
|
name: aplayer
|
||||||
file: dist/APlayer.min.css
|
file: dist/APlayer.min.css
|
||||||
@@ -95,7 +95,7 @@ fontawesome:
|
|||||||
name: '@fortawesome/fontawesome-free'
|
name: '@fortawesome/fontawesome-free'
|
||||||
file: css/all.min.css
|
file: css/all.min.css
|
||||||
other_name: font-awesome
|
other_name: font-awesome
|
||||||
version: 7.2.0
|
version: 7.3.1
|
||||||
gitalk:
|
gitalk:
|
||||||
name: gitalk
|
name: gitalk
|
||||||
file: dist/gitalk.min.js
|
file: dist/gitalk.min.js
|
||||||
@@ -125,7 +125,7 @@ lazyload:
|
|||||||
mathjax:
|
mathjax:
|
||||||
name: mathjax
|
name: mathjax
|
||||||
file: tex-mml-chtml.js
|
file: tex-mml-chtml.js
|
||||||
version: 4.1.2
|
version: 4.1.3
|
||||||
medium_zoom:
|
medium_zoom:
|
||||||
name: medium-zoom
|
name: medium-zoom
|
||||||
file: dist/medium-zoom.min.js
|
file: dist/medium-zoom.min.js
|
||||||
@@ -133,7 +133,7 @@ medium_zoom:
|
|||||||
mermaid:
|
mermaid:
|
||||||
name: mermaid
|
name: mermaid
|
||||||
file: dist/mermaid.min.js
|
file: dist/mermaid.min.js
|
||||||
version: 11.15.0
|
version: 11.16.0
|
||||||
meting_js:
|
meting_js:
|
||||||
name: butterfly-extsrc
|
name: butterfly-extsrc
|
||||||
file: metingjs/dist/Meting.min.js
|
file: metingjs/dist/Meting.min.js
|
||||||
@@ -186,7 +186,7 @@ snackbar_css:
|
|||||||
twikoo:
|
twikoo:
|
||||||
name: twikoo
|
name: twikoo
|
||||||
file: dist/twikoo.all.min.js
|
file: dist/twikoo.all.min.js
|
||||||
version: 1.7.11
|
version: 1.7.14
|
||||||
typed:
|
typed:
|
||||||
name: typed.js
|
name: typed.js
|
||||||
file: dist/typed.umd.js
|
file: dist/typed.umd.js
|
||||||
|
|||||||
@@ -17,12 +17,11 @@ hexo.extend.helper.register('getArchiveLength', function () {
|
|||||||
const m = date.month() + 1
|
const m = date.month() + 1
|
||||||
const d = date.date()
|
const d = date.date()
|
||||||
|
|
||||||
if (yearly) {
|
// Always track year so year archive pages can be counted
|
||||||
const keyYear = `${y}`
|
const keyYear = `${y}`
|
||||||
map.set(keyYear, (map.get(keyYear) || 0) + 1)
|
map.set(keyYear, (map.get(keyYear) || 0) + 1)
|
||||||
}
|
|
||||||
|
|
||||||
if (monthly) {
|
if (monthly || daily) {
|
||||||
const keyMonth = `${y}-${m}`
|
const keyMonth = `${y}-${m}`
|
||||||
map.set(keyMonth, (map.get(keyMonth) || 0) + 1)
|
map.set(keyMonth, (map.get(keyMonth) || 0) + 1)
|
||||||
}
|
}
|
||||||
@@ -37,8 +36,8 @@ hexo.extend.helper.register('getArchiveLength', function () {
|
|||||||
|
|
||||||
// Determine the appropriate key to fetch based on current page context
|
// Determine the appropriate key to fetch based on current page context
|
||||||
let key
|
let key
|
||||||
if (yearly && year) key = `${year}`
|
if (yearly || monthly || daily) key = `${year}`
|
||||||
if (monthly && month) key = `${year}-${month}`
|
if ((monthly || daily) && month) key = `${year}-${month}`
|
||||||
if (daily && day) key = `${year}-${month}-${day}`
|
if (daily && day) key = `${year}-${month}-${day}`
|
||||||
|
|
||||||
// Return the count for the current period or default to the total posts
|
// Return the count for the current period or default to the total posts
|
||||||
|
|||||||
+11
-12
@@ -11,6 +11,8 @@ const colorPattern = /^(#|rgb|rgba|hsl|hsla)/i
|
|||||||
const simpleFilePattern = /\.(png|jpg|jpeg|gif|bmp|webp|svg|tiff)$/i
|
const simpleFilePattern = /\.(png|jpg|jpeg|gif|bmp|webp|svg|tiff)$/i
|
||||||
const archiveRegex = /\/archives\//
|
const archiveRegex = /\/archives\//
|
||||||
|
|
||||||
|
const { version: themeVersion } = require('../../package.json')
|
||||||
|
|
||||||
hexo.extend.helper.register('truncate', truncateContent)
|
hexo.extend.helper.register('truncate', truncateContent)
|
||||||
|
|
||||||
hexo.extend.helper.register('postDesc', data => {
|
hexo.extend.helper.register('postDesc', data => {
|
||||||
@@ -58,8 +60,6 @@ hexo.extend.helper.register('cloudTags', function (options = {}) {
|
|||||||
|
|
||||||
const userColors = normalizeColors(custom_colors)
|
const userColors = normalizeColors(custom_colors)
|
||||||
|
|
||||||
const resolveColorClass = (idx) => `tag-color-${idx % userColors.length}`
|
|
||||||
|
|
||||||
const generateStyle = (size, unit, page, color) => {
|
const generateStyle = (size, unit, page, color) => {
|
||||||
const colorStyle = page === 'tags' ? `background-color: ${color};` : `color: ${color};`
|
const colorStyle = page === 'tags' ? `background-color: ${color};` : `color: ${color};`
|
||||||
return `font-size: ${parseFloat(size.toFixed(2))}${unit}; ${colorStyle}`
|
return `font-size: ${parseFloat(size.toFixed(2))}${unit}; ${colorStyle}`
|
||||||
@@ -70,10 +70,9 @@ hexo.extend.helper.register('cloudTags', function (options = {}) {
|
|||||||
const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
|
const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
|
||||||
|
|
||||||
if (userColors && userColors.length) {
|
if (userColors && userColors.length) {
|
||||||
const colorClass = resolveColorClass(idx)
|
|
||||||
const color = userColors[idx % userColors.length]
|
const color = userColors[idx % userColors.length]
|
||||||
const style = generateStyle(size, unit, page, color)
|
const style = generateStyle(size, unit, page, color)
|
||||||
return `<a href="${env.url_for(tag.path)}" class="tag-cloud-item ${colorClass}" style="${style}">${tag.name}</a>`
|
return `<a href="${env.url_for(tag.path)}" class="tag-cloud-item" style="${style}">${tag.name}</a>`
|
||||||
}
|
}
|
||||||
|
|
||||||
const color = getRandomColor()
|
const color = getRandomColor()
|
||||||
@@ -105,13 +104,13 @@ hexo.extend.helper.register('findArchivesTitle', function (page, menu, date) {
|
|||||||
if (!menu) return defaultTitle
|
if (!menu) return defaultTitle
|
||||||
|
|
||||||
const loop = m => {
|
const loop = m => {
|
||||||
for (const key in m) {
|
for (const [key, value] of Object.entries(m)) {
|
||||||
if (typeof m[key] === 'object') {
|
if (value && typeof value === 'object') {
|
||||||
const result = loop(m[key])
|
const result = loop(value)
|
||||||
if (result) return result
|
if (result) return result
|
||||||
}
|
}
|
||||||
|
|
||||||
if (archiveRegex.test(m[key])) {
|
if (typeof value === 'string' && archiveRegex.test(value)) {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -154,9 +153,10 @@ hexo.extend.helper.register('shuoshuoFN', (data, page) => {
|
|||||||
|
|
||||||
// This is a hack method, because hexo treats time as UTC time
|
// This is a hack method, because hexo treats time as UTC time
|
||||||
// so you need to manually convert the time zone
|
// so you need to manually convert the time zone
|
||||||
|
const timezone = hexo.config.timezone
|
||||||
processedData.forEach(item => {
|
processedData.forEach(item => {
|
||||||
const utcDate = moment.utc(item.date).format('YYYY-MM-DD HH:mm:ss')
|
const parsed = moment.utc(item.date)
|
||||||
item.date = moment.tz(utcDate, hexo.config.timezone).format('YYYY-MM-DD HH:mm:ss')
|
item.date = moment.tz(parsed.format('YYYY-MM-DD HH:mm:ss'), timezone).format('YYYY-MM-DD HH:mm:ss')
|
||||||
// markdown
|
// markdown
|
||||||
item.content = hexo.render.renderSync({ text: item.content, engine: 'markdown' })
|
item.content = hexo.render.renderSync({ text: item.content, engine: 'markdown' })
|
||||||
})
|
})
|
||||||
@@ -179,8 +179,7 @@ hexo.extend.helper.register('getPageType', (page, isHome) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
hexo.extend.helper.register('getVersion', () => {
|
hexo.extend.helper.register('getVersion', () => {
|
||||||
const { version } = require('../../package.json')
|
return { hexo: hexo.version, theme: themeVersion }
|
||||||
return { hexo: hexo.version, theme: version }
|
|
||||||
})
|
})
|
||||||
|
|
||||||
hexo.extend.helper.register('safeJSON', data => {
|
hexo.extend.helper.register('safeJSON', data => {
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ hexo.extend.helper.register('related_posts', function (currentPost) {
|
|||||||
if (relatedPosts.has(post.path)) {
|
if (relatedPosts.has(post.path)) {
|
||||||
relatedPosts.get(post.path).weight += 1
|
relatedPosts.get(post.path).weight += 1
|
||||||
} else {
|
} else {
|
||||||
const getPostDesc = post.postDesc || postDesc(post, hexo)
|
|
||||||
relatedPosts.set(post.path, {
|
relatedPosts.set(post.path, {
|
||||||
title: post.title,
|
title: post.title,
|
||||||
path: post.path,
|
path: post.path,
|
||||||
@@ -32,7 +31,7 @@ hexo.extend.helper.register('related_posts', function (currentPost) {
|
|||||||
weight: 1,
|
weight: 1,
|
||||||
updated: post.updated,
|
updated: post.updated,
|
||||||
created: post.date,
|
created: post.date,
|
||||||
postDesc: getPostDesc,
|
post,
|
||||||
random: Math.random()
|
random: Math.random()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -61,12 +60,15 @@ hexo.extend.helper.register('related_posts', function (currentPost) {
|
|||||||
result += `<div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>${headlineLang}</span></div>`
|
result += `<div class="headline"><i class="fas fa-thumbs-up fa-fw"></i><span>${headlineLang}</span></div>`
|
||||||
result += '<div class="relatedPosts-list">'
|
result += '<div class="relatedPosts-list">'
|
||||||
|
|
||||||
for (let i = 0; i < Math.min(relatedPostsList.length, limitNum); i++) {
|
const max = Math.min(relatedPostsList.length, limitNum)
|
||||||
let { cover, title, path, cover_type, created, updated, postDesc } = relatedPostsList[i]
|
for (let i = 0; i < max; i++) {
|
||||||
|
const item = relatedPostsList[i]
|
||||||
|
let { cover, title, path, cover_type, created, updated, post } = item
|
||||||
const { escape_html, url_for, date } = this
|
const { escape_html, url_for, date } = this
|
||||||
cover = cover || 'var(--default-bg-color)'
|
cover = cover || 'var(--default-bg-color)'
|
||||||
title = escape_html(title)
|
title = escape_html(title)
|
||||||
const className = postDesc ? 'pagination-related' : 'pagination-related no-desc'
|
const desc = post.postDesc || postDesc(post, hexo)
|
||||||
|
const className = desc ? 'pagination-related' : 'pagination-related no-desc'
|
||||||
result += `<a class="${className}" href="${url_for(path)}" title="${title}">`
|
result += `<a class="${className}" href="${url_for(path)}" title="${title}">`
|
||||||
if (cover_type === 'img') {
|
if (cover_type === 'img') {
|
||||||
result += `<img class="cover" src="${url_for(cover)}" alt="cover">`
|
result += `<img class="cover" src="${url_for(cover)}" alt="cover">`
|
||||||
@@ -80,8 +82,8 @@ hexo.extend.helper.register('related_posts', function (currentPost) {
|
|||||||
}
|
}
|
||||||
result += `<div class="info-item-2">${title}</div></div>`
|
result += `<div class="info-item-2">${title}</div></div>`
|
||||||
|
|
||||||
if (postDesc) {
|
if (desc) {
|
||||||
result += `<div class="info-2"><div class="info-item-1">${postDesc}</div></div>`
|
result += `<div class="info-2"><div class="info-item-1">${desc}</div></div>`
|
||||||
}
|
}
|
||||||
result += '</div></a>'
|
result += '</div></a>'
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,16 @@
|
|||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const urlFor = require('hexo-util').url_for.bind(hexo)
|
const { url_for, escapeHTML } = require('hexo-util')
|
||||||
|
const urlFor = url_for.bind(hexo)
|
||||||
|
|
||||||
const btn = args => {
|
const btn = args => {
|
||||||
const [url = '', text = '', icon = '', option = ''] = args.join(' ').split(',').map(arg => arg.trim())
|
const [url = '', text = '', icon = '', option = ''] = args.join(' ').split(',').map(arg => arg.trim())
|
||||||
|
|
||||||
const iconHTML = icon ? `<i class="${icon}"></i>` : ''
|
const iconHTML = icon ? `<i class="${escapeHTML(icon)}"></i>` : ''
|
||||||
const textHTML = text ? `<span>${text}</span>` : ''
|
const textHTML = text ? `<span>${escapeHTML(text)}</span>` : ''
|
||||||
|
|
||||||
return `<a class="btn-beautify ${option}" href="${urlFor(url)}" title="${text}">${iconHTML}${textHTML}</a>`
|
return `<a class="btn-beautify ${escapeHTML(option)}" href="${urlFor(url)}" title="${escapeHTML(text)}">${iconHTML}${textHTML}</a>`
|
||||||
}
|
}
|
||||||
|
|
||||||
hexo.extend.tag.register('btn', btn, { ends: false })
|
hexo.extend.tag.register('btn', btn, { ends: false })
|
||||||
|
|||||||
@@ -4,24 +4,25 @@
|
|||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const urlFor = require('hexo-util').url_for.bind(hexo)
|
const { url_for, escapeHTML } = require('hexo-util')
|
||||||
|
const urlFor = url_for.bind(hexo)
|
||||||
|
|
||||||
const flinkFn = (args, content) => {
|
const flinkFn = (args, content) => {
|
||||||
const data = hexo.render.renderSync({ text: content, engine: 'yaml' })
|
const data = hexo.render.renderSync({ text: content, engine: 'yaml' })
|
||||||
let result = ''
|
let result = ''
|
||||||
|
|
||||||
data.forEach(item => {
|
data.forEach(item => {
|
||||||
const className = item.class_name ? `<div class="flink-name">${item.class_name}</div>` : ''
|
const className = item.class_name ? `<div class="flink-name">${escapeHTML(item.class_name)}</div>` : ''
|
||||||
const classDesc = item.class_desc ? `<div class="flink-desc">${item.class_desc}</div>` : ''
|
const classDesc = item.class_desc ? `<div class="flink-desc">${escapeHTML(item.class_desc)}</div>` : ''
|
||||||
|
|
||||||
const listResult = item.link_list.map(link => `
|
const listResult = item.link_list.map(link => `
|
||||||
<div class="flink-list-item">
|
<div class="flink-list-item">
|
||||||
<a href="${link.link}" title="${link.name}" target="_blank">
|
<a href="${escapeHTML(link.link)}" title="${escapeHTML(link.name)}" target="_blank">
|
||||||
<div class="flink-item-icon">
|
<div class="flink-item-icon">
|
||||||
<img class="no-lightbox" src="${link.avatar}" onerror='this.onerror=null;this.src="${urlFor(hexo.theme.config.error_img.flink)}"' alt="${link.name}" />
|
<img class="no-lightbox" src="${escapeHTML(link.avatar)}" onerror='this.onerror=null;this.src="${urlFor(hexo.theme.config.error_img.flink)}"' alt="${escapeHTML(link.name)}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="flink-item-name">${link.name}</div>
|
<div class="flink-item-name">${escapeHTML(link.name)}</div>
|
||||||
<div class="flink-item-desc" title="${link.descr}">${link.descr}</div>
|
<div class="flink-item-desc" title="${escapeHTML(link.descr)}">${escapeHTML(link.descr)}</div>
|
||||||
</a>
|
</a>
|
||||||
</div>`).join('')
|
</div>`).join('')
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const parseGalleryArgs = args => {
|
|||||||
const parseImageContent = content => {
|
const parseImageContent = content => {
|
||||||
const images = []
|
const images = []
|
||||||
let match
|
let match
|
||||||
|
IMAGE_REGEX.lastIndex = 0
|
||||||
|
|
||||||
while ((match = IMAGE_REGEX.exec(content)) !== null) {
|
while ((match = IMAGE_REGEX.exec(content)) !== null) {
|
||||||
images.push({
|
images.push({
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const parseArgs = args => args.join(' ').split(',')
|
const parseArgs = args => args.join(' ').split(',').map(s => s.trim())
|
||||||
|
|
||||||
const generateStyle = (bg, color) => {
|
const generateStyle = (bg, color) => {
|
||||||
let style = 'style="'
|
let style = 'style="'
|
||||||
|
|||||||
+3
-13
@@ -5,20 +5,10 @@
|
|||||||
|
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
|
const { escapeHTML } = require('hexo-util')
|
||||||
|
|
||||||
const score = (args, content) => {
|
const score = (args, content) => {
|
||||||
// Escape HTML tags and some special characters, including curly braces
|
const escapeHtmlTags = s => escapeHTML(s).replace(/[{}]/g, c => c === '{' ? '{' : '}')
|
||||||
const escapeHtmlTags = s => {
|
|
||||||
const lookup = {
|
|
||||||
'&': '&',
|
|
||||||
'"': '"',
|
|
||||||
"'": ''',
|
|
||||||
'<': '<',
|
|
||||||
'>': '>',
|
|
||||||
'{': '{',
|
|
||||||
'}': '}'
|
|
||||||
}
|
|
||||||
return s.replace(/[&"'<>{}]/g, c => lookup[c])
|
|
||||||
}
|
|
||||||
|
|
||||||
const trimmed = content.trim()
|
const trimmed = content.trim()
|
||||||
// Split content using six dashes as a delimiter
|
// Split content using six dashes as a delimiter
|
||||||
|
|||||||
@@ -12,6 +12,10 @@
|
|||||||
const urlFor = require('hexo-util').url_for.bind(hexo)
|
const urlFor = require('hexo-util').url_for.bind(hexo)
|
||||||
const groups = {}
|
const groups = {}
|
||||||
|
|
||||||
|
hexo.extend.filter.register('before_generate', () => {
|
||||||
|
Object.keys(groups).forEach(k => delete groups[k])
|
||||||
|
})
|
||||||
|
|
||||||
hexo.extend.filter.register('before_post_render', data => {
|
hexo.extend.filter.register('before_post_render', data => {
|
||||||
if (!hexo.theme.config.series.enable) return data
|
if (!hexo.theme.config.series.enable) return data
|
||||||
|
|
||||||
|
|||||||
+45
-34
@@ -267,18 +267,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const fetchUrl = async url => {
|
const fetchUrl = async url => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(url)
|
const response = await fetch(url)
|
||||||
|
if (!response.ok) throw new Error(`HTTP ${response.status}`)
|
||||||
return await response.json()
|
return await response.json()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Failed to fetch URL:', error)
|
console.error('Failed to fetch URL:', error)
|
||||||
return []
|
throw error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const runJustifiedGallery = (container, data, config) => {
|
const runJustifiedGallery = (container, data, config) => {
|
||||||
const { isButton, limit, firstLimit, tabs } = config
|
const { isButton, tabs } = config
|
||||||
|
const limit = Math.max(1, Number(config.limit) || 20)
|
||||||
|
const firstLimit = Math.max(1, Number(config.firstLimit) || limit)
|
||||||
|
|
||||||
const dataLength = data.length
|
const dataLength = data.length
|
||||||
const maxGroupKey = Math.ceil((dataLength - firstLimit) / limit + 1)
|
const maxGroupKey = dataLength
|
||||||
|
? Math.ceil(Math.max(0, dataLength - firstLimit) / limit) + 1
|
||||||
|
: 0
|
||||||
|
|
||||||
// Gallery configuration
|
// Gallery configuration
|
||||||
const igConfig = {
|
const igConfig = {
|
||||||
@@ -295,13 +300,19 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
let isLayoutHidden = false
|
let isLayoutHidden = false
|
||||||
|
|
||||||
// Utility functions
|
// Utility functions
|
||||||
const sanitizeString = str => (str && str.replace(/"/g, '"')) || ''
|
const sanitizeString = str => String(str ?? '')
|
||||||
|
.replace(/&/g, '&')
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/'/g, ''')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
|
||||||
const createImageItem = item => {
|
const createImageItem = item => {
|
||||||
const alt = item.alt ? `alt="${sanitizeString(item.alt)}"` : ''
|
const alt = item.alt ? `alt="${sanitizeString(item.alt)}"` : ''
|
||||||
const title = item.title ? `title="${sanitizeString(item.title)}"` : ''
|
const title = item.title ? `title="${sanitizeString(item.title)}"` : ''
|
||||||
|
const url = item.url ? sanitizeString(item.url) : ''
|
||||||
return `<div class="item">
|
return `<div class="item">
|
||||||
<img src="${item.url}" data-grid-maintained-target="true" ${alt} ${title} />
|
<img src="${url}" data-grid-maintained-target="true" ${alt} ${title} />
|
||||||
</div>`
|
</div>`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -370,11 +381,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
btf.setLoading.add(container)
|
btf.setLoading.add(container)
|
||||||
ig.on('renderComplete', handleRenderComplete)
|
ig.on('renderComplete', handleRenderComplete)
|
||||||
|
|
||||||
if (isButton) {
|
if (isButton && dataLength) {
|
||||||
appendItems(1, firstLimit, true)
|
appendItems(1, firstLimit, true)
|
||||||
} else {
|
} else if (dataLength) {
|
||||||
ig.on('requestAppend', handleRequestAppend)
|
ig.on('requestAppend', handleRequestAppend)
|
||||||
ig.renderItems()
|
ig.renderItems()
|
||||||
|
} else {
|
||||||
|
btf.setLoading.remove(container)
|
||||||
}
|
}
|
||||||
|
|
||||||
btf.addGlobalFn('pjaxSendOnce', () => ig.destroy())
|
btf.addGlobalFn('pjaxSendOnce', () => ig.destroy())
|
||||||
@@ -397,11 +410,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
const container = element.firstElementChild
|
const container = element.firstElementChild
|
||||||
const content = container.textContent
|
const content = container.textContent
|
||||||
container.textContent = ''
|
container.textContent = ''
|
||||||
element.classList.add('loaded')
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const data = element.getAttribute('data-type') === 'url' ? await fetchUrl(content) : JSON.parse(content)
|
const data = element.getAttribute('data-type') === 'url' ? await fetchUrl(content) : JSON.parse(content)
|
||||||
|
if (!Array.isArray(data)) throw new TypeError('Gallery data must be an array')
|
||||||
runJustifiedGallery(container, data, config)
|
runJustifiedGallery(container, data, config)
|
||||||
|
element.classList.add('loaded')
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Gallery data parsing failed:', error)
|
console.error('Gallery data parsing failed:', error)
|
||||||
}
|
}
|
||||||
@@ -436,24 +449,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
*/
|
*/
|
||||||
const scrollFn = () => {
|
const scrollFn = () => {
|
||||||
const $rightside = document.getElementById('rightside')
|
const $rightside = document.getElementById('rightside')
|
||||||
const innerHeight = window.innerHeight + 56
|
|
||||||
let initTop = 0
|
let initTop = 0
|
||||||
const $header = document.getElementById('page-header')
|
const $header = document.getElementById('page-header')
|
||||||
const isChatBtn = typeof chatBtn !== 'undefined'
|
const isChatBtn = typeof window.chatBtn !== 'undefined'
|
||||||
const isShowPercent = GLOBAL_CONFIG.percent.rightside
|
const isShowPercent = GLOBAL_CONFIG.percent.rightside
|
||||||
|
|
||||||
// 檢查文檔高度是否小於視窗高度
|
// 檢查文檔高度是否小於視窗高度
|
||||||
const checkDocumentHeight = () => {
|
const checkDocumentHeight = () => {
|
||||||
if (document.body.scrollHeight <= innerHeight) {
|
if (document.body.scrollHeight <= window.innerHeight + 56) {
|
||||||
$rightside.classList.add('rightside-show')
|
$rightside.classList.add('rightside-show')
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果文檔高度小於視窗高度,直接返回
|
|
||||||
if (checkDocumentHeight()) return
|
|
||||||
|
|
||||||
// find the scroll direction
|
// find the scroll direction
|
||||||
const scrollDirection = currentTop => {
|
const scrollDirection = currentTop => {
|
||||||
const result = currentTop > initTop // true is down & false is up
|
const result = currentTop > initTop // true is down & false is up
|
||||||
@@ -463,6 +472,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
let flag = ''
|
let flag = ''
|
||||||
const scrollTask = btf.rafThrottle(() => {
|
const scrollTask = btf.rafThrottle(() => {
|
||||||
|
if (checkDocumentHeight()) return
|
||||||
|
|
||||||
const currentTop = window.scrollY || document.documentElement.scrollTop
|
const currentTop = window.scrollY || document.documentElement.scrollTop
|
||||||
const isDown = scrollDirection(currentTop)
|
const isDown = scrollDirection(currentTop)
|
||||||
if (currentTop > 56) {
|
if (currentTop > 56) {
|
||||||
@@ -490,14 +501,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
$header.classList.remove('nav-fixed', 'nav-visible')
|
$header.classList.remove('nav-fixed', 'nav-visible')
|
||||||
}
|
}
|
||||||
$rightside.classList.remove('rightside-show')
|
$rightside.classList.remove('rightside-show')
|
||||||
}
|
}
|
||||||
|
|
||||||
isShowPercent && rightsideScrollPercent(currentTop)
|
isShowPercent && rightsideScrollPercent(currentTop)
|
||||||
checkDocumentHeight()
|
})
|
||||||
})
|
|
||||||
|
checkDocumentHeight()
|
||||||
btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true })
|
btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* toc, anchor
|
* toc, anchor
|
||||||
@@ -631,17 +642,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
const handleThemeChange = mode => {
|
const handleThemeChange = mode => {
|
||||||
const globalFn = window.globalFn || {}
|
const globalFn = window.globalFn || {}
|
||||||
const themeChange = globalFn.themeChange || {}
|
const themeChange = globalFn.themeChange
|
||||||
if (!themeChange) {
|
if (!themeChange) return
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
Object.keys(themeChange).forEach(key => {
|
Object.keys(themeChange).forEach(key => {
|
||||||
const themeChangeFn = themeChange[key]
|
const fn = themeChange[key]
|
||||||
|
if (typeof fn !== 'function') return
|
||||||
|
|
||||||
if (['disqus', 'disqusjs'].includes(key)) {
|
if (['disqus', 'disqusjs'].includes(key)) {
|
||||||
setTimeout(() => themeChangeFn(mode), 300)
|
setTimeout(() => fn(mode), 300)
|
||||||
} else {
|
} else {
|
||||||
themeChangeFn(mode)
|
fn(mode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -952,7 +963,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
|
|
||||||
const forPostFn = () => {
|
const forPostFn = () => {
|
||||||
const $article = document.getElementById('article-container')
|
const $article = document.getElementById('article-container')
|
||||||
if (!$article) return
|
if (!$article || $article.querySelector('.hbe-container')) return
|
||||||
|
|
||||||
addHighlightTool($article)
|
addHighlightTool($article)
|
||||||
addPhotoFigcaption($article)
|
addPhotoFigcaption($article)
|
||||||
|
|||||||
Reference in New Issue
Block a user