mirror of
https://github.com/jerryc127/hexo-theme-butterfly.git
synced 2026-08-10 20:48:42 +08:00
feat: add wordcount helpers, waline lightbox, and extensive bug fixes
- 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
This commit is contained in:
+97
-61
@@ -1,61 +1,97 @@
|
||||
script.
|
||||
window.newestComments = {
|
||||
changeContent: content => {
|
||||
if (content === '') return content
|
||||
|
||||
content = content.replace(/<img.*?src="(.*?)"?[^\>]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link
|
||||
content = content.replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url
|
||||
content = content.replace(/<pre><code>.*?<\/pre>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
|
||||
content = content.replace(/<code>.*?<\/code>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
|
||||
content = content.replace(/<[^>]+>/g, "") // remove html tag
|
||||
|
||||
if (content.length > 150) {
|
||||
content = content.substring(0, 150) + '...'
|
||||
}
|
||||
return content
|
||||
},
|
||||
|
||||
generateHtml: (array, ele) => {
|
||||
let result = ''
|
||||
|
||||
if (array.length) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
result += '<div class="aside-list-item">'
|
||||
|
||||
if (!{theme.aside.card_newest_comments.avatar} && array[i].avatar) {
|
||||
const imgAttr = '!{theme.lazyload.enable && !theme.lazyload.native ? "data-lazy-src" : "src"}'
|
||||
const lazyloadNative = '!{theme.lazyload.enable && theme.lazyload.native ? "loading=\"lazy\"" : ""}'
|
||||
result += `<a href="${array[i].url}" class="thumbnail"><img ${imgAttr}="${array[i].avatar}" alt="${array[i].nick}" ${lazyloadNative}></a>`
|
||||
}
|
||||
|
||||
result += `<div class="content">
|
||||
<a class="comment" href="${array[i].url}" title="${array[i].content}">${array[i].content}</a>
|
||||
<div class="name"><span>${array[i].nick} / </span><time datetime="${array[i].date}">${btf.diffDate(array[i].date, true)}</time></div>
|
||||
</div></div>`
|
||||
}
|
||||
} else {
|
||||
result += '!{_p("aside.card_newest_comments.zero")}'
|
||||
}
|
||||
|
||||
ele.innerHTML = result
|
||||
window.lazyLoadInstance && window.lazyLoadInstance.update()
|
||||
window.pjax && window.pjax.refresh(ele)
|
||||
},
|
||||
|
||||
newestCommentInit: (name, getComment) => {
|
||||
const $dom = document.querySelector('#card-newest-comments .aside-list')
|
||||
if ($dom) {
|
||||
const data = btf.saveToLocal.get(name)
|
||||
if (data) {
|
||||
newestComments.generateHtml(JSON.parse(data), $dom)
|
||||
} else {
|
||||
getComment($dom)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
run: (name, getComment) => {
|
||||
newestComments.newestCommentInit(name, getComment)
|
||||
btf.addGlobalFn('pjaxComplete', () => newestComments.newestCommentInit(name, getComment), name)
|
||||
}
|
||||
}
|
||||
script.
|
||||
window.newestComments = {
|
||||
ready: fn => {
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', fn, { once: true })
|
||||
} else {
|
||||
fn()
|
||||
}
|
||||
},
|
||||
|
||||
escapeHtml: str => {
|
||||
return String(str)
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
},
|
||||
|
||||
changeContent: content => {
|
||||
if (!content) return ''
|
||||
|
||||
content = content.replace(/<img[^>]*>/gis, '[!{_p("aside.card_newest_comments.image")}]') // replace image link
|
||||
content = content.replace(/<pre><code>[\s\S]*?<\/pre>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code block
|
||||
content = content.replace(/<a[^>]+?>[\s\S]*?<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url
|
||||
content = content.replace(/<code[^>]*?>[\s\S]*?<\/code>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
|
||||
content = content.replace(/<[^>]+>/g, '') // remove html tag
|
||||
|
||||
if (content.length > 150) {
|
||||
content = Array.from(content).slice(0, 150).join('') + '...'
|
||||
}
|
||||
|
||||
return content
|
||||
},
|
||||
|
||||
generateHtml: (array, ele) => {
|
||||
const { escapeHtml } = window.newestComments
|
||||
let result = ''
|
||||
|
||||
if (array.length) {
|
||||
result = array.map(item => {
|
||||
let html = '<div class="aside-list-item">'
|
||||
|
||||
if (!{theme.aside.card_newest_comments.avatar} && item.avatar) {
|
||||
const imgAttr = '!{theme.lazyload.enable && !theme.lazyload.native ? "data-lazy-src" : "src"}'
|
||||
const lazyloadNative = '!{theme.lazyload.enable && theme.lazyload.native ? "loading=\"lazy\"" : ""}'
|
||||
html += `<a href="${escapeHtml(item.url)}" class="thumbnail"><img ${imgAttr}="${escapeHtml(item.avatar)}" alt="${escapeHtml(item.nick)}" ${lazyloadNative}></a>`
|
||||
}
|
||||
|
||||
html += `<div class="content">
|
||||
<a class="comment" href="${escapeHtml(item.url)}" title="${escapeHtml(item.content)}">${escapeHtml(item.content)}</a>
|
||||
<div class="name"><span>${escapeHtml(item.nick)} / </span><time datetime="${escapeHtml(item.date)}">${btf.diffDate(item.date, true)}</time></div>
|
||||
</div></div>`
|
||||
|
||||
return html
|
||||
}).join('')
|
||||
} else {
|
||||
result += '!{_p("aside.card_newest_comments.zero")}'
|
||||
}
|
||||
|
||||
ele.innerHTML = result
|
||||
window.lazyLoadInstance && window.lazyLoadInstance.update()
|
||||
window.pjax && window.pjax.refresh(ele)
|
||||
},
|
||||
|
||||
fetchAndRender: (keyName, ele, getComment) => {
|
||||
Promise.resolve(getComment(ele)).then(array => {
|
||||
btf.saveToLocal.set(keyName, JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24))
|
||||
newestComments.generateHtml(array, ele)
|
||||
}).catch(e => {
|
||||
console.error(e)
|
||||
const data = btf.saveToLocal.get(keyName)
|
||||
if (data) {
|
||||
newestComments.generateHtml(JSON.parse(data), ele)
|
||||
} else {
|
||||
ele.textContent = '!{_p("aside.card_newest_comments.error")}'
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
newestCommentInit: (name, getComment) => {
|
||||
const $dom = document.querySelector('#card-newest-comments .aside-list')
|
||||
if ($dom) {
|
||||
const data = btf.saveToLocal.get(name)
|
||||
if (data) {
|
||||
newestComments.generateHtml(JSON.parse(data), $dom)
|
||||
} else {
|
||||
newestComments.fetchAndRender(name, $dom, getComment)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
run: (name, getComment) => {
|
||||
newestComments.newestCommentInit(name, getComment)
|
||||
btf.addGlobalFn('pjaxComplete', () => newestComments.newestCommentInit(name, getComment), name)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user