mirror of
https://github.com/jerryc127/hexo-theme-butterfly.git
synced 2026-04-10 21:17:07 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f3ea55890 | ||
|
|
3d4bf30948 | ||
|
|
172a8ee846 | ||
|
|
5331f4ef9e | ||
|
|
0d0001c808 | ||
|
|
13db106172 | ||
|
|
f42048792e | ||
|
|
247c1b664d | ||
|
|
f7483d59b5 | ||
|
|
b7771e5938 | ||
|
|
74c555fb37 | ||
|
|
648ca6eb4f | ||
|
|
e5a52d5621 | ||
|
|
1045f66a51 | ||
|
|
5338a2be99 | ||
|
|
3ea138178d |
@@ -101,7 +101,7 @@ npm i hexo-theme-butterfly
|
||||
- [x] Chart.js
|
||||
- [x] Justified Gallery
|
||||
- [x] Lazyload images
|
||||
- [x] Instantpage/Pangu/Snackbar notification toast/PWA......
|
||||
- [x] Instantpage/Snackbar notification toast/PWA......
|
||||
|
||||
## ✨ Contributors
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ theme: butterfly
|
||||
- [x] Chart.js 圖表顯示
|
||||
- [x] 照片牆
|
||||
- [x] 圖片懶加載
|
||||
- [x] Instantpage/Pangu/Snackbar彈窗/PWA......
|
||||
- [x] Instantpage/Snackbar彈窗/PWA......
|
||||
|
||||
## ✨ 貢獻者
|
||||
|
||||
|
||||
12
_config.yml
12
_config.yml
@@ -983,13 +983,6 @@ snackbar:
|
||||
# https://instant.page/
|
||||
instantpage: false
|
||||
|
||||
# Pangu - Insert a space between Chinese character and English character
|
||||
# https://github.com/vinta/pangu.js
|
||||
pangu:
|
||||
enable: false
|
||||
# Specify the field to use pangu (site or post)
|
||||
field: site
|
||||
|
||||
# Lazyload
|
||||
# https://github.com/verlok/vanilla-lazyload
|
||||
lazyload:
|
||||
@@ -1023,6 +1016,10 @@ Open_Graph_meta:
|
||||
# fb_admins:
|
||||
# fb_app_id:
|
||||
|
||||
# Structured Data
|
||||
# https://developers.google.com/search/docs/guides/intro-structured-data
|
||||
structured_data: true
|
||||
|
||||
# Add the vendor prefixes to ensure compatibility
|
||||
css_prefix: true
|
||||
|
||||
@@ -1092,7 +1089,6 @@ CDN:
|
||||
# medium_zoom:
|
||||
# mermaid:
|
||||
# meting_js:
|
||||
# pangu:
|
||||
# prismjs_autoloader:
|
||||
# prismjs_js:
|
||||
# prismjs_lineNumber_js:
|
||||
|
||||
@@ -11,15 +11,12 @@ div
|
||||
if theme.instantpage
|
||||
script(src=url_for(theme.asset.instantpage), type='module')
|
||||
|
||||
if theme.lazyload.enable
|
||||
if theme.lazyload.enable && !theme.lazyload.native
|
||||
script(src=url_for(theme.asset.lazyload))
|
||||
|
||||
if theme.snackbar.enable
|
||||
script(src=url_for(theme.asset.snackbar))
|
||||
|
||||
if theme.pangu.enable
|
||||
!= partial("includes/third-party/pangu.pug", {}, { cache: true })
|
||||
|
||||
.js-pjax
|
||||
if needLoadCountJs
|
||||
!= partial("includes/third-party/card-post-count/index", {}, { cache: true })
|
||||
@@ -36,7 +33,7 @@ div
|
||||
!= partial("includes/third-party/prismjs", {}, { cache: true })
|
||||
|
||||
if theme.aside.enable && theme.aside.card_newest_comments.enable
|
||||
if theme.pjax.enable || (!is_post() && page.aside !== false)
|
||||
if theme.pjax.enable || (globalPageType !== 'post' && page.aside !== false)
|
||||
!= partial("includes/third-party/newest-comments/index", {}, { cache: true })
|
||||
|
||||
!= fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)})
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
- var pageTitle
|
||||
- is_archive() ? page.title = findArchivesTitle(page, theme.menu, date) : ''
|
||||
- if (is_tag()) pageTitle = _p('page.tag') + ': ' + page.tag
|
||||
- else if (is_category()) pageTitle = _p('page.category') + ': ' + page.category
|
||||
- else if (is_current('/404.html', [strict])) pageTitle = _p('error404')
|
||||
- else pageTitle = page.title || config.title || ''
|
||||
- globalPageType === 'archive' ? page.title = findArchivesTitle(page, theme.menu, date) : ''
|
||||
case globalPageType
|
||||
when 'tag'
|
||||
- pageTitle = _p('page.tag') + ': ' + page.tag
|
||||
when 'category'
|
||||
- pageTitle = _p('page.category') + ': ' + page.category
|
||||
when '404'
|
||||
- pageTitle = _p('error404')
|
||||
default
|
||||
- pageTitle = page.title || config.title || ''
|
||||
|
||||
|
||||
- var isSubtitle = config.subtitle ? ' - ' + config.subtitle : ''
|
||||
- var tabTitle = is_home() || !pageTitle ? config.title + isSubtitle : pageTitle + ' | ' + config.title
|
||||
- var tabTitle = globalPageType === 'home' || !pageTitle ? config.title + isSubtitle : pageTitle + ' | ' + config.title
|
||||
- var pageAuthor = config.email ? config.author + ',' + config.email : config.author
|
||||
- var pageCopyright = config.copyright || config.author
|
||||
- var themeColorLight = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_light || '#ffffff'
|
||||
@@ -25,6 +31,9 @@ meta(name="theme-color" content=themeColor)
|
||||
//- Open_Graph
|
||||
include ./head/Open_Graph.pug
|
||||
|
||||
//- Structured Data
|
||||
include ./head/structured_data.pug
|
||||
|
||||
!=favicon_tag(theme.favicon || config.favicon)
|
||||
link(rel="canonical" href=urlNoIndex(null,config.pretty_urls.trailing_index,config.pretty_urls.trailing_html))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ if theme.Open_Graph_meta.enable
|
||||
-
|
||||
const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img
|
||||
let ogOption = Object.assign({
|
||||
type: is_post() ? 'article' : 'website',
|
||||
type: globalPageType === 'post' ? 'article' : 'website',
|
||||
image: coverVal ? full_url_for(coverVal) : '',
|
||||
fb_admins: theme.facebook_comments.user_id || '',
|
||||
fb_app_id: theme.facebook_comments.app_id || '',
|
||||
|
||||
@@ -4,7 +4,7 @@ if theme.baidu_analytics
|
||||
(function() {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?!{theme.baidu_analytics}";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
btf.addGlobalFn('pjaxComplete', () => {
|
||||
|
||||
@@ -116,7 +116,7 @@ script.
|
||||
buttonText: '!{_p("load_more")}'
|
||||
},
|
||||
isPhotoFigcaption: !{theme.photofigcaption},
|
||||
islazyload: !{theme.lazyload.enable},
|
||||
islazyloadPlugin: !{theme.lazyload.enable && !theme.lazyload.native},
|
||||
isAnchor: !{theme.anchor.auto_update || false},
|
||||
percent: {
|
||||
toc: !{theme.toc.scroll_percent},
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
var showToc = false
|
||||
if (theme.aside.enable && page.aside !== false) {
|
||||
let tocEnable = false
|
||||
if (is_post() && theme.toc.post) tocEnable = true
|
||||
else if (is_page() && theme.toc.page) tocEnable = true
|
||||
if (globalPageType === 'post' && theme.toc.post) tocEnable = true
|
||||
else if (globalPageType === 'page' && theme.toc.page) tocEnable = true
|
||||
const pageToc = typeof page.toc === 'boolean' ? page.toc : tocEnable
|
||||
showToc = pageToc && (toc(page.content) !== '' || page.encrypt === true)
|
||||
}
|
||||
@@ -19,9 +19,7 @@
|
||||
script#config-diff.
|
||||
var GLOBAL_CONFIG_SITE = {
|
||||
title: '!{titleVal}',
|
||||
isPost: !{is_post()},
|
||||
isHome: !{is_home()},
|
||||
isHighlightShrink: !{isHighlightShrink},
|
||||
isToc: !{showToc},
|
||||
isShuoshuo: !{page.type == 'shuoshuo'}
|
||||
pageType: '!{page.type == 'shuoshuo' ? 'shuoshuo' : globalPageType}'
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
if internal_provider === third_party_provider && internal_provider !== 'local'
|
||||
link(rel="preconnect" href=providers[internal_provider])
|
||||
else
|
||||
else
|
||||
if internal_provider !== 'local'
|
||||
link(rel="preconnect" href=providers[internal_provider])
|
||||
if third_party_provider !== 'local'
|
||||
|
||||
34
layout/includes/head/structured_data.pug
Normal file
34
layout/includes/head/structured_data.pug
Normal file
@@ -0,0 +1,34 @@
|
||||
if theme.structured_data && page.layout === 'post'
|
||||
-
|
||||
// use json-ld to add structured data
|
||||
|
||||
const title = page.title
|
||||
const url = page.permalink
|
||||
const imageVal = page.cover_type === 'img' ? page.cover : theme.avatar.img
|
||||
const image = imageVal ? full_url_for(imageVal) : ''
|
||||
const datePublished = page.date.toISOString()
|
||||
const dateModified = (page.updated || page.date).toISOString()
|
||||
const author = page.copyright_author || config.author
|
||||
const authorHrefVal = page.copyright_author_href || theme.post_copyright.author_href || site.url;
|
||||
const authorHref = full_url_for(authorHrefVal);
|
||||
|
||||
const jsonLd = {
|
||||
"@context": "https://schema.org",
|
||||
"@type": "BlogPosting",
|
||||
"headline": title,
|
||||
"url": url,
|
||||
"image": image,
|
||||
"datePublished": datePublished,
|
||||
"dateModified": dateModified,
|
||||
"author": [{
|
||||
"@type": "Person",
|
||||
"name": author,
|
||||
"url": authorHref
|
||||
}]
|
||||
};
|
||||
|
||||
jsonLdScript = JSON.stringify(jsonLd, null, 2);
|
||||
-
|
||||
|
||||
script(type="application/ld+json").
|
||||
!{jsonLdScript}
|
||||
@@ -6,33 +6,32 @@
|
||||
var bg_img = ''
|
||||
|
||||
if !theme.disable_top_img && page.top_img !== false
|
||||
if is_post()
|
||||
- top_img = page.top_img || page.cover || theme.default_top_img
|
||||
else if is_page()
|
||||
- top_img = page.top_img || theme.default_top_img
|
||||
else if is_tag()
|
||||
- top_img = theme.tag_per_img && theme.tag_per_img[page.tag]
|
||||
- top_img = top_img || returnTopImg(theme.tag_img)
|
||||
else if is_category()
|
||||
- top_img = theme.category_per_img && theme.category_per_img[page.category]
|
||||
- top_img = top_img || returnTopImg(theme.category_img)
|
||||
else if is_home()
|
||||
- top_img = returnTopImg(theme.index_img)
|
||||
else if is_archive()
|
||||
- top_img = returnTopImg(theme.archive_img)
|
||||
else
|
||||
- top_img = page.top_img || theme.default_top_img
|
||||
case globalPageType
|
||||
when 'post'
|
||||
- top_img = page.top_img || page.cover || theme.default_top_img
|
||||
when 'page'
|
||||
- top_img = page.top_img || theme.default_top_img
|
||||
when 'tag'
|
||||
- top_img = theme.tag_per_img && theme.tag_per_img[page.tag] || returnTopImg(theme.tag_img)
|
||||
when 'category'
|
||||
- top_img = theme.category_per_img && theme.category_per_img[page.category] || returnTopImg(theme.category_img)
|
||||
when 'home'
|
||||
- top_img = returnTopImg(theme.index_img)
|
||||
when 'archive'
|
||||
- top_img = returnTopImg(theme.archive_img)
|
||||
default
|
||||
- top_img = page.top_img || theme.default_top_img
|
||||
|
||||
if top_img !== false
|
||||
- bg_img = getBgPath(top_img)
|
||||
- headerClassName = is_home() ? 'full_page' : is_post() ? 'post-bg' : 'not-home-page'
|
||||
- headerClassName = globalPageType === 'home' ? 'full_page' : globalPageType === 'post' ? 'post-bg' : 'not-home-page'
|
||||
|
||||
header#page-header(class=`${headerClassName + isFixedClass}` style=bg_img)
|
||||
include ./nav.pug
|
||||
if top_img !== false
|
||||
if is_post()
|
||||
if globalPageType === 'post'
|
||||
include ./post-info.pug
|
||||
else if is_home()
|
||||
else if globalPageType === 'home'
|
||||
#site-info
|
||||
h1#site-title=config.title
|
||||
if theme.subtitle.enable
|
||||
@@ -48,6 +47,6 @@ header#page-header(class=`${headerClassName + isFixedClass}` style=bg_img)
|
||||
#page-site-info
|
||||
h1#site-title=page.title || page.tag || page.category
|
||||
else
|
||||
//- improvement seo
|
||||
if !is_post()
|
||||
//- improve seo
|
||||
if globalPageType !== 'post'
|
||||
h1.title-seo=page.title || page.tag || page.category || config.title
|
||||
@@ -5,7 +5,7 @@ nav#nav
|
||||
img.site-icon(src=url_for(theme.nav.logo) alt='Logo')
|
||||
if theme.nav.display_title
|
||||
span.site-name=config.title
|
||||
if is_post()
|
||||
if globalPageType === 'post'
|
||||
a.nav-page-title(href=url_for('/'))
|
||||
span.site-name=(page.title || config.title)
|
||||
#menus
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
- var globalPageType = getPageType(page, is_home)
|
||||
- var htmlClassHideAside = theme.aside.enable && theme.aside.hide ? 'hide-aside' : ''
|
||||
- page.aside = is_archive() ? theme.aside.display.archive: is_category() ? theme.aside.display.category : is_tag() ? theme.aside.display.tag : page.aside
|
||||
- page.aside = globalPageType === 'archive' ? theme.aside.display.archive: globalPageType === 'category' ? theme.aside.display.category : globalPageType === 'tag' ? theme.aside.display.tag : page.aside
|
||||
- var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : ''
|
||||
- var pageType = is_post() ? 'post' : 'page'
|
||||
- var pageType = globalPageType === 'post' ? 'post' : 'page'
|
||||
- pageType = page.type ? pageType + ' type-' + page.type : pageType
|
||||
|
||||
doctype html
|
||||
@@ -13,7 +14,7 @@ html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside
|
||||
|
||||
if theme.background
|
||||
#web_bg(style=getBgPath(theme.background))
|
||||
|
||||
|
||||
!=partial('includes/sidebar', {}, {cache: true})
|
||||
|
||||
#body-wrap(class=pageType)
|
||||
|
||||
@@ -10,7 +10,7 @@ mixin indexPostUI()
|
||||
- const leftOrRight = indexLayout === 3 ? (index % 2 === 0 ? 'left' : 'right') : (indexLayout === 2 ? 'right' : '')
|
||||
- const post_cover = article.cover
|
||||
- const no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
|
||||
|
||||
|
||||
if post_cover && theme.cover.index_enable
|
||||
.post_cover(class=leftOrRight)
|
||||
a(href=url_for(link) title=title)
|
||||
@@ -20,7 +20,7 @@ mixin indexPostUI()
|
||||
div.post-bg(style=`background: ${post_cover}`)
|
||||
.recent-post-info(class=no_cover)
|
||||
a.article-title(href=url_for(link) title=title)
|
||||
if is_home() && (article.top || article.sticky > 0)
|
||||
if globalPageType === 'home' && (article.top || article.sticky > 0)
|
||||
i.fas.fa-thumbtack.sticky
|
||||
= title
|
||||
.article-meta-wrap
|
||||
@@ -58,7 +58,7 @@ mixin indexPostUI()
|
||||
a(href=url_for(item.path)).article-meta__tags #[=item.name]
|
||||
if index < article.tags.data.length - 1
|
||||
span.article-meta-link #[='•']
|
||||
|
||||
|
||||
mixin countBlockInIndex
|
||||
- needLoadCountJs = true
|
||||
span.article-meta
|
||||
@@ -67,7 +67,7 @@ mixin indexPostUI()
|
||||
if block
|
||||
block
|
||||
span.article-meta-label= ' ' + _p('card_post_count')
|
||||
|
||||
|
||||
if theme.comments.card_post_count && theme.comments.use
|
||||
case theme.comments.use[0]
|
||||
when 'Disqus'
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<div class="flink-item-icon">
|
||||
<img class="no-lightbox" src="${lists[j].avatar}" onerror='this.onerror=null;this.src="!{url_for(theme.error_img.flink)}"' alt="${lists[j].name}" />
|
||||
</div>
|
||||
<div class="flink-item-name">${lists[j].name}</div>
|
||||
<div class="flink-item-name">${lists[j].name}</div>
|
||||
<div class="flink-item-desc" title="${lists[j].descr}">${lists[j].descr}</div>
|
||||
</a>
|
||||
</div>`
|
||||
@@ -63,14 +63,14 @@
|
||||
- let listResult = ""
|
||||
|
||||
each j in i.link_list
|
||||
-
|
||||
-
|
||||
listResult += `
|
||||
<div class="flink-list-item">
|
||||
<a href="${j.link}" title="${j.name}" target="_blank">
|
||||
<div class="flink-item-icon">
|
||||
<img class="no-lightbox" src="${j.avatar}" onerror='this.onerror=null;this.src="${url_for(theme.error_img.flink)}"' alt="${j.name}" />
|
||||
</div>
|
||||
<div class="flink-item-name">${j.name}</div>
|
||||
<div class="flink-item-name">${j.name}</div>
|
||||
<div class="flink-item-desc" title="${j.descr}">${j.descr}</div>
|
||||
</a>
|
||||
</div>`
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
escape: false
|
||||
}
|
||||
|
||||
if is_post()
|
||||
if globalPageType === 'post'
|
||||
- let paginationOrder = theme.post_pagination === 1 ? { prev: page.prev, next: page.next } : { prev: page.next, next: page.prev }
|
||||
|
||||
nav#pagination.pagination-post
|
||||
@@ -15,13 +15,13 @@ if is_post()
|
||||
- const getPostDesc = direction.postDesc || postDesc(direction)
|
||||
- let className = key === 'prev' ? (paginationOrder.next ? '' : 'full-width') : (paginationOrder.prev ? '' : 'full-width')
|
||||
- className = getPostDesc ? className : className + ' no-desc'
|
||||
|
||||
|
||||
a.pagination-related(class=className href=url_for(direction.path) title=direction.title)
|
||||
if direction.cover_type === 'img'
|
||||
img.cover(src=url_for(direction.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt=`cover of ${key === 'prev' ? 'previous' : 'next'} post`)
|
||||
else
|
||||
.cover(style=`background: ${direction.cover || 'var(--default-bg-color)'}`)
|
||||
|
||||
|
||||
.info(class=key === 'prev' ? '' : 'text-right')
|
||||
.info-1
|
||||
.info-item-1=_p(`pagination.${key}`)
|
||||
@@ -32,6 +32,6 @@ if is_post()
|
||||
else
|
||||
nav#pagination
|
||||
.pagination
|
||||
if is_home()
|
||||
if globalPageType === 'home'
|
||||
- options.format = 'page/%d/#content-inner'
|
||||
!=paginator(options)
|
||||
@@ -3,7 +3,7 @@ mixin rightsideItem(array)
|
||||
each item in array
|
||||
case item
|
||||
when 'readmode'
|
||||
if is_post() && readmode
|
||||
if globalPageType === 'post' && readmode
|
||||
button#readmode(type="button" title=_p('rightside.readmode_title'))
|
||||
i.fas.fa-book-open
|
||||
when 'translate'
|
||||
@@ -23,7 +23,7 @@ mixin rightsideItem(array)
|
||||
i.fas.fa-list-ul
|
||||
when 'chat'
|
||||
if chat.rightside_button && chat.use
|
||||
button#chat-btn(type="button" title=_p("rightside.chat"))
|
||||
button#chat-btn(type="button" title=_p("rightside.chat") style="display:none")
|
||||
i.fas.fa-message
|
||||
when 'comment'
|
||||
if commentsJsLoad
|
||||
@@ -35,7 +35,7 @@ mixin rightsideItem(array)
|
||||
- const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode','hideAside']
|
||||
- const showArray = enable ? show && show.split(',') : ['toc','chat','comment']
|
||||
|
||||
|
||||
|
||||
#rightside-config-hide
|
||||
if hideArray
|
||||
+rightsideItem(hideArray)
|
||||
@@ -45,7 +45,7 @@ mixin rightsideItem(array)
|
||||
button#rightside-config(type="button" title=_p("rightside.setting"))
|
||||
i.fas.fa-cog.fa-spin
|
||||
else
|
||||
if is_post()
|
||||
if globalPageType === 'post'
|
||||
if (readmode || translate.enable || (darkmode.enable && darkmode.button))
|
||||
button#rightside-config(type="button" title=_p("rightside.setting"))
|
||||
i.fas.fa-cog.fa-spin
|
||||
|
||||
@@ -3,16 +3,16 @@ if theme.menu
|
||||
#menu-mask
|
||||
#sidebar-menus
|
||||
.avatar-img.text-center
|
||||
img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar")
|
||||
img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.flink)}'` alt="avatar")
|
||||
.site-data.text-center
|
||||
a(href=url_for(config.archive_dir) + '/')
|
||||
a(href=`${url_for(config.archive_dir)}/`)
|
||||
.headline= _p('aside.articles')
|
||||
.length-num= site.posts.length
|
||||
a(href=url_for(config.tag_dir) + '/' )
|
||||
a(href=`${url_for(config.tag_dir)}/`)
|
||||
.headline= _p('aside.tags')
|
||||
.length-num= site.tags.length
|
||||
a(href=url_for(config.category_dir) + '/')
|
||||
.headline= _p('aside.categories')
|
||||
a(href=`${url_for(config.category_dir)}/`)
|
||||
.headline= _p('aside.categories')
|
||||
.length-num= site.categories.length
|
||||
|
||||
!=partial('includes/header/menu_item', {}, {cache: true})
|
||||
!= partial('includes/header/menu_item', {}, { cache: true })
|
||||
5
layout/includes/third-party/abcjs/index.pug
vendored
5
layout/includes/third-party/abcjs/index.pug
vendored
@@ -1,6 +1,3 @@
|
||||
if theme.abcjs.enable
|
||||
if theme.abcjs.per_page
|
||||
if is_post() || is_page()
|
||||
include ./abcjs.pug
|
||||
else if page.abcjs
|
||||
if theme.abcjs.per_page && (['post','page'].includes(globalPageType)) || page.abcjs
|
||||
include ./abcjs.pug
|
||||
|
||||
62
layout/includes/third-party/chat/chatra.pug
vendored
62
layout/includes/third-party/chat/chatra.pug
vendored
@@ -1,42 +1,38 @@
|
||||
//- https://chatra.io/help/api/
|
||||
script.
|
||||
(() => {
|
||||
const isChatBtn = !{theme.chat.rightside_button}
|
||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||
|
||||
if (isChatBtn) {
|
||||
const close = () => {
|
||||
Chatra('minimizeWidget')
|
||||
Chatra('hide')
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
Chatra('openChat', true)
|
||||
Chatra('show')
|
||||
}
|
||||
|
||||
window.ChatraSetup = { startHidden: true }
|
||||
|
||||
window.chatBtnFn = () => {
|
||||
document.getElementById('chatra').classList.contains('chatra--expanded') ? close() : open()
|
||||
}
|
||||
} else if (isChatHideShow) {
|
||||
window.chatBtn = {
|
||||
hide: () => Chatra('hide'),
|
||||
show: () => Chatra('show')
|
||||
}
|
||||
window.ChatraID = '#{theme.chatra.id}'
|
||||
window.Chatra = window.Chatra || function() {
|
||||
(window.Chatra.q = window.Chatra.q || []).push(arguments)
|
||||
}
|
||||
|
||||
(function(d, w, c) {
|
||||
w.ChatraID = '#{theme.chatra.id}'
|
||||
var s = d.createElement('script')
|
||||
w[c] = w[c] || function() {
|
||||
(w[c].q = w[c].q || []).push(arguments)
|
||||
btf.getScript('https://call.chatra.io/chatra.js').then(() => {
|
||||
const isChatBtn = !{theme.chat.rightside_button}
|
||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||
|
||||
if (isChatBtn) {
|
||||
const close = () => {
|
||||
Chatra('minimizeWidget')
|
||||
Chatra('hide')
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
Chatra('openChat', true)
|
||||
Chatra('show')
|
||||
}
|
||||
|
||||
window.ChatraSetup = { startHidden: true }
|
||||
|
||||
window.chatBtnFn = () => document.getElementById('chatra').classList.contains('chatra--expanded') ? close() : open()
|
||||
|
||||
document.getElementById('chat-btn').style.display = 'block'
|
||||
} else if (isChatHideShow) {
|
||||
window.chatBtn = {
|
||||
hide: () => Chatra('hide'),
|
||||
show: () => Chatra('show')
|
||||
}
|
||||
}
|
||||
s.async = true
|
||||
s.src = 'https://call.chatra.io/chatra.js'
|
||||
if (d.head) d.head.appendChild(s)
|
||||
})(document, window, 'Chatra')
|
||||
})
|
||||
})()
|
||||
|
||||
|
||||
|
||||
57
layout/includes/third-party/chat/crisp.pug
vendored
57
layout/includes/third-party/chat/crisp.pug
vendored
@@ -1,37 +1,32 @@
|
||||
script.
|
||||
(() => {
|
||||
window.$crisp = [];
|
||||
window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}";
|
||||
(function () {
|
||||
d = document;
|
||||
s = d.createElement("script");
|
||||
s.src = "https://client.crisp.chat/l.js";
|
||||
s.async = 1;
|
||||
d.getElementsByTagName("head")[0].appendChild(s);
|
||||
})();
|
||||
$crisp.push(["safe", true])
|
||||
window.$crisp = ['safe', true]
|
||||
window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}"
|
||||
|
||||
const isChatBtn = !{theme.chat.rightside_button}
|
||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||
btf.getScript('https://client.crisp.chat/l.js').then(() => {
|
||||
const isChatBtn = !{theme.chat.rightside_button}
|
||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||
|
||||
if (isChatBtn) {
|
||||
const open = () => {
|
||||
$crisp.push(["do", "chat:show"])
|
||||
$crisp.push(["do", "chat:open"])
|
||||
if (isChatBtn) {
|
||||
const open = () => {
|
||||
$crisp.push(["do", "chat:show"])
|
||||
$crisp.push(["do", "chat:open"])
|
||||
}
|
||||
|
||||
const close = () => $crisp.push(["do", "chat:hide"])
|
||||
|
||||
close()
|
||||
|
||||
$crisp.push(["on", "chat:closed", close])
|
||||
|
||||
window.chatBtnFn = () => $crisp.is("chat:visible") ? close() : open()
|
||||
|
||||
document.getElementById('chat-btn').style.display = 'block'
|
||||
} else if (isChatHideShow) {
|
||||
window.chatBtn = {
|
||||
hide: () => $crisp.push(["do", "chat:hide"]),
|
||||
show: () => $crisp.push(["do", "chat:show"])
|
||||
}
|
||||
}
|
||||
|
||||
const close = () => $crisp.push(["do", "chat:hide"])
|
||||
|
||||
close()
|
||||
|
||||
$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"])
|
||||
}
|
||||
}
|
||||
})
|
||||
})()
|
||||
70
layout/includes/third-party/chat/tidio.pug
vendored
70
layout/includes/third-party/chat/tidio.pug
vendored
@@ -1,41 +1,45 @@
|
||||
script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async)
|
||||
script.
|
||||
(() => {
|
||||
const isChatBtn = !{theme.chat.rightside_button}
|
||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||
btf.getScript('//code.tidio.co/!{theme.tidio.public_key}.js').then(() => {
|
||||
const isChatBtn = !{theme.chat.rightside_button}
|
||||
const isChatHideShow = !{theme.chat.button_hide_show}
|
||||
|
||||
if (isChatBtn) {
|
||||
let isShow = false
|
||||
const close = () => {
|
||||
window.tidioChatApi.hide()
|
||||
isShow = false
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
window.tidioChatApi.open()
|
||||
window.tidioChatApi.show()
|
||||
isShow = true
|
||||
}
|
||||
if (isChatBtn) {
|
||||
let isShow = false
|
||||
const close = () => {
|
||||
window.tidioChatApi.hide()
|
||||
isShow = false
|
||||
}
|
||||
|
||||
const open = () => {
|
||||
window.tidioChatApi.open()
|
||||
window.tidioChatApi.show()
|
||||
isShow = true
|
||||
}
|
||||
|
||||
const onTidioChatApiReady = () => {
|
||||
window.tidioChatApi.hide()
|
||||
window.tidioChatApi.on("close", close)
|
||||
}
|
||||
if (window.tidioChatApi) {
|
||||
window.tidioChatApi.on("ready", onTidioChatApiReady)
|
||||
} else {
|
||||
document.addEventListener("tidioChat-ready", onTidioChatApiReady)
|
||||
}
|
||||
const onTidioChatApiReady = () => {
|
||||
window.tidioChatApi.hide()
|
||||
window.tidioChatApi.on("close", close)
|
||||
}
|
||||
if (window.tidioChatApi) {
|
||||
window.tidioChatApi.on("ready", onTidioChatApiReady)
|
||||
} else {
|
||||
document.addEventListener("tidioChat-ready", onTidioChatApiReady)
|
||||
}
|
||||
|
||||
window.chatBtnFn = () => {
|
||||
if (!window.tidioChatApi) return
|
||||
isShow ? close() : open()
|
||||
window.chatBtnFn = () => {
|
||||
if (!window.tidioChatApi) return
|
||||
isShow ? close() : open()
|
||||
}
|
||||
|
||||
document.getElementById('chat-btn').style.display = 'block'
|
||||
|
||||
} else if (isChatHideShow) {
|
||||
window.chatBtn = {
|
||||
hide: () => window.tidioChatApi && window.tidioChatApi.hide(),
|
||||
show: () => window.tidioChatApi && window.tidioChatApi.show()
|
||||
}
|
||||
}
|
||||
} else if (isChatHideShow) {
|
||||
window.chatBtn = {
|
||||
hide: () => window.tidioChatApi && window.tidioChatApi.hide(),
|
||||
show: () => window.tidioChatApi && window.tidioChatApi.show()
|
||||
}
|
||||
}
|
||||
})
|
||||
})()
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ script.
|
||||
(() => {
|
||||
let artalkItem = null
|
||||
const option = !{JSON.stringify(option)}
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
|
||||
const destroyArtalk = () => {
|
||||
if (artalkItem) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
|
||||
const disqusReset = conf => {
|
||||
window.DISQUS && window.DISQUS.reset({
|
||||
@@ -72,7 +72,7 @@ script.
|
||||
if (!{lazyload}) btf.loadComment(document.getElementById('disqus_thread'), loadDisqus)
|
||||
else {
|
||||
loadDisqus()
|
||||
!{ count ? 'GLOBAL_CONFIG_SITE.isPost && getCount()' : '' }
|
||||
!{ count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : '' }
|
||||
}
|
||||
} else {
|
||||
window.loadOtherComment = loadDisqus
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'== 'shuoshuo'
|
||||
const dqOption = !{JSON.stringify(dqOption)}
|
||||
|
||||
const destroyDisqusjs = () => {
|
||||
@@ -79,7 +79,7 @@ script.
|
||||
if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqusjs-wrap'), loadDisqusjs)
|
||||
else {
|
||||
loadDisqusjs()
|
||||
!{ theme.comments.count ? 'GLOBAL_CONFIG_SITE.isPost && getCount()' : '' }
|
||||
!{ theme.comments.count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : '' }
|
||||
}
|
||||
} else {
|
||||
window.loadOtherComment = loadDisqusjs
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
script.
|
||||
(()=>{
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'== 'shuoshuo'
|
||||
|
||||
const loadFBComment = (el = document, path) => {
|
||||
if (isShuoshuo) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
|
||||
const getGiscusTheme = theme => theme === 'dark' ? '!{dark_theme}' : '!{light_theme}'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
|
||||
const commentCount = n => {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
|
||||
const loadLivere = (el, path) => {
|
||||
window.livereOptions = {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
|
||||
const loadScript = src => {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
|
||||
const getCount = () => {
|
||||
@@ -33,7 +33,7 @@ script.
|
||||
path: isShuoshuo ? path : (option && option.path) || path
|
||||
})
|
||||
|
||||
!{count ? 'GLOBAL_CONFIG_SITE.isPost && getCount()' : ''}
|
||||
!{count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : ''}
|
||||
|
||||
isShuoshuo && (window.shuoshuoComment.destroyTwikoo = () => {
|
||||
if (el.children.length) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
const getUtterancesTheme = theme => theme === 'dark' ? '#{dark_theme}' : '#{light_theme}'
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ if site.data.valine
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
|
||||
const initValine = (el, path) => {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
script.
|
||||
(() => {
|
||||
let initFn = window.walineFn || null
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.isShuoshuo
|
||||
const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'
|
||||
const option = !{JSON.stringify(option)}
|
||||
|
||||
const destroyWaline = ele => ele.destroy()
|
||||
|
||||
18
layout/includes/third-party/math/chartjs.pug
vendored
18
layout/includes/third-party/math/chartjs.pug
vendored
@@ -2,9 +2,6 @@
|
||||
|
||||
script.
|
||||
(() => {
|
||||
const $chartjs = document.querySelectorAll('#article-container .chartjs-container')
|
||||
if ($chartjs.length === 0) return
|
||||
|
||||
const applyThemeDefaultsConfig = theme => {
|
||||
if (theme === 'dark-mode') {
|
||||
Chart.defaults.color = "!{fontColor.dark}"
|
||||
@@ -20,7 +17,7 @@ script.
|
||||
// Recursively traverse the config object and automatically apply theme-specific color schemes
|
||||
const applyThemeConfig = (obj, theme) => {
|
||||
if (typeof obj !== 'object' || obj === null) return
|
||||
|
||||
|
||||
Object.keys(obj).forEach(key => {
|
||||
const value = obj[key]
|
||||
// If the property is an object and has theme-specific options, apply them
|
||||
@@ -35,10 +32,10 @@ script.
|
||||
})
|
||||
}
|
||||
|
||||
const runChartJS = () => {
|
||||
const runChartJS = ele => {
|
||||
window.loadChartJS = true
|
||||
|
||||
Array.from($chartjs).forEach((item, index) => {
|
||||
Array.from(ele).forEach((item, index) => {
|
||||
const chartSrc = item.firstElementChild
|
||||
const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID
|
||||
const width = item.getAttribute('data-width')
|
||||
@@ -80,12 +77,15 @@ script.
|
||||
}
|
||||
|
||||
const loadChartJS = () => {
|
||||
window.loadChartJS ? runChartJS() : btf.getScript('!{url_for(theme.asset.chartjs)}').then(runChartJS)
|
||||
const chartJSEle = document.querySelectorAll('#article-container .chartjs-container')
|
||||
if (chartJSEle.length === 0) return
|
||||
|
||||
window.loadChartJS ? runChartJS(chartJSEle) : btf.getScript('!{url_for(theme.asset.chartjs)}').then(() => runChartJS(chartJSEle))
|
||||
}
|
||||
|
||||
// Listen for theme change events
|
||||
btf.addGlobalFn('themeChange', runChartJS, 'chartjs')
|
||||
btf.addGlobalFn('encrypt', runChartJS, 'chartjs')
|
||||
btf.addGlobalFn('themeChange', loadChartJS, 'chartjs')
|
||||
btf.addGlobalFn('encrypt', loadChartJS, 'chartjs')
|
||||
|
||||
window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS)
|
||||
})()
|
||||
|
||||
4
layout/includes/third-party/math/index.pug
vendored
4
layout/includes/third-party/math/index.pug
vendored
@@ -1,10 +1,10 @@
|
||||
case theme.math.use
|
||||
when 'mathjax'
|
||||
if (theme.math.per_page && (is_post() || is_page())) || page.mathjax
|
||||
if (theme.math.per_page && (['post','page'].includes(globalPageType))) || page.mathjax
|
||||
include ./mathjax.pug
|
||||
|
||||
when 'katex'
|
||||
if (theme.math.per_page && (is_post() || is_page())) || page.katex
|
||||
if (theme.math.per_page && (['post','page'].includes(globalPageType))) || page.katex
|
||||
include ./katex.pug
|
||||
|
||||
if theme.mermaid.enable
|
||||
|
||||
2
layout/includes/third-party/math/mathjax.pug
vendored
2
layout/includes/third-party/math/mathjax.pug
vendored
@@ -29,7 +29,7 @@ script.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const script = document.createElement('script')
|
||||
script.src = '!{url_for(theme.asset.mathjax)}'
|
||||
script.id = 'MathJax-script'
|
||||
|
||||
@@ -18,7 +18,7 @@ script.
|
||||
if (predefinedAvatarCdn && predefinedAvatarDefault) {
|
||||
return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) }
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
const res = await fetch('!{server}/api/v2/conf')
|
||||
const result = await res.json()
|
||||
@@ -34,7 +34,7 @@ script.
|
||||
|
||||
const searchParams = new URLSearchParams({
|
||||
'site_name': '!{site}',
|
||||
'limit': '!{theme.aside.card_newest_comments.limit}',
|
||||
'limit': '!{newestCommentsLimit * 2}', // Fetch more comments to filter pending comments
|
||||
})
|
||||
|
||||
const getComment = async (ele) => {
|
||||
@@ -42,16 +42,19 @@ script.
|
||||
const res = await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`)
|
||||
const result = await res.json()
|
||||
const { avatarCdn, avatarDefault } = await getAvatarValue()
|
||||
const artalk = result.data.map(e => {
|
||||
const avatar = avatarCdn && e.email_encrypted ? `${avatarCdn}${e.email_encrypted}?${avatarDefault}` : ''
|
||||
return {
|
||||
'avatar': avatar,
|
||||
'content': changeContent(e.content_marked),
|
||||
'nick': e.nick,
|
||||
'url': e.page_url,
|
||||
'date': e.date,
|
||||
}
|
||||
})
|
||||
const artalk = result.data
|
||||
.filter(e => !e.is_pending) // Filter pending comments
|
||||
.slice(0, !{newestCommentsLimit}) // Limit the number of comments
|
||||
.map(e => {
|
||||
const avatar = avatarCdn && e.email_encrypted ? `${avatarCdn}${e.email_encrypted}?${avatarDefault}` : ''
|
||||
return {
|
||||
'avatar': avatar,
|
||||
'content': changeContent(e.content_marked),
|
||||
'nick': e.nick,
|
||||
'url': e.page_url,
|
||||
'date': e.date,
|
||||
}
|
||||
})
|
||||
btf.saveToLocal.set(keyName, JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24))
|
||||
generateHtml(artalk, ele)
|
||||
} catch (e) {
|
||||
|
||||
@@ -6,7 +6,7 @@ script.
|
||||
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(/<code>.*?<\/code>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
|
||||
content = content.replace(/<[^>]+>/g, "") // remove html tag
|
||||
|
||||
if (content.length > 150) {
|
||||
@@ -23,8 +23,9 @@ script.
|
||||
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>`
|
||||
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">
|
||||
|
||||
@@ -6,7 +6,7 @@ script.
|
||||
const { changeContent, generateHtml, run } = window.newestComments
|
||||
|
||||
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}')
|
||||
fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{newestCommentsLimit}&api_key=!{apiKey}')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const disqusArray = data.response.map(item => {
|
||||
|
||||
@@ -32,7 +32,7 @@ script.
|
||||
}
|
||||
|
||||
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',{
|
||||
fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{newestCommentsLimit}&page=1',{
|
||||
"headers": {
|
||||
Accept: 'application/vnd.github.v3.html+json'
|
||||
}
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
- let { use } = theme.comments
|
||||
|
||||
if use
|
||||
- let forum,apiKey,userRepo
|
||||
-
|
||||
let forum,apiKey,userRepo
|
||||
let { limit:newestCommentsLimit } = theme.aside.card_newest_comments
|
||||
if (newestCommentsLimit > 10 || newestCommentsLimit < 1) newestCommentsLimit = 6
|
||||
|
||||
case use[0]
|
||||
when 'Valine'
|
||||
include ./valine.pug
|
||||
|
||||
@@ -7,7 +7,7 @@ script.
|
||||
const { changeContent, generateHtml, run } = window.newestComments
|
||||
|
||||
const getComment = ele => {
|
||||
fetch('!{host}/api/v1/last/!{theme.aside.card_newest_comments.limit}?site=!{siteId}')
|
||||
fetch('!{host}/api/v1/last/!{newestCommentsLimit}?site=!{siteId}')
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const remark42 = data.map(e => {
|
||||
|
||||
@@ -10,7 +10,7 @@ script.
|
||||
twikoo.getRecentComments({
|
||||
envId: '!{theme.twikoo.envId}',
|
||||
region: '!{theme.twikoo.region}',
|
||||
pageSize: !{theme.aside.card_newest_comments.limit},
|
||||
pageSize: !{newestCommentsLimit},
|
||||
includeReply: true
|
||||
}).then(res => {
|
||||
const twikooArray = res.map(e => {
|
||||
|
||||
@@ -27,7 +27,7 @@ script.
|
||||
},
|
||||
}
|
||||
|
||||
fetch(`${serverURL}/1.1/classes/Comment?limit=!{theme.aside.card_newest_comments.limit}&order=-createdAt`,settings)
|
||||
fetch(`${serverURL}/1.1/classes/Comment?limit=!{newestCommentsLimit}&order=-createdAt`,settings)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
const valineArray = data.results.map(e => {
|
||||
|
||||
@@ -9,7 +9,7 @@ script.
|
||||
|
||||
const getComment = async (ele) => {
|
||||
try {
|
||||
const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{theme.aside.card_newest_comments.limit}', { method: 'GET' })
|
||||
const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{newestCommentsLimit}')
|
||||
const result = await res.json()
|
||||
const walineArray = result.data.map(e => {
|
||||
return {
|
||||
|
||||
23
layout/includes/third-party/pangu.pug
vendored
23
layout/includes/third-party/pangu.pug
vendored
@@ -1,23 +0,0 @@
|
||||
script.
|
||||
(() => {
|
||||
const panguFn = () => {
|
||||
if (typeof pangu === 'object') pangu.autoSpacingPage()
|
||||
else {
|
||||
btf.getScript('!{url_for(theme.asset.pangu)}')
|
||||
.then(() => {
|
||||
pangu.autoSpacingPage()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const panguInit = () => {
|
||||
if (!{theme.pangu.field === 'post'}){
|
||||
GLOBAL_CONFIG_SITE.isPost && panguFn()
|
||||
} else {
|
||||
panguFn()
|
||||
}
|
||||
}
|
||||
|
||||
btf.addGlobalFn('pjaxComplete', panguInit, 'pangu')
|
||||
document.addEventListener('DOMContentLoaded', panguInit)
|
||||
})()
|
||||
@@ -14,7 +14,7 @@
|
||||
#algolia-info
|
||||
.algolia-stats
|
||||
.algolia-poweredBy
|
||||
|
||||
|
||||
#search-mask
|
||||
|
||||
script(src=url_for(theme.asset.algolia_search))
|
||||
|
||||
@@ -35,7 +35,7 @@ script.
|
||||
|
||||
const insertData = async () => {
|
||||
try {
|
||||
if (GLOBAL_CONFIG_SITE.isPost && config.page_pv) {
|
||||
if (GLOBAL_CONFIG_SITE.pageType === 'post' && config.page_pv) {
|
||||
const pagePV = document.getElementById('umamiPV')
|
||||
if (pagePV) {
|
||||
const data = await getData(true)
|
||||
|
||||
@@ -13,14 +13,14 @@ if theme.aside.card_author.enable
|
||||
.headline= _p('aside.tags')
|
||||
.length-num= site.tags.length
|
||||
a(href=url_for(config.category_dir) + '/')
|
||||
.headline= _p('aside.categories')
|
||||
.headline= _p('aside.categories')
|
||||
.length-num= site.categories.length
|
||||
|
||||
if theme.aside.card_author.button.enable
|
||||
a#card-info-btn(href=theme.aside.card_author.button.link)
|
||||
i(class=theme.aside.card_author.button.icon)
|
||||
span=theme.aside.card_author.button.text
|
||||
|
||||
|
||||
if(theme.social)
|
||||
.card-info-social-icons
|
||||
!=partial('includes/header/social', {}, {cache: true})
|
||||
|
||||
@@ -10,6 +10,5 @@
|
||||
|
||||
if (page.encrypt == true)
|
||||
.toc-content.toc-div-class(class=tocExpandClass style="display:none")!=toc(page.origin, {list_number: tocNumber})
|
||||
else
|
||||
else
|
||||
.toc-content(class=tocExpandClass)!=toc(page.content, {list_number: tocNumber})
|
||||
|
||||
@@ -6,40 +6,39 @@ if theme.aside.card_webinfo.enable
|
||||
.webinfo
|
||||
if theme.aside.card_webinfo.post_count
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.article_name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.article_name')} :`
|
||||
.item-count= site.posts.length
|
||||
if theme.aside.card_webinfo.runtime_date
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.runtime.name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.runtime.name')} :`
|
||||
.item-count#runtimeshow(data-publishDate=date_xml(theme.aside.card_webinfo.runtime_date))
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
if theme.wordcount.enable && theme.wordcount.total_wordcount
|
||||
.webinfo-item
|
||||
.item-name=_p('aside.card_webinfo.site_wordcount') + " :"
|
||||
.item-count=totalcount(site)
|
||||
.item-name= `${_p('aside.card_webinfo.site_wordcount')} :`
|
||||
.item-count= totalcount(site)
|
||||
if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.site_uv
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.site_uv_name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.site_uv_name')} :`
|
||||
.item-count#umami-site-uv
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
else if theme.busuanzi.site_uv
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.site_uv_name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.site_uv_name')} :`
|
||||
.item-count#busuanzi_value_site_uv
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.site_pv
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.site_pv_name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.site_pv_name')} :`
|
||||
.item-count#umami-site-pv
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
else if theme.busuanzi.site_pv
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.site_pv_name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.site_pv_name')} :`
|
||||
.item-count#busuanzi_value_site_pv
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
if theme.aside.card_webinfo.last_push_date
|
||||
.webinfo-item
|
||||
.item-name= _p('aside.card_webinfo.last_push_date.name') + " :"
|
||||
.item-name= `${_p('aside.card_webinfo.last_push_date.name')} :`
|
||||
.item-count#last-push-date(data-lastPushDate=date_xml(Date.now()))
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
|
||||
i.fa-solid.fa-spinner.fa-spin
|
||||
@@ -1,6 +1,6 @@
|
||||
#aside-content.aside-content
|
||||
//- post
|
||||
if is_post()
|
||||
if globalPageType === 'post'
|
||||
- const tocStyle = page.toc_style_simple
|
||||
- const tocStyleVal = tocStyle === true || tocStyle === false ? tocStyle : theme.toc.style_simple
|
||||
if showToc && tocStyleVal
|
||||
|
||||
@@ -2,7 +2,7 @@ extends includes/layout.pug
|
||||
|
||||
block content
|
||||
- const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : ''
|
||||
- var commentsJsLoad = false
|
||||
- var commentsJsLoad = false
|
||||
|
||||
mixin commentLoad
|
||||
if page.comments !== false && theme.comments.use
|
||||
|
||||
@@ -6,7 +6,7 @@ block content
|
||||
include includes/header/post-info.pug
|
||||
|
||||
article#article-container.container.post-content
|
||||
if theme.noticeOutdate.enable && page.noticeOutdate !== false
|
||||
if theme.noticeOutdate.enable && page.noticeOutdate !== false
|
||||
include includes/post/outdate-notice.pug
|
||||
else
|
||||
!=page.content
|
||||
@@ -17,7 +17,7 @@ block content
|
||||
each item, index in page.tags.data
|
||||
a(href=url_for(item.path)).post-meta__tags #[=item.name]
|
||||
include includes/third-party/share/index.pug
|
||||
|
||||
|
||||
if theme.reward.enable && theme.reward.QR_code
|
||||
!=partial('includes/post/reward', {}, {cache: true})
|
||||
|
||||
@@ -33,4 +33,3 @@ block content
|
||||
if page.comments !== false && theme.comments.use
|
||||
- var commentsJsLoad = true
|
||||
!=partial('includes/third-party/comments/index', {}, {cache: true})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hexo-theme-butterfly",
|
||||
"version": "5.2.2",
|
||||
"version": "5.3.2",
|
||||
"description": "A Simple and Card UI Design theme for Hexo",
|
||||
"main": "package.json",
|
||||
"scripts": {
|
||||
|
||||
30
plugins.yml
30
plugins.yml
@@ -9,7 +9,7 @@ activate_power_mode:
|
||||
algolia_search:
|
||||
name: algoliasearch
|
||||
file: dist/lite/builds/browser.umd.js
|
||||
version: 5.12.0
|
||||
version: 5.19.0
|
||||
aplayer_css:
|
||||
name: aplayer
|
||||
file: dist/APlayer.min.css
|
||||
@@ -45,7 +45,7 @@ canvas_ribbon:
|
||||
chartjs:
|
||||
name: chart.js
|
||||
file: dist/chart.umd.js
|
||||
version: 4.4.6
|
||||
version: 4.4.7
|
||||
clickShowText:
|
||||
name: butterfly-extsrc
|
||||
file: dist/click-show-text.min.js
|
||||
@@ -66,12 +66,12 @@ docsearch_css:
|
||||
name: '@docsearch/css'
|
||||
other_name: docsearch-css
|
||||
file: dist/style.css
|
||||
version: 3.6.3
|
||||
version: 3.8.2
|
||||
docsearch_js:
|
||||
name: '@docsearch/js'
|
||||
other_name: docsearch-js
|
||||
file: dist/umd/index.js
|
||||
version: 3.6.3
|
||||
version: 3.8.2
|
||||
egjs_infinitegrid:
|
||||
name: '@egjs/infinitegrid'
|
||||
other_name: egjs-infinitegrid
|
||||
@@ -95,7 +95,7 @@ fontawesome:
|
||||
name: '@fortawesome/fontawesome-free'
|
||||
file: css/all.min.css
|
||||
other_name: font-awesome
|
||||
version: 6.6.0
|
||||
version: 6.7.2
|
||||
gitalk:
|
||||
name: gitalk
|
||||
file: dist/gitalk.min.js
|
||||
@@ -111,17 +111,17 @@ instantpage:
|
||||
instantsearch:
|
||||
name: instantsearch.js
|
||||
file: dist/instantsearch.production.min.js
|
||||
version: 4.75.3
|
||||
version: 4.75.7
|
||||
katex:
|
||||
name: katex
|
||||
file: dist/katex.min.css
|
||||
other_name: KaTeX
|
||||
version: 0.16.11
|
||||
version: 0.16.19
|
||||
katex_copytex:
|
||||
name: katex
|
||||
file: dist/contrib/copy-tex.min.js
|
||||
other_name: KaTeX
|
||||
version: 0.16.11
|
||||
version: 0.16.19
|
||||
lazyload:
|
||||
name: vanilla-lazyload
|
||||
file: dist/lazyload.iife.min.js
|
||||
@@ -137,7 +137,7 @@ medium_zoom:
|
||||
mermaid:
|
||||
name: mermaid
|
||||
file: dist/mermaid.min.js
|
||||
version: 11.4.0
|
||||
version: 11.4.1
|
||||
meting_js:
|
||||
name: butterfly-extsrc
|
||||
file: metingjs/dist/Meting.min.js
|
||||
@@ -152,10 +152,6 @@ pace_js:
|
||||
other_name: pace
|
||||
file: pace.min.js
|
||||
version: 1.2.4
|
||||
pangu:
|
||||
name: pangu
|
||||
file: dist/browser/pangu.min.js
|
||||
version: 4.0.7
|
||||
pjax:
|
||||
name: pjax
|
||||
file: pjax.min.js
|
||||
@@ -194,7 +190,7 @@ snackbar_css:
|
||||
twikoo:
|
||||
name: twikoo
|
||||
file: dist/twikoo.all.min.js
|
||||
version: 1.6.39
|
||||
version: 1.6.41
|
||||
typed:
|
||||
name: typed.js
|
||||
file: dist/typed.umd.js
|
||||
@@ -202,14 +198,14 @@ typed:
|
||||
valine:
|
||||
name: valine
|
||||
file: dist/Valine.min.js
|
||||
version: 1.5.2
|
||||
version: 1.5.3
|
||||
waline_css:
|
||||
name: '@waline/client'
|
||||
file: dist/waline.css
|
||||
other_name: waline
|
||||
version: 3.3.2
|
||||
version: 3.4.3
|
||||
waline_js:
|
||||
name: '@waline/client'
|
||||
file: dist/waline.js
|
||||
other_name: waline
|
||||
version: 3.3.2
|
||||
version: 3.4.3
|
||||
|
||||
@@ -545,12 +545,9 @@ hexo.extend.filter.register('before_generate', () => {
|
||||
bg_dark: '#1f1f1f'
|
||||
},
|
||||
instantpage: false,
|
||||
pangu: {
|
||||
enable: false,
|
||||
field: 'site'
|
||||
},
|
||||
lazyload: {
|
||||
enable: false,
|
||||
native: false,
|
||||
field: 'site',
|
||||
placeholder: null,
|
||||
blur: false
|
||||
@@ -567,6 +564,7 @@ hexo.extend.filter.register('before_generate', () => {
|
||||
enable: true,
|
||||
option: null
|
||||
},
|
||||
structured_data: true,
|
||||
css_prefix: true,
|
||||
inject: {
|
||||
head: null,
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
const urlFor = require('hexo-util').url_for.bind(hexo)
|
||||
|
||||
const lazyload = htmlContent => {
|
||||
if (hexo.theme.config.lazyload.native) {
|
||||
return htmlContent.replace(/(<img.*?)(>)/ig, '$1 loading=\'lazy\'$2')
|
||||
}
|
||||
|
||||
const bg = hexo.theme.config.lazyload.placeholder ? urlFor(hexo.theme.config.lazyload.placeholder) : 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7'
|
||||
return htmlContent.replace(/(<img.*? src=)/ig, `$1 "${bg}" data-lazy-src=`)
|
||||
}
|
||||
|
||||
@@ -1,40 +1,82 @@
|
||||
/**
|
||||
* Butterfly
|
||||
* ramdom cover
|
||||
* Random cover for posts
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
hexo.extend.filter.register('before_post_render', data => {
|
||||
const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/i
|
||||
let { cover: coverVal, top_img: topImg } = data
|
||||
hexo.extend.generator.register('post', locals => {
|
||||
const previousIndexes = []
|
||||
|
||||
// Add path to top_img and cover if post_asset_folder is enabled
|
||||
if (hexo.config.post_asset_folder) {
|
||||
if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) data.top_img = `${data.path}${topImg}`
|
||||
if (coverVal && coverVal.indexOf('/') === -1 && imgTestReg.test(coverVal)) data.cover = `${data.path}${coverVal}`
|
||||
}
|
||||
|
||||
const randomCoverFn = () => {
|
||||
const { cover: { default_cover: defaultCover } } = hexo.theme.config
|
||||
const getRandomCover = defaultCover => {
|
||||
if (!defaultCover) return false
|
||||
if (!Array.isArray(defaultCover)) return defaultCover
|
||||
const num = Math.floor(Math.random() * defaultCover.length)
|
||||
return defaultCover[num]
|
||||
|
||||
const coverCount = defaultCover.length
|
||||
|
||||
if (coverCount === 1) {
|
||||
return defaultCover[0]
|
||||
}
|
||||
|
||||
const maxPreviousIndexes = coverCount === 2 ? 1 : (coverCount === 3 ? 2 : 3)
|
||||
|
||||
let index
|
||||
do {
|
||||
index = Math.floor(Math.random() * coverCount)
|
||||
} while (previousIndexes.includes(index) && previousIndexes.length < coverCount)
|
||||
|
||||
previousIndexes.push(index)
|
||||
if (previousIndexes.length > maxPreviousIndexes) {
|
||||
previousIndexes.shift()
|
||||
}
|
||||
|
||||
return defaultCover[index]
|
||||
}
|
||||
|
||||
if (coverVal === false) return data
|
||||
const handleImg = data => {
|
||||
const imgTestReg = /\.(png|jpe?g|gif|svg|webp|avif)(\?.*)?$/i
|
||||
let { cover: coverVal, top_img: topImg } = data
|
||||
|
||||
// If cover is not set, use random cover
|
||||
if (!coverVal) {
|
||||
const randomCover = randomCoverFn()
|
||||
data.cover = randomCover
|
||||
coverVal = randomCover // update coverVal
|
||||
// Add path to top_img and cover if post_asset_folder is enabled
|
||||
if (hexo.config.post_asset_folder) {
|
||||
if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) {
|
||||
data.top_img = `${data.path}${topImg}`
|
||||
}
|
||||
if (coverVal && coverVal.indexOf('/') === -1 && imgTestReg.test(coverVal)) {
|
||||
data.cover = `${data.path}${coverVal}`
|
||||
}
|
||||
}
|
||||
|
||||
if (coverVal === false) return data
|
||||
|
||||
// If cover is not set, use random cover
|
||||
if (!coverVal) {
|
||||
const { cover: { default_cover: defaultCover } } = hexo.theme.config
|
||||
const randomCover = getRandomCover(defaultCover)
|
||||
data.cover = randomCover
|
||||
coverVal = randomCover // update coverVal
|
||||
}
|
||||
|
||||
if (coverVal && (coverVal.indexOf('//') !== -1 || imgTestReg.test(coverVal))) {
|
||||
data.cover_type = 'img'
|
||||
}
|
||||
|
||||
return data
|
||||
}
|
||||
|
||||
if (coverVal && (coverVal.indexOf('//') !== -1 || imgTestReg.test(coverVal))) {
|
||||
data.cover_type = 'img'
|
||||
}
|
||||
// https://github.com/hexojs/hexo/blob/master/lib%2Fplugins%2Fgenerator%2Fpost.ts
|
||||
const posts = locals.posts.sort('date').toArray()
|
||||
const { length } = posts
|
||||
|
||||
return data
|
||||
return posts.map((post, i) => {
|
||||
if (i) post.prev = posts[i - 1]
|
||||
if (i < length - 1) post.next = posts[i + 1]
|
||||
|
||||
post.__post = true
|
||||
|
||||
return {
|
||||
data: handleImg(post),
|
||||
layout: 'post',
|
||||
path: post.path
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,38 +2,68 @@
|
||||
|
||||
hexo.extend.helper.register('aside_archives', function (options = {}) {
|
||||
const { config, page, site, url_for, _p } = this
|
||||
const archiveDir = config.archive_dir
|
||||
const { timezone } = config
|
||||
const lang = toMomentLocale(page.lang || page.language || config.language)
|
||||
const type = options.type || 'monthly'
|
||||
const format = options.format || (type === 'monthly' ? 'MMMM YYYY' : 'YYYY')
|
||||
const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count') ? options.show_count : true
|
||||
const order = options.order || -1
|
||||
const limit = options.limit
|
||||
const {
|
||||
archive_dir: archiveDir,
|
||||
timezone,
|
||||
language
|
||||
} = config
|
||||
|
||||
// Destructure and set default options with object destructuring
|
||||
const {
|
||||
type = 'monthly',
|
||||
format = type === 'monthly' ? 'MMMM YYYY' : 'YYYY',
|
||||
show_count: showCount = true,
|
||||
order = -1,
|
||||
limit,
|
||||
transform
|
||||
} = options
|
||||
|
||||
// Optimize locale handling
|
||||
const lang = toMomentLocale(page.lang || page.language || language)
|
||||
|
||||
// Memoize comparison function to improve performance
|
||||
const compareFunc = type === 'monthly'
|
||||
? (yearA, monthA, yearB, monthB) => yearA === yearB && monthA === monthB
|
||||
: (yearA, monthA, yearB, monthB) => yearA === yearB
|
||||
: (yearA, yearB) => yearA === yearB
|
||||
|
||||
const posts = site.posts.sort('date', order)
|
||||
if (!posts.length) return ''
|
||||
// Early return if no posts
|
||||
if (!site.posts.length) return ''
|
||||
|
||||
const data = []
|
||||
posts.forEach(post => {
|
||||
let date = post.date.clone()
|
||||
if (timezone) date = date.tz(timezone)
|
||||
// Use reduce for more efficient data processing
|
||||
const data = site.posts
|
||||
.sort('date', order)
|
||||
.reduce((acc, post) => {
|
||||
let date = post.date.clone()
|
||||
if (timezone) date = date.tz(timezone)
|
||||
|
||||
const year = date.year()
|
||||
const month = date.month() + 1
|
||||
const year = date.year()
|
||||
const month = date.month() + 1
|
||||
|
||||
if (!data.length || !compareFunc(data[data.length - 1].year, data[data.length - 1].month, year, month)) {
|
||||
if (lang) date = date.locale(lang)
|
||||
data.push({ name: date.format(format), year, month, count: 1 })
|
||||
} else {
|
||||
data[data.length - 1].count++
|
||||
}
|
||||
})
|
||||
|
||||
const link = item => {
|
||||
// Find or create archive entry
|
||||
const lastEntry = acc[acc.length - 1]
|
||||
if (!lastEntry || !compareFunc(
|
||||
lastEntry.year,
|
||||
lastEntry.month,
|
||||
year,
|
||||
month
|
||||
)) {
|
||||
acc.push({
|
||||
name: date.format(format),
|
||||
year,
|
||||
month,
|
||||
count: 1
|
||||
})
|
||||
} else {
|
||||
lastEntry.count++
|
||||
}
|
||||
|
||||
return acc
|
||||
}, [])
|
||||
|
||||
// Create link generator function
|
||||
const createArchiveLink = item => {
|
||||
let url = `${archiveDir}/${item.year}/`
|
||||
if (type === 'monthly') {
|
||||
url += item.month < 10 ? `0${item.month}/` : `${item.month}/`
|
||||
@@ -41,37 +71,48 @@ hexo.extend.helper.register('aside_archives', function (options = {}) {
|
||||
return url_for(url)
|
||||
}
|
||||
|
||||
const len = data.length
|
||||
const limitLength = limit === 0 ? len : Math.min(len, limit)
|
||||
// Limit results efficiently
|
||||
const limitedData = limit > 0
|
||||
? data.slice(0, Math.min(data.length, limit))
|
||||
: data
|
||||
|
||||
let result = `
|
||||
// Use template literal for better readability
|
||||
const archiveHeader = `
|
||||
<div class="item-headline">
|
||||
<i class="fas fa-archive"></i>
|
||||
<span>${_p('aside.card_archives')}</span>
|
||||
${len > limitLength ? `<a class="card-more-btn" href="${url_for(archiveDir)}/" title="${_p('aside.more_button')}"><i class="fas fa-angle-right"></i></a>` : ''}
|
||||
${data.length > limitedData.length
|
||||
? `<a class="card-more-btn" href="${url_for(archiveDir)}/"
|
||||
title="${_p('aside.more_button')}">
|
||||
<i class="fas fa-angle-right"></i>
|
||||
</a>`
|
||||
: ''}
|
||||
</div>
|
||||
<ul class="card-archive-list">
|
||||
`
|
||||
|
||||
for (let i = 0; i < limitLength; i++) {
|
||||
const item = data[i]
|
||||
result += `
|
||||
<li class="card-archive-list-item">
|
||||
<a class="card-archive-list-link" href="${link(item)}">
|
||||
<span class="card-archive-list-date">${options.transform ? options.transform(item.name) : item.name}</span>
|
||||
${showCount ? `<span class="card-archive-list-count">${item.count}</span>` : ''}
|
||||
</a>
|
||||
</li>
|
||||
`
|
||||
}
|
||||
// Use map for generating list items, join for performance
|
||||
const archiveList = `
|
||||
<ul class="card-archive-list">
|
||||
${limitedData.map(item => `
|
||||
<li class="card-archive-list-item">
|
||||
<a class="card-archive-list-link" href="${createArchiveLink(item)}">
|
||||
<span class="card-archive-list-date">
|
||||
${transform ? transform(item.name) : item.name}
|
||||
</span>
|
||||
${showCount
|
||||
? `<span class="card-archive-list-count">${item.count}</span>`
|
||||
: ''}
|
||||
</a>
|
||||
</li>
|
||||
`).join('')}
|
||||
</ul>
|
||||
`
|
||||
|
||||
result += '</ul>'
|
||||
return result
|
||||
return archiveHeader + archiveList
|
||||
})
|
||||
|
||||
const toMomentLocale = function (lang) {
|
||||
if (!lang || lang === 'en' || lang === 'default') {
|
||||
return 'en'
|
||||
}
|
||||
// Improved locale conversion function
|
||||
const toMomentLocale = lang => {
|
||||
if (!lang || ['en', 'default'].includes(lang)) return 'en'
|
||||
return lang.toLowerCase().replace('_', '-')
|
||||
}
|
||||
|
||||
@@ -131,3 +131,17 @@ hexo.extend.helper.register('shuoshuoFN', (data, page) => {
|
||||
|
||||
return finalResult
|
||||
})
|
||||
|
||||
hexo.extend.helper.register('getPageType', (page, isHome) => {
|
||||
const { layout, tag, category, type, archive } = page
|
||||
if (layout) return layout
|
||||
if (tag) return 'tag'
|
||||
if (category) return 'category'
|
||||
if (archive) return 'archive'
|
||||
if (type) {
|
||||
if (type === 'tags' || type === 'categories') return type
|
||||
else return 'page'
|
||||
}
|
||||
if (isHome) return 'home'
|
||||
return 'post'
|
||||
})
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* galleryGroup and gallery
|
||||
* {% galleryGroup [name] [descr] [url] [img] %}
|
||||
*
|
||||
* {% gallery [button] %}
|
||||
* {% gallery [button],[limit],[firstLimit] %}
|
||||
* {% gallery url,[url],[button] %}
|
||||
*/
|
||||
|
||||
@@ -11,54 +11,66 @@
|
||||
|
||||
const urlFor = require('hexo-util').url_for.bind(hexo)
|
||||
|
||||
const gallery = (args, content) => {
|
||||
args = args.join(' ').split(',')
|
||||
let button = false
|
||||
let type = 'data'
|
||||
let dataStr = ''
|
||||
const DEFAULT_LIMIT = 10
|
||||
const DEFAULT_FIRST_LIMIT = 10
|
||||
const IMAGE_REGEX = /!\[(.*?)\]\(([^\s]*)\s*(?:["'](.*?)["']?)?\s*\)/g
|
||||
|
||||
if (args[0] === 'url') {
|
||||
[type, dataStr, button] = args // url,[link],[lazyload]
|
||||
dataStr = urlFor(dataStr)
|
||||
} else {
|
||||
[button] = args // [lazyload]
|
||||
const regex = /!\[(.*?)\]\(([^\s]*)\s*(?:["'](.*?)["']?)?\s*\)/g
|
||||
let m
|
||||
const arr = []
|
||||
while ((m = regex.exec(content)) !== null) {
|
||||
if (m.index === regex.lastIndex) {
|
||||
regex.lastIndex++
|
||||
}
|
||||
arr.push({
|
||||
url: m[2],
|
||||
alt: m[1],
|
||||
title: m[3]
|
||||
})
|
||||
}
|
||||
// Helper functions
|
||||
const parseGalleryArgs = args => {
|
||||
const [type, ...rest] = args.join(' ').split(',').map(arg => arg.trim())
|
||||
return {
|
||||
isUrl: type === 'url',
|
||||
params: type === 'url' ? rest : [type, ...rest]
|
||||
}
|
||||
}
|
||||
|
||||
dataStr = JSON.stringify(arr)
|
||||
const parseImageContent = content => {
|
||||
const images = []
|
||||
let match
|
||||
|
||||
while ((match = IMAGE_REGEX.exec(content)) !== null) {
|
||||
images.push({
|
||||
url: match[2],
|
||||
alt: match[1] || '',
|
||||
title: match[3] || ''
|
||||
})
|
||||
}
|
||||
|
||||
return `<div class="gallery-container" data-type="${type}" data-button="${button}">
|
||||
<div class="gallery-items">${dataStr}</div>
|
||||
</div>`
|
||||
return images
|
||||
}
|
||||
|
||||
const createGalleryHTML = (type, dataStr, button, limit, firstLimit) => {
|
||||
return `<div class="gallery-container" data-type="${type}" data-button="${button}" data-limit="${limit}" data-first="${firstLimit}">
|
||||
<div class="gallery-items">${dataStr}</div>
|
||||
</div>`
|
||||
}
|
||||
|
||||
const gallery = (args, content) => {
|
||||
const { isUrl, params } = parseGalleryArgs(args)
|
||||
|
||||
if (isUrl) {
|
||||
const [dataStr, button = false, limit = DEFAULT_LIMIT, firstLimit = DEFAULT_FIRST_LIMIT] = params
|
||||
return createGalleryHTML('url', urlFor(dataStr), button, limit, firstLimit)
|
||||
}
|
||||
|
||||
const [button = false, limit = DEFAULT_LIMIT, firstLimit = DEFAULT_FIRST_LIMIT] = params
|
||||
const images = parseImageContent(content)
|
||||
return createGalleryHTML('data', JSON.stringify(images), button, limit, firstLimit)
|
||||
}
|
||||
|
||||
const galleryGroup = args => {
|
||||
const [name, descr, url, img] = args
|
||||
const imgUrl = urlFor(img)
|
||||
const urlLink = urlFor(url)
|
||||
const [name = '', descr = '', url = '', img = ''] = args.map(arg => arg.trim())
|
||||
|
||||
return `<figure class="gallery-group">
|
||||
<img class="gallery-group-img no-lightbox" src='${imgUrl}' alt="Group Image Gallery">
|
||||
<figcaption>
|
||||
<div class="gallery-group-name">${name}</div>
|
||||
<p>${descr}</p>
|
||||
<a href='${urlLink}'></a>
|
||||
</figcaption>
|
||||
</figure>
|
||||
`
|
||||
<img class="gallery-group-img no-lightbox" src='${urlFor(img)}' alt="Group Image Gallery">
|
||||
<figcaption>
|
||||
<div class="gallery-group-name">${name}</div>
|
||||
<p>${descr}</p>
|
||||
<a href='${urlFor(url)}'></a>
|
||||
</figcaption>
|
||||
</figure>`
|
||||
}
|
||||
|
||||
// Register tags
|
||||
hexo.extend.tag.register('gallery', gallery, { ends: true })
|
||||
hexo.extend.tag.register('galleryGroup', galleryGroup)
|
||||
|
||||
@@ -16,50 +16,37 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
const parseArgs = args => {
|
||||
return args.join(' ').split(',')
|
||||
}
|
||||
const parseArgs = args => args.join(' ').split(',')
|
||||
|
||||
const generateStyle = (bg, color) => {
|
||||
let style = 'style="'
|
||||
if (bg) {
|
||||
style += `background-color: ${bg};`
|
||||
}
|
||||
if (color) {
|
||||
style += `color: ${color}`
|
||||
}
|
||||
if (bg) style += `background-color: ${bg};`
|
||||
if (color) style += `color: ${color}`
|
||||
style += '"'
|
||||
return style
|
||||
}
|
||||
|
||||
const hideInline = args => {
|
||||
const [content, display = 'Click', bg = false, color = false] = parseArgs(args)
|
||||
const group = generateStyle(bg, color)
|
||||
|
||||
return `<span class="hide-inline"><button type="button" class="hide-button" ${group}>${display}
|
||||
</button><span class="hide-content">${content}</span></span>`
|
||||
const style = generateStyle(bg, color)
|
||||
return `<span class="hide-inline"><button type="button" class="hide-button" ${style}>${display}</button><span class="hide-content">${content}</span></span>`
|
||||
}
|
||||
|
||||
const hideBlock = (args, content) => {
|
||||
const [display = 'Click', bg = false, color = false] = parseArgs(args)
|
||||
const group = generateStyle(bg, color)
|
||||
|
||||
return `<div class="hide-block"><button type="button" class="hide-button" ${group}>${display}
|
||||
</button><div class="hide-content">${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div></div>`
|
||||
const style = generateStyle(bg, color)
|
||||
const renderedContent = hexo.render.renderSync({ text: content, engine: 'markdown' })
|
||||
return `<div class="hide-block"><button type="button" class="hide-button" ${style}>${display}</button><div class="hide-content">${renderedContent}</div></div>`
|
||||
}
|
||||
|
||||
const hideToggle = (args, content) => {
|
||||
const [display, bg = false, color = false] = parseArgs(args)
|
||||
const group = generateStyle(bg, color)
|
||||
let border = ''
|
||||
|
||||
if (bg) {
|
||||
border = `style="border: 1px solid ${bg}"`
|
||||
}
|
||||
|
||||
return `<details class="toggle" ${border}><summary class="toggle-button" ${group}>${display}</summary><div class="toggle-content">${hexo.render.renderSync({ text: content, engine: 'markdown' })}</div></details>`
|
||||
const style = generateStyle(bg, color)
|
||||
const border = bg ? `style="border: 1px solid ${bg}"` : ''
|
||||
const renderedContent = hexo.render.renderSync({ text: content, engine: 'markdown' })
|
||||
return `<details class="toggle" ${border}><summary class="toggle-button" ${style}>${display}</summary><div class="toggle-content">${renderedContent}</div></details>`
|
||||
}
|
||||
|
||||
hexo.extend.tag.register('hideInline', hideInline)
|
||||
hexo.extend.tag.register('hideBlock', hideBlock, { ends: true })
|
||||
hexo.extend.tag.register('hideToggle', hideToggle, { ends: true })
|
||||
hexo.extend.tag.register('hideToggle', hideToggle, { ends: true })
|
||||
@@ -1,9 +1,9 @@
|
||||
/**
|
||||
* inlineImg 圖片
|
||||
* @param {Array} args 圖片名稱和高度
|
||||
* @param {string} args[0] 圖片名稱
|
||||
* @param {number} args[1] 圖片高度
|
||||
* @returns {string} 圖片標籤
|
||||
* inlineImg
|
||||
* @param {Array} args - Image name and height
|
||||
* @param {string} args[0] - Image name
|
||||
* @param {number} args[1] - Image height
|
||||
* @returns {string} - Image tag
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
@@ -10,7 +10,7 @@ const { escapeHTML } = require('hexo-util')
|
||||
|
||||
const mermaid = (args, content) => {
|
||||
return `<div class="mermaid-wrap"><pre class="mermaid-src" hidden>
|
||||
${escapeHTML(content)}
|
||||
${escapeHTML(content)}
|
||||
</pre></div>`
|
||||
}
|
||||
|
||||
|
||||
@@ -1,41 +1,50 @@
|
||||
/**
|
||||
* timeline
|
||||
* by Jerry
|
||||
* Timeline tag for Hexo
|
||||
* Syntax:
|
||||
* {% timeline [headline],[color] %}
|
||||
* <!-- timeline [title] -->
|
||||
* [content]
|
||||
* <!-- endtimeline -->
|
||||
* <!-- timeline [title] -->
|
||||
* [content]
|
||||
* <!-- endtimeline -->
|
||||
* {% endtimeline %}
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
const timeLineFn = (args, content) => {
|
||||
const tlBlock = /<!--\s*timeline (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtimeline\s*-->/g
|
||||
// Use named capture groups for better readability
|
||||
const tlBlock = /<!--\s*timeline\s*(?<title>.*?)\s*-->\n(?<content>[\s\S]*?)<!--\s*endtimeline\s*-->/g
|
||||
|
||||
let result = ''
|
||||
let color = ''
|
||||
let text = ''
|
||||
if (args.length) {
|
||||
[text, color] = args.join(' ').split(',')
|
||||
const mdContent = hexo.render.renderSync({ text, engine: 'markdown' })
|
||||
result += `<div class='timeline-item headline'><div class='timeline-item-title'><div class='item-circle'>${mdContent}</div></div></div>`
|
||||
}
|
||||
// Pre-compile markdown render function
|
||||
const renderMd = text => hexo.render.renderSync({ text, engine: 'markdown' })
|
||||
|
||||
const matches = []
|
||||
let match
|
||||
// Parse arguments more efficiently
|
||||
const [text, color = ''] = args.length ? args.join(' ').split(',') : []
|
||||
|
||||
while ((match = tlBlock.exec(content)) !== null) {
|
||||
matches.push(match[1])
|
||||
matches.push(match[2])
|
||||
}
|
||||
// Build initial headline if text exists
|
||||
const headline = text
|
||||
? `<div class='timeline-item headline'>
|
||||
<div class='timeline-item-title'>
|
||||
<div class='item-circle'>${renderMd(text)}</div>
|
||||
</div>
|
||||
</div>`
|
||||
: ''
|
||||
|
||||
for (let i = 0; i < matches.length; i += 2) {
|
||||
const tlChildTitle = hexo.render.renderSync({ text: matches[i], engine: 'markdown' })
|
||||
const tlChildContent = hexo.render.renderSync({ text: matches[i + 1], engine: 'markdown' })
|
||||
// Match all timeline blocks in one pass and transform
|
||||
const items = Array.from(content.matchAll(tlBlock))
|
||||
.map(({ groups: { title, content } }) =>
|
||||
`<div class='timeline-item'>
|
||||
<div class='timeline-item-title'>
|
||||
<div class='item-circle'>${renderMd(title)}</div>
|
||||
</div>
|
||||
<div class='timeline-item-content'>${renderMd(content)}</div>
|
||||
</div>`
|
||||
)
|
||||
.join('')
|
||||
|
||||
const tlTitleHtml = `<div class='timeline-item-title'><div class='item-circle'>${tlChildTitle}</div></div>`
|
||||
const tlContentHtml = `<div class='timeline-item-content'>${tlChildContent}</div>`
|
||||
|
||||
result += `<div class='timeline-item'>${tlTitleHtml + tlContentHtml}</div>`
|
||||
}
|
||||
|
||||
return `<div class="timeline ${color || ''}">${result}</div>`
|
||||
return `<div class="timeline ${color}">${headline}${items}</div>`
|
||||
}
|
||||
|
||||
hexo.extend.tag.register('timeline', timeLineFn, { ends: true })
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
width: 100% !important
|
||||
|
||||
.pagination-related
|
||||
width: 50%
|
||||
height: 150px
|
||||
|
||||
+maxWidth768()
|
||||
width: 100%
|
||||
+minWidth768()
|
||||
flex: 1
|
||||
|
||||
.info-1
|
||||
.info-item-2
|
||||
@@ -31,6 +30,10 @@
|
||||
margin-top: 40px
|
||||
width: 100%
|
||||
addBorderRadius()
|
||||
display: flex
|
||||
|
||||
+maxWidth768()
|
||||
flex-direction: column
|
||||
|
||||
.layout
|
||||
.pagination
|
||||
|
||||
@@ -16,7 +16,7 @@ $theme-toc-color = $themeColorEnable && hexo-config('theme_color.toc_color') ? c
|
||||
|
||||
$chinseFont = $language == 'zh-CN' ? 'Microsoft YaHei' : 'Microsoft JhengHei'
|
||||
$dafault-font-family = -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', $chinseFont, sans-serif
|
||||
$dafault-code-font = consolas, Menlo, 'PingFang SC', $chinseFont, sans-serif
|
||||
$dafault-code-font = consolas, Menlo, monospace, 'PingFang SC', $chinseFont, sans-serif
|
||||
|
||||
$font-family = hexo-config('font.font_family') ? unquote(hexo-config('font.font_family')) : $dafault-font-family
|
||||
$code-font-family = hexo-config('font.code_font_family') ? unquote(hexo-config('font.code_font_family')) : $dafault-code-font
|
||||
|
||||
@@ -224,14 +224,23 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
*/
|
||||
|
||||
const fetchUrl = async url => {
|
||||
const response = await fetch(url)
|
||||
return await response.json()
|
||||
try {
|
||||
const response = await fetch(url)
|
||||
return await response.json()
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch URL:', error)
|
||||
return []
|
||||
}
|
||||
}
|
||||
|
||||
const runJustifiedGallery = (item, data, isButton = false, tabs) => {
|
||||
const dataLength = data.length
|
||||
const runJustifiedGallery = (container, data, config) => {
|
||||
const { isButton, limit, firstLimit, tabs } = config
|
||||
|
||||
const ig = new InfiniteGrid.JustifiedInfiniteGrid(item, {
|
||||
const dataLength = data.length
|
||||
const maxGroupKey = Math.ceil((dataLength - firstLimit) / limit + 1)
|
||||
|
||||
// Gallery configuration
|
||||
const igConfig = {
|
||||
gap: 5,
|
||||
isConstantSize: true,
|
||||
sizeRange: [150, 600],
|
||||
@@ -239,132 +248,130 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
// observeChildren: true,
|
||||
useTransform: true
|
||||
// useRecycle: false
|
||||
})
|
||||
|
||||
const replaceDq = str => str.replace(/"/g, '"') // replace double quotes to "
|
||||
|
||||
const getItems = (nextGroupKey, count) => {
|
||||
const nextItems = []
|
||||
const startCount = (nextGroupKey - 1) * count
|
||||
|
||||
for (let i = 0; i < count; ++i) {
|
||||
const num = startCount + i
|
||||
if (num >= dataLength) {
|
||||
break
|
||||
}
|
||||
|
||||
const item = data[num]
|
||||
const alt = item.alt ? `alt="${replaceDq(item.alt)}"` : ''
|
||||
const title = item.title ? `title="${replaceDq(item.title)}"` : ''
|
||||
|
||||
nextItems.push(`<div class="item">
|
||||
<img src="${item.url}" data-grid-maintained-target="true" ${alt + title} />
|
||||
</div>`)
|
||||
}
|
||||
return nextItems
|
||||
}
|
||||
|
||||
const buttonText = GLOBAL_CONFIG.infinitegrid.buttonText
|
||||
const addButton = item => {
|
||||
const button = document.createElement('button')
|
||||
button.innerHTML = buttonText + '<i class="fa-solid fa-arrow-down"></i>'
|
||||
|
||||
button.addEventListener('click', e => {
|
||||
e.target.closest('button').remove()
|
||||
btf.setLoading.add(item)
|
||||
appendItem(ig.getGroups().length + 1, 10)
|
||||
}, { once: true })
|
||||
|
||||
item.insertAdjacentElement('afterend', button)
|
||||
}
|
||||
|
||||
const appendItem = (nextGroupKey, count) => {
|
||||
ig.append(getItems(nextGroupKey, count), nextGroupKey)
|
||||
}
|
||||
|
||||
const maxGroupKey = Math.ceil(dataLength / 10)
|
||||
const ig = new InfiniteGrid.JustifiedInfiniteGrid(container, igConfig)
|
||||
let isLayoutHidden = false
|
||||
|
||||
const completeFn = e => {
|
||||
if (tabs) {
|
||||
const parentNode = item.parentNode
|
||||
// Utility functions
|
||||
const sanitizeString = str => (str && str.replace(/"/g, '"')) || ''
|
||||
|
||||
const createImageItem = item => {
|
||||
const alt = item.alt ? `alt="${sanitizeString(item.alt)}"` : ''
|
||||
const title = item.title ? `title="${sanitizeString(item.title)}"` : ''
|
||||
return `<div class="item">
|
||||
<img src="${item.url}" data-grid-maintained-target="true" ${alt} ${title} />
|
||||
</div>`
|
||||
}
|
||||
|
||||
const getItems = (nextGroupKey, count, isFirst = false) => {
|
||||
const startIndex = isFirst ? (nextGroupKey - 1) * count : (nextGroupKey - 2) * count + firstLimit
|
||||
return data.slice(startIndex, startIndex + count).map(createImageItem)
|
||||
}
|
||||
|
||||
// Load more button
|
||||
const addLoadMoreButton = container => {
|
||||
const button = document.createElement('button')
|
||||
button.innerHTML = `${GLOBAL_CONFIG.infinitegrid.buttonText}<i class="fa-solid fa-arrow-down"></i>`
|
||||
|
||||
button.addEventListener('click', () => {
|
||||
button.remove()
|
||||
btf.setLoading.add(container)
|
||||
appendItems(ig.getGroups().length + 1, limit)
|
||||
}, { once: true })
|
||||
|
||||
container.insertAdjacentElement('afterend', button)
|
||||
}
|
||||
|
||||
const appendItems = (nextGroupKey, count, isFirst) => {
|
||||
ig.append(getItems(nextGroupKey, count, isFirst), nextGroupKey)
|
||||
}
|
||||
|
||||
// Event handlers
|
||||
const handleRenderComplete = e => {
|
||||
if (tabs) {
|
||||
const parentNode = container.parentNode
|
||||
if (isLayoutHidden) {
|
||||
parentNode.style.visibility = 'visible'
|
||||
}
|
||||
|
||||
if (item.offsetHeight === 0) {
|
||||
if (container.offsetHeight === 0) {
|
||||
parentNode.style.visibility = 'hidden'
|
||||
isLayoutHidden = true
|
||||
}
|
||||
}
|
||||
|
||||
const { updated, isResize, mounted } = e
|
||||
if (!updated.length || !mounted.length || isResize) {
|
||||
return
|
||||
}
|
||||
if (!updated.length || !mounted.length || isResize) return
|
||||
|
||||
btf.loadLightbox(item.querySelectorAll('img:not(.medium-zoom-image)'))
|
||||
btf.loadLightbox(container.querySelectorAll('img:not(.medium-zoom-image)'))
|
||||
|
||||
if (ig.getGroups().length === maxGroupKey) {
|
||||
btf.setLoading.remove(item)
|
||||
!tabs && ig.off('renderComplete', completeFn)
|
||||
btf.setLoading.remove(container)
|
||||
!tabs && ig.off('renderComplete', handleRenderComplete)
|
||||
return
|
||||
}
|
||||
|
||||
if (isButton) {
|
||||
btf.setLoading.remove(item)
|
||||
addButton(item)
|
||||
btf.setLoading.remove(container)
|
||||
addLoadMoreButton(container)
|
||||
}
|
||||
}
|
||||
|
||||
const requestAppendFn = btf.debounce(e => {
|
||||
const handleRequestAppend = btf.debounce(e => {
|
||||
const nextGroupKey = (+e.groupKey || 0) + 1
|
||||
appendItem(nextGroupKey, 10)
|
||||
|
||||
if (nextGroupKey === maxGroupKey) {
|
||||
ig.off('requestAppend', requestAppendFn)
|
||||
}
|
||||
if (nextGroupKey === 1) appendItems(nextGroupKey, firstLimit, true)
|
||||
else appendItems(nextGroupKey, limit)
|
||||
|
||||
if (nextGroupKey === maxGroupKey) ig.off('requestAppend', handleRequestAppend)
|
||||
}, 300)
|
||||
|
||||
btf.setLoading.add(item)
|
||||
ig.on('renderComplete', completeFn)
|
||||
btf.setLoading.add(container)
|
||||
ig.on('renderComplete', handleRenderComplete)
|
||||
|
||||
if (isButton) {
|
||||
appendItem(1, 10)
|
||||
appendItems(1, firstLimit, true)
|
||||
} else {
|
||||
ig.on('requestAppend', requestAppendFn)
|
||||
ig.on('requestAppend', handleRequestAppend)
|
||||
ig.renderItems()
|
||||
}
|
||||
|
||||
btf.addGlobalFn('pjaxSendOnce', () => { ig.destroy() })
|
||||
btf.addGlobalFn('pjaxSendOnce', () => ig.destroy())
|
||||
}
|
||||
|
||||
const addJustifiedGallery = async (ele, tabs = false) => {
|
||||
if (!ele.length) return
|
||||
const init = async () => {
|
||||
for (const item of ele) {
|
||||
if (btf.isHidden(item) || item.classList.contains('loaded')) continue
|
||||
const addJustifiedGallery = async (elements, tabs = false) => {
|
||||
if (!elements.length) return
|
||||
|
||||
const initGallery = async () => {
|
||||
for (const element of elements) {
|
||||
if (btf.isHidden(element) || element.classList.contains('loaded')) continue
|
||||
|
||||
const config = {
|
||||
isButton: element.getAttribute('data-button') === 'true',
|
||||
limit: parseInt(element.getAttribute('data-limit'), 10),
|
||||
firstLimit: parseInt(element.getAttribute('data-first'), 10),
|
||||
tabs
|
||||
}
|
||||
|
||||
const container = element.firstElementChild
|
||||
const content = container.textContent
|
||||
container.textContent = ''
|
||||
element.classList.add('loaded')
|
||||
|
||||
const isButton = item.getAttribute('data-button') === 'true'
|
||||
const children = item.firstElementChild
|
||||
const text = children.textContent
|
||||
children.textContent = ''
|
||||
item.classList.add('loaded')
|
||||
try {
|
||||
const content = item.getAttribute('data-type') === 'url' ? await fetchUrl(text) : JSON.parse(text)
|
||||
runJustifiedGallery(children, content, isButton, tabs)
|
||||
} catch (e) {
|
||||
console.error('Gallery data parsing failed:', e)
|
||||
const data = element.getAttribute('data-type') === 'url' ? await fetchUrl(content) : JSON.parse(content)
|
||||
runJustifiedGallery(container, data, config)
|
||||
} catch (error) {
|
||||
console.error('Gallery data parsing failed:', error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof InfiniteGrid === 'function') {
|
||||
init()
|
||||
await initGallery()
|
||||
} else {
|
||||
await btf.getScript(`${GLOBAL_CONFIG.infinitegrid.js}`)
|
||||
init()
|
||||
await btf.getScript(GLOBAL_CONFIG.infinitegrid.js)
|
||||
await initGallery()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +871,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
menuMask && menuMask.addEventListener('click', () => { sidebarFn.close() })
|
||||
|
||||
clickFnOfSubMenu()
|
||||
GLOBAL_CONFIG.islazyload && lazyloadImg()
|
||||
GLOBAL_CONFIG.islazyloadPlugin && lazyloadImg()
|
||||
GLOBAL_CONFIG.copyright !== undefined && addCopyright()
|
||||
|
||||
if (GLOBAL_CONFIG.autoDarkmode) {
|
||||
@@ -890,7 +897,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
initAdjust()
|
||||
justifiedIndexPostUI()
|
||||
|
||||
if (GLOBAL_CONFIG_SITE.isPost) {
|
||||
if (GLOBAL_CONFIG_SITE.pageType === 'post') {
|
||||
addPostOutdateNotice()
|
||||
GLOBAL_CONFIG.relativeDate.post && relativeDate(document.querySelectorAll('#post-meta time'))
|
||||
} else {
|
||||
@@ -900,11 +907,11 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
toggleCardCategory()
|
||||
}
|
||||
|
||||
GLOBAL_CONFIG_SITE.isHome && scrollDownInIndex()
|
||||
GLOBAL_CONFIG_SITE.pageType === 'home' && scrollDownInIndex()
|
||||
scrollFn()
|
||||
|
||||
forPostFn()
|
||||
!GLOBAL_CONFIG_SITE.isShuoshuo && btf.switchComments(document)
|
||||
GLOBAL_CONFIG_SITE.pageType !== 'shuoshuo' && btf.switchComments(document)
|
||||
openMobileMenu()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user