Add solitude

This commit is contained in:
IF-chan
2024-07-05 21:01:19 +08:00
parent 26d71c4fbc
commit 71758b9fce
289 changed files with 23277 additions and 0 deletions
@@ -0,0 +1,9 @@
if theme.google_adsense && theme.google_adsense.enable
script(async src=theme.google_adsense.js onerror="document.querySelectorAll('.google-ads-warp').forEach(i => i.style.display='none')")
if theme.google_adsense.auto_ads
script.
(adsbygoogle = window.adsbygoogle || []).push({
google_ad_client: '!{theme.google_adsense.client}',
enable_page_level_ads: !{theme.google_adsense.enable_page_level_ads},
});
@@ -0,0 +1,38 @@
case theme.display_mode.type
when "auto"
script.
initTheme = () => {
let isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
const cachedMode = utils.saveToLocal.get('theme');
if (cachedMode === undefined) {
const nowMode =
isDarkMode ? 'dark' : 'light'
document.documentElement.setAttribute('data-theme', nowMode);
} else {
document.documentElement.setAttribute('data-theme', cachedMode);
}
typeof rm === 'object' && rm.mode(cachedMode === 'dark' && isDarkMode)
}
initTheme()
when "dark"
script.
initTheme = () => {
const cachedMode = utils.saveToLocal.get('theme');
if (cachedMode === undefined)
document.documentElement.setAttribute('data-theme', 'dark');
else
document.documentElement.setAttribute('data-theme', cachedMode);
typeof rm === 'object' && rm.mode(cachedMode === undefined || cachedMode === 'dark')
}
initTheme()
when "light"
script.
initTheme = () => {
const cachedMode = utils.saveToLocal.get('theme');
if (cachedMode === undefined)
document.documentElement.setAttribute('data-theme', 'light');
else
document.documentElement.setAttribute('data-theme', cachedMode);
typeof rm === 'object' && rm.mode(cachedMode === 'dark')
}
initTheme()
@@ -0,0 +1,51 @@
div#console
div.close-btn(onclick="sco.hideConsole()")
i.solitude.st-close-fill
if theme.console_plus
div.console-card-group
if theme.recent_comments.enable && theme.recent_comments.img
div.console-card-group-left
div.console-card#card-newest-comments(onclick="sco.hideConsole()")
div.card-content
div.author-content-item-tips= _p('console.comment_tip')
div.author-content-item-title
| #{_p('console.comment_title')}
if theme.recent_comments.enable
a.recent-comment-more(href=url_for(theme.recent_comments.page) title=_p('console.recent_comment_more'))
i.solitude.st-right-btn-fill
a.recent-comment-image(href=url_for(theme.recent_comments.page))
img(src=theme.recent_comments.img)
div.console-card-group-right
div.console-card.tags(onclick="sco.hideConsole()")
div.card-content
div.author-content-item-tips= _p('console.tag_tip')
div.author-content-item-title= _p('console.tag_title')
div.card-tag-cloud
each tag in site.tags.find({ parent: { $exists: false } }).data
a(href=url_for(tag.path))= tag.name
sup= tag.length
div.console-card.history(onclick="sco.hideConsole()")
include ./widgets/aside/asideArchive.pug
div.button-group
div.console-btn-item
span.darkmode_switchbutton(onclick="sco.switchDarkMode()", title=_p('console.switch_darkmode'))
i.solitude.st-moon-clear-fill
div.console-btn-item#consoleHideAside
span.asideSwitch(onclick="sco.switchHideAside()", title=_p('console.switch_hideAside'))
i.solitude.st-side-bar-fill
if theme.keyboard.enable
div.console-btn-item#consoleKeyboard(onclick="sco.switchKeyboard()")
span.keyboardSwitch(title=_p('console.switch_keyboard'))
i.solitude.st-keyboard-box-fill
if theme.capsule.enable
div.console-btn-item#consoleMusic(onclick="sco.musicToggle()")
span.music-switch(title=_p('console.switch_music'))
i.solitude.st-disc-fill
if theme.comment.use && theme.comment.commentBarrage
div.console-btn-item.on#consoleCommentBarrage(onclick="sco.switchCommentBarrage()")
span.commentBarrage
i.solitude.st-chat-fill
div.console-mask(onclick="sco.hideConsole()")
@@ -0,0 +1,72 @@
if theme.post.footer.enable && is_post()
div#st-footer-bar
div.footer-logo
if theme.site.name.class === 'i_class'
i.solitude(class=theme.site.name.custom)
else if theme.site.name.class === 'img'
img.solitude.nolazyload(src=url_for(theme.site.name.custom))
else if theme.site.name.class === 'text'
span= theme.site.name.custom
div.footer-bar-description=theme.post.footer.desc
if theme.post.footer.button.enable
a.footer-bar-link(href=url_for(theme.post.footer.button.url))= theme.post.footer.button.name
div#footer_deal
- var leftInfo = theme.footer && theme.footer.information && theme.footer.information.left || {}
- var rightInfo = theme.footer && theme.footer.information && theme.footer.information.right || {}
each value, label in leftInfo
- var array = value.split('||')
a.deal_link(href=url_for(trim(array[0])), title=label)
i.solitude(class=array[1])
if theme.footer.information.author
div#footer_mini_logo.nolazyload.footer_mini_logo(title=_p('nav.backtop'), onclick="sco.toTop()")
img(src=theme.site.icon, alt=_p('nav.backtop'))
each value, label in rightInfo
- var array = value.split('||')
a.deal_link(href=url_for(trim(array[0])), title=label)
i.solitude(class=array[1])
div#st-footer
- var group = theme.footer && theme.footer.group ? theme.footer.group : {}
each value, x in group
div.footer-group
h3.footer-title= x
div.footer-links
each url, y in value
a.footer-item(href=url_for(url), title=y)= y
if theme.footer && theme.footer.randomlink
div.footer-group
div.footer-title-group
h3.footer-title= _p('footer.randomlink')
button.random-friends-btn(onclick='randomLinksList()', title=_p('footer.randomlink'))
i.solitude.st-refresh-line
div.footer-links#friend-links-in-footer
div#footer-bar
div.footer-bar-links
div.footer-bar-left
if moment(theme.aside.siteinfo.runtime).year() === new Date().getFullYear()
div.copyright © #{moment(theme.aside.siteinfo.runtime).year()} By 
a.footer-bar-link(href=url_for("/"))= config.author
else
div.copyright © #{moment(theme.aside.siteinfo.runtime).year()} - #{new Date().getFullYear()} By 
a.footer-bar-link(href=url_for("/"))= config.author
div.footer-bar-right
each item in theme.footer.links
a.footer-bar-link(href=url_for(item.url), alt=item.name)!= item.name
a.footer-bar-link.cc(href=url_for(theme.footer.license), aria-label = 'copyright')
i.solitude.st-copyright-line
i.solitude.st-creative-commons-by-line
i.solitude.st-creative-commons-nc-line
i.solitude.st-creative-commons-nd-line
if theme.footer.privacy
div.needEndHide#cookies-window
div.cookies-window-title= __('cookies.title')
div.cookies-window-content
span.cookies-tip= __('cookies.tip')
a.cookies-link(href=url_for(theme.footer.privacy), title=_p('cookies.privacy'))
i.solitude.st-right-btn-fill
if theme.comment.use && theme.comment.commentBarrage
div.comment-barrage.needEndHide
+32
View File
@@ -0,0 +1,32 @@
- let title = page.title, subtitle =''
- if (is_home()) title = config.title
- else if (is_archive()) title = _p('page.archives') + (page.year || "")
- else if (is_tag()) title = _p('page.tag')+': ' + page.tag
- else if (is_category()) title = _p('page.category') +': ' + page.category
- else if (page.type === '404') title = _p('page.404')
- else if (page.type === 'tags') title = _p('page.tags')
- else if (page.type === 'categories') title = _p('page.categories')
- else if (is_post() || is_page()) title = page.title
- if (is_home()) subtitle = config.subtitle ? ' - ' + config.subtitle : ''
- else subtitle = title ? ' | ' + config.title : config.title
meta(charset="utf-8")
meta(http-equiv="X-UA-Compatible", content="IE=edge")
meta(name="viewport" content="width=device-width, initial-scale=1")
title= title + subtitle
noscript= _p('head.noscript')
link(rel="icon", href=url_for(theme.site.siteIcon))
// index.css
link(rel="stylesheet", href=url_for(theme.cdn.main_css))
// inject head
include ./inject/head.pug
// global head
include ./head/config.pug
// page-config head
include ./head/page_config
@@ -0,0 +1,166 @@
-
if (theme.search.enable) {
var localSearch = 'undefined';
var algolia = 'undefined';
switch (theme.search.type) {
case 'local':
localSearch = JSON.stringify({
preload: theme.search.local.preload,
path: theme?.search?.local?.CDN || '/search.xml'
});
break;
case 'algolia':
algolia = JSON.stringify({
appId: config.algolia.appId || config.algolia.applicationID,
apiKey: config.algolia.apiKey,
indexName: config.algolia.indexName,
hits: {
per_page: theme?.search?.algolia?.hits?.per_page || 10
}
});
break;
}
}
const sayhello2 = theme.aside?.card?.sayhello2?.map(item => `"${item}"`) || [];
const [hello_prefix, hello_back] = [_p('aside.hello'), _p('aside.back')];
let comment = false
if (theme.comment.use && theme.comment.commentBarrage) {
comment = {
avatar: theme.comment.avatar,
commentBarrage: theme.comment.commentBarrage,
}
}
let post_ai = false
if (theme.post_ai.enable) {
post_ai = JSON.stringify({
key: theme.post_ai.key,
talk: theme.post_ai.talk,
randomPost: theme.post_ai.randomPost,
})
}
let copyright = false;
if (theme.copy.enable && theme.copy.copyright.enable) {
copyright = JSON.stringify({
limit: theme.copy.copyright.limit,
author: _p("copy_copyright.author") + ': ' + config.author,
link: _p("copy_copyright.link") + ': ',
source: _p("copy_copyright.source") + ': ' + config.title,
info: _p("copy_copyright.info")
})
}
let lang = false
lang = {
theme: {
dark: _p('theme.dark'),
light: _p('theme.light'),
},
copy: {
success: _p('copy.success'),
error: _p('copy.error'),
},
backtop: _p('nav.backtop'),
time: {
day: _p('time.day'),
hour: _p('time.hour'),
just: _p('time.just'),
min: _p('time.min'),
month: _p('time.month')
},
day: _p('day'),
f12: _p('f12'),
totalk: _p('totalk')
}
if (theme.search.enable) {
lang.search = {
empty: _p('search.empty'),
hit: _p('search.hit'),
placeholder: _p('search.placeholder'),
count: _p('search.count')
}
}
if (theme.comment.use && theme.comment.commentBarrage) {
lang.barrage = {
title: _p('commentBarrage.title'),
}
}
let rightMenu = false
if (theme.right_menu.enable) {
rightMenu = {
mode: {
dark: _p('right_menu.light'),
light: _p('right_menu.dark'),
},
img_error: _p('right_menu.img_error')
}
if (theme.capsule.enable) {
rightMenu.music = {
start: _p('right_menu.music.start'),
stop: _p('right_menu.music.stop'),
}
}
if (theme.comment.use && theme.comment.commentBarrage) {
rightMenu.barrage = {
open: _p('right_menu.barrage.open'),
close: _p('right_menu.barrage.close')
}
}
if (theme.right_menu.translate.enable) {
rightMenu.translate = {
translateDelay: theme.right_menu.translate.translateDelay,
defaultEncoding: theme.right_menu.translate.defaultEncoding
}
}
}
script.
const GLOBAL_CONFIG = {
root: '!{config.root}',
algolia: !{algolia ? algolia : 'undefined'},
localsearch: !{localSearch ? localSearch : 'undefined'},
runtime: '!{theme.aside.siteinfo.runtimeenable ? theme.aside.siteinfo.runtime : false}',
lazyload: {
enable: !{theme.lazyload.enable},
error: '!{theme.lazyload.errorimg}'
},
copyright: !{copyright},
highlight: {
enable: !{theme.highlight.enable},
limit: !{theme.highlight.limit},
expand: !{theme.highlight.expand},
copy: !{theme.highlight.copy},
syntax: '!{config.syntax_highlighter}'
},
randomlink: !{theme.footer.randomlink},
lang: !{JSON.stringify(lang)},
aside: {
sayhello: {
morning: '!{theme.aside.card.sayhello.morning}',
noon: '!{theme.aside.card.sayhello.noon}',
afternoon: '!{theme.aside.card.sayhello.afternoon}',
night: '!{theme.aside.card.sayhello.night}',
goodnight: '!{theme.aside.card.sayhello.goodnight}',
},
sayhello2: [!{sayhello2}],
sayhello3: {
prefix: '!{hello_prefix}',
back: '!{hello_back}',
},
},
covercolor: {
enable: !{theme.post.covercolor.enable}
},
comment: !{comment ? JSON.stringify(comment) : false},
lightbox: '!{ theme.mediumZoom ? "mediumZoom" : (theme.fancybox ? "fancybox" : "null")}',
post_ai: !{post_ai},
right_menu: !{rightMenu ? JSON.stringify(rightMenu) : false},
};
@@ -0,0 +1,13 @@
if theme.OpenGraph.enable
-
const coverVal = page.cover || theme.site.siteIcon
let ogOption = {
type: is_post() ? 'article' : 'website',
image: coverVal ? full_url_for(coverVal) : '',
...theme.OpenGraph.options
}
-
!= open_graph(ogOption)
meta(name="description" content=page_description())
else
meta(name="description" content=page_description())
@@ -0,0 +1,10 @@
script#config-diff.
var PAGE_CONFIG = {
is_post: !{is_post()},
is_page: !{!is_post() && !is_home()},
is_home: !{is_home()},
page: '!{page.type}',
toc: !{!!page.toc},
comment: !{!!page.comment},
ai_text: !{is_post && page.ai_text ? "'"+ page.ai_text+"'" : false}
}
@@ -0,0 +1,22 @@
if theme.pwa.enable
meta(name="theme-color", content=theme.pwa.theme_color)
meta(name="apple-mobile-web-app-status-bar-style", content=theme.pwa.theme_color)
link(rel="manifest" href=url_for(theme.pwa.manifest))
if theme.pwa.theme_color
meta(name="msapplication-TileColor" content=theme.pwa.theme_color)
if theme.pwa.mask_icon
link(rel="mask-icon", href=url_for(theme.pwa.mask_icon), color=theme.pwa.theme_color)
if theme.pwa.apple_touch_icon
link(rel="apple-touch-icon" sizes="180x180" href=url_for(theme.pwa.apple_touch_icon))
if theme.pwa.favicon_16_16
link(rel="icon", type="image/png", sizes="16x16", href=url_for(theme.pwa.favicon_16_16))
if theme.pwa.favicon_32_32
link(rel="icon", type="image/png", sizes="32x32", href=url_for(theme.pwa.favicon_32_32))
if theme.pwa.bookmark_icon
link(rel="bookmark", href=url_for(theme.pwa.bookmark_icon))
else
meta(name="apple-mobile-web-app-capable", content=config.title)
meta(name="theme-color", content="var(--efu-main)")
meta(name="apple-mobile-web-app-status-bar-style", content="var(--efu-main)")
link(rel="bookmark", href=url_for(theme.site.siteIcon))
link(rel="apple-touch-icon", href=url_for(theme.site.siteIcon), sizes="180x180")
@@ -0,0 +1,4 @@
header#page-header(class=is_post() ? 'post-bg' : 'not-top-img')
include ./nav.pug
if is_post()
include ./widgets/post/postMeta.pug
@@ -0,0 +1,117 @@
- page.type = is_post() ? 'post' : page.type
mixin katex
if theme.katex.copytex
script(src=url_for(theme.cdn.katex_copytex))
script.
(() => {
document.querySelectorAll('#article-container span.katex-display').forEach(item => {
utils.wrap(item, 'div', {class: 'katex-wrap'})
})
})();
div
script(src=url_for(theme.cdn.utils))
script(src=url_for(theme.cdn.main))
script(src=url_for(theme.cdn.waterfall))
script(src=url_for(theme.cdn.pjax))
if theme.mermaid
script(src=url_for(theme.cdn.mermaid_js))
if theme.post.share.enable && theme.post.share.list && theme.post.share.list.includes('qrcode')
script(src=url_for(theme.cdn.qrcode))
if theme.display_mode.universe
script(src=url_for(theme.cdn.universe_js))
script.
dark()
if theme.right_menu.enable && theme.right_menu.translate.enable
script(src=url_for(theme.cdn.translate_js))
if theme.katex && theme.katex.enable
if theme.katex.per_page && (is_post() || is_page())
+katex
else if page.katex
+katex
if theme.lazyload.enable
script(src=url_for(theme.cdn.lazyload))
script(src=url_for(theme.cdn.snackbar))
if theme.lightbox
if theme.mediumZoom
script(src=url_for(theme.cdn.medium_zoom))
if theme.fancybox
script(src=url_for(theme.cdn.fancyapps_ui))
if (theme.says.home_mini && theme.says.enable) || theme.carousel
script(src=url_for(theme.cdn.swiper_js))
if theme.post_ai.enable
script(src=url_for(theme.cdn.efu_ai))
if theme.capsule.enable || theme.music.enable || theme.says.enable
script.
var meting_api = '!{theme.meting_api}';
script(src=url_for(theme.cdn.aplayer_js))
script(src=url_for(theme.cdn.meting_js))
if theme.post.covercolor.enable
case theme.post.covercolor.mode
when 'local'
script(src=url_for(theme.cdn.cover_local))
when 'api'
script.
const coverColorConfig = {
api: '!{theme.post.covercolor.api}',
time: !{theme.post.covercolor.time}
}
script(src=url_for(theme.cdn.cover_api))
if theme.loading.pace
script(src=url_for(theme.cdn.pace_js))
if theme.search.enable && theme.search.type === "algolia"
script(src=url_for(theme.cdn.instantsearch))
script(src=url_for(theme.cdn.algolia_search))
if theme.right_menu.enable
script(src=url_for(theme.cdn.right_menu_js))
if theme.extends.body
each item in theme.extends.body
!= item
.js-pjax
if is_home() && theme.says.enable && theme.says.home_mini
script.
sco.initbbtalk()
if page.type === 'says' && theme.says.enable
script.
GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll(".bber-content-img img"));
sco.changeTimeFormat(document.querySelectorAll('.bber-info-time time'))
if comment_js
include ../widgets/third-party/comments/js
if theme.mermaid
script.
mermaid.run();
if is_home() && theme.carousel && site.posts.data.filter(item => item.recommend === true).slice(0, 6) || false
script.
carousel_swiper()
if theme.busuanzi && (theme.aside.siteinfo.uv || theme.aside.siteinfo.pv)
if theme.busuanzi_use === 0
script(defer pjax src=url_for(theme.cdn.busuanzi_js))
else
script(defer pjax src=url_for(theme.cdn.busuanzi_qj_js))
if theme.footer.randomlink
include ../widgets/randomlink.pug
// pjax
!= partial("includes/widgets/third-party/pjax", {}, {cache: true})
// theme
include ../body/mode
// google adsense
include ../body/gadsense
@@ -0,0 +1,52 @@
each item in theme.verify_site || []
meta(name=item.name, content=item.content)
link(rel="canonical" href=urlNoIndex())
link(rel="stylesheet", href=url_for(theme.cdn.solitude_css))
// aplayer
if theme.capsule.enable || theme.music.enable
link(rel="stylesheet", href=url_for(theme.cdn.aplayer_css))
// swiper
if (theme.says.home_mini && theme.says.enable) || theme.carousel
link(rel="stylesheet", href=url_for(theme.cdn.swiper_css))
// fancybox ui
if theme.lightbox && theme.fancybox
link(rel="stylesheet", href=url_for(theme.cdn.fancyapps_css))
// katex
if theme.katex && theme.katex.enable
link(rel="stylesheet", href=url_for(theme.cdn.katex))
// Open Graph
include ../head/opengraph.pug
// pwa
include ../head/pwa.pug
script.
console.log(
"%c Program: Hexo %c Theme: Solitude %c Version: v1.12.2",
"border-radius:5px 0 0 5px;padding: 5px 10px;color:white;background:#ff3842;",
"padding: 5px 10px;color:white;background:#3e9f50;",
"padding: 5px 10px;color:white;background:#0084ff;border-radius:0 5px 5px 0",
)
if theme.memorial.enable
script.
let mdate = "!{theme.memorial.date}";
mdate = (mdate.split(","));
let ndate = new Date();
for (let i of mdate) {
if (i === (ndate.getMonth()+1) + "-" + (ndate.getDate())) {
document.documentElement.classList.add('memorial');
}
}
if theme.extends.head
each item in theme.extends.head
!= item
!=fragment_cache('injectHeadJs', function(){return inject_head_js()})
@@ -0,0 +1,65 @@
- const list = theme.keyboard.list || []
#keyboard-tips
.keyboardTitle=_p('keyboard.title')
.keyboardList
each item in list
.keyboardItem
.keyGroup
.key= 'Shift'
.key= item.key
.keyContent
.content= item.name
script.
const keyboard_addKeyup = (e) => {
if (e.key === 'Shift') {
document.getElementById('keyboard-tips').classList.remove('show');
}
}
const keyboard_addKeydown = (e) => {
const keyboards = !{JSON.stringify(list)};
if (e.keyCode === 16) {
document.getElementById('keyboard-tips').classList.add('show');
}
for (let i = 0; i < keyboards.length; i++) {
if (keyboards[i].url) {
if (keyboards[i].url.startsWith('http')) {
if (e.key === keyboards[i].key) {
window.open(keyboards[i].url);
}
} else {
if (e.key === keyboards[i].key) {
pjax.loadUrl(keyboards[i].url);
}
}
} else if (keyboards[i].sco) {
if (e.key === keyboards[i].key) {
sco[keyboards[i].sco]();
}
} else if (keyboards[i].func) {
if (e.key === keyboards[i].key) {
window[keyboards[i].func]();
}
}
}
}
function openKeyboard() {
window.addEventListener('keyup', keyboard_addKeyup);
window.addEventListener('keydown', keyboard_addKeydown);
}
function closeKeyboard() {
window.removeEventListener('keyup', keyboard_addKeyup);
window.removeEventListener('keydown', keyboard_addKeydown);
}
var sco_keyboards = localStorage.getItem('keyboard') === 'true'
if (sco_keyboards) {
openKeyboard();
document.getElementById('consoleKeyboard').classList.add('on');
}
@@ -0,0 +1,54 @@
- page.type = is_home() ? 'solitude' : page.type
doctype html
html(lang=config.language, data-theme="light")
head
include ./head.pug
body#body(data-type=page.type)
// universe
if theme.display_mode.universe
canvas#universe
// loading
if theme.loading.fullpage
include ./loading.pug
// console
include ./console.pug
// sidebar
include ./sidebar.pug
// keyboard
if theme.keyboard.enable
include ./keyboard.pug
#body-wrap(class = is_post() ? 'post' : 'page')
include ./header.pug
if(page.type !== '404')
block content
footer#footer
include ./footer.pug
else
.error#body-wrap
block content
// right_menu
if theme.right_menu.enable
include rightmenu
// inject body
include ./inject/body.pug
// search
include ./widgets/third-party/search/index.pug
// Tianli-Talk
if theme.tianli_talk.enable
include ./widgets/third-party/tianli-talk.pug
// music
if theme.capsule.enable
include ./widgets/third-party/music.pug
@@ -0,0 +1,25 @@
div(id="loading-box" onclick="preloader.endLoading();" style="zoom:1")
div.loading-bg
img.loading-img.nolazyload(src=url_for(theme.site.icon), alt="loading image")
script.
const preloader = {
endLoading: () => {
document.getElementById('loading-box').classList.toggle('loaded');
},
initLoading: () => {
document.getElementById('loading-box').classList.remove('loaded');
},
removePaceDone: () => {
document.getElementById('body').classList = 'pace-done';
}
}
window.addEventListener('load', () => {
preloader.endLoading();
});
window.addEventListener('pjax:send', () => {
preloader.initLoading();
});
document.addEventListener('pjax:complete', () => {
preloader.endLoading();
});
@@ -0,0 +1,14 @@
- let year
each post in page.posts.find({ parent: { $exists: false } }).data
if(year !== post.date.year())
- year = post.date.year()
.article-sort-item.year #{year}
.article-sort-item
a.article-sort-item-img(href=url_for(post.path) title=post.title)
img(src=post.cover alt=post.title)
.article-sort-item-info
a.article-sort-item-title(href=url_for(post.path) title=post.title onclick="window.event.cancelBubble=true;") #{post.title}
.article-sort-item-tags
each tags in post.tags.data
a.article-meta__tags(href=url_for(tags.path) onclick="window.event.cancelBubble=true;")
span.tags-punctuation #{tags.name}
@@ -0,0 +1,8 @@
nav#pagination
div.pagination
- var options = {mid_size: 1,escape: false,next_text: `<div class="pagination_tips_next">${_p("pagination.next")}</div> <i class="solitude st-arrow-right-bold"></i>`,prev_text: `<i class="solitude st-arrow-left-bold"></i> <div class="pagination_tips_prev">${_p("pagination.prev")}</div>`}
!=paginator(options)
div.toPageGroup
input#toPageText(oninput="value=value.replace(/[^0-9]/g,'')" maxlength="3" title=_p('pagination.to') onkeyup="if (this.value === '0') this.value = ''")
a#toPageButton(onclick="sco.toPage()")
i.solitude.st-show-right-line
+22
View File
@@ -0,0 +1,22 @@
nav#nav.show
#nav-group
#blog_name
if theme.nav.group
.back-home-button(tabindex="-1")
i.back-home-button-icon.solitude.st-more-fill
include ./widgets/nav/group
a#site-name(href=url_for("/"), title=_p('nav.site_name_title'))
if theme.site.name.class === 'i_class'
i.solitude(class=theme.site.name.custom, style="font-size: 16px;")
else if theme.site.name.class === 'img'
img(src=theme.site.name.custom, alt=config.title)
else if theme.site.name.class === 'text'
span.title= theme.site.name.custom
#page-name-mask
#page-name
a#page-name-text(onclick="sco.toTop()")= title || config.title
#menus
include ./widgets/nav/menu.pug
#nav-left
#nav-right
include ./widgets/nav/right.pug
@@ -0,0 +1,11 @@
if site.data.about
#about-page
include ../widgets/page/about/authorinfo
include ../widgets/page/about/contentinfo
include ../widgets/page/about/skillsinfo
include ../widgets/page/about/personalities
include ../widgets/page/about/motto
include ../widgets/page/about/hobbies
include ../widgets/page/about/other
include ../widgets/page/about/tenyear
include ../widgets/page/about/award
@@ -0,0 +1,8 @@
h1.page-title= _p('page.category')
.category-lists
.tag-cloud-list.is-center
each item in site.categories.find({ parent: { $exists: false } }).data
a(href=url_for(item.path))
span.tags-punctuation
= item.name
span.tagsPageCount= item.length
@@ -0,0 +1,2 @@
#article-container
!= page.content
@@ -0,0 +1,2 @@
include ../widgets/page/banner
include ../widgets/page/equipment/content
@@ -0,0 +1,14 @@
.flink#banners
include ../widgets/page/links/banner
.flink#article-container
each data in site.data.links.links
h2= data.class_name + " (" + data.link_list.length + ")"
.flink-desc= data.descr
case data.type
when 'card'
include ../widgets/page/links/linksCard
when 'item'
include ../widgets/page/links/linksItem
when 'discn'
include ../widgets/page/links/linksDiscn
!= page.content
@@ -0,0 +1,5 @@
- const { line,speed,hover,loop,enable } = theme.envelope
include ../widgets/page/message/content
if enable
include ../widgets/page/message/js
@@ -0,0 +1,11 @@
if theme.music.enable
#Music-bg
#Music-page
meting-js(id=theme.music.id server=theme.music.server type=theme.music.type mutex=theme.music.mutex ? "true" : "false" volume=theme.music.volume preload="none" data-lrctype="0" order="random")
.Music-loading
div APlayer加载中...
script(pjax).
(async function () {
if (typeof initializeMusicPlayer === "undefined") await utils.getScript('!{url_for(theme.cdn.music_js)}').then(() => initializeMusicPlayer())
else initializeMusicPlayer()
})()
@@ -0,0 +1,16 @@
- const { enable, limit, cache } = theme.recent_comments
- const {use, avatar} = theme.comment
include ../widgets/page/banner
if enable && use
#comments-page
case use[0]
when 'Twikoo'
include ../widgets/page/recentcomment/twikoo
when 'Valine'
include ../widgets/page/recentcomment/valine
when 'Waline'
include ../widgets/page/recentcomment/waline
when 'Artalk'
include ../widgets/page/recentcomment/artalk
@@ -0,0 +1,58 @@
include ../widgets/page/banner
if theme.says.enable
#bber
section.timeline.page-1
ul.list.waterfall
each item in site.data.essay.essay_list.slice(0, theme.says.strip)
li.item
if theme.says.style === 2
.meta
img.avatar(src=theme.aside.card.author.img)
.info
span.bber_nick= config.author
time.datetime.bber_date(datetime=moment(item.date).format())
if item.content
a.bber-reply.goComment(onclick=`sco.toTalk('${item.content}')`)
i.solitude.st-chat-fill
#bber-content
p.datacont= item.content
if item.image
.bber-content-img
each img in item.image
img(src=img alt="image")
if item.aplayer
.bber-music
meting-js(server=item.aplayer.server type="song" id=item.aplayer.id mutex="true" preload="none" theme="var(--efu-main)" data-lrctype="0")
if item.video
.bber-video
if item.video.player
video(src=item.video.player controls="controls" style="object-fit: cover;")
if item.video.bilibili
iframe(src='//player.bilibili.com/player.html?autoplay=0&bvid=' + item.video.bilibili scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true")
if theme.says.style === 1
hr
.bber-bottom
.bber-info
.bber-info-time
i.solitude.st-calendar-todo-fill
time.datetime(datetime=moment(item.date).format())
if item.location
.bber-info-location
i.solitude.st-map-pin-fill
| #{item.location}
if item.link
a.bber-content-link(href=url_for(item.link) target="_blank")
i.solitude.st-link-m-line
| 链接
if item.content
a.bber-reply(onclick=`sco.toTalk('${item.content}')`)
i.solitude.st-chat-fill
#bber-tips
if theme.says.strip === -1
| - 已展开所有短文 -
else
| - 只展示最近 #{theme.says.strip} 条短文 -
@@ -0,0 +1,8 @@
h1.page-title= __('page.tag')
.category-lists
.tag-cloud-list.is-center
each tag in site.tags.find({ parent: { $exists: false } }).data
a(href=url_for(tag.path))
span.tags-punctuation
= tag.name
span.tagsPageCount= tag.length
@@ -0,0 +1,13 @@
include ../widgets/page/banner
.flink#article-container
each data in site.data.tlink.links
h2= data.class_name + " (" + data.link_list.length + ")"
.flink-desc= data.descr
case data.type
when 'card'
include ../widgets/page/links/linksCard
when 'item'
include ../widgets/page/links/linksItem
when 'discn'
include ../widgets/page/links/linksDiscn
!= page.content
@@ -0,0 +1,80 @@
- let custom_list = theme.right_menu.custom_list || []
div#rightMenu
div.rightMenu-group.rightMenu-small
div.rightMenu-item#menu-backward
i.solitude.st-arrow-left-line
div.rightMenu-item#menu-forward
i.solitude.st-arrow-right-line
div.rightMenu-item#menu-refresh
i.solitude.st-restart-line
div.rightMenu-item#menu-top
i.solitude.st-arrow-up-line
div.rightMenu-group.rightMenu-line.rightMenuPlugin
div.rightMenu-item#menu-copytext
i.solitude.st-copy-fill
span= _p('right_menu.copy')
div.rightMenu-item#menu-pastetext
i.solitude.st-clipboard-fill
span= _p('right_menu.paste')
if theme.comment.use
div.rightMenu-item#menu-commenttext
i.solitude.st-chat-new-fill
span= _p('right_menu.comment')
div.rightMenu-item#menu-newwindow
i.solitude.st-window-fill
span= _p('right_menu.new')
div.rightMenu-item#menu-copylink
i.solitude.st-link-line
span= _p('right_menu.link')
div.rightMenu-item#menu-copyimg
i.solitude.st-copy-fill
span= _p('right_menu.img')
div.rightMenu-item#menu-downloadimg
i.solitude.st-download-cloud-fill
span= _p('right_menu.downloadImg')
if theme.search.enable
div.rightMenu-item#menu-search
i.solitude.st-search-line
span= _p('right_menu.search')
if theme.capsule.enable
div.rightMenu-item#menu-music-toggle
i.solitude.st-play-fill
span= _p('right_menu.music.start')
div.rightMenu-item#menu-music-back
i.solitude.st-skip-back-fill
span= _p('right_menu.music.back')
div.rightMenu-item#menu-music-forward
i.solitude.st-skip-forward-fill
span= _p('right_menu.music.forward')
div.rightMenu-item#menu-music-copyMusicName
i.solitude.st-copy-fill
span= _p('right_menu.music.copyMusicName')
div.rightMenu-group.rightMenu-line.rightMenuOther
each item,index in custom_list
div.rightMenu-item(id=item.id class=item.class onclick=item.click+'||rm.hideRightMenu()')
i.solitude(class=item.icon)
span= item.name
div.rightMenu-group.rightMenu-line.rightMenuOther
if theme.right_menu.commentBarrage && theme.comment.use && theme.comment.commentBarrage
div.rightMenu-item#menu-commentBarrage(onclick="sco.switchCommentBarrage()")
i.solitude.st-chat-fill
span.menu-commentBarrage-text= _p('right_menu.barrage.close')
div.rightMenu-item#menu-darkmode(onclick="sco.switchDarkMode()")
i.solitude.st-moon-clear-fill
case theme.display_mode.type
when 'auto'
when 'light'
span.menu-darkmode-text= _p('right_menu.light')
when 'dark'
span.menu-darkmode-text= _p('right_menu.dark')
if theme.right_menu.translate.enable
div.rightMenu-item#menu-translate
case theme.right_menu.translate.defaultEncoding
when 2
i.solitude.st-panben-line
span= _p('right_menu.chs_to_cht')
when 1
i.solitude.st-jianben-line
span= _p('right_menu.cht_to_chs')
div#rightmenu-mask
@@ -0,0 +1,32 @@
div#sidebar(style="zoom: 1;")
div#menu-mask(style="display: none;")
div#sidebar-menus
.site-data
.data-item.is-center
.data-item-link
a(href=url_for('/archives/'))
.headline=_p('page.archives')
.length-num=site.posts.find({ parent: { $exists: false } }).length
.data-item.is-center
.data-item-link
a(href=url_for('/categories/'))
.headline=_p('page.category')
.length-num=site.categories.find({parent: {$exists: false}}).length
.data-item.is-center
.data-item-link
a(href=url_for('/tags/'))
.headline=_p('page.tag')
.length-num=site.tags.find({parent: {$exists: false}}).length
span.sidebar-menu-item-title= __('sidebar.function')
div.sidebar-menu-item
span.darkmode_switchbutton.menu-child(onclick="sco.switchDarkMode()")
i.solitude.st-moon-clear-fill
span= __('sidebar.darkmode')
include ./widgets/nav/group
include ./widgets/nav/menu.pug
span.sidebar-menu-item-title= __('page.tag')
div.card-widget.card-tags.card-archives.card-webinfo.card-allinfo
div.card-tag-cloud
each tag in site.tags.find({ parent: { $exists: false } }).data
a(href=url_for(tag.path))= tag.name
sup= tag.length
@@ -0,0 +1,18 @@
.aside-content#aside-content
- var noSticky, Sticky
if(is_home())
- noSticky = theme.aside.home.noSticky.split(',')
- Sticky = theme.aside.home.Sticky.split(',')
else if(is_post())
- noSticky = theme.aside.post.noSticky.split(',')
- Sticky = theme.aside.post.Sticky.split(',')
else if(is_page() || is_archive() || is_tag() || is_category())
- noSticky = theme.aside.page.noSticky.split(',')
- Sticky = theme.aside.page.Sticky.split(',')
each item in noSticky
include ./asideSwitch.pug
.sticky_layout
if page.toc
include ./asideToc.pug
each item in Sticky
include ./asideSwitch.pug
@@ -0,0 +1,5 @@
if theme.google_adsense.enable && !theme.google_adsense.auto_ads && theme.google_adsense.aside_card
.card-widget.card-adsense
ins.adsbygoogle(style="display:block; text-align:center; min-height:120px; min-width: 100%", data-ad-layout="in-article", data-ad-format="fluid", hide-unfilled="true", data-ad-client=theme.google_adsense.client, data-ad-slot=theme.google_adsense.slot)
script.
(adsbygoogle = window.adsbygoogle || []).push({});
@@ -0,0 +1,8 @@
.card-widget.card-tags.card-archives.card-webinfo.card-allinfo
if theme.aside.tags.enable
include ./asideTag
hr
if theme.aside.archive.enable
include ./asideArchive
hr
include ./asideWebInfo
@@ -0,0 +1,11 @@
- var archive = theme.aside.archive
ul.card-archive-list
- var type = archive.type ? archive.type : 'year'
each value, key in getArchiveLength(type)
li.card-archive-list-item
a.card-archive-list-link(href=`/archives/${key}/`)
span.card-archive-list-date= key
.card-archive-list-count-group
span.card-archive-list-count= value
span.card-archive-list-count-unit= __('console.archive_unit')
@@ -0,0 +1,7 @@
.card-widget(class=custom.class, id=custom.id)
if !custom.no_head
.item-headline
i(class=custom.icon)
span=custom.title
div(class=custom.content_class ||'item-content', id=custom.content_id, style=custom.content_css)
!= custom.content_html
@@ -0,0 +1,5 @@
.card-widget.card-platform
#flip-wrapper
#flip-content
.face
.back.face
@@ -0,0 +1,86 @@
- const {style ,url} = theme.aside.card
.card-widget.card-info
.card-content
case style
when 0
.card-info-avatar.is-center
.author-info__top-group
.author-info__sayhi#author-info__sayhi(onclick="sco.changeSayHelloText()")= _p('sayhello.morning')
.avatar-img-group
img.avatar-img(alt=_p('aside.avatar'), src=theme.aside.card.author.img)
if theme.aside.card.author.sticker
.avatar-sticker
img.avatar-sticker-img(src=theme.aside.card.author.sticker, alt=_p('aside.sticker'))
.author-info__description_group
.author-info__description!= theme.aside.card.content
.author-info__description2!= theme.aside.card.content2
.author-info__bottom-group
a.author-info__bottom-group-left(href=url_for(theme.aside.card.url))
.author-info__name= config.author
.author-info__desc!= config.subtitle
.card-info-social-icons.is-center
each value, label in theme.aside.card.information || {}
- var array = value.split('||')
a.social-icon(href=url_for(trim(array[0])), title=label)
i.solitude(class=array[1])
when 1
.card-info-bg-top
.is-center
.author-info__top-group
.author-info__sayhi#author-info__sayhi(onclick="sco.changeSayHelloText()")= _p('sayhello.morning')
a.card-info-avatar(href=url_for(theme.aside.card.url) title=_p('aside.avatar'))
.avatar-img
img(src=theme.aside.card.author.img alt=_p('aside.avatar'))
if theme.aside.card.author.sticker
.avatar-sticker
img.avatar-sticker-img(src=theme.aside.card.author.sticker, alt=_p('aside.sticker'))
.card-info__desc_group
.author-info__name= config.author
.author-info__desc!= config.subtitle
.card-info__data.is-center
a(href=url_for('/archives/') title=_p('aside.card.posts') + site.posts.length)
.length-num= site.posts.length
.headline= _p('page.archives')
a(href=url_for('/tags/') title=_p('aside.card.tags') + site.tags.length)
.length-num= site.tags.length
.headline= _p('page.tag')
a(href=url_for('/categories/') title=_p('aside.card.categories') + site.categories.length)
.length-num= site.categories.length
.headline= _p('page.category')
.card-info-social-icons.is-center
each value, label in theme.aside.card.information || {}
- var array = value.split('||')
a.social-icon(href=url_for(trim(array[0])), title=label)
i.solitude(class=array[1])
when 2
.card-info-bg-top
.author-info-social
.social-icons
each value, label in theme.aside.card.information || {}
- var array = value.split('||')
a.social-icon(href=url_for(trim(array[0])), title=label)
i.solitude(class=array[1])
span.more-info(onclick="document.querySelector('.social-icons').classList.toggle('show')")
i.solitude.st-more-2-fill
a.card-info-avatar(href=url_for(theme.aside.card.url) title=_p('aside.avatar'))
.avatar-img
img(src=theme.aside.card.author.img alt=_p('aside.avatar'))
if theme.aside.card.author.sticker
.avatar-sticker
img.avatar-sticker-img(src=theme.aside.card.author.sticker, alt=_p('aside.sticker'))
.author-info__name= config.author
.card-info__data.is-center
a(href=url_for('/archives/') title=_p('aside.card.posts') + site.posts.length)
.length-num= site.posts.length
.headline= _p('page.archives')
a(href=url_for('/tags/') title=_p('aside.card.tags') + site.tags.length)
.length-num= site.tags.length
.headline= _p('page.tag')
a(href=url_for('/categories/') title=_p('aside.card.categories') + site.categories.length)
.length-num= site.categories.length
.headline= _p('page.category')
.card-info__desc_group
.author-info__description!= theme.aside.card.content
.author-info__description2!= theme.aside.card.content2
@@ -0,0 +1,16 @@
.card-widget.card-recent-post
.item-headline
i.solitude.st-map-line
span= _p('aside.newpost')
.aside-list
- let index = 1
each post in site.posts.data.sort((a, b) => b.date < a.date ? -1 : 1)
if index <= 5
.aside-list-item
a.thumbnail(href=url_for(post.path) title=post.title)
img(alt=post.title src=post.cover)
.content
a.title(href=url_for(post.path) title=post.title)= post.title
if post.categories.data[0]
a.article-recent_post_categories(href=url_for(post.path))= post.categories.data[0].name
- index++
@@ -0,0 +1,9 @@
.card-widget.card-recent-comment
.item-headline
i.solitude.st-chat-fill
span= _p('aside.newcomment')
if theme.recent_comments.enable
a.recent-comment-more(href=url_for(theme.recent_comments.page) title=_p('console.recent_comment_more'))
i.solitude.st-right-btn-fill
.aside-list
include ../third-party/news-comment/newest-comment.pug
@@ -0,0 +1,19 @@
case item
when 'about'
include ./asideInfoCard.pug
when 'flip'
include ./asideFlipCard.pug
when 'newestPost'
include ./asideNewestPost.pug
when 'allInfo'
include ./asideAllInfo.pug
when 'ads'
include ./asideAdsense.pug
when 'newest_comment'
include ./asideNewstComments.pug
default
- const custom = site.data?.aside?.find((i) => i.name === item)
if custom
include ./asideCustom.pug
else
include ../../page/default.pug
@@ -0,0 +1,16 @@
- const highlight = theme.aside.tags.highlight_list || []
.card-tag-cloud
each tag in site.tags.find({ parent: { $exists: false } }).data
if highlight.includes(tag.name)
a.highlight(href=url_for(tag.path))= tag.name
sup= tag.length
else
a(href=url_for(tag.path))= tag.name
sup= tag.length
if site.tags.length >= theme.aside.tags.limit
span#more-tags-btn(onclick="sco.openAllTags()")= __('aside.tagmore')
else
style.
.card-tag-cloud::after {
display: none !important;
}
@@ -0,0 +1,5 @@
.card-widget#card-toc
.item-headline
i.solitude.st-menu-line
span= __('aside.toc')
.toc-content#toc-content!= toc(page.content, { list_number: false })
@@ -0,0 +1,48 @@
.webinfo
if theme.aside.siteinfo.postcount
.webinfo-item
.webinfo-item-title
i.item-icon.solitude.st-folder-fill
.item-name= __('aside.postcount')
.item-count= site.posts.length
if theme.busuanzi
if theme.aside.siteinfo.pv
.webinfo-item
.webinfo-item-title
i.item-icon.solitude.st-visitor-line
.item-name= __('aside.pv')
if theme.busuanzi_use === 0
span#busuanzi_value_site_pv
i.solitude.st-loading-line
else
span#busuanzi_site_pv
i.solitude.st-loading-line
if theme.aside.siteinfo.uv
.webinfo-item
.webinfo-item-title
i.item-icon.solitude.st-team-fill
.item-name= __('aside.uv')
if theme.busuanzi_use === 0
span#busuanzi_value_site_uv
i.solitude.st-loading-line
else
span#busuanzi_site_uv
i.solitude.st-loading-line
if theme.aside.siteinfo.runtimeenable
.webinfo-item
.webinfo-item-title
i.item-icon.solitude.st-calendar-todo-fill
.item-name= __('aside.runtime')
.item-count#runtimeshow
if theme.aside.siteinfo.updatetime
.webinfo-item
.webinfo-item-title
i.item-icon.solitude.st-loop-left-fill
.item-name= __('aside.updatetime')
time.item-count(datetime=new Date())
if theme.wordcount && theme.aside.siteinfo.wordcount
.webinfo-item
.webinfo-item-title
i.item-icon.solitude.st-word-fill
.item-name= __('aside.wordcount')
.item-count= totalcount(site)
@@ -0,0 +1,23 @@
div.banners-title
div.banners-title-big!= theme.hometop.banner.title
div.banners-title-small= theme.hometop.banner.url
- var group = theme.hometop.group
if group
div.banners-links
each value,label in group
- var array = value.split('||')
a.banners-link-btn(href=url_for(trim(array[0])) style=`background-image: ${array[2]} `)
if array[1]
i.solitude(class=array[1])
.banners-link-title= label
div.tags-group-all
.tags-group-wrapper
each i in [1,2]
- var keys = Object.keys(theme.hometop.banner.icon)
- var pairs = keys.map((val, i) => i % 2 ? [keys[i - 1], val] : []).filter(x => x.length)
each pair in pairs
.tags-group-icon-pair
each key in pair
.tags-group-icon(style=`background: ${theme.hometop.banner.icon[key].color}`)
img.nolazyload(src=theme.hometop.banner.icon[key].img, title=key)
@@ -0,0 +1,18 @@
.bbTimeList.container#bbTimeList(class=is_home_first_page() ? '' : 'more-page')
i.bber-logo.solitude.st-bblogo(onclick=`pjax.loadUrl('/essay/')`)
.swiper-container.swiper-no-swiping.swiper-container-initialized.swiper-container-vertical.swiper-container-pointer-events#bbtalk(tabindex="-1" onclick=`pjax.loadUrl('/essay/')`)
.swiper-wrapper#bber-talk
each item, i in site.data.essay.essay_list.slice(0, 10)
.li-style.swiper-slide
| #{item.content}
if item.image
i.solitude.st-image-fill
else if item.aplayer
i.solitude.st-disc-fill
else if item.video
i.solitude.st-video-fill
else if item.bilibili
i.solitude.st-bilibili-line
else if item.link
i.solitude.st-links
i.bber-gotobb.solitude.st-right-btn-fill(title=_p('home.bbtime.text') onclick=`pjax.loadUrl('/essay/')`)
@@ -0,0 +1,72 @@
- let recommends = site.posts.data.filter(item => item.recommend === true).slice(0,6) || false
if recommends
.recent-post-item#swiperBox
div.blog-slider.swiper-container-fade.swiper-container-horizontal#swiper_container
.blog-slider__wrp.swiper-wrapper
each item,index in recommends
.blog-slider__item.swiper-slide(onclick="pjax.loadUrl('"+item.path+"')")
.blog-slider__img
img(src=item.cover, alt=item.title)
.blog-slider__content
span.blog-slider__title=item.title
case theme.index_post_list.content
when false
break
when 1
span.blog-slider__desc= item.description
when 2
if item.description
span.blog-slider__desc= item.description
else
- const content = strip_html(item.content)
- let expert = content.substring(0, theme.index_post_list.length).replace(/\d+/g, '').replace(/&#xF/g, '').replace(/&#x/g, '')
- content.length > theme.index_post_list.length ? expert += ' ...' : ''
.span.blog-slider__desc= expert
default
- const content = strip_html(item.content)
- let expert = content.substring(0, theme.index_post_list.length).replace(/\d+/g, '').replace(/&#xF/g, '').replace(/&#x/g, '')
- content.length > theme.index_post_list.length ? expert += ' ...' : ''
.span.blog-slider__desc= expert
div.article-meta-wrap
span.article-meta.tags
each tag in item.tags.data
a.article-meta__tags(href=url_for(tag.path), onclick="event.stopPropagation();")
span.tags-punctuation=tag.name
span.post-meta-date
time(datetime=moment(item.date))
.blog-slider__pagination.swiper-pagination-clickable.swiper-pagination-bullets
script.
function carousel_swiper() {
let e = new Swiper(".blog-slider", {
direction: "vertical",
passiveListeners: true,
loop: true,
autoplay: {
disableOnInteraction: true,
delay: 5e3
},
pagination: {
el: ".blog-slider__pagination",
clickable: true
},
effect: 'fade',
fadeEffect: {
crossFade: true
},
passiveListeners: true,
spaceBetween: 30,
watchSlidesProgress: true,
mousewheel: true
})
, t = document.getElementById("swiper_container");
null !== t && (t.onmouseenter = () => {
e.autoplay.stop()
}
,
t.onmouseleave = () => {
e.autoplay.start()
}
)
}
@@ -0,0 +1,15 @@
.category-bar-items#category-bar-items(class=is_home() ? 'home' : '')
.category-bar-item(class=is_home() ? 'select' : '', id="category-bar-home")
a(href=url_for('/'))= __('home.home')
.category-bar-item
a(href=url_for('/archives/'))= __('home.archives')
each item in site.categories.find({ parent: { $exists: false } }).data
.category-bar-item(class=select ? (select === item.name ? 'select' : '') : '', id=item.name)
a(href=url_for(item.path))= item.name
div.category-bar-right
- let categories = site.categories.find({parent: {$exists: false}})
- let wordcount = categories.map(category => category.name).join('').length
if wordcount > 40 || categories.data.length > 10
.category-bar-next#category-bar-next(onclick="sco.scrollCategoryBarToRight()")
i.solitude.st-show-right-line
a.category-bar-more(href=url_for('/categories/'))= __('more')
@@ -0,0 +1,7 @@
.recent-top-post-group#recent-top-post-group
.recent-post-top#recent-post-top
#bannerGroup
#banners
include ./banner.pug
.topGroup
include ./topGroup.pug
@@ -0,0 +1,81 @@
mixin cover
a(href=url_for(post.path), title=post.title)
img.post_bg(src=url_for(post.cover), alt=post.title)
mixin info
div.recent-post-info-top
div.recent-post-info-top-tips
if post.sticky && is_home()
span.article-meta.sticky-warp
i.solitude.st-thumbtack-solid.sticky.orange
span.sticky.orange= _p('home.sticky')
each category in post.categories.data
span.original= category.name
if post.prev == null && is_home()
span.original= _p('home.new')
a.unvisited-post(href=url_for(post.path))= _p('home.read')
a.article-title(href=url_for(post.path), title=post.title)= post.title
case theme.index_post_list.content
when false
break
when 1
.content!= post.description
when 2
if post.description
.content!= post.description
else
- const content = strip_html(post.content)
- let expert = content.substring(0, theme.index_post_list.length).replace(/\d+/g, '').replace(/&#xF/g, '').replace(/&#x/g, '')
- content.length > theme.index_post_list.length ? expert += ' ...' : ''
.content!= expert
default
- const content = strip_html(post.content)
- let expert = content.substring(0, theme.index_post_list.length).replace(/\d+/g, '').replace(/&#xF/g, '').replace(/&#x/g, '')
- content.length > theme.index_post_list.length ? expert += ' ...' : ''
.content!= expert
div.article-meta-wrap
span.article-meta.tags
each tag in post.tags.data
a.article-meta__tags(href=url_for(tag.path), onclick="event.stopPropagation();")
span.tags-punctuation=tag.name
span.post-meta-date
time(datetime=moment(post.date))
- const { direction, cover } = theme.index_post_list
if direction === 'row'
- var position = cover === 'both' ? index % 2 === 0 ? 0 : 1 : cover === 'left' ? 0 : 1
div.recent-post-item(onclick="pjax.loadUrl('" + url_for(post.path) + "')")
if direction === 'column'
div.post_cover
+cover()
div.recent-post-info
+info()
else
case position
when 0
div.post_cover
+cover()
div.recent-post-info
+info()
when 1
div.recent-post-info
+info()
div.post_cover
+cover()
if theme.google_adsense && theme.google_adsense.enable && theme.google_adsense.auto_ads === false && theme.google_adsense.post_card
- var ads_height = theme.index_post_list.direction === 'column' ? '401px;' : '280px;'
if (index + 1) % 3 === 0
div.recent-post-item.google-ads-warp
ins.adsbygoogle(style="display:block; text-align:center; min-width: 100%; height:" + ads_height, data-ad-layout="in-article", data-ad-format="fluid", hide-unfilled="true", data-ad-client=theme.google_adsense.client, data-ad-slot=theme.google_adsense.slot)
script.
(adsbygoogle = window.adsbygoogle || []).push({});
@@ -0,0 +1,32 @@
- var filteredPosts = site.posts.data.filter(item => item.recommend === true).slice(0,6)
.recent-post-group
each post in filteredPosts
.recent-post-item
.post_cover
a(href=url_for(post.path), title=post.title)
span.recent-post-top-text= _p('home.recommend')
img.post_bg(alt=post.title, src=post.cover)
.recent-post-info
a.article-title(href=url_for(post.path), title=post.title)= post.title
mixin todayCardContent
.todayCard-info
.todayCard-tips= theme.hometop.recommendList.sup
.todayCard-title= theme.hometop.recommendList.title
.todayCard-cover.nolazyload(style=`background: url('${theme.hometop.recommendList.img}') no-repeat center /cover`)
.banner-button-group
a.banner-button(onclick="window.event.cancelBubble=true;sco.hideTodayCard();")
i.solitude.st-add-fill
span.banner-button-text= _p('home.recommendmore')
case theme.hometop.recommendList.url.startsWith('/')
when true
.todayCard#todayCard(onclick=`pjax.loadUrl('${theme.hometop.recommendList.url}')`)
+todayCardContent()
when false
script.
function GoTodayCard() {
window.open("#{theme.hometop.recommendList.url}", "_blank");
}
.todayCard#todayCard(onclick="GoTodayCard()")
+todayCardContent()
@@ -0,0 +1,13 @@
- var menu = theme.nav.group
if menu
.back-menu-list-groups
each value, label in menu
.back-menu-list-group
.back-menu-list-title= label
.back-menu-list
each data, label in value
- var array = data.split('||')
a.back-menu-item(href=url_for(trim(array[0])), title=label)
if array[1]
img.nolazyload.back-menu-item-icon(src=trim(array[1]), alt=label)
span.back-menu-item-text= label
@@ -0,0 +1,20 @@
- var menu = theme.nav.menu
if menu
.menus_items
each value, label in menu
.menus_item
if typeof value !== 'object'
a.site-page(href=url_for(value))
span= label
else
a.site-page(href="javascript:void(0);")
span= label
ul.menus_item_child
each childValue, childLabel in value
li
- var array = childValue.split('||')
a.site-page.child(href=url_for(trim(array[0])))
if array[1]
i.solitude(class=array[1])
span= childLabel
@@ -0,0 +1,24 @@
- var custom = theme.nav.right.custom || []
each item in custom
.nav-button(id=item.id)
a.site-page(href=url_for(item.url) || 'javascript:void(0);', onclick=item.onclick, title=item.title || '')
i.solitude(class=item.icon || '')
if theme.nav.right.random
.nav-button#randomPost_button
a.site-page(onclick="toRandomPost()", title=_p('nav.randompost'), href="javascript:void(0);")
i.solitude.st-dice-line
if theme.search.enable
.nav-button#search-button
a.site-page.social-icon.search(href="javascript:void(0);", title=_p('nav.search'))
i.solitude.st-search-line
if theme.nav.right.console
.nav-button#nav-console
a.console_switchbutton(onclick="sco.showConsole()", title=_p('nav.console'), href="javascript:void(0);")
i.solitude.st-dashboard-fill
.nav-button#nav-totop(onclick="sco.toTop()")
a.totopbtn
i.solitude.st-arrow-up-line
span#percent= "0"
#toggle-menu
a.site-page
i.solitude.st-menu-line
@@ -0,0 +1,13 @@
- const authorinfo = site.data.about.authorinfo
if authorinfo
.author-info
.author-tag-left
each tag in authorinfo.leftTags
span.author-tag= tag
.author-img
img(src=authorinfo.image)
.author-tag-right
each tag in authorinfo.rightTags
span.author-tag= tag
.author-title= site.data.about.title
@@ -0,0 +1,39 @@
- award = site.data.about.award
- var sum = 0
if site.data.about.rewardList
.author-content
.author-content-item.single.reward
.author-content-item-tips= _p('award.thanks')
span.author-content-item-title= _p('award.title')
.author-content-item-description
!= award.description
.reward-list-all
each reward in site.data.about.rewardList
- sum += reward.money
.reward-list-item
.reward-list-item-name= reward.name
.reward-list-bottom-group
.reward-list-item-money(style=(reward.vip ? "background: var(--efu-vip);color: var(--efu-white)" : ""))
if reward.icon
i.solitude(class=reward.icon)
| ¥ #{reward.money}
time.datatime.reward-list-item-time(datetime=moment(reward.time).format())
if theme.post.award.enable
.post-reward
.post-reward(onclick="AddRewardMask()")
.reward-button(title=_p('award.tipping'))
i.solitude.st-hand-heart-fill
= _p('award.tipping')
.reward-main
ul.reward-all
span.reward-title= theme.post.award.title
ul.reward-group
- var rewards = theme.post.award.list
each reward in rewards
li.reward-item
a(href=url_for(reward.url))
img.post-qr-code-img(alt=reward.name, src=reward.qcode, style="border-color:" + reward.color)
.post-qr-code-desc= reward.name
.reward-list-tips
p= award.tips.replace('{sum}', sum.toFixed(2))
@@ -0,0 +1,39 @@
- const contentinfo = site.data.about.contentinfo
if contentinfo
.author-content
.author-content-item.myInfoAndSayHello
.title1= contentinfo.sup
.title2
span.inline-word= contentinfo.name
.title1= contentinfo.title
.aboutsiteTips.author-content-item
.author-content-item-tips= contentinfo.tip
h2
span.inline-word!= contentinfo.slogan
.mask
each item,index in contentinfo.mask
if index === 0
span.first-tips(data-show='')= item
else if index === contentinfo.mask.length - 1
span(data-up='')= item
else
span= item
script.
var pursuitInterval = null;
pursuitInterval = setInterval(function () {
const show = document.querySelector('span[data-show]')
const next = show.nextElementSibling || document.querySelector('.first-tips')
const up = document.querySelector('span[data-up]')
if (up) {
up.removeAttribute('data-up')
}
show.removeAttribute('data-show')
show.setAttribute('data-up', '')
next.setAttribute('data-show', '')
}, 2000)
document.addEventListener('pjax:send', function () {
clearInterval(pursuitInterval);
});
@@ -0,0 +1,37 @@
- var game1 = site.data.about.game1
- var game2 = site.data.about.game2
if game1 || game2
.author-content
if game1
.author-content-item.game-apex(style=`background: url(${game1.img}) no-repeat top; background-size: cover;`)
.card-content
.author-content-item-tips= game1.title
span.author-content-item-title= game1.subtitle
.content-bottom
.tips= game1.tips_left
.tips= game1.tips_right
if game2
.author-content-item.game-jl(style=`background: url(${game2.img}) no-repeat top; background-size: cover;`)
.card-content
.author-content-item-tips= game2.title
span.author-content-item-title= game2.subtitle
.content-bottom
.tips= game2.tips_left
.tips= game2.tips_right
if site.data.about.likes
- const likes = site.data.about.likes
.author-content
each like in likes
.author-content-item(class=like.type, style=`background: url(${like.bg}) no-repeat center;`)
.card-content
.author-content-item-tips= like.tips
span.author-content-item-title= like.title
.content-bottom
.tips= like.subtips
if like.button
.banner-button-group
a.banner-button(href=url_for(like.button_link))
i.solitude.st-right-btn-fill
span.banner-button-text= like.button_text
@@ -0,0 +1,22 @@
- const motto = site.data.about.motto
- const expertise = site.data.about.expertise
if motto || expertise
.author-content
if motto
.author-content-item.maxim
.author-content-item-tips= motto.title
span.maxim-title
span= motto.prefix
span= motto.content
if expertise
.author-content-item.buff
.card-content
.author-content-item-tips= expertise.title
span.buff-title
span
| #{expertise.prefix}
span.inline-word= expertise.specialist
span
| #{expertise.content}
span.inline-word= expertise.level
@@ -0,0 +1,89 @@
- var tj = site.data.about.tj
- var oneself = site.data.about.oneself
if tj || oneself
.author-content
if tj
.about-statistic.author-content-item(style=`background: url(${tj.img});`)
.card-content
.author-content-item-tips=_p('about.other.tj.tip')
span.author-content-item-title=_p('about.other.tj.title')
#statistic
.post-tips
= _p('about.other.tj.post_tip')
case tj.provider
when '51la'
a(href="https://v6.51.la/") 51la网站统计
when 'baidu'
a(href="https://tongji.baidu.com/") 百度统计
if tj.button
.banner-button-group
a.banner-button(href=url_for(tj.button_link))
i.solitude.st-right-btn-fill
span.banner-button-text= tj.button_text
case tj.provider
when '51la'
script.
fetch("#{tj.url}")
.then(res => res.text())
.then(data => {
const title = ["最近活跃", "今日人数", "今日访问", "昨日人数", "昨日访问", "本月访问", "总访问量"];
let num = data.match(/(<\/span><span>).*?(\/span><\/p>)/g);
num = num.map(el => {
let val = el.replace(/(<\/span><span>)/g, "");
return val.replace(/(<\/span><\/p>)/g, "");
});
const s = document.getElementById("statistic");
let html = '';
for (let i = 0; i < num.length; i++) {
if (i === 0 || i === num.length - 1) continue;
html += `<div><span>${title[i]}</span><span id="${title[i]}">${num[i]}</span></div>`;
}
s.innerHTML = html;
});
when 'baidu'
script.
fetch("#{tj.url}")
.then(res => res.json())
.then(data => {
const title = {"today_uv": "今日人数", "today_pv": "今日访问", "yesterday_uv": "昨日人数", "yesterday_pv": "昨日访问", "last_month_pv": "最近月访问", "last_year_pv": "最近年访问"};
let s = document.getElementById("statistic");
for (let key in data) {
if (data.hasOwnProperty(key) && title[key]) {
s.innerHTML += `<div><span>${title[key]}</span><span id="${key}">${data[key]}</span></div>`;
}
}
});
if oneself
style.
:root {
--site-about-oneself-map--light: url(#{oneself.map.light});
--site-about-oneself-map--dark: url(#{oneself.map.dark});
}
.author-content-item-group.column.mapAndInfo
.author-content-item.map.single
span.map-title=_p('about.other.oneself.map_title') + oneself.location
.author-content-item.selfInfo.single
div
span.selfInfo-title=_p('about.other.oneself.info_title1')
span.selfInfo-content(style="color: #43a6c6;")= oneself.birthYear
div
span.selfInfo-title= oneself.university
span.selfInfo-content(style="color: #c69043;")= oneself.major
div
span.selfInfo-title=_p('about.other.oneself.info_title2')
span.selfInfo-content(style="color: #b04fe6;")= oneself.occupation
- var cause = site.data.about.cause
if cause
.author-content
.create-site-post.author-content-item.single
.author-content-item-tips= cause.tip
span.author-content-item-title= cause.title
!= cause.content
@@ -0,0 +1,17 @@
- const personalities = site.data.about.personalities
if personalities
.author-content
.author-content-item.personalities
.author-content-item-tips= personalities.tips
span.author-content-item-title= personalities.title
.title2(style=`color:${personalities.color}`)= personalities.type
.image
img.nolazyload(src=personalities.image)
.post-tips
= _p('about.personalities.tip1') + ' '
a(href='https://www.16personalities.com/')= personalities.linkText + ' '
= _p('about.personalities.tip2') + ' '
a(href=personalities.typeLink)= personalities.typeName
.author-content-item.myphoto
img.author-content-img(src=personalities.myphoto, alt="my photo")
@@ -0,0 +1,42 @@
- var skills = site.data.about.skills
- var careers = site.data.about.careers
if skills || careers
.author-content
if skills
.author-content-item.skills
.card-content
.author-content-item-tips= skills.title
span.author-content-item-title= skills.subtitle
.skills-style-group
.tags-group-all
.tags-group-wrapper
each i in [1,2]
- var pair = []
each tag, index in skills.tags
- pair.push(tag)
if pair.length === 2 || index === skills.tags.length - 1
.tags-group-icon-pair
each item in pair
.tags-group-icon(style=`background:${item.color}`)
img(src=item.icon, title=item.title)
- pair = []
.skills-list
each tag in skills.tags
.skill-info
.skill-icon(style=`background:${tag.color}`)
img(src=tag.icon, title=tag.title)
.skill-name
span= tag.title
.etc ...
if careers
.author-content-item.careers
.card-content
.author-content-item-tips= careers.title
span.author-content-item-title= careers.subtitle
.careers-group
each item in careers.items
.careers-item
.circle(style=`background:${item.color}`)
.name= `${item.school}, ${item.major}`
img.author-content-img(src=careers.image, alt=careers.title)
@@ -0,0 +1,48 @@
- var tenyear = site.data.about.tenyear
if tenyear
.author-content#tenyear
.create-site-post.author-content-item.single
.author-content-item-tips=tenyear.tips
.author-content-item-title=tenyear.title
p=tenyear.text
.tenyear-timeline
.progress
.past-time
.percentage-label
.time-labels
.start-time#tenyear-start-time= tenyear.start
.end-time#tenyear-end-time= tenyear.end
script.
function parseDateString(e) {
return e.replace(/年|月/g, '-').replace(/日/g, '');
}
function tenYear() {
let progressElement = document.querySelector(".progress");
let pastTimeElement = document.querySelector(".past-time");
let percentageLabelElement = document.querySelector(".percentage-label");
let startTimeElement = document.getElementById("tenyear-start-time");
let endTimeElement = document.getElementById("tenyear-end-time");
let startTime = new Date(parseDateString(startTimeElement.textContent)).getTime();
let endTime = new Date(parseDateString(endTimeElement.textContent)).getTime();
function updateProgress() {
let currentTime = new Date().getTime();
let progress = ((currentTime - startTime) / (endTime - startTime) * 100);
let progressPercentage = progress <= 100 ? progress + "%" : "100%";
pastTimeElement.style.setProperty("--past-time-percentage", progress + "%");
progressElement.style.setProperty("--progress-percentage", progressPercentage);
if(progress > 5){
percentageLabelElement.textContent = `${progress.toFixed(0)}%`;
percentageLabelElement.style.left = `calc(${progress}% - 35px)`;
}
}
percentageLabelElement.style.visibility = "visible";
updateProgress();
}
document.getElementById("tenyear") && tenYear() && window.Pjax.on('complete', tenYear)
@@ -0,0 +1,15 @@
.author-content.author-content-item.single.sharePage(style=`background: url(${page.cover}) no-repeat center; background-size: cover;`)
.card-content
.author-content-item-tips= page.desc
span.author-content-item-title= page.title
.content-bottom
if page.leftend
.tips= page.leftend
if page.rightend
.tips= page.rightend
if page.rightbtn
.banner-button-group
- const isInternalLink = page.rightbtnlink.startsWith('/')
a.banner-button(onclick=isInternalLink ? `pjax.loadUrl("${page.rightbtnlink}")`: null, href=isInternalLink ? null : url_for(page.rightbtnlink), target=isInternalLink ? null : "_blank")
i.solitude.st-right-btn-fill
span.banner-button-text= page.rightbtn
@@ -0,0 +1,23 @@
#equipment
if site.data.equipment
each i in site.data.equipment
.equipment-item
h2.equipment-item-title= i.class_name
.equipment-item-description= i.description
.equipment-item-content
each item in i.equipment_list
.equipment-item-content-item
.equipment-item-content-item-cover
img.equipment-item-content-item-image(src=item.image, alt=item.name)
.equipment-item-content-item-info
.equipment-item-content-item-name(onclick='utils.copy("' + item.name + '")')= item.name
.equipment-item-content-item-specification= item.specification
.equipment-item-content-item-description= item.description
if item.link
.equipment-item-content-item-toolbar
if item.link.includes('https://') || item.link.includes('http://')
a.equipment-item-content-item-link(href=item.link, target="_blank") 详情
else
a.equipment-item-content-item-link(href=item.link, target="_blank") 查看文章
a.bber-reply(onclick=`sco.toTalk('${item.description}')`)
i.solitude.st-chat-fill(style="font-size: 1rem;")
@@ -0,0 +1,31 @@
.banners-title
.banners-title-small= page.title
.banners-title-big= page.desc
.banner-button-group
if theme.footer.randomlink
a.banner-button.secondary(onclick="travelling()")
i.solitude.st-signal-tower-fill
span.banner-button-text=_p('link.banner.random')
if theme.comment.use
a.banner-button(onclick="sco.scrollToComment()")
i.solitude.st-right-btn-fill
span.solitude.banner-button-text=_p('link.banner.toComment')
.tags-group-all.nowrapMove
.tags-group-wrapper
- const data = site.data.links.links
- for (let i = 0; i < 2; i++)
each x in data
if x.type === "item"
- var pairs = []
each y, index in x.link_list
if (index % 2 === 0)
- pairs.push([y])
else
- pairs[pairs.length - 1].push(y)
each pair in pairs
.tags-group-icon-pair
each y in pair
a.tags-group-icon(href=url_for(y.link), title=y.name)
img(src=y.avatar + (site.data.links.banner_suffix || ''), title=y.name)
@@ -0,0 +1,15 @@
.site-card-group
each item in data.link_list
.site-card
if item.tag
span.site-card-tag(class=item.color)= item.tag
i.light
a.img(title=item.name, href=url_for(item.link))
img.flink-avatar(src=item.topimg + (data.topimg_suffix || ''), alt=item.name)
a.info.cf-friends-link(title=item.name, href=url_for(item.link))
.site-card-avatar
img.flink-avatar.cf-friends-avatar(src=item.avatar + (data.suffix || ''), alt=item.name)
.img-alt.is-center= item.name
.site-card-text
span.title.cf-friends-name= item.name
span.desc(title=item.descr)= item.descr
@@ -0,0 +1,8 @@
.flink-list.cf-friends-lost-contact.mini
each item in data.link_list
.flink-list-item
a.cf-friends-link(href="javascript:void(0);", title=item.name)
img.flink-avatar.cf-friends-avatar(alt=item.name, src=item.avatar + (data.suffix || ''))
.flink-item-info
span.flink-item-name.cf-friends-name= item.name
span.flink-item-desc(title=item.descr)= item.descr
@@ -0,0 +1,11 @@
.flink-list
each item in data.link_list
.flink-list-item
if item.tag
span.site-card-tag(class=item.color)= item.tag
i.light
a.cf-friends-link(href=url_for(item.link), title=item.name)
img.flink-avatar.cf-friends-avatar(alt=item.name, src=item.avatar + (data.suffix || ''))
.flink-item-info
span.flink-item-name.cf-friends-name= item.name
span.flink-item-desc(title=item.descr)= item.descr
@@ -0,0 +1,45 @@
- const { server, site, option } = theme.artalk
script(pjax).
(async () => {
const emojiReg = /<img [^>]+ atk-emoticon="[^"]+">/g
if (typeof EasyDanmaku === "undefined") await utils.getScript('!{url_for(theme.cdn.envelope_js)}')
const envel = new EasyDanmaku({
page: '!{theme.envelope.page}',
el: '#barrage',
line: !{line},
speed: !{speed},
hover: !{hover},
loop: !{loop},
})
const data = utils.saveToLocal.get('enevlope')
if (data) {
envel.batchSend(data, true)
return
}
const searchParams = new URLSearchParams({'site_name': "!{site}", 'limit': '100'})
await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`, {method: 'GET'}).then(async res => res.json())
.then(async data => {
let ls = []
for (const i of data.data) {
ls.push({
content: i.nick + ': ' + formatDanmaku(i.content),
avatar: '!{avatar}' + '/avatar/' + i.email_encrypted,
url: i.page_key + '#atk-comment-' + i.id,
})
}
envel.batchSend(ls, true)
utils.saveToLocal.set('enevlope', ls, .02)
}).catch(error => {
console.error("An error occurred while fetching comments: ", error)
})
function formatDanmaku(str) {
str = str.replace(emojiReg, '[!{__("console.newest_comment.emoji")}]')
str = str.replace(/!\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.image")}]')
str = str.replace(/\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.link")}]')
str = str.replace(/```.*?```/g, '[!{__("console.newest_comment.code")}]')
return str
}
})()
@@ -0,0 +1,9 @@
#article-container
!= page.content
if theme.envelope.enable
.switch_message
button.open(type='button' onclick="document.getElementById('barrage').classList.remove('hide')")
span(aria-hidden='true')= __('message.open')
button.close(type='button' onclick="document.getElementById('barrage').classList.add('hide')")
span(aria-hidden='true')= __('message.close')
#barrage
@@ -0,0 +1,12 @@
- const {use,avatar} = theme.comment
if use
case use[0]
when "Valine"
include ./valine
when "Twikoo"
include ./twikoo
when "Waline"
include ./waline
when "Artalk"
include ./artalk
@@ -0,0 +1,47 @@
- const {envId} = theme.twikoo
script(pjax).
(async () => {
const emojiReg = /<img class="tk-owo-emotion" [^>]+>/g
if (typeof EasyDanmaku === "undefined") await utils.getScript('!{url_for(theme.cdn.envelope_js)}')
const Danmaku = new EasyDanmaku({
page: '!{theme.envelope.page}',
el: '#barrage',
line: !{line},
speed: !{speed},
hover: !{hover},
loop: !{loop},
})
const data = utils.saveToLocal.get('enevlope')
if (data) {
Danmaku.batchSend(data, true)
return
}
let ls = []
fetch('!{envId}/', {
method: "POST",
body: JSON.stringify({
"event": "GET_RECENT_COMMENTS",
"includeReply": false,
"pageSize": 100
}),
headers: {'Content-Type': 'application/json'}
}).then(res => res.json()).then(({data}) => {
for (const i of data) {
if (i.avatar === undefined) i.avatar = '!{avatar}/avatar/d615d5793929e8c7d70eab5f00f7f5f1?d=mp'
ls.push({avatar: i.avatar, content: i.nick + ': ' + formatDanmaku(i.comment), url: i.url + '#' + i.id})
}
Danmaku.batchSend(ls, true);
utils.saveToLocal.set('envelope', ls, 0.02)
});
function formatDanmaku(str) {
str = str.replace(emojiReg, '!{__("console.newest_comment.emoji")}')
str = str.replace(/<\/*br>|[\s\uFEFF\xA0]+/g, '');
str = str.replace(/<img.*?>/g, '[!{__("console.newest_comment.image")}]');
str = str.replace(/<a.*?>.*?<\/a>/g, '[!{__("console.newest_comment.link")}]');
str = str.replace(/<pre.*?>.*?<\/pre>/g, '[!{__("console.newest_comment.code")}]');
str = str.replace(/<.*?>/g, '');
return str
}
})()
@@ -0,0 +1,57 @@
- const {serverURLs,appId,appKey} = theme.valine
script(pjax).
(async () => {
const emojiReg = /:[a-z0-9_\u4e00-\u9fa5]+:/g
if(typeof EasyDanmaku === "undefined") await utils.getScript('!{url_for(theme.cdn.envelope_js)}')
const envel = new EasyDanmaku({
page: '!{theme.envelope.page}',
el: '#barrage',
line: !{line},
speed: !{speed},
hover: !{hover},
loop: !{loop},
})
const data = utils.saveToLocal.get('enevlope')
if(data){
envel.batchSend(data,true)
return
}
const url = new URL('!{serverURLs}/1.1/classes/Comment')
const params = {
url: window.location.pathname,
order: '-createdAt'
}
Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value))
try {
const res = await fetch(url, {
method: "GET",
headers: {
"X-LC-Id": "#{appId}",
"X-LC-Key": "#{appKey}",
"Content-Type": "application/json"
},
})
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`)
const data = await res.json()
const init = () =>
data.results.map(item => ({
content: item.nick + ': ' + formatDanmaku(item.comment),
avatar: '!{avatar}/avatar/'+md5(item.mail),
url: item.url
}))
if (typeof md5 === "undefined") await utils.getScript('!{url_for(theme.cdn.blueimp_md5)}')
envel.batchSend(init(),true)
utils.saveToLocal.set('enevlope',init(),.02)
} catch (error) {
console.error("An error occurred while fetching comments: ", error)
}
function formatDanmaku(str) {
str = str.replace(emojiReg, '[!{__("console.newest_comment.emoji")}]')
str = str.replace(/!\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.image")}]')
str = str.replace(/\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.link")}]')
str = str.replace(/```.*?```/g, '[!{__("console.newest_comment.code")}]')
return str
}
})()
@@ -0,0 +1,42 @@
script(pjax).
(async () => {
const emojiReg = /<img [^>]+ class="wl-emoji">/g
if(typeof EasyDanmaku === "undefined") await utils.getScript('!{url_for(theme.cdn.envelope_js)}')
const envel = new EasyDanmaku({
page: '!{theme.envelope.page}',
el: '#barrage',
line: !{line},
speed: !{speed},
hover: !{hover},
loop: !{loop},
})
const data = utils.saveToLocal.get('enevlope')
if(data){
envel.batchSend(data,true)
return
}
await fetch('!{theme.waline.envId}/api/comment?type=recent&count=50', {method: 'GET'}).then(async res => res.json())
.then(async data => {
let ls = []
for (const i of data.data) {
ls.push({
content: i.nick + ': ' + formatContent(i.comment),
avatar: i.avatar,
url: i.url
})
}
envel.batchSend(ls,true)
utils.saveToLocal.set('enevlope',ls,.02)
}).catch(error => {
console.error("An error occurred while fetching comments: ", error)
})
function formatContent(content) {
content = content.replace(emojiReg, '[!{__("console.newest_comment.emoji")}]')
content = content.replace(/<img.*?>/g, '[!{__("console.newest_comment.image")}]');
content = content.replace(/<a.*?>.*?<\/a>/g, '[!{__("console.newest_comment.link")}]');
content = content.replace(/<pre.*?>.*?<\/pre>/g, '[!{__("console.newest_comment.code")}]');
content = content.replace(/<.*?>/g, '');
return content
}
})()
@@ -0,0 +1,78 @@
- const { server, site, option } = theme.artalk
script(pjax).
(async () => {
document.querySelector('#comments-page').textContent = `#{__("loading")}`
const emojiReg = /<img [^>]+ atk-emoticon="[^"]+">/g
let cache = utils.saveToLocal.get('artalk-recent-comments')
if (cache) {
setHtml(document.querySelector('#comments-page'), cache)
return
}
let ls = []
const searchParams = new URLSearchParams({'site_name': "!{site}", 'limit': '!{limit}'})
await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`, {method: 'GET'}).then(async res => res.json())
.then(async data => {
for (const i of data.data) {
if (checkEmoji(i.content)) continue
let title = ''
if (i.page_key) {
await fetch(i.page_key).then(res => res.text()).then(html => {
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
title = doc.querySelector('title').innerText
}).catch(() => {
title = i.page_key
})
}
if (title.indexOf('|') > 0) {
title = title.split('|')[0]
}
ls.push({
title: title,
url: i.page_key + '#atk-comment-' + i.id,
nick: i.nick,
avatar: '!{avatar}' + '/avatar/' + i.email_encrypted,
time: i.date,
content: formatContent(i.content)
})
}
setHtml(document.querySelector('#comments-page'), ls)
utils.saveToLocal.set('artalk-recent-comments', ls, !{cache})
})
function setHtml(el, data) {
el.innerHTML = data.map(i => `
<div class="comment-card" title="${i.title}" onclick="pjax.loadUrl('${i.url}')">
<div class="comment-info">
<img src="${i.avatar}" class="nolazyload" alt="${i.nick}">
<div>
<span class="comment-user">${i.nick}</span>
</div>
<time class="comment-time" datetime="${i.time}"></time>
</div>
<div class="comment-content">${i.content}</div>
<div class="comment-title">
<i class="solitude st-chat-fill"></i>
${i.title}</div>
</div>
`).join('')
if (typeof sco !== 'undefined') sco.changeTimeFormat(document.querySelectorAll('.comment-time'))
else {
document.addEventListener('pjax:complete', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
document.addEventListener('DOMContentLoaded', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
}
}
function checkEmoji(content) {
return emojiReg.test(content)
}
function formatContent(content) {
content = content.replace(emojiReg, '[!{__("console.newest_comment.emoji")}]')
content = content.replace(/!\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.image")}]')
content = content.replace(/\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.link")}]')
content = content.replace(/```.*?```/g, '[!{__("console.newest_comment.code")}]')
return content
}
})()
@@ -0,0 +1,83 @@
- const {envId} = theme.twikoo
script(pjax).
(async () => {
document.querySelector('#comments-page').textContent = `#{__("loading")}`
const emojiReg = /<img class="tk-owo-emotion" [^>]+>/g
let cache = utils.saveToLocal.get('twikoo-recent-comments')
if (cache) {
setHtml(document.querySelector('#comments-page'), cache)
return
}
let ls = []
await fetch('!{envId}', {
method: "POST",
body: JSON.stringify({
"event": "GET_RECENT_COMMENTS",
"includeReply": true,
"pageSize": !{limit}
}),
headers: {'Content-Type': 'application/json'}
}).then(res => res.json()).then(async ({data}) => {
for (const i of data) {
if (i.avatar === undefined) i.avatar = '!{avatar}/avatar/d615d5793929e8c7d70eab5f00f7f5f1?d=mp'
let title = ''
if (i.url) {
await fetch(i.url).then(res => res.text()).then(html => {
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
title = doc.querySelector('title').innerText
}).catch(() => {
title = i.url
})
}
if (title.indexOf('|') > 0) {
title = title.split('|')[0]
}
ls.push({
avatar: i.avatar,
nick: i.nick,
title: title,
content: i.comment,
url: i.url + '#' + i.id,
time: i.created
})
}
setHtml(document.querySelector('#comments-page'), ls)
utils.saveToLocal.set('twikoo-recent-comments', ls, !{cache})
});
function setHtml(el, data) {
el.innerHTML = data.map(i => `
<div class="comment-card" title="${i.title}" onclick="pjax.loadUrl('${i.url}')">
<div class="comment-info">
<img src="${i.avatar}" class="nolazyload" alt="${i.nick}">
<div>
<span class="comment-user">${i.nick}</span>
</div>
<time class="comment-time" datetime="${new Date(i.time)}"></time>
</div>
<div class="comment-content">${formatContent(i.content)}</div>
<div class="comment-title">
<i class="solitude st-chat-fill"></i>
${i.title}</div>
</div>
`).join('')
if (typeof sco !== 'undefined') sco.changeTimeFormat(document.querySelectorAll('.comment-time'))
else {
document.addEventListener('pjax:complete', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
document.addEventListener('DOMContentLoaded', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
}
}
function formatContent(content) {
content = content.replace(emojiReg, '!{__("console.newest_comment.emoji")}')
content = content.replace(/<\/*br>|[\s\uFEFF\xA0]+/g, '');
content = content.replace(/<img.*?>/g, '[!{__("console.newest_comment.image")}]');
content = content.replace(/<a.*?>.*?<\/a>/g, '[!{__("console.newest_comment.link")}]');
content = content.replace(/<pre.*?>.*?<\/pre>/g, '[!{__("console.newest_comment.code")}]');
content = content.replace(/<.*?>/g, '');
return content
}
})()
@@ -0,0 +1,79 @@
- const { appId, appKey, serverURLs } = theme.valine
script(pjax).
(async () => {
document.querySelector('#comments-page').textContent = `#{__("loading")}`
const emojiReg = /:[a-z0-9_\u4e00-\u9fa5]+:/g
let cache = utils.saveToLocal.get('valine-recent-comments')
if (cache) {
setHtml(document.querySelector('#comments-page'), cache)
return
}
let ls = []
if (typeof md5 === "undefined") await utils.getScript('!{url_for(theme.cdn.blueimp_md5)}')
await fetch('!{serverURLs}/1.1/classes/Comment?limit=8&order=-createdAt', {
method: "GET",
headers: {
"X-LC-Id": '!{appId}',
"X-LC-Key": '!{appKey}',
"Content-Type": "application/json"
}
}).then(async res => res.json()).then(async results => {
for (const i of results.results) {
let title = ''
if (i.url) {
await fetch(i.url).then(res => res.text()).then(html => {
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
title = doc.querySelector('title').innerText
}).catch(() => {
title = i.url
})
}
if (title.indexOf('|') > 0) {
title = title.split('|')[0]
}
ls.push({
title: title,
url: i.url,
nick: i.nick,
avatar: '!{avatar}' + '/avatar/' + md5(i.mail.trim().toLowerCase()),
time: i.createdAt,
content: formatContent(i.comment)
})
}
setHtml(document.querySelector('#comments-page'), ls)
utils.saveToLocal.set('valine-recent-comments', ls, !{cache})
})
function setHtml(el, data) {
el.innerHTML = data.map(i => `
<div class="comment-card" title="${i.title}" onclick="pjax.loadUrl('${i.url}')">
<div class="comment-info">
<img src="${i.avatar}" class="nolazyload" alt="${i.nick}">
<div>
<span class="comment-user">${i.nick}</span>
</div>
<time class="comment-time" datetime="${i.time}"></time>
</div>
<div class="comment-content">${i.content}</div>
<div class="comment-title">
<i class="solitude st-chat-fill"></i>
${i.title}</div>
</div>
`).join('')
if (typeof sco !== 'undefined') sco.changeTimeFormat(document.querySelectorAll('.comment-time'))
else {
document.addEventListener('pjax:complete', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
document.addEventListener('DOMContentLoaded', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
}
}
function formatContent(content) {
content = content.replace(emojiReg, '[!{__("console.newest_comment.emoji")}]')
content = content.replace(/!\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.image")}]')
content = content.replace(/\[.*?\]\((.*?)\)/g, '[!{__("console.newest_comment.link")}]')
content = content.replace(/```.*?```/g, '[!{__("console.newest_comment.code")}]')
return content
}
})()
@@ -0,0 +1,72 @@
script(pjax).
(async () => {
document.querySelector('#comments-page').textContent = `#{__("loading")}`
const emojiReg = /<img [^>]+ class="wl-emoji">/g
let cache = utils.saveToLocal.get('waline-recent-comments')
if (cache) {
setHtml(document.querySelector('#comments-page'), cache)
return
}
let ls = []
await fetch('!{theme.waline.envId}/api/comment?type=recent&count=!{limit}', {method: 'GET'}).then(async res => res.json())
.then(async data => {
console.log(data)
for (const i of data.data) {
let title = ''
if (i.url) {
await fetch(i.url).then(res => res.text()).then(html => {
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
title = doc.querySelector('title').innerText
}).catch(() => {
title = i.url
})
}
if (title.indexOf('|') > 0) {
title = title.split('|')[0]
}
ls.push({
title: title,
url: i.url,
nick: i.nick,
avatar: i.avatar,
time: new Date(i.time),
content: formatContent(i.comment)
})
}
setHtml(document.querySelector('#comments-page'), ls)
utils.saveToLocal.set('waline-recent-comments', ls, !{cache})
})
function setHtml(el, data) {
el.innerHTML = data.map(i => `
<div class="comment-card" title="${i.title}" onclick="pjax.loadUrl('${i.url}')">
<div class="comment-info">
<img src="${i.avatar}" class="nolazyload" alt="${i.nick}">
<div>
<span class="comment-user">${i.nick}</span>
</div>
<time class="comment-time" datetime="${i.time}"></time>
</div>
<div class="comment-content">${i.content}</div>
<div class="comment-title">
<i class="solitude st-chat-fill"></i>
${i.title}</div>
</div>
`).join('')
if (typeof sco !== 'undefined') sco.changeTimeFormat(document.querySelectorAll('.comment-time'))
else {
document.addEventListener('pjax:complete', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
document.addEventListener('DOMContentLoaded', () => sco.changeTimeFormat(document.querySelectorAll('.comment-time')))
}
}
function formatContent(content) {
content = content.replace(emojiReg, '[!{__("console.newest_comment.emoji")}]')
content = content.replace(/<img.*?>/g, '[!{__("console.newest_comment.image")}]');
content = content.replace(/<a.*?>.*?<\/a>/g, '[!{__("console.newest_comment.link")}]');
content = content.replace(/<pre.*?>.*?<\/pre>/g, '[!{__("console.newest_comment.code")}]');
content = content.replace(/<.*?>/g, '');
return content
}
})()
@@ -0,0 +1,44 @@
.post-reward
.reward-button(title=_p('award.tipping') onclick="AddRewardMask()")
i.solitude.st-hand-heart-fill
=_p('award.tipping')
.reward-main
ul.reward-all
span.reward-title=theme.post.award.title
ul.reward-group
- let list = theme.post.award.list || []
for item in list
li.reward-item
a(href=url_for(item.url))
img.post-qr-code-img.nolazyload(src=item.qcode, alt=item.name, style="border-color: " + item.color)
.post-qr-code-desc=item.name
a.reward-main-btn(href=url_for(theme.post.award.appreciators))
.reward-text= _p('award.title')
.reward-dec=theme.post.award.desc
script.
function RemoveRewardMask() {
let rewardMainElements = document.querySelectorAll(".reward-main");
let quitBoxElement = document.querySelector("#quit-box");
rewardMainElements.forEach(element => {
element.style.display = "none";
});
if (quitBoxElement) {
quitBoxElement.style.display = "none";
}
}
function AddRewardMask() {
let rewardMainElements = document.querySelectorAll(".reward-main");
let quitBoxElement = document.querySelector("#quit-box");
rewardMainElements.forEach(element => {
element.style.display = "flex";
});
if (quitBoxElement) {
quitBoxElement.style.display = "flex";
}
}
@@ -0,0 +1,74 @@
- const {copyright} = theme.post.default
.post-copyright
.post-copyright__author_group
a.post-copyright__author_img(href=url_for(copyright.author.url))
img.post-copyright__author_img_front(src=copyright.author.img || theme.site.icon)
.post-copyright__author_name= config.title
.post-copyright__author_desc= config.subtitle
.post-tools#post-tools
.post-tools-left
#quit-box(onclick="RemoveRewardMask()")
if theme.post.award.enable
include ./award
if theme.post.rss
.reward-link.mode
a.reward-link-button(href=url_for(theme.post.rss))
i.solitude.st-plant-fill
= _p('footer.rss')
if theme.post.share.enable
.social-share
- const path = config.url + url_for(page.path);
- const encodedPath = encodeURIComponent(path);
- const encodedTitle = encodeURIComponent(page.title);
- const encodedDescription = encodeURIComponent(page.description);
- const encodedIcon = encodeURIComponent(page.cover || theme.site.icon);
each item in theme.post.share.list || []
case item
when 'qq'
a.social-share-ico.icon-qq(href=`https://connect.qq.com/widget/shareqq/index.html?url=${encodedPath}&title=${encodedTitle}&desc=${encodedDescription}&summary=${encodedDescription}&site=${encodedTitle}&pics=${encodedIcon}` title=_p('post.share.qq'))
i.solitude.st-qq-fill
when 'weibo'
a.social-share-ico.icon-weibo(href=`http://service.weibo.com/share/share.php?url=${encodedPath}&title=${encodedTitle}&pic=${encodedIcon}` title=_p('post.share.weibo'))
i.solitude.st-weibo-fill
when 'telegram'
a.social-share-ico.icon-telegram(href=`https://t.me/share/url?url=${encodedPath}&text=${encodedTitle}` title=_p('post.share.telegram'))
i.solitude.st-telegram-fill
when 'whatsapp'
a.social-share-ico.icon-whatsapp(href=`https://api.whatsapp.com/send?text=${encodedTitle} ${encodedPath}` title=_p('post.share.whatsapp'))
i.solitude.st-whatsapp-fill
when 'linkedin'
a.social-share-ico.icon-linkedin(href=`https://www.linkedin.com/shareArticle?mini=true&url=${encodedPath}&title=${encodedTitle}&summary=${encodedDescription}&source=${encodedTitle}` title=_p('post.share.linkedin'))
i.solitude.st-linkedin-box-fill
when 'facebook'
a.social-share-ico.icon-facebook(href=`https://www.facebook.com/sharer/sharer.php?u=${encodedPath}` title=_p('post.share.facebook'))
i.solitude.st-facebook-fill
when 'twitter'
a.social-share-ico.icon-twitter(href=`https://twitter.com/intent/tweet?url=${encodedPath}&text=${encodedTitle}` title=_p('post.share.twitter'))
i.solitude.st-twitter-x-fill
when 'link'
.social-share-ico.icon-link(onclick=`utils.copy("${path}")` title=_p('post.share.link'))
i.solitude.st-links-line
when 'qrcode'
.social-share-ico.icon-qrcode(title=_p('post.share.qrcode'))
i.solitude.st-qr-code-fill
.share-main
.share-main-all
#qrcode
.reward-dec=_p('post.share.qrcode')
script(pjax).
typeof QRCode === 'function' && new QRCode(document.getElementById("qrcode"), '!{path}');
window.addEventListener('DOMContentLoaded', () => {
new QRCode(document.getElementById("qrcode"), '!{path}');
});
if copyright.enable || page.copyright
.post-copyright__notice
span.post-copyright-info
if page.reprint
= _p('post.copyright.reprint')
else
= _p('post.copyright.original')
a(href=url_for(theme.post.default.copyright.licenurl))
| #{theme.post.default.copyright.license}
= _p('post.copyright.original_end')
a(href=url_for("/")) #{config.title}
@@ -0,0 +1,12 @@
.post-ai
.ai-title
.ai-title-left
i.ai-title-icon.solitude.st-robot-fill
.ai-title-text=_p('post.ai.title')
.ai-tag#ai-tag= theme.post_ai.modelName
.ai-explanation(style="display: block;")
.ai-suggestions
.ai-bottom
.ai-tips= theme.post_ai.tips
if theme.post_ai.report
a.ai-report(title=_p('post.ai.tip'), href=url_for(theme.post_ai.report))=_p('post.ai.tip')
@@ -0,0 +1,84 @@
.coverdiv#coverdiv
img#post-cover.nolazyload(src=url_for(page.cover), alt=page.title)
#post-info
#post-firstinfo
.meta-firstline
- var cc = page.reprint ? _p('post.reprint') : _p('post.original')
a.post-meta-original(title=_p('post.cc').replace(/\$\{cc}/, cc))= cc
if page.categories.data.length > 0
span.post-meta-categories
a.post-meta-categories(href=url_for('/' + page.categories.data[0].path))= page.categories.data[0].name
.tag_share
.post-meta__tag-list
each tag in page.tags.data
a.post-meta__tags(href=url_for(tag.path))
span.tags-name.tags-punctuation= tag.name
h1.post-title= page.title
#post-meta
.meta-secondline
if theme.post.meta.date
span.post-meta-date(title=_p('post.posted') + ' ' + full_date(page.date))
i.post-meta-icon.solitude.st-calendar-todo-fill
time(datetime=date_xml(page.date))= date_xml(page.date)
if theme.post.meta.updated
span.post-meta-date(title=_p('post.updated') + ' ' + full_date(page.updated))
i.post-meta-icon.solitude.st-refresh-line
time(datetime=date_xml(page.updated))= date_xml(page.updated)
if theme.wordcount
span.post-meta-wordcount
if theme.post.meta.wordcount
i.post-meta-icon.solitude.st-word-fill(title=_p('post.wordcount'))
span.word-count= wordcount(page.content)
span.post-meta-separator
if theme.post.meta.readtime
i.post-meta-icon.solitude.st-clock-fill(title=_p('post.minread'))
span= min2read(page.content) + " min"
if theme.post.meta.locate
span.post-meta-position(title=_p('post.ip') + page.locate)
i.post-meta-icon.solitude.st-map-pin-fill
span= page.locate
if theme.post.meta.pv
a.post-meta-pv(href=url_for(page.path), title=_p('post.pv'))
i.post-meta-icon.solitude.st-fire-fill
if theme.comment.use && theme.comment.pv
case theme.comment.use[0]
when "Twikoo"
span#twikoo_visitors
i.solitude.st-loading-line
when "Waline"
span.waline-pageview-count
i.solitude.st-loading-line
when "Valine"
span.leancloud_visitors(id=url_for(page.path))
span.leancloud-visitors-count
i.solitude.st-loading-line
when 'Artalk'
span#ArtalkPV
i.solitude.st-loading-line
else
if theme.busuanzi
if theme.busuanzi_use === 0
span#busuanzi_value_page_pv
i.solitude.st-loading-line
else
span#busuanzi_page_pv
i.solitude.st-loading-line
if theme.post.meta.comment && page.comment && theme.comment.count && theme.comment.use
span.post-meta-commentcount(title=_p('post.comment'), onclick="sco.scrollTo('post-comment')")
i.solitude.st-chat-fill
a(href=url_for(page.path) + "#post-comment")
case theme.comment.use[0]
when "Twikoo"
span.twikoo-count
i.solitude.st-loading-line
when "Waline"
span.waline-comment-count
i.solitude.st-loading-line
when "Valine"
span.valine-comment-count(data-xid=url_for(page.path) itemprop="commentCount")
i.solitude.st-loading-line
when 'Artalk'
span.artalk-count
i.solitude.st-loading-line
include ./wave
@@ -0,0 +1,25 @@
nav.needEndHide.pagination-post#pagination
if page.prev && page.next
.prev-post.pull-left
a(href=url_for(page.prev.path))
.pagination-info
.label=_p('post.nav.prev')
.prev_info= page.prev.title
.next-post.pull-right
a(href=url_for(page.next.path))
.pagination-info
.label=_p('post.nav.next')
.next_info= page.next.title
else
if !page.prev && page.next
.next-post.pull-full
a(href=url_for(page.next.path))
div.pagination-info
.label=_p('post.nav.next')
.next_info= page.next.title
if !page.next && page.prev
.prev-post.pull-full
a(href=url_for(page.prev.path))
.pagination-info
.label=_p('post.nav.prev')
.prev_info= page.prev.title
@@ -0,0 +1,9 @@
section.main-hero-waves-area.waves-area
svg.waves-svg(xmlns="http://www.w3.org/2000/svg", xlink="http://www.w3.org/1999/xlink", viewBox="0 24 150 28", preserveAspectRatio="none", shape-rendering="auto")
defs
path#gentle-wave(d="M -160 44 c 30 0 58 -18 88 -18 s 58 18 88 18 s 58 -18 88 -18 s 58 18 88 18 v 44 h -352 Z")
g.parallax
use(href="#gentle-wave", x="48", y="0")
use(href="#gentle-wave", x="48", y="3")
use(href="#gentle-wave", x="48", y="5")
use(href="#gentle-wave", x="48", y="7")
@@ -0,0 +1,44 @@
- var datalinks = []
- var data = site.data.links.links
if(data)
each item in data
if item.type === "item"
each y in item.link_list
- datalinks.push({ name: y.name,link: y.link})
script.
const links = !{JSON.stringify(datalinks)}
const randomText = '!{_p('link.random')}'
function travelling() {
const link = links[utils.randomNum(links.length)];
Snackbar.show({
text: randomText.replace(/\$\{name}/,link.name),
duration: 8000,
pos: 'top-center',
actionText: '!{_p('link.to')}',
onActionClick: function(element) {
element.style.opacity = 0;
window.open(link.link, '_blank');
}
});
}
if theme.footer.randomlink
script.
function randomLinksList() {
const linkcard = document.getElementById('friend-links-in-footer');
if (linkcard == null) return;
let data = '';
let linksCopy = [...links];
let count = Math.min(3, linksCopy.length);
for (let i = 0; i < count; i++) {
let index = utils.randomNum(linksCopy.length);
const {link, name} = linksCopy[index];
data += `<a class="footer-item" href="${link}" target="_blank" rel="noopener noreferrer nofollow">${name}</a>`;
linksCopy.splice(index, 1);
}
linkcard.innerHTML = data + '<a class="footer-item" href="#{url_for(/links/)}">#{_p('more')}</a>';
}
@@ -0,0 +1,61 @@
- const { server, site, option } = theme.artalk
- const { lazyload ,use} = theme.comment
script.
(() => {
let artalkItem = null
const initArtalk = () => {
artalkItem = Artalk.init({
el: '#artalk-wrap',
server: '!{server}',
site: "!{site}",
pageKey: location.pathname,
darkMode: document.documentElement.getAttribute('data-theme') === 'dark'
}, !{JSON.stringify(option)})
if (GLOBAL_CONFIG.lightbox === 'null') return
artalkItem.on('list-loaded', () => {
const array = []
artalkItem.ctx.get('list').getCommentNodes().forEach(comment => {
array.push({
nick: comment.data.nick,
content: comment.data.content_marked,
mailMd5: comment.data.email_encrypted,
})
const $content = comment.getRender().$content
GLOBAL_CONFIG.lightbox && utils.lightbox($content.querySelectorAll('img:not([atk-emoticon])'))
})
sco.owoBig({body: '.atk-grp', item: '.atk-item'})
!{commentBarrage} && barrageArtalk(array)
})
const destroyArtalk = () => artalkItem.destroy()
utils.addGlobalFn('pjax', destroyArtalk, 'destroyArtalk')
}
const loadArtalk = async () => {
if (typeof Artalk === 'object') initArtalk()
else {
await utils.getCSS('!{theme.cdn.artalk_css}')
await utils.getScript('!{theme.cdn.artalk_js}').then(initArtalk)
}
}
const artalkChangeMode = theme => {
const artalkWrap = document.getElementById('artalk-wrap')
if (!(artalkWrap && artalkWrap.children.length)) return
const isDark = theme === 'dark'
artalkItem.setDarkMode(isDark)
}
utils.addGlobalFn('themeChange', artalkChangeMode, 'artalk')
if ('!{use[0]}' === 'Artalk' || !{lazyload}) {
if (!{lazyload}) utils.loadComment(document.getElementById('artalk-wrap'), loadArtalk)
else loadArtalk()
} else {
window.loadTwoComment = loadArtalk
}
})()
if commentBarrage
script.
async function barrageArtalk(array) {
const init = () => initializeCommentBarrage(array)
if (typeof initializeCommentBarrage === "undefined") await utils.getScript('!{url_for(theme.cdn.commentBarrage)}').then(init)
else init()
}
@@ -0,0 +1,44 @@
- const {use,count} = theme.comment
#post-comment
.comment-head
.comment-headline
i.solitude.st-chat-fill
span=' ' + _p('comment.title')
if count && is_post()
span.count
= ' ('
each name in use
case name
when "Twikoo"
span.twikoo-count
i.solitude.st-loading-line
when "Waline"
span.waline-comment-count
i.solitude.st-loading-line
when "Valine"
span.valine-comment-count(data-xid=url_for(page.path) itemprop="commentCount")
i.solitude.st-loading-line
when "Artalk"
span.artalk-count
| )
if use.length > 1
.comment-switch
span.first=use[0]
span#switch-btn
span.second=use[1]
.comment-wrap
each name in use
case name
when 'Valine'
#vcomment.vcomment
when 'Twikoo'
#twikoo-wrap
when 'Waline'
#waline-wrap
when 'Artalk'
#artalk-wrap
when 'Giscus'
#giscus-wrap
@@ -0,0 +1,60 @@
- const { repo, repo_id, category_id, theme:themes, option } = theme.giscus
- const giscusUrl = theme.cdn.giscus || 'https://giscus.app/client.js'
- const giscusOriginUrl = new URL(giscusUrl).origin
- const { use, lazyload } = theme.comment
script.
(()=>{
const getGiscusTheme = theme => {
return theme === 'dark' ? '!{themes.dark}' : '!{themes.light}'
}
const loadGiscus = () => {
const config = Object.assign({
src: '!{giscusUrl}',
'data-repo': '!{repo}',
'data-repo-id': '!{repo_id}',
'data-category-id': '!{category_id}',
'data-mapping': 'pathname',
'data-theme': getGiscusTheme(document.documentElement.getAttribute('data-theme')),
'data-reactions-enabled': '1',
crossorigin: 'anonymous',
async: true
},!{JSON.stringify(option)})
const ele = document.createElement('script')
for (let key in config) {
ele.setAttribute(key, config[key])
}
document.getElementById('giscus-wrap').appendChild(ele)
}
const changeGiscusTheme = theme => {
const sendMessage = message => {
const iframe = document.querySelector('iframe.giscus-frame')
if (!iframe) return
iframe.contentWindow.postMessage({ giscus: message }, '!{giscusOriginUrl}')
}
sendMessage({
setConfig: {
theme: getGiscusTheme(theme)
}
});
}
utils.addGlobalFn('themeChange', changeGiscusTheme, 'giscus')
if ('!{use[0]}' === 'Giscus' || !!{lazyload}) {
if (!{lazyload}) {
const giscusWrap = document.getElementById('giscus-wrap')
if (giscusWrap) {
utils.loadComment(giscusWrap, loadGiscus)
}
} else {
loadGiscus()
}
} else {
window.loadOtherComment = loadGiscus
}
})()
@@ -0,0 +1,14 @@
- const {use} = theme.comment
each name in use
case name
when 'Twikoo'
!=partial('includes/widgets/third-party/comments/twikoo', {}, {cache: true})
when 'Waline'
!=partial('includes/widgets/third-party/comments/waline', {}, {cache: true})
when 'Valine'
!=partial('includes/widgets/third-party/comments/valine', {}, {cache: true})
when 'Artalk'
!=partial('includes/widgets/third-party/comments/artalk', {}, {cache: true})
when 'Giscus'
!=partial('includes/widgets/third-party/comments/giscus', {}, {cache: true})
@@ -0,0 +1,80 @@
- const { envId, region, option ,accessToken } = theme.twikoo
- const { lazyload, count, use,commentBarrage } = theme.comment
script().
(() => {
const getCount = () => {
const ele = document.querySelectorAll('.twikoo-count')
if (!ele) return
twikoo.getCommentsCount({
envId: '!{envId}',
region: '!{region}',
urls: [window.location.pathname],
includeReply: false
}).then(res => {
ele.forEach(item => item.textContent = res[0].count)
}).catch(err => {
console.error(err)
})
}
const init = () => {
twikoo.init(Object.assign({
el: '#twikoo-wrap',
envId: '!{envId}',
region: '!{region}',
path: window.location.pathname,
onCommentLoaded: () => {
GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)'))
}
}, !{JSON.stringify(option)}))
!{count ? ' && getCount()' : ''}
sco.owoBig({
body: '.OwO-body',
item: '.OwO-items li'
})
barrageTwikoo()
}
const loadTwikoo = () => {
if (typeof twikoo === 'object') setTimeout(init,0)
else utils.getScript('!{url_for(theme.cdn.twikoo)}').then(init)
}
if ('!{use[0]}' === 'Twikoo' || !{lazyload}) {
if (!{lazyload}) utils.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo)
else loadTwikoo()
} else {
window.loadTwoComment = loadTwikoo
}
})()
if commentBarrage
script.
async function barrageTwikoo() {
await fetch("!{envId}", {
method: "POST",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({
event: "COMMENT_GET",
accessToken: "!{accessToken}",
url: window.location.pathname
})
}).then(async res => {
if (!res.ok) throw new Error("HTTP error! status: " + res.status)
const data = await res.json();
const init = () => {
initializeCommentBarrage((data.data).map(item => Object.assign({
content: item.comment,
nick: item.nick,
mailMd5: item.mailMd5,
id: item.id
})))
}
if (typeof initializeCommentBarrage === "undefined") await utils.getScript('!{url_for(theme.cdn.commentBarrage)}').then(init)
else init()
}).catch(error => console.error("An error occurred while fetching comments: ", error))
}
@@ -0,0 +1,72 @@
- const { lazyload, count, use,commentBarrage } = theme.comment
- const { appId, appKey, avatar, serverURLs, visitor, option } = theme.valine
- let emojiMaps = '""'
if site.data.valine
- emojiMaps = JSON.stringify(site.data.valine)
script.
(() => {
const initValine = () => {
const valine = new Valine({
el: '#vcomment',
appId: '#{appId}',
appKey: '#{appKey}',
avatar: '#{avatar}',
serverURLs: '#{serverURLs}',
emojiMaps: !{emojiMaps},
path: window.location.pathname,
visitor: #{visitor},
...!{JSON.stringify(option)}
})
GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll('#comment .vcontent img:not(.vemoji)'))
sco.owoBig({body: '.vwrap', item: '.vemojis i'})
}
const loadValine = async () => {
if (typeof Valine === 'function') setTimeout(initValine, 0)
else {
await utils.getScript('!{url_for(theme.cdn.valine)}').then(initValine)
}
!{commentBarrage} && barrageValine()
}
if ('!{use[0]}' === 'Valine' || !{lazyload}) {
if (!{lazyload}) utils.loadComment(document.getElementById('vcomment'), loadValine)
else loadValine()
} else {
window.loadTwoComment = loadValine
}
})()
if commentBarrage
script.
async function barrageValine() {
const url = new URL('!{serverURLs}/1.1/classes/Comment')
const params = {
url: window.location.pathname,
order: '-createdAt'
}
Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value))
await fetch(url, {
method: "GET",
headers: {
"X-LC-Id": "#{appId}",
"X-LC-Key": "#{appKey}",
"Content-Type": "application/json"
},
}).then(async res => {
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`)
const data = await res.json()
const init = () =>
initializeCommentBarrage(data.results
.filter(item => item.url === window.location.pathname)
.map(item => ({
content: item.comment,
nick: item.nick,
mailMd5: md5(item.mail),
id: item.objectId
})))
if (typeof md5 === "undefined") await utils.getScript('!{url_for(theme.cdn.blueimp_md5)}')
if (typeof initializeCommentBarrage === "undefined") await utils.getScript('!{url_for(theme.cdn.commentBarrage)}').then(init)
else init()
}).catch(error => console.error("An error occurred while fetching comments: ", error))
}
@@ -0,0 +1,67 @@
- const { envId, option ,pageview } = theme.waline
- const { lazyload, count, commentBarrage,use } = theme.comment
script.
(() => {
let walineInitFunction = window.walineFn || null
function initWaline(initFn) {
const walineOptions = {
el: '#waline-wrap',
serverURL: '!{envId}',
pageview: !{pageview},
dark: 'html[data-theme="dark"]',
path: window.location.pathname,
comment: !{count},
...!{JSON.stringify(option)}
}
const walineInstance = initFn(walineOptions)
utils.addGlobalFn('pjax', () => walineInstance.destroy(), 'destroyWaline')
GLOBAL_CONFIG.lightbox && utils.lightbox(document.querySelectorAll('#comment .wl-content img:not(.wl-emoji)'))
sco.owoBig({
body: '.wl-emoji-popup',
item: '.wl-tab-wrapper button'
})
}
async function loadWaline() {
if (walineInitFunction) initWaline(walineInitFunction)
else {
await utils.getCSS('!{url_for(theme.cdn.waline_css)}')
const {init} = await import('!{url_for(theme.cdn.waline_js)}')
walineInitFunction = init || Waline.init
initWaline(walineInitFunction)
window.walineFn = walineInitFunction
}
!{commentBarrage} && barrageWaline()
}
if (!{use[0] === 'Waline'} || !{lazyload}) {
if (!{lazyload}) utils.loadComment(document.getElementById('waline-wrap'), loadWaline)
else loadWaline()
} else window.loadTwoComment = loadWaline
})()
if commentBarrage
script.
async function barrageWaline() {
const url = new URL('!{envId}/api/comment')
const params = {path: window.location.pathname, sortBy: 'insertedAt_asc'}
Object.entries(params).forEach(([key, value]) => url.searchParams.append(key, value))
await fetch(url).then(async res => {
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`)
const data = await res.json();
const regex = /<img [^>]*class="wl-emoji"[^>]*>/;
const init = () => {
initializeCommentBarrage(data.data.data
.map(item => ({
nick: item.nick,
mailId: item.avatar,
content: item.comment.replace(regex, ''),
id: item.objectId
})))
}
if (typeof initializeCommentBarrage === "undefined") await utils.getScript('!{url_for(theme.cdn.commentBarrage)}').then(init)
else init()
}).catch(error => console.error("An error occurred while fetching comments: ", error))
}
@@ -0,0 +1,3 @@
div.needEndHide#nav-music(onclick="sco.musicToggle()")
div#nav-music-hoverTips=__('music.hit')
meting-js(id=theme.capsule.id, server=theme.capsule.server, type="playlist", mutex="true", preload="none", data-lrctype="0", order="random", theme="var(--efu-main)")
@@ -0,0 +1,92 @@
- const { server, site, option } = theme.artalk
- const avatarCdn = theme.comment.avatar
script(pjax).
(() => {
const changeContent = content => {
if (content === '') return content;
const replacements = [
{
regex: /<img.*?src="(.*?)"?[^\>]+>/ig,
replacement: '[!{_p("console.newest_comment.image")}]'
},
{
regex: /<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,
replacement: '[!{_p("console.newest_comment.link")}]'
},
{
regex: /<pre><code>.*?<\/pre>/gi,
replacement: '[!{_p("console.newest_comment.code")}]'
},
{
regex: /<[^>]+>/g,
replacement: ''
}
];
content = replacements.reduce((str, {regex, replacement}) => str.replace(regex, replacement), content);
return content.length > 150 ? content.substring(0, 100) + '...' : content;
};
const generateHtml = (array, asideList) => {
asideList.innerHTML = array.length ? array.map(item => `
<div class='aside-list-item'>
<div class='thumbnail'>
<img src='${item.avatar}' alt='${item.nick}'>
</div>
<div class='content'>
<div class='comment' onclick='pjax.loadUrl("${item.url}")'>${item.content}</div>
<time class="datetime" datetime="${item.date}"></time>
</div>
</div>
`).join('') : "!{_p('newest_comment.zero')}";
window.lazyLoadInstance?.update();
window.pjax?.refresh();
sco?.changeTimeFormat(document.querySelectorAll('.aside-list-item time'));
};
const getSetting = async () => {
try {
const res = await fetch('!{server}/api/v2/conf', {method: 'GET'});
return await res.json();
} catch (e) {
console.error(e);
return null;
}
};
const getComment = async (asideList) => {
const searchParams = new URLSearchParams({'site_name': "!{site}", 'limit': '6'});
await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`, {method: 'GET'}).then(async res => {
const result = await res.json();
const avatarConfig = await getSetting();
const avatarCdn = '!{avatarCdn}' + '/avatar/';
const params = avatarConfig?.gravatar?.params || '';
const artalk = result.data.map(e => ({
avatar: avatarCdn + e.email_encrypted + '?' + params,
content: changeContent(e.content_marked),
nick: e.nick,
url: e.page_key + `#atk-comment-${e.id}`,
date: e.date,
})).slice(0, !{limit});
utils.saveToLocal.set('artalk-newest-comments', artalk, !{theme.comment.newest_comment.storage});
generateHtml(artalk, asideList);
}).catch(error => {
console.error(error);
asideList.textContent = "!{_p('newest_comment.error')}";
});
};
const newestCommentInit = (asideList) => {
if (!asideList) return;
const data = utils.saveToLocal.get('artalk-newest-comments');
if (data) {
generateHtml(data, asideList);
} else {
getComment(asideList);
}
};
const $asideList = document.querySelector('.card-recent-comment .aside-list');
window.addEventListener('DOMContentLoaded', () => newestCommentInit($asideList), false)
window.addEventListener('pjax:complete', () => newestCommentInit(document.querySelector('.card-recent-comment .aside-list')), false);
})();
@@ -0,0 +1,11 @@
- var limit = theme.aside.newest_comment.limit ? theme.aside.newest_comment.limit : 5
if theme.comment.use
case theme.comment.use[0]
when 'Twikoo'
!=partial('includes/widgets/third-party/news-comment/twikoo', {limit}, {cache: true})
when 'Waline'
!=partial('includes/widgets/third-party/news-comment/waline', {limit}, {cache: true})
when 'Valine'
!=partial('includes/widgets/third-party/news-comment/valine', {limit}, {cache: true})
when 'Artalk'
!=partial('includes/widgets/third-party/news-comment/artalk', {limit}, {cache: true})
@@ -0,0 +1,69 @@
script.
(() => {
const changeContent = (content) => {
if (!content) return '';
const replacements = [
{regex: /<img.*?src="(.*?)"?[^\>]+>/ig, replacement: '[!{_p("console.newest_comment.image")}]'},
{
regex: /<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,
replacement: '[!{_p("console.newest_comment.link")}]'
},
{regex: /<pre><code>.*?<\/pre>/gi, replacement: '[!{_p("console.newest_comment.code")}]'},
{regex: /<[^>]+>/g, replacement: ''}
]
content = replacements.reduce((str, {regex, replacement}) => str.replace(regex, replacement), content)
return content.length > 150 ? `${content.substring(0, 100)}...` : content
}
const generateHtml = (array) => {
const html = array.map(item => `
<div class='aside-list-item'>
<div class='thumbnail'>
<img src='${item.avatar}' alt='${item.nick}'>
</div>
<div class='content'>
<div class='comment' onclick='pjax.loadUrl("${item.url}")'>${item.content}</div>
<time class="datetime" datetime="${item.date}"></time>
</div>
</div>
`).join('')
document.querySelector('.card-recent-comment .aside-list').innerHTML = array.length ? html : "!{_p('newest_comment.zero')}"
window.lazyLoadInstance?.update()
window.pjax?.refresh()
sco?.changeTimeFormat(document.querySelectorAll('.aside-list-item time'))
}
const getComment = async () => {
const runTwikoo = () => {
twikoo.getRecentComments({
envId: '!{theme.twikoo.envId}',
region: '',
pageSize: !{limit},
includeReply: true
}).then(res => {
const twikooArray = res.map(e => ({
content: changeContent(e.comment),
avatar: e.avatar,
nick: e.nick,
url: `${e.url}#${e.id}`,
date: new Date(e.created).toString()
})).slice(0, 6)
utils.saveToLocal.set('twikoo-newest-comment', twikooArray, !{theme.comment.newest_comment.storage})
generateHtml(twikooArray)
}).catch((err) => {
console.error(err);
document.querySelector('.card-recent-comment .aside-list').textContent = "!{_p('newest_comment.error')}"
})
}
if (typeof twikoo === 'object') {
runTwikoo()
} else {
utils.getScript('!{url_for(theme.cdn.twikoo)}').then(runTwikoo)
}
}
const newestCommentInit = () => {
if (!document.querySelector('.card-recent-comment')) return
const data = utils.saveToLocal.get('twikoo-newest-comment')
data ? generateHtml(data) : getComment()
}
window.addEventListener('DOMContentLoaded', newestCommentInit, false)
window.addEventListener('pjax:complete', newestCommentInit, false);
})()
@@ -0,0 +1,85 @@
script.
(() => {
const emojiReg = /:[a-z0-9_\u4e00-\u9fa5]+:/g
const changeContent = (content) => {
if (content === '') return content;
const replacements = [
{regex: /<img.*?src="(.*?)"?[^\>]+>/ig, replacement: '[!{_p("console.newest_comment.image")}]'},
{
regex: /<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,
replacement: '[!{_p("console.newest_comment.link")}]'
},
{regex: /```[\s\S]*?```/g, replacement: '[!{_p("console.newest_comment.code")}]'},
{regex: /<[^>]+>/g, replacement: ""}
];
content = replacements.reduce((str, {regex, replacement}) => str.replace(regex, replacement), content);
return content.length > 150 ? content.substring(0, 100) + '...' : content;
}
const $asideList = document.querySelector('.card-recent-comment .aside-list')
const newestCommentInit = () => {
if (!document.querySelector('.card-recent-comment')) return
const data = utils.saveToLocal.get('valine-newest-comment')
if (data) {
generateHtml(data)
} else {
getComment()
}
}
const getComment = async () => {
const settings = {
"method": "GET",
"headers": {
"X-LC-Id": '!{theme.valine.appId}',
"X-LC-Key": '!{theme.valine.appKey}',
"Content-Type": "application/json"
},
}
if (typeof md5 === "undefined") await utils.getScript('!{url_for(theme.cdn.blueimp_md5)}')
await fetch('!{theme.valine.serverURLs}/1.1/classes/Comment?limit=8&order=-createdAt', settings).then(res => res.json())
.then(async result => {
let ls = []
for (const i of result.results.slice(0, !{limit})) {
if (emojiReg.test(i.comment)) continue
ls.push({
content: changeContent(i.comment),
avatar: '!{theme.comment.avatar}' + '/avatar/' + md5(i.mail.toLowerCase()),
nick: i.nick,
url: i.url,
date: i.updatedAt || i.createdAt
})
}
utils.saveToLocal.set('valine-newest-comment', ls, !{theme.comment.newest_comment.storage})
generateHtml(ls)
}).catch(error => {
console.error(error);
$asideList.textContent = "!{_p('newest_comment.error')}"
})
}
const generateHtml = array => {
const $dom = document.querySelector('.card-recent-comment .aside-list')
$dom.innerHTML = array.length ? array.map(item => `
<div class='aside-list-item'>
<div onclick='pjax.loadUrl(\"${item.url}\")' class='thumbnail'>
<img src='${item.avatar}' alt='${item.nick}'>
<div class='name'><span>${item.nick}</span></div>
</div>
<div class='content'>
<div class='comment' onclick='pjax.loadUrl("${item.url}")'>${item.content}</div>
<time class="datetime" datetime="${item.date}"></time>
</div>
</div>
`).join('') : "!{_p('newest_comment.zero')}"
window.lazyLoadInstance?.update()
window.pjax?.refresh()
sco?.changeTimeFormat(document.querySelectorAll('.aside-list-item time'))
}
window.addEventListener('DOMContentLoaded', newestCommentInit, false)
window.addEventListener('pjax:complete', newestCommentInit, false);
})()
@@ -0,0 +1,73 @@
script.
(() => {
const changeContent = (content) => {
if (content === '') return content;
const replacements = [
{regex: /<img.*?src="(.*?)"?[^\>]+>/ig, replacement: '[!{_p("console.newest_comment.image")}]'},
{
regex: /<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi,
replacement: '[!{_p("console.newest_comment.link")}]'
},
{regex: /<pre><code>.*?<\/pre>/gi, replacement: '[!{_p("console.newest_comment.code")}]'},
{regex: /<[^>]+>/g, replacement: ""}
];
content = replacements.reduce((str, {regex, replacement}) => str.replace(regex, replacement), content);
return content.length > 150 ? content.substring(0, 100) + '...' : content;
}
const $asideList = document.querySelector('.card-recent-comment .aside-list')
const newestCommentInit = () => {
if (!document.querySelector('.card-recent-comment')) return
const data = utils.saveToLocal.get('waline-newest-comment')
if (data) {
generateHtml(data)
} else {
getComment()
}
}
const getComment = async () => {
await fetch('!{theme.waline.envId}/api/comment?type=recent&count=!{limit}', {method: 'GET'}).then(async res => {
const result = await res.json()
const walineArray = result.data.map(e => {
return {
'content': changeContent(e.comment),
'avatar': e.avatar,
'nick': e.nick,
'url': e.url + '#' + e.objectId,
'date': new Date(e.time || e.insertedAt)
}
})
utils.saveToLocal.set('waline-newest-comment', walineArray, !{theme.comment.newest_comment.storage})
generateHtml(walineArray)
}).catch(error => {
console.error(error)
$asideList.textContent = "!{_p('newest_comment.error')}"
})
}
const generateHtml = array => {
const $dom = document.querySelector('.card-recent-comment .aside-list')
$dom.innerHTML = array.length ? array.map(item => `
<div class='aside-list-item'>
<div onclick='pjax.loadUrl("${item.url}")' class='thumbnail'>
<img src='${item.avatar}' alt='${item.nick}'>
<div class='name'><span>${item.nick}</span></div>
</div>
<div class='content'>
<div class='comment' onclick='pjax.loadUrl("${item.url}")'>${item.content}</div>
<time class="datetime" datetime="${item.date}"></time>
</div>
</div>
`).join('') : "!{_p('newest_comment.zero')}"
window.lazyLoadInstance?.update()
window.pjax?.refresh()
sco?.changeTimeFormat(document.querySelectorAll('.aside-list-item time'))
}
window.addEventListener('DOMContentLoaded', newestCommentInit, false)
window.addEventListener('pjax:complete', newestCommentInit, false);
})()
@@ -0,0 +1,39 @@
- const google_adsense = theme.google_adsense.enable
script.
const pjax = new Pjax({
elements: 'a:not([target="_blank"])',
selectors: ['title','#body-wrap','#site-config','meta[name="description"]','.js-pjax','meta[property^="og:"]','#config-diff'],
cacheBust: false,
analytics: !{google_adsense},
scrollRestoration: false
})
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)
})
document.addEventListener('pjax:complete', () => {
window.refreshFn()
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)
})
GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()
})
document.addEventListener('pjax:error', (e) => {
if (e.request.status === 404) {
pjax.loadUrl('/404.html')
}
})

Some files were not shown because too many files have changed in this diff Show More