由於整合了多個設定並更改了部分設定名稱,升級到 5.0 版本時,請重新設定 `_config.yml` 文件。

1. 新增 macstyle 設定,取消 mac / mac light 主題設定
2. 整合搜索相關設定
3. 修改程式碼區塊設定
4. 主頁文章新增多種版面配置
5. 新增說說頁面
6. 適配 hexo-blog-encrypt 加密插件
7. 改善手機端目錄的開啟效果
8. 新增平滑滾動功能
9. 支持以程式碼區塊方式撰寫 mermaid 圖表
10. 可自訂文章標題位置
11. 新增程式碼全螢幕按鈕
12. 友情連結頭像改為圓角設計
13. 優化程式碼,使用 hexo-util 的參數和 hexo 內建參數
14. 可自訂搜索框提示文字
15. 未設定選單時,不顯示側邊欄目錄和按鈕
16. 螢幕寬度超過 2000px 時,增加卡片高度
17. 根據語言設定調整字體:簡體中文使用雅黑,其他使用正黑體
18. 更新 plugins.yml
19. 全新的側邊欄界面設計
20. 新增 giscus 的 js 設定
21. 調整 utterances js 的設定位置
22. 新增 utterances option 設定
23. 修改 giscus 的主題設定
24. 多個界面元素改為圓角設計
25. 可選擇圓角或直角界面風格
26. 圖庫加載按鈕新增圖標
27. 改善標籤頁面的滑鼠懸停效果
28. 調整側邊欄的滑鼠懸停效果
29. 微調部分界面元素

1. 修復 Hexo 新版本下 Prism.js 無法正確高亮的問題
2. 修復文章標籤為空時可能出現的錯誤
3. 修正 mermaid 圖表可能出現的錯誤
4. 解決未設定選單時控制台報錯的問題
5. 修復 Algolia 搜索的每頁顯示數量設定無效的問題
6. 解決 Algolia 搜索結果出現滾動條的問題
7. 修正滾動條出現上下按鈕的問題
8. 修復圖庫遠程連結未加前綴的問題
9. 修正 label 標籤外掛右側多餘空格的問題
10. 解決 APlayer 報告內存洩漏的問題

1. 優化 PJAX 下的函數調用
2. 整體代碼優化
3. 提升兼容性
4. 改善 Lighthouse 評分
5. 在 PJAX 關閉時減少不必要的全局變量
6. 優化 Waline 的 import 兼容性
7. 改善頁面進入效果
8. 優化程式碼區塊工具列顯示邏輯
9. 改善不同螢幕寬度下文章標題位置的顯示
10. 優化標籤顏色生成算法,避免過暗或過亮
11. 調整 Artalk 和 Waline 在夜間模式下的字體顏色,與主題保持一致
12. 調整 Algolia 搜索加載動畫位置,避免換行
13. 優化 Algolia 搜索結果為空時的處理
14. 改善系列文章的滑鼠懸停效果
15. 優化 404 頁面代碼
16. 解決搜索和側邊欄開啟時窗口抖動的問題
17. 優化 tabs 標籤外掛的代碼和效能
18. 改善 tabs 中使用 gallery 標籤外掛時的圖片加載邏輯
19. 優化目錄滾動效果,使當前標題保持在中間
20. 調整螢幕寬度超過 1024px 時 gallerygroup 的顯示數量
pull/1550/head
Jerry 2 months ago
parent 0d52505331
commit 06f543ed96

@ -7,11 +7,12 @@ body:
attributes: attributes:
value: | value: |
重要:請依照該模板來提交 重要:請依照該模板來提交
Please follow the template to create a new issue Important: Please follow the template to create a new issue
- type: input - type: input
id: butterfly-ver id: butterfly-ver
attributes: attributes:
label: 使用的 Butterfly 版本? | What version of Butterfly are you use? label: 使用的 Butterfly 版本? | What version of Butterfly are you using?
description: 檢視主題的 package.json | Check the theme's package.json description: 檢視主題的 package.json | Check the theme's package.json
validations: validations:
required: true required: true
@ -19,17 +20,17 @@ body:
- type: dropdown - type: dropdown
id: modify id: modify
attributes: attributes:
label: 是否修改过主题文件? || Has the theme files been modified? label: 是否修改過主題文件? | Has the theme files been modified?
options: options:
- 是 (Yes) - 是 (Yes)
- 不是 (No) - (No)
validations: validations:
required: true required: true
- type: dropdown - type: dropdown
id: browser id: browser
attributes: attributes:
label: 使用的瀏覽器? || What browse are you using? label: 使用的瀏覽器? | What browser are you using?
options: options:
- Chrome - Chrome
- Edge - Edge
@ -42,7 +43,7 @@ body:
- type: dropdown - type: dropdown
id: platform id: platform
attributes: attributes:
label: 使用的系統? || What operating system are you using? label: 使用的系統? | What operating system are you using?
options: options:
- Windows - Windows
- macOS - macOS
@ -56,7 +57,7 @@ body:
- type: textarea - type: textarea
id: dependencies id: dependencies
attributes: attributes:
label: 依賴插件 | Package dependencies Information label: 依賴插件 | Package dependencies information
description: 在 Hexo 根目錄下執行 `npm ls --depth 0` | Run `npm ls --depth 0` in Hexo root directory description: 在 Hexo 根目錄下執行 `npm ls --depth 0` | Run `npm ls --depth 0` in Hexo root directory
render: Text render: Text
validations: validations:
@ -75,8 +76,8 @@ body:
- type: input - type: input
id: website id: website
attributes: attributes:
label: 出現問題網站 | Website label: 出現問題網站 | Website with the issue
description: 請提供下可復現網站地址 | Please supply a website url which can reproduce problem. description: 請提供可復現問題的網站地址 | Please provide a website URL where the problem can be reproduced.
placeholder: placeholder: 請填寫具體的網址,不要填寫 localhost 網站 | Please provide a specific URL, do not use localhost.
validations: validations:
required: true required: true

@ -2,6 +2,10 @@
<a title="Chinese" href="/README_CN.md">中文</a> <a title="Chinese" href="/README_CN.md">中文</a>
</div> </div>
<div align="center">
<img src="./source/img/butterfly-icon.png" width="150" height="150" />
# hexo-theme-butterfly # hexo-theme-butterfly
![master version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly/master?color=%231ab1ad&label=master) ![master version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly/master?color=%231ab1ad&label=master)
@ -10,13 +14,15 @@
![hexo version](https://img.shields.io/badge/hexo-5.3.0+-0e83c) ![hexo version](https://img.shields.io/badge/hexo-5.3.0+-0e83c)
![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531) ![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531)
![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) 📢 Demo: [Butterfly](https://butterfly.js.org/) / [CrazyWong](https://blog.crazywong.com/)
📢 Demo: [Butterfly](https://butterfly.js.org/) || [CrazyWong](https://blog.crazywong.com/) 📖 Docs: [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) / [Chinese](https://butterfly.js.org/posts/21cfbf15/)
📖 Docs: [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) || [Chinese](https://butterfly.js.org/posts/21cfbf15/) ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png)
</div>
Based on [hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody) theme. ---
## 💻 Installation ## 💻 Installation
@ -59,6 +65,7 @@ npm i hexo-theme-butterfly
## 🎉 Features ## 🎉 Features
- [x] Card UI Design - [x] Card UI Design
- [x] Rounded Design/Squared Design
- [X] Support sub-menu - [X] Support sub-menu
- [x] Two-column layout - [x] Two-column layout
- [x] Responsive Web Design - [x] Responsive Web Design

@ -2,6 +2,10 @@
<a title="English" href="/README.md">English</a> <a title="English" href="/README.md">English</a>
</div> </div>
<div align="center">
<img src="./source/img/butterfly-icon.png" width="150" height="150" />
# hexo-theme-butterfly # hexo-theme-butterfly
![master version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly/master?color=%231ab1ad&label=master) ![master version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly/master?color=%231ab1ad&label=master)
@ -10,13 +14,15 @@
![hexo version](https://img.shields.io/badge/hexo-5.3.0+-0e83c) ![hexo version](https://img.shields.io/badge/hexo-5.3.0+-0e83c)
![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531) ![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531)
![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) 📢 預覽: [Butterfly](https://butterfly.js.org/) / [CrazyWong](https://blog.crazywong.com/)
📢 預覽: [Butterfly](https://butterfly.js.org/) || [CrazyWong](https://blog.crazywong.com/) 📖 文檔: [中文](https://butterfly.js.org/posts/21cfbf15/) / [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/)
📖 文檔: [中文](https://butterfly.js.org/posts/21cfbf15/) || [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png)
</div>
一款基於[hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody)修改的主題 ---
## 💻 安裝 ## 💻 安裝
@ -59,6 +65,7 @@ theme: butterfly
## 🎉 特色 ## 🎉 特色
- [x] 卡片化設計 - [x] 卡片化設計
- [x] 圓角化設計/直角化設計
- [X] 支持二級目錄 - [X] 支持二級目錄
- [x] 雙欄設計 - [x] 雙欄設計
- [x] 響應式主題 - [x] 響應式主題

File diff suppressed because it is too large Load Diff

@ -36,13 +36,11 @@ post:
search: search:
title: Search title: Search
load_data: Loading the Database load_data: Loading the Database
algolia_search:
input_placeholder: Search for Posts input_placeholder: Search for Posts
algolia_search:
hits_empty: "We didn't find any results for the search: ${query}." hits_empty: "We didn't find any results for the search: ${query}."
hits_stats: '${hits} results found in ${time} ms' hits_stats: '${hits} results found in ${time} ms'
local_search: local_search:
input_placeholder: Search for Posts
hits_empty: "We didn't find any results for the search: ${query}" hits_empty: "We didn't find any results for the search: ${query}"
hits_stats: '${hits} results found' hits_stats: '${hits} results found'

@ -36,13 +36,11 @@ post:
search: search:
title: Search title: Search
load_data: Loading the Database load_data: Loading the Database
algolia_search:
input_placeholder: Search for Posts input_placeholder: Search for Posts
algolia_search:
hits_empty: "We didn't find any results for the search: ${query}." hits_empty: "We didn't find any results for the search: ${query}."
hits_stats: '${hits} results found in ${time} ms' hits_stats: '${hits} results found in ${time} ms'
local_search: local_search:
input_placeholder: Search for Posts
hits_empty: "We didn't find any results for the search: ${query}" hits_empty: "We didn't find any results for the search: ${query}"
hits_stats: '${hits} results found' hits_stats: '${hits} results found'

@ -37,13 +37,11 @@ post:
search: search:
title: 搜索 title: 搜索
load_data: 数据库加载中 load_data: 数据库加载中
algolia_search:
input_placeholder: 搜索文章 input_placeholder: 搜索文章
algolia_search:
hits_empty: '找不到您查询的内容:${query}' hits_empty: '找不到您查询的内容:${query}'
hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒'
local_search: local_search:
input_placeholder: 搜索文章
hits_empty: '找不到您查询的内容:${query}' hits_empty: '找不到您查询的内容:${query}'
hits_stats: '共找到 ${hits} 篇文章' hits_stats: '共找到 ${hits} 篇文章'

@ -15,7 +15,7 @@ page:
card_post_count: 條評論 card_post_count: 條評論
no_title: no_title:
post: post:
created: 發表於 created: 發表於
@ -28,8 +28,8 @@ post:
copyright: copyright:
author: 文章作者 author: 文章作者
link: 文章連結 link: 文章連結
copyright_notice: 版權聲明 copyright_notice: 版權宣告
copyright_content: '本部落格所有文章除特別聲明外,均採用 copyright_content: '本部落格所有文章除特別宣告外,均採用
<a href="%s" target="_blank">%s</a> 許可協議。轉載請註明來自 <a href="%s" target="_blank">%s</a>' <a href="%s" target="_blank">%s</a> 許可協議。轉載請註明來自 <a href="%s" target="_blank">%s</a>'
recommend: 相關推薦 recommend: 相關推薦
edit: 編輯 edit: 編輯
@ -37,13 +37,11 @@ post:
search: search:
title: 搜尋 title: 搜尋
load_data: 資料庫載入中 load_data: 資料庫載入中
algolia_search:
input_placeholder: 搜尋文章 input_placeholder: 搜尋文章
algolia_search:
hits_empty: '找不到您查詢的內容:${query}' hits_empty: '找不到您查詢的內容:${query}'
hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒'
local_search: local_search:
input_placeholder: 搜尋文章
hits_empty: '找不到您查詢的內容:${query}' hits_empty: '找不到您查詢的內容:${query}'
hits_stats: '共找到 ${hits} 篇文章' hits_stats: '共找到 ${hits} 篇文章'
@ -83,7 +81,7 @@ aside:
link: 連結 link: 連結
code: 程式碼 code: 程式碼
card_toc: 目錄 card_toc: 目錄
card_post_series: 文章系列 card_post_series: 系列文章
date_suffix: date_suffix:
just: 剛剛 just: 剛剛
@ -99,7 +97,7 @@ rightside:
readmode_title: 閱讀模式 readmode_title: 閱讀模式
translate_title: 簡繁轉換 translate_title: 簡繁轉換
night_mode_title: 淺色和深色模式轉換 night_mode_title: 淺色和深色模式轉換
back_to_top: 回頂部 back_to_top: 頂部
toc: 目錄 toc: 目錄
scroll_to_comment: 直達評論 scroll_to_comment: 直達評論
setting: 設定 setting: 設定
@ -110,7 +108,7 @@ copy_copyright:
author: 作者 author: 作者
link: 連結 link: 連結
source: 來源 source: 來源
info: 著作權歸作者所有。商業轉載請聯作者獲得授權,非商業轉載請註明出處。 info: 著作權歸作者所有。商業轉載請聯作者獲得授權,非商業轉載請註明出處。
Snackbar: Snackbar:
chs_to_cht: 你已切換為繁體中文 chs_to_cht: 你已切換為繁體中文

@ -2,10 +2,8 @@ extends includes/layout.pug
block content block content
if theme.category_ui == 'index' if theme.category_ui == 'index'
include ./includes/mixins/post-ui.pug include ./includes/mixins/indexPostUI.pug
#recent-posts.recent-posts.category_ui +indexPostUI
+postUI
include includes/pagination.pug
else else
include ./includes/mixins/article-sort.pug include ./includes/mixins/article-sort.pug
#category #category

@ -1,12 +0,0 @@
- var top_img_404 = theme.error_404.background || theme.default_top_img
#body-wrap.error404
include ./header/index.pug
#error-wrap
.error-content
.error-img
img(src=url_for(top_img_404) alt='Page not found')
.error-info
h1.error_title= '404'
.error_subtitle= theme.error_404.subtitle || _p('error404')

@ -5,9 +5,9 @@ div
if theme.translate.enable if theme.translate.enable
script(src=url_for(theme.asset.translate)) script(src=url_for(theme.asset.translate))
if theme.medium_zoom if theme.lightbox === 'medium_zoom'
script(src=url_for(theme.asset.medium_zoom)) script(src=url_for(theme.asset.medium_zoom))
else if theme.fancybox else if theme.lightbox === 'fancybox'
script(src=url_for(theme.asset.fancybox)) script(src=url_for(theme.asset.fancybox))
if theme.instantpage if theme.instantpage
@ -38,7 +38,7 @@ div
!= partial("includes/third-party/prismjs", {}, { cache: true }) != partial("includes/third-party/prismjs", {}, { cache: true })
if theme.aside.enable && theme.newest_comments.enable if theme.aside.enable && theme.aside.card_newest_comments.enable
if theme.pjax.enable if theme.pjax.enable
!= partial("includes/third-party/newest-comments/index", {}, { cache: true }) != partial("includes/third-party/newest-comments/index", {}, { cache: true })
else if (!is_post() && page.aside !== false) else if (!is_post() && page.aside !== false)

@ -45,7 +45,7 @@ link(rel='stylesheet', href=url_for(theme.asset.fontawesome))
if (theme.snackbar && theme.snackbar.enable) if (theme.snackbar && theme.snackbar.enable)
link(rel='stylesheet', href=url_for(theme.asset.snackbar_css) media="print" onload="this.media='all'") link(rel='stylesheet', href=url_for(theme.asset.snackbar_css) media="print" onload="this.media='all'")
if theme.fancybox if theme.lightbox === 'fancybox'
link(rel='stylesheet' href=url_for(theme.asset.fancybox_css) media="print" onload="this.media='all'") link(rel='stylesheet' href=url_for(theme.asset.fancybox_css) media="print" onload="this.media='all'")
!=fragment_cache('injectHeadJs', function(){return inject_head_js()}) !=fragment_cache('injectHeadJs', function(){return inject_head_js()})

@ -10,5 +10,7 @@ if theme.Open_Graph_meta.enable
- -
!= open_graph(ogOption) != open_graph(ogOption)
else else
meta(name="description" content=page_description()) - const description = page.description || page.content || page.title || config.description
if description
meta(name="description" content=truncate(description, 150))

@ -1,28 +1,30 @@
- -
let algolia = 'undefined'; let algolia = 'undefined'
let env = process.env; if (theme.search.use === 'algolia_search') {
if (theme.algolia_search.enable) { const { ALGOLIA_APP_ID, ALGOLIA_API_KEY, ALGOLIA_INDEX_NAME } = process.env
const { appId, applicationID, apiKey, indexName } = config.algolia
algolia = JSON.stringify({ algolia = JSON.stringify({
appId: env.ALGOLIA_APP_ID || config.algolia.appId || config.algolia.applicationID, appId: ALGOLIA_APP_ID || appId || applicationID,
apiKey: env.ALGOLIA_API_KEY || config.algolia.apiKey, apiKey: ALGOLIA_API_KEY || apiKey,
indexName: env.ALGOLIA_INDEX_NAME || config.algolia.indexName, indexName: ALGOLIA_INDEX_NAME || indexName,
hits: theme.algolia_search.hits, hitsPerPage: theme.search.algolia_search.hitsPerPage,
// search languages // search languages
languages: { languages: {
input_placeholder: _p("search.algolia_search.input_placeholder"), input_placeholder: theme.search.placeholder || _p("search.input_placeholder"),
hits_empty: _p("search.algolia_search.hits_empty"), hits_empty: _p("search.algolia_search.hits_empty"),
hits_stats: _p("search.algolia_search.hits_stats"), hits_stats: _p("search.algolia_search.hits_stats"),
} }
}) })
} }
let localSearch = 'undefined'; let localSearch = 'undefined'
if (theme.local_search && theme.local_search.enable) { if (theme.search.use === 'local_search') {
const { CDN, preload, top_n_per_article, unescape } = theme.search.local_search
localSearch = JSON.stringify({ localSearch = JSON.stringify({
path: theme.local_search.CDN ? theme.local_search.CDN : config.root + config.search.path, path: CDN || config.root + config.search.path,
preload: theme.local_search.preload, preload,
top_n_per_article: theme.local_search.top_n_per_article, top_n_per_article,
unescape: theme.local_search.unescape, unescape,
languages: { languages: {
// search languages // search languages
hits_empty: _p("search.local_search.hits_empty"), hits_empty: _p("search.local_search.hits_empty"),
@ -31,7 +33,7 @@
}) })
} }
let translate = 'undefined'; let translate = 'undefined'
if (theme.translate && theme.translate.enable){ if (theme.translate && theme.translate.enable){
translate = JSON.stringify({ translate = JSON.stringify({
defaultEncoding: theme.translate.defaultEncoding, defaultEncoding: theme.translate.defaultEncoding,
@ -41,7 +43,7 @@
}) })
} }
let copyright = 'undefined'; let copyright = 'undefined'
if (theme.copy.enable && theme.copy.copyright.enable){ if (theme.copy.enable && theme.copy.copyright.enable){
copyright = JSON.stringify({ copyright = JSON.stringify({
limitCount: theme.copy.copyright.limit_count, limitCount: theme.copy.copyright.limit_count,
@ -54,7 +56,7 @@
}) })
} }
let Snackbar = 'undefined'; let Snackbar = 'undefined'
if (theme.snackbar && theme.snackbar.enable) { if (theme.snackbar && theme.snackbar.enable) {
Snackbar = JSON.stringify({ Snackbar = JSON.stringify({
chs_to_cht: _p("Snackbar.chs_to_cht"), chs_to_cht: _p("Snackbar.chs_to_cht"),
@ -67,7 +69,7 @@
}) })
} }
let noticeOutdate = 'undefined'; let noticeOutdate = 'undefined'
if (theme.noticeOutdate && theme.noticeOutdate.enable) { if (theme.noticeOutdate && theme.noticeOutdate.enable) {
noticeOutdate = JSON.stringify({ noticeOutdate = JSON.stringify({
limitDay: theme.noticeOutdate.limit_day, limitDay: theme.noticeOutdate.limit_day,
@ -77,17 +79,18 @@
}) })
} }
let highlight = 'undefined'; let highlight = 'undefined'
let syntaxHighlighter = config.syntax_highlighter; let syntaxHighlighter = config.syntax_highlighter
let highlightEnable = syntaxHighlighter ? ['highlight.js', 'prismjs'].includes(syntaxHighlighter) : (config.highlight.enable || config.prismjs.enable); let highlightEnable = syntaxHighlighter ? ['highlight.js', 'prismjs'].includes(syntaxHighlighter) : (config.highlight.enable || config.prismjs.enable)
if (highlightEnable) { if (highlightEnable) {
const { copy, language, height_limit, fullpage, macStyle } = theme.code_blocks
highlight = JSON.stringify({ highlight = JSON.stringify({
plugin: syntaxHighlighter ? syntaxHighlighter : config.highlight.enable ? 'highlight.js' : 'prismjs', plugin: syntaxHighlighter ? syntaxHighlighter : config.highlight.enable ? 'highlight.js' : 'prismjs',
highlightCopy: theme.highlight_copy, highlightCopy: copy,
highlightLang: theme.highlight_lang, highlightLang: language,
highlightHeightLimit: theme.highlight_height_limit, highlightHeightLimit: height_limit,
highlightFullpage: theme.highlight_fullpage, highlightFullpage: fullpage,
highlightMacStyle: theme.highlight_theme_macStyle highlightMacStyle: macStyle
}) })
} }
@ -108,7 +111,7 @@ script.
homepage: !{theme.post_meta.page.date_format === 'relative'}, homepage: !{theme.post_meta.page.date_format === 'relative'},
post: !{theme.post_meta.post.date_format === 'relative'} post: !{theme.post_meta.post.date_format === 'relative'}
}, },
runtime: '!{theme.runtimeshow.enable ? _p("aside.card_webinfo.runtime.unit") : ""}', runtime: '!{theme.aside.card_webinfo.runtime_date ? _p("aside.card_webinfo.runtime.unit") : ""}',
dateSuffix: { dateSuffix: {
just: '!{_p("date_suffix.just")}', just: '!{_p("date_suffix.just")}',
min: '!{_p("date_suffix.min")}', min: '!{_p("date_suffix.min")}',
@ -117,7 +120,7 @@ script.
month: '!{_p("date_suffix.month")}' month: '!{_p("date_suffix.month")}'
}, },
copyright: !{copyright}, copyright: !{copyright},
lightbox: '!{ theme.medium_zoom ? "mediumZoom" : (theme.fancybox ? "fancybox" : "null" )}', lightbox: '!{ theme.lightbox || 'null' }',
Snackbar: !{Snackbar}, Snackbar: !{Snackbar},
infinitegrid: { infinitegrid: {
js: '!{url_for(theme.asset.egjs_infinitegrid)}', js: '!{url_for(theme.asset.egjs_infinitegrid)}',

@ -2,20 +2,17 @@
const titleVal = pageTitle.replace(/'/ig,"\\'") const titleVal = pageTitle.replace(/'/ig,"\\'")
let isHighlightShrink let isHighlightShrink
if (theme.highlight_shrink == 'none') isHighlightShrink = 'undefined' if (theme.code_blocks.shrink == 'none') isHighlightShrink = 'undefined'
else if (page.highlight_shrink === true || page.highlight_shrink === false) isHighlightShrink = page.highlight_shrink else if (typeof page.highlight_shrink == 'boolean') isHighlightShrink = page.highlight_shrink
else isHighlightShrink = theme.highlight_shrink else isHighlightShrink = theme.code_blocks.shrink
var showToc = false var showToc = false
if (theme.aside.enable && page.aside !== false) { if (theme.aside.enable && page.aside !== false) {
let tocEnable = false let tocEnable = false
if (is_post()) { if (is_post() && theme.toc.post) tocEnable = true
if (theme.toc.post) tocEnable = true else if (is_page() && theme.toc.page) tocEnable = true
} else if (is_page()) { const pageToc = typeof page.toc === 'boolean' ? page.toc : tocEnable
if (theme.toc.page) tocEnable = true showToc = pageToc && (toc(page.content) !== '' || page.encrypt === true)
}
const pageToc = page.toc === true || page.toc === false ? page.toc : tocEnable
showToc = pageToc && (toc(page.content) !== '' || page.encrypt == true )
} }
- -

@ -7,11 +7,12 @@ nav#nav
span.site-name=config.title span.site-name=config.title
#menus #menus
if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable) if (theme.search.use)
#search-button #search-button
span.site-page.social-icon.search span.site-page.social-icon.search
i.fas.fa-search.fa-fw i.fas.fa-search.fa-fw
span=' '+_p('search.title') span=' '+_p('search.title')
if theme.menu
!=partial('includes/header/menu_item', {}, {cache: true}) !=partial('includes/header/menu_item', {}, {cache: true})
#toggle-menu #toggle-menu

@ -2,6 +2,7 @@
- page.aside = is_archive() ? theme.aside.display.archive: is_category() ? theme.aside.display.category : is_tag() ? theme.aside.display.tag : page.aside - page.aside = is_archive() ? theme.aside.display.archive: is_category() ? theme.aside.display.category : is_tag() ? theme.aside.display.tag : page.aside
- var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : '' - var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : ''
- var pageType = is_post() ? 'post' : 'page' - var pageType = is_post() ? 'post' : 'page'
- pageType = page.type ? pageType + ' type-' + page.type : pageType
doctype html doctype html
html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside) html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside)
@ -16,7 +17,6 @@ html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside
!=partial('includes/sidebar', {}, {cache: true}) !=partial('includes/sidebar', {}, {cache: true})
if page.type !== '404'
#body-wrap(class=pageType) #body-wrap(class=pageType)
include ./header/index.pug include ./header/index.pug
@ -28,7 +28,7 @@ html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside
if theme.aside.enable && page.aside !== false if theme.aside.enable && page.aside !== false
include widget/index.pug include widget/index.pug
- var footerBg = theme.footer_bg - var footerBg = theme.footer_img
if (footerBg) if (footerBg)
if (footerBg === true) if (footerBg === true)
- var footer_bg = bg_img - var footer_bg = bg_img
@ -40,8 +40,5 @@ html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside
footer#footer(style=footer_bg) footer#footer(style=footer_bg)
!=partial('includes/footer', {}, {cache: true}) !=partial('includes/footer', {}, {cache: true})
else
include ./404.pug
include ./rightside.pug include ./rightside.pug
include ./additional-js.pug include ./additional-js.pug

@ -0,0 +1,125 @@
mixin indexPostUI()
- let indexLayout = theme.index_layout
- let masonryLayoutClass = (indexLayout === 6 || indexLayout === 7) ? 'masonry' : ''
#recent-posts.recent-posts.nc(class=masonryLayoutClass)
.recent-post-items
each article , index in page.posts.data
.recent-post-item
-
let link = article.link || article.path
let title = article.title || _p('no_title')
let leftOrRight = indexLayout === 3
? index%2 == 0 ? 'left' : 'right'
: indexLayout === 2 ? 'right' : ''
let post_cover = article.cover
let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
-
if post_cover && theme.cover.index_enable
.post_cover(class=leftOrRight)
a(href=url_for(link) title=title)
if article.cover_type === 'img'
img.post-bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title)
else
div.post-bg(style=`background: ${post_cover}`)
.recent-post-info(class=no_cover)
a.article-title(href=url_for(link) title=title)
if (is_home() && (article.top || article.sticky > 0))
i.fas.fa-thumbtack.sticky
= title
.article-meta-wrap
if (theme.post_meta.page.date_type)
span.post-meta-date
if (theme.post_meta.page.date_type === 'both')
i.far.fa-calendar-alt
span.article-meta-label=_p('post.created')
time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format)
span.article-meta-separator |
i.fas.fa-history
span.article-meta-label=_p('post.updated')
time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format)
else
- let data_type_updated = theme.post_meta.page.date_type === 'updated'
- let date_type = data_type_updated ? 'updated' : 'date'
- let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt'
- let date_title = data_type_updated ? _p('post.updated') : _p('post.created')
i(class=date_icon)
span.article-meta-label=date_title
time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format)
if (theme.post_meta.page.categories && article.categories.data.length > 0)
span.article-meta
span.article-meta-separator |
each item, index in article.categories.data
i.fas.fa-inbox
a(href=url_for(item.path)).article-meta__categories #[=item.name]
if (index < article.categories.data.length - 1)
i.fas.fa-angle-right.article-meta-link
if (theme.post_meta.page.tags && article.tags.length > 0)
span.article-meta.tags
span.article-meta-separator |
each item, index in article.tags.data
i.fas.fa-tag
a(href=url_for(item.path)).article-meta__tags #[=item.name]
if (index < article.tags.data.length - 1)
span.article-meta-link #[='•']
mixin countBlockInIndex
- needLoadCountJs = true
span.article-meta
span.article-meta-separator |
i.fas.fa-comments
if block
block
span.article-meta-label= ' ' + _p('card_post_count')
if theme.comments.card_post_count && theme.comments.use
case theme.comments.use[0]
when 'Disqus'
when 'Disqusjs'
+countBlockInIndex
a.disqus-count(href=full_url_for(link) + '#post-comment')
i.fa-solid.fa-spinner.fa-spin
when 'Valine'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.valine-comment-count(data-xid=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Waline'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.waline-comment-count(data-path=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Twikoo'
+countBlockInIndex
a.twikoo-count(href=url_for(link) + '#post-comment')
i.fa-solid.fa-spinner.fa-spin
when 'Facebook Comments'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.fb-comments-count(data-href=urlNoIndex(article.permalink))
when 'Remark42'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.remark42__counter(data-url=urlNoIndex(article.permalink))
i.fa-solid.fa-spinner.fa-spin
when 'Artalk'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.artalk-count(data-page-key=url_for(link))
i.fa-solid.fa-spinner.fa-spin
//- Display the article introduction on homepage
case theme.index_post_content.method
when false
- break
when 1
.content!= article.description
when 2
.content!= article.description || truncate(article.content, theme.index_post_content.length)
default
.content!= truncate(article.content, theme.index_post_content.length)
if theme.ad && theme.ad.index
if (index + 1) % 3 == 0
.recent-post-item.ads-wrap!=theme.ad.index
include ../pagination.pug

@ -1,129 +0,0 @@
mixin postUI(posts)
each article , index in page.posts.data
.recent-post-item
-
let link = article.link || article.path
let title = article.title || _p('no_title')
const position = theme.cover.position
let leftOrRight = position === 'both'
? index%2 == 0 ? 'left' : 'right'
: position === 'left' ? 'left' : 'right'
let post_cover = article.cover
let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : ''
-
if post_cover && theme.cover.index_enable
.post_cover(class=leftOrRight)
a(href=url_for(link) title=title)
if article.cover_type === 'img'
img.post-bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title)
else
div.post-bg(style=`background: ${post_cover}`)
.recent-post-info(class=no_cover)
a.article-title(href=url_for(link) title=title)
if (is_home() && (article.top || article.sticky > 0))
i.fas.fa-thumbtack.sticky
= title
.article-meta-wrap
if (theme.post_meta.page.date_type)
span.post-meta-date
if (theme.post_meta.page.date_type === 'both')
i.far.fa-calendar-alt
span.article-meta-label=_p('post.created')
time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format)
span.article-meta-separator |
i.fas.fa-history
span.article-meta-label=_p('post.updated')
time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format)
else
- let data_type_updated = theme.post_meta.page.date_type === 'updated'
- let date_type = data_type_updated ? 'updated' : 'date'
- let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt'
- let date_title = data_type_updated ? _p('post.updated') : _p('post.created')
i(class=date_icon)
span.article-meta-label=date_title
time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format)
if (theme.post_meta.page.categories && article.categories.data.length > 0)
span.article-meta
span.article-meta-separator |
each item, index in article.categories.data
i.fas.fa-inbox
a(href=url_for(item.path)).article-meta__categories #[=item.name]
if (index < article.categories.data.length - 1)
i.fas.fa-angle-right.article-meta-link
if (theme.post_meta.page.tags && article.tags.data.length > 0)
span.article-meta.tags
span.article-meta-separator |
each item, index in article.tags.data
i.fas.fa-tag
a(href=url_for(item.path)).article-meta__tags #[=item.name]
if (index < article.tags.data.length - 1)
span.article-meta-link #[='•']
mixin countBlockInIndex
- needLoadCountJs = true
span.article-meta
span.article-meta-separator |
i.fas.fa-comments
if block
block
span.article-meta-label= ' ' + _p('card_post_count')
if theme.comments.card_post_count && theme.comments.use
case theme.comments.use[0]
when 'Disqus'
when 'Disqusjs'
+countBlockInIndex
a.disqus-count(href=full_url_for(link) + '#post-comment')
i.fa-solid.fa-spinner.fa-spin
when 'Valine'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.valine-comment-count(data-xid=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Waline'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.waline-comment-count(data-path=url_for(link))
i.fa-solid.fa-spinner.fa-spin
when 'Twikoo'
+countBlockInIndex
a.twikoo-count(href=url_for(link) + '#post-comment')
i.fa-solid.fa-spinner.fa-spin
when 'Facebook Comments'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.fb-comments-count(data-href=urlNoIndex(article.permalink))
when 'Remark42'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.remark42__counter(data-url=urlNoIndex(article.permalink))
i.fa-solid.fa-spinner.fa-spin
when 'Artalk'
+countBlockInIndex
a(href=url_for(link) + '#post-comment')
span.artalk-count(data-page-key=url_for(link))
i.fa-solid.fa-spinner.fa-spin
//- Display the article introduction on homepage
case theme.index_post_content.method
when false
- break
when 1
.content!= article.description
when 2
if article.description
.content!= article.description
else
- const content = strip_html(article.content)
- let expert = content.substring(0, theme.index_post_content.length)
- content.length > theme.index_post_content.length ? expert += ' ...' : ''
.content!= expert
default
- const content = strip_html(article.content)
- let expert = content.substring(0, theme.index_post_content.length)
- content.length > theme.index_post_content.length ? expert += ' ...' : ''
.content!= expert
if theme.ad && theme.ad.index
if (index + 1) % 3 == 0
.recent-post-item.ads-wrap!=theme.ad.index

@ -0,0 +1,8 @@
- var top_img_404 = theme.error_404.background || theme.default_top_img
.error-content
.error-img
img(src=url_for(top_img_404) alt='Page not found')
.error-info
h1.error_title= '404'
.error_subtitle= theme.error_404.subtitle || _p('error404')

@ -0,0 +1,103 @@
//- - author:
//- avatar:
//- date:
//- content:
//- tags:
//- - tag1
//- - tag2
- page.comments = false
- page.toc = false
#article-container
if page.shuoshuo_url
script.
(() => {
const loadShuoshuo = async () => {
try {
const fetchContent = await fetch('!{url_for(page.shuoshuo_url)}')
const shuoshuo = await fetchContent.json()
let start = 0
const container = document.getElementById('article-container')
const addData = data => {
const cLength = data.length
const end = start + 10 > cLength ? cLength : start + 10
let result = ''
data.slice(start, end).forEach((item) => {
result += `
<div class="shuoshuo-item">
<div class="shuoshuo-item-header">
<div class="shuoshuo-avatar">
<img class="no-lightbox" src="${item.avatar || '!{url_for(theme.avatar.img)}'}">
</div>
<div class="shuoshuo-info">
<div class="shuoshuo-author">${item.author || '!{config.author}'}</div>
<div class="shuoshuo-date">${btf.diffDate(item.date, true)}</div>
</div>
</div>
<div class="shuoshuo-content">
${item.content}
</div>
<div class="shuoshuo-footer">
<div class="shuoshuo-tags">
${item.tags.map(tag => `<span class="shuoshuo-tag">${tag}</span>`).join('')}
</div>
</div>
</div>
`
})
start = end
container.insertAdjacentHTML('beforeend', result)
if (start >= cLength) {
observer.disconnect()
} else {
setTimeout(() => observer.observe(container.lastElementChild), 100)
}
window.lazyLoadInstance.update()
btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)'))
}
addData(shuoshuo)
const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting) {
observer.unobserve(entries[0].target)
addData(shuoshuo)
}
}, {
root: null,
rootMargin: '0px',
threshold: 1.0
})
if (container.lastElementChild) {
observer.observe(container.lastElementChild)
}
} catch (e) {
console.error(e)
}
}
window.pjax ? loadShuoshuo() : window.addEventListener('load', loadShuoshuo)
})()
else
if site.data.shuoshuo
each i in site.data.shuoshuo
.shuoshuo-item
.shuoshuo-item-header
.shuoshuo-avatar
img.no-lightbox(src=i.avatar || url_for(theme.avatar.img))
.shuoshuo-info
.shuoshuo-author=i.author || config.author
.shuoshuo-date=relative_date(i.date)
.shuoshuo-content
!=markdown(i.content)
.shuoshuo-footer
.shuoshuo-tags
each tag in i.tags
span.shuoshuo-tag=tag

@ -1,2 +1,2 @@
.tag-cloud-list.is-center .tag-cloud-list.is-center
!=cloudTags({source: site.tags, orderby: page.orderby || 'random', order: page.order || 1, minfontsize: 1.2, maxfontsize: 2.1, limit: 0, unit: 'em'}) !=cloudTags({source: site.tags, orderby: page.orderby || 'random', order: page.order || 1, minfontsize: 1.2, maxfontsize: 1.5, limit: 0, unit: 'em'})

@ -12,8 +12,7 @@ if is_post()
nav#pagination.pagination-post nav#pagination.pagination-post
if(prev) if(prev)
- var hasPageNext = next ? 'pull-left' : 'pull-full' - var hasPageNext = next ? 'pull-left' : 'pull-full'
.prev-post(class=hasPageNext) a.prev-post(class=hasPageNext href=url_for(prev.path) title=prev.title)
a(href=url_for(prev.path) title=prev.title)
if prev.cover_type === 'img' if prev.cover_type === 'img'
img.cover(src=url_for(prev.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of previous post') img.cover(src=url_for(prev.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of previous post')
else else
@ -24,8 +23,7 @@ if is_post()
if(next) if(next)
- var hasPagePrev = prev ? 'pull-right' : 'pull-full' - var hasPagePrev = prev ? 'pull-right' : 'pull-full'
.next-post(class=hasPagePrev) a.next-post(class=hasPagePrev href=url_for(next.path) title=next.title)
a(href=url_for(next.path) title=next.title)
if next.cover_type === 'img' if next.cover_type === 'img'
img.cover(src=url_for(next.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of next post') img.cover(src=url_for(next.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of next post')
else else

@ -1,4 +1,4 @@
- const { readmode, translate, darkmode, aside, chat_btn } = theme - const { readmode, translate, darkmode, aside, chat } = theme
mixin rightsideItem(array) mixin rightsideItem(array)
each item in array each item in array
case item case item
@ -22,9 +22,9 @@ mixin rightsideItem(array)
button#mobile-toc-button.close(type="button" title=_p("rightside.toc")) button#mobile-toc-button.close(type="button" title=_p("rightside.toc"))
i.fas.fa-list-ul i.fas.fa-list-ul
when 'chat' when 'chat'
if chat_btn if chat.rightside_button && chat.use
button#chat-btn(type="button" title=_p("rightside.chat")) button#chat-btn(type="button" title=_p("rightside.chat"))
i.fas.fa-sms i.fas.fa-message
when 'comment' when 'comment'
if commentsJsLoad if commentsJsLoad
a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment")) a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment"))

@ -1,9 +1,10 @@
if theme.menu
#sidebar #sidebar
#menu-mask #menu-mask
#sidebar-menus #sidebar-menus
.avatar-img.is-center .avatar-img.is-center
img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar") img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar")
.sidebar-site-data.site-data.is-center .site-data.is-center
a(href=url_for(config.archive_dir) + '/') a(href=url_for(config.archive_dir) + '/')
.headline= _p('aside.articles') .headline= _p('aside.articles')
.length-num= site.posts.length .length-num= site.posts.length
@ -14,5 +15,4 @@
.headline= _p('aside.categories') .headline= _p('aside.categories')
.length-num= site.categories.length .length-num= site.categories.length
hr.custom-hr
!=partial('includes/header/menu_item', {}, {cache: true}) !=partial('includes/header/menu_item', {}, {cache: true})

@ -14,10 +14,10 @@ if theme.pjax.enable
} }
} }
const loadMeting = () => { const runMetingJS = () => {
typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting()
} }
btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer') btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer')
btf.addGlobalFn('pjaxComplete', loadMeting, 'loadMeting') btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS')
})() })()

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

@ -1,8 +1,8 @@
//- https://chatra.io/help/api/ //- https://chatra.io/help/api/
script. script.
(() => { (() => {
const isChatBtn = !{theme.chat_btn} const isChatBtn = !{theme.chat.rightside_button}
const isChatHideShow = !{theme.chat_hide_show} const isChatHideShow = !{theme.chat.button_hide_show}
if (isChatBtn) { if (isChatBtn) {
const close = () => { const close = () => {

@ -11,8 +11,8 @@ script.
})(); })();
$crisp.push(["safe", true]) $crisp.push(["safe", true])
const isChatBtn = !{theme.chat_btn} const isChatBtn = !{theme.chat.rightside_button}
const isChatHideShow = !{theme.chat_hide_show} const isChatHideShow = !{theme.chat.button_hide_show}
if (isChatBtn) { if (isChatBtn) {
const open = () => { const open = () => {

@ -3,8 +3,8 @@ script.
(() => { (() => {
(function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice") (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice")
const isChatBtn = !{theme.chat_btn} const isChatBtn = !{theme.chat.rightside_button}
const isChatHideShow = !{theme.chat_hide_show} const isChatHideShow = !{theme.chat.button_hide_show}
daovoice('init', { daovoice('init', {
app_id: '!{theme.daovoice.app_id}',},{ app_id: '!{theme.daovoice.app_id}',},{

@ -1,10 +1,11 @@
if theme.chatra && theme.chatra.enable case theme.chat.use
when 'chatra'
include ./chatra.pug include ./chatra.pug
else if theme.tidio && theme.tidio.enable when 'tidio'
include ./tidio.pug include ./tidio.pug
else if theme.daovoice && theme.daovoice.enable when 'daovoice'
include ./daovoice.pug include ./daovoice.pug
else if theme.crisp && theme.crisp.enable when 'crisp'
include ./crisp.pug include ./crisp.pug
else if theme.messenger && theme.messenger.enable when 'messenger'
include ./messenger.pug include ./messenger.pug

@ -22,8 +22,8 @@ script.
fjs.parentNode.insertBefore(js, fjs); fjs.parentNode.insertBefore(js, fjs);
}(document, 'script', 'facebook-jssdk')); }(document, 'script', 'facebook-jssdk'));
const isChatBtn = !{theme.chat_btn} const isChatBtn = !{theme.chat.rightside_button}
const isChatHideShow = !{theme.chat_hide_show} const isChatHideShow = !{theme.chat.button_hide_show}
if (isChatBtn) { if (isChatBtn) {
window.chatBtnFn = () => { window.chatBtnFn = () => {

@ -1,8 +1,8 @@
script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async) script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async)
script. script.
(() => { (() => {
const isChatBtn = !{theme.chat_btn} const isChatBtn = !{theme.chat.rightside_button}
const isChatHideShow = !{theme.chat_hide_show} const isChatHideShow = !{theme.chat.button_hide_show}
if (isChatBtn) { if (isChatBtn) {
let isShow = false let isShow = false

@ -25,7 +25,7 @@ script.
artalkItem.destroy() artalkItem.destroy()
} }
btf.addGlobalFn('pjax', destroyArtalk, 'destroyArtalk') btf.addGlobalFn('pjaxSendOnce', destroyArtalk, 'destroyArtalk')
} }
const loadArtalk = async () => { const loadArtalk = async () => {

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

@ -1,13 +1,11 @@
- const { repo, repo_id, category_id, theme:themes, option } = theme.giscus
- const giscusUrl = theme.asset.giscus || 'https://giscus.app/client.js'
- const giscusOriginUrl = new URL(giscusUrl).origin
- const { use, lazyload } = theme.comments - const { use, lazyload } = theme.comments
- const { repo, repo_id, category_id, light_theme, dark_theme, js, option } = theme.giscus
- const giscusUrl = js || 'https://giscus.app/client.js'
- const giscusOriginUrl = new URL(giscusUrl).origin
script. script.
(()=>{ (()=>{
const getGiscusTheme = theme => { const getGiscusTheme = theme => theme === 'dark' ? '!{dark_theme}' : '!{light_theme}'
return theme === 'dark' ? '!{themes.dark}' : '!{themes.light}'
}
const loadGiscus = () => { const loadGiscus = () => {
const config = Object.assign({ const config = Object.assign({
@ -30,17 +28,17 @@ script.
} }
const changeGiscusTheme = theme => { const changeGiscusTheme = theme => {
const sendMessage = message => { const iframe = document.querySelector('#giscus-wrap iframe')
const iframe = document.querySelector('iframe.giscus-frame') if (iframe) {
if (!iframe) return const message = {
iframe.contentWindow.postMessage({ giscus: message }, '!{giscusOriginUrl}') giscus: {
}
sendMessage({
setConfig: { setConfig: {
theme: getGiscusTheme(theme) theme: getGiscusTheme(theme)
} }
}); }
}
iframe.contentWindow.postMessage(message, '!{giscusOriginUrl}')
}
} }
btf.addGlobalFn('themeChange', changeGiscusTheme, 'giscus') btf.addGlobalFn('themeChange', changeGiscusTheme, 'giscus')

@ -1,34 +1,42 @@
- const { use, lazyload } = theme.comments - const { use, lazyload } = theme.comments
- const { repo, issue_term, light_theme, dark_theme } = theme.utterances - const { repo, issue_term, light_theme, dark_theme, js, option } = theme.utterances
- const utterancesUrl = js || 'https://utteranc.es/client.js'
- const utterancesOriginUrl = new URL(utterancesUrl).origin
script. script.
(() => { (() => {
const getUtterancesTheme = theme => theme === 'dark' ? '#{dark_theme}' : '#{light_theme}'
const loadUtterances = () => { const loadUtterances = () => {
let ele = document.createElement('script') const config = Object.assign({
ele.id = 'utterances_comment' id: 'utterances_comment',
ele.src = 'https://utteranc.es/client.js' src: '!{utterancesUrl}',
ele.setAttribute('repo', '!{repo}') repo: '!{repo}',
ele.setAttribute('issue-term', '!{issue_term}') 'issue-term': '!{issue_term}',
const nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{dark_theme}' : '#{light_theme}' theme: getUtterancesTheme(document.documentElement.getAttribute('data-theme')),
ele.setAttribute('theme', nowTheme) crossorigin: 'anonymous',
ele.crossOrigin = 'anonymous' async: true
ele.async = true },!{JSON.stringify(option)})
const ele = document.createElement('script')
for (let key in config) {
ele.setAttribute(key, config[key])
}
document.getElementById('utterances-wrap').appendChild(ele) document.getElementById('utterances-wrap').appendChild(ele)
} }
const utterancesTheme = theme => { const changeUtterancesTheme = theme => {
const iframe = document.querySelector('.utterances-frame') const iframe = document.querySelector('#utterances-wrap iframe')
if (iframe) { if (iframe) {
const theme = theme === 'dark' ? '#{dark_theme}' : '#{light_theme}'
const message = { const message = {
type: 'set-theme', type: 'set-theme',
theme: theme theme: getUtterancesTheme(theme)
}; };
iframe.contentWindow.postMessage(message, 'https://utteranc.es'); iframe.contentWindow.postMessage(message, '!{utterancesOriginUrl}')
} }
} }
btf.addGlobalFn('themeChange', utterancesTheme, 'utterances') btf.addGlobalFn('themeChange', changeUtterancesTheme, 'utterances')
if ('!{use[0]}' === 'Utterances' || !!{lazyload}) { if ('!{use[0]}' === 'Utterances' || !!{lazyload}) {
if (!{lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances) if (!{lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances)

@ -19,7 +19,7 @@ script.
waline.destroy() waline.destroy()
} }
btf.addGlobalFn('pjax', destroyWaline, 'destroyWaline') btf.addGlobalFn('pjaxSendOnce', destroyWaline, 'destroyWaline')
} }
const loadWaline = () => { const loadWaline = () => {

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

@ -1,2 +1,16 @@
link(rel="stylesheet" type="text/css" href=url_for(theme.asset.katex)) script.
script(src=url_for(theme.asset.katex_copytex)) (async () => {
const showKatex = () => {
const mathElements = document.querySelectorAll('#article-container .katex')
mathElements.length && mathElements.forEach((el) => {
el.classList.add('katex-show')
})
}
if (!window.katex_js_css) {
window.katex_js_css = true
await btf.getCSS('!{url_for(theme.asset.katex)}')
if (!{theme.math.katex.copy_tex}) await btf.getScript('!{url_for(theme.asset.katex_copytex)}')
}
showKatex()
})()

@ -1,4 +1,5 @@
//- Mathjax 3 //- Mathjax 3
- const { tags, enableMenu } = theme.math.mathjax
script. script.
(() => { (() => {
const loadMathjax = () => { const loadMathjax = () => {
@ -6,12 +7,13 @@ script.
window.MathJax = { window.MathJax = {
tex: { tex: {
inlineMath: [['$', '$'], ['\\(', '\\)']], inlineMath: [['$', '$'], ['\\(', '\\)']],
tags: 'ams' tags: '!{tags}',
}, },
chtml: { chtml: {
scale: 1.1 scale: 1.1
}, },
options: { options: {
enableMenu: !{enableMenu},
renderActions: { renderActions: {
findScript: [10, doc => { findScript: [10, doc => {
for (const node of document.querySelectorAll('script[type^="math/tex"]')) { for (const node of document.querySelectorAll('script[type^="math/tex"]')) {

@ -11,18 +11,12 @@ script.
const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
const renderFn = mermaid.render(mermaidID, mermaidDefinition) const renderFn = mermaid.render(mermaidID, mermaidDefinition)
const renderMermaid = svg => {
const renderV10 = () => {
renderFn.then(({svg}) => {
mermaidSrc.insertAdjacentHTML('afterend', svg)
})
}
const renderV9 = svg => {
mermaidSrc.insertAdjacentHTML('afterend', svg) mermaidSrc.insertAdjacentHTML('afterend', svg)
} }
typeof renderFn === 'string' ? renderV9(renderFn) : renderV10() // mermaid v9 and v10 compatibility
typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({svg}) => renderMermaid(svg))
}) })
} }
@ -31,9 +25,13 @@ script.
if (codeMermaidEle.length === 0) return if (codeMermaidEle.length === 0) return
codeMermaidEle.forEach(ele => { codeMermaidEle.forEach(ele => {
const preEle = document.createElement('pre')
preEle.className = 'mermaid-src'
preEle.hidden = true
preEle.textContent = ele.textContent
const newEle = document.createElement('div') const newEle = document.createElement('div')
newEle.className = 'mermaid-wrap' newEle.className = 'mermaid-wrap'
newEle.innerHTML = `<pre class="mermaid-src" hidden>${ele.textContent}</pre>` newEle.appendChild(preEle)
ele.parentNode.replaceWith(newEle) ele.parentNode.replaceWith(newEle)
}) })
} }

@ -1,6 +1,6 @@
- const { server, site, option } = theme.artalk - const { server, site, option } = theme.artalk
- const avatarCdn = option !== null && option.gravatar && option.gravatar.mirror - const avatarCdn = (option !== null && option.gravatar && option.gravatar.mirror) || ''
- const avatarDefault = option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default) - const avatarDefault = (option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default)) || ''
script. script.
window.addEventListener('load', () => { window.addEventListener('load', () => {
@ -25,7 +25,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }
@ -60,7 +60,7 @@ script.
const searchParams = new URLSearchParams({ const searchParams = new URLSearchParams({
'site_name': '!{site}', 'site_name': '!{site}',
'limit': '!{theme.newest_comments.limit}', 'limit': '!{theme.aside.card_newest_comments.limit}',
}) })
const getComment = async () => { const getComment = async () => {
@ -69,8 +69,8 @@ script.
const result = await res.json() const result = await res.json()
const avatarStr = await getSetting() const avatarStr = await getSetting()
const { mirror, params, default:defaults } = avatarStr.frontend_conf.gravatar const { mirror, params, default:defaults } = avatarStr.frontend_conf.gravatar
const avatarCdn = !{avatarCdn} || mirror const avatarCdn = '!{avatarCdn}' || mirror
let avatarDefault = !{avatarDefault} || params || defaults let avatarDefault = '!{avatarDefault}' || params || defaults
avatarDefault = avatarDefault.startsWith('d=') ? avatarDefault : `d=${avatarDefault}` avatarDefault = avatarDefault.startsWith('d=') ? avatarDefault : `d=${avatarDefault}`
const artalk = result.data.map(function (e) { const artalk = result.data.map(function (e) {
return { return {
@ -81,7 +81,7 @@ script.
'date': e.date, 'date': e.date,
} }
}) })
btf.saveToLocal.set('artalk-newest-comments', JSON.stringify(artalk), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('artalk-newest-comments', JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(artalk) generateHtml(artalk)
} catch (e) { } catch (e) {
console.log(e) console.log(e)

@ -15,7 +15,7 @@ script.
} }
const getComment = () => { const getComment = () => {
fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{theme.newest_comments.limit}&api_key=!{apiKey}') fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{theme.aside.card_newest_comments.limit}&api_key=!{apiKey}')
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const disqusArray = data.response.map(item => { const disqusArray = data.response.map(item => {
@ -28,7 +28,7 @@ script.
} }
}) })
btf.saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(disqusArray) generateHtml(disqusArray)
}).catch(e => { }).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list') const $dom = document.querySelector('#card-newest-comments .aside-list')
@ -43,7 +43,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }

@ -35,13 +35,13 @@ script.
} }
}) })
btf.saveToLocal.set('github-newest-comments', JSON.stringify(array), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('github-newest-comments', JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(array) generateHtml(array)
}); });
} }
const getComment = () => { const getComment = () => {
fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.newest_comments.limit}&page=1',{ fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.aside.card_newest_comments.limit}&page=1',{
"headers": { "headers": {
Accept: 'application/vnd.github.v3.html+json' Accept: 'application/vnd.github.v3.html+json'
} }
@ -72,7 +72,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }

@ -23,7 +23,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }
@ -44,7 +44,7 @@ script.
} }
const getComment = () => { const getComment = () => {
fetch('!{host}/api/v1/last/!{theme.newest_comments.limit}?site=!{siteId}') fetch('!{host}/api/v1/last/!{theme.aside.card_newest_comments.limit}?site=!{siteId}')
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const remark42 = data.map(function (e) { const remark42 = data.map(function (e) {
@ -56,7 +56,7 @@ script.
'date': e.time, 'date': e.time,
} }
}) })
btf.saveToLocal.set('remark42-newest-comments', JSON.stringify(remark42), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('remark42-newest-comments', JSON.stringify(remark42), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(remark42) generateHtml(remark42)
}).catch(e => { }).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list') const $dom = document.querySelector('#card-newest-comments .aside-list')

@ -5,7 +5,7 @@ script.
content = content.replace(/<img.*?src="(.*?)"?[^\>]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link content = content.replace(/<img.*?src="(.*?)"?[^\>]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link
content = content.replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url content = content.replace(/<a[^>]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url
content = content.replace(/<pre><code>.*?<\/pre>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code content = content.replace(/<pre><code>.*?<\/pre>/gi, '[!{_p("aside.card_aside.card_aside.card_newest_comments.code")}]') // replace code
content = content.replace(/<[^>]+>/g,"") // remove html tag content = content.replace(/<[^>]+>/g,"") // remove html tag
if (content.length > 150) { if (content.length > 150) {
@ -19,7 +19,7 @@ script.
twikoo.getRecentComments({ twikoo.getRecentComments({
envId: '!{theme.twikoo.envId}', envId: '!{theme.twikoo.envId}',
region: '!{theme.twikoo.region}', region: '!{theme.twikoo.region}',
pageSize: !{theme.newest_comments.limit}, pageSize: !{theme.aside.card_newest_comments.limit},
includeReply: true includeReply: true
}).then(function (res) { }).then(function (res) {
const twikooArray = res.map(e => { const twikooArray = res.map(e => {
@ -32,7 +32,7 @@ script.
} }
}) })
btf.saveToLocal.set('twikoo-newest-comments', JSON.stringify(twikooArray), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('twikoo-newest-comments', JSON.stringify(twikooArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(twikooArray) generateHtml(twikooArray)
}).catch(function (err) { }).catch(function (err) {
const $dom = document.querySelector('#card-newest-comments .aside-list') const $dom = document.querySelector('#card-newest-comments .aside-list')
@ -54,7 +54,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }

@ -31,7 +31,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }
@ -63,7 +63,7 @@ script.
}, },
} }
fetch(`${serverURL}/1.1/classes/Comment?limit=!{theme.newest_comments.limit}&order=-createdAt`,settings) fetch(`${serverURL}/1.1/classes/Comment?limit=!{theme.aside.card_newest_comments.limit}&order=-createdAt`,settings)
.then(response => response.json()) .then(response => response.json())
.then(data => { .then(data => {
const valineArray = data.results.map(function (e) { const valineArray = data.results.map(function (e) {
@ -75,7 +75,7 @@ script.
'date': e.updatedAt, 'date': e.updatedAt,
} }
}) })
btf.saveToLocal.set('valine-newest-comments', JSON.stringify(valineArray), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('valine-newest-comments', JSON.stringify(valineArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(valineArray) generateHtml(valineArray)
}).catch(e => { }).catch(e => {
const $dom = document.querySelector('#card-newest-comments .aside-list') const $dom = document.querySelector('#card-newest-comments .aside-list')

@ -23,7 +23,7 @@ script.
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
result += '<div class=\'aside-list-item\'>' result += '<div class=\'aside-list-item\'>'
if (!{theme.newest_comments.avatar}) { if (!{theme.aside.card_newest_comments.avatar}) {
const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}'
result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>` result += `<a href='${array[i].url}' class='thumbnail'><img ${name}='${array[i].avatar}' alt='${array[i].nick}'></a>`
} }
@ -45,7 +45,7 @@ script.
const getComment = async () => { const getComment = async () => {
try { try {
const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{theme.newest_comments.limit}', { method: 'GET' }) const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{theme.aside.card_newest_comments.limit}', { method: 'GET' })
const result = await res.json() const result = await res.json()
const walineArray = result.data.map(e => { const walineArray = result.data.map(e => {
return { return {
@ -56,7 +56,7 @@ script.
'date': e.time || e.insertedAt 'date': e.time || e.insertedAt
} }
}) })
btf.saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.newest_comments.storage}/(60*24)) btf.saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.aside.card_newest_comments.storage}/(60*24))
generateHtml(walineArray) generateHtml(walineArray)
} catch (err) { } catch (err) {
console.error(err) console.error(err)

@ -32,7 +32,7 @@ script.
document.addEventListener('pjax:send', function () { document.addEventListener('pjax:send', function () {
// removeEventListener // removeEventListener
btf.removeGlobalFnEvent('pjax') btf.removeGlobalFnEvent('pjaxSendOnce')
btf.removeGlobalFnEvent('themeChange') btf.removeGlobalFnEvent('themeChange')
//reset readmode //reset readmode
@ -43,6 +43,7 @@ script.
}) })
document.addEventListener('pjax:complete', () => { document.addEventListener('pjax:complete', () => {
btf.removeGlobalFnEvent('pjaxCompleteOnce')
document.querySelectorAll('script[data-pjax]').forEach(item => { document.querySelectorAll('script[data-pjax]').forEach(item => {
const newScript = document.createElement('script') const newScript = document.createElement('script')
const content = item.text || item.textContent || item.innerHTML || "" const content = item.text || item.textContent || item.innerHTML || ""

@ -1,4 +1,4 @@
- const { appId, apiKey, indexName, option } = theme.docsearch - const { placeholder, docsearch: { appId, apiKey, indexName, option } } = theme.search
.docsearch-wrap .docsearch-wrap
#docsearch(style="display:none") #docsearch(style="display:none")
@ -11,6 +11,7 @@
apiKey: '!{apiKey}', apiKey: '!{apiKey}',
indexName: '!{indexName}', indexName: '!{indexName}',
container: '#docsearch', container: '#docsearch',
placeholder: '!{ placeholder || _p("search.input_placeholder")}',
}, !{JSON.stringify(option)})) }, !{JSON.stringify(option)}))
const handleClick = () => { const handleClick = () => {

@ -1,6 +1,7 @@
if theme.algolia_search.enable case theme.search.use
when 'algolia_search'
include ./algolia.pug include ./algolia.pug
else if theme.local_search.enable when 'local_search'
include ./local-search.pug include ./local-search.pug
else if theme.docsearch.enable when 'docsearch'
include ./docsearch.pug include ./docsearch.pug

@ -13,7 +13,7 @@
.search-wrap .search-wrap
#local-search-input #local-search-input
.local-search-box .local-search-box
input(placeholder=_p("search.local_search.input_placeholder") type="text").local-search-box--input input(placeholder=theme.search.placeholder || _p("search.input_placeholder") type="text").local-search-box--input
hr hr
#local-search-results #local-search-results
#local-search-stats-wrap #local-search-stats-wrap

@ -1,5 +1,9 @@
.post_share - const { use } = theme.share
if theme.sharejs.enable
include ./share-js.pug if use
else if theme.addtoany.enable .post-share
case use
when 'addtoany'
!=partial('includes/third-party/share/addtoany', {}, {cache: true}) !=partial('includes/third-party/share/addtoany', {}, {cache: true})
when 'sharejs'
include ./share-js.pug

@ -1,4 +1,4 @@
- const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img - const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img
.social-share(data-image=url_for(coverVal) data-sites= theme.sharejs.sites) .social-share(data-image=url_for(coverVal) data-sites= theme.share.sharejs.sites)
link(rel='stylesheet' href=url_for(theme.asset.sharejs_css) media="print" onload="this.media='all'") link(rel='stylesheet' href=url_for(theme.asset.sharejs_css) media="print" onload="this.media='all'")
script(src=url_for(theme.asset.sharejs) defer) script(src=url_for(theme.asset.sharejs) defer)

@ -3,7 +3,7 @@
script. script.
window.typedJSFn = { window.typedJSFn = {
init: (str) => { init: str => {
window.typed = new Typed('#subtitle', Object.assign({ window.typed = new Typed('#subtitle', Object.assign({
strings: str, strings: str,
startDelay: 300, startDelay: 300,
@ -12,7 +12,7 @@ script.
backSpeed: 50, backSpeed: 50,
}, !{JSON.stringify(typed_option)})) }, !{JSON.stringify(typed_option)}))
}, },
run: (subtitleType) => { run: subtitleType => {
if (!{effect}) { if (!{effect}) {
if (typeof Typed === 'function') { if (typeof Typed === 'function') {
subtitleType() subtitleType()
@ -24,7 +24,7 @@ script.
} }
} }
} }
btf.addGlobalFn('pjaxSend', () => { typed.destroy() }, 'typedDestroy') btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy')
case source case source
when 1 when 1

@ -1,12 +1,11 @@
if theme.aside.card_author.enable if theme.aside.card_author.enable
.card-widget.card-info .card-widget.card-info.is-center
.is-center
.avatar-img .avatar-img
img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar") img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar")
.author-info__name= config.author .author-info-name= config.author
.author-info__description!= theme.aside.card_author.description || config.description .author-info-description!= theme.aside.card_author.description || config.description
.card-info-data.site-data.is-center .site-data
a(href=url_for(config.archive_dir) + '/') a(href=url_for(config.archive_dir) + '/')
.headline= _p('aside.articles') .headline= _p('aside.articles')
.length-num= site.posts.length .length-num= site.posts.length
@ -23,5 +22,5 @@ if theme.aside.card_author.enable
span=theme.aside.card_author.button.text span=theme.aside.card_author.button.text
if(theme.social) if(theme.social)
.card-info-social-icons.is-center .card-info-social-icons
!=partial('includes/header/social', {}, {cache: true}) !=partial('includes/header/social', {}, {cache: true})

@ -1,4 +1,4 @@
if theme.newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0]) if theme.aside.card_newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0])
.card-widget#card-newest-comments .card-widget#card-newest-comments
.item-headline .item-headline
i.fas.fa-comment-dots i.fas.fa-comment-dots

@ -8,10 +8,10 @@ if theme.aside.card_webinfo.enable
.webinfo-item .webinfo-item
.item-name= _p('aside.card_webinfo.article_name') + " :" .item-name= _p('aside.card_webinfo.article_name') + " :"
.item-count= site.posts.length .item-count= site.posts.length
if theme.runtimeshow.enable if theme.aside.card_webinfo.runtime_date
.webinfo-item .webinfo-item
.item-name= _p('aside.card_webinfo.runtime.name') + " :" .item-name= _p('aside.card_webinfo.runtime.name') + " :"
.item-count#runtimeshow(data-publishDate=date_xml(theme.runtimeshow.publish_date)) .item-count#runtimeshow(data-publishDate=date_xml(theme.aside.card_webinfo.runtime_date))
i.fa-solid.fa-spinner.fa-spin i.fa-solid.fa-spinner.fa-spin
if theme.wordcount.enable && theme.wordcount.total_wordcount if theme.wordcount.enable && theme.wordcount.total_wordcount
.webinfo-item .webinfo-item

@ -1,7 +1,5 @@
extends includes/layout.pug extends includes/layout.pug
block content block content
include ./includes/mixins/post-ui.pug include ./includes/mixins/indexPostUI.pug
#recent-posts.recent-posts +indexPostUI
+postUI
include includes/pagination.pug

@ -1,20 +1,32 @@
extends includes/layout.pug extends includes/layout.pug
block content block content
#page - const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : ''
if top_img === false - var commentsJsLoad = false
mixin commentLoad
if page.comments !== false && theme.comments.use
- commentsJsLoad = true
!=partial('includes/third-party/comments/index', {}, {cache: true})
#page(class=noCardLayout)
if top_img === false && page.title
h1.page-title= page.title h1.page-title= page.title
case page.type case page.type
when 'tags' when 'tags'
include includes/page/tags.pug include includes/page/tags.pug
+commentLoad
when 'link' when 'link'
include includes/page/flink.pug include includes/page/flink.pug
+commentLoad
when 'categories' when 'categories'
include includes/page/categories.pug include includes/page/categories.pug
+commentLoad
when '404'
include includes/page/404.pug
when 'shuoshuo'
include includes/page/shuoshuo.pug
default default
include includes/page/default-page.pug include includes/page/default-page.pug
+commentLoad
if page.comments !== false && theme.comments && theme.comments.use
- var commentsJsLoad = true
!=partial('includes/third-party/comments/index', {}, {cache: true})

@ -8,7 +8,7 @@ block content
article#article-container.post-content!=page.content article#article-container.post-content!=page.content
include includes/post/post-copyright.pug include includes/post/post-copyright.pug
.tag_share .tag_share
if (theme.post_meta.post.tags) if (page.tags.length > 0 && theme.post_meta.post.tags)
.post-meta__tag-list .post-meta__tag-list
each item, index in page.tags.data each item, index in page.tags.data
a(href=url_for(item.path)).post-meta__tags #[=item.name] a(href=url_for(item.path)).post-meta__tags #[=item.name]
@ -26,7 +26,7 @@ block content
if theme.related_post && theme.related_post.enable if theme.related_post && theme.related_post.enable
!= related_posts(page,site.posts) != related_posts(page,site.posts)
if page.comments !== false && theme.comments && theme.comments.use if page.comments !== false && theme.comments.use
- var commentsJsLoad = true - var commentsJsLoad = true
!=partial('includes/third-party/comments/index', {}, {cache: true}) !=partial('includes/third-party/comments/index', {}, {cache: true})

@ -2,10 +2,8 @@ extends includes/layout.pug
block content block content
if theme.tag_ui == 'index' if theme.tag_ui == 'index'
include ./includes/mixins/post-ui.pug include ./includes/mixins/indexPostUI.pug
#recent-posts.recent-posts +indexPostUI
+postUI
include includes/pagination.pug
else else
include ./includes/mixins/article-sort.pug include ./includes/mixins/article-sort.pug
#tag #tag

@ -1,6 +1,6 @@
{ {
"name": "hexo-theme-butterfly", "name": "hexo-theme-butterfly",
"version": "4.14.0-b3", "version": "5.0.0-b1",
"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": {

@ -1,7 +1,7 @@
abcjs_basic_js: abcjs_basic_js:
name: abcjs name: abcjs
file: dist/abcjs-basic-min.js file: dist/abcjs-basic-min.js
version: 6.3.0 version: 6.4.1
activate_power_mode: activate_power_mode:
name: butterfly-extsrc name: butterfly-extsrc
file: dist/activate-power-mode.min.js file: dist/activate-power-mode.min.js
@ -9,7 +9,7 @@ activate_power_mode:
algolia_search: algolia_search:
name: algoliasearch name: algoliasearch
file: dist/algoliasearch-lite.umd.js file: dist/algoliasearch-lite.umd.js
version: 4.23.2 version: 4.24.0
aplayer_css: aplayer_css:
name: aplayer name: aplayer
file: dist/APlayer.min.css file: dist/APlayer.min.css
@ -21,11 +21,11 @@ aplayer_js:
artalk_css: artalk_css:
name: artalk name: artalk
file: dist/Artalk.css file: dist/Artalk.css
version: 2.8.3 version: 2.8.7
artalk_js: artalk_js:
name: artalk name: artalk
file: dist/Artalk.js file: dist/Artalk.js
version: 2.8.3 version: 2.8.7
blueimp_md5: blueimp_md5:
name: blueimp-md5 name: blueimp-md5
file: js/md5.min.js file: js/md5.min.js
@ -62,26 +62,26 @@ 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: 3.6.0 version: 3.6.1
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: 3.6.0 version: 3.6.1
egjs_infinitegrid: egjs_infinitegrid:
name: '@egjs/infinitegrid' name: '@egjs/infinitegrid'
other_name: egjs-infinitegrid other_name: egjs-infinitegrid
file: dist/infinitegrid.min.js file: dist/infinitegrid.min.js
version: 4.11.1 version: 4.12.0
fancybox: fancybox:
name: '@fancyapps/ui' name: '@fancyapps/ui'
file: dist/fancybox/fancybox.umd.js file: dist/fancybox/fancybox.umd.js
version: 5.0.35 version: 5.0.36
other_name: fancyapps-ui other_name: fancyapps-ui
fancybox_css: fancybox_css:
name: '@fancyapps/ui' name: '@fancyapps/ui'
file: dist/fancybox/fancybox.css file: dist/fancybox/fancybox.css
version: 5.0.35 version: 5.0.36
other_name: fancyapps-ui other_name: fancyapps-ui
fireworks: fireworks:
name: butterfly-extsrc name: butterfly-extsrc
@ -91,7 +91,7 @@ fontawesome:
name: '@fortawesome/fontawesome-free' name: '@fortawesome/fontawesome-free'
file: css/all.min.css file: css/all.min.css
other_name: font-awesome other_name: font-awesome
version: 6.5.1 version: 6.6.0
gitalk: gitalk:
name: gitalk name: gitalk
file: dist/gitalk.min.js file: dist/gitalk.min.js
@ -107,21 +107,21 @@ instantpage:
instantsearch: instantsearch:
name: instantsearch.js name: instantsearch.js
file: dist/instantsearch.production.min.js file: dist/instantsearch.production.min.js
version: 4.66.1 version: 4.73.3
katex: katex:
name: katex name: katex
file: dist/katex.min.css file: dist/katex.min.css
other_name: KaTeX other_name: KaTeX
version: 0.16.10 version: 0.16.11
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.16.10 version: 0.16.11
lazyload: lazyload:
name: vanilla-lazyload name: vanilla-lazyload
file: dist/lazyload.iife.min.js file: dist/lazyload.iife.min.js
version: 19.0.5 version: 19.1.3
mathjax: mathjax:
name: mathjax name: mathjax
file: es5/tex-mml-chtml.js file: es5/tex-mml-chtml.js
@ -133,7 +133,7 @@ medium_zoom:
mermaid: mermaid:
name: mermaid name: mermaid
file: dist/mermaid.min.js file: dist/mermaid.min.js
version: 10.9.0 version: 10.9.1
meting_js: meting_js:
name: butterfly-extsrc name: butterfly-extsrc
file: metingjs/dist/Meting.min.js file: metingjs/dist/Meting.min.js
@ -190,7 +190,7 @@ snackbar_css:
twikoo: twikoo:
name: twikoo name: twikoo
file: dist/twikoo.all.min.js file: dist/twikoo.all.min.js
version: 1.6.32 version: 1.6.38
typed: typed:
name: typed.js name: typed.js
file: dist/typed.umd.js file: dist/typed.umd.js
@ -198,14 +198,14 @@ typed:
valine: valine:
name: valine name: valine
file: dist/Valine.min.js file: dist/Valine.min.js
version: 1.5.1 version: 1.5.2
waline_css: waline_css:
name: '@waline/client' name: '@waline/client'
file: dist/waline.css file: dist/waline.css
other_name: waline other_name: waline
version: 3.1.3 version: 3.3.0
waline_js: waline_js:
name: '@waline/client' name: '@waline/client'
file: dist/waline.js file: dist/waline.js
other_name: waline other_name: waline
version: 3.1.3 version: 3.3.0

@ -12,7 +12,9 @@ hexo.extend.generator.register('404', function (locals) {
layout: ['page'], layout: ['page'],
data: { data: {
type: '404', type: '404',
top_img: false top_img: false,
comments: false,
aside: false
} }
} }
}) })

@ -1,3 +1,5 @@
const { deepMerge } = require('hexo-util')
hexo.extend.filter.register('before_generate', () => { hexo.extend.filter.register('before_generate', () => {
const defaultConfig = { const defaultConfig = {
nav: { nav: {
@ -6,33 +8,36 @@ hexo.extend.filter.register('before_generate', () => {
fixed: false fixed: false
}, },
menu: null, menu: null,
highlight_theme: 'light', code_blocks: {
highlight_theme_macStyle: false, theme: 'light',
highlight_copy: true, macStyle: false,
highlight_lang: true, height_limit: false,
highlight_shrink: false, word_wrap: false,
highlight_fullpage: true, copy: true,
highlight_height_limit: false, language: true,
code_word_wrap: false, shrink: false,
fullpage: false
},
social: null, social: null,
favicon: '/img/favicon.png', favicon: '/img/favicon.png',
avatar: { avatar: {
img: 'https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png', img: '/img/butterfly-icon.png',
effect: false effect: false
}, },
disable_top_img: false, disable_top_img: false,
index_img: null,
default_top_img: null, default_top_img: null,
index_img: null,
archive_img: null, archive_img: null,
tag_img: null, tag_img: null,
tag_per_img: null, tag_per_img: null,
category_img: null, category_img: null,
category_per_img: null, category_per_img: null,
footer_img: false,
background: null,
cover: { cover: {
index_enable: true, index_enable: true,
aside_enable: true, aside_enable: true,
archives_enable: true, archives_enable: true,
position: 'both',
default_cover: null default_cover: null
}, },
error_img: { error_img: {
@ -42,7 +47,7 @@ hexo.extend.filter.register('before_generate', () => {
error_404: { error_404: {
enable: false, enable: false,
subtitle: 'Page Not Found', subtitle: 'Page Not Found',
background: 'https://i.loli.net/2020/05/19/aKOcLiyPl2JQdFD.png' background: '/img/error-page.png'
}, },
post_meta: { post_meta: {
page: { page: {
@ -61,22 +66,20 @@ hexo.extend.filter.register('before_generate', () => {
label: true label: true
} }
}, },
index_site_info_top: null,
index_top_img_height: null,
subtitle: {
enable: false,
effect: true,
typed_option: null,
source: false,
sub: null
},
index_layout: 3,
index_post_content: { index_post_content: {
method: 3, method: 3,
length: 500 length: 500
}, },
anchor: {
auto_update: false,
click_to_scroll: false
},
photofigcaption: false,
copy: {
enable: true,
copyright: {
enable: false,
limit_count: 50
}
},
toc: { toc: {
post: true, post: true,
page: false, page: false,
@ -110,7 +113,7 @@ hexo.extend.filter.register('before_generate', () => {
noticeOutdate: { noticeOutdate: {
enable: false, enable: false,
style: 'flat', style: 'flat',
limit_day: 500, limit_day: 365,
position: 'top', position: 'top',
message_prev: 'It has been', message_prev: 'It has been',
message_next: 'days since the last update, the content of the article may be outdated.' message_next: 'days since the last update, the content of the article may be outdated.'
@ -118,7 +121,7 @@ hexo.extend.filter.register('before_generate', () => {
footer: { footer: {
owner: { owner: {
enable: true, enable: true,
since: 2020 since: 2019
}, },
custom_text: null, custom_text: null,
copyright: true copyright: true
@ -154,6 +157,13 @@ hexo.extend.filter.register('before_generate', () => {
sort: 'date', sort: 'date',
sort_order: null sort_order: null
}, },
card_newest_comments: {
enable: false,
sort_order: null,
limit: 6,
storage: 10,
avatar: true
},
card_categories: { card_categories: {
enable: true, enable: true,
limit: 8, limit: 8,
@ -176,35 +186,21 @@ hexo.extend.filter.register('before_generate', () => {
limit: 8, limit: 8,
sort_order: null sort_order: null
}, },
card_webinfo: {
enable: true,
post_count: true,
last_push_date: true,
sort_order: null
},
card_post_series: { card_post_series: {
enable: true, enable: true,
series_title: false, series_title: false,
orderBy: 'date', orderBy: 'date',
order: -1 order: -1
}
},
busuanzi: {
site_uv: true,
site_pv: true,
page_pv: true
},
runtimeshow: {
enable: false,
publish_date: null
}, },
newest_comments: { card_webinfo: {
enable: false, enable: true,
post_count: true,
last_push_date: true,
sort_order: null, sort_order: null,
limit: 6, runtime_date: null
storage: 10, }
avatar: true
}, },
rightside_bottom: null,
translate: { translate: {
enable: false, enable: false,
default: '繁', default: '繁',
@ -227,42 +223,68 @@ hexo.extend.filter.register('before_generate', () => {
hide: null, hide: null,
show: null show: null
}, },
mathjax: { anchor: {
enable: false, auto_update: false,
per_page: false click_to_scroll: false
}, },
katex: { photofigcaption: false,
copy: {
enable: true,
copyright: {
enable: false, enable: false,
per_page: false, limit_count: 150
hide_scrollbar: true }
}, },
algolia_search: { wordcount: {
enable: false, enable: false,
hits: { post_wordcount: true,
per_page: 6 min2read: true,
total_wordcount: true
},
busuanzi: {
site_uv: true,
site_pv: true,
page_pv: true
},
math: {
use: null,
per_page: true,
hide_scrollbar: false,
mathjax: {
enableMenu: true,
tags: 'none'
},
katex: {
copy_tex: false
} }
}, },
search: {
use: null,
placeholder: null,
algolia_search: {
hitsPerPage: 6
},
local_search: { local_search: {
enable: false,
preload: false, preload: false,
top_n_per_article: 1, top_n_per_article: 1,
unescape: false, unescape: false,
CDN: null CDN: null
}, },
docsearch: { docsearch: {
enable: false,
appId: null, appId: null,
apiKey: null, apiKey: null,
indexName: null, indexName: null,
option: null option: null
}
}, },
share: {
use: 'sharejs',
sharejs: { sharejs: {
enable: true,
sites: 'facebook,twitter,wechat,weibo,qq' sites: 'facebook,twitter,wechat,weibo,qq'
}, },
addtoany: { addtoany: {
enable: false,
item: 'facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link' item: 'facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link'
}
}, },
comments: { comments: {
use: null, use: null,
@ -310,7 +332,9 @@ hexo.extend.filter.register('before_generate', () => {
repo: null, repo: null,
issue_term: 'pathname', issue_term: 'pathname',
light_theme: 'github-light', light_theme: 'github-light',
dark_theme: 'photon-dark' dark_theme: 'photon-dark',
js: null,
option: null
}, },
facebook_comments: { facebook_comments: {
app_id: null, app_id: null,
@ -329,10 +353,9 @@ hexo.extend.filter.register('before_generate', () => {
repo: null, repo: null,
repo_id: null, repo_id: null,
category_id: null, category_id: null,
theme: { light_theme: 'light',
light: 'light', dark_theme: 'dark',
dark: 'dark' js: null,
},
option: null option: null
}, },
remark42: { remark42: {
@ -346,26 +369,24 @@ hexo.extend.filter.register('before_generate', () => {
visitor: false, visitor: false,
option: null option: null
}, },
chat_btn: false, chat: {
chat_hide_show: false, use: null,
rightside_button: false,
button_hide_show: false
},
chatra: { chatra: {
enable: false,
id: null id: null
}, },
tidio: { tidio: {
enable: false,
public_key: null public_key: null
}, },
daovoice: { daovoice: {
enable: false,
app_id: null app_id: null
}, },
crisp: { crisp: {
enable: false,
website_id: null website_id: null
}, },
messenger: { messenger: {
enable: false,
pageID: null, pageID: null,
lang: 'zh_TW' lang: 'zh_TW'
}, },
@ -380,20 +401,48 @@ hexo.extend.filter.register('before_generate', () => {
client: null, client: null,
enable_page_level_ads: true enable_page_level_ads: true
}, },
ad: {
index: null,
aside: null,
post: null
},
site_verification: null, site_verification: null,
index_site_info_top: null,
index_top_img_height: null,
category_ui: null, category_ui: null,
tag_ui: null, tag_ui: null,
rounded_corners_ui: true,
text_align_justify: false, text_align_justify: false,
background: null,
footer_bg: false,
mask: { mask: {
header: true, header: true,
footer: true footer: true
}, },
rightside_bottom: null, preloader: {
enable: false,
source: 1,
pace_css_url: null
},
enter_transitions: true, enter_transitions: true,
display_mode: 'light',
beautify: {
enable: false,
field: 'post',
'title-prefix-icon': null,
'title-prefix-icon-color': null
},
font: {
'global-font-size': null,
'code-font-size': null,
'font-family': null,
'code-font-family': null
},
blog_title_font: {
font_link: null,
'font-family': null
},
hr_icon: {
enable: true,
icon: null,
'icon-top': null
},
activate_power_mode: { activate_power_mode: {
enable: false, enable: false,
colorful: true, colorful: true,
@ -436,50 +485,9 @@ hexo.extend.filter.register('before_generate', () => {
random: false, random: false,
mobile: false mobile: false
}, },
display_mode: 'light', lightbox: null,
beautify: {
enable: false,
field: 'post',
'title-prefix-icon': null,
'title-prefix-icon-color': null
},
font: {
'global-font-size': null,
'code-font-size': null,
'font-family': null,
'code-font-family': null
},
blog_title_font: {
font_link: null,
'font-family': null
},
hr_icon: {
enable: true,
icon: null,
'icon-top': null
},
subtitle: {
enable: false,
effect: true,
typed_option: null,
source: false,
sub: null
},
preloader: {
enable: false,
source: 1,
pace_css_url: null
},
wordcount: {
enable: false,
post_wordcount: true,
min2read: true,
total_wordcount: true
},
medium_zoom: false,
fancybox: true,
series: { series: {
enable: true, enable: false,
orderBy: 'title', orderBy: 'title',
order: 1, order: 1,
number: true number: true
@ -527,6 +535,14 @@ hexo.extend.filter.register('before_generate', () => {
placeholder: null, placeholder: null,
blur: false blur: false
}, },
pwa: {
enable: false,
manifest: null,
apple_touch_icon: null,
favicon_32_32: null,
favicon_16_16: null,
mask_icon: null
},
Open_Graph_meta: { Open_Graph_meta: {
enable: true, enable: true,
option: null option: null
@ -539,11 +555,11 @@ hexo.extend.filter.register('before_generate', () => {
CDN: { CDN: {
internal_provider: 'local', internal_provider: 'local',
third_party_provider: 'jsdelivr', third_party_provider: 'jsdelivr',
version: true, version: false,
custom_format: null, custom_format: null,
option: null option: null
} }
} }
hexo.theme.config = Object.assign(defaultConfig, hexo.theme.config) hexo.theme.config = deepMerge(defaultConfig, hexo.theme.config)
}, 1) }, 1)

@ -19,5 +19,6 @@ hexo.extend.filter.register('stylus:renderer', style => {
.define('$highlight_line_number', highlightLineNumber) .define('$highlight_line_number', highlightLineNumber)
.define('$prismjs_enable', prismjsEnable) .define('$prismjs_enable', prismjsEnable)
.define('$prismjs_line_number', prismjsLineNumber) .define('$prismjs_line_number', prismjsLineNumber)
.define('$language', hexo.config.language)
// .import(`${this.source_dir.replace(/\\/g, '/')}_data/css/*`) // .import(`${this.source_dir.replace(/\\/g, '/')}_data/css/*`)
}) })

@ -1,58 +0,0 @@
hexo.extend.helper.register('getArchiveLength', function () {
const { archive_generator: archiveGenerator } = hexo.config
if (archiveGenerator && archiveGenerator.enable === false) return this.site.posts.length
const { yearly, monthly, daily } = archiveGenerator
const { year, month, day } = this.page
if (yearly === false || !year) return this.site.posts.length
const posts = this.site.posts.sort('date')
const compareFunc = (type, y1, m1, d1, y2, m2, d2) => {
switch (type) {
case 'year':
return y1 === y2
case 'month':
return y1 === y2 && m1 === m2
case 'day':
return y1 === y2 && m1 === m2 && d1 === d2
default:
return false
}
}
const generateDateObj = (type) => {
return posts.reduce((dateObj, post) => {
const date = post.date.clone()
const year = date.year()
const month = date.month() + 1
const day = date.date()
const lastData = dateObj[dateObj.length - 1]
if (!lastData || !compareFunc(type, lastData.year, lastData.month, lastData.day, year, month, day)) {
const name = type === 'year' ? year : type === 'month' ? `${year}-${month}` : `${year}-${month}-${day}`
dateObj.push({
name,
year,
month,
day,
count: 1
})
} else {
lastData.count++
}
return dateObj
}, [])
}
const data = this.fragment_cache('createArchiveObj', () => {
const dateObjs = []
if (yearly) dateObjs.push(...generateDateObj('year'))
if (monthly) dateObjs.push(...generateDateObj('month'))
if (daily) dateObjs.push(...generateDateObj('day'))
return dateObjs
})
const name = month ? (day ? `${year}-${month}-${day}` : `${year}-${month}`) : year
return data.find(item => item.name === name).count
})

@ -0,0 +1,45 @@
hexo.extend.helper.register('getArchiveLength', function () {
const archiveGenerator = hexo.config.archive_generator
const posts = this.site.posts
const { yearly, monthly, daily } = archiveGenerator
const { year, month, day } = this.page
// Archives Page
if (!year) return posts.length
// Function to generate a unique key based on the granularity
const getKey = (post, type) => {
const date = post.date.clone()
const y = date.year()
const m = date.month() + 1
const d = date.date()
if (type === 'year') return `${y}`
if (type === 'month') return `${y}-${m}`
if (type === 'day') return `${y}-${m}-${d}`
}
// Create a map to count posts per period
const mapData = this.fragment_cache('createArchiveObj', () => {
const map = new Map()
posts.forEach(post => {
const keyYear = getKey(post, 'year')
const keyMonth = getKey(post, 'month')
const keyDay = getKey(post, 'day')
if (yearly) map.set(keyYear, (map.get(keyYear) || 0) + 1)
if (monthly) map.set(keyMonth, (map.get(keyMonth) || 0) + 1)
if (daily) map.set(keyDay, (map.get(keyDay) || 0) + 1)
})
return map
})
// Determine the appropriate key to fetch based on current page context
let key
if (yearly && year) key = `${year}`
if (monthly && month) key = `${year}-${month}`
if (daily && day) key = `${year}-${month}-${day}`
// Return the count for the current period or default to the total posts
return mapData.get(key) || posts.length
})

@ -1,6 +1,12 @@
/** /**
* Butterfly * Butterfly
* inject js to head * inject js to head
*
* addGlobalFn
* pjaxSendOnce - remove in pjaxSend
* pjaxCompleteOnce - remove in pjaxComplete
* pjaxSend - run in pjaxSend
* pjaxComplete - run in pjaxComplete
*/ */
'use strict' 'use strict'

@ -1,18 +1,10 @@
'use strict' 'use strict'
const { stripHTML, escapeHTML, prettyUrls } = require('hexo-util') const { stripHTML, prettyUrls, truncate } = require('hexo-util')
const crypto = require('crypto') const crypto = require('crypto')
hexo.extend.helper.register('page_description', function () { hexo.extend.helper.register('truncate', (content, length) => {
const { config, page } = this return truncate(stripHTML(content), { length, separator: ' ' }).replace(/\n/g, ' ')
let description = page.description || page.content || page.title || config.description
if (description) {
description = escapeHTML(stripHTML(description).substring(0, 150)
.trim()
).replace(/\n/g, ' ')
return description
}
}) })
hexo.extend.helper.register('cloudTags', function (options = {}) { hexo.extend.helper.register('cloudTags', function (options = {}) {
@ -32,13 +24,26 @@ hexo.extend.helper.register('cloudTags', function (options = {}) {
sizes.push(length) sizes.push(length)
}) })
const getRandomColor = () => {
const randomColor = () => Math.floor(Math.random() * 201)
const r = randomColor()
const g = randomColor()
const b = randomColor()
// 確保顏色不是太暗,通過增加一個最低值
return `rgb(${Math.max(r, 50)}, ${Math.max(g, 50)}, ${Math.max(b, 50)})`
}
const generateStyle = (size, unit) => {
const fontSize = parseFloat(size.toFixed(2)) + unit
const color = getRandomColor()
return `font-size: ${fontSize}; color: ${color};`
}
const length = sizes.length - 1 const length = sizes.length - 1
source.sort(orderby, order).forEach(tag => { source.sort(orderby, order).forEach(tag => {
const ratio = length ? sizes.indexOf(tag.length) / length : 0 const ratio = length ? sizes.indexOf(tag.length) / length : 0
const size = minfontsize + ((maxfontsize - minfontsize) * ratio) const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
let style = `font-size: ${parseFloat(size.toFixed(2))}${unit};` const style = generateStyle(size, unit)
const color = 'rgb(' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ')' // 0,0,0 -> 200,200,200
style += ` color: ${color}`
result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}</a>` result += `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}</a>`
}) })
return result return result
@ -84,5 +89,5 @@ hexo.extend.helper.register('findArchivesTitle', function (page, menu, date) {
hexo.extend.helper.register('isImgOrUrl', function (path) { hexo.extend.helper.register('isImgOrUrl', function (path) {
const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/i const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/i
return path.indexOf('//') !== -1 || imgTestReg.test(path) return path.includes('//') || imgTestReg.test(path)
}) })

@ -8,9 +8,10 @@
hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { hexo.extend.helper.register('related_posts', function (currentPost, allPosts) {
let relatedPosts = [] let relatedPosts = []
currentPost.tags.forEach(function (tag) { const tagsData = currentPost.tags
tagsData.length && tagsData.forEach(function (tag) {
allPosts.forEach(function (post) { allPosts.forEach(function (post) {
if (isTagRelated(tag.name, post.tags)) { if (currentPost.path !== post.path && isTagRelated(tag.name, post.tags)) {
const relatedPost = { const relatedPost = {
title: post.title, title: post.title,
path: post.path, path: post.path,
@ -24,13 +25,12 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) {
if (index !== -1) { if (index !== -1) {
relatedPosts[index].weight += 1 relatedPosts[index].weight += 1
} else { } else {
if (currentPost.path !== post.path) {
relatedPosts.push(relatedPost) relatedPosts.push(relatedPost)
} }
} }
}
}) })
}) })
if (relatedPosts.length === 0) { if (relatedPosts.length === 0) {
return '' return ''
} }
@ -52,7 +52,7 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) {
for (let i = 0; i < Math.min(relatedPosts.length, limitNum); i++) { for (let i = 0; i < Math.min(relatedPosts.length, limitNum); i++) {
const cover = relatedPosts[i].cover || 'var(--default-bg-color)' const cover = relatedPosts[i].cover || 'var(--default-bg-color)'
const title = this.escape_html(relatedPosts[i].title) const title = this.escape_html(relatedPosts[i].title)
result += `<div><a href="${this.url_for(relatedPosts[i].path)}" title="${title}">` result += `<a href="${this.url_for(relatedPosts[i].path)}" title="${title}">`
if (relatedPosts[i].cover_type === 'img') { if (relatedPosts[i].cover_type === 'img') {
result += `<img class="cover" src="${this.url_for(cover)}" alt="cover">` result += `<img class="cover" src="${this.url_for(cover)}" alt="cover">`
} else { } else {
@ -64,7 +64,7 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) {
result += `<div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> ${this.date(relatedPosts[i].updated, hexoConfig.date_format)}</div>` result += `<div class="content is-center"><div class="date"><i class="fas fa-history fa-fw"></i> ${this.date(relatedPosts[i].updated, hexoConfig.date_format)}</div>`
} }
result += `<div class="title">${title}</div>` result += `<div class="title">${title}</div>`
result += '</div></a></div>' result += '</div></a>'
} }
result += '</div></div>' result += '</div></div>'
@ -72,29 +72,14 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) {
} }
}) })
function isTagRelated (tagName, TBDtags) { function isTagRelated (tagName, tags) {
let result = false return tags.some(tag => tag.name === tagName)
TBDtags.forEach(function (tag) {
if (tagName === tag.name) {
result = true
}
})
return result
} }
function findItem (arrayToSearch, attr, val) { function findItem (arrayToSearch, attr, val) {
for (let i = 0; i < arrayToSearch.length; i++) { return arrayToSearch.findIndex(item => item[attr] === val)
if (arrayToSearch[i][attr] === val) {
return i
}
}
return -1
} }
function compare (attr) { function compare (attr) {
return function (a, b) { return (a, b) => b[attr] - a[attr]
const val1 = a[attr]
const val2 = b[attr]
return val2 - val1
}
} }

@ -19,6 +19,7 @@ const gallery = (args, content) => {
if (args[0] === 'url') { if (args[0] === 'url') {
[type, dataStr, button] = args // url,[link],[lazyload] [type, dataStr, button] = args // url,[link],[lazyload]
dataStr = urlFor(dataStr)
} else { } else {
[button] = args // [lazyload] [button] = args // [lazyload]
const regex = /!\[(.*?)\]\(([^\s]*)\s*(?:["'](.*?)["']?)?\s*\)/g const regex = /!\[(.*?)\]\(([^\s]*)\s*(?:["'](.*?)["']?)?\s*\)/g
@ -39,9 +40,7 @@ const gallery = (args, content) => {
} }
return `<div class="gallery-container" data-type="${type}" data-button="${button}"> return `<div class="gallery-container" data-type="${type}" data-button="${button}">
<div class="gallery-data">${dataStr}</div> <div class="gallery-items">${dataStr}</div>
<div class="gallery-items">
</div>
</div>` </div>`
} }

@ -63,7 +63,7 @@ function series (args) {
result += `<li><a href="${urlFor(ele.path)}" title="${ele.title}">${ele.title}</a></li>` result += `<li><a href="${urlFor(ele.path)}" title="${ele.title}">${ele.title}</a></li>`
}) })
return series.number ? `<ol>${result}</ol>` : `<ul>${result}</ul>` return series.number ? `<ol class="series-items">${result}</ol>` : `<ul class="series-items">${result}</ul>`
} }
hexo.extend.tag.register('series', series, { ends: false }) hexo.extend.tag.register('series', series, { ends: false })

@ -9,7 +9,7 @@
const postTabs = (args, content) => { const postTabs = (args, content) => {
const tabBlock = /<!--\s*tab (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g const tabBlock = /<!--\s*tab (.*?)\s*-->\n([\w\W\s\S]*?)<!--\s*endtab\s*-->/g
args = args.join(' ').split(',') args = args.join(' ').split(',')
const tabName = args[0] const tabName = args[0] || 'tab'
const tabActive = Number(args[1]) || 0 const tabActive = Number(args[1]) || 0
const matches = [] const matches = []
let match let match
@ -18,8 +18,6 @@ const postTabs = (args, content) => {
let tabContent = '' let tabContent = ''
let noDefault = true let noDefault = true
!tabName && hexo.log.warn('Tabs block must have unique name!')
while ((match = tabBlock.exec(content)) !== null) { while ((match = tabBlock.exec(content)) !== null) {
matches.push(match[1], match[2]) matches.push(match[1], match[2])
} }
@ -29,34 +27,31 @@ const postTabs = (args, content) => {
let postContent = matches[i + 1] let postContent = matches[i + 1]
let tabCaption = tabParameters[0] || '' let tabCaption = tabParameters[0] || ''
let tabIcon = tabParameters[1] || '' let tabIcon = tabParameters[1] || ''
let tabHref = ''
postContent = hexo.render.renderSync({ text: postContent, engine: 'markdown' }).trim() postContent = hexo.render.renderSync({ text: postContent, engine: 'markdown' }).trim()
tabId += 1 tabId += 1
tabHref = (tabName + ' ' + tabId).toLowerCase().split(' ').join('-');
((tabCaption.length === 0) && (tabIcon.length === 0)) && (tabCaption = tabName + ' ' + tabId) if (tabCaption.length === 0 && tabIcon.length === 0) tabCaption = tabName + ' ' + tabId
const isOnlyicon = tabIcon.length > 0 && tabCaption.length === 0 ? ' style="text-align: center;"' : ''
const icon = tabIcon.trim() const icon = tabIcon.trim()
tabIcon.length > 0 && (tabIcon = `<i class="${icon}"${isOnlyicon}></i>`) tabIcon.length > 0 && (tabIcon = `<i class="${icon}"></i>`)
let isActive = '' let isActive = ''
if ((tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1)) { if ((tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1)) {
isActive = ' active' isActive = ' active'
noDefault = false noDefault = false
} }
tabNav += `<button type="button" class="tab ${isActive}" data-href="${tabHref}">${tabIcon + tabCaption.trim()}</button>` tabNav += `<button type="button" class="tab${isActive}">${tabIcon + tabCaption.trim()}</button>`
tabContent += `<div class="tab-item-content${isActive}" id="${tabHref}">${postContent}</div>` tabContent += `<div class="tab-item-content${isActive}">${postContent}</div>`
} }
const toTop = '<div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div>' const toTop = '<div class="tab-to-top"><button type="button" aria-label="scroll to top"><i class="fas fa-arrow-up"></i></button></div>'
tabNav = `<ul class="nav-tabs${noDefault ? ' no-default' : ''}">${tabNav}</ul>` tabNav = `<div class="nav-tabs${noDefault ? ' no-default' : ''}">${tabNav}</div>`
tabContent = `<div class="tab-contents">${tabContent}</div>` tabContent = `<div class="tab-contents">${tabContent}</div>`
return `<div class="tabs" id="${tabName.toLowerCase().split(' ').join('-')}">${tabNav + tabContent + toTop}</div>` return `<div class="tabs">${tabNav + tabContent + toTop}</div>`
} }
hexo.extend.tag.register('tabs', postTabs, { ends: true }) hexo.extend.tag.register('tabs', postTabs, { ends: true })

@ -15,12 +15,16 @@
text-rendering: auto text-rendering: auto
-webkit-font-smoothing: antialiased -webkit-font-smoothing: antialiased
addBorderRadius(x = 6)
if hexo-config('rounded_corners_ui')
border-radius: unit(x, 'px')
// card hover // card hover
.cardHover .cardHover
border-radius: 8px
background: var(--card-bg) background: var(--card-bg)
box-shadow: var(--card-box-shadow) box-shadow: var(--card-box-shadow)
transition: all .3s transition: all .3s
addBorderRadius(8)
&:hover &:hover
box-shadow: var(--card-hover-box-shadow) box-shadow: var(--card-hover-box-shadow)
@ -37,11 +41,10 @@
.postImgHover .postImgHover
&:hover &:hover
.cover .cover
opacity: .8 opacity: .7
transform: scale(1.1) transform: scale(1.1)
.cover .cover
position: absolute
width: 100% width: 100%
height: 100% height: 100%
opacity: .4 opacity: .4
@ -96,6 +99,12 @@
transition: all 1s ease-in-out transition: all 1s ease-in-out
@extend .fontawesomeIcon @extend .fontawesomeIcon
.verticalCenter
position: absolute
top: 50%
width: 100%
transform: translate(0, -50%)
maxWidth600() maxWidth600()
@media screen and (max-width: 600px) @media screen and (max-width: 600px)
{block} {block}
@ -112,6 +121,10 @@ maxWidth1024()
@media screen and (max-width: 1024px) @media screen and (max-width: 1024px)
{block} {block}
minWidth1024()
@media screen and (min-width: 1024px)
{block}
maxWidth900() maxWidth900()
@media screen and (max-width: 900px) @media screen and (max-width: 900px)
{block} {block}

@ -15,7 +15,9 @@
--tab-button-hover-bg: $tab-button-hover-bg --tab-button-hover-bg: $tab-button-hover-bg
--tab-button-active-bg: $tab-button-active-bg --tab-button-active-bg: $tab-button-active-bg
--card-bg: $card-bg --card-bg: $card-bg
--card-meta: $theme-meta-color
--sidebar-bg: $sidebar-background --sidebar-bg: $sidebar-background
--sidebar-menu-bg: $white
--btn-hover-color: $button-hover-color --btn-hover-color: $button-hover-color
--btn-color: $button-color --btn-color: $button-color
--btn-bg: $button-bg --btn-bg: $button-bg
@ -39,6 +41,7 @@
body body
position: relative position: relative
overflow-y: scroll
min-height: 100% min-height: 100%
background: var(--global-bg) background: var(--global-bg)
color: var(--font-color) color: var(--font-color)
@ -52,6 +55,12 @@ body
user-select: none user-select: none
-webkit-user-select: none -webkit-user-select: none
// scrollbar - firefox
@-moz-document url-prefix()
*
scrollbar-width: thin
scrollbar-color: var(--scrollbar-color) transparent
// scrollbar - chrome/safari // scrollbar - chrome/safari
*::-webkit-scrollbar *::-webkit-scrollbar
width: 5px width: 5px
@ -63,11 +72,6 @@ body
*::-webkit-scrollbar-track *::-webkit-scrollbar-track
background-color: transparent background-color: transparent
// scrollbar - firefox
*
scrollbar-width: thin
scrollbar-color: var(--scrollbar-color) transparent
input::placeholder input::placeholder
color: var(--font-color) color: var(--font-color)
@ -104,11 +108,34 @@ h6
overflow-x: scroll overflow-x: scroll
margin: 0 0 20px margin: 0 0 20px
if hexo-config('rounded_corners_ui')
$borderRadius = 5px
border-radius: $borderRadius
table
border-radius: $borderRadius
thead > tr:first-child
th:first-child
border-top-left-radius: $borderRadius
th:last-child
border-top-right-radius: $borderRadius
tbody > tr:last-child
td:first-child
border-bottom-left-radius: $borderRadius
td:last-child
border-bottom-right-radius: $borderRadius
table table
display: table display: table
width: 100% width: 100%
border-spacing: 0 border-spacing: 0
border-collapse: collapse border-collapse: separate
border-top: 1px solid var(--light-grey)
border-left: 1px solid var(--light-grey)
empty-cells: show empty-cells: show
thead thead
@ -118,6 +145,8 @@ table
td td
padding: 6px 12px padding: 6px 12px
border: 1px solid var(--light-grey) border: 1px solid var(--light-grey)
border-top: none
border-left: none
vertical-align: middle vertical-align: middle
*::selection *::selection
@ -147,8 +176,8 @@ if $site-name-font
#site-title, #site-title,
#site-subtitle, #site-subtitle,
.site-name, .site-name,
#aside-content .author-info__name, #aside-content .author-info-name,
#aside-content .author-info__description #aside-content .author-info-description
font-family: $site-name-font font-family: $site-name-font
.is-center .is-center
@ -183,10 +212,11 @@ if hexo-config('lazyload.enable') && hexo-config('lazyload.blur') && !hexo-confi
blockquote blockquote
margin: 0 0 20px margin: 0 0 20px
padding: 12px 15px padding: 7px 15px
border-left: 3px solid $blockquote-padding-color border-left: 4px solid $blockquote-padding-color
background-color: var(--blockquote-bg) background-color: var(--blockquote-bg)
color: var(--blockquote-color) color: var(--blockquote-color)
addBorderRadius()
footer footer
cite cite

@ -1,6 +1,6 @@
$highlight_theme = hexo-config('highlight_theme') $highlight_theme = hexo-config('code_blocks.theme')
$highlight_macstyle = hexo-config('highlight_theme_macStyle') $highlight_macstyle = hexo-config('code_blocks.macStyle')
wordWrap = $highlight_enable && !$highlight_line_number && hexo-config('code_word_wrap') wordWrap = $highlight_enable && !$highlight_line_number && hexo-config('code_blocks.word_wrap')
@require 'theme' @require 'theme'
@ -47,9 +47,10 @@ $code-block
code code
font-size: $code-font-size font-size: $code-font-size
font-family: $code-font-family !important font-family: $code-font-family !important
addBorderRadius()
code code
padding: 2px 4px padding: 2px 5px
background: $code-background background: $code-background
color: $code-foreground color: $code-foreground
@ -66,6 +67,7 @@ $code-block
figure.highlight figure.highlight
@extend $code-block @extend $code-block
position: relative position: relative
addBorderRadius()
pre pre
margin: 0 margin: 0
@ -104,9 +106,10 @@ $code-block
background: var(--hltools-bg) background: var(--hltools-bg)
color: var(--hltools-color) color: var(--hltools-color)
font-size: $code-font-size font-size: $code-font-size
overflow: hidden
& > * & > *
margin: 0 3px padding: 5px
i i
cursor: pointer cursor: pointer
@ -124,7 +127,7 @@ $code-block
if !$highlight_macstyle if !$highlight_macstyle
& > .macStyle & > .macStyle
margin: 0 padding: 0
.code-lang .code-lang
flex: 1 flex: 1
@ -133,16 +136,17 @@ $code-block
font-size: 1.15em font-size: 1.15em
user-select: none user-select: none
-webkit-user-select: none -webkit-user-select: none
padding 2px
.copy-notice .copy-notice
padding-right: 2px padding-right: 2px
opacity: 0 opacity: 0
transition: opacity .4s transition: opacity .4s
if hexo-config('highlight_lang') if hexo-config('code_blocks.language')
.code-lang .code-lang
flex: 1 flex: 1
else if (!$highlight_macstyle && hexo-config('highlight_shrink') != 'none') else if (!$highlight_macstyle && hexo-config('code_blocks.shrink') != 'none')
& > div:nth-child(2) & > div:nth-child(2)
flex: 1 flex: 1
else else
@ -168,8 +172,6 @@ if $highlight_macstyle
-webkit-transform: translateZ(0) -webkit-transform: translateZ(0)
.highlight-tools .highlight-tools
padding: 0 10px
.macStyle .macStyle
display: flex display: flex
@ -191,15 +193,15 @@ if $highlight_macstyle
.mac-maximize .mac-maximize
background: #35cd4b background: #35cd4b
if hexo-config('highlight_shrink') != 'none' if hexo-config('code_blocks.shrink') != 'none'
& > div:nth-child(2) & > :nth-child(2)
order: 8 order: 8
&.closed &.closed
.expand .expand
transform: rotate(90deg) transform: rotate(90deg)
if hexo-config('highlight_height_limit') if hexo-config('code_blocks.height_limit')
#article-container #article-container
.code-expand-btn .code-expand-btn
position: absolute position: absolute
@ -228,7 +230,7 @@ if hexo-config('highlight_height_limit')
& ~ table, & ~ table,
& ~ pre & ~ pre
overflow: hidden overflow: hidden
height: unit(hexo-config('highlight_height_limit'), px) height: unit(hexo-config('code_blocks.height_limit'), px)
@keyframes code-expand-key @keyframes code-expand-key
0% 0%
@ -240,7 +242,7 @@ if hexo-config('highlight_height_limit')
100% 100%
opacity: .6 opacity: .6
if hexo-config('highlight_fullpage') if hexo-config('code_blocks.fullpage')
#article-container #article-container
figure.highlight.code-fullpage figure.highlight.code-fullpage
position: fixed position: fixed

@ -1,5 +1,7 @@
figure.highlight figure.highlight
table table
// scrollbar - firefox
@-moz-document url-prefix()
scrollbar-color: var(--hlscrollbar-bg) transparent scrollbar-color: var(--hlscrollbar-bg) transparent
&::-webkit-scrollbar-thumb &::-webkit-scrollbar-thumb

@ -6,6 +6,8 @@ if $highlight_theme != false
#article-container #article-container
pre[class*='language-'] pre[class*='language-']
// scrollbar - firefox
@-moz-document url-prefix()
scrollbar-color: var(--hlscrollbar-bg) transparent scrollbar-color: var(--hlscrollbar-bg) transparent
&::-webkit-scrollbar-thumb &::-webkit-scrollbar-thumb

@ -10,7 +10,7 @@
position: relative position: relative
line-height: $line-height-code-block line-height: $line-height-code-block
if hexo-config('code_word_wrap') if hexo-config('code_blocks.word_wrap')
white-space: pre-wrap white-space: pre-wrap
else else
white-space: inherit white-space: inherit

@ -7,20 +7,15 @@
else else
padding-right: 15px padding-right: 15px
+maxWidth900()
width: 100%
> .card-widget:first-child
margin-top: 0
+maxWidth900() +maxWidth900()
margin-top: 20px margin-top: 20px
width: 100%
.card-widget .card-widget
@extend .cardHover @extend .cardHover
position: relative position: relative
overflow: hidden overflow: hidden
margin-top: 20px margin-bottom: 20px
padding: 20px 24px padding: 20px 24px
if hexo-config('aside.mobile') == false if hexo-config('aside.mobile') == false
@ -28,16 +23,19 @@
&:not(#card-toc) &:not(#card-toc)
display: none display: none
&:last-child
margin-bottom: 0
.card-info .card-info
.author-info .author-info
&__name &-name
font-weight: 500 font-weight: 500
font-size: 1.57em font-size: 1.57em
&__description &-description
margin-top: -.42em margin-top: -.42em
.card-info-data .site-data
margin: 14px 0 4px margin: 14px 0 4px
.card-info-social-icons .card-info-social-icons
@ -61,6 +59,7 @@
color: var(--btn-color) color: var(--btn-color)
text-align: center text-align: center
line-height: 2.4 line-height: 2.4
addBorderRadius(7)
&:hover &:hover
background-color: var(--btn-hover-color) background-color: var(--btn-hover-color)
@ -86,6 +85,7 @@
a a
display: inline-block display: inline-block
padding: 0 4px padding: 0 4px
line-height: 1.8
&:hover &:hover
color: $text-hover !important color: $text-hover !important
@ -112,8 +112,9 @@
.thumbnail .thumbnail
overflow: hidden overflow: hidden
width: w = 4.2em width: w = 4em
height: w height: w
addBorderRadius()
:first-child :first-child
@extend .imgHover @extend .imgHover
@ -130,14 +131,14 @@
& > time, & > time,
& > .name & > .name
display: block display: block
color: $theme-meta-color color: var(--card-meta)
font-size: 85% font-size: .85em
& > .title, & > .title,
& > .comment & > .comment
@extend .limit-more-line @extend .limit-more-line
color: var(--font-color) color: var(--font-color)
font-size: 95% // font-size: 95%
line-height: 1.5 line-height: 1.5
-webkit-line-clamp: 2 -webkit-line-clamp: 2
@ -158,13 +159,16 @@
a a
display: flex display: flex
flex-direction: row flex-direction: row
padding: 3px 10px padding: 2px 8px
margin: 2px 0
color: var(--font-color) color: var(--font-color)
transition: all .4s transition: all .3s
addBorderRadius()
&:hover &:hover
padding: 3px 17px padding: 2px 12px
background-color: var(--text-bg-hover) background-color: var(--text-bg-hover)
color: var(--white)
span span
@extend .limit-one-line @extend .limit-one-line
@ -288,9 +292,10 @@
.toc-link .toc-link
display: block display: block
margin: 4px 0 margin: 4px 0
padding: 1px 6px padding: 1px 8px
color: var(--toc-link-color) color: var(--toc-link-color)
transition: all .2s ease-in-out transition: all .2s ease-in-out
addBorderRadius()
&:hover &:hover
color: $theme-color color: $theme-color
@ -397,9 +402,9 @@
.card-recent-post .card-recent-post
order: hexo-config('aside.card_recent_post.sort_order') order: hexo-config('aside.card_recent_post.sort_order')
if hexo-config('newest_comments.sort_order') if hexo-config('aside.card_newest_comments.sort_order')
#card-newest-comments #card-newest-comments
order: hexo-config('newest_comments.sort_order') order: hexo-config('aside.card_newest_comments.sort_order')
if hexo-config('aside.card_categories.sort_order') if hexo-config('aside.card_categories.sort_order')
.card-categories .card-categories

@ -1,5 +1,6 @@
// chat // chat
if hexo-config('chat_btn') == true && hexo-config('chatra.enable') if hexo-config('chat.rightside_button') == true
if hexo-config('chat.use') == 'chatra'
#chatra:not(.chatra--expanded) #chatra:not(.chatra--expanded)
visibility: hidden !important visibility: hidden !important
width: 1px !important width: 1px !important
@ -7,7 +8,7 @@ if hexo-config('chat_btn') == true && hexo-config('chatra.enable')
opacity: 0 !important opacity: 0 !important
pointer-events: none pointer-events: none
if hexo-config('chat_btn') == true && hexo-config('messenger.enable') if hexo-config('chat.use') == 'messenger'
.fb_dialog, .fb_dialog,
.fb-customerchat .fb-customerchat
visibility: hidden !important visibility: hidden !important

@ -5,7 +5,7 @@
background-position: bottom background-position: bottom
background-size: cover background-size: cover
if hexo-config('footer_bg') != false && hexo-config('mask.footer') if hexo-config('footer_img') != false && hexo-config('mask.footer')
&:before &:before
position: absolute position: absolute
width: 100% width: 100%

@ -146,6 +146,7 @@
background: rgba(255, 255, 255, .8) background: rgba(255, 255, 255, .8)
box-shadow: 0 5px 6px -5px alpha($grey, .6) box-shadow: 0 5px 6px -5px alpha($grey, .6)
transition: transform .2s ease-in-out, opacity .2s ease-in-out transition: transform .2s ease-in-out, opacity .2s ease-in-out
will-change: transform
#blog-info #blog-info
color: var(--font-color) color: var(--font-color)
@ -345,10 +346,10 @@
margin-top: 8px margin-top: 8px
padding: 0 padding: 0
width: max-content width: max-content
border-radius: 5px
background-color: var(--sidebar-bg) background-color: var(--sidebar-bg)
box-shadow: 0 5px 20px -4px rgba($dark-black, .5) box-shadow: 0 5px 20px -4px rgba($dark-black, .5)
animation: sub_menus .3s .1s ease both animation: sub_menus .3s .1s ease both
addBorderRadius(5)
&:before &:before
position: absolute position: absolute
@ -364,6 +365,7 @@
&:hover &:hover
background: var(--text-bg-hover) background: var(--text-bg-hover)
if hexo-config('rounded_corners_ui')
&:first-child &:first-child
border-top-left-radius: 5px border-top-left-radius: 5px
border-top-right-radius: 5px border-top-right-radius: 5px

@ -37,25 +37,22 @@
.prev-post, .prev-post,
.next-post .next-post
@extend .postImgHover @extend .postImgHover
position: relative
overflow: hidden
width: 50% width: 50%
height: 150px
+maxWidth768() +maxWidth768()
width: 100% width: 100%
a
position: relative
display: block
overflow: hidden
height: 150px
&.pagination-post &.pagination-post
overflow: hidden overflow: hidden
margin-top: 40px margin-top: 40px
width: 100% width: 100%
background: $dark-black background: $dark-black
addBorderRadius()
.layout .layout
& > .recent-posts
.pagination .pagination
& > * & > *
display: inline-block display: inline-block
@ -71,13 +68,9 @@
background: var(--btn-hover-color) background: var(--btn-hover-color)
color: var(--btn-color) color: var(--btn-color)
& > div:not(.recent-posts) #archive
.pagination .pagination
.page-number margin-top: 30px
display: inline-block
margin: 0 4px & > *:not(.space)
min-width: w = 24px box-shadow: none
height: w
text-align: center
line-height: w
cursor: pointer

@ -87,6 +87,7 @@ beautify()
margin: 0 auto 20px margin: 0 auto 20px
max-width: 100% max-width: 100%
transition: filter 375ms ease-in .2s transition: filter 375ms ease-in .2s
addBorderRadius()
p p
margin: 0 0 16px margin: 0 0 16px
@ -98,7 +99,6 @@ beautify()
margin: 0 3px margin: 0 3px
padding: 3px 5px padding: 3px 5px
border: 1px solid #b4b4b4 border: 1px solid #b4b4b4
border-radius: 3px
background-color: #f8f8f8 background-color: #f8f8f8
box-shadow: 0 1px 3px rgba(0, 0, 0, .25), 0 2px 1px 0 rgba(255, 255, 255, .6) inset box-shadow: 0 1px 3px rgba(0, 0, 0, .25), 0 2px 1px 0 rgba(255, 255, 255, .6) inset
color: #34495e color: #34495e
@ -107,6 +107,7 @@ beautify()
font-size: .9em font-size: .9em
font-family: Monaco, 'Ubuntu Mono', monospace font-family: Monaco, 'Ubuntu Mono', monospace
line-height: 1em line-height: 1em
addBorderRadius(3)
if hexo-config('anchor.click_to_scroll') if hexo-config('anchor.click_to_scroll')
h1, h1,
@ -181,7 +182,7 @@ beautify()
background: $light-blue background: $light-blue
color: var(--white) color: var(--white)
.post_share .post-share
display: inline-block display: inline-block
float: right float: right
margin: 8px 0 0 margin: 8px 0 0
@ -203,6 +204,7 @@ beautify()
padding: 10px 16px padding: 10px 16px
border: 1px solid var(--light-grey) border: 1px solid var(--light-grey)
transition: box-shadow .3s ease-in-out transition: box-shadow .3s ease-in-out
addBorderRadius()
&:before &:before
@extend .fontawesomeIcon @extend .fontawesomeIcon
@ -238,9 +240,9 @@ beautify()
position: relative position: relative
margin: 0 0 20px margin: 0 0 20px
padding: .5em 1.2em padding: .5em 1.2em
border-radius: 3px
background-color: $noticeOutdate-bg background-color: $noticeOutdate-bg
color: $noticeOutdate-color color: $noticeOutdate-color
addBorderRadius(3)
if hexo-config('noticeOutdate.style') == 'flat' if hexo-config('noticeOutdate.style') == 'flat'
padding: .5em 1em .5em 2.6em padding: .5em 1em .5em 2.6em

@ -7,7 +7,7 @@
font-size: 1.43em font-size: 1.43em
& > .relatedPosts-list & > .relatedPosts-list
& > div & > a
position: relative position: relative
display: inline-block display: inline-block
overflow: hidden overflow: hidden
@ -17,6 +17,7 @@
background: $dark-black background: $dark-black
vertical-align: bottom vertical-align: bottom
@extend .postImgHover @extend .postImgHover
addBorderRadius()
+maxWidth768() +maxWidth768()
margin: 2px margin: 2px
@ -27,11 +28,8 @@
width: calc(100% - 4px) width: calc(100% - 4px)
.content .content
position: absolute
top: 50%
padding: 0 20px padding: 0 20px
width: 100% @extend .verticalCenter
transform: translate(0, -50%)
.date .date
color: var(--light-grey) color: var(--light-grey)

@ -14,6 +14,7 @@
background: var(--btn-bg) background: var(--btn-bg)
color: var(--btn-color) color: var(--btn-color)
cursor: pointer cursor: pointer
addBorderRadius()
i i
margin-right: 5px margin-right: 5px
@ -33,12 +34,12 @@
display: none display: none
padding: 0 0 15px padding: 0 0 15px
width: 100% width: 100%
addBorderRadius()
.reward-all .reward-all
display: inline-block display: inline-block
margin: 0 margin: 0
padding: 20px 10px padding: 20px 10px
border-radius: 4px
background: var(--reward-pop) background: var(--reward-pop)
&:before &:before

@ -32,12 +32,12 @@
margin-bottom: 5px margin-bottom: 5px
width: w = 35px width: w = 35px
height: w height: w
border-radius: 5px
background-color: var(--btn-bg) background-color: var(--btn-bg)
color: var(--btn-color) color: var(--btn-color)
text-align: center text-align: center
font-size: 16px font-size: 16px
line-height: w line-height: w
addBorderRadius(5)
&:hover &:hover
background-color: var(--btn-hover-color) background-color: var(--btn-hover-color)

@ -26,27 +26,33 @@
& > .avatar-img & > .avatar-img
margin: 20px auto margin: 20px auto
.sidebar-site-data .site-data
padding: 0 10px padding: 0 10px
hr hr
margin: 20px auto margin: 20px auto
.menus_items .menus_items
padding: 0 10px margin: 20px
padding: 15px
background: var(--sidebar-menu-bg)
box-shadow: 0 0 1px 1px rgba(7, 17, 27, .05)
addBorderRadius(10)
.site-page .site-page
@extend .limit-one-line @extend .limit-one-line
position: relative position: relative
display: block display: block
padding: 3px 28px 3px 20px margin: 4px 0
border-radius: 6px padding: 2px 23px 2px 15px
color: var(--font-color) color: var(--font-color)
font-size: 1.15em font-size: 1.15em
cursor: pointer cursor: pointer
addBorderRadius(6)
&:hover &:hover
background: var(--text-bg-hover) background: var(--text-bg-hover)
color: var(--white)
i:first-child i:first-child
width: 15% width: 15%
@ -55,8 +61,8 @@
&.group &.group
& > i:last-child & > i:last-child
position: absolute position: absolute
top: .78em top: .6em
right: 13px right: 10px
transition: transform .3s transition: transform .3s
&.hide &.hide

@ -79,11 +79,25 @@ if hexo-config('mermaid.enable')
margin: 0 0 .8em margin: 0 0 .8em
padding: 6px 0 16px padding: 6px 0 16px
if hexo-config('math.use')
.katex-display .katex-display
overflow: auto hidden overflow: auto hidden
padding: 5px padding: 5px
if hexo-config('katex') && hexo-config('katex.hide_scrollbar') .katex-show
display: block
.katex
display: none
&.katex-show
display: inline
if hexo-config('math.hide_scrollbar')
.katex-display,
mjx-container
scrollbar-width: none
&::-webkit-scrollbar &::-webkit-scrollbar
display: none display: none

@ -16,6 +16,7 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark'
--tab-button-active-bg: #121212 --tab-button-active-bg: #121212
--card-bg: #121212 --card-bg: #121212
--sidebar-bg: #121212 --sidebar-bg: #121212
--sidebar-menu-bg: lighten(#121212, 5)
--btn-hover-color: lighten(#121212, 40) --btn-hover-color: lighten(#121212, 40)
--btn-color: alpha(#FFFFFF, .7) --btn-color: alpha(#FFFFFF, .7)
--btn-bg: lighten(#121212, 5) --btn-bg: lighten(#121212, 5)
@ -140,3 +141,20 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark'
#card-toc #card-toc
+maxWidth900() +maxWidth900()
background: lighten(#121212, 5) background: lighten(#121212, 5)
// artalk
.artalk.atk-dark-mode,
.atk-layer-wrap.atk-dark-mode
--at-color-font: alpha(#FFFFFF, .7)
--at-color-meta: alpha(#FFFFFF, .7)
--at-color-grey: alpha(#FFFFFF, .7)
.atk-send-btn,
.atk-badge
color: alpha(#FFFFFF, .7) !important
// waline
#waline-wrap
--waline-color: alpha(#FFFFFF, .7)
--waline-dark-grey: alpha(#FFFFFF, .7)
--waline-info-color: alpha(#FFFFFF, .5)

@ -37,11 +37,11 @@ if hexo-config('readmode')
z-index: 100 z-index: 100
width: 40px width: 40px
height: 40px height: 40px
border-radius: 8px
background: var(--exit-btn-bg) background: var(--exit-btn-bg)
color: var(--exit-btn-color) color: var(--exit-btn-color)
font-size: 16px font-size: 16px
transition: background .3s transition: background .3s
addBorderRadius(8)
+maxWidth768() +maxWidth768()
top: initial top: initial

@ -1,15 +1,5 @@
if hexo-config('error_404.enable') if hexo-config('error_404.enable')
.error404 .type-404
#error-wrap
position: absolute
top: 50%
right: 0
left: 0
margin: 0 auto
padding: 60px 20px 0
max-width: 1000px
transform: translate(0, -50%)
.error-content .error-content
@extend .cardHover @extend .cardHover
overflow: hidden overflow: hidden
@ -65,5 +55,12 @@ if hexo-config('error_404.enable')
font-size: 1.6em font-size: 1.6em
-webkit-line-clamp: 2 -webkit-line-clamp: 2
.nc
margin-top: 5%
padding: 0 20px
#footer
display: none
& + #rightside & + #rightside
display: none display: none

@ -78,8 +78,8 @@
border-color: var(--pseudo-hover) border-color: var(--pseudo-hover)
&-time &-time
color: $theme-meta-color color: var(--card-meta)
font-size: 95% font-size: .85em
time time
padding-left: 6px padding-left: 6px
@ -88,7 +88,7 @@
&-title &-title
@extend .limit-more-line @extend .limit-more-line
color: var(--font-color) color: var(--font-color)
font-size: 1.1em font-size: 1.05em
transition: all .3s transition: all .3s
-webkit-line-clamp: 2 -webkit-line-clamp: 2
@ -98,8 +98,13 @@
&-img &-img
overflow: hidden overflow: hidden
width: 80px width: 100px
height: 80px height: 70px
addBorderRadius()
+maxWidth768()
width: 70px
height: 70px
:first-child :first-child
@extend .imgHover @extend .imgHover

@ -16,7 +16,7 @@
.category-list-count .category-list-count
margin-left: 8px margin-left: 8px
color: $theme-meta-color color: var(--card-meta)
&:before &:before
content: '(' content: '('

@ -20,7 +20,7 @@
+minWidth2000() +minWidth2000()
max-width: 70% max-width: 70%
& > div:first-child:not(.recent-posts) & > div:first-child:not(.nc)
@extend .cardHover @extend .cardHover
align-self: flex-start align-self: flex-start
padding: 50px 40px padding: 50px 40px

@ -14,9 +14,9 @@
margin: 15px 7px margin: 15px 7px
width: calc(100% / 3 - 15px) width: calc(100% / 3 - 15px)
height: 90px height: 90px
border-radius: 8px
line-height: 17px line-height: 17px
-webkit-transform: translateZ(0) -webkit-transform: translateZ(0)
addBorderRadius(8)
+maxWidth1024() +maxWidth1024()
width: calc(50% - 15px) !important width: calc(50% - 15px) !important
@ -56,7 +56,7 @@
margin: 15px 10px margin: 15px 10px
width: 60px width: 60px
height: 60px height: 60px
border-radius: 35px border-radius: 7px
transition: width .3s ease-out transition: width .3s ease-out
img img

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

Loading…
Cancel
Save