mirror of
https://github.com/jerryc127/hexo-theme-butterfly.git
synced 2026-08-10 20:48:42 +08:00
- wordcount/min2read/totalcount built-in helpers (replaces hexo-wordcount) - cloudTags random sort support - waline lightbox via MutationObserver - subtitle: seq guard prevents stale API response race - newest-comments: escapeHtml XSS fix, unified fetchAndRender with cache fallback - katex: try/catch asset load, encrypt re-render - chartjs: destroy charts on pjax, fix theme property check - mathjax: DOMContentLoaded instead of load - mermaid: clean stale error elements - medium-zoom: single instance, detach on pjax - getScrollPercent: WeakMap cache with resize invalidation - overflowPaddingR: avoid stale DOM refs - readmode: dedupe button, pjax cleanup - hexo-blog-decrypt: null-guard translateFn and encryptFn - tw_cn: expand skipped translate tags - localStorage: try/catch setItem - cdn.js: fix [lib|dist]* character class regex bug - findArchivesTitle: support custom archive_dir - shuoshuoFN: guard moment.tz when timezone empty - umami: no-store cache, error handling, path param - artalk: vote config option - bump version 5.7.1.260810
111 lines
3.7 KiB
Plaintext
111 lines
3.7 KiB
Plaintext
- let { serverURL, script_name, website_id, option, UV_PV } = theme.umami_analytics
|
|
- const isServerURL = !!serverURL
|
|
- const baseURL = serverURL ? serverURL.replace(/\/$/, '') : 'https://cloud.umami.is'
|
|
- const apiUrl = serverURL ? serverURL.replace(/\/$/, '') + '/api' : 'https://api.umami.is/v1'
|
|
|
|
script.
|
|
(() => {
|
|
const option = !{JSON.stringify(option)}
|
|
const config = !{JSON.stringify(UV_PV)}
|
|
|
|
const runTrack = () => {
|
|
if (typeof umami !== 'undefined' && typeof umami.track === 'function') {
|
|
umami.track(props => ({ ...props, url: window.location.pathname, title: GLOBAL_CONFIG_SITE.title }))
|
|
} else {
|
|
console.warn('Umami Analytics: umami.track is not available')
|
|
}
|
|
}
|
|
|
|
const loadUmamiJS = () => {
|
|
btf.getScript('!{baseURL}/!{script_name}', {
|
|
'data-website-id': '!{website_id}',
|
|
'data-auto-track': 'false',
|
|
...option
|
|
}).then(() => {
|
|
runTrack()
|
|
}).catch(error => {
|
|
console.error('Umami Analytics: Error loading script', error)
|
|
})
|
|
}
|
|
|
|
const extractValue = stat => (stat && typeof stat.value !== 'undefined') ? stat.value : stat
|
|
|
|
const getData = async (isPost, path = window.location.pathname) => {
|
|
const now = Date.now()
|
|
const pathQuery = isPost ? `&url=${path}&path=${path}` : ''
|
|
const headers = {
|
|
'Accept': 'application/json',
|
|
[!{isServerURL} ? 'Authorization' : 'x-umami-api-key']: !{isServerURL} ? `Bearer ${config.token}` : config.token
|
|
}
|
|
|
|
const res = await fetch(`!{apiUrl}/websites/!{website_id}/stats?startAt=0000000000&endAt=${now}${pathQuery}`, {
|
|
method: 'GET',
|
|
headers,
|
|
cache: 'no-store'
|
|
})
|
|
|
|
if (!res.ok) {
|
|
throw new Error(`HTTP error! status: ${res.status}`)
|
|
}
|
|
|
|
return await res.json()
|
|
}
|
|
|
|
const insertData = async () => {
|
|
try {
|
|
const tasks = []
|
|
|
|
if (GLOBAL_CONFIG_SITE.pageType === 'post' && config.page_pv) {
|
|
tasks.push((async () => {
|
|
const pagePV = document.getElementById('umamiPV')
|
|
if (pagePV) {
|
|
const path = pagePV.dataset.path || window.location.pathname
|
|
const data = await getData(true, path)
|
|
if (data && data.pageviews) {
|
|
pagePV.textContent = extractValue(data.pageviews)
|
|
} else {
|
|
console.warn('Umami Analytics: Invalid page view data received')
|
|
}
|
|
}
|
|
})())
|
|
}
|
|
|
|
const siteUV = config.site_uv ? document.getElementById('umami-site-uv') : null
|
|
const sitePV = config.site_pv ? document.getElementById('umami-site-pv') : null
|
|
|
|
if (siteUV || sitePV) {
|
|
tasks.push((async () => {
|
|
const data = await getData(false)
|
|
|
|
if (siteUV && data && data.visitors) {
|
|
siteUV.textContent = extractValue(data.visitors)
|
|
} else if (siteUV) {
|
|
console.warn('Umami Analytics: Invalid site UV data received')
|
|
}
|
|
|
|
if (sitePV && data && data.pageviews) {
|
|
sitePV.textContent = extractValue(data.pageviews)
|
|
} else if (sitePV) {
|
|
console.warn('Umami Analytics: Invalid site PV data received')
|
|
}
|
|
})())
|
|
}
|
|
|
|
await Promise.all(tasks)
|
|
} catch (error) {
|
|
console.error('Umami Analytics: Failed to insert data', error)
|
|
}
|
|
}
|
|
|
|
btf.addGlobalFn('pjaxComplete', runTrack, 'umami_analytics_run_track')
|
|
btf.addGlobalFn('pjaxComplete', insertData, 'umami_analytics_insert')
|
|
|
|
loadUmamiJS()
|
|
|
|
if (document.readyState === 'loading') {
|
|
document.addEventListener('DOMContentLoaded', insertData)
|
|
} else {
|
|
setTimeout(insertData, 100)
|
|
}
|
|
})()
|