breaking change:

1. 部分配置更改

feat:
1. 移除 messenger 聊天插件
2. 更新 fackbook 版本號
3. 增加 香港繁體、日文和韓語
4. 使用的新的複製api 代替舊的
5. 增加 umami 分析
6. 增加 umami 獲取訪問量/訪客數
7. snackbar 增加透明度
8. 文章頁下, nav fixed 下 顯示文章標題

improvement:
1. 代碼優化
2. 修改部分用語
3. 回復之前的相對時間邏輯
4. timeline tag 樣式優化
5. 優化 seo
6. 優化 artalk 的最新評論

fix:
1. tag-hide toggle 圓角問題
2. lazyload 為 false 時,artalk 無法正常加載評論的 bug
3. 修復 gallery 出現抖動的 bug
This commit is contained in:
Jerry
2024-09-15 00:43:03 +08:00
Unverified
parent 48212b9610
commit d8a1fa6417
76 changed files with 1315 additions and 1296 deletions

View File

@@ -1,4 +1,4 @@
if theme.abcjs && theme.abcjs.enable
if theme.abcjs.enable
if theme.abcjs.per_page
if is_post() || is_page()
include ./abcjs.pug

View File

@@ -1,5 +1,5 @@
- const fbSDKVer = 'v16.0'
- const fbSDK = theme.chat.use === 'messenger' ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}`
- const fbSDKVer = 'v20.0'
- const fbSDK = `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}`
script.
(()=>{

View File

@@ -15,22 +15,15 @@ script.
Chatra('show')
}
window.ChatraSetup = {
startHidden: true
}
window.ChatraSetup = { startHidden: true }
window.chatBtnFn = () => {
const isShow = document.getElementById('chatra').classList.contains('chatra--expanded')
isShow ? close() : open()
document.getElementById('chatra').classList.contains('chatra--expanded') ? close() : open()
}
} else if (isChatHideShow) {
window.chatBtn = {
hide: () => {
Chatra('hide')
},
show: () => {
Chatra('show')
}
hide: () => Chatra('hide'),
show: () => Chatra('show')
}
}
@@ -38,13 +31,12 @@ script.
w.ChatraID = '#{theme.chatra.id}'
var s = d.createElement('script')
w[c] = w[c] || function() {
(w[c].q = w[c].q || []).push(arguments)
(w[c].q = w[c].q || []).push(arguments)
}
s.async = true
s.src = 'https://call.chatra.io/chatra.js'
if (d.head) d.head.appendChild(s)
})(document, window, 'Chatra')
})()

View File

@@ -20,26 +20,18 @@ script.
$crisp.push(["do", "chat:open"])
}
const close = () => {
$crisp.push(["do", "chat:hide"])
}
const close = () => $crisp.push(["do", "chat:hide"])
close()
$crisp.push(["on", "chat:closed", function() {
close()
}])
window.chatBtnFn = () => {
$crisp.is("chat:visible") ? close() : open()
}
$crisp.push(["on", "chat:closed", close])
window.chatBtnFn = () => $crisp.is("chat:visible") ? close() : open()
} else if (isChatHideShow) {
window.chatBtn = {
hide: () => {
$crisp.push(["do", "chat:hide"])
},
show: () => {
$crisp.push(["do", "chat:show"])
}
hide: () => $crisp.push(["do", "chat:hide"]),
show: () => $crisp.push(["do", "chat:show"])
}
}
})()

View File

@@ -6,6 +6,4 @@ case theme.chat.use
when 'daovoice'
include ./daovoice.pug
when 'crisp'
include ./crisp.pug
when 'messenger'
include ./messenger.pug
include ./crisp.pug

View File

@@ -1,44 +0,0 @@
- let { pageID, lang } = theme.messenger
- lang = theme.comments.use && theme.comments.use.includes('Facebook Comments') ? theme.facebook_comments.lang : lang
#fb-customer-chat.fb-customerchat(page_id=pageID attribution='biz_inbox')
script.
(() => {
document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '<div id="fb-root"></div>')
window.fbAsyncInit = function() {
FB.init({
xfbml: true,
version: 'v16.0'
});
};
(function(d, s, id) {
var js, fjs = d.getElementsByTagName(s)[0];
if (d.getElementById(id)) return;
js = d.createElement(s); js.id = id;
js.src = 'https://connect.facebook.net/!{lang}/sdk/xfbml.customerchat.js';
fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk'));
const isChatBtn = !{theme.chat.rightside_button}
const isChatHideShow = !{theme.chat.button_hide_show}
if (isChatBtn) {
window.chatBtnFn = () => {
const isShow = document.querySelector('.fb_customer_chat_bounce_in_v2')
isShow ? FB.CustomerChat.hide() : FB.CustomerChat.show()
}
} else if (isChatHideShow) {
window.chatBtn = {
hide: () => {
FB.CustomerChat.hide()
},
show: () => {
FB.CustomerChat.show(false)
}
}
}
})()

View File

@@ -33,12 +33,8 @@ script.
}
} else if (isChatHideShow) {
window.chatBtn = {
hide: () => {
window.tidioChatApi && window.tidioChatApi.hide()
},
show: () => {
window.tidioChatApi && window.tidioChatApi.show()
}
hide: () => window.tidioChatApi && window.tidioChatApi.hide(),
show: () => window.tidioChatApi && window.tidioChatApi.show()
}
}
})()

View File

@@ -48,7 +48,7 @@ script.
if ('!{use[0]}' === 'Artalk' || !!{lazyload}) {
if (!{lazyload}) btf.loadComment(document.getElementById('artalk-wrap'), loadArtalk)
else loadArtalk()
else setTimeout(loadArtalk, 100)
} else {
window.loadOtherComment = loadArtalk
}

View File

@@ -1,5 +1,5 @@
- const fbSDKVer = 'v16.0'
- const fbSDK = theme.chat.use === 'messenger' ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}`
- const fbSDKVer = 'v20.0'
- const fbSDK = `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}`
script.
(()=>{

View File

@@ -1,19 +1,11 @@
case theme.math.use
when 'mathjax'
if theme.math.per_page
if is_post() || is_page()
include ./mathjax.pug
else
if page.mathjax
include ./mathjax.pug
if (theme.math.per_page && (is_post() || is_page())) || page.mathjax
include ./mathjax.pug
when 'katex'
if theme.math.per_page
if is_post() || is_page()
include ./katex.pug
else
if page.katex
include ./katex.pug
if (theme.math.per_page && (is_post() || is_page())) || page.katex
include ./katex.pug
if theme.mermaid.enable
include ./mermaid.pug

View File

@@ -1,15 +1,15 @@
script.
(async () => {
const showKatex = () => {
const mathElements = document.querySelectorAll('#article-container .katex')
mathElements.length && mathElements.forEach((el) => {
el.classList.add('katex-show')
})
document.querySelectorAll('#article-container .katex').forEach(el => el.classList.add('katex-show'))
}
if (!window.katex_js_css) {
window.katex_js_css = true
await btf.getCSS('!{url_for(theme.asset.katex)}')
if (!{theme.math.katex.copy_tex}) await btf.getScript('!{url_for(theme.asset.katex_copytex)}')
if (!{theme.math.katex.copy_tex}) {
await btf.getScript('!{url_for(theme.asset.katex_copytex)}')
}
}
showKatex()

View File

@@ -1,13 +1,13 @@
script.
(() => {
const runMermaid = (ele) => {
const runMermaid = ele => {
window.loadMermaid = true
const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}'
Array.from(ele).forEach((item, index) => {
ele.forEach((item, index) => {
const mermaidSrc = item.firstElementChild
const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n'
const mermaidID = 'mermaid-' + index
const mermaidThemeConfig = `%%{init:{ 'theme':'${theme}'}}%%\n`
const mermaidID = `mermaid-${index}`
const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
const renderFn = mermaid.render(mermaidID, mermaidDefinition)
@@ -16,14 +16,14 @@ script.
}
// mermaid v9 and v10 compatibility
typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({svg}) => renderMermaid(svg))
typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({ svg }) => renderMermaid(svg))
})
}
const codeToMermaid = () => {
const codeMermaidEle = document.querySelectorAll('pre > code.mermaid')
if (codeMermaidEle.length === 0) return
codeMermaidEle.forEach(ele => {
const preEle = document.createElement('pre')
preEle.className = 'mermaid-src'
@@ -45,7 +45,7 @@ script.
btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid')
window.loadMermaid ? runMermaidFn() : btf.getScript('!{url_for(theme.asset.mermaid)}').then(runMermaidFn)
}
btf.addGlobalFn('encrypt', loadMermaid, 'mermaid')
window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
})()

View File

@@ -2,106 +2,63 @@
- const avatarCdn = (option !== null && option.gravatar && option.gravatar.mirror) || ''
- const avatarDefault = (option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default)) || ''
!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true })
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
const keyName = 'artalk-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
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(/<[^>]+>/g,"") // remove html tag
const getAvatarValue = async () => {
const predefinedAvatarCdn = '!{avatarCdn}'
const predefinedAvatarDefault = '!{avatarDefault}'
if (content.length > 150) {
content = content.substring(0,150) + '...'
const avatarDefaultFormat = e => e.startsWith('d=') ? e : `d=${e}`
if (predefinedAvatarCdn && predefinedAvatarDefault) {
return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) }
}
return content
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom && ($dom.innerHTML= result))
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const getSetting = async () => {
try {
const res = await fetch('!{server}/api/v2/conf', { method: 'GET' })
return await res.json()
const res = await fetch('!{server}/api/v2/conf')
const result = await res.json()
const { mirror, params, default: defaults } = result.frontend_conf.gravatar
const avatarCdn = predefinedAvatarCdn || mirror
let avatarDefault = avatarDefaultFormat(predefinedAvatarDefault || params || defaults)
return { avatarCdn, avatarDefault}
} catch (e) {
console.log(e)
console.error(e)
return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) }
}
}
const headerList = {
method: 'GET',
}
const searchParams = new URLSearchParams({
'site_name': '!{site}',
'limit': '!{theme.aside.card_newest_comments.limit}',
})
const getComment = async () => {
const getComment = async (ele) => {
try {
const res = await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`, headerList)
const res = await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`)
const result = await res.json()
const avatarStr = await getSetting()
const { mirror, params, default:defaults } = avatarStr.frontend_conf.gravatar
const avatarCdn = '!{avatarCdn}' || mirror
let avatarDefault = '!{avatarDefault}' || params || defaults
avatarDefault = avatarDefault.startsWith('d=') ? avatarDefault : `d=${avatarDefault}`
const artalk = result.data.map(function (e) {
const { avatarCdn, avatarDefault } = await getAvatarValue()
const artalk = result.data.map(e => {
const avatar = avatarCdn && e.email_encrypted ? `${avatarCdn}${e.email_encrypted}?${avatarDefault}` : ''
return {
'avatar': `${avatarCdn}${e.email_encrypted}?${avatarDefault}`,
'avatar': avatar,
'content': changeContent(e.content_marked),
'nick': e.nick,
'url': e.page_url,
'date': e.date,
}
})
btf.saveToLocal.set('artalk-newest-comments', JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(artalk)
btf.saveToLocal.set(keyName, JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(artalk, ele)
} catch (e) {
console.log(e)
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
}
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('artalk-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'artalk_newestComment')
})
run(keyName, getComment)
})

View File

@@ -0,0 +1,60 @@
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 ? "data-lazy-src" : "src"}'
result += `<a href="${array[i].url}" class="thumbnail"><img ${imgAttr}="${array[i].avatar}" alt="${array[i].nick}"></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)
}
}

View File

@@ -1,20 +1,11 @@
!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true })
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
const keyName = 'disqus-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
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(/<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
}
const getComment = () => {
const getComment = ele => {
fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{theme.aside.card_newest_comments.limit}&api_key=!{apiKey}')
.then(response => response.json())
.then(data => {
@@ -28,54 +19,15 @@ script.
}
})
btf.saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(disqusArray)
btf.saveToLocal.set(keyName, JSON.stringify(disqusArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(disqusArray, ele)
}).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
console.error(e)
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
})
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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> / ${btf.diffDate(array[i].date, true)}</time></div>
</div></div>`
}
} else {
result += '!{_p("aside.card_newest_comments.zero")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom.innerHTML= result)
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('disqus-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'disqus_newestComment')
run(keyName, getComment)
})

View File

@@ -1,20 +1,11 @@
!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true })
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
const keyName = 'github-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
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(/<[^>]+>/g,"") // remove html tag
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const findTrueUrl = (array) => {
const findTrueUrl = (array, ele) => {
Promise.all(array.map(item =>
fetch(item.url).then(resp => resp.json()).then(data => {
let urlArray = data.body ? data.body.match(/(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/ig) : []
@@ -35,12 +26,12 @@ script.
}
})
btf.saveToLocal.set('github-newest-comments', JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(array)
btf.saveToLocal.set(keyName, JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(array, ele)
});
}
const getComment = () => {
const getComment = ele => {
fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.aside.card_newest_comments.limit}&page=1',{
"headers": {
Accept: 'application/vnd.github.v3.html+json'
@@ -54,57 +45,16 @@ script.
'content': changeContent(item.body_html || item.body),
'nick': item.user.login,
'url': item.issue_url,
'date': item.updated_at,
'githubUrl': item.html_url
'date': item.updated_at
}
})
findTrueUrl(githubArray)
findTrueUrl(githubArray, ele)
}).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
console.error(e)
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
})
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom.innerHTML= result)
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('github-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'github_newestComment')
run(keyName, getComment)
})

View File

@@ -2,52 +2,14 @@
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
const keyName = 'remark42-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
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(/<[^>]+>/g,"") // remove html tag
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom.innerHTML= result)
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const getComment = () => {
const getComment = ele => {
fetch('!{host}/api/v1/last/!{theme.aside.card_newest_comments.limit}?site=!{siteId}')
.then(response => response.json())
.then(data => {
const remark42 = data.map(function (e) {
const remark42 = data.map(e => {
return {
'avatar': e.user.picture,
'content': changeContent(e.text),
@@ -56,25 +18,13 @@ script.
'date': e.time,
}
})
btf.saveToLocal.set('remark42-newest-comments', JSON.stringify(remark42), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(remark42)
btf.saveToLocal.set(keyName, JSON.stringify(remark42), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(remark42, ele)
}).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
console.error(e)
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
})
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('remark42-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'remark42_newestComment')
run(keyName, getComment)
})

View File

@@ -1,27 +1,18 @@
!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true })
script.
window.addEventListener('load', () => {
const changeContent = (content) => {
if (content === '') return content
const keyName = 'twikoo-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
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_aside.card_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
}
const getComment = () => {
const getComment = ele => {
const runTwikoo = () => {
twikoo.getRecentComments({
envId: '!{theme.twikoo.envId}',
region: '!{theme.twikoo.region}',
pageSize: !{theme.aside.card_newest_comments.limit},
includeReply: true
}).then(function (res) {
}).then(res => {
const twikooArray = res.map(e => {
return {
'content': changeContent(e.comment),
@@ -32,11 +23,11 @@ script.
}
})
btf.saveToLocal.set('twikoo-newest-comments', JSON.stringify(twikooArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(twikooArray)
}).catch(function (err) {
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
btf.saveToLocal.set(keyName, JSON.stringify(twikooArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(twikooArray, ele)
}).catch(err => {
console.error(err)
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
})
}
@@ -47,46 +38,7 @@ script.
}
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom.innerHTML= result)
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('twikoo-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'twikoo_newestComment')
run(keyName, getComment)
})

View File

@@ -1,21 +1,12 @@
- let default_avatar = theme.valine.avatar
script(src=url_for(theme.asset.blueimp_md5))
!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true })
script.
window.addEventListener('load', () => {
const 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(/<[^>]+>/g,"") // remove html tag
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const keyName = 'valine-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
const getIcon = (icon, mail) => {
if (icon) return icon
@@ -24,34 +15,7 @@ script.
return iconUrl
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom.innerHTML= result)
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const getComment = () => {
const getComment = ele => {
const serverURL = '!{theme.valine.serverURLs || `https://${theme.valine.appId.substring(0,8)}.api.lncldglobal.com` }'
var settings = {
@@ -66,7 +30,7 @@ script.
fetch(`${serverURL}/1.1/classes/Comment?limit=!{theme.aside.card_newest_comments.limit}&order=-createdAt`,settings)
.then(response => response.json())
.then(data => {
const valineArray = data.results.map(function (e) {
const valineArray = data.results.map(e => {
return {
'avatar': getIcon(e.QQAvatar, e.mail),
'content': changeContent(e.comment),
@@ -75,25 +39,13 @@ script.
'date': e.updatedAt,
}
})
btf.saveToLocal.set('valine-newest-comments', JSON.stringify(valineArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(valineArray)
btf.saveToLocal.set(keyName, JSON.stringify(valineArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(valineArray, ele)
}).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
})
console.error(e)
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
})
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('valine-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'valine_newestComment')
run(keyName, getComment)
})

View File

@@ -1,49 +1,13 @@
- const serverURL = theme.waline.serverURL.replace(/\/$/, '')
!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true })
script.
window.addEventListener('load', () => {
const changeContent = content => {
if (content === '') return content
const keyName = 'waline-newest-comments'
const { changeContent, generateHtml, run } = window.newestComments
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(/<[^>]+>/g,"") // remove html tag
if (content.length > 150) {
content = content.substring(0,150) + '...'
}
return content
}
const generateHtml = array => {
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}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></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")}'
}
let $dom = document.querySelector('#card-newest-comments .aside-list')
$dom && ($dom.innerHTML= result)
window.lazyLoadInstance && window.lazyLoadInstance.update()
window.pjax && window.pjax.refresh($dom)
}
const getComment = async () => {
const getComment = async (ele) => {
try {
const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{theme.aside.card_newest_comments.limit}', { method: 'GET' })
const result = await res.json()
@@ -56,26 +20,13 @@ script.
'date': e.time || e.insertedAt
}
})
btf.saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(walineArray)
btf.saveToLocal.set(keyName, JSON.stringify(walineArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(walineArray, ele)
} catch (err) {
console.error(err)
const $dom = document.querySelector('#card-newest-comments .aside-list')
$dom.textContent= "!{_p('aside.card_newest_comments.error')}"
ele.textContent= "!{_p('aside.card_newest_comments.error')}"
}
}
const newestCommentInit = () => {
if (document.querySelector('#card-newest-comments .aside-list')) {
const data = btf.saveToLocal.get('waline-newest-comments')
if (data) {
generateHtml(JSON.parse(data))
} else {
getComment()
}
}
}
newestCommentInit()
btf.addGlobalFn('pjaxComplete', newestCommentInit, 'waline_newestComment')
run(keyName, getComment)
})

View File

@@ -1,9 +1,9 @@
- var pjaxExclude = 'a:not([target="_blank"])'
if theme.pjax.exclude
each val in theme.pjax.exclude
- pjaxExclude = pjaxExclude + `:not([href="${val}"])`
- pjaxExclude += `:not([href="${val}"])`
- let pjaxSelectors = ['head > title','#config-diff','#body-wrap','#rightside-config-hide','#rightside-config-show','.js-pjax']
- let pjaxSelectors = ['head > title', '#config-diff', '#body-wrap', '#rightside-config-hide', '#rightside-config-show', '.js-pjax']
- let choose = theme.comments.use
if choose
@@ -14,49 +14,50 @@ if choose
script(src=url_for(theme.asset.pjax))
script.
let pjaxSelectors = !{JSON.stringify(pjaxSelectors)}
(() => {
const pjaxSelectors = !{JSON.stringify(pjaxSelectors)}
var pjax = new Pjax({
elements: '!{pjaxExclude}',
selectors: pjaxSelectors,
cacheBust: false,
analytics: !{theme.google_analytics ? true : false},
scrollRestoration: false
})
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => { fn() })
}
document.addEventListener('pjax:send', function () {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
//reset readmode
const $bodyClassList = document.body.classList
$bodyClassList.contains('read-mode') && $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
window.pjax = new Pjax({
elements: '!{pjaxExclude}',
selectors: pjaxSelectors,
cacheBust: false,
analytics: !{theme.google_analytics ? true : false},
scrollRestoration: false
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
if (e.request.status === 404) {
pjax.loadUrl('!{url_for("/404.html")}')
const triggerPjaxFn = (val) => {
if (!val) return
Object.values(val).forEach(fn => fn())
}
})
document.addEventListener('pjax:send', () => {
// removeEventListener
btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange')
// reset readmode
const $bodyClassList = document.body.classList
if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode')
triggerPjaxFn(window.globalFn.pjaxSend)
})
document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || ""
Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value))
newScript.appendChild(document.createTextNode(content))
item.parentNode.replaceChild(newScript, item)
})
triggerPjaxFn(window.globalFn.pjaxComplete)
})
document.addEventListener('pjax:error', e => {
if (e.request.status === 404) {
pjax.loadUrl('!{url_for("/404.html")}')
}
})
})()

View File

@@ -0,0 +1,65 @@
- let { serverURL, 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 = () => {
umami.track(props => ({ ...props, url: window.location.pathname, title: GLOBAL_CONFIG_SITE.title }))
}
const loadUmamiJS = () => {
btf.getScript('!{baseURL}/script.js', {
'data-website-id': '!{website_id}',
'data-auto-track': 'false',
...option
}).then(runTrack)
}
const getData = async (isPost) => {
const now = Date.now()
const keyUrl = isPost ? `&url=${window.location.pathname}` : ''
const headerList = { 'Accept': 'application/json' }
if (!{isServerURL}) headerList['Authorization'] = `Bearer ${config.token}`
else headerList['x-umami-api-key'] = config.token
const res = await fetch(`!{apiUrl}/websites/!{website_id}/stats?startAt=0000000000&endAt=${now}${keyUrl}`, {
method: "GET",
headers: headerList
})
return await res.json()
}
const insertData = async () => {
try {
if (GLOBAL_CONFIG_SITE.isPost && config.page_pv) {
const pagePV = document.getElementById('umamiPV')
if (pagePV) {
const data = await getData(true)
pagePV.textContent = data.pageviews.value
}
} else {
const data = (config.site_uv || config.site_pv) && await getData()
if (config.site_uv) {
const siteUV = document.getElementById('umami-site-uv')
if (siteUV) siteUV.textContent = data.visitors.value
}
if (config.site_pv) {
const sitePV = document.getElementById('umami-site-pv')
if (sitePV) sitePV.textContent = data.pageviews.value
}
}
} catch (e) {
console.error('Failed to load Umami Analytics:', e)
}
}
btf.addGlobalFn('pjaxComplete', runTrack, 'umami_analytics_run_track')
btf.addGlobalFn('pjaxComplete', insertData, 'umami_analytics_insert')
loadUmamiJS()
insertData()
})()