mirror of
https://github.com/jerryc127/hexo-theme-butterfly.git
synced 2026-08-09 20:18:41 +08:00
Compare commits
3
Commits
dev
..
1b1a26e382
@@ -124,6 +124,7 @@ npm install hexo-renderer-pug hexo-renderer-stylus --save
|
|||||||
- [x] **Theme Customization** - Custom site color schemes
|
- [x] **Theme Customization** - Custom site color schemes
|
||||||
- [x] **Chart Support** - Mermaid flowcharts/Chart.js data charts
|
- [x] **Chart Support** - Mermaid flowcharts/Chart.js data charts
|
||||||
- [x] **Music Notation** - ABCJS music notation support
|
- [x] **Music Notation** - ABCJS music notation support
|
||||||
|
- [x] **Music Player** - APlayer/Meting music playback
|
||||||
- [x] **Article Series** - Series article organization
|
- [x] **Article Series** - Series article organization
|
||||||
- [x] **Instantpage** - Page preloading acceleration
|
- [x] **Instantpage** - Page preloading acceleration
|
||||||
- [x] **Snackbar** - Elegant notification messages
|
- [x] **Snackbar** - Elegant notification messages
|
||||||
|
|||||||
@@ -124,6 +124,7 @@ npm install hexo-renderer-pug hexo-renderer-stylus --save
|
|||||||
- [x] **主題定製** - 自訂網站配色方案
|
- [x] **主題定製** - 自訂網站配色方案
|
||||||
- [x] **圖表支援** - Mermaid 流程圖/Chart.js 數據圖表
|
- [x] **圖表支援** - Mermaid 流程圖/Chart.js 數據圖表
|
||||||
- [x] **音樂符號** - ABCJS 音樂記譜法支援
|
- [x] **音樂符號** - ABCJS 音樂記譜法支援
|
||||||
|
- [x] **音樂播放器** - APlayer/Meting 音樂播放功能
|
||||||
- [x] **系列文章** - 系列文章組織功能
|
- [x] **系列文章** - 系列文章組織功能
|
||||||
- [x] **Instantpage** - 頁面預載入加速
|
- [x] **Instantpage** - 頁面預載入加速
|
||||||
- [x] **Snackbar** - 優雅的提示訊息
|
- [x] **Snackbar** - 優雅的提示訊息
|
||||||
|
|||||||
@@ -993,6 +993,11 @@ pjax:
|
|||||||
exclude:
|
exclude:
|
||||||
# - /xxxxxx/
|
# - /xxxxxx/
|
||||||
|
|
||||||
|
# Inject the css and script (aplayer/meting)
|
||||||
|
aplayerInject:
|
||||||
|
enable: false
|
||||||
|
per_page: true
|
||||||
|
|
||||||
# Snackbar - Toast Notification
|
# Snackbar - Toast Notification
|
||||||
# https://github.com/polonel/SnackBar
|
# https://github.com/polonel/SnackBar
|
||||||
# position: top-left / top-center / top-right / bottom-left / bottom-center / bottom-right
|
# position: top-left / top-center / top-right / bottom-left / bottom-center / bottom-right
|
||||||
@@ -1083,6 +1088,8 @@ CDN:
|
|||||||
# activate_power_mode:
|
# activate_power_mode:
|
||||||
# algolia_js:
|
# algolia_js:
|
||||||
# algolia_search:
|
# algolia_search:
|
||||||
|
# aplayer_css:
|
||||||
|
# aplayer_js:
|
||||||
# artalk_css:
|
# artalk_css:
|
||||||
# artalk_js:
|
# artalk_js:
|
||||||
# blueimp_md5:
|
# blueimp_md5:
|
||||||
@@ -1115,6 +1122,7 @@ CDN:
|
|||||||
# mathjax:
|
# mathjax:
|
||||||
# medium_zoom:
|
# medium_zoom:
|
||||||
# mermaid:
|
# mermaid:
|
||||||
|
# meting_js:
|
||||||
# prismjs_autoloader:
|
# prismjs_autoloader:
|
||||||
# prismjs_js:
|
# prismjs_js:
|
||||||
# prismjs_lineNumber_js:
|
# prismjs_lineNumber_js:
|
||||||
|
|||||||
@@ -41,6 +41,10 @@ div
|
|||||||
!= partial("includes/third-party/effect", {}, { cache: true })
|
!= partial("includes/third-party/effect", {}, { cache: true })
|
||||||
!= partial("includes/third-party/chat/index", {}, { cache: true })
|
!= partial("includes/third-party/chat/index", {}, { cache: true })
|
||||||
|
|
||||||
|
if theme.aplayerInject && theme.aplayerInject.enable
|
||||||
|
if theme.pjax.enable || theme.aplayerInject.per_page || page.aplayer
|
||||||
|
include ./third-party/aplayer.pug
|
||||||
|
|
||||||
if theme.pjax.enable
|
if theme.pjax.enable
|
||||||
!= partial("includes/third-party/pjax", {}, { cache: true })
|
!= partial("includes/third-party/pjax", {}, { cache: true })
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@
|
|||||||
container.innerHTML = content
|
container.innerHTML = content
|
||||||
|
|
||||||
window.lazyLoadInstance && window.lazyLoadInstance.update()
|
window.lazyLoadInstance && window.lazyLoadInstance.update()
|
||||||
document.dispatchEvent(new Event('shuoshuo:rendered'))
|
btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)'))
|
||||||
}
|
}
|
||||||
|
|
||||||
const setupNavEvents = (nav) => {
|
const setupNavEvents = (nav) => {
|
||||||
|
|||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
link(rel='stylesheet' href=url_for(theme.asset.aplayer_css) media="print" onload="this.media='all'")
|
||||||
|
script(src=url_for(theme.asset.aplayer_js))
|
||||||
|
script(src=url_for(theme.asset.meting_js))
|
||||||
|
if theme.pjax.enable
|
||||||
|
script.
|
||||||
|
(() => {
|
||||||
|
const destroyAplayer = () => {
|
||||||
|
if (window.aplayers) {
|
||||||
|
for (let i = 0; i < window.aplayers.length; i++) {
|
||||||
|
if (!window.aplayers[i].options.fixed) {
|
||||||
|
window.aplayers[i].destroy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const runMetingJS = () => {
|
||||||
|
typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()
|
||||||
|
}
|
||||||
|
|
||||||
|
btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer')
|
||||||
|
btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS')
|
||||||
|
})()
|
||||||
@@ -43,13 +43,4 @@ hr.custom-hr
|
|||||||
when 'Remark42'
|
when 'Remark42'
|
||||||
#remark42
|
#remark42
|
||||||
when 'Artalk'
|
when 'Artalk'
|
||||||
if theme.artalk.vote
|
|
||||||
.artalk-vote
|
|
||||||
span.artalk-page-vote-up
|
|
||||||
i.fas.fa-thumbs-up
|
|
||||||
span.artalk-page-vote-up-count
|
|
||||||
span.artalk-page-vote-down
|
|
||||||
i.fas.fa-thumbs-down
|
|
||||||
span.artalk-page-vote-down-count
|
|
||||||
#artalk-wrap
|
#artalk-wrap
|
||||||
|
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
- var pjaxExclude = 'a:not([target="_blank"]):not([data-fancybox])'
|
- var pjaxExclude = 'a:not([target="_blank"])'
|
||||||
if theme.pjax.exclude
|
if theme.pjax.exclude
|
||||||
each val in theme.pjax.exclude
|
each val in theme.pjax.exclude
|
||||||
- pjaxExclude += `:not([href="${val}"])`
|
- pjaxExclude += `:not([href="${val}"])`
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hexo-theme-butterfly",
|
"name": "hexo-theme-butterfly",
|
||||||
"version": "5.7.0",
|
"version": "5.6.0",
|
||||||
"description": "A Simple and Card UI Design theme for Hexo",
|
"description": "A Simple and Card UI Design theme for Hexo",
|
||||||
"main": "package.json",
|
"main": "package.json",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
"hexo-renderer-pug": "^3.0.0",
|
"hexo-renderer-pug": "^3.0.0",
|
||||||
"hexo-renderer-stylus": "^3.0.1",
|
"hexo-renderer-stylus": "^3.0.1",
|
||||||
"hexo-util": "^4.0.0",
|
"hexo-util": "^4.0.0",
|
||||||
"moment-timezone": "^0.6.3"
|
"moment-timezone": "^0.6.2"
|
||||||
},
|
},
|
||||||
"homepage": "https://butterfly.js.org/",
|
"homepage": "https://butterfly.js.org/",
|
||||||
"author": "Jerry <my@crazywong.com>",
|
"author": "Jerry <my@crazywong.com>",
|
||||||
|
|||||||
+21
-9
@@ -10,14 +10,22 @@ algolia_search:
|
|||||||
name: algoliasearch
|
name: algoliasearch
|
||||||
file: dist/lite/builds/browser.umd.js
|
file: dist/lite/builds/browser.umd.js
|
||||||
version: 5.56.0
|
version: 5.56.0
|
||||||
|
aplayer_css:
|
||||||
|
name: aplayer
|
||||||
|
file: dist/APlayer.min.css
|
||||||
|
version: 1.10.1
|
||||||
|
aplayer_js:
|
||||||
|
name: aplayer
|
||||||
|
file: dist/APlayer.min.js
|
||||||
|
version: 1.10.1
|
||||||
artalk_css:
|
artalk_css:
|
||||||
name: artalk
|
name: artalk
|
||||||
file: dist/Artalk.css
|
file: dist/Artalk.css
|
||||||
version: 2.10.0
|
version: 2.9.1
|
||||||
artalk_js:
|
artalk_js:
|
||||||
name: artalk
|
name: artalk
|
||||||
file: dist/Artalk.js
|
file: dist/Artalk.js
|
||||||
version: 2.10.0
|
version: 2.9.1
|
||||||
blueimp_md5:
|
blueimp_md5:
|
||||||
name: blueimp-md5
|
name: blueimp-md5
|
||||||
file: js/md5.min.js
|
file: js/md5.min.js
|
||||||
@@ -58,12 +66,12 @@ docsearch_css:
|
|||||||
name: '@docsearch/css'
|
name: '@docsearch/css'
|
||||||
other_name: docsearch-css
|
other_name: docsearch-css
|
||||||
file: dist/style.css
|
file: dist/style.css
|
||||||
version: 4.7.0
|
version: 4.6.3
|
||||||
docsearch_js:
|
docsearch_js:
|
||||||
name: '@docsearch/js'
|
name: '@docsearch/js'
|
||||||
other_name: docsearch-js
|
other_name: docsearch-js
|
||||||
file: dist/umd/index.js
|
file: dist/umd/index.js
|
||||||
version: 4.7.0
|
version: 4.6.3
|
||||||
egjs_infinitegrid:
|
egjs_infinitegrid:
|
||||||
name: '@egjs/infinitegrid'
|
name: '@egjs/infinitegrid'
|
||||||
other_name: egjs-infinitegrid
|
other_name: egjs-infinitegrid
|
||||||
@@ -72,13 +80,13 @@ egjs_infinitegrid:
|
|||||||
fancybox:
|
fancybox:
|
||||||
name: '@fancyapps/ui'
|
name: '@fancyapps/ui'
|
||||||
file: dist/fancybox/fancybox.umd.js
|
file: dist/fancybox/fancybox.umd.js
|
||||||
other_name: fancyapps-ui
|
|
||||||
version: 6.1.14
|
version: 6.1.14
|
||||||
|
other_name: fancyapps-ui
|
||||||
fancybox_css:
|
fancybox_css:
|
||||||
name: '@fancyapps/ui'
|
name: '@fancyapps/ui'
|
||||||
file: dist/fancybox/fancybox.css
|
file: dist/fancybox/fancybox.css
|
||||||
other_name: fancyapps-ui
|
|
||||||
version: 6.1.14
|
version: 6.1.14
|
||||||
|
other_name: fancyapps-ui
|
||||||
fireworks:
|
fireworks:
|
||||||
name: butterfly-extsrc
|
name: butterfly-extsrc
|
||||||
file: dist/fireworks.min.js
|
file: dist/fireworks.min.js
|
||||||
@@ -104,12 +112,12 @@ katex:
|
|||||||
name: katex
|
name: katex
|
||||||
file: dist/katex.min.css
|
file: dist/katex.min.css
|
||||||
other_name: KaTeX
|
other_name: KaTeX
|
||||||
version: 0.18.1
|
version: 0.17.0
|
||||||
katex_copytex:
|
katex_copytex:
|
||||||
name: katex
|
name: katex
|
||||||
file: dist/contrib/copy-tex.min.js
|
file: dist/contrib/copy-tex.min.js
|
||||||
other_name: KaTeX
|
other_name: KaTeX
|
||||||
version: 0.18.1
|
version: 0.17.0
|
||||||
lazyload:
|
lazyload:
|
||||||
name: vanilla-lazyload
|
name: vanilla-lazyload
|
||||||
file: dist/lazyload.iife.min.js
|
file: dist/lazyload.iife.min.js
|
||||||
@@ -126,6 +134,10 @@ mermaid:
|
|||||||
name: mermaid
|
name: mermaid
|
||||||
file: dist/mermaid.min.js
|
file: dist/mermaid.min.js
|
||||||
version: 11.16.0
|
version: 11.16.0
|
||||||
|
meting_js:
|
||||||
|
name: butterfly-extsrc
|
||||||
|
file: metingjs/dist/Meting.min.js
|
||||||
|
version: 1.1.6
|
||||||
pace_default_css:
|
pace_default_css:
|
||||||
name: pace-js
|
name: pace-js
|
||||||
other_name: pace
|
other_name: pace
|
||||||
@@ -174,7 +186,7 @@ snackbar_css:
|
|||||||
twikoo:
|
twikoo:
|
||||||
name: twikoo
|
name: twikoo
|
||||||
file: dist/twikoo.all.min.js
|
file: dist/twikoo.all.min.js
|
||||||
version: 1.7.15
|
version: 1.7.14
|
||||||
typed:
|
typed:
|
||||||
name: typed.js
|
name: typed.js
|
||||||
file: dist/typed.umd.js
|
file: dist/typed.umd.js
|
||||||
|
|||||||
@@ -378,7 +378,6 @@ module.exports = {
|
|||||||
server: null,
|
server: null,
|
||||||
site: null,
|
site: null,
|
||||||
visitor: false,
|
visitor: false,
|
||||||
vote: false,
|
|
||||||
option: null
|
option: null
|
||||||
},
|
},
|
||||||
chat: {
|
chat: {
|
||||||
@@ -556,6 +555,10 @@ module.exports = {
|
|||||||
enable: false,
|
enable: false,
|
||||||
exclude: null
|
exclude: null
|
||||||
},
|
},
|
||||||
|
aplayerInject: {
|
||||||
|
enable: false,
|
||||||
|
per_page: true
|
||||||
|
},
|
||||||
snackbar: {
|
snackbar: {
|
||||||
enable: false,
|
enable: false,
|
||||||
position: 'bottom-left',
|
position: 'bottom-left',
|
||||||
|
|||||||
@@ -6,8 +6,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
hexo.extend.generator.register('404', function (locals) {
|
hexo.extend.generator.register('404', function (locals) {
|
||||||
const error404 = hexo.theme.config.error_404 || {}
|
if (!hexo.theme.config.error_404.enable) return
|
||||||
if (!error404.enable) return
|
|
||||||
return {
|
return {
|
||||||
path: '404.html',
|
path: '404.html',
|
||||||
layout: ['page'],
|
layout: ['page'],
|
||||||
|
|||||||
@@ -8,19 +8,11 @@
|
|||||||
const { version } = require('../../package.json')
|
const { version } = require('../../package.json')
|
||||||
const path = require('path')
|
const path = require('path')
|
||||||
|
|
||||||
// Cache plugins.yml to avoid re-rendering on every generate
|
|
||||||
let cachedPlugins = null
|
|
||||||
const loadPlugins = hexo => {
|
|
||||||
if (cachedPlugins) return cachedPlugins
|
|
||||||
cachedPlugins = hexo.render.renderSync({ path: path.join(hexo.theme_dir, '/plugins.yml'), engine: 'yaml' })
|
|
||||||
return cachedPlugins
|
|
||||||
}
|
|
||||||
|
|
||||||
hexo.extend.filter.register('before_generate', () => {
|
hexo.extend.filter.register('before_generate', () => {
|
||||||
const themeConfig = hexo.theme.config
|
const themeConfig = hexo.theme.config
|
||||||
const { CDN } = themeConfig
|
const { CDN } = themeConfig
|
||||||
|
|
||||||
const thirdPartySrc = loadPlugins(hexo)
|
const thirdPartySrc = hexo.render.renderSync({ path: path.join(hexo.theme_dir, '/plugins.yml'), engine: 'yaml' })
|
||||||
const internalSrc = {
|
const internalSrc = {
|
||||||
main: {
|
main: {
|
||||||
name: 'hexo-theme-butterfly',
|
name: 'hexo-theme-butterfly',
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
hexo.extend.filter.register('stylus:renderer', style => {
|
hexo.extend.filter.register('stylus:renderer', style => {
|
||||||
const { syntax_highlighter: syntaxHighlighter, highlight = {}, prismjs = {} } = hexo.config
|
const { syntax_highlighter: syntaxHighlighter, highlight, prismjs } = hexo.config
|
||||||
let { enable: highlightEnable, line_number: highlightLineNumber } = highlight
|
let { enable: highlightEnable, line_number: highlightLineNumber } = highlight
|
||||||
let { enable: prismjsEnable, line_number: prismjsLineNumber } = prismjs
|
let { enable: prismjsEnable, line_number: prismjsLineNumber } = prismjs
|
||||||
|
|
||||||
|
|||||||
@@ -69,14 +69,18 @@ hexo.extend.helper.register('aside_archives', function (options = {}) {
|
|||||||
|
|
||||||
// Use template literal for better readability
|
// Use template literal for better readability
|
||||||
const archiveHeader = `
|
const archiveHeader = `
|
||||||
<div class="item-headline"><i class="fas fa-archive"></i><span>${_p('aside.card_archives')}</span>${
|
<div class="item-headline">
|
||||||
|
<i class="fas fa-archive"></i>
|
||||||
|
<span>${_p('aside.card_archives')}</span>
|
||||||
|
${
|
||||||
data.length > limitedData.length
|
data.length > limitedData.length
|
||||||
? `<a class="card-more-btn" href="${urlFor(archiveDir)}/"
|
? `<a class="card-more-btn" href="${urlFor(archiveDir)}/"
|
||||||
title="${_p('aside.more_button')}">
|
title="${_p('aside.more_button')}">
|
||||||
<i class="fas fa-angle-right"></i>
|
<i class="fas fa-angle-right"></i>
|
||||||
</a>`
|
</a>`
|
||||||
: ''
|
: ''
|
||||||
}</div>
|
}
|
||||||
|
</div>
|
||||||
`
|
`
|
||||||
|
|
||||||
// Use map for generating list items, join for performance
|
// Use map for generating list items, join for performance
|
||||||
|
|||||||
@@ -89,7 +89,11 @@ hexo.extend.helper.register('aside_categories', function (categories, options =
|
|||||||
<i class="fas fa-angle-right"></i></a>`
|
<i class="fas fa-angle-right"></i></a>`
|
||||||
: ''
|
: ''
|
||||||
|
|
||||||
return `<div class="item-headline"><i class="fas fa-folder-open"></i><span>${this._p('aside.card_categories')}</span>${moreButton}</div>
|
return `<div class="item-headline">
|
||||||
|
<i class="fas fa-folder-open"></i>
|
||||||
|
<span>${this._p('aside.card_categories')}</span>
|
||||||
|
${moreButton}
|
||||||
|
</div>
|
||||||
<ul class="card-category-list${isExpand && list.result ? ' expandBtn' : ''}" id="aside-cat-list">
|
<ul class="card-category-list${isExpand && list.result ? ' expandBtn' : ''}" id="aside-cat-list">
|
||||||
${list.result}
|
${list.result}
|
||||||
</ul>`
|
</ul>`
|
||||||
|
|||||||
+1
-33
@@ -157,40 +157,8 @@ hexo.extend.helper.register('shuoshuoFN', (data, page) => {
|
|||||||
processedData.forEach(item => {
|
processedData.forEach(item => {
|
||||||
const parsed = moment.utc(item.date)
|
const parsed = moment.utc(item.date)
|
||||||
item.date = moment.tz(parsed.format('YYYY-MM-DD HH:mm:ss'), timezone).format('YYYY-MM-DD HH:mm:ss')
|
item.date = moment.tz(parsed.format('YYYY-MM-DD HH:mm:ss'), timezone).format('YYYY-MM-DD HH:mm:ss')
|
||||||
|
// markdown
|
||||||
// Render the content using Hexo's rendering engine to process any tags or markdown
|
|
||||||
const mockPost = {
|
|
||||||
content: item.content,
|
|
||||||
source: item.source || page.source || '',
|
|
||||||
full_source: page.full_source || '',
|
|
||||||
path: page.path || '',
|
|
||||||
layout: item.layout || page.layout || 'post',
|
|
||||||
raw: item.raw || item.content,
|
|
||||||
draft: false,
|
|
||||||
published: true
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
hexo.execFilterSync('before_post_render', mockPost, { context: hexo })
|
|
||||||
} catch (e) {
|
|
||||||
// ignore third-party plugin errors, fallback to markdown-only rendering
|
|
||||||
}
|
|
||||||
item.content = mockPost.content
|
|
||||||
|
|
||||||
const codeBlocks = []
|
|
||||||
item.content = item.content.replace(/<hexoPostRenderCodeBlock>([\s\S]*?)<\/hexoPostRenderCodeBlock>/g, (_, c) => {
|
|
||||||
codeBlocks.push(c)
|
|
||||||
return `<!--CODEBLOCK_${codeBlocks.length - 1}-->`
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
|
||||||
item.content = hexo.extend.tag.env.renderString(item.content, {})
|
|
||||||
} catch (e) {
|
|
||||||
// ignore tag plugin errors, fallback to markdown-only rendering
|
|
||||||
}
|
|
||||||
|
|
||||||
item.content = hexo.render.renderSync({ text: item.content, engine: 'markdown' })
|
item.content = hexo.render.renderSync({ text: item.content, engine: 'markdown' })
|
||||||
|
|
||||||
item.content = item.content.replace(/<!--CODEBLOCK_(\d+)-->/g, (_, i) => codeBlocks[+i])
|
|
||||||
})
|
})
|
||||||
|
|
||||||
return processedData
|
return processedData
|
||||||
|
|||||||
+16
-18
@@ -1,24 +1,22 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
// Read pre-built groups from tag/series.js (hexo._seriesGroups)
|
|
||||||
// and sort each group according to the sidebar card config.
|
|
||||||
hexo.extend.helper.register('groupPosts', function () {
|
hexo.extend.helper.register('groupPosts', function () {
|
||||||
const groups = hexo._seriesGroups || {}
|
const getGroupArray = array => {
|
||||||
const { orderBy = 'date', order = 1 } = this.theme.aside.card_post_series
|
return array.reduce((groups, item) => {
|
||||||
|
const key = item.series
|
||||||
const result = {}
|
if (key) {
|
||||||
Object.keys(groups).forEach(key => {
|
groups[key] = groups[key] || []
|
||||||
const arr = groups[key].slice() // copy to avoid mutating the shared data
|
groups[key].push(item)
|
||||||
if (orderBy === 'title') {
|
}
|
||||||
arr.sort((a, b) => {
|
return groups
|
||||||
const cmp = a.title.toUpperCase().localeCompare(b.title.toUpperCase())
|
}, {})
|
||||||
return order === 1 ? cmp : -cmp
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
arr.sort((a, b) => order === 1 ? a.date - b.date : b.date - a.date)
|
|
||||||
}
|
}
|
||||||
result[key] = arr
|
|
||||||
})
|
|
||||||
|
|
||||||
return result
|
const sortPosts = posts => {
|
||||||
|
const { orderBy = 'date', order = 1 } = this.theme.aside.card_post_series
|
||||||
|
if (orderBy === 'title') return posts.sort('title', order)
|
||||||
|
return posts.sort('date', order)
|
||||||
|
}
|
||||||
|
|
||||||
|
return getGroupArray(sortPosts(this.site.posts))
|
||||||
})
|
})
|
||||||
|
|||||||
+22
-43
@@ -10,42 +10,27 @@
|
|||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
const urlFor = require('hexo-util').url_for.bind(hexo)
|
const urlFor = require('hexo-util').url_for.bind(hexo)
|
||||||
|
|
||||||
// Iterate all posts once and group by series name.
|
|
||||||
// Result is stored on hexo._seriesGroups, shared by both tag and helper.
|
|
||||||
function buildSeriesGroups () {
|
|
||||||
const groups = {}
|
const groups = {}
|
||||||
const posts = hexo.model('Post').toArray()
|
|
||||||
for (let i = 0, len = posts.length; i < len; i++) {
|
|
||||||
const p = posts[i]
|
|
||||||
if (p.series) {
|
|
||||||
if (!groups[p.series]) groups[p.series] = []
|
|
||||||
groups[p.series].push({
|
|
||||||
title: p.title,
|
|
||||||
path: p.path,
|
|
||||||
date: p.date.valueOf()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return groups
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build once before the first render (hexo generate / hexo server initial load).
|
hexo.extend.filter.register('before_generate', () => {
|
||||||
// before_generate runs after tag rendering, so we need this as a fallback.
|
Object.keys(groups).forEach(k => delete groups[k])
|
||||||
|
})
|
||||||
|
|
||||||
hexo.extend.filter.register('before_post_render', data => {
|
hexo.extend.filter.register('before_post_render', data => {
|
||||||
if (!hexo.theme.config.series.enable) return data
|
if (!hexo.theme.config.series.enable) return data
|
||||||
if (!hexo._seriesGroups) {
|
|
||||||
hexo._seriesGroups = buildSeriesGroups()
|
const { layout, series } = data
|
||||||
|
if (layout === 'post' && series) {
|
||||||
|
if (!groups[series]) groups[series] = []
|
||||||
|
groups[series].push({
|
||||||
|
title: data.title,
|
||||||
|
path: data.path,
|
||||||
|
date: data.date.unix()
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return data
|
return data
|
||||||
})
|
})
|
||||||
|
|
||||||
// Rebuild after each generate cycle in hexo server to reflect latest post data.
|
|
||||||
hexo.extend.filter.register('before_generate', () => {
|
|
||||||
if (!hexo.theme.config.series.enable) return
|
|
||||||
hexo._seriesGroups = buildSeriesGroups()
|
|
||||||
})
|
|
||||||
|
|
||||||
function series (args) {
|
function series (args) {
|
||||||
const { series } = hexo.theme.config
|
const { series } = hexo.theme.config
|
||||||
if (!series.enable) {
|
if (!series.enable) {
|
||||||
@@ -53,30 +38,24 @@ function series (args) {
|
|||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const groupName = args.length ? args[0] : this.series
|
const seriesArr = args.length ? groups[args[0]] : groups[this.series]
|
||||||
|
|
||||||
if (!groupName) {
|
if (!seriesArr) {
|
||||||
hexo.log.warn('No series specified')
|
hexo.log.warn(`There is no series named "${args[0]}"`)
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
const groups = hexo._seriesGroups || {}
|
const isAsc = (series.order || 1) === 1 // 1: asc, -1: desc
|
||||||
const source = groups[groupName]
|
|
||||||
|
|
||||||
if (!source || !source.length) {
|
|
||||||
hexo.log.warn(`There is no series named "${groupName}"`)
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
|
|
||||||
const isAsc = (series.order || 1) === 1
|
|
||||||
const isSortByTitle = series.orderBy === 'title'
|
const isSortByTitle = series.orderBy === 'title'
|
||||||
|
|
||||||
// .slice() to copy before sorting, so we don't mutate the shared data
|
const compareFn = (a, b) => {
|
||||||
const seriesArr = source.slice().sort((a, b) => {
|
|
||||||
const itemA = isSortByTitle ? a.title.toUpperCase() : a.date
|
const itemA = isSortByTitle ? a.title.toUpperCase() : a.date
|
||||||
const itemB = isSortByTitle ? b.title.toUpperCase() : b.date
|
const itemB = isSortByTitle ? b.title.toUpperCase() : b.date
|
||||||
|
|
||||||
return itemA < itemB ? (isAsc ? -1 : 1) : itemA > itemB ? (isAsc ? 1 : -1) : 0
|
return itemA < itemB ? (isAsc ? -1 : 1) : itemA > itemB ? (isAsc ? 1 : -1) : 0
|
||||||
})
|
}
|
||||||
|
|
||||||
|
seriesArr.sort(compareFn)
|
||||||
|
|
||||||
const listItems = seriesArr.map(ele =>
|
const listItems = seriesArr.map(ele =>
|
||||||
`<li><a href="${urlFor(ele.path)}" title="${ele.title}">${ele.title}</a></li>`
|
`<li><a href="${urlFor(ele.path)}" title="${ele.title}">${ele.title}</a></li>`
|
||||||
|
|||||||
@@ -131,10 +131,6 @@ body
|
|||||||
*::-webkit-scrollbar-track
|
*::-webkit-scrollbar-track
|
||||||
background-color: transparent
|
background-color: transparent
|
||||||
|
|
||||||
// make the scrollbar transparent when fancybox is open
|
|
||||||
html.with-fancybox
|
|
||||||
--scrollbar-color: transparent
|
|
||||||
|
|
||||||
input::placeholder
|
input::placeholder
|
||||||
color: var(--font-color)
|
color: var(--font-color)
|
||||||
|
|
||||||
|
|||||||
@@ -28,107 +28,6 @@
|
|||||||
.wl-comment-actions > button:not(last-child)
|
.wl-comment-actions > button:not(last-child)
|
||||||
padding-right: 4px
|
padding-right: 4px
|
||||||
|
|
||||||
if hexo-config('artalk.vote')
|
|
||||||
.artalk-vote
|
|
||||||
display: flex
|
|
||||||
justify-content: center
|
|
||||||
align-items: center
|
|
||||||
margin: 4px 0 20px
|
|
||||||
gap: 10px
|
|
||||||
|
|
||||||
.artalk-page-vote-up,
|
|
||||||
.artalk-page-vote-down
|
|
||||||
position: relative
|
|
||||||
display: inline-flex
|
|
||||||
align-items: center
|
|
||||||
overflow: hidden
|
|
||||||
padding: 5px 16px
|
|
||||||
border: 1px solid alpha($theme-color, .15)
|
|
||||||
gap: 6px
|
|
||||||
addBorderRadius(8)
|
|
||||||
background: var(--card-bg)
|
|
||||||
color: var(--font-color)
|
|
||||||
font-weight: 500
|
|
||||||
font-size: .95em
|
|
||||||
cursor: pointer
|
|
||||||
transition: all .2s ease
|
|
||||||
user-select: none
|
|
||||||
|
|
||||||
i,
|
|
||||||
.artalk-page-vote-up-count,
|
|
||||||
.artalk-page-vote-down-count
|
|
||||||
position: relative
|
|
||||||
z-index: 1
|
|
||||||
|
|
||||||
i
|
|
||||||
font-size: 1em
|
|
||||||
line-height: 1
|
|
||||||
|
|
||||||
.artalk-page-vote-up-count,
|
|
||||||
.artalk-page-vote-down-count
|
|
||||||
min-width: 1em
|
|
||||||
text-align: center
|
|
||||||
font-weight: 600
|
|
||||||
font-size: .9em
|
|
||||||
font-variant-numeric: tabular-nums
|
|
||||||
|
|
||||||
&::after
|
|
||||||
position: absolute
|
|
||||||
top: 50%
|
|
||||||
left: 50%
|
|
||||||
z-index: 0
|
|
||||||
width: 8px
|
|
||||||
height: 8px
|
|
||||||
border-radius: 50%
|
|
||||||
content: ''
|
|
||||||
opacity: 0
|
|
||||||
pointer-events: none
|
|
||||||
|
|
||||||
&:hover
|
|
||||||
border-color: $theme-color
|
|
||||||
|
|
||||||
&:active
|
|
||||||
transform: scale(.95)
|
|
||||||
|
|
||||||
&::after
|
|
||||||
animation: artalkVoteRipple .6s ease-out forwards
|
|
||||||
|
|
||||||
.artalk-page-vote-up
|
|
||||||
&:hover,
|
|
||||||
&.active
|
|
||||||
border-color: $theme-color
|
|
||||||
background: alpha($theme-color, .1)
|
|
||||||
color: $theme-color
|
|
||||||
|
|
||||||
&::after
|
|
||||||
background: alpha($theme-color, .5)
|
|
||||||
|
|
||||||
.artalk-page-vote-down
|
|
||||||
&:hover,
|
|
||||||
&.active
|
|
||||||
border-color: $light-red
|
|
||||||
background: alpha($light-red, .1)
|
|
||||||
color: $light-red
|
|
||||||
|
|
||||||
&::after
|
|
||||||
background: alpha($light-red, .5)
|
|
||||||
|
|
||||||
+maxWidth600()
|
|
||||||
gap: 8px
|
|
||||||
|
|
||||||
.artalk-page-vote-up,
|
|
||||||
.artalk-page-vote-down
|
|
||||||
padding: 4px 12px
|
|
||||||
|
|
||||||
@keyframes artalkVoteRipple
|
|
||||||
0%
|
|
||||||
opacity: .8
|
|
||||||
transform: translate(-50%, -50%) scale(0)
|
|
||||||
|
|
||||||
100%
|
|
||||||
opacity: 0
|
|
||||||
transform: translate(-50%, -50%) scale(20)
|
|
||||||
|
|
||||||
if hexo-config('valine.bg')
|
if hexo-config('valine.bg')
|
||||||
#vcomment
|
#vcomment
|
||||||
textarea
|
textarea
|
||||||
@@ -294,6 +193,26 @@ if hexo-config('math.use')
|
|||||||
right: 0
|
right: 0
|
||||||
bottom: 0
|
bottom: 0
|
||||||
|
|
||||||
|
.aplayer
|
||||||
|
color: $font-black
|
||||||
|
|
||||||
|
.container
|
||||||
|
.aplayer
|
||||||
|
margin: 0 0 20px
|
||||||
|
|
||||||
|
if hexo-config('beautify.enable')
|
||||||
|
ol,
|
||||||
|
ul
|
||||||
|
margin: 0
|
||||||
|
padding: 0
|
||||||
|
|
||||||
|
li
|
||||||
|
margin: 0
|
||||||
|
padding: 0 15px
|
||||||
|
|
||||||
|
&:before
|
||||||
|
content: none
|
||||||
|
|
||||||
.snackbar-container.snackbar-css
|
.snackbar-container.snackbar-css
|
||||||
addBorderRadius(5)
|
addBorderRadius(5)
|
||||||
opacity: .85 !important
|
opacity: .85 !important
|
||||||
|
|||||||
@@ -105,6 +105,9 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark'
|
|||||||
code
|
code
|
||||||
background: $code-background
|
background: $code-background
|
||||||
|
|
||||||
|
.aplayer
|
||||||
|
filter: brightness(.8)
|
||||||
|
|
||||||
kbd
|
kbd
|
||||||
border-color: #696969
|
border-color: #696969
|
||||||
background-color: #525252
|
background-color: #525252
|
||||||
|
|||||||
+1
-6
@@ -995,11 +995,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
GLOBAL_CONFIG_SITE.pageType === 'home' && scrollDownInIndex()
|
GLOBAL_CONFIG_SITE.pageType === 'home' && scrollDownInIndex()
|
||||||
scrollFn()
|
scrollFn()
|
||||||
|
|
||||||
if (GLOBAL_CONFIG_SITE.pageType !== 'shuoshuo') {
|
|
||||||
forPostFn()
|
forPostFn()
|
||||||
btf.switchComments(document)
|
GLOBAL_CONFIG_SITE.pageType !== 'shuoshuo' && btf.switchComments(document)
|
||||||
}
|
|
||||||
|
|
||||||
openMobileMenu()
|
openMobileMenu()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,6 +1012,4 @@ document.addEventListener('DOMContentLoaded', () => {
|
|||||||
fn()
|
fn()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener('shuoshuo:rendered', forPostFn)
|
|
||||||
})
|
})
|
||||||
|
|||||||
+2
-4
@@ -243,8 +243,7 @@
|
|||||||
],
|
],
|
||||||
right: ['slideshow', 'thumbs', 'close']
|
right: ['slideshow', 'thumbs', 'close']
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
hideScrollbar: false
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
options = {
|
options = {
|
||||||
@@ -275,8 +274,7 @@
|
|||||||
maxScale: 4
|
maxScale: 4
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
hideScrollbar: false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user