From f605e6dc8999d6691424d697b80faf67906d8b58 Mon Sep 17 00:00:00 2001 From: Jerry Date: Sun, 16 Feb 2025 20:38:17 +0800 Subject: [PATCH] update --- .DS_Store | Bin 0 -> 6148 bytes .github/ISSUE_TEMPLATE/bug_report.yml | 164 +- .github/ISSUE_TEMPLATE/config.yml | 36 +- .github/ISSUE_TEMPLATE/feature_request.yml | 26 +- .github/workflows/publish.yml | 36 +- .github/workflows/stale.yml | 36 +- LICENSE | 402 +-- README.md | 234 +- README_CN.md | 234 +- _config.yml | 2212 ++++++++--------- languages/default.yml | 242 +- languages/en.yml | 242 +- languages/ja.yml | 242 +- languages/ko.yml | 242 +- languages/zh-CN.yml | 244 +- languages/zh-HK.yml | 242 +- languages/zh-TW.yml | 242 +- layout/archive.pug | 14 +- layout/category.pug | 22 +- layout/includes/additional-js.pug | 112 +- layout/includes/footer.pug | 35 +- layout/includes/head.pug | 154 +- layout/includes/head/Open_Graph.pug | 32 +- layout/includes/head/analytics.pug | 66 +- layout/includes/head/config.pug | 252 +- layout/includes/head/config_site.pug | 50 +- layout/includes/head/google_adsense.pug | 16 +- layout/includes/head/preconnect.pug | 68 +- layout/includes/head/pwa.pug | 26 +- layout/includes/head/site_verification.pug | 4 +- layout/includes/header/index.pug | 102 +- layout/includes/header/menu_item.pug | 52 +- layout/includes/header/nav.pug | 42 +- layout/includes/header/post-info.pug | 296 +-- layout/includes/header/social.pug | 14 +- layout/includes/layout.pug | 72 +- layout/includes/loading/fullpage-loading.pug | 64 +- layout/includes/loading/index.pug | 8 +- layout/includes/loading/pace.pug | 22 +- layout/includes/mixins/article-sort.pug | 44 +- layout/includes/mixins/indexPostUI.pug | 230 +- layout/includes/page/404.pug | 16 +- layout/includes/page/default-page.pug | 2 +- layout/includes/page/flink.pug | 164 +- layout/includes/page/shuoshuo.pug | 374 +-- layout/includes/page/tags.pug | 2 +- layout/includes/pagination.pug | 72 +- layout/includes/post/outdate-notice.pug | 14 +- layout/includes/post/post-copyright.pug | 44 +- layout/includes/post/reward.pug | 22 +- layout/includes/rightside.pug | 120 +- layout/includes/sidebar.pug | 34 +- layout/includes/third-party/abcjs/abcjs.pug | 32 +- layout/includes/third-party/abcjs/index.pug | 6 +- layout/includes/third-party/aplayer.pug | 46 +- .../third-party/card-post-count/artalk.pug | 60 +- .../third-party/card-post-count/disqus.pug | 50 +- .../third-party/card-post-count/fb.pug | 36 +- .../third-party/card-post-count/index.pug | 30 +- .../third-party/card-post-count/remark42.pug | 34 +- .../third-party/card-post-count/twikoo.pug | 72 +- .../third-party/card-post-count/valine.pug | 40 +- .../third-party/card-post-count/waline.pug | 42 +- layout/includes/third-party/chat/chatra.pug | 76 +- layout/includes/third-party/chat/crisp.pug | 62 +- layout/includes/third-party/chat/index.pug | 12 +- layout/includes/third-party/chat/tidio.pug | 90 +- .../includes/third-party/comments/artalk.pug | 144 +- .../includes/third-party/comments/disqus.pug | 160 +- .../third-party/comments/disqusjs.pug | 172 +- .../comments/facebook_comments.pug | 128 +- .../includes/third-party/comments/giscus.pug | 164 +- .../includes/third-party/comments/gitalk.pug | 128 +- .../includes/third-party/comments/index.pug | 92 +- layout/includes/third-party/comments/js.pug | 50 +- .../includes/third-party/comments/livere.pug | 92 +- .../third-party/comments/remark42.pug | 154 +- .../includes/third-party/comments/twikoo.pug | 126 +- .../third-party/comments/utterances.pug | 124 +- .../includes/third-party/comments/valine.pug | 118 +- .../includes/third-party/comments/waline.pug | 122 +- layout/includes/third-party/effect.pug | 68 +- layout/includes/third-party/math/chartjs.pug | 182 +- layout/includes/third-party/math/index.pug | 26 +- layout/includes/third-party/math/katex.pug | 30 +- layout/includes/third-party/math/mathjax.pug | 92 +- layout/includes/third-party/math/mermaid.pug | 100 +- .../third-party/newest-comments/artalk.pug | 132 +- .../third-party/newest-comments/common.pug | 120 +- .../newest-comments/disqus-comment.pug | 68 +- .../newest-comments/github-issues.pug | 124 +- .../third-party/newest-comments/index.pug | 66 +- .../third-party/newest-comments/remark42.pug | 62 +- .../newest-comments/twikoo-comment.pug | 90 +- .../third-party/newest-comments/valine.pug | 102 +- .../third-party/newest-comments/waline.pug | 64 +- layout/includes/third-party/pjax.pug | 126 +- layout/includes/third-party/prismjs.pug | 44 +- .../includes/third-party/search/algolia.pug | 42 +- .../includes/third-party/search/docsearch.pug | 58 +- layout/includes/third-party/search/index.pug | 12 +- .../third-party/search/local-search.pug | 42 +- .../includes/third-party/share/addtoany.pug | 20 +- layout/includes/third-party/share/index.pug | 16 +- .../includes/third-party/share/share-js.pug | 6 +- layout/includes/third-party/subtitle.pug | 184 +- .../includes/third-party/umami_analytics.pug | 128 +- layout/includes/widget/card_ad.pug | 6 +- layout/includes/widget/card_announcement.pug | 10 +- layout/includes/widget/card_archives.pug | 14 +- layout/includes/widget/card_author.pug | 52 +- layout/includes/widget/card_bottom_self.pug | 18 +- layout/includes/widget/card_categories.pug | 8 +- .../includes/widget/card_newest_comment.pug | 14 +- layout/includes/widget/card_post_series.pug | 42 +- layout/includes/widget/card_post_toc.pug | 28 +- layout/includes/widget/card_recent_post.pug | 52 +- layout/includes/widget/card_tags.pug | 28 +- layout/includes/widget/card_top_self.pug | 14 +- layout/includes/widget/card_webinfo.pug | 86 +- layout/includes/widget/index.pug | 70 +- layout/index.pug | 8 +- layout/page.pug | 62 +- layout/post.pug | 70 +- layout/tag.pug | 22 +- package.json | 64 +- plugins.yml | 422 ++-- scripts/common/postDesc.js | 72 +- scripts/events/404.js | 40 +- scripts/events/cdn.js | 194 +- scripts/events/comment.js | 48 +- scripts/events/init.js | 40 +- scripts/events/merge_config.js | 1166 ++++----- scripts/events/stylus.js | 48 +- scripts/events/welcome.js | 26 +- scripts/filters/post_lazyload.js | 62 +- scripts/filters/random_cover.js | 164 +- scripts/helpers/aside_archives.js | 236 +- scripts/helpers/aside_categories.js | 162 +- scripts/helpers/getArchiveLength.js | 90 +- scripts/helpers/inject_head_js.js | 310 +-- scripts/helpers/page.js | 299 +-- scripts/helpers/related_post.js | 194 +- scripts/helpers/series.js | 44 +- scripts/tag/button.js | 42 +- scripts/tag/chartjs.js | 98 +- scripts/tag/flink.js | 68 +- scripts/tag/gallery.js | 152 +- scripts/tag/hide.js | 102 +- scripts/tag/inlineImg.js | 38 +- scripts/tag/label.js | 28 +- scripts/tag/mermaid.js | 34 +- scripts/tag/note.js | 54 +- scripts/tag/score.js | 44 +- scripts/tag/series.js | 126 +- scripts/tag/tabs.js | 102 +- scripts/tag/timeline.js | 100 +- source/css/_global/function.styl | 560 ++--- source/css/_global/index.styl | 448 ++-- source/css/_highlight/highlight.styl | 560 ++--- source/css/_highlight/highlight/diff.styl | 162 +- source/css/_highlight/highlight/index.styl | 78 +- source/css/_highlight/prismjs/diff.styl | 602 ++--- source/css/_highlight/prismjs/index.styl | 48 +- .../css/_highlight/prismjs/line-number.styl | 84 +- source/css/_highlight/theme.styl | 242 +- source/css/_layout/aside.styl | 848 +++---- source/css/_layout/chat.styl | 16 +- source/css/_layout/comments.styl | 160 +- source/css/_layout/footer.styl | 70 +- source/css/_layout/head.styl | 874 +++---- source/css/_layout/loading.styl | 190 +- source/css/_layout/pagination.styl | 210 +- source/css/_layout/post.styl | 528 ++-- source/css/_layout/relatedposts.styl | 60 +- source/css/_layout/reward.styl | 156 +- source/css/_layout/rightside.styl | 144 +- source/css/_layout/sidebar.styl | 154 +- source/css/_layout/third-party.styl | 372 +-- source/css/_mode/darkmode.styl | 318 +-- source/css/_mode/readmode.styl | 370 +-- source/css/_page/404.styl | 130 +- source/css/_page/archives.styl | 230 +- source/css/_page/categories.styl | 74 +- source/css/_page/common.styl | 120 +- source/css/_page/flink.styl | 172 +- source/css/_page/homepage.styl | 346 +-- source/css/_page/shuoshuo.styl | 156 +- source/css/_page/tags.styl | 54 +- source/css/_search/algolia.styl | 184 +- source/css/_search/index.styl | 110 +- source/css/_search/local-search.styl | 112 +- source/css/_tags/button.styl | 112 +- source/css/_tags/gallery.styl | 436 ++-- source/css/_tags/hexo.styl | 60 +- source/css/_tags/hide.styl | 96 +- source/css/_tags/inlineImg.styl | 10 +- source/css/_tags/label.styl | 22 +- source/css/_tags/note.styl | 248 +- source/css/_tags/series.styl | 8 +- source/css/_tags/tabs.styl | 154 +- source/css/_tags/timeline.styl | 134 +- source/css/_third-party/normalize.min.css | 358 +-- source/css/index.styl | 28 +- source/css/var.styl | 372 +-- source/js/main.js | 1860 +++++++------- source/js/search/algolia.js | 348 +-- source/js/search/local-search.js | 720 +++--- source/js/tw_cn.js | 234 +- source/js/utils.js | 626 ++--- 210 files changed, 16126 insertions(+), 16118 deletions(-) create mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 zcmeH~Jr2S!425mzP>H1@V-^m;4Wg<&0T*E43hX&L&p$$qDprKhvt+--jT7}7np#A3 zem<@ulZcFPQ@L2!n>{z**++&mCkOWA81W14cNZlEfg7;MkzE(HCqgga^y>{tEnwC%0;vJ&^%eQ zLs35+`xjp>T0 -中文 - - -
- - - -# 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/dev?label=dev) -![https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff](https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff) -![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) - -📢 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/) - -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) - -
- ---- - -## 💻 Installation - -### GIT - -> If you are in Mainland China, you can download in [Gitee](https://gitee.com/immyw/hexo-theme-butterfly.git) - -Stable branch [recommend]: - -``` -git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly -``` - -Dev branch: - -``` -git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly -``` - -### NPM - -> It supports Hexo 5.0.0 or later - -In Hexo site root directory - -```powershell -npm i hexo-theme-butterfly -``` - -## ⚙ Configuration - - Set theme in the hexo work folder's root config file `_config.yml`: - -> theme: butterfly - - If you don't have pug & stylus renderer, try this: - -> npm install hexo-renderer-pug hexo-renderer-stylus - -## 🎉 Features - -- [x] Card UI Design -- [x] Rounded Design/Squared Design -- [X] Support sub-menu -- [x] Two-column layout -- [x] Responsive Web Design -- [x] Dark Mode -- [x] Pjax -- [x] Read Mode -- [x] Conversion between Traditional and Simplified Chinese -- [X] TOC catalog is available for both computers and mobile phones -- [X] Built-in Syntax Highlighting Themes (darker/pale night/light/ocean), also support customization -- [X] Code Blocks (Display code language/close or expand Code Blocks/Copy Button/word wrap) -- [X] Disable copy/Add a Copyright Notice to the Copied Text -- [X] Search (Algolia Search/Local Search) -- [x] Mathjax and Katex -- [x] Built-in 404 page -- [x] WordCount -- [x] Related articles -- [x] Displays outdated notice for a post -- [x] Share (Sharejs/Addtoany) -- [X] Comment (Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/artalk) -- [x] Multiple Comment System Support -- [x] Online Chats (Chatra/Tidio/Crisp) -- [x] Web analytics -- [x] Google AdSense -- [x] Webmaster Verification -- [x] Change website colour scheme -- [x] Typewriter Effect: activate_power_mode -- [x] Background effects (Canvas ribbon/canvas_ribbon_piao/canvas_nest) -- [x] Mouse click effects (Fireworks/Heart/Text) -- [x] Preloader/Loading Animation/pace.js -- [x] Busuanzi visitor counter -- [x] Medium Zoom/Fancybox -- [x] Mermaid -- [x] Chart.js -- [x] Justified Gallery -- [x] Lazyload images -- [x] Instantpage/Snackbar notification toast/PWA...... - -## ✨ Contributors - - - - - -## 📷 Screenshots - -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-1.jpg) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-2.jpg) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-3.jpg) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-4.jpg) +
+中文 +
+ +
+ + + +# 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/dev?label=dev) +![https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff](https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff) +![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) + +📢 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/) + +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) + +
+ +--- + +## 💻 Installation + +### GIT + +> If you are in Mainland China, you can download in [Gitee](https://gitee.com/immyw/hexo-theme-butterfly.git) + +Stable branch [recommend]: + +``` +git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +Dev branch: + +``` +git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +### NPM + +> It supports Hexo 5.0.0 or later + +In Hexo site root directory + +```powershell +npm i hexo-theme-butterfly +``` + +## ⚙ Configuration + + Set theme in the hexo work folder's root config file `_config.yml`: + +> theme: butterfly + + If you don't have pug & stylus renderer, try this: + +> npm install hexo-renderer-pug hexo-renderer-stylus + +## 🎉 Features + +- [x] Card UI Design +- [x] Rounded Design/Squared Design +- [X] Support sub-menu +- [x] Two-column layout +- [x] Responsive Web Design +- [x] Dark Mode +- [x] Pjax +- [x] Read Mode +- [x] Conversion between Traditional and Simplified Chinese +- [X] TOC catalog is available for both computers and mobile phones +- [X] Built-in Syntax Highlighting Themes (darker/pale night/light/ocean), also support customization +- [X] Code Blocks (Display code language/close or expand Code Blocks/Copy Button/word wrap) +- [X] Disable copy/Add a Copyright Notice to the Copied Text +- [X] Search (Algolia Search/Local Search) +- [x] Mathjax and Katex +- [x] Built-in 404 page +- [x] WordCount +- [x] Related articles +- [x] Displays outdated notice for a post +- [x] Share (Sharejs/Addtoany) +- [X] Comment (Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/artalk) +- [x] Multiple Comment System Support +- [x] Online Chats (Chatra/Tidio/Crisp) +- [x] Web analytics +- [x] Google AdSense +- [x] Webmaster Verification +- [x] Change website colour scheme +- [x] Typewriter Effect: activate_power_mode +- [x] Background effects (Canvas ribbon/canvas_ribbon_piao/canvas_nest) +- [x] Mouse click effects (Fireworks/Heart/Text) +- [x] Preloader/Loading Animation/pace.js +- [x] Busuanzi visitor counter +- [x] Medium Zoom/Fancybox +- [x] Mermaid +- [x] Chart.js +- [x] Justified Gallery +- [x] Lazyload images +- [x] Instantpage/Snackbar notification toast/PWA...... + +## ✨ Contributors + + + + + +## 📷 Screenshots + +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-1.jpg) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-2.jpg) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-3.jpg) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-4.jpg) diff --git a/README_CN.md b/README_CN.md index 2b0e07d..5a42e0e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -1,117 +1,117 @@ -
- English -
- -
- - - -# 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/dev?label=dev) -![https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff](https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff) -![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) - -📢 預覽: [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://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) - -
- ---- - -## 💻 安裝 - -### Git 安裝 - -> 本倉庫同時上傳到 [Gitee](https://gitee.com/immyw/hexo-theme-butterfly.git),如果你訪問 Github 緩慢,可從 Gitee 中下載。 - -在博客根目錄裡安裝穩定版【推薦】 - -```powershell -git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly -``` - -如果想要安裝比較新的dev分支,可以 - -```powershell -git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly -``` - -### npm 安裝 - -> 此方法只支持Hexo 5.0.0以上版本 - -在博客根目錄裡 - -```powershell -npm i hexo-theme-butterfly -``` - -## ⚙ 應用主題 - -修改hexo配置文件`_config.yml`,把主題改為`Butterfly` - -``` -theme: butterfly -``` - ->如果你沒有pug以及stylus的渲染器,請下載安裝: npm install hexo-renderer-pug hexo-renderer-stylus --save - -## 🎉 特色 - -- [x] 卡片化設計 -- [x] 圓角化設計/直角化設計 -- [X] 支持二級目錄 -- [x] 雙欄設計 -- [x] 響應式主題 -- [x] 夜間模式 -- [x] Pjax -- [x] 文章閲讀模式 -- [x] 簡體和繁體轉換 -- [X] 電腦和手機都可查看TOC目錄 -- [X] 內置多種代碼配色(darker/pale night/light/ocean),可自定義代碼配色 -- [X] 代碼塊顯示代碼語言/關閉或展開代碼塊/代碼複製/代碼自動換行 -- [X] 可關閉文字複製/可開啟內容複製增加版權信息) -- [X] 兩種搜索( Algolia 搜索和本地搜索) -- [x] Mathjax 和 Katex -- [x] 內置404頁面 -- [x] 顯示字數統計 -- [x] 顯示相關文章 -- [x] 過期文章提醒 -- [x] 多種分享系統(Sharejs/Addtoany) -- [X] 多種評論系統(Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/artalk) -- [x] 支持雙評論部署 -- [x] 多種在線聊天(Chatra/Tidio/Crisp) -- [x] 多種分析系統 -- [x] 谷歌廣告/手動廣告位置 -- [x] 各種站長驗證 -- [x] 修改網站配色 -- [x] 打字特效 activate_power_mode -- [x] 多種背景特效(靜止彩帶/動態彩帶/Canvas Nest) -- [x] 多種鼠標點擊特效(煙花/文字/愛心) -- [x] 內置一種 Preloader 加載動畫和 pace.js 加載動畫條 -- [x] 不蒜子訪問統計 -- [x] 兩種大圖模式(Medium Zoom/Fancybox) -- [x] Mermaid 圖表顯示 -- [x] Chart.js 圖表顯示 -- [x] 照片牆 -- [x] 圖片懶加載 -- [x] Instantpage/Snackbar彈窗/PWA...... - -## ✨ 貢獻者 - - - - - -## 📷 截圖 - -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-1.jpg) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-2.jpg) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-3.jpg) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-4.jpg) +
+ English +
+ +
+ + + +# 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/dev?label=dev) +![https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff](https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff) +![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) + +📢 預覽: [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://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) + +
+ +--- + +## 💻 安裝 + +### Git 安裝 + +> 本倉庫同時上傳到 [Gitee](https://gitee.com/immyw/hexo-theme-butterfly.git),如果你訪問 Github 緩慢,可從 Gitee 中下載。 + +在博客根目錄裡安裝穩定版【推薦】 + +```powershell +git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +如果想要安裝比較新的dev分支,可以 + +```powershell +git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +### npm 安裝 + +> 此方法只支持Hexo 5.0.0以上版本 + +在博客根目錄裡 + +```powershell +npm i hexo-theme-butterfly +``` + +## ⚙ 應用主題 + +修改hexo配置文件`_config.yml`,把主題改為`Butterfly` + +``` +theme: butterfly +``` + +>如果你沒有pug以及stylus的渲染器,請下載安裝: npm install hexo-renderer-pug hexo-renderer-stylus --save + +## 🎉 特色 + +- [x] 卡片化設計 +- [x] 圓角化設計/直角化設計 +- [X] 支持二級目錄 +- [x] 雙欄設計 +- [x] 響應式主題 +- [x] 夜間模式 +- [x] Pjax +- [x] 文章閲讀模式 +- [x] 簡體和繁體轉換 +- [X] 電腦和手機都可查看TOC目錄 +- [X] 內置多種代碼配色(darker/pale night/light/ocean),可自定義代碼配色 +- [X] 代碼塊顯示代碼語言/關閉或展開代碼塊/代碼複製/代碼自動換行 +- [X] 可關閉文字複製/可開啟內容複製增加版權信息) +- [X] 兩種搜索( Algolia 搜索和本地搜索) +- [x] Mathjax 和 Katex +- [x] 內置404頁面 +- [x] 顯示字數統計 +- [x] 顯示相關文章 +- [x] 過期文章提醒 +- [x] 多種分享系統(Sharejs/Addtoany) +- [X] 多種評論系統(Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/artalk) +- [x] 支持雙評論部署 +- [x] 多種在線聊天(Chatra/Tidio/Crisp) +- [x] 多種分析系統 +- [x] 谷歌廣告/手動廣告位置 +- [x] 各種站長驗證 +- [x] 修改網站配色 +- [x] 打字特效 activate_power_mode +- [x] 多種背景特效(靜止彩帶/動態彩帶/Canvas Nest) +- [x] 多種鼠標點擊特效(煙花/文字/愛心) +- [x] 內置一種 Preloader 加載動畫和 pace.js 加載動畫條 +- [x] 不蒜子訪問統計 +- [x] 兩種大圖模式(Medium Zoom/Fancybox) +- [x] Mermaid 圖表顯示 +- [x] Chart.js 圖表顯示 +- [x] 照片牆 +- [x] 圖片懶加載 +- [x] Instantpage/Snackbar彈窗/PWA...... + +## ✨ 貢獻者 + + + + + +## 📷 截圖 + +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-1.jpg) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-2.jpg) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-3.jpg) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/butterfly-readme-screenshots-4.jpg) diff --git a/_config.yml b/_config.yml index 0ec8370..8316d81 100644 --- a/_config.yml +++ b/_config.yml @@ -1,1106 +1,1106 @@ -# -------------------------------------- -# Hexo Butterfly Theme Configuration -# If you have any questions, please refer to the documentation -# Chinese: https://butterfly.js.org/ -# English: https://butterfly.js.org/en/ -# -------------------------------------- - -# -------------------------------------- -# Navigation Settings -# -------------------------------------- - -nav: - # Navigation bar logo image - logo: - display_title: true - # Whether to fix navigation bar - fixed: false - -menu: - # Home: / || fas fa-home - # List||fas fa-list: - # Music: /music/ || fas fa-music - # Movie: /movies/ || fas fa-video - -# -------------------------------------- -# Code Blocks Settings -# -------------------------------------- - -code_blocks: - # Code block theme: darker / pale night / light / ocean / false - theme: light - macStyle: false - # Code block height limit (unit: px) - height_limit: false - word_wrap: false - - # Toolbar - copy: true - language: true - # true: shrink the code blocks | false: expand the code blocks | none: expand code blocks and hide the button - shrink: false - fullpage: false - -# Social media links -# Formal: -# icon: link || the description || color -social: - # fab fa-github: https://github.com/xxxxx || Github || '#24292e' - # fas fa-envelope: mailto:xxxxxx@gmail.com || Email || '#4a7dbe' - -# -------------------------------------- -# Image Settings -# -------------------------------------- - -favicon: /img/favicon.png - -avatar: - img: /img/butterfly-icon.png - effect: false - -# Disable all banner images -disable_top_img: false - -# If the banner of page not setting, it will show the default_top_img -default_top_img: - -# The banner image of index page -index_img: - -# The banner image of archive page -archive_img: - -# Note: tag page, not tags page -tag_img: - -# The banner image of tag page, you can set the banner image for each tag -# Format: -# - tag name: xxxxx -tag_per_img: - -# Note: category page, not categories page -category_img: - -# The banner image of category page, you can set the banner image for each category -# Format: -# - category name: xxxxx -category_per_img: - -# The background image of footer -footer_img: false - -# Website Background -# Can set it to color or image url -background: - -cover: - # Disable the cover or not - index_enable: true - aside_enable: true - archives_enable: true - # When cover is not set, the default cover is displayed - default_cover: - # - xxx.jpg - -# Replace Broken Images -error_img: - flink: /img/friend_404.gif - post_page: /img/404.jpg - -# A simple 404 page -error_404: - enable: false - subtitle: 'Page Not Found' - background: /img/error-page.png - -post_meta: - # Home Page - page: - # Choose: created / updated / both - date_type: created - # Choose: date / relative - date_format: date - categories: true - tags: false - label: true - post: - # Choose: left / center - position: left - # Choose: created / updated / both - date_type: both - # Choose: date / relative - date_format: date - categories: true - tags: true - label: true - -# -------------------------------------- -# Index page settings -# -------------------------------------- - -# The top_img settings of home page -# default: top img - full screen, site info - middle -# The position of site info, eg: 300px/300em/300rem/10% -index_site_info_top: -# The height of top_img, eg: 300px/300em/300rem -index_top_img_height: - -# The subtitle on homepage -subtitle: - enable: false - # Typewriter Effect - effect: true - # Customize typed.js - # https://github.com/mattboldt/typed.js/#customization - typed_option: - # Source - Call the third-party service API (Chinese only) - # It will show the source first, then show the content of sub - # Choose: false/1/2/3 - # false - disable the function - # 1 - hitokoto.cn - # 2 - yijuzhan.com - # 3 - jinrishici.com - source: false - # If you close the typewriter effect, the subtitle will only show the first line of sub - sub: - -# Article layout on the homepage -# 1: Cover on the left, info on the right -# 2: Cover on the right, info on the left -# 3: Cover and info alternate between left and right -# 4: Cover on top, info on the bottom -# 5: Info displayed on the cover -# 6: Masonry layout - Cover on top, info on the bottom -# 7: Masonry layout - Info displayed on the cover -index_layout: 3 - -# Display the article introduction on homepage -# 1: description -# 2: both (if the description exists, it will show description, or show the auto_excerpt) -# 3: auto_excerpt (default) -# false: do not show the article introduction -index_post_content: - method: 3 - # If you set method to 2 or 3, the length need to config - length: 500 - -# -------------------------------------- -# Post Settings -# -------------------------------------- - -toc: - post: true - page: false - number: true - expand: false - # Only for post - style_simple: false - scroll_percent: true - -post_copyright: - enable: true - decode: false - author_href: - license: CC BY-NC-SA 4.0 - license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/ - -# Sponsor/reward -reward: - enable: false - text: - QR_code: - # - img: /img/wechat.jpg - # link: - # text: wechat - # - img: /img/alipay.jpg - # link: - # text: alipay - -# Post edit -# Easily browse and edit blog source code online. -post_edit: - enable: false - # url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/ - # For example: https://github.com/jerryc127/butterfly.js.org/edit/main/source/ - url: - -# Related Articles -related_post: - enable: true - # Number of posts displayed - limit: 6 - # Choose: created / updated - date_type: created - -# Choose: 1 / 2 / false -# 1: The 'next post' will link to old post -# 2: The 'next post' will link to new post -# false: disable pagination -post_pagination: 1 - -# Displays outdated notice for a post -noticeOutdate: - enable: false - # Style: simple / flat - style: flat - # When will it be shown - limit_day: 365 - # Position: top / bottom - position: top - message_prev: It has been - message_next: days since the last update, the content of the article may be outdated. - -# -------------------------------------- -# Footer Settings -# -------------------------------------- -footer: - owner: - enable: true - since: 2019 - custom_text: - # Copyright of theme and framework - copyright: true - -# -------------------------------------- -# Aside Settings -# -------------------------------------- - -aside: - enable: true - hide: false - # Show the button to hide the aside in bottom right button - button: true - mobile: true - # Position: left / right - position: right - display: - archive: true - tag: true - category: true - card_author: - enable: true - description: - button: - enable: true - icon: fab fa-github - text: Follow Me - link: https://github.com/xxxxxx - card_announcement: - enable: true - content: This is my Blog - card_recent_post: - enable: true - # If set 0 will show all - limit: 5 - # Sort: date / updated - sort: date - sort_order: - card_newest_comments: - enable: false - sort_order: - limit: 6 - # Unit: mins, save data to localStorage - storage: 10 - avatar: true - card_categories: - enable: true - # If set 0 will show all - limit: 8 - # Choose: none / true / false - expand: none - sort_order: - card_tags: - enable: true - # If set 0 will show all - limit: 40 - color: false - # Order of tags, random/name/length - orderby: random - # Sort of order. 1, asc for ascending; -1, desc for descending - order: 1 - sort_order: - card_archives: - enable: true - # Type: monthly / yearly - type: monthly - # Eg: YYYY年MM月 - format: MMMM YYYY - # Sort of order. 1, asc for ascending; -1, desc for descending - order: -1 - # If set 0 will show all - limit: 8 - sort_order: - card_post_series: - enable: true - # The title shows the series name - series_title: false - # Order by title or date - orderBy: 'date' - # Sort of order. 1, asc for ascending; -1, desc for descending - order: -1 - card_webinfo: - enable: true - post_count: true - last_push_date: true - sort_order: - # Time difference between publish date and now - # Formal: Month/Day/Year Time or Year/Month/Day Time - # Leave it empty if you don't enable this feature - runtime_date: - -# -------------------------------------- -# Bottom right button -# -------------------------------------- - -# The distance between the bottom right button and the bottom (default unit: px) -rightside_bottom: - -# Conversion between Traditional and Simplified Chinese -translate: - enable: false - # The text of a button - default: 繁 - # the language of website (1 - Traditional Chinese/ 2 - Simplified Chinese) - defaultEncoding: 2 - # Time delay - translateDelay: 0 - # The text of the button when the language is Simplified Chinese - msgToTraditionalChinese: '繁' - # The text of the button when the language is Traditional Chinese - msgToSimplifiedChinese: '簡' - -# Read Mode -readmode: true - -# Dark Mode -darkmode: - enable: true - # Toggle Button to switch dark/light mode - button: true - # Switch dark/light mode automatically - # autoChangeMode: 1 Following System Settings, if the system doesn't support dark mode, it will switch dark mode between 6 pm to 6 am - # autoChangeMode: 2 Switch dark mode between 6 pm to 6 am - # autoChangeMode: false - autoChangeMode: false - # Set the light mode time. The value is between 0 and 24. If not set, the default value is 6 and 18 - start: - end: - -# Show scroll percent in scroll-to-top button -rightside_scroll_percent: false - -# Don't modify the following settings unless you know how they work -# Choose: readmode,translate,darkmode,hideAside,toc,chat,comment -# Don't repeat the same value -rightside_item_order: - enable: false - # Default: readmode,translate,darkmode,hideAside - hide: - # Default: toc,chat,comment - show: - -# -------------------------------------- -# Global Settings -# -------------------------------------- - -anchor: - # When you scroll, the URL will update according to header id. - auto_update: false - # Click the headline to scroll and update the anchor - click_to_scroll: false - -photofigcaption: false - -copy: - enable: true - # Add the copyright information after copied content - copyright: - enable: false - limit_count: 150 - -# Need to install the hexo-wordcount plugin -wordcount: - enable: false - # Display the word count of the article in post meta - post_wordcount: true - # Display the time to read the article in post meta - min2read: true - # Display the total word count of the website in aside's webinfo - total_wordcount: true - -# Busuanzi count for PV / UV in site -busuanzi: - site_uv: true - site_pv: true - page_pv: true - -# -------------------------------------- -# Math -# -------------------------------------- - -# About the per_page -# if you set it to true, it will load mathjax/katex script in each page -# if you set it to false, it will load mathjax/katex script according to your setting (add the 'mathjax: true' or 'katex: true' in page's front-matter) -math: - # Choose: mathjax, katex - # Leave it empty if you don't need math - use: - per_page: true - hide_scrollbar: false - - mathjax: - # Enable the contextual menu - enableMenu: true - # Choose: all / ams / none, This controls whether equations are numbered and how - tags: none - - katex: - # Enable the copy KaTeX formula - copy_tex: false - -# -------------------------------------- -# Search -# -------------------------------------- - -search: - # Choose: algolia_search / local_search / docsearch - # leave it empty if you don't need search - use: - placeholder: - - # Algolia Search - algolia_search: - # Number of search results per page - hitsPerPage: 6 - - # Local Search - local_search: - # Preload the search data when the page loads. - preload: false - # Show top n results per article, show all results by setting to -1 - top_n_per_article: 1 - # Unescape html strings to the readable one. - unescape: false - CDN: - - # Docsearch - # https://docsearch.algolia.com/ - docsearch: - appId: - apiKey: - indexName: - option: - -# -------------------------------------- -# Share System -# -------------------------------------- - -share: - # Choose: sharejs / addtoany - # Leave it empty if you don't need share - use: sharejs - - # Share.js - # https://github.com/overtrue/share.js - sharejs: - sites: facebook,twitter,wechat,weibo,qq - - # AddToAny - # https://www.addtoany.com/ - addtoany: - item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link - -# -------------------------------------- -# Comments System -# -------------------------------------- - -comments: - # Up to two comments system, the first will be shown as default - # Leave it empty if you don't need comments - # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/Artalk - # Format of two comments system : Disqus,Waline - use: - # Display the comment name next to the button - text: true - # Lazyload: The comment system will be load when comment element enters the browser's viewport. - # If you set it to true, the comment count will be invalid - lazyload: false - # Display comment count in post's top_img - count: false - # Display comment count in Home Page - card_post_count: false - -# Disqus -# https://disqus.com/ -disqus: - shortname: - # For newest comments widget - apikey: - -# Alternative Disqus - Render comments with Disqus API -# https://github.com/SukkaW/DisqusJS -disqusjs: - shortname: - apikey: - option: - -# Livere -# https://www.livere.com/ -livere: - uid: - -# Gitalk -# https://github.com/gitalk/gitalk -gitalk: - client_id: - client_secret: - repo: - owner: - admin: - option: - -# Valine -# https://valine.js.org -valine: - appId: - appKey: - avatar: monsterid - # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in) - serverURLs: - bg: - # Use Valine visitor count as the page view count - visitor: false - option: - -# Waline - A simple comment system with backend support fork from Valine -# https://waline.js.org/ -waline: - serverURL: - bg: - # Use Waline pageview count as the page view count - pageview: false - option: - -# Utterances -# https://utteranc.es/ -utterances: - repo: - # Issue Mapping: pathname/url/title/og:title - issue_term: pathname - # Theme: github-light/github-dark/github-dark-orange/icy-dark/dark-blue/photon-dark - light_theme: github-light - dark_theme: photon-dark - js: - option: - -# Facebook Comments Plugin -# https://developers.facebook.com/docs/plugins/comments/ -facebook_comments: - app_id: - # optional - user_id: - pageSize: 10 - # Choose: social / time / reverse_time - order_by: social - lang: en_US - -# Twikoo -# https://github.com/imaegoo/twikoo -twikoo: - envId: - region: - # Use Twikoo visitor count as the page view count - visitor: false - option: - -# Giscus -# https://giscus.app/ -giscus: - repo: - repo_id: - category_id: - light_theme: light - dark_theme: dark - js: - option: - -# Remark42 -# https://remark42.com/docs/configuration/frontend/ -remark42: - host: - siteId: - option: - -# Artalk -# https://artalk.js.org/guide/frontend/config.html -artalk: - server: - site: - # Use Artalk visitor count as the page view count - visitor: false - option: - -# -------------------------------------- -# Chat Services -# -------------------------------------- - -chat: - # Choose: chatra/tidio/crisp - # Leave it empty if you don't need chat - use: - # Chat Button [recommend] - # It will create a button in the bottom right corner of website, and hide the origin button - rightside_button: false - # The origin chat button is displayed when scrolling up, and the button is hidden when scrolling down - button_hide_show: false - -# https://chatra.io/ -chatra: - id: - -# https://www.tidio.com/ -tidio: - public_key: - -# https://crisp.chat/en/ -crisp: - website_id: - -# -------------------------------------- -# Analysis -# -------------------------------------- - -# https://tongji.baidu.com/web/welcome/login -baidu_analytics: - -# https://analytics.google.com/analytics/web/ -google_analytics: - -# https://www.cloudflare.com/zh-tw/web-analytics/ -cloudflare_analytics: - -# https://clarity.microsoft.com/ -microsoft_clarity: - -# https://umami.is/ -umami_analytics: - enable: false - # For self-hosted setups, configure the hostname of the Umami instance - serverURL: - website_id: - option: - UV_PV: - site_uv: false - site_pv: false - page_pv: false - # Umami Cloud (API key) / self-hosted Umami (token) - token: - -# -------------------------------------- -# Advertisement -# -------------------------------------- - -# Google Adsense -google_adsense: - enable: false - auto_ads: true - js: https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js - client: - enable_page_level_ads: true - -# Insert ads manually -# Leave it empty if you don't need ads -ad: - # Insert ads in the index (every three posts) - index: - # Insert ads in aside - aside: - # Insert ads in the post (before pagination) - post: - -# -------------------------------------- -# Verification -# -------------------------------------- - -site_verification: - # - name: google-site-verification - # content: xxxxxx - # - name: baidu-site-verification - # content: xxxxxxx - -# -------------------------------------- -# Beautify / Effect -# -------------------------------------- - -# Theme color for customize -# Notice: color value must in double quotes like "#000" or may cause error! - -# theme_color: -# enable: true -# main: "#49B1F5" -# paginator: "#00c4b6" -# button_hover: "#FF7242" -# text_selection: "#00c4b6" -# link_color: "#99a9bf" -# meta_color: "#858585" -# hr_color: "#A4D8FA" -# code_foreground: "#F47466" -# code_background: "rgba(27, 31, 35, .05)" -# toc_color: "#00c4b6" -# blockquote_padding_color: "#49b1f5" -# blockquote_background_color: "#49b1f5" -# scrollbar_color: "#49b1f5" -# meta_theme_color_light: "ffffff" -# meta_theme_color_dark: "#0d0d0d" - -# The user interface setting of category and tag page -# Choose: index - same as Homepage UI / default - same as archives UI -# leave it empty or index -category_ui: -tag_ui: - -# Rounded corners for UI elements -rounded_corners_ui: true - -# Stretches the lines so that each line has equal width -text_align_justify: false - -# Add a mask to the header and footer -mask: - header: true - footer: true - -# Loading Animation -preloader: - enable: false - # source - # 1. fullpage-loading - # 2. pace (progress bar) - source: 1 - # pace theme (see https://codebyzach.github.io/pace/) - pace_css_url: - -# Page Transition -enter_transitions: true - -# Default display mode - light (default) / dark -display_mode: light - -# Configuration for beautifying the content of the article -beautify: - enable: false - # Specify the field to beautify (site or post) - field: post - # Specify the icon to be used as a prefix for the title, such as '\f0c1' - title_prefix_icon: - # Specify the color of the title prefix icon, such as '#F47466' - title_prefix_icon_color: - -# Global font settings -# Don't modify the following settings unless you know how they work -font: - global_font_size: - code_font_size: - font_family: - code_font_family: - -# Font settings for the site title and site subtitle -blog_title_font: - font_link: - font_family: - -# The setting of divider icon -hr_icon: - enable: true - # The unicode value of Font Awesome icon, such as '\3423' - icon: - icon_top: - -# Typewriter Effect -# https://github.com/disjukr/activate-power-mode -activate_power_mode: - enable: false - colorful: true - shake: true - mobile: false - -# Background effects -# -------------------------------------- - -# canvas_ribbon -# See: https://github.com/hustcc/ribbon.js -canvas_ribbon: - enable: false - # The size of ribbon - size: 150 - # The opacity of ribbon (0 ~ 1) - alpha: 0.6 - zIndex: -1 - click_to_change: false - mobile: false - -# Fluttering Ribbon -canvas_fluttering_ribbon: - enable: false - mobile: false - -# canvas_nest -# https://github.com/hustcc/canvas-nest.js -canvas_nest: - enable: false - # Color of lines, default: '0,0,0'; RGB values: (R,G,B).(note: use ',' to separate.) - color: '0,0,255' - # The opacity of line (0~1) - opacity: 0.7 - # The z-index property of the background - zIndex: -1 - # The number of lines - count: 99 - mobile: false - -# Mouse click effects: fireworks -fireworks: - enable: false - zIndex: 9999 - mobile: false - -# Mouse click effects: Heart symbol -click_heart: - enable: false - mobile: false - -# Mouse click effects: words -clickShowText: - enable: false - text: - # - I - # - LOVE - # - YOU - fontSize: 15px - random: false - mobile: false - -# -------------------------------------- -# Lightbox Settings -# -------------------------------------- - -# Choose: fancybox / medium_zoom -# https://github.com/francoischalifour/medium-zoom -# https://fancyapps.com/fancybox/ -# Leave it empty if you don't need lightbox -lightbox: - -# -------------------------------------- -# Tag Plugins settings -# -------------------------------------- - -# Series -series: - enable: false - # Order by title or date - orderBy: 'title' - # Sort of order. 1, asc for ascending; -1, desc for descending - order: 1 - number: true - -# ABCJS - The ABC Music Notation Plugin -# https://github.com/paulrosen/abcjs -abcjs: - enable: false - per_page: true - -# Mermaid -# https://github.com/mermaid-js/mermaid -mermaid: - enable: false - # Write Mermaid diagrams using code blocks - code_write: false - # built-in themes: default / forest / dark / neutral - theme: - light: default - dark: dark - -# chartjs -# see https://www.chartjs.org/docs/latest/ -chartjs: - enable: false - # Do not modify unless you understand how they work. - # The default settings are only used when the MD syntax is not specified. - # General font color for the chart - fontColor: - light: 'rgba(0, 0, 0, 0.8)' - dark: 'rgba(255, 255, 255, 0.8)' - # General border color for the chart - borderColor: - light: 'rgba(0, 0, 0, 0.1)' - dark: 'rgba(255, 255, 255, 0.2)' - # Background color for scale labels on radar and polar area charts - scale_ticks_backdropColor: - light: 'transparent' - dark: 'transparent' - -# Note - Bootstrap Callout -note: - # Note tag style values: - # - simple bs-callout old alert style. Default. - # - modern bs-callout new (v2-v3) alert style. - # - flat flat callout style with background, like on Mozilla or StackOverflow. - # - disabled disable all CSS styles import of note tag. - style: flat - icons: true - border_radius: 3 - # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6). - # Offset also applied to label tag variables. This option can work with disabled note tag. - light_bg_offset: 0 - -# -------------------------------------- -# Other Settings -# -------------------------------------- - -# https://github.com/MoOx/pjax -pjax: - enable: false - # Exclude the specified pages from pjax, such as '/music/' - exclude: - # - /xxxxxx/ - -# Inject the css and script (aplayer/meting) -aplayerInject: - enable: false - per_page: true - -# Snackbar - Toast Notification -# https://github.com/polonel/SnackBar -# position: top-left / top-center / top-right / bottom-left / bottom-center / bottom-right -snackbar: - enable: false - position: bottom-left - # The background color of Toast Notification in light mode and dark mode - bg_light: '#49b1f5' - bg_dark: '#1f1f1f' - -# Instant.page -# https://instant.page/ -instantpage: false - -# Lazyload -# https://github.com/verlok/vanilla-lazyload -lazyload: - enable: false - # Specify the field to use lazyload (site or post) - field: site - placeholder: - blur: false - -# PWA -# See https://github.com/JLHwung/hexo-offline -# --------------- -pwa: - enable: false - manifest: - apple_touch_icon: - favicon_32_32: - favicon_16_16: - mask_icon: - -# Open graph meta tags -# https://hexo.io/docs/helpers#open-graph -Open_Graph_meta: - enable: true - option: - # twitter_card: - # twitter_image: - # twitter_id: - # twitter_site: - # google_plus: - # fb_admins: - # fb_app_id: - -# Structured Data -# https://developers.google.com/search/docs/guides/intro-structured-data -structured_data: true - -# Add the vendor prefixes to ensure compatibility -css_prefix: true - -# Inject -# Insert the code to head (before '' tag) and the bottom (before '' tag) -inject: - head: - # - - bottom: - # - - -# CDN Settings -# Don't modify the following settings unless you know how they work -CDN: - # The CDN provider for internal and third-party scripts - # Options for both: local/jsdelivr/unpkg/cdnjs/custom - # Note: Dev version can only use 'local' for internal scripts - # Note: When setting third-party scripts to 'local', you need to install hexo-butterfly-extjs - internal_provider: local - third_party_provider: jsdelivr - - # Add version number to url, true or false - version: false - - # Custom format - # For example: https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file} - custom_format: - - option: - # abcjs_basic_js: - # activate_power_mode: - # algolia_js: - # algolia_search: - # aplayer_css: - # aplayer_js: - # artalk_css: - # artalk_js: - # blueimp_md5: - # busuanzi: - # canvas_fluttering_ribbon: - # canvas_nest: - # canvas_ribbon: - # chartjs: - # click_heart: - # clickShowText: - # disqusjs: - # disqusjs_css: - # docsearch_css: - # docsearch_js: - # egjs_infinitegrid: - # fancybox: - # fancybox_css: - # fireworks: - # fontawesome: - # gitalk: - # gitalk_css: - # giscus: - # instantpage: - # instantsearch: - # katex: - # katex_copytex: - # lazyload: - # local_search: - # main: - # main_css: - # mathjax: - # medium_zoom: - # mermaid: - # meting_js: - # prismjs_autoloader: - # prismjs_js: - # prismjs_lineNumber_js: - # pjax: - # sharejs: - # sharejs_css: - # snackbar: - # snackbar_css: - # translate: - # twikoo: - # typed: - # utils: - # valine: - # waline_css: - # waline_js: +# -------------------------------------- +# Hexo Butterfly Theme Configuration +# If you have any questions, please refer to the documentation +# Chinese: https://butterfly.js.org/ +# English: https://butterfly.js.org/en/ +# -------------------------------------- + +# -------------------------------------- +# Navigation Settings +# -------------------------------------- + +nav: + # Navigation bar logo image + logo: + display_title: true + # Whether to fix navigation bar + fixed: false + +menu: + # Home: / || fas fa-home + # List||fas fa-list: + # Music: /music/ || fas fa-music + # Movie: /movies/ || fas fa-video + +# -------------------------------------- +# Code Blocks Settings +# -------------------------------------- + +code_blocks: + # Code block theme: darker / pale night / light / ocean / false + theme: light + macStyle: false + # Code block height limit (unit: px) + height_limit: false + word_wrap: false + + # Toolbar + copy: true + language: true + # true: shrink the code blocks | false: expand the code blocks | none: expand code blocks and hide the button + shrink: false + fullpage: false + +# Social media links +# Formal: +# icon: link || the description || color +social: + # fab fa-github: https://github.com/xxxxx || Github || '#24292e' + # fas fa-envelope: mailto:xxxxxx@gmail.com || Email || '#4a7dbe' + +# -------------------------------------- +# Image Settings +# -------------------------------------- + +favicon: /img/favicon.png + +avatar: + img: /img/butterfly-icon.png + effect: false + +# Disable all banner images +disable_top_img: false + +# If the banner of page not setting, it will show the default_top_img +default_top_img: + +# The banner image of index page +index_img: + +# The banner image of archive page +archive_img: + +# Note: tag page, not tags page +tag_img: + +# The banner image of tag page, you can set the banner image for each tag +# Format: +# - tag name: xxxxx +tag_per_img: + +# Note: category page, not categories page +category_img: + +# The banner image of category page, you can set the banner image for each category +# Format: +# - category name: xxxxx +category_per_img: + +# The background image of footer +footer_img: false + +# Website Background +# Can set it to color or image url +background: + +cover: + # Disable the cover or not + index_enable: true + aside_enable: true + archives_enable: true + # When cover is not set, the default cover is displayed + default_cover: + # - xxx.jpg + +# Replace Broken Images +error_img: + flink: /img/friend_404.gif + post_page: /img/404.jpg + +# A simple 404 page +error_404: + enable: false + subtitle: 'Page Not Found' + background: /img/error-page.png + +post_meta: + # Home Page + page: + # Choose: created / updated / both + date_type: created + # Choose: date / relative + date_format: date + categories: true + tags: false + label: true + post: + # Choose: left / center + position: left + # Choose: created / updated / both + date_type: both + # Choose: date / relative + date_format: date + categories: true + tags: true + label: true + +# -------------------------------------- +# Index page settings +# -------------------------------------- + +# The top_img settings of home page +# default: top img - full screen, site info - middle +# The position of site info, eg: 300px/300em/300rem/10% +index_site_info_top: +# The height of top_img, eg: 300px/300em/300rem +index_top_img_height: + +# The subtitle on homepage +subtitle: + enable: false + # Typewriter Effect + effect: true + # Customize typed.js + # https://github.com/mattboldt/typed.js/#customization + typed_option: + # Source - Call the third-party service API (Chinese only) + # It will show the source first, then show the content of sub + # Choose: false/1/2/3 + # false - disable the function + # 1 - hitokoto.cn + # 2 - yijuzhan.com + # 3 - jinrishici.com + source: false + # If you close the typewriter effect, the subtitle will only show the first line of sub + sub: + +# Article layout on the homepage +# 1: Cover on the left, info on the right +# 2: Cover on the right, info on the left +# 3: Cover and info alternate between left and right +# 4: Cover on top, info on the bottom +# 5: Info displayed on the cover +# 6: Masonry layout - Cover on top, info on the bottom +# 7: Masonry layout - Info displayed on the cover +index_layout: 3 + +# Display the article introduction on homepage +# 1: description +# 2: both (if the description exists, it will show description, or show the auto_excerpt) +# 3: auto_excerpt (default) +# false: do not show the article introduction +index_post_content: + method: 3 + # If you set method to 2 or 3, the length need to config + length: 500 + +# -------------------------------------- +# Post Settings +# -------------------------------------- + +toc: + post: true + page: false + number: true + expand: false + # Only for post + style_simple: false + scroll_percent: true + +post_copyright: + enable: true + decode: false + author_href: + license: CC BY-NC-SA 4.0 + license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/ + +# Sponsor/reward +reward: + enable: false + text: + QR_code: + # - img: /img/wechat.jpg + # link: + # text: wechat + # - img: /img/alipay.jpg + # link: + # text: alipay + +# Post edit +# Easily browse and edit blog source code online. +post_edit: + enable: false + # url: https://github.com/user-name/repo-name/edit/branch-name/subdirectory-name/ + # For example: https://github.com/jerryc127/butterfly.js.org/edit/main/source/ + url: + +# Related Articles +related_post: + enable: true + # Number of posts displayed + limit: 6 + # Choose: created / updated + date_type: created + +# Choose: 1 / 2 / false +# 1: The 'next post' will link to old post +# 2: The 'next post' will link to new post +# false: disable pagination +post_pagination: 1 + +# Displays outdated notice for a post +noticeOutdate: + enable: false + # Style: simple / flat + style: flat + # When will it be shown + limit_day: 365 + # Position: top / bottom + position: top + message_prev: It has been + message_next: days since the last update, the content of the article may be outdated. + +# -------------------------------------- +# Footer Settings +# -------------------------------------- +footer: + owner: + enable: true + since: 2019 + custom_text: + # Copyright of theme and framework + copyright: true + +# -------------------------------------- +# Aside Settings +# -------------------------------------- + +aside: + enable: true + hide: false + # Show the button to hide the aside in bottom right button + button: true + mobile: true + # Position: left / right + position: right + display: + archive: true + tag: true + category: true + card_author: + enable: true + description: + button: + enable: true + icon: fab fa-github + text: Follow Me + link: https://github.com/xxxxxx + card_announcement: + enable: true + content: This is my Blog + card_recent_post: + enable: true + # If set 0 will show all + limit: 5 + # Sort: date / updated + sort: date + sort_order: + card_newest_comments: + enable: false + sort_order: + limit: 6 + # Unit: mins, save data to localStorage + storage: 10 + avatar: true + card_categories: + enable: true + # If set 0 will show all + limit: 8 + # Choose: none / true / false + expand: none + sort_order: + card_tags: + enable: true + # If set 0 will show all + limit: 40 + color: false + # Order of tags, random/name/length + orderby: random + # Sort of order. 1, asc for ascending; -1, desc for descending + order: 1 + sort_order: + card_archives: + enable: true + # Type: monthly / yearly + type: monthly + # Eg: YYYY年MM月 + format: MMMM YYYY + # Sort of order. 1, asc for ascending; -1, desc for descending + order: -1 + # If set 0 will show all + limit: 8 + sort_order: + card_post_series: + enable: true + # The title shows the series name + series_title: false + # Order by title or date + orderBy: 'date' + # Sort of order. 1, asc for ascending; -1, desc for descending + order: -1 + card_webinfo: + enable: true + post_count: true + last_push_date: true + sort_order: + # Time difference between publish date and now + # Formal: Month/Day/Year Time or Year/Month/Day Time + # Leave it empty if you don't enable this feature + runtime_date: + +# -------------------------------------- +# Bottom right button +# -------------------------------------- + +# The distance between the bottom right button and the bottom (default unit: px) +rightside_bottom: + +# Conversion between Traditional and Simplified Chinese +translate: + enable: false + # The text of a button + default: 繁 + # the language of website (1 - Traditional Chinese/ 2 - Simplified Chinese) + defaultEncoding: 2 + # Time delay + translateDelay: 0 + # The text of the button when the language is Simplified Chinese + msgToTraditionalChinese: '繁' + # The text of the button when the language is Traditional Chinese + msgToSimplifiedChinese: '簡' + +# Read Mode +readmode: true + +# Dark Mode +darkmode: + enable: true + # Toggle Button to switch dark/light mode + button: true + # Switch dark/light mode automatically + # autoChangeMode: 1 Following System Settings, if the system doesn't support dark mode, it will switch dark mode between 6 pm to 6 am + # autoChangeMode: 2 Switch dark mode between 6 pm to 6 am + # autoChangeMode: false + autoChangeMode: false + # Set the light mode time. The value is between 0 and 24. If not set, the default value is 6 and 18 + start: + end: + +# Show scroll percent in scroll-to-top button +rightside_scroll_percent: false + +# Don't modify the following settings unless you know how they work +# Choose: readmode,translate,darkmode,hideAside,toc,chat,comment +# Don't repeat the same value +rightside_item_order: + enable: false + # Default: readmode,translate,darkmode,hideAside + hide: + # Default: toc,chat,comment + show: + +# -------------------------------------- +# Global Settings +# -------------------------------------- + +anchor: + # When you scroll, the URL will update according to header id. + auto_update: false + # Click the headline to scroll and update the anchor + click_to_scroll: false + +photofigcaption: false + +copy: + enable: true + # Add the copyright information after copied content + copyright: + enable: false + limit_count: 150 + +# Need to install the hexo-wordcount plugin +wordcount: + enable: false + # Display the word count of the article in post meta + post_wordcount: true + # Display the time to read the article in post meta + min2read: true + # Display the total word count of the website in aside's webinfo + total_wordcount: true + +# Busuanzi count for PV / UV in site +busuanzi: + site_uv: true + site_pv: true + page_pv: true + +# -------------------------------------- +# Math +# -------------------------------------- + +# About the per_page +# if you set it to true, it will load mathjax/katex script in each page +# if you set it to false, it will load mathjax/katex script according to your setting (add the 'mathjax: true' or 'katex: true' in page's front-matter) +math: + # Choose: mathjax, katex + # Leave it empty if you don't need math + use: + per_page: true + hide_scrollbar: false + + mathjax: + # Enable the contextual menu + enableMenu: true + # Choose: all / ams / none, This controls whether equations are numbered and how + tags: none + + katex: + # Enable the copy KaTeX formula + copy_tex: false + +# -------------------------------------- +# Search +# -------------------------------------- + +search: + # Choose: algolia_search / local_search / docsearch + # leave it empty if you don't need search + use: + placeholder: + + # Algolia Search + algolia_search: + # Number of search results per page + hitsPerPage: 6 + + # Local Search + local_search: + # Preload the search data when the page loads. + preload: false + # Show top n results per article, show all results by setting to -1 + top_n_per_article: 1 + # Unescape html strings to the readable one. + unescape: false + CDN: + + # Docsearch + # https://docsearch.algolia.com/ + docsearch: + appId: + apiKey: + indexName: + option: + +# -------------------------------------- +# Share System +# -------------------------------------- + +share: + # Choose: sharejs / addtoany + # Leave it empty if you don't need share + use: sharejs + + # Share.js + # https://github.com/overtrue/share.js + sharejs: + sites: facebook,twitter,wechat,weibo,qq + + # AddToAny + # https://www.addtoany.com/ + addtoany: + item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link + +# -------------------------------------- +# Comments System +# -------------------------------------- + +comments: + # Up to two comments system, the first will be shown as default + # Leave it empty if you don't need comments + # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/Artalk + # Format of two comments system : Disqus,Waline + use: + # Display the comment name next to the button + text: true + # Lazyload: The comment system will be load when comment element enters the browser's viewport. + # If you set it to true, the comment count will be invalid + lazyload: false + # Display comment count in post's top_img + count: false + # Display comment count in Home Page + card_post_count: false + +# Disqus +# https://disqus.com/ +disqus: + shortname: + # For newest comments widget + apikey: + +# Alternative Disqus - Render comments with Disqus API +# https://github.com/SukkaW/DisqusJS +disqusjs: + shortname: + apikey: + option: + +# Livere +# https://www.livere.com/ +livere: + uid: + +# Gitalk +# https://github.com/gitalk/gitalk +gitalk: + client_id: + client_secret: + repo: + owner: + admin: + option: + +# Valine +# https://valine.js.org +valine: + appId: + appKey: + avatar: monsterid + # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in) + serverURLs: + bg: + # Use Valine visitor count as the page view count + visitor: false + option: + +# Waline - A simple comment system with backend support fork from Valine +# https://waline.js.org/ +waline: + serverURL: + bg: + # Use Waline pageview count as the page view count + pageview: false + option: + +# Utterances +# https://utteranc.es/ +utterances: + repo: + # Issue Mapping: pathname/url/title/og:title + issue_term: pathname + # Theme: github-light/github-dark/github-dark-orange/icy-dark/dark-blue/photon-dark + light_theme: github-light + dark_theme: photon-dark + js: + option: + +# Facebook Comments Plugin +# https://developers.facebook.com/docs/plugins/comments/ +facebook_comments: + app_id: + # optional + user_id: + pageSize: 10 + # Choose: social / time / reverse_time + order_by: social + lang: en_US + +# Twikoo +# https://github.com/imaegoo/twikoo +twikoo: + envId: + region: + # Use Twikoo visitor count as the page view count + visitor: false + option: + +# Giscus +# https://giscus.app/ +giscus: + repo: + repo_id: + category_id: + light_theme: light + dark_theme: dark + js: + option: + +# Remark42 +# https://remark42.com/docs/configuration/frontend/ +remark42: + host: + siteId: + option: + +# Artalk +# https://artalk.js.org/guide/frontend/config.html +artalk: + server: + site: + # Use Artalk visitor count as the page view count + visitor: false + option: + +# -------------------------------------- +# Chat Services +# -------------------------------------- + +chat: + # Choose: chatra/tidio/crisp + # Leave it empty if you don't need chat + use: + # Chat Button [recommend] + # It will create a button in the bottom right corner of website, and hide the origin button + rightside_button: false + # The origin chat button is displayed when scrolling up, and the button is hidden when scrolling down + button_hide_show: false + +# https://chatra.io/ +chatra: + id: + +# https://www.tidio.com/ +tidio: + public_key: + +# https://crisp.chat/en/ +crisp: + website_id: + +# -------------------------------------- +# Analysis +# -------------------------------------- + +# https://tongji.baidu.com/web/welcome/login +baidu_analytics: + +# https://analytics.google.com/analytics/web/ +google_analytics: + +# https://www.cloudflare.com/zh-tw/web-analytics/ +cloudflare_analytics: + +# https://clarity.microsoft.com/ +microsoft_clarity: + +# https://umami.is/ +umami_analytics: + enable: false + # For self-hosted setups, configure the hostname of the Umami instance + serverURL: + website_id: + option: + UV_PV: + site_uv: false + site_pv: false + page_pv: false + # Umami Cloud (API key) / self-hosted Umami (token) + token: + +# -------------------------------------- +# Advertisement +# -------------------------------------- + +# Google Adsense +google_adsense: + enable: false + auto_ads: true + js: https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js + client: + enable_page_level_ads: true + +# Insert ads manually +# Leave it empty if you don't need ads +ad: + # Insert ads in the index (every three posts) + index: + # Insert ads in aside + aside: + # Insert ads in the post (before pagination) + post: + +# -------------------------------------- +# Verification +# -------------------------------------- + +site_verification: + # - name: google-site-verification + # content: xxxxxx + # - name: baidu-site-verification + # content: xxxxxxx + +# -------------------------------------- +# Beautify / Effect +# -------------------------------------- + +# Theme color for customize +# Notice: color value must in double quotes like "#000" or may cause error! + +# theme_color: +# enable: true +# main: "#49B1F5" +# paginator: "#00c4b6" +# button_hover: "#FF7242" +# text_selection: "#00c4b6" +# link_color: "#99a9bf" +# meta_color: "#858585" +# hr_color: "#A4D8FA" +# code_foreground: "#F47466" +# code_background: "rgba(27, 31, 35, .05)" +# toc_color: "#00c4b6" +# blockquote_padding_color: "#49b1f5" +# blockquote_background_color: "#49b1f5" +# scrollbar_color: "#49b1f5" +# meta_theme_color_light: "ffffff" +# meta_theme_color_dark: "#0d0d0d" + +# The user interface setting of category and tag page +# Choose: index - same as Homepage UI / default - same as archives UI +# leave it empty or index +category_ui: +tag_ui: + +# Rounded corners for UI elements +rounded_corners_ui: true + +# Stretches the lines so that each line has equal width +text_align_justify: false + +# Add a mask to the header and footer +mask: + header: true + footer: true + +# Loading Animation +preloader: + enable: false + # source + # 1. fullpage-loading + # 2. pace (progress bar) + source: 1 + # pace theme (see https://codebyzach.github.io/pace/) + pace_css_url: + +# Page Transition +enter_transitions: true + +# Default display mode - light (default) / dark +display_mode: light + +# Configuration for beautifying the content of the article +beautify: + enable: false + # Specify the field to beautify (site or post) + field: post + # Specify the icon to be used as a prefix for the title, such as '\f0c1' + title_prefix_icon: + # Specify the color of the title prefix icon, such as '#F47466' + title_prefix_icon_color: + +# Global font settings +# Don't modify the following settings unless you know how they work +font: + global_font_size: + code_font_size: + font_family: + code_font_family: + +# Font settings for the site title and site subtitle +blog_title_font: + font_link: + font_family: + +# The setting of divider icon +hr_icon: + enable: true + # The unicode value of Font Awesome icon, such as '\3423' + icon: + icon_top: + +# Typewriter Effect +# https://github.com/disjukr/activate-power-mode +activate_power_mode: + enable: false + colorful: true + shake: true + mobile: false + +# Background effects +# -------------------------------------- + +# canvas_ribbon +# See: https://github.com/hustcc/ribbon.js +canvas_ribbon: + enable: false + # The size of ribbon + size: 150 + # The opacity of ribbon (0 ~ 1) + alpha: 0.6 + zIndex: -1 + click_to_change: false + mobile: false + +# Fluttering Ribbon +canvas_fluttering_ribbon: + enable: false + mobile: false + +# canvas_nest +# https://github.com/hustcc/canvas-nest.js +canvas_nest: + enable: false + # Color of lines, default: '0,0,0'; RGB values: (R,G,B).(note: use ',' to separate.) + color: '0,0,255' + # The opacity of line (0~1) + opacity: 0.7 + # The z-index property of the background + zIndex: -1 + # The number of lines + count: 99 + mobile: false + +# Mouse click effects: fireworks +fireworks: + enable: false + zIndex: 9999 + mobile: false + +# Mouse click effects: Heart symbol +click_heart: + enable: false + mobile: false + +# Mouse click effects: words +clickShowText: + enable: false + text: + # - I + # - LOVE + # - YOU + fontSize: 15px + random: false + mobile: false + +# -------------------------------------- +# Lightbox Settings +# -------------------------------------- + +# Choose: fancybox / medium_zoom +# https://github.com/francoischalifour/medium-zoom +# https://fancyapps.com/fancybox/ +# Leave it empty if you don't need lightbox +lightbox: + +# -------------------------------------- +# Tag Plugins settings +# -------------------------------------- + +# Series +series: + enable: false + # Order by title or date + orderBy: 'title' + # Sort of order. 1, asc for ascending; -1, desc for descending + order: 1 + number: true + +# ABCJS - The ABC Music Notation Plugin +# https://github.com/paulrosen/abcjs +abcjs: + enable: false + per_page: true + +# Mermaid +# https://github.com/mermaid-js/mermaid +mermaid: + enable: false + # Write Mermaid diagrams using code blocks + code_write: false + # built-in themes: default / forest / dark / neutral + theme: + light: default + dark: dark + +# chartjs +# see https://www.chartjs.org/docs/latest/ +chartjs: + enable: false + # Do not modify unless you understand how they work. + # The default settings are only used when the MD syntax is not specified. + # General font color for the chart + fontColor: + light: 'rgba(0, 0, 0, 0.8)' + dark: 'rgba(255, 255, 255, 0.8)' + # General border color for the chart + borderColor: + light: 'rgba(0, 0, 0, 0.1)' + dark: 'rgba(255, 255, 255, 0.2)' + # Background color for scale labels on radar and polar area charts + scale_ticks_backdropColor: + light: 'transparent' + dark: 'transparent' + +# Note - Bootstrap Callout +note: + # Note tag style values: + # - simple bs-callout old alert style. Default. + # - modern bs-callout new (v2-v3) alert style. + # - flat flat callout style with background, like on Mozilla or StackOverflow. + # - disabled disable all CSS styles import of note tag. + style: flat + icons: true + border_radius: 3 + # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6). + # Offset also applied to label tag variables. This option can work with disabled note tag. + light_bg_offset: 0 + +# -------------------------------------- +# Other Settings +# -------------------------------------- + +# https://github.com/MoOx/pjax +pjax: + enable: false + # Exclude the specified pages from pjax, such as '/music/' + exclude: + # - /xxxxxx/ + +# Inject the css and script (aplayer/meting) +aplayerInject: + enable: false + per_page: true + +# Snackbar - Toast Notification +# https://github.com/polonel/SnackBar +# position: top-left / top-center / top-right / bottom-left / bottom-center / bottom-right +snackbar: + enable: false + position: bottom-left + # The background color of Toast Notification in light mode and dark mode + bg_light: '#49b1f5' + bg_dark: '#1f1f1f' + +# Instant.page +# https://instant.page/ +instantpage: false + +# Lazyload +# https://github.com/verlok/vanilla-lazyload +lazyload: + enable: false + # Specify the field to use lazyload (site or post) + field: site + placeholder: + blur: false + +# PWA +# See https://github.com/JLHwung/hexo-offline +# --------------- +pwa: + enable: false + manifest: + apple_touch_icon: + favicon_32_32: + favicon_16_16: + mask_icon: + +# Open graph meta tags +# https://hexo.io/docs/helpers#open-graph +Open_Graph_meta: + enable: true + option: + # twitter_card: + # twitter_image: + # twitter_id: + # twitter_site: + # google_plus: + # fb_admins: + # fb_app_id: + +# Structured Data +# https://developers.google.com/search/docs/guides/intro-structured-data +structured_data: true + +# Add the vendor prefixes to ensure compatibility +css_prefix: true + +# Inject +# Insert the code to head (before '' tag) and the bottom (before '' tag) +inject: + head: + # - + bottom: + # - + +# CDN Settings +# Don't modify the following settings unless you know how they work +CDN: + # The CDN provider for internal and third-party scripts + # Options for both: local/jsdelivr/unpkg/cdnjs/custom + # Note: Dev version can only use 'local' for internal scripts + # Note: When setting third-party scripts to 'local', you need to install hexo-butterfly-extjs + internal_provider: local + third_party_provider: jsdelivr + + # Add version number to url, true or false + version: false + + # Custom format + # For example: https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file} + custom_format: + + option: + # abcjs_basic_js: + # activate_power_mode: + # algolia_js: + # algolia_search: + # aplayer_css: + # aplayer_js: + # artalk_css: + # artalk_js: + # blueimp_md5: + # busuanzi: + # canvas_fluttering_ribbon: + # canvas_nest: + # canvas_ribbon: + # chartjs: + # click_heart: + # clickShowText: + # disqusjs: + # disqusjs_css: + # docsearch_css: + # docsearch_js: + # egjs_infinitegrid: + # fancybox: + # fancybox_css: + # fireworks: + # fontawesome: + # gitalk: + # gitalk_css: + # giscus: + # instantpage: + # instantsearch: + # katex: + # katex_copytex: + # lazyload: + # local_search: + # main: + # main_css: + # mathjax: + # medium_zoom: + # mermaid: + # meting_js: + # prismjs_autoloader: + # prismjs_js: + # prismjs_lineNumber_js: + # pjax: + # sharejs: + # sharejs_css: + # snackbar: + # snackbar_css: + # translate: + # twikoo: + # typed: + # utils: + # valine: + # waline_css: + # waline_js: diff --git a/languages/default.yml b/languages/default.yml index f35cb35..2fe206f 100644 --- a/languages/default.yml +++ b/languages/default.yml @@ -1,121 +1,121 @@ -footer: - framework: Framework - theme: Theme - -copy: - success: Copy Successful - error: Copy Failed - noSupport: Browser Not Supported - -page: - articles: All Articles - tag: Tag - category: Category - archives: Archives - -card_post_count: comments - -no_title: Untitled - -post: - created: Created - updated: Updated - wordcount: Word Count - min2read: Reading Time - min2read_unit: mins - page_pv: Post Views - comments: Comments - copyright: - author: Author - link: Link - copyright_notice: Copyright Notice - copyright_content: 'All articles on this blog are licensed under %s unless otherwise stated.' - recommend: Related Articles - edit: Edit - -search: - title: Search - load_data: Loading Database - input_placeholder: Search for Posts - algolia_search: - hits_empty: 'No results found for: ${query}' - hits_stats: '${hits} results found in ${time} ms' - local_search: - hits_empty: 'No results found for: ${query}' - hits_stats: '${hits} articles found' - -pagination: - prev: Previous - next: Next - -comment: Comments - -aside: - articles: Articles - tags: Tags - categories: Categories - card_announcement: Announcement - card_categories: Categories - card_tags: Tags - card_archives: Archives - card_recent_post: Recent Posts - card_webinfo: - headline: Website Info - article_name: Article Count - runtime: - name: Runtime - unit: days - last_push_date: - name: Last Update - site_wordcount: Total Word Count - site_uv_name: Unique Visitors - site_pv_name: Page Views - more_button: View More - card_newest_comments: - headline: Latest Comments - loading_text: Loading... - error: Unable to retrieve comments, please check the configuration - zero: No comments - image: Image - link: Link - code: Code - card_toc: Contents - card_post_series: Post Series - -date_suffix: - just: Just now - min: minutes ago - hour: hours ago - day: days ago - month: months ago - -donate: Sponsor -share: Share - -rightside: - readmode_title: Reading Mode - translate_title: Toggle Between Traditional and Simplified Chinese - night_mode_title: Toggle Between Light and Dark Mode - back_to_top: Back to Top - toc: Table of Contents - scroll_to_comment: Scroll to Comments - setting: Settings - aside: Toggle Between Single-column and Double-column - chat: Chat - -copy_copyright: - author: Author - link: Link - source: Source - info: Copyright belongs to the author. For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source. - -Snackbar: - chs_to_cht: You have switched to Traditional Chinese - cht_to_chs: You have switched to Simplified Chinese - day_to_night: You have switched to Dark Mode - night_to_day: You have switched to Light Mode - -loading: Loading... -load_more: Load More - -error404: Page Not Found +footer: + framework: Framework + theme: Theme + +copy: + success: Copy Successful + error: Copy Failed + noSupport: Browser Not Supported + +page: + articles: All Articles + tag: Tag + category: Category + archives: Archives + +card_post_count: comments + +no_title: Untitled + +post: + created: Created + updated: Updated + wordcount: Word Count + min2read: Reading Time + min2read_unit: mins + page_pv: Post Views + comments: Comments + copyright: + author: Author + link: Link + copyright_notice: Copyright Notice + copyright_content: 'All articles on this blog are licensed under %s unless otherwise stated.' + recommend: Related Articles + edit: Edit + +search: + title: Search + load_data: Loading Database + input_placeholder: Search for Posts + algolia_search: + hits_empty: 'No results found for: ${query}' + hits_stats: '${hits} results found in ${time} ms' + local_search: + hits_empty: 'No results found for: ${query}' + hits_stats: '${hits} articles found' + +pagination: + prev: Previous + next: Next + +comment: Comments + +aside: + articles: Articles + tags: Tags + categories: Categories + card_announcement: Announcement + card_categories: Categories + card_tags: Tags + card_archives: Archives + card_recent_post: Recent Posts + card_webinfo: + headline: Website Info + article_name: Article Count + runtime: + name: Runtime + unit: days + last_push_date: + name: Last Update + site_wordcount: Total Word Count + site_uv_name: Unique Visitors + site_pv_name: Page Views + more_button: View More + card_newest_comments: + headline: Latest Comments + loading_text: Loading... + error: Unable to retrieve comments, please check the configuration + zero: No comments + image: Image + link: Link + code: Code + card_toc: Contents + card_post_series: Post Series + +date_suffix: + just: Just now + min: minutes ago + hour: hours ago + day: days ago + month: months ago + +donate: Sponsor +share: Share + +rightside: + readmode_title: Reading Mode + translate_title: Toggle Between Traditional and Simplified Chinese + night_mode_title: Toggle Between Light and Dark Mode + back_to_top: Back to Top + toc: Table of Contents + scroll_to_comment: Scroll to Comments + setting: Settings + aside: Toggle Between Single-column and Double-column + chat: Chat + +copy_copyright: + author: Author + link: Link + source: Source + info: Copyright belongs to the author. For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source. + +Snackbar: + chs_to_cht: You have switched to Traditional Chinese + cht_to_chs: You have switched to Simplified Chinese + day_to_night: You have switched to Dark Mode + night_to_day: You have switched to Light Mode + +loading: Loading... +load_more: Load More + +error404: Page Not Found diff --git a/languages/en.yml b/languages/en.yml index f35cb35..2fe206f 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -1,121 +1,121 @@ -footer: - framework: Framework - theme: Theme - -copy: - success: Copy Successful - error: Copy Failed - noSupport: Browser Not Supported - -page: - articles: All Articles - tag: Tag - category: Category - archives: Archives - -card_post_count: comments - -no_title: Untitled - -post: - created: Created - updated: Updated - wordcount: Word Count - min2read: Reading Time - min2read_unit: mins - page_pv: Post Views - comments: Comments - copyright: - author: Author - link: Link - copyright_notice: Copyright Notice - copyright_content: 'All articles on this blog are licensed under %s unless otherwise stated.' - recommend: Related Articles - edit: Edit - -search: - title: Search - load_data: Loading Database - input_placeholder: Search for Posts - algolia_search: - hits_empty: 'No results found for: ${query}' - hits_stats: '${hits} results found in ${time} ms' - local_search: - hits_empty: 'No results found for: ${query}' - hits_stats: '${hits} articles found' - -pagination: - prev: Previous - next: Next - -comment: Comments - -aside: - articles: Articles - tags: Tags - categories: Categories - card_announcement: Announcement - card_categories: Categories - card_tags: Tags - card_archives: Archives - card_recent_post: Recent Posts - card_webinfo: - headline: Website Info - article_name: Article Count - runtime: - name: Runtime - unit: days - last_push_date: - name: Last Update - site_wordcount: Total Word Count - site_uv_name: Unique Visitors - site_pv_name: Page Views - more_button: View More - card_newest_comments: - headline: Latest Comments - loading_text: Loading... - error: Unable to retrieve comments, please check the configuration - zero: No comments - image: Image - link: Link - code: Code - card_toc: Contents - card_post_series: Post Series - -date_suffix: - just: Just now - min: minutes ago - hour: hours ago - day: days ago - month: months ago - -donate: Sponsor -share: Share - -rightside: - readmode_title: Reading Mode - translate_title: Toggle Between Traditional and Simplified Chinese - night_mode_title: Toggle Between Light and Dark Mode - back_to_top: Back to Top - toc: Table of Contents - scroll_to_comment: Scroll to Comments - setting: Settings - aside: Toggle Between Single-column and Double-column - chat: Chat - -copy_copyright: - author: Author - link: Link - source: Source - info: Copyright belongs to the author. For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source. - -Snackbar: - chs_to_cht: You have switched to Traditional Chinese - cht_to_chs: You have switched to Simplified Chinese - day_to_night: You have switched to Dark Mode - night_to_day: You have switched to Light Mode - -loading: Loading... -load_more: Load More - -error404: Page Not Found +footer: + framework: Framework + theme: Theme + +copy: + success: Copy Successful + error: Copy Failed + noSupport: Browser Not Supported + +page: + articles: All Articles + tag: Tag + category: Category + archives: Archives + +card_post_count: comments + +no_title: Untitled + +post: + created: Created + updated: Updated + wordcount: Word Count + min2read: Reading Time + min2read_unit: mins + page_pv: Post Views + comments: Comments + copyright: + author: Author + link: Link + copyright_notice: Copyright Notice + copyright_content: 'All articles on this blog are licensed under %s unless otherwise stated.' + recommend: Related Articles + edit: Edit + +search: + title: Search + load_data: Loading Database + input_placeholder: Search for Posts + algolia_search: + hits_empty: 'No results found for: ${query}' + hits_stats: '${hits} results found in ${time} ms' + local_search: + hits_empty: 'No results found for: ${query}' + hits_stats: '${hits} articles found' + +pagination: + prev: Previous + next: Next + +comment: Comments + +aside: + articles: Articles + tags: Tags + categories: Categories + card_announcement: Announcement + card_categories: Categories + card_tags: Tags + card_archives: Archives + card_recent_post: Recent Posts + card_webinfo: + headline: Website Info + article_name: Article Count + runtime: + name: Runtime + unit: days + last_push_date: + name: Last Update + site_wordcount: Total Word Count + site_uv_name: Unique Visitors + site_pv_name: Page Views + more_button: View More + card_newest_comments: + headline: Latest Comments + loading_text: Loading... + error: Unable to retrieve comments, please check the configuration + zero: No comments + image: Image + link: Link + code: Code + card_toc: Contents + card_post_series: Post Series + +date_suffix: + just: Just now + min: minutes ago + hour: hours ago + day: days ago + month: months ago + +donate: Sponsor +share: Share + +rightside: + readmode_title: Reading Mode + translate_title: Toggle Between Traditional and Simplified Chinese + night_mode_title: Toggle Between Light and Dark Mode + back_to_top: Back to Top + toc: Table of Contents + scroll_to_comment: Scroll to Comments + setting: Settings + aside: Toggle Between Single-column and Double-column + chat: Chat + +copy_copyright: + author: Author + link: Link + source: Source + info: Copyright belongs to the author. For commercial use, please contact the author for authorization. For non-commercial use, please indicate the source. + +Snackbar: + chs_to_cht: You have switched to Traditional Chinese + cht_to_chs: You have switched to Simplified Chinese + day_to_night: You have switched to Dark Mode + night_to_day: You have switched to Light Mode + +loading: Loading... +load_more: Load More + +error404: Page Not Found diff --git a/languages/ja.yml b/languages/ja.yml index 1a291f8..f1ccbb7 100644 --- a/languages/ja.yml +++ b/languages/ja.yml @@ -1,121 +1,121 @@ -footer: - framework: フレームワーク - theme: テーマ - -copy: - success: コピー成功 - error: コピー失敗 - noSupport: ブラウザが対応していません - -page: - articles: 記事一覧 - tag: タグ - category: カテゴリ - archives: アーカイブ - -card_post_count: コメント数 - -no_title: タイトルなし - -post: - created: 作成日 - updated: 更新日 - wordcount: 総文字数 - min2read: 読む時間 - min2read_unit: 分 - page_pv: 閲覧数 - comments: コメント数 - copyright: - author: 著者 - link: リンク - copyright_notice: 著作権表示 - copyright_content: 'このブログのすべての記事は、%s ライセンスの下で提供されており、特に明記されていない限り、すべての権利を留保します。転載時には出典を明記してください: %s。' - recommend: 関連記事 - edit: 編集 - -search: - title: 検索 - load_data: データベースを読み込んでいます - input_placeholder: 記事を検索 - algolia_search: - hits_empty: '${query} の検索結果が見つかりませんでした。' - hits_stats: '${hits} 件の結果が ${time}ms で見つかりました' - local_search: - hits_empty: '${query} の検索結果が見つかりませんでした。' - hits_stats: '${hits} 件の記事が見つかりました' - -pagination: - prev: 前へ - next: 次へ - -comment: コメント - -aside: - articles: 記事 - tags: タグ - categories: カテゴリ - card_announcement: お知らせ - card_categories: カテゴリ - card_tags: タグ - card_archives: アーカイブ - card_recent_post: 最近の記事 - card_webinfo: - headline: サイト情報 - article_name: 記事数 - runtime: - name: 稼働時間 - unit: 日 - last_push_date: - name: 最終更新日 - site_wordcount: 総文字数 - site_uv_name: ユーザー数 - site_pv_name: ページビュー数 - more_button: もっと見る - card_newest_comments: - headline: 最新コメント - loading_text: ローディング中... - error: コメントを取得できませんでした。設定を確認してください。 - zero: コメントがありません - image: 画像 - link: リンク - code: コード - card_toc: 目次 - card_post_series: シリーズ記事 - -date_suffix: - just: たった今 - min: 分前 - hour: 時間前 - day: 日前 - month: ヶ月前 - -donate: 寄付 -share: 共有 - -rightside: - readmode_title: 読書モード - translate_title: 簡体字と繁体字の切り替え - night_mode_title: ライトモード/ダークモード切り替え - back_to_top: トップに戻る - toc: 目次 - scroll_to_comment: コメントへ移動 - setting: 設定 - aside: シングルカラムとダブルカラムの切り替え - chat: チャット - -copy_copyright: - author: 著者 - link: リンク - source: ソース - info: 著作権は著者に帰属します。商業的利用の場合は著者に連絡して許可を得てください。非商業的利用の場合は出典を明記してください。 - -Snackbar: - chs_to_cht: 繁体字に切り替えました - cht_to_chs: 簡体字に切り替えました - day_to_night: ダークモードに切り替えました - night_to_day: ライトモードに切り替えました - -loading: ローディング中... -load_more: もっと見る - -error404: ページが見つかりません +footer: + framework: フレームワーク + theme: テーマ + +copy: + success: コピー成功 + error: コピー失敗 + noSupport: ブラウザが対応していません + +page: + articles: 記事一覧 + tag: タグ + category: カテゴリ + archives: アーカイブ + +card_post_count: コメント数 + +no_title: タイトルなし + +post: + created: 作成日 + updated: 更新日 + wordcount: 総文字数 + min2read: 読む時間 + min2read_unit: 分 + page_pv: 閲覧数 + comments: コメント数 + copyright: + author: 著者 + link: リンク + copyright_notice: 著作権表示 + copyright_content: 'このブログのすべての記事は、%s ライセンスの下で提供されており、特に明記されていない限り、すべての権利を留保します。転載時には出典を明記してください: %s。' + recommend: 関連記事 + edit: 編集 + +search: + title: 検索 + load_data: データベースを読み込んでいます + input_placeholder: 記事を検索 + algolia_search: + hits_empty: '${query} の検索結果が見つかりませんでした。' + hits_stats: '${hits} 件の結果が ${time}ms で見つかりました' + local_search: + hits_empty: '${query} の検索結果が見つかりませんでした。' + hits_stats: '${hits} 件の記事が見つかりました' + +pagination: + prev: 前へ + next: 次へ + +comment: コメント + +aside: + articles: 記事 + tags: タグ + categories: カテゴリ + card_announcement: お知らせ + card_categories: カテゴリ + card_tags: タグ + card_archives: アーカイブ + card_recent_post: 最近の記事 + card_webinfo: + headline: サイト情報 + article_name: 記事数 + runtime: + name: 稼働時間 + unit: 日 + last_push_date: + name: 最終更新日 + site_wordcount: 総文字数 + site_uv_name: ユーザー数 + site_pv_name: ページビュー数 + more_button: もっと見る + card_newest_comments: + headline: 最新コメント + loading_text: ローディング中... + error: コメントを取得できませんでした。設定を確認してください。 + zero: コメントがありません + image: 画像 + link: リンク + code: コード + card_toc: 目次 + card_post_series: シリーズ記事 + +date_suffix: + just: たった今 + min: 分前 + hour: 時間前 + day: 日前 + month: ヶ月前 + +donate: 寄付 +share: 共有 + +rightside: + readmode_title: 読書モード + translate_title: 簡体字と繁体字の切り替え + night_mode_title: ライトモード/ダークモード切り替え + back_to_top: トップに戻る + toc: 目次 + scroll_to_comment: コメントへ移動 + setting: 設定 + aside: シングルカラムとダブルカラムの切り替え + chat: チャット + +copy_copyright: + author: 著者 + link: リンク + source: ソース + info: 著作権は著者に帰属します。商業的利用の場合は著者に連絡して許可を得てください。非商業的利用の場合は出典を明記してください。 + +Snackbar: + chs_to_cht: 繁体字に切り替えました + cht_to_chs: 簡体字に切り替えました + day_to_night: ダークモードに切り替えました + night_to_day: ライトモードに切り替えました + +loading: ローディング中... +load_more: もっと見る + +error404: ページが見つかりません diff --git a/languages/ko.yml b/languages/ko.yml index 7dca8da..b94c365 100644 --- a/languages/ko.yml +++ b/languages/ko.yml @@ -1,121 +1,121 @@ -footer: - framework: 프레임워크 - theme: 테마 - -copy: - success: 복사 성공 - error: 복사 실패 - noSupport: 브라우저가 지원되지 않음 - -page: - articles: 모든 글 - tag: 태그 - category: 카테고리 - archives: 아카이브 - -card_post_count: 댓글 수 - -no_title: 제목 없음 - -post: - created: 작성일 - updated: 수정일 - wordcount: 총 글자 수 - min2read: 읽기 시간 - min2read_unit: 분 - page_pv: 조회수 - comments: 댓글 - copyright: - author: 작성자 - link: 링크 - copyright_notice: 저작권 고지 - copyright_content: '이 블로그의 모든 글은 %s 라이선스를 따르며, 별도로 명시되지 않는 한 모든 권리를 보유합니다. 재배포 시 출처를 명시해 주세요: %s.' - recommend: 관련 글 - edit: 편집 - -search: - title: 검색 - load_data: 데이터베이스 로드 중 - input_placeholder: 글 검색 - algolia_search: - hits_empty: '${query}에 대한 결과를 찾을 수 없습니다.' - hits_stats: '${hits}개의 결과를 ${time}ms 만에 찾음' - local_search: - hits_empty: '${query}에 대한 결과를 찾을 수 없습니다.' - hits_stats: '${hits}개의 글을 찾음' - -pagination: - prev: 이전 - next: 다음 - -comment: 댓글 - -aside: - articles: 글 - tags: 태그 - categories: 카테고리 - card_announcement: 공지 - card_categories: 카테고리 - card_tags: 태그 - card_archives: 아카이브 - card_recent_post: 최근 글 - card_webinfo: - headline: 사이트 정보 - article_name: 글 수 - runtime: - name: 운영 시간 - unit: 일 - last_push_date: - name: 마지막 업데이트 - site_wordcount: 총 글자 수 - site_uv_name: 방문자 수 - site_pv_name: 총 조회수 - more_button: 더 보기 - card_newest_comments: - headline: 최신 댓글 - loading_text: 로딩 중... - error: 댓글을 가져올 수 없습니다. 설정을 확인해 주세요. - zero: 댓글 없음 - image: 이미지 - link: 링크 - code: 코드 - card_toc: 목차 - card_post_series: 시리즈 글 - -date_suffix: - just: 방금 - min: 분 전 - hour: 시간 전 - day: 일 전 - month: 달 전 - -donate: 후원 -share: 공유 - -rightside: - readmode_title: 읽기 모드 - translate_title: 번체와 간체 전환 - night_mode_title: 라이트/다크 모드 전환 - back_to_top: 맨 위로 - toc: 목차 - scroll_to_comment: 댓글로 이동 - setting: 설정 - aside: 단일/이중 열 전환 - chat: 채팅 - -copy_copyright: - author: 작성자 - link: 링크 - source: 출처 - info: 저작권은 작성자에게 있습니다. 상업적 사용을 위해서는 작성자의 허가를 받아야 하며, 비상업적 사용 시에는 출처를 명시해 주세요. - -Snackbar: - chs_to_cht: 번체로 전환되었습니다. - cht_to_chs: 간체로 전환되었습니다. - day_to_night: 다크 모드로 전환되었습니다. - night_to_day: 라이트 모드로 전환되었습니다. - -loading: 로딩 중... -load_more: 더 보기 - -error404: 페이지를 찾을 수 없습니다. +footer: + framework: 프레임워크 + theme: 테마 + +copy: + success: 복사 성공 + error: 복사 실패 + noSupport: 브라우저가 지원되지 않음 + +page: + articles: 모든 글 + tag: 태그 + category: 카테고리 + archives: 아카이브 + +card_post_count: 댓글 수 + +no_title: 제목 없음 + +post: + created: 작성일 + updated: 수정일 + wordcount: 총 글자 수 + min2read: 읽기 시간 + min2read_unit: 분 + page_pv: 조회수 + comments: 댓글 + copyright: + author: 작성자 + link: 링크 + copyright_notice: 저작권 고지 + copyright_content: '이 블로그의 모든 글은 %s 라이선스를 따르며, 별도로 명시되지 않는 한 모든 권리를 보유합니다. 재배포 시 출처를 명시해 주세요: %s.' + recommend: 관련 글 + edit: 편집 + +search: + title: 검색 + load_data: 데이터베이스 로드 중 + input_placeholder: 글 검색 + algolia_search: + hits_empty: '${query}에 대한 결과를 찾을 수 없습니다.' + hits_stats: '${hits}개의 결과를 ${time}ms 만에 찾음' + local_search: + hits_empty: '${query}에 대한 결과를 찾을 수 없습니다.' + hits_stats: '${hits}개의 글을 찾음' + +pagination: + prev: 이전 + next: 다음 + +comment: 댓글 + +aside: + articles: 글 + tags: 태그 + categories: 카테고리 + card_announcement: 공지 + card_categories: 카테고리 + card_tags: 태그 + card_archives: 아카이브 + card_recent_post: 최근 글 + card_webinfo: + headline: 사이트 정보 + article_name: 글 수 + runtime: + name: 운영 시간 + unit: 일 + last_push_date: + name: 마지막 업데이트 + site_wordcount: 총 글자 수 + site_uv_name: 방문자 수 + site_pv_name: 총 조회수 + more_button: 더 보기 + card_newest_comments: + headline: 최신 댓글 + loading_text: 로딩 중... + error: 댓글을 가져올 수 없습니다. 설정을 확인해 주세요. + zero: 댓글 없음 + image: 이미지 + link: 링크 + code: 코드 + card_toc: 목차 + card_post_series: 시리즈 글 + +date_suffix: + just: 방금 + min: 분 전 + hour: 시간 전 + day: 일 전 + month: 달 전 + +donate: 후원 +share: 공유 + +rightside: + readmode_title: 읽기 모드 + translate_title: 번체와 간체 전환 + night_mode_title: 라이트/다크 모드 전환 + back_to_top: 맨 위로 + toc: 목차 + scroll_to_comment: 댓글로 이동 + setting: 설정 + aside: 단일/이중 열 전환 + chat: 채팅 + +copy_copyright: + author: 작성자 + link: 링크 + source: 출처 + info: 저작권은 작성자에게 있습니다. 상업적 사용을 위해서는 작성자의 허가를 받아야 하며, 비상업적 사용 시에는 출처를 명시해 주세요. + +Snackbar: + chs_to_cht: 번체로 전환되었습니다. + cht_to_chs: 간체로 전환되었습니다. + day_to_night: 다크 모드로 전환되었습니다. + night_to_day: 라이트 모드로 전환되었습니다. + +loading: 로딩 중... +load_more: 더 보기 + +error404: 페이지를 찾을 수 없습니다. diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml index 1afa96b..32ff836 100644 --- a/languages/zh-CN.yml +++ b/languages/zh-CN.yml @@ -1,122 +1,122 @@ -footer: - framework: 框架 - theme: 主题 - -copy: - success: 复制成功 - error: 复制失败 - noSupport: 浏览器不支持 - -page: - articles: 全部文章 - tag: 标签 - category: 分类 - archives: 归档 - -card_post_count: 条评论 - -no_title: 无标题 - -post: - created: 发表于 - updated: 更新于 - wordcount: 总字数 - min2read: 阅读时长 - min2read_unit: 分钟 - page_pv: 浏览量 - comments: 评论数 - copyright: - author: 文章作者 - link: 文章链接 - copyright_notice: 版权声明 - copyright_content: '本博客所有文章除特别声明外,均采用 - %s 许可协议。转载请注明来源 %s!' - recommend: 相关推荐 - edit: 编辑 - -search: - title: 搜索 - load_data: 数据加载中 - input_placeholder: 搜索文章 - algolia_search: - hits_empty: '未找到符合您查询的内容:${query}' - hits_stats: '找到 ${hits} 条结果,耗时 ${time} 毫秒' - local_search: - hits_empty: '未找到符合您查询的内容:${query}' - hits_stats: '共找到 ${hits} 篇文章' - -pagination: - prev: 上一篇 - next: 下一篇 - -comment: 评论 - -aside: - articles: 文章 - tags: 标签 - categories: 分类 - card_announcement: 公告 - card_categories: 分类 - card_tags: 标签 - card_archives: 归档 - card_recent_post: 最新文章 - card_webinfo: - headline: 网站信息 - article_name: 文章数目 - runtime: - name: 运行时间 - unit: 天 - last_push_date: - name: 最后更新时间 - site_wordcount: 本站总字数 - site_uv_name: 本站访客数 - site_pv_name: 本站总浏览量 - more_button: 查看更多 - card_newest_comments: - headline: 最新评论 - loading_text: 加载中... - error: 无法获取评论,请确认相关配置是否正确 - zero: 暂无评论 - image: 图片 - link: 链接 - code: 代码 - card_toc: 目录 - card_post_series: 系列文章 - -date_suffix: - just: 刚刚 - min: 分钟前 - hour: 小时前 - day: 天前 - month: 个月前 - -donate: 赞助 -share: 分享 - -rightside: - readmode_title: 阅读模式 - translate_title: 简繁转换 - night_mode_title: 日间和夜间模式切换 - back_to_top: 回到顶部 - toc: 目录 - scroll_to_comment: 前往评论 - setting: 设置 - aside: 单栏和双栏切换 - chat: 聊天 - -copy_copyright: - author: 作者 - link: 链接 - source: 来源 - info: 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 - -Snackbar: - chs_to_cht: 已切换为繁体中文 - cht_to_chs: 已切换为简体中文 - day_to_night: 已切换为深色模式 - night_to_day: 已切换为浅色模式 - -loading: 加载中... -load_more: 加载更多 - -error404: 页面未找到 +footer: + framework: 框架 + theme: 主题 + +copy: + success: 复制成功 + error: 复制失败 + noSupport: 浏览器不支持 + +page: + articles: 全部文章 + tag: 标签 + category: 分类 + archives: 归档 + +card_post_count: 条评论 + +no_title: 无标题 + +post: + created: 发表于 + updated: 更新于 + wordcount: 总字数 + min2read: 阅读时长 + min2read_unit: 分钟 + page_pv: 浏览量 + comments: 评论数 + copyright: + author: 文章作者 + link: 文章链接 + copyright_notice: 版权声明 + copyright_content: '本博客所有文章除特别声明外,均采用 + %s 许可协议。转载请注明来源 %s!' + recommend: 相关推荐 + edit: 编辑 + +search: + title: 搜索 + load_data: 数据加载中 + input_placeholder: 搜索文章 + algolia_search: + hits_empty: '未找到符合您查询的内容:${query}' + hits_stats: '找到 ${hits} 条结果,耗时 ${time} 毫秒' + local_search: + hits_empty: '未找到符合您查询的内容:${query}' + hits_stats: '共找到 ${hits} 篇文章' + +pagination: + prev: 上一篇 + next: 下一篇 + +comment: 评论 + +aside: + articles: 文章 + tags: 标签 + categories: 分类 + card_announcement: 公告 + card_categories: 分类 + card_tags: 标签 + card_archives: 归档 + card_recent_post: 最新文章 + card_webinfo: + headline: 网站信息 + article_name: 文章数目 + runtime: + name: 运行时间 + unit: 天 + last_push_date: + name: 最后更新时间 + site_wordcount: 本站总字数 + site_uv_name: 本站访客数 + site_pv_name: 本站总浏览量 + more_button: 查看更多 + card_newest_comments: + headline: 最新评论 + loading_text: 加载中... + error: 无法获取评论,请确认相关配置是否正确 + zero: 暂无评论 + image: 图片 + link: 链接 + code: 代码 + card_toc: 目录 + card_post_series: 系列文章 + +date_suffix: + just: 刚刚 + min: 分钟前 + hour: 小时前 + day: 天前 + month: 个月前 + +donate: 赞助 +share: 分享 + +rightside: + readmode_title: 阅读模式 + translate_title: 简繁转换 + night_mode_title: 日间和夜间模式切换 + back_to_top: 回到顶部 + toc: 目录 + scroll_to_comment: 前往评论 + setting: 设置 + aside: 单栏和双栏切换 + chat: 聊天 + +copy_copyright: + author: 作者 + link: 链接 + source: 来源 + info: 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +Snackbar: + chs_to_cht: 已切换为繁体中文 + cht_to_chs: 已切换为简体中文 + day_to_night: 已切换为深色模式 + night_to_day: 已切换为浅色模式 + +loading: 加载中... +load_more: 加载更多 + +error404: 页面未找到 diff --git a/languages/zh-HK.yml b/languages/zh-HK.yml index b1f99d7..0ef4487 100644 --- a/languages/zh-HK.yml +++ b/languages/zh-HK.yml @@ -1,121 +1,121 @@ -footer: - framework: 框架 - theme: 主題 - -copy: - success: 複製成功 - error: 複製失敗 - noSupport: 瀏覽器不支援 - -page: - articles: 全部文章 - tag: 標籤 - category: 分類 - archives: 歸檔 - -card_post_count: 條評論 - -no_title: 無標題 - -post: - created: 發表於 - updated: 更新於 - wordcount: 字數統計 - min2read: 閱讀時間 - min2read_unit: 分鐘 - page_pv: 瀏覽量 - comments: 評論數 - copyright: - author: 文章作者 - link: 文章連結 - copyright_notice: 版權聲明 - copyright_content: '除特別聲明外,本博客所有文章均採用%s 授權協議。轉載請註明出處:%s。' - recommend: 相關文章 - edit: 編輯 - -search: - title: 搜尋 - load_data: 正在加載數據庫 - input_placeholder: 搜尋文章 - algolia_search: - hits_empty: '未找到相關內容:${query}' - hits_stats: '找到 ${hits} 條結果,耗時 ${time} 毫秒' - local_search: - hits_empty: '未找到相關內容:${query}' - hits_stats: '找到 ${hits} 篇文章' - -pagination: - prev: 上一頁 - next: 下一頁 - -comment: 評論 - -aside: - articles: 文章 - tags: 標籤 - categories: 分類 - card_announcement: 公告 - card_categories: 分類 - card_tags: 標籤 - card_archives: 歸檔 - card_recent_post: 最新文章 - card_webinfo: - headline: 網站資訊 - article_name: 文章數目 - runtime: - name: 運行時間 - unit: 天 - last_push_date: - name: 最後更新時間 - site_wordcount: 總字數 - site_uv_name: 訪客數 - site_pv_name: 總瀏覽量 - more_button: 查看更多 - card_newest_comments: - headline: 最新評論 - loading_text: 正在加載... - error: 無法取得評論,請確認配置是否正確 - zero: 暫無評論 - image: 圖片 - link: 連結 - code: 代碼 - card_toc: 目錄 - card_post_series: 系列文章 - -date_suffix: - just: 剛剛 - min: 分鐘前 - hour: 小時前 - day: 天前 - month: 個月前 - -donate: 贊助 -share: 分享 - -rightside: - readmode_title: 閱讀模式 - translate_title: 簡繁轉換 - night_mode_title: 切換日夜模式 - back_to_top: 回到頂部 - toc: 目錄 - scroll_to_comment: 前往評論 - setting: 設定 - aside: 單欄與雙欄切換 - chat: 聊天 - -copy_copyright: - author: 作者 - link: 連結 - source: 來源 - info: 版權屬於作者所有。商業用途請聯絡作者獲得授權,非商業用途請註明出處。 - -Snackbar: - chs_to_cht: 已切換為繁體中文 - cht_to_chs: 已切換為簡體中文 - day_to_night: 已切換為深色模式 - night_to_day: 已切換為淺色模式 - -loading: 正在加載... -load_more: 加載更多 - -error404: 未找到頁面 +footer: + framework: 框架 + theme: 主題 + +copy: + success: 複製成功 + error: 複製失敗 + noSupport: 瀏覽器不支援 + +page: + articles: 全部文章 + tag: 標籤 + category: 分類 + archives: 歸檔 + +card_post_count: 條評論 + +no_title: 無標題 + +post: + created: 發表於 + updated: 更新於 + wordcount: 字數統計 + min2read: 閱讀時間 + min2read_unit: 分鐘 + page_pv: 瀏覽量 + comments: 評論數 + copyright: + author: 文章作者 + link: 文章連結 + copyright_notice: 版權聲明 + copyright_content: '除特別聲明外,本博客所有文章均採用%s 授權協議。轉載請註明出處:%s。' + recommend: 相關文章 + edit: 編輯 + +search: + title: 搜尋 + load_data: 正在加載數據庫 + input_placeholder: 搜尋文章 + algolia_search: + hits_empty: '未找到相關內容:${query}' + hits_stats: '找到 ${hits} 條結果,耗時 ${time} 毫秒' + local_search: + hits_empty: '未找到相關內容:${query}' + hits_stats: '找到 ${hits} 篇文章' + +pagination: + prev: 上一頁 + next: 下一頁 + +comment: 評論 + +aside: + articles: 文章 + tags: 標籤 + categories: 分類 + card_announcement: 公告 + card_categories: 分類 + card_tags: 標籤 + card_archives: 歸檔 + card_recent_post: 最新文章 + card_webinfo: + headline: 網站資訊 + article_name: 文章數目 + runtime: + name: 運行時間 + unit: 天 + last_push_date: + name: 最後更新時間 + site_wordcount: 總字數 + site_uv_name: 訪客數 + site_pv_name: 總瀏覽量 + more_button: 查看更多 + card_newest_comments: + headline: 最新評論 + loading_text: 正在加載... + error: 無法取得評論,請確認配置是否正確 + zero: 暫無評論 + image: 圖片 + link: 連結 + code: 代碼 + card_toc: 目錄 + card_post_series: 系列文章 + +date_suffix: + just: 剛剛 + min: 分鐘前 + hour: 小時前 + day: 天前 + month: 個月前 + +donate: 贊助 +share: 分享 + +rightside: + readmode_title: 閱讀模式 + translate_title: 簡繁轉換 + night_mode_title: 切換日夜模式 + back_to_top: 回到頂部 + toc: 目錄 + scroll_to_comment: 前往評論 + setting: 設定 + aside: 單欄與雙欄切換 + chat: 聊天 + +copy_copyright: + author: 作者 + link: 連結 + source: 來源 + info: 版權屬於作者所有。商業用途請聯絡作者獲得授權,非商業用途請註明出處。 + +Snackbar: + chs_to_cht: 已切換為繁體中文 + cht_to_chs: 已切換為簡體中文 + day_to_night: 已切換為深色模式 + night_to_day: 已切換為淺色模式 + +loading: 正在加載... +load_more: 加載更多 + +error404: 未找到頁面 diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml index c91cb73..c9558ef 100644 --- a/languages/zh-TW.yml +++ b/languages/zh-TW.yml @@ -1,121 +1,121 @@ -footer: - framework: 框架 - theme: 主題 - -copy: - success: 複製成功 - error: 複製失敗 - noSupport: 瀏覽器不支援 - -page: - articles: 所有文章 - tag: 標籤 - category: 分類 - archives: 歸檔 - -card_post_count: 則評論 - -no_title: 無標題 - -post: - created: 發表於 - updated: 更新於 - wordcount: 總字數 - min2read: 閱讀時間 - min2read_unit: 分鐘 - page_pv: 瀏覽量 - comments: 評論數 - copyright: - author: 文章作者 - link: 文章連結 - copyright_notice: 版權聲明 - copyright_content: '本部落格所有文章除特別聲明外,均採用%s 授權協議。轉載請註明來源 %s!' - recommend: 相關推薦 - edit: 編輯 - -search: - title: 搜尋 - load_data: 資料載入中 - input_placeholder: 搜尋文章 - algolia_search: - hits_empty: '找不到符合您查詢的內容:${query}' - hits_stats: '找到 ${hits} 筆結果,耗時 ${time} 毫秒' - local_search: - hits_empty: '找不到符合您查詢的內容:${query}' - hits_stats: '共找到 ${hits} 篇文章' - -pagination: - prev: 上一篇 - next: 下一篇 - -comment: 評論 - -aside: - articles: 文章 - tags: 標籤 - categories: 分類 - card_announcement: 公告 - card_categories: 分類 - card_tags: 標籤 - card_archives: 歸檔 - card_recent_post: 最新文章 - card_webinfo: - headline: 網站資訊 - article_name: 文章數量 - runtime: - name: 運行時間 - unit: 天 - last_push_date: - name: 最後更新時間 - site_wordcount: 總字數 - site_uv_name: 訪客數 - site_pv_name: 總瀏覽量 - more_button: 檢視更多 - card_newest_comments: - headline: 最新評論 - loading_text: 載入中... - error: 無法獲取評論,請確認相關配置是否正確 - zero: 尚無評論 - image: 圖片 - link: 連結 - code: 程式碼 - card_toc: 目錄 - card_post_series: 系列文章 - -date_suffix: - just: 剛剛 - min: 分鐘前 - hour: 小時前 - day: 天前 - month: 個月前 - -donate: 贊助 -share: 分享 - -rightside: - readmode_title: 閱讀模式 - translate_title: 繁簡轉換 - night_mode_title: 日夜模式切換 - back_to_top: 回到頂端 - toc: 目錄 - scroll_to_comment: 前往評論 - setting: 設定 - aside: 單欄和雙欄切換 - chat: 聊天 - -copy_copyright: - author: 作者 - link: 連結 - source: 來源 - info: 著作權歸作者所有。如需商業轉載,請聯絡作者獲得授權,非商業轉載請註明出處。 - -Snackbar: - chs_to_cht: 已切換為繁體中文 - cht_to_chs: 已切換為簡體中文 - day_to_night: 已切換為深色模式 - night_to_day: 已切換為淺色模式 - -loading: 載入中... -load_more: 載入更多 - -error404: 找不到頁面 +footer: + framework: 框架 + theme: 主題 + +copy: + success: 複製成功 + error: 複製失敗 + noSupport: 瀏覽器不支援 + +page: + articles: 所有文章 + tag: 標籤 + category: 分類 + archives: 歸檔 + +card_post_count: 則評論 + +no_title: 無標題 + +post: + created: 發表於 + updated: 更新於 + wordcount: 總字數 + min2read: 閱讀時間 + min2read_unit: 分鐘 + page_pv: 瀏覽量 + comments: 評論數 + copyright: + author: 文章作者 + link: 文章連結 + copyright_notice: 版權聲明 + copyright_content: '本部落格所有文章除特別聲明外,均採用%s 授權協議。轉載請註明來源 %s!' + recommend: 相關推薦 + edit: 編輯 + +search: + title: 搜尋 + load_data: 資料載入中 + input_placeholder: 搜尋文章 + algolia_search: + hits_empty: '找不到符合您查詢的內容:${query}' + hits_stats: '找到 ${hits} 筆結果,耗時 ${time} 毫秒' + local_search: + hits_empty: '找不到符合您查詢的內容:${query}' + hits_stats: '共找到 ${hits} 篇文章' + +pagination: + prev: 上一篇 + next: 下一篇 + +comment: 評論 + +aside: + articles: 文章 + tags: 標籤 + categories: 分類 + card_announcement: 公告 + card_categories: 分類 + card_tags: 標籤 + card_archives: 歸檔 + card_recent_post: 最新文章 + card_webinfo: + headline: 網站資訊 + article_name: 文章數量 + runtime: + name: 運行時間 + unit: 天 + last_push_date: + name: 最後更新時間 + site_wordcount: 總字數 + site_uv_name: 訪客數 + site_pv_name: 總瀏覽量 + more_button: 檢視更多 + card_newest_comments: + headline: 最新評論 + loading_text: 載入中... + error: 無法獲取評論,請確認相關配置是否正確 + zero: 尚無評論 + image: 圖片 + link: 連結 + code: 程式碼 + card_toc: 目錄 + card_post_series: 系列文章 + +date_suffix: + just: 剛剛 + min: 分鐘前 + hour: 小時前 + day: 天前 + month: 個月前 + +donate: 贊助 +share: 分享 + +rightside: + readmode_title: 閱讀模式 + translate_title: 繁簡轉換 + night_mode_title: 日夜模式切換 + back_to_top: 回到頂端 + toc: 目錄 + scroll_to_comment: 前往評論 + setting: 設定 + aside: 單欄和雙欄切換 + chat: 聊天 + +copy_copyright: + author: 作者 + link: 連結 + source: 來源 + info: 著作權歸作者所有。如需商業轉載,請聯絡作者獲得授權,非商業轉載請註明出處。 + +Snackbar: + chs_to_cht: 已切換為繁體中文 + cht_to_chs: 已切換為簡體中文 + day_to_night: 已切換為深色模式 + night_to_day: 已切換為淺色模式 + +loading: 載入中... +load_more: 載入更多 + +error404: 找不到頁面 diff --git a/layout/archive.pug b/layout/archive.pug index 913dedc..31a1b50 100644 --- a/layout/archive.pug +++ b/layout/archive.pug @@ -1,8 +1,8 @@ -extends includes/layout.pug - -block content - include ./includes/mixins/article-sort.pug - #archive - .article-sort-title= `${_p('page.articles')} - ${getArchiveLength()}` - +articleSort(page.posts) +extends includes/layout.pug + +block content + include ./includes/mixins/article-sort.pug + #archive + .article-sort-title= `${_p('page.articles')} - ${getArchiveLength()}` + +articleSort(page.posts) include includes/pagination.pug \ No newline at end of file diff --git a/layout/category.pug b/layout/category.pug index 092be9a..cdc0295 100644 --- a/layout/category.pug +++ b/layout/category.pug @@ -1,12 +1,12 @@ -extends includes/layout.pug - -block content - if theme.category_ui == 'index' - include ./includes/mixins/indexPostUI.pug - +indexPostUI - else - include ./includes/mixins/article-sort.pug - #category - .article-sort-title= _p('page.category') + ' - ' + page.category - +articleSort(page.posts) +extends includes/layout.pug + +block content + if theme.category_ui == 'index' + include ./includes/mixins/indexPostUI.pug + +indexPostUI + else + include ./includes/mixins/article-sort.pug + #category + .article-sort-title= _p('page.category') + ' - ' + page.category + +articleSort(page.posts) include includes/pagination.pug \ No newline at end of file diff --git a/layout/includes/additional-js.pug b/layout/includes/additional-js.pug index b884ced..5312260 100644 --- a/layout/includes/additional-js.pug +++ b/layout/includes/additional-js.pug @@ -1,57 +1,57 @@ -div - script(src=url_for(theme.asset.utils)) - script(src=url_for(theme.asset.main)) - - if theme.translate.enable - script(src=url_for(theme.asset.translate)) - - if theme.lightbox - script(src=url_for(theme.asset[theme.lightbox])) - - if theme.instantpage - script(src=url_for(theme.asset.instantpage), type='module') - - if theme.lazyload.enable && !theme.lazyload.native - script(src=url_for(theme.asset.lazyload)) - - if theme.snackbar.enable - script(src=url_for(theme.asset.snackbar)) - - .js-pjax - if needLoadCountJs - != partial("includes/third-party/card-post-count/index", {}, { cache: true }) - - if loadSubJs - include ./third-party/subtitle.pug - - include ./third-party/math/index.pug - include ./third-party/abcjs/index.pug - - if commentsJsLoad - include ./third-party/comments/js.pug - - != partial("includes/third-party/prismjs", {}, { cache: true }) - - if theme.aside.enable && theme.aside.card_newest_comments.enable - if theme.pjax.enable || (globalPageType !== 'post' && page.aside !== false) - != partial("includes/third-party/newest-comments/index", {}, { cache: true }) - - != fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)}) - - != partial("includes/third-party/effect", {}, { cache: true }) - != partial("includes/third-party/chat/index", {}, { cache: true }) - - if theme.aplayerInject && theme.aplayerInject.enable - if theme.pjax.enable || theme.aplayerInject.per_page || page.aplayer - include ./third-party/aplayer.pug - - if theme.pjax.enable - != partial("includes/third-party/pjax", {}, { cache: true }) - - if theme.umami_analytics.enable - != partial("includes/third-party/umami_analytics", {}, { cache: true }) - - if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv - script(async data-pjax src= theme.asset.busuanzi || '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js') - +div + script(src=url_for(theme.asset.utils)) + script(src=url_for(theme.asset.main)) + + if theme.translate.enable + script(src=url_for(theme.asset.translate)) + + if theme.lightbox + script(src=url_for(theme.asset[theme.lightbox])) + + if theme.instantpage + script(src=url_for(theme.asset.instantpage), type='module') + + if theme.lazyload.enable && !theme.lazyload.native + script(src=url_for(theme.asset.lazyload)) + + if theme.snackbar.enable + script(src=url_for(theme.asset.snackbar)) + + .js-pjax + if needLoadCountJs + != partial("includes/third-party/card-post-count/index", {}, { cache: true }) + + if loadSubJs + include ./third-party/subtitle.pug + + include ./third-party/math/index.pug + include ./third-party/abcjs/index.pug + + if commentsJsLoad + include ./third-party/comments/js.pug + + != partial("includes/third-party/prismjs", {}, { cache: true }) + + if theme.aside.enable && theme.aside.card_newest_comments.enable + if theme.pjax.enable || (globalPageType !== 'post' && page.aside !== false) + != partial("includes/third-party/newest-comments/index", {}, { cache: true }) + + != fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)}) + + != partial("includes/third-party/effect", {}, { cache: true }) + != partial("includes/third-party/chat/index", {}, { cache: true }) + + if theme.aplayerInject && theme.aplayerInject.enable + if theme.pjax.enable || theme.aplayerInject.per_page || page.aplayer + include ./third-party/aplayer.pug + + if theme.pjax.enable + != partial("includes/third-party/pjax", {}, { cache: true }) + + if theme.umami_analytics.enable + != partial("includes/third-party/umami_analytics", {}, { cache: true }) + + if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv + script(async data-pjax src= theme.asset.busuanzi || '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js') + != partial('includes/third-party/search/index', {}, { cache: true }) \ No newline at end of file diff --git a/layout/includes/footer.pug b/layout/includes/footer.pug index f6c3e87..0f3dbe3 100644 --- a/layout/includes/footer.pug +++ b/layout/includes/footer.pug @@ -1,18 +1,19 @@ -#footer-wrap - if theme.footer.owner.enable - - const currentYear = new Date().getFullYear() - - const sinceYear = theme.footer.owner.since - .copyright - if sinceYear && sinceYear != currentYear - != `©${sinceYear} - ${currentYear} By ${config.author}` - else - != `©${currentYear} By ${config.author}` - if theme.footer.copyright - .framework-info - span= _p('footer.framework') + ' ' - a(href='https://hexo.io')= 'Hexo' - span.footer-separator | - span= _p('footer.theme') + ' ' - a(href='https://github.com/jerryc127/hexo-theme-butterfly')= 'Butterfly' - if theme.footer.custom_text +#footer-wrap + if theme.footer.owner.enable + - const currentYear = new Date().getFullYear() + - const sinceYear = theme.footer.owner.since + .copyright + if sinceYear && sinceYear != currentYear + != `©${sinceYear} - ${currentYear} By ${config.author}` + else + != `©${currentYear} By ${config.author}` + if theme.footer.copyright + - const v = getVersion() + .framework-info + span= _p('footer.framework') + ' ' + a(href='https://hexo.io')= `Hexo ${v.hexo}` + span.footer-separator | + span= _p('footer.theme') + ' ' + a(href='https://github.com/jerryc127/hexo-theme-butterfly')= `Butterfly ${v.theme}` + if theme.footer.custom_text .footer_custom_text!= theme.footer.custom_text \ No newline at end of file diff --git a/layout/includes/head.pug b/layout/includes/head.pug index 3e77573..447199b 100644 --- a/layout/includes/head.pug +++ b/layout/includes/head.pug @@ -1,77 +1,77 @@ -- var pageTitle -- globalPageType === 'archive' ? page.title = findArchivesTitle(page, theme.menu, date) : '' -case globalPageType - when 'tag' - - pageTitle = _p('page.tag') + ': ' + page.tag - when 'category' - - pageTitle = _p('page.category') + ': ' + page.category - when '404' - - pageTitle = _p('error404') - default - - pageTitle = page.title || config.title || '' - - -- var isSubtitle = config.subtitle ? ' - ' + config.subtitle : '' -- var tabTitle = globalPageType === 'home' || !pageTitle ? config.title + isSubtitle : pageTitle + ' | ' + config.title -- var pageAuthor = config.email ? config.author + ',' + config.email : config.author -- var pageCopyright = config.copyright || config.author -- var themeColorLight = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_light || '#ffffff' -- var themeColorDark = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_dark || '#0d0d0d' -- var themeColor = theme.display_mode === 'dark' ? themeColorDark : themeColorLight - -meta(charset='UTF-8') -meta(http-equiv="X-UA-Compatible" content="IE=edge") -meta(name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover") -title= tabTitle -meta(name="author" content=pageAuthor) -meta(name="copyright" content=pageCopyright) -meta(name ="format-detection" content="telephone=no") -meta(name="theme-color" content=themeColor) - -//- Open_Graph -include ./head/Open_Graph.pug - -//- Structured Data -include ./head/structured_data.pug - -!=favicon_tag(theme.favicon || config.favicon) -link(rel="canonical" href=urlNoIndex(null,config.pretty_urls.trailing_index,config.pretty_urls.trailing_html)) - -//- 預解析 -!=partial('includes/head/preconnect', {}, {cache: true}) - -//- 網站驗證 -!=partial('includes/head/site_verification', {}, {cache: true}) - -//- PWA -if (theme.pwa && theme.pwa.enable) - !=partial('includes/head/pwa', {}, {cache: true}) - -//- main css -link(rel='stylesheet', href=url_for(theme.asset.main_css)) -link(rel='stylesheet', href=url_for(theme.asset.fontawesome)) - -if (theme.snackbar && theme.snackbar.enable) - link(rel='stylesheet', href=url_for(theme.asset.snackbar_css) media="print" onload="this.media='all'") - -if theme.lightbox === 'fancybox' - link(rel='stylesheet' href=url_for(theme.asset.fancybox_css) media="print" onload="this.media='all'") - -!=fragment_cache('injectHeadJs', function(){return inject_head_js()}) - -//- google_adsense -!=partial('includes/head/google_adsense', {}, {cache: true}) - -//- analytics -!=partial('includes/head/analytics', {}, {cache: true}) - -//- font -if theme.blog_title_font && theme.blog_title_font.font_link - link(rel='stylesheet' href=url_for(theme.blog_title_font.font_link) media="print" onload="this.media='all'") - -//- global config -!=partial('includes/head/config', {}, {cache: true}) - -include ./head/config_site.pug - -!=fragment_cache('injectHead', function(){return injectHtml(theme.inject.head)}) +- var pageTitle +- globalPageType === 'archive' ? page.title = findArchivesTitle(page, theme.menu, date) : '' +case globalPageType + when 'tag' + - pageTitle = _p('page.tag') + ': ' + page.tag + when 'category' + - pageTitle = _p('page.category') + ': ' + page.category + when '404' + - pageTitle = _p('error404') + default + - pageTitle = page.title || config.title || '' + + +- var isSubtitle = config.subtitle ? ' - ' + config.subtitle : '' +- var tabTitle = globalPageType === 'home' || !pageTitle ? config.title + isSubtitle : pageTitle + ' | ' + config.title +- var pageAuthor = config.email ? config.author + ',' + config.email : config.author +- var pageCopyright = config.copyright || config.author +- var themeColorLight = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_light || '#ffffff' +- var themeColorDark = theme.theme_color && theme.theme_color.enable && theme.theme_color.meta_theme_color_dark || '#0d0d0d' +- var themeColor = theme.display_mode === 'dark' ? themeColorDark : themeColorLight + +meta(charset='UTF-8') +meta(http-equiv="X-UA-Compatible" content="IE=edge") +meta(name="viewport" content="width=device-width, initial-scale=1.0,viewport-fit=cover") +title= tabTitle +meta(name="author" content=pageAuthor) +meta(name="copyright" content=pageCopyright) +meta(name ="format-detection" content="telephone=no") +meta(name="theme-color" content=themeColor) + +//- Open_Graph +include ./head/Open_Graph.pug + +//- Structured Data +include ./head/structured_data.pug + +!=favicon_tag(theme.favicon || config.favicon) +link(rel="canonical" href=urlNoIndex(null,config.pretty_urls.trailing_index,config.pretty_urls.trailing_html)) + +//- 預解析 +!=partial('includes/head/preconnect', {}, {cache: true}) + +//- 網站驗證 +!=partial('includes/head/site_verification', {}, {cache: true}) + +//- PWA +if (theme.pwa && theme.pwa.enable) + !=partial('includes/head/pwa', {}, {cache: true}) + +//- main css +link(rel='stylesheet', href=url_for(theme.asset.main_css)) +link(rel='stylesheet', href=url_for(theme.asset.fontawesome)) + +if (theme.snackbar && theme.snackbar.enable) + link(rel='stylesheet', href=url_for(theme.asset.snackbar_css) media="print" onload="this.media='all'") + +if theme.lightbox === 'fancybox' + link(rel='stylesheet' href=url_for(theme.asset.fancybox_css) media="print" onload="this.media='all'") + +!=fragment_cache('injectHeadJs', function(){return inject_head_js()}) + +//- google_adsense +!=partial('includes/head/google_adsense', {}, {cache: true}) + +//- analytics +!=partial('includes/head/analytics', {}, {cache: true}) + +//- font +if theme.blog_title_font && theme.blog_title_font.font_link + link(rel='stylesheet' href=url_for(theme.blog_title_font.font_link) media="print" onload="this.media='all'") + +//- global config +!=partial('includes/head/config', {}, {cache: true}) + +include ./head/config_site.pug + +!=fragment_cache('injectHead', function(){return injectHtml(theme.inject.head)}) diff --git a/layout/includes/head/Open_Graph.pug b/layout/includes/head/Open_Graph.pug index b3628d0..d353f3e 100644 --- a/layout/includes/head/Open_Graph.pug +++ b/layout/includes/head/Open_Graph.pug @@ -1,16 +1,16 @@ -if theme.Open_Graph_meta.enable - - - const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img - let ogOption = Object.assign({ - type: globalPageType === 'post' ? 'article' : 'website', - image: coverVal ? full_url_for(coverVal) : '', - fb_admins: theme.facebook_comments.user_id || '', - fb_app_id: theme.facebook_comments.app_id || '', - }, theme.Open_Graph_meta.option) - - - != open_graph(ogOption) -else - - const description = page.description || page.content || page.title || config.description - if description - meta(name="description" content=truncate(description, 150)) - +if theme.Open_Graph_meta.enable + - + const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img + let ogOption = Object.assign({ + type: globalPageType === 'post' ? 'article' : 'website', + image: coverVal ? full_url_for(coverVal) : '', + fb_admins: theme.facebook_comments.user_id || '', + fb_app_id: theme.facebook_comments.app_id || '', + }, theme.Open_Graph_meta.option) + - + != open_graph(ogOption) +else + - const description = page.description || page.content || page.title || config.description + if description + meta(name="description" content=truncate(description, 150)) + diff --git a/layout/includes/head/analytics.pug b/layout/includes/head/analytics.pug index d75145d..e6aa621 100644 --- a/layout/includes/head/analytics.pug +++ b/layout/includes/head/analytics.pug @@ -1,34 +1,34 @@ -if theme.baidu_analytics - script. - var _hmt = _hmt || []; - (function() { - var hm = document.createElement("script"); - hm.src = "https://hm.baidu.com/hm.js?!{theme.baidu_analytics}"; - var s = document.getElementsByTagName("script")[0]; - s.parentNode.insertBefore(hm, s); - })(); - btf.addGlobalFn('pjaxComplete', () => { - _hmt.push(['_trackPageview',window.location.pathname]) - }, 'baidu_analytics') - -if theme.google_analytics - script(async src=`https://www.googletagmanager.com/gtag/js?id=${theme.google_analytics}`) - script. - window.dataLayer = window.dataLayer || [] - function gtag(){dataLayer.push(arguments)} - gtag('js', new Date()) - gtag('config', '!{theme.google_analytics}') - btf.addGlobalFn('pjaxComplete', () => { - gtag('config', '!{theme.google_analytics}', {'page_path': window.location.pathname}) - }, 'google_analytics') - -if theme.cloudflare_analytics - script(defer data-pjax src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon=`{"token": "${theme.cloudflare_analytics}"}`) - -if theme.microsoft_clarity - script. - (function(c,l,a,r,i,t,y){ - c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; - t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; - y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); +if theme.baidu_analytics + script. + var _hmt = _hmt || []; + (function() { + var hm = document.createElement("script"); + hm.src = "https://hm.baidu.com/hm.js?!{theme.baidu_analytics}"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(hm, s); + })(); + btf.addGlobalFn('pjaxComplete', () => { + _hmt.push(['_trackPageview',window.location.pathname]) + }, 'baidu_analytics') + +if theme.google_analytics + script(async src=`https://www.googletagmanager.com/gtag/js?id=${theme.google_analytics}`) + script. + window.dataLayer = window.dataLayer || [] + function gtag(){dataLayer.push(arguments)} + gtag('js', new Date()) + gtag('config', '!{theme.google_analytics}') + btf.addGlobalFn('pjaxComplete', () => { + gtag('config', '!{theme.google_analytics}', {'page_path': window.location.pathname}) + }, 'google_analytics') + +if theme.cloudflare_analytics + script(defer data-pjax src='https://static.cloudflareinsights.com/beacon.min.js' data-cf-beacon=`{"token": "${theme.cloudflare_analytics}"}`) + +if theme.microsoft_clarity + script. + (function(c,l,a,r,i,t,y){ + c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)}; + t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; + y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y); })(window, document, "clarity", "script", "!{theme.microsoft_clarity}"); \ No newline at end of file diff --git a/layout/includes/head/config.pug b/layout/includes/head/config.pug index efa3654..b50ecfe 100644 --- a/layout/includes/head/config.pug +++ b/layout/includes/head/config.pug @@ -1,126 +1,126 @@ -- - let algolia = 'undefined' - if (theme.search.use === 'algolia_search') { - const { ALGOLIA_APP_ID, ALGOLIA_API_KEY, ALGOLIA_INDEX_NAME } = process.env - const { appId, applicationID, apiKey, indexName } = config.algolia - algolia = JSON.stringify({ - appId: ALGOLIA_APP_ID || appId || applicationID, - apiKey: ALGOLIA_API_KEY || apiKey, - indexName: ALGOLIA_INDEX_NAME || indexName, - hitsPerPage: theme.search.algolia_search.hitsPerPage, - // search languages - languages: { - input_placeholder: theme.search.placeholder || _p("search.input_placeholder"), - hits_empty: _p("search.algolia_search.hits_empty"), - hits_stats: _p("search.algolia_search.hits_stats"), - } - }) - } - - let localSearch = 'undefined' - if (theme.search.use === 'local_search') { - const { CDN, preload, top_n_per_article, unescape } = theme.search.local_search - localSearch = JSON.stringify({ - path: CDN || config.root + config.search.path, - preload, - top_n_per_article, - unescape, - languages: { - // search languages - hits_empty: _p("search.local_search.hits_empty"), - hits_stats: _p("search.local_search.hits_stats"), - } - }) - } - - let translate = 'undefined' - if (theme.translate && theme.translate.enable){ - translate = JSON.stringify({ - defaultEncoding: theme.translate.defaultEncoding, - translateDelay: theme.translate.translateDelay, - msgToTraditionalChinese: theme.translate.msgToTraditionalChinese, - msgToSimplifiedChinese: theme.translate.msgToSimplifiedChinese - }) - } - - let copyright = 'undefined' - if (theme.copy.enable && theme.copy.copyright.enable){ - copyright = JSON.stringify({ - limitCount: theme.copy.copyright.limit_count, - languages: { - author: _p("copy_copyright.author") + ': ' + config.author, - link: _p("copy_copyright.link") + ': ', - source: _p("copy_copyright.source") + ': ' + config.title, - info: _p("copy_copyright.info") - } - }) - } - - let Snackbar = 'undefined' - if (theme.snackbar && theme.snackbar.enable) { - Snackbar = JSON.stringify({ - chs_to_cht: _p("Snackbar.chs_to_cht"), - cht_to_chs: _p("Snackbar.cht_to_chs"), - day_to_night: _p("Snackbar.day_to_night"), - night_to_day: _p("Snackbar.night_to_day"), - bgLight: theme.snackbar.bg_light, - bgDark: theme.snackbar.bg_dark, - position: theme.snackbar.position, - }) - } - - let highlight = 'undefined' - let syntaxHighlighter = config.syntax_highlighter - let highlightEnable = syntaxHighlighter ? ['highlight.js', 'prismjs'].includes(syntaxHighlighter) : (config.highlight.enable || config.prismjs.enable) - if (highlightEnable) { - const { copy, language, height_limit, fullpage, macStyle } = theme.code_blocks - highlight = JSON.stringify({ - plugin: syntaxHighlighter ? syntaxHighlighter : config.highlight.enable ? 'highlight.js' : 'prismjs', - highlightCopy: copy, - highlightLang: language, - highlightHeightLimit: height_limit, - highlightFullpage: fullpage, - highlightMacStyle: macStyle - }) - } - -script. - const GLOBAL_CONFIG = { - root: '!{config.root}', - algolia: !{algolia}, - localSearch: !{localSearch}, - translate: !{translate}, - highlight: !{highlight}, - copy: { - success: '!{_p("copy.success")}', - error: '!{_p("copy.error")}', - noSupport: '!{_p("copy.noSupport")}' - }, - relativeDate: { - homepage: !{theme.post_meta.page.date_format === 'relative'}, - post: !{theme.post_meta.post.date_format === 'relative'} - }, - runtime: '!{theme.aside.card_webinfo.runtime_date ? _p("aside.card_webinfo.runtime.unit") : ""}', - dateSuffix: { - just: '!{_p("date_suffix.just")}', - min: '!{_p("date_suffix.min")}', - hour: '!{_p("date_suffix.hour")}', - day: '!{_p("date_suffix.day")}', - month: '!{_p("date_suffix.month")}' - }, - copyright: !{copyright}, - lightbox: '!{ theme.lightbox || 'null' }', - Snackbar: !{Snackbar}, - infinitegrid: { - js: '!{url_for(theme.asset.egjs_infinitegrid)}', - buttonText: '!{_p("load_more")}' - }, - isPhotoFigcaption: !{theme.photofigcaption}, - islazyloadPlugin: !{theme.lazyload.enable && !theme.lazyload.native}, - isAnchor: !{theme.anchor.auto_update || false}, - percent: { - toc: !{theme.toc.scroll_percent}, - rightside: !{theme.rightside_scroll_percent}, - }, - autoDarkmode: !{theme.darkmode.enable && theme.darkmode.autoChangeMode === 1} - } +- + let algolia = 'undefined' + if (theme.search.use === 'algolia_search') { + const { ALGOLIA_APP_ID, ALGOLIA_API_KEY, ALGOLIA_INDEX_NAME } = process.env + const { appId, applicationID, apiKey, indexName } = config.algolia + algolia = JSON.stringify({ + appId: ALGOLIA_APP_ID || appId || applicationID, + apiKey: ALGOLIA_API_KEY || apiKey, + indexName: ALGOLIA_INDEX_NAME || indexName, + hitsPerPage: theme.search.algolia_search.hitsPerPage, + // search languages + languages: { + input_placeholder: theme.search.placeholder || _p("search.input_placeholder"), + hits_empty: _p("search.algolia_search.hits_empty"), + hits_stats: _p("search.algolia_search.hits_stats"), + } + }) + } + + let localSearch = 'undefined' + if (theme.search.use === 'local_search') { + const { CDN, preload, top_n_per_article, unescape } = theme.search.local_search + localSearch = JSON.stringify({ + path: CDN || config.root + config.search.path, + preload, + top_n_per_article, + unescape, + languages: { + // search languages + hits_empty: _p("search.local_search.hits_empty"), + hits_stats: _p("search.local_search.hits_stats"), + } + }) + } + + let translate = 'undefined' + if (theme.translate && theme.translate.enable){ + translate = JSON.stringify({ + defaultEncoding: theme.translate.defaultEncoding, + translateDelay: theme.translate.translateDelay, + msgToTraditionalChinese: theme.translate.msgToTraditionalChinese, + msgToSimplifiedChinese: theme.translate.msgToSimplifiedChinese + }) + } + + let copyright = 'undefined' + if (theme.copy.enable && theme.copy.copyright.enable){ + copyright = JSON.stringify({ + limitCount: theme.copy.copyright.limit_count, + languages: { + author: _p("copy_copyright.author") + ': ' + config.author, + link: _p("copy_copyright.link") + ': ', + source: _p("copy_copyright.source") + ': ' + config.title, + info: _p("copy_copyright.info") + } + }) + } + + let Snackbar = 'undefined' + if (theme.snackbar && theme.snackbar.enable) { + Snackbar = JSON.stringify({ + chs_to_cht: _p("Snackbar.chs_to_cht"), + cht_to_chs: _p("Snackbar.cht_to_chs"), + day_to_night: _p("Snackbar.day_to_night"), + night_to_day: _p("Snackbar.night_to_day"), + bgLight: theme.snackbar.bg_light, + bgDark: theme.snackbar.bg_dark, + position: theme.snackbar.position, + }) + } + + let highlight = 'undefined' + let syntaxHighlighter = config.syntax_highlighter + let highlightEnable = syntaxHighlighter ? ['highlight.js', 'prismjs'].includes(syntaxHighlighter) : (config.highlight.enable || config.prismjs.enable) + if (highlightEnable) { + const { copy, language, height_limit, fullpage, macStyle } = theme.code_blocks + highlight = JSON.stringify({ + plugin: syntaxHighlighter ? syntaxHighlighter : config.highlight.enable ? 'highlight.js' : 'prismjs', + highlightCopy: copy, + highlightLang: language, + highlightHeightLimit: height_limit, + highlightFullpage: fullpage, + highlightMacStyle: macStyle + }) + } + +script. + const GLOBAL_CONFIG = { + root: '!{config.root}', + algolia: !{algolia}, + localSearch: !{localSearch}, + translate: !{translate}, + highlight: !{highlight}, + copy: { + success: '!{_p("copy.success")}', + error: '!{_p("copy.error")}', + noSupport: '!{_p("copy.noSupport")}' + }, + relativeDate: { + homepage: !{theme.post_meta.page.date_format === 'relative'}, + post: !{theme.post_meta.post.date_format === 'relative'} + }, + runtime: '!{theme.aside.card_webinfo.runtime_date ? _p("aside.card_webinfo.runtime.unit") : ""}', + dateSuffix: { + just: '!{_p("date_suffix.just")}', + min: '!{_p("date_suffix.min")}', + hour: '!{_p("date_suffix.hour")}', + day: '!{_p("date_suffix.day")}', + month: '!{_p("date_suffix.month")}' + }, + copyright: !{copyright}, + lightbox: '!{ theme.lightbox || 'null' }', + Snackbar: !{Snackbar}, + infinitegrid: { + js: '!{url_for(theme.asset.egjs_infinitegrid)}', + buttonText: '!{_p("load_more")}' + }, + isPhotoFigcaption: !{theme.photofigcaption}, + islazyloadPlugin: !{theme.lazyload.enable && !theme.lazyload.native}, + isAnchor: !{theme.anchor.auto_update || false}, + percent: { + toc: !{theme.toc.scroll_percent}, + rightside: !{theme.rightside_scroll_percent}, + }, + autoDarkmode: !{theme.darkmode.enable && theme.darkmode.autoChangeMode === 1} + } diff --git a/layout/includes/head/config_site.pug b/layout/includes/head/config_site.pug index 5c1c67d..8f8d3b6 100644 --- a/layout/includes/head/config_site.pug +++ b/layout/includes/head/config_site.pug @@ -1,25 +1,25 @@ -- - const titleVal = pageTitle.replace(/'/ig,"\\'") - - let isHighlightShrink - if (theme.code_blocks.shrink == 'none') isHighlightShrink = 'undefined' - else if (typeof page.highlight_shrink == 'boolean') isHighlightShrink = page.highlight_shrink - else isHighlightShrink = theme.code_blocks.shrink - - var showToc = false - if (theme.aside.enable && page.aside !== false) { - let tocEnable = false - if (globalPageType === 'post' && theme.toc.post) tocEnable = true - else if (globalPageType === 'page' && theme.toc.page) tocEnable = true - const pageToc = typeof page.toc === 'boolean' ? page.toc : tocEnable - showToc = pageToc && (toc(page.content) !== '' || page.encrypt === true) - } -- - -script#config-diff. - var GLOBAL_CONFIG_SITE = { - title: '!{titleVal}', - isHighlightShrink: !{isHighlightShrink}, - isToc: !{showToc}, - pageType: '!{page.type == 'shuoshuo' ? 'shuoshuo' : globalPageType}' - } +- + const titleVal = pageTitle.replace(/'/ig,"\\'") + + let isHighlightShrink + if (theme.code_blocks.shrink == 'none') isHighlightShrink = 'undefined' + else if (typeof page.highlight_shrink == 'boolean') isHighlightShrink = page.highlight_shrink + else isHighlightShrink = theme.code_blocks.shrink + + var showToc = false + if (theme.aside.enable && page.aside !== false) { + let tocEnable = false + if (globalPageType === 'post' && theme.toc.post) tocEnable = true + else if (globalPageType === 'page' && theme.toc.page) tocEnable = true + const pageToc = typeof page.toc === 'boolean' ? page.toc : tocEnable + showToc = pageToc && (toc(page.content) !== '' || page.encrypt === true) + } +- + +script#config-diff. + var GLOBAL_CONFIG_SITE = { + title: '!{titleVal}', + isHighlightShrink: !{isHighlightShrink}, + isToc: !{showToc}, + pageType: '!{page.type == 'shuoshuo' ? 'shuoshuo' : globalPageType}' + } diff --git a/layout/includes/head/google_adsense.pug b/layout/includes/head/google_adsense.pug index 3ef1af9..f4dac01 100644 --- a/layout/includes/head/google_adsense.pug +++ b/layout/includes/head/google_adsense.pug @@ -1,9 +1,9 @@ -if (theme.google_adsense && theme.google_adsense.enable) - script(async src=theme.google_adsense.js) - - if theme.google_adsense.auto_ads - script. - (adsbygoogle = window.adsbygoogle || []).push({ - google_ad_client: '!{theme.google_adsense.client}', - enable_page_level_ads: '!{theme.google_adsense.enable_page_level_ads}' +if (theme.google_adsense && theme.google_adsense.enable) + script(async src=theme.google_adsense.js) + + if theme.google_adsense.auto_ads + script. + (adsbygoogle = window.adsbygoogle || []).push({ + google_ad_client: '!{theme.google_adsense.client}', + enable_page_level_ads: '!{theme.google_adsense.enable_page_level_ads}' }); \ No newline at end of file diff --git a/layout/includes/head/preconnect.pug b/layout/includes/head/preconnect.pug index cefe9fc..25bda87 100644 --- a/layout/includes/head/preconnect.pug +++ b/layout/includes/head/preconnect.pug @@ -1,35 +1,35 @@ -- - const { internal_provider, third_party_provider, custom_format } = theme.CDN - const providers = { - 'jsdelivr': '//cdn.jsdelivr.net', - 'cdnjs': '//cdnjs.cloudflare.com', - 'unpkg': '//unpkg.com', - 'custom': custom_format && custom_format.match(/^((https?:)?(\/\/[^/]+)|([^/]+))(\/|$)/)[1] - } -- - -if internal_provider === third_party_provider && internal_provider !== 'local' - link(rel="preconnect" href=providers[internal_provider]) -else - if internal_provider !== 'local' - link(rel="preconnect" href=providers[internal_provider]) - if third_party_provider !== 'local' - link(rel="preconnect" href=providers[third_party_provider]) - -if theme.google_analytics - link(rel="preconnect" href="//www.google-analytics.com" crossorigin='') - -if theme.baidu_analytics - link(rel="preconnect" href="//hm.baidu.com") - -if theme.cloudflare_analytics - link(rel="preconnect" href="//static.cloudflareinsights.com") - -if theme.microsoft_clarity - link(rel="preconnect" href="//www.clarity.ms") - -if theme.blog_title_font && theme.blog_title_font.font_link && theme.blog_title_font.font_link.indexOf('//fonts.googleapis.com') != -1 - link(rel="preconnect" href="//fonts.googleapis.com" crossorigin='') - -if !theme.asset.busuanzi && (theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv) +- + const { internal_provider, third_party_provider, custom_format } = theme.CDN + const providers = { + 'jsdelivr': '//cdn.jsdelivr.net', + 'cdnjs': '//cdnjs.cloudflare.com', + 'unpkg': '//unpkg.com', + 'custom': custom_format && custom_format.match(/^((https?:)?(\/\/[^/]+)|([^/]+))(\/|$)/)[1] + } +- + +if internal_provider === third_party_provider && internal_provider !== 'local' + link(rel="preconnect" href=providers[internal_provider]) +else + if internal_provider !== 'local' + link(rel="preconnect" href=providers[internal_provider]) + if third_party_provider !== 'local' + link(rel="preconnect" href=providers[third_party_provider]) + +if theme.google_analytics + link(rel="preconnect" href="//www.google-analytics.com" crossorigin='') + +if theme.baidu_analytics + link(rel="preconnect" href="//hm.baidu.com") + +if theme.cloudflare_analytics + link(rel="preconnect" href="//static.cloudflareinsights.com") + +if theme.microsoft_clarity + link(rel="preconnect" href="//www.clarity.ms") + +if theme.blog_title_font && theme.blog_title_font.font_link && theme.blog_title_font.font_link.indexOf('//fonts.googleapis.com') != -1 + link(rel="preconnect" href="//fonts.googleapis.com" crossorigin='') + +if !theme.asset.busuanzi && (theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv) link(rel="preconnect" href="//busuanzi.ibruce.info") \ No newline at end of file diff --git a/layout/includes/head/pwa.pug b/layout/includes/head/pwa.pug index 816026a..13703fb 100644 --- a/layout/includes/head/pwa.pug +++ b/layout/includes/head/pwa.pug @@ -1,13 +1,13 @@ -- const { manifest, theme_color, apple_touch_icon, favicon_32_32, favicon_16_16, mask_icon } = theme.pwa - -link(rel="manifest" href=url_for(manifest)) -if theme_color - meta(name="msapplication-TileColor" content=theme_color) -if apple_touch_icon - link(rel="apple-touch-icon" sizes="180x180" href=url_for(apple_touch_icon)) -if favicon_32_32 - link(rel="icon" type="image/png" sizes="32x32" href=url_for(favicon_32_32)) -if favicon_16_16 - link(rel="icon" type="image/png" sizes="16x16" href=url_for(favicon_16_16)) -if mask_icon - link(rel="mask-icon" href=url_for(mask_icon) color="#5bbad5") +- const { manifest, theme_color, apple_touch_icon, favicon_32_32, favicon_16_16, mask_icon } = theme.pwa + +link(rel="manifest" href=url_for(manifest)) +if theme_color + meta(name="msapplication-TileColor" content=theme_color) +if apple_touch_icon + link(rel="apple-touch-icon" sizes="180x180" href=url_for(apple_touch_icon)) +if favicon_32_32 + link(rel="icon" type="image/png" sizes="32x32" href=url_for(favicon_32_32)) +if favicon_16_16 + link(rel="icon" type="image/png" sizes="16x16" href=url_for(favicon_16_16)) +if mask_icon + link(rel="mask-icon" href=url_for(mask_icon) color="#5bbad5") diff --git a/layout/includes/head/site_verification.pug b/layout/includes/head/site_verification.pug index 8947644..9130030 100644 --- a/layout/includes/head/site_verification.pug +++ b/layout/includes/head/site_verification.pug @@ -1,3 +1,3 @@ -if theme.site_verification - each item in theme.site_verification +if theme.site_verification + each item in theme.site_verification meta(name=item.name content=item.content) \ No newline at end of file diff --git a/layout/includes/header/index.pug b/layout/includes/header/index.pug index 481db70..fa39f5c 100644 --- a/layout/includes/header/index.pug +++ b/layout/includes/header/index.pug @@ -1,52 +1,52 @@ -- - const returnTopImg = img => img !== false ? img || theme.default_top_img : false - const isFixedClass = theme.nav.fixed ? ' fixed' : '' - var top_img = false - let headerClassName = 'not-top-img' - var bg_img = '' - -if !theme.disable_top_img && page.top_img !== false - case globalPageType - when 'post' - - top_img = page.top_img || page.cover || theme.default_top_img - when 'page' - - top_img = page.top_img || theme.default_top_img - when 'tag' - - top_img = theme.tag_per_img && theme.tag_per_img[page.tag] || returnTopImg(theme.tag_img) - when 'category' - - top_img = theme.category_per_img && theme.category_per_img[page.category] || returnTopImg(theme.category_img) - when 'home' - - top_img = returnTopImg(theme.index_img) - when 'archive' - - top_img = returnTopImg(theme.archive_img) - default - - top_img = page.top_img || theme.default_top_img - - if top_img !== false - - bg_img = getBgPath(top_img) - - headerClassName = globalPageType === 'home' ? 'full_page' : globalPageType === 'post' ? 'post-bg' : 'not-home-page' - -header#page-header(class=`${headerClassName + isFixedClass}` style=bg_img) - include ./nav.pug - if top_img !== false - if globalPageType === 'post' - include ./post-info.pug - else if globalPageType === 'home' - #site-info - h1#site-title=config.title - if theme.subtitle.enable - - var loadSubJs = true - #site-subtitle - span#subtitle - if theme.social - #site_social_icons - !=partial('includes/header/social', {}, {cache: true}) - #scroll-down - i.fas.fa-angle-down.scroll-down-effects - else - #page-site-info - h1#site-title=page.title || page.tag || page.category - else - //- improve seo - if globalPageType !== 'post' +- + const returnTopImg = img => img !== false ? img || theme.default_top_img : false + const isFixedClass = theme.nav.fixed ? ' fixed' : '' + var top_img = false + let headerClassName = 'not-top-img' + var bg_img = '' + +if !theme.disable_top_img && page.top_img !== false + case globalPageType + when 'post' + - top_img = page.top_img || page.cover || theme.default_top_img + when 'page' + - top_img = page.top_img || theme.default_top_img + when 'tag' + - top_img = theme.tag_per_img && theme.tag_per_img[page.tag] || returnTopImg(theme.tag_img) + when 'category' + - top_img = theme.category_per_img && theme.category_per_img[page.category] || returnTopImg(theme.category_img) + when 'home' + - top_img = returnTopImg(theme.index_img) + when 'archive' + - top_img = returnTopImg(theme.archive_img) + default + - top_img = page.top_img || theme.default_top_img + + if top_img !== false + - bg_img = getBgPath(top_img) + - headerClassName = globalPageType === 'home' ? 'full_page' : globalPageType === 'post' ? 'post-bg' : 'not-home-page' + +header#page-header(class=`${headerClassName + isFixedClass}` style=bg_img) + include ./nav.pug + if top_img !== false + if globalPageType === 'post' + include ./post-info.pug + else if globalPageType === 'home' + #site-info + h1#site-title=config.title + if theme.subtitle.enable + - var loadSubJs = true + #site-subtitle + span#subtitle + if theme.social + #site_social_icons + !=partial('includes/header/social', {}, {cache: true}) + #scroll-down + i.fas.fa-angle-down.scroll-down-effects + else + #page-site-info + h1#site-title=page.title || page.tag || page.category + else + //- improve seo + if globalPageType !== 'post' h1.title-seo=page.title || page.tag || page.category || config.title \ No newline at end of file diff --git a/layout/includes/header/menu_item.pug b/layout/includes/header/menu_item.pug index 6302ee4..4b0590c 100644 --- a/layout/includes/header/menu_item.pug +++ b/layout/includes/header/menu_item.pug @@ -1,27 +1,27 @@ -if theme.menu - .menus_items - each value, label in theme.menu - if typeof value !== 'object' - .menus_item - - const [link, icon] = value.split('||').map(part => trim(part)) - a.site-page(href=url_for(link)) - if icon - i.fa-fw(class=icon) - span= ' ' + label - else - .menus_item - - const [groupLabel, groupIcon, groupClass] = label.split('||').map(part => trim(part)) - - const hideClass = groupClass === 'hide' ? 'hide' : '' - span.site-page.group(class=hideClass) - if groupIcon - i.fa-fw(class=groupIcon) - span= ' ' + groupLabel - i.fas.fa-chevron-down - ul.menus_item_child - each val, lab in value - - const [childLink, childIcon] = val.split('||').map(part => trim(part)) - li - a.site-page.child(href=url_for(childLink)) - if childIcon - i.fa-fw(class=childIcon) +if theme.menu + .menus_items + each value, label in theme.menu + if typeof value !== 'object' + .menus_item + - const [link, icon] = value.split('||').map(part => trim(part)) + a.site-page(href=url_for(link)) + if icon + i.fa-fw(class=icon) + span= ' ' + label + else + .menus_item + - const [groupLabel, groupIcon, groupClass] = label.split('||').map(part => trim(part)) + - const hideClass = groupClass === 'hide' ? 'hide' : '' + span.site-page.group(class=hideClass) + if groupIcon + i.fa-fw(class=groupIcon) + span= ' ' + groupLabel + i.fas.fa-chevron-down + ul.menus_item_child + each val, lab in value + - const [childLink, childIcon] = val.split('||').map(part => trim(part)) + li + a.site-page.child(href=url_for(childLink)) + if childIcon + i.fa-fw(class=childIcon) span= ' ' + lab \ No newline at end of file diff --git a/layout/includes/header/nav.pug b/layout/includes/header/nav.pug index 814a476..32fdf68 100644 --- a/layout/includes/header/nav.pug +++ b/layout/includes/header/nav.pug @@ -1,22 +1,22 @@ -nav#nav - span#blog-info - a.nav-site-title(href=url_for('/')) - if theme.nav.logo - img.site-icon(src=url_for(theme.nav.logo) alt='Logo') - if theme.nav.display_title - span.site-name=config.title - if globalPageType === 'post' - a.nav-page-title(href=url_for('/')) - span.site-name=(page.title || config.title) - #menus - if theme.search.use - #search-button - span.site-page.social-icon.search - i.fas.fa-search.fa-fw - span= ' ' + _p('search.title') - if theme.menu - != partial('includes/header/menu_item', {}, {cache: true}) - - #toggle-menu - span.site-page +nav#nav + span#blog-info + a.nav-site-title(href=url_for('/')) + if theme.nav.logo + img.site-icon(src=url_for(theme.nav.logo) alt='Logo') + if theme.nav.display_title + span.site-name=config.title + if globalPageType === 'post' + a.nav-page-title(href=url_for('/')) + span.site-name=(page.title || config.title) + #menus + if theme.search.use + #search-button + span.site-page.social-icon.search + i.fas.fa-search.fa-fw + span= ' ' + _p('search.title') + if theme.menu + != partial('includes/header/menu_item', {}, {cache: true}) + + #toggle-menu + span.site-page i.fas.fa-bars.fa-fw \ No newline at end of file diff --git a/layout/includes/header/post-info.pug b/layout/includes/header/post-info.pug index f346f83..2e5100c 100644 --- a/layout/includes/header/post-info.pug +++ b/layout/includes/header/post-info.pug @@ -1,149 +1,149 @@ -- let comments = theme.comments -#post-info - h1.post-title= page.title || _p('no_title') - if theme.post_edit.enable - a.post-edit-link(href=theme.post_edit.url + page.source title=_p('post.edit') target="_blank") - i.fas.fa-pencil-alt - - #post-meta - .meta-firstline - if theme.post_meta.post.date_type - span.post-meta-date - if theme.post_meta.post.date_type === 'both' - i.far.fa-calendar-alt.fa-fw.post-meta-icon - span.post-meta-label= _p('post.created') - time.post-meta-date-created(datetime=date_xml(page.date) title=_p('post.created') + ' ' + full_date(page.date))= date(page.date, config.date_format) - span.post-meta-separator | - i.fas.fa-history.fa-fw.post-meta-icon - span.post-meta-label= _p('post.updated') - time.post-meta-date-updated(datetime=date_xml(page.updated) title=_p('post.updated') + ' ' + full_date(page.updated))= date(page.updated, config.date_format) - else - - let data_type_update = theme.post_meta.post.date_type === 'updated' - - let date_type = data_type_update ? 'updated' : 'date' - - let date_icon = data_type_update ? 'fas fa-history' : 'far fa-calendar-alt' - - let date_title = data_type_update ? _p('post.updated') : _p('post.created') - i.fa-fw.post-meta-icon(class=date_icon) - span.post-meta-label= date_title - time(datetime=date_xml(page[date_type]) title=date_title + ' ' + full_date(page[date_type]))= date(page[date_type], config.date_format) - if theme.post_meta.post.categories && page.categories.data.length > 0 - span.post-meta-categories - if theme.post_meta.post.date_type - span.post-meta-separator | - each item, index in page.categories.data - i.fas.fa-inbox.fa-fw.post-meta-icon - a(href=url_for(item.path)).post-meta-categories #[=item.name] - if index < page.categories.data.length - 1 - i.fas.fa-angle-right.post-meta-separator - - .meta-secondline - - let postWordcount = theme.wordcount.enable && (theme.wordcount.post_wordcount || theme.wordcount.min2read) - if postWordcount - span.post-meta-separator | - span.post-meta-wordcount - if theme.wordcount.post_wordcount - i.far.fa-file-word.fa-fw.post-meta-icon - span.post-meta-label= _p('post.wordcount') + ':' - span.word-count= wordcount(page.content) - if theme.wordcount.min2read - span.post-meta-separator | - if theme.wordcount.min2read - i.far.fa-clock.fa-fw.post-meta-icon - span.post-meta-label= _p('post.min2read') + ':' - span= min2read(page.content, {cn: 350, en: 160}) + _p('post.min2read_unit') - - //- for pv and count - mixin pvBlock(parent_id, parent_class, parent_title) - span.post-meta-separator | - span(class=parent_class id=parent_id data-flag-title=parent_title) - i.far.fa-eye.fa-fw.post-meta-icon - span.post-meta-label= _p('post.page_pv') + ':' - if block - block - - mixin otherPV() - if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.page_pv - +pvBlock('', '', '') - span#umamiPV(data-path=url_for(page.path)) - i.fa-solid.fa-spinner.fa-spin - else if theme.busuanzi.page_pv - +pvBlock('', 'post-meta-pv-cv', '') - span#busuanzi_value_page_pv - i.fa-solid.fa-spinner.fa-spin - - - const commentUse = comments.use && comments.use[0] - if page.comments !== false && commentUse && !comments.lazyload - if commentUse === 'Valine' && theme.valine.visitor - +pvBlock(url_for(page.path), 'leancloud_visitors', page.title) - span.leancloud-visitors-count - i.fa-solid.fa-spinner.fa-spin - else if commentUse === 'Waline' && theme.waline.pageview - +pvBlock('', '', '') - span.waline-pageview-count(data-path=url_for(page.path)) - i.fa-solid.fa-spinner.fa-spin - else if commentUse === 'Twikoo' && theme.twikoo.visitor - +pvBlock('', '', '') - span#twikoo_visitors - i.fa-solid.fa-spinner.fa-spin - else if commentUse === 'Artalk' && theme.artalk.visitor - +pvBlock('', '', '') - span#ArtalkPV - i.fa-solid.fa-spinner.fa-spin - else - +otherPV() - else - +otherPV() - - if comments.count && !comments.lazyload && page.comments !== false && comments.use - - var whichCount = comments.use[0] - - mixin countBlock - span.post-meta-separator | - span.post-meta-commentcount - i.far.fa-comments.fa-fw.post-meta-icon - span.post-meta-label= _p('post.comments') + ':' - if block - block - - case whichCount - when 'Disqus' - +countBlock - a.disqus-comment-count(href=full_url_for(page.path) + '#post-comment') - i.fa-solid.fa-spinner.fa-spin - when 'Disqusjs' - +countBlock - a.disqusjs-comment-count(href=full_url_for(page.path) + '#post-comment') - i.fa-solid.fa-spinner.fa-spin - when 'Valine' - +countBlock - a(href=url_for(page.path) + '#post-comment' itemprop="discussionUrl") - span.valine-comment-count(data-xid=url_for(page.path) itemprop="commentCount") - i.fa-solid.fa-spinner.fa-spin - when 'Waline' - +countBlock - a(href=url_for(page.path) + '#post-comment') - span.waline-comment-count(data-path=url_for(page.path)) - i.fa-solid.fa-spinner.fa-spin - when 'Gitalk' - +countBlock - a(href=url_for(page.path) + '#post-comment') - span.gitalk-comment-count - i.fa-solid.fa-spinner.fa-spin - when 'Twikoo' - +countBlock - a(href=url_for(page.path) + '#post-comment') - span#twikoo-count - i.fa-solid.fa-spinner.fa-spin - when 'Facebook Comments' - +countBlock - a(href=url_for(page.path) + '#post-comment') - span.fb-comments-count(data-href=urlNoIndex()) - when 'Remark42' - +countBlock - a(href=url_for(page.path) + '#post-comment') - span.remark42__counter(data-url=urlNoIndex()) - i.fa-solid.fa-spinner.fa-spin - when 'Artalk' - +countBlock - a(href=url_for(page.path) + '#post-comment') - span#ArtalkCount +- let comments = theme.comments +#post-info + h1.post-title= page.title || _p('no_title') + if theme.post_edit.enable + a.post-edit-link(href=theme.post_edit.url + page.source title=_p('post.edit') target="_blank") + i.fas.fa-pencil-alt + + #post-meta + .meta-firstline + if theme.post_meta.post.date_type + span.post-meta-date + if theme.post_meta.post.date_type === 'both' + i.far.fa-calendar-alt.fa-fw.post-meta-icon + span.post-meta-label= _p('post.created') + time.post-meta-date-created(datetime=date_xml(page.date) title=_p('post.created') + ' ' + full_date(page.date))= date(page.date, config.date_format) + span.post-meta-separator | + i.fas.fa-history.fa-fw.post-meta-icon + span.post-meta-label= _p('post.updated') + time.post-meta-date-updated(datetime=date_xml(page.updated) title=_p('post.updated') + ' ' + full_date(page.updated))= date(page.updated, config.date_format) + else + - let data_type_update = theme.post_meta.post.date_type === 'updated' + - let date_type = data_type_update ? 'updated' : 'date' + - let date_icon = data_type_update ? 'fas fa-history' : 'far fa-calendar-alt' + - let date_title = data_type_update ? _p('post.updated') : _p('post.created') + i.fa-fw.post-meta-icon(class=date_icon) + span.post-meta-label= date_title + time(datetime=date_xml(page[date_type]) title=date_title + ' ' + full_date(page[date_type]))= date(page[date_type], config.date_format) + if theme.post_meta.post.categories && page.categories.data.length > 0 + span.post-meta-categories + if theme.post_meta.post.date_type + span.post-meta-separator | + each item, index in page.categories.data + i.fas.fa-inbox.fa-fw.post-meta-icon + a(href=url_for(item.path)).post-meta-categories #[=item.name] + if index < page.categories.data.length - 1 + i.fas.fa-angle-right.post-meta-separator + + .meta-secondline + - let postWordcount = theme.wordcount.enable && (theme.wordcount.post_wordcount || theme.wordcount.min2read) + if postWordcount + span.post-meta-separator | + span.post-meta-wordcount + if theme.wordcount.post_wordcount + i.far.fa-file-word.fa-fw.post-meta-icon + span.post-meta-label= _p('post.wordcount') + ':' + span.word-count= wordcount(page.content) + if theme.wordcount.min2read + span.post-meta-separator | + if theme.wordcount.min2read + i.far.fa-clock.fa-fw.post-meta-icon + span.post-meta-label= _p('post.min2read') + ':' + span= min2read(page.content, {cn: 350, en: 160}) + _p('post.min2read_unit') + + //- for pv and count + mixin pvBlock(parent_id, parent_class, parent_title) + span.post-meta-separator | + span(class=parent_class id=parent_id data-flag-title=parent_title) + i.far.fa-eye.fa-fw.post-meta-icon + span.post-meta-label= _p('post.page_pv') + ':' + if block + block + + mixin otherPV() + if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.page_pv + +pvBlock('', '', '') + span#umamiPV(data-path=url_for(page.path)) + i.fa-solid.fa-spinner.fa-spin + else if theme.busuanzi.page_pv + +pvBlock('', 'post-meta-pv-cv', '') + span#busuanzi_value_page_pv + i.fa-solid.fa-spinner.fa-spin + + - const commentUse = comments.use && comments.use[0] + if page.comments !== false && commentUse && !comments.lazyload + if commentUse === 'Valine' && theme.valine.visitor + +pvBlock(url_for(page.path), 'leancloud_visitors', page.title) + span.leancloud-visitors-count + i.fa-solid.fa-spinner.fa-spin + else if commentUse === 'Waline' && theme.waline.pageview + +pvBlock('', '', '') + span.waline-pageview-count(data-path=url_for(page.path)) + i.fa-solid.fa-spinner.fa-spin + else if commentUse === 'Twikoo' && theme.twikoo.visitor + +pvBlock('', '', '') + span#twikoo_visitors + i.fa-solid.fa-spinner.fa-spin + else if commentUse === 'Artalk' && theme.artalk.visitor + +pvBlock('', '', '') + span#ArtalkPV + i.fa-solid.fa-spinner.fa-spin + else + +otherPV() + else + +otherPV() + + if comments.count && !comments.lazyload && page.comments !== false && comments.use + - var whichCount = comments.use[0] + + mixin countBlock + span.post-meta-separator | + span.post-meta-commentcount + i.far.fa-comments.fa-fw.post-meta-icon + span.post-meta-label= _p('post.comments') + ':' + if block + block + + case whichCount + when 'Disqus' + +countBlock + a.disqus-comment-count(href=full_url_for(page.path) + '#post-comment') + i.fa-solid.fa-spinner.fa-spin + when 'Disqusjs' + +countBlock + a.disqusjs-comment-count(href=full_url_for(page.path) + '#post-comment') + i.fa-solid.fa-spinner.fa-spin + when 'Valine' + +countBlock + a(href=url_for(page.path) + '#post-comment' itemprop="discussionUrl") + span.valine-comment-count(data-xid=url_for(page.path) itemprop="commentCount") + i.fa-solid.fa-spinner.fa-spin + when 'Waline' + +countBlock + a(href=url_for(page.path) + '#post-comment') + span.waline-comment-count(data-path=url_for(page.path)) + i.fa-solid.fa-spinner.fa-spin + when 'Gitalk' + +countBlock + a(href=url_for(page.path) + '#post-comment') + span.gitalk-comment-count + i.fa-solid.fa-spinner.fa-spin + when 'Twikoo' + +countBlock + a(href=url_for(page.path) + '#post-comment') + span#twikoo-count + i.fa-solid.fa-spinner.fa-spin + when 'Facebook Comments' + +countBlock + a(href=url_for(page.path) + '#post-comment') + span.fb-comments-count(data-href=urlNoIndex()) + when 'Remark42' + +countBlock + a(href=url_for(page.path) + '#post-comment') + span.remark42__counter(data-url=urlNoIndex()) + i.fa-solid.fa-spinner.fa-spin + when 'Artalk' + +countBlock + a(href=url_for(page.path) + '#post-comment') + span#ArtalkCount i.fa-solid.fa-spinner.fa-spin \ No newline at end of file diff --git a/layout/includes/header/social.pug b/layout/includes/header/social.pug index 81b47cc..cc816fa 100644 --- a/layout/includes/header/social.pug +++ b/layout/includes/header/social.pug @@ -1,8 +1,8 @@ -each url, icon in theme.social - - - const [link, title, color] = url.split('||').map(i => trim(i)) - const href = url_for(link) - const iconStyle = color ? `color: ${color.replace(/[\'\"]/g, '')};` : '' - const iconTitle = title || '' - a.social-icon(href=href target="_blank" title=iconTitle) +each url, icon in theme.social + - + const [link, title, color] = url.split('||').map(i => trim(i)) + const href = url_for(link) + const iconStyle = color ? `color: ${color.replace(/[\'\"]/g, '')};` : '' + const iconTitle = title || '' + a.social-icon(href=href target="_blank" title=iconTitle) i(class=icon style=iconStyle) \ No newline at end of file diff --git a/layout/includes/layout.pug b/layout/includes/layout.pug index cf3e973..ef6a46b 100644 --- a/layout/includes/layout.pug +++ b/layout/includes/layout.pug @@ -1,37 +1,37 @@ -- var globalPageType = getPageType(page, is_home) -- var htmlClassHideAside = theme.aside.enable && theme.aside.hide ? 'hide-aside' : '' -- page.aside = globalPageType === 'archive' ? theme.aside.display.archive: globalPageType === 'category' ? theme.aside.display.category : globalPageType === 'tag' ? theme.aside.display.tag : page.aside -- var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : '' -- var pageType = globalPageType === 'post' ? 'post' : 'page' -- pageType = page.type ? pageType + ' type-' + page.type : pageType - -doctype html -html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside) - head - include ./head.pug - body - !=partial('includes/loading/index', {}, {cache: true}) - - if theme.background - #web_bg(style=getBgPath(theme.background)) - - !=partial('includes/sidebar', {}, {cache: true}) - - #body-wrap(class=pageType) - include ./header/index.pug - - main#content-inner.layout(class=hideAside) - if body - div!= body - else - block content - if theme.aside.enable && page.aside !== false - include widget/index.pug - - - const footerBg = theme.footer_img - - const footer_bg = footerBg ? footerBg === true ? bg_img : getBgPath(footerBg) : '' - footer#footer(style=footer_bg) - !=partial('includes/footer', {}, {cache: true}) - - include ./rightside.pug +- var globalPageType = getPageType(page, is_home) +- var htmlClassHideAside = theme.aside.enable && theme.aside.hide ? 'hide-aside' : '' +- page.aside = globalPageType === 'archive' ? theme.aside.display.archive: globalPageType === 'category' ? theme.aside.display.category : globalPageType === 'tag' ? theme.aside.display.tag : page.aside +- var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : '' +- var pageType = globalPageType === 'post' ? 'post' : 'page' +- pageType = page.type ? pageType + ' type-' + page.type : pageType + +doctype html +html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside) + head + include ./head.pug + body + !=partial('includes/loading/index', {}, {cache: true}) + + if theme.background + #web_bg(style=getBgPath(theme.background)) + + !=partial('includes/sidebar', {}, {cache: true}) + + #body-wrap(class=pageType) + include ./header/index.pug + + main#content-inner.layout(class=hideAside) + if body + div!= body + else + block content + if theme.aside.enable && page.aside !== false + include widget/index.pug + + - const footerBg = theme.footer_img + - const footer_bg = footerBg ? footerBg === true ? bg_img : getBgPath(footerBg) : '' + footer#footer(style=footer_bg) + !=partial('includes/footer', {}, {cache: true}) + + include ./rightside.pug include ./additional-js.pug \ No newline at end of file diff --git a/layout/includes/loading/fullpage-loading.pug b/layout/includes/loading/fullpage-loading.pug index 774a6b9..a3d0098 100644 --- a/layout/includes/loading/fullpage-loading.pug +++ b/layout/includes/loading/fullpage-loading.pug @@ -1,33 +1,33 @@ -#loading-box - .loading-left-bg - .loading-right-bg - .spinner-box - .configure-border-1 - .configure-core - .configure-border-2 - .configure-core - .loading-word= _p('loading') - -script. - (()=>{ - const $loadingBox = document.getElementById('loading-box') - const $body = document.body - const preloader = { - endLoading: () => { - $body.style.overflow = '' - $loadingBox.classList.add('loaded') - }, - initLoading: () => { - $body.style.overflow = 'hidden' - $loadingBox.classList.remove('loaded') - } - } - - preloader.initLoading() - window.addEventListener('load', preloader.endLoading) - - if (!{theme.pjax && theme.pjax.enable}) { - btf.addGlobalFn('pjaxSend', preloader.initLoading, 'preloader_init') - btf.addGlobalFn('pjaxComplete', preloader.endLoading, 'preloader_end') - } +#loading-box + .loading-left-bg + .loading-right-bg + .spinner-box + .configure-border-1 + .configure-core + .configure-border-2 + .configure-core + .loading-word= _p('loading') + +script. + (()=>{ + const $loadingBox = document.getElementById('loading-box') + const $body = document.body + const preloader = { + endLoading: () => { + $body.style.overflow = '' + $loadingBox.classList.add('loaded') + }, + initLoading: () => { + $body.style.overflow = 'hidden' + $loadingBox.classList.remove('loaded') + } + } + + preloader.initLoading() + window.addEventListener('load', preloader.endLoading) + + if (!{theme.pjax && theme.pjax.enable}) { + btf.addGlobalFn('pjaxSend', preloader.initLoading, 'preloader_init') + btf.addGlobalFn('pjaxComplete', preloader.endLoading, 'preloader_end') + } })() \ No newline at end of file diff --git a/layout/includes/loading/index.pug b/layout/includes/loading/index.pug index 6a6facc..b058b58 100644 --- a/layout/includes/loading/index.pug +++ b/layout/includes/loading/index.pug @@ -1,5 +1,5 @@ -if theme.preloader.enable - if theme.preloader.source === 1 - include ./fullpage-loading.pug - else +if theme.preloader.enable + if theme.preloader.source === 1 + include ./fullpage-loading.pug + else include ./pace.pug \ No newline at end of file diff --git a/layout/includes/loading/pace.pug b/layout/includes/loading/pace.pug index 4cf2a4e..ac04c9b 100644 --- a/layout/includes/loading/pace.pug +++ b/layout/includes/loading/pace.pug @@ -1,12 +1,12 @@ -script. - window.paceOptions = { - restartOnPushState: false - } - - btf.addGlobalFn('pjaxSend', () => { - Pace.restart() - }, 'pace_restart') - - -link(rel="stylesheet", href=url_for(theme.preloader.pace_css_url || theme.asset.pace_default_css)) +script. + window.paceOptions = { + restartOnPushState: false + } + + btf.addGlobalFn('pjaxSend', () => { + Pace.restart() + }, 'pace_restart') + + +link(rel="stylesheet", href=url_for(theme.preloader.pace_css_url || theme.asset.pace_default_css)) script(src=url_for(theme.asset.pace_js)) \ No newline at end of file diff --git a/layout/includes/mixins/article-sort.pug b/layout/includes/mixins/article-sort.pug index acc5d9f..79f87da 100644 --- a/layout/includes/mixins/article-sort.pug +++ b/layout/includes/mixins/article-sort.pug @@ -1,23 +1,23 @@ -mixin articleSort(posts) - .article-sort - - let year - - posts.forEach(article => { - - const tempYear = date(article.date, 'YYYY') - - const noCoverClass = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : '' - - const title = article.title || _p('no_title') - if tempYear !== year - - year = tempYear - .article-sort-item.year= year - .article-sort-item(class=noCoverClass) - if article.cover && theme.cover.archives_enable - a.article-sort-item-img(href=url_for(article.path) title=title) - if article.cover_type === 'img' - img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`) - else - div(style=`background: ${article.cover}`) - .article-sort-item-info - .article-sort-item-time - i.far.fa-calendar-alt - time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format) - a.article-sort-item-title(href=url_for(article.path) title=title)= title +mixin articleSort(posts) + .article-sort + - let year + - posts.forEach(article => { + - const tempYear = date(article.date, 'YYYY') + - const noCoverClass = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : '' + - const title = article.title || _p('no_title') + if tempYear !== year + - year = tempYear + .article-sort-item.year= year + .article-sort-item(class=noCoverClass) + if article.cover && theme.cover.archives_enable + a.article-sort-item-img(href=url_for(article.path) title=title) + if article.cover_type === 'img' + img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`) + else + div(style=`background: ${article.cover}`) + .article-sort-item-info + .article-sort-item-time + i.far.fa-calendar-alt + time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format) + a.article-sort-item-title(href=url_for(article.path) title=title)= title - }) \ No newline at end of file diff --git a/layout/includes/mixins/indexPostUI.pug b/layout/includes/mixins/indexPostUI.pug index 4f2c3ee..874ad5e 100644 --- a/layout/includes/mixins/indexPostUI.pug +++ b/layout/includes/mixins/indexPostUI.pug @@ -1,116 +1,116 @@ -mixin indexPostUI() - - const indexLayout = theme.index_layout - - const 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 - - const link = article.link || article.path - - const title = article.title || _p('no_title') - - const leftOrRight = indexLayout === 3 ? (index % 2 === 0 ? 'left' : 'right') : (indexLayout === 2 ? 'right' : '') - - const post_cover = article.cover - - const no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : '' - - if post_cover && theme.cover.index_enable - .post_cover(class=leftOrRight) - a(href=url_for(link) title=title) - 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 globalPageType === '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 - - const data_type_updated = theme.post_meta.page.date_type === 'updated' - - const date_type = data_type_updated ? 'updated' : 'date' - - const date_icon = data_type_updated ? 'fas fa-history' : 'far fa-calendar-alt' - - const 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 - - const content = postDesc(article) - if content - .content!=content - - if theme.ad && theme.ad.index - if (index + 1) % 3 === 0 - .recent-post-item.ads-wrap!= theme.ad.index - +mixin indexPostUI() + - const indexLayout = theme.index_layout + - const 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 + - const link = article.link || article.path + - const title = article.title || _p('no_title') + - const leftOrRight = indexLayout === 3 ? (index % 2 === 0 ? 'left' : 'right') : (indexLayout === 2 ? 'right' : '') + - const post_cover = article.cover + - const no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : '' + + if post_cover && theme.cover.index_enable + .post_cover(class=leftOrRight) + a(href=url_for(link) title=title) + 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 globalPageType === '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 + - const data_type_updated = theme.post_meta.page.date_type === 'updated' + - const date_type = data_type_updated ? 'updated' : 'date' + - const date_icon = data_type_updated ? 'fas fa-history' : 'far fa-calendar-alt' + - const 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 + - const content = postDesc(article) + if content + .content!=content + + if theme.ad && theme.ad.index + if (index + 1) % 3 === 0 + .recent-post-item.ads-wrap!= theme.ad.index + include ../pagination.pug \ No newline at end of file diff --git a/layout/includes/page/404.pug b/layout/includes/page/404.pug index 9444204..b08b5ad 100644 --- a/layout/includes/page/404.pug +++ b/layout/includes/page/404.pug @@ -1,8 +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') +- 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') diff --git a/layout/includes/page/default-page.pug b/layout/includes/page/default-page.pug index 4a7d515..38f651a 100644 --- a/layout/includes/page/default-page.pug +++ b/layout/includes/page/default-page.pug @@ -1,2 +1,2 @@ -#article-container.container +#article-container.container != page.content \ No newline at end of file diff --git a/layout/includes/page/flink.pug b/layout/includes/page/flink.pug index f94fffc..a4b6e27 100644 --- a/layout/includes/page/flink.pug +++ b/layout/includes/page/flink.pug @@ -1,82 +1,82 @@ -#article-container.container - .flink - - let { content, random, flink_url } = page - - let pageContent = content - - if flink_url || random - - const linkData = flink_url ? false : site.data.link || false - script. - (()=>{ - const replaceSymbol = (str) => { - return str.replace(/[\p{P}\p{S}]/gu, "-") - } - - let result = "" - const add = (str) => { - for(let i = 0; i < str.length; i++){ - const replaceClassName = replaceSymbol(str[i].class_name) - const className = str[i].class_name ? `

${str[i].class_name}

` : "" - const classDesc = str[i].class_desc ? `` : "" - - let listResult = "" - const lists = str[i].link_list - if (!{random === true}) { - lists.sort(() => Math.random() - 0.5) - } - for(let j = 0; j < lists.length; j++){ - listResult += ` - ` - } - - result += `${className}${classDesc} ` - } - - document.querySelector(".flink").insertAdjacentHTML("afterbegin", result) - window.lazyLoadInstance && window.lazyLoadInstance.update() - } - - const linkData = !{JSON.stringify(linkData)} - if (!{Boolean(flink_url)}) { - fetch("!{url_for(flink_url)}") - .then(response => response.json()) - .then(add) - } else if (linkData) { - add(linkData) - } - })() - - else - if site.data.link - - let result = "" - each i in site.data.link - - let className = i.class_name ? markdown(`## ${i.class_name}`) : "" - - let classDesc = i.class_desc ? `` : "" - - - let listResult = "" - - each j in i.link_list - - - listResult += ` - ` - - - - - result += `${className}${classDesc} ` - - - pageContent = result + pageContent - != pageContent +#article-container.container + .flink + - let { content, random, flink_url } = page + - let pageContent = content + + if flink_url || random + - const linkData = flink_url ? false : site.data.link || false + script. + (()=>{ + const replaceSymbol = (str) => { + return str.replace(/[\p{P}\p{S}]/gu, "-") + } + + let result = "" + const add = (str) => { + for(let i = 0; i < str.length; i++){ + const replaceClassName = replaceSymbol(str[i].class_name) + const className = str[i].class_name ? `

${str[i].class_name}

` : "" + const classDesc = str[i].class_desc ? `` : "" + + let listResult = "" + const lists = str[i].link_list + if (!{random === true}) { + lists.sort(() => Math.random() - 0.5) + } + for(let j = 0; j < lists.length; j++){ + listResult += ` + ` + } + + result += `${className}${classDesc} ` + } + + document.querySelector(".flink").insertAdjacentHTML("afterbegin", result) + window.lazyLoadInstance && window.lazyLoadInstance.update() + } + + const linkData = !{JSON.stringify(linkData)} + if (!{Boolean(flink_url)}) { + fetch("!{url_for(flink_url)}") + .then(response => response.json()) + .then(add) + } else if (linkData) { + add(linkData) + } + })() + + else + if site.data.link + - let result = "" + each i in site.data.link + - let className = i.class_name ? markdown(`## ${i.class_name}`) : "" + - let classDesc = i.class_desc ? `` : "" + + - let listResult = "" + + each j in i.link_list + - + listResult += ` + ` + - + + - result += `${className}${classDesc} ` + + - pageContent = result + pageContent + != pageContent diff --git a/layout/includes/page/shuoshuo.pug b/layout/includes/page/shuoshuo.pug index 3bcb01d..c107d5c 100644 --- a/layout/includes/page/shuoshuo.pug +++ b/layout/includes/page/shuoshuo.pug @@ -1,188 +1,188 @@ -//- - author: -//- avatar: -//- date: -//- content: -//- tags: -//- - tag1 -//- - tag2 - -- page.toc = false - -#article-container - if page.comments !== false && theme.comments.use - - commentsJsLoad = true - - script. - (() => { - const commentDiv = `!{partial('includes/third-party/comments/index', {}, {cache: true})}` - - const runDestroy = (shuoshuoComment) => { - if (!shuoshuoComment) return - - for (const [key, fn] of Object.entries(shuoshuoComment)) { - if (key.startsWith('destroy')) fn() - } - } - - window.addCommentToShuoshuo = e => { - const btn = e.target.closest('.shuoshuo-comment-btn') - if (!btn) return - - const ele = btn.closest('.container').nextElementSibling - const { shuoshuoComment } = window - const isInclude = ele.classList.contains('no-comment') - runDestroy(shuoshuoComment) - if (isInclude) { - ele.classList.remove('no-comment') - ele.innerHTML = commentDiv - const key = `${location.pathname.replace(/\/$/, '')}?key=${ele.getAttribute('data-key')}` - btf.switchComments(ele, key) - shuoshuoComment.loadComment && shuoshuoComment.loadComment(ele, key) - } - } - })() - - if page.shuoshuo_url - script. - (() => { - const limitConfig = !{ JSON.stringify(page.limit || {}) } - - const sortDataByDate = data => data.sort((a, b) => new Date(b.date) - new Date(a.date)) - - const filterDataByLimit = (data, limit) => { - if (!limit || !limit.type) return data - if (limit.type === 'num') return data.slice(0, limit.value) - if (limit.type === 'date') { - const limitDate = new Date(limit.value) - return data.filter(item => new Date(item.date) >= limitDate) - } - return data - }; - - const formatToTimeZone = (date) => { - const fullDate = date.length === 10 ? `${date} 00:00:00` : date - const visitorTimeZone = '#{config.timezone}' || Intl.DateTimeFormat().resolvedOptions().timeZone - const options = { - timeZone: visitorTimeZone, - year: 'numeric', - month: '2-digit', - day: '2-digit', - hour: '2-digit', - minute: '2-digit', - second: '2-digit', - hour12: false - } - const [day, month, year, hour, minute, second] = new Intl.DateTimeFormat('en-GB', options) - .format(new Date(fullDate)) - .match(/\d+/g) - return `${year}-${month}-${day} ${hour}:${minute}:${second}` - } - - const loadShuoshuo = async () => { - try { - const response = await fetch('!{url_for(page.shuoshuo_url)}') - let data = await response.json() - - data = filterDataByLimit(sortDataByDate(data), limitConfig) - - const container = document.getElementById('article-container') - let start = 0 - - const renderData = (dataSlice) => { - const content = dataSlice.map(item => { - const formattedDate = formatToTimeZone(item.date) - const tags = item.tags && item.tags.map(tag => `${tag}`).join('') || '' - const commentButton = item.key && !{commentsJsLoad} - ? `
- -
` - : '' - const commentContainer = item.key - ? `
` - : '' - - return ` -
-
-
-
- -
-
-
${item.author || '!{config.author}'}
- -
-
-
${item.content}
- -
- ${commentContainer} -
` - }).join('') - - container.insertAdjacentHTML('beforeend', content) - - window.lazyLoadInstance.update() - btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)')) - } - - const handleIntersection = (entries) => { - if (!entries[0].isIntersecting) return - observer.unobserve(entries[0].target) - - const slice = data.slice(start, start + 10) - renderData(slice) - start += 10 - - if (start < data.length) { - setTimeout(() => observer.observe(container.lastElementChild), 100) - } else { - observer.disconnect() - } - }; - - const observer = new IntersectionObserver(handleIntersection, { - root: null, - rootMargin: '0px', - threshold: 1.0 - }) - - renderData(data.slice(start, 10)) - start += 10 - - if (container.lastElementChild) observer.observe(container.lastElementChild) - } catch (error) { - console.error(error) - } - }; - - window.pjax ? loadShuoshuo() : window.addEventListener('load', loadShuoshuo) - })() - else - if site.data.shuoshuo - each i in shuoshuoFN(site.data.shuoshuo, page) - .shuoshuo-item - .container - .shuoshuo-item-header - .shuoshuo-avatar - img.no-lightbox(src=i.avatar || url_for(theme.avatar.img)) - .shuoshuo-info - .shuoshuo-author=i.author || config.author - time.shuoshuo-date(title=i.date)=i.date - .shuoshuo-content - !=markdown(i.content) - .shuoshuo-footer(class=i.tags && i.tags.length ? 'flex-between' : 'flex-end') - if i.tags - .shuoshuo-tags - each tag in i.tags - span.shuoshuo-tag=tag - if i.key && commentsJsLoad - .shuoshuo-comment-btn(onclick='addCommentToShuoshuo(event)') - i.fa-solid.fa-comments - if i.key && commentsJsLoad +//- - author: +//- avatar: +//- date: +//- content: +//- tags: +//- - tag1 +//- - tag2 + +- page.toc = false + +#article-container + if page.comments !== false && theme.comments.use + - commentsJsLoad = true + + script. + (() => { + const commentDiv = `!{partial('includes/third-party/comments/index', {}, {cache: true})}` + + const runDestroy = (shuoshuoComment) => { + if (!shuoshuoComment) return + + for (const [key, fn] of Object.entries(shuoshuoComment)) { + if (key.startsWith('destroy')) fn() + } + } + + window.addCommentToShuoshuo = e => { + const btn = e.target.closest('.shuoshuo-comment-btn') + if (!btn) return + + const ele = btn.closest('.container').nextElementSibling + const { shuoshuoComment } = window + const isInclude = ele.classList.contains('no-comment') + runDestroy(shuoshuoComment) + if (isInclude) { + ele.classList.remove('no-comment') + ele.innerHTML = commentDiv + const key = `${location.pathname.replace(/\/$/, '')}?key=${ele.getAttribute('data-key')}` + btf.switchComments(ele, key) + shuoshuoComment.loadComment && shuoshuoComment.loadComment(ele, key) + } + } + })() + + if page.shuoshuo_url + script. + (() => { + const limitConfig = !{ JSON.stringify(page.limit || {}) } + + const sortDataByDate = data => data.sort((a, b) => new Date(b.date) - new Date(a.date)) + + const filterDataByLimit = (data, limit) => { + if (!limit || !limit.type) return data + if (limit.type === 'num') return data.slice(0, limit.value) + if (limit.type === 'date') { + const limitDate = new Date(limit.value) + return data.filter(item => new Date(item.date) >= limitDate) + } + return data + }; + + const formatToTimeZone = (date) => { + const fullDate = date.length === 10 ? `${date} 00:00:00` : date + const visitorTimeZone = '#{config.timezone}' || Intl.DateTimeFormat().resolvedOptions().timeZone + const options = { + timeZone: visitorTimeZone, + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', + second: '2-digit', + hour12: false + } + const [day, month, year, hour, minute, second] = new Intl.DateTimeFormat('en-GB', options) + .format(new Date(fullDate)) + .match(/\d+/g) + return `${year}-${month}-${day} ${hour}:${minute}:${second}` + } + + const loadShuoshuo = async () => { + try { + const response = await fetch('!{url_for(page.shuoshuo_url)}') + let data = await response.json() + + data = filterDataByLimit(sortDataByDate(data), limitConfig) + + const container = document.getElementById('article-container') + let start = 0 + + const renderData = (dataSlice) => { + const content = dataSlice.map(item => { + const formattedDate = formatToTimeZone(item.date) + const tags = item.tags && item.tags.map(tag => `${tag}`).join('') || '' + const commentButton = item.key && !{commentsJsLoad} + ? `
+ +
` + : '' + const commentContainer = item.key + ? `
` + : '' + + return ` +
+
+
+
+ +
+
+
${item.author || '!{config.author}'}
+ +
+
+
${item.content}
+ +
+ ${commentContainer} +
` + }).join('') + + container.insertAdjacentHTML('beforeend', content) + + window.lazyLoadInstance.update() + btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)')) + } + + const handleIntersection = (entries) => { + if (!entries[0].isIntersecting) return + observer.unobserve(entries[0].target) + + const slice = data.slice(start, start + 10) + renderData(slice) + start += 10 + + if (start < data.length) { + setTimeout(() => observer.observe(container.lastElementChild), 100) + } else { + observer.disconnect() + } + }; + + const observer = new IntersectionObserver(handleIntersection, { + root: null, + rootMargin: '0px', + threshold: 1.0 + }) + + renderData(data.slice(start, 10)) + start += 10 + + if (container.lastElementChild) observer.observe(container.lastElementChild) + } catch (error) { + console.error(error) + } + }; + + window.pjax ? loadShuoshuo() : window.addEventListener('load', loadShuoshuo) + })() + else + if site.data.shuoshuo + each i in shuoshuoFN(site.data.shuoshuo, page) + .shuoshuo-item + .container + .shuoshuo-item-header + .shuoshuo-avatar + img.no-lightbox(src=i.avatar || url_for(theme.avatar.img)) + .shuoshuo-info + .shuoshuo-author=i.author || config.author + time.shuoshuo-date(title=i.date)=i.date + .shuoshuo-content + !=markdown(i.content) + .shuoshuo-footer(class=i.tags && i.tags.length ? 'flex-between' : 'flex-end') + if i.tags + .shuoshuo-tags + each tag in i.tags + span.shuoshuo-tag=tag + if i.key && commentsJsLoad + .shuoshuo-comment-btn(onclick='addCommentToShuoshuo(event)') + i.fa-solid.fa-comments + if i.key && commentsJsLoad .shuoshuo-comment.no-comment(data-key=i.key) \ No newline at end of file diff --git a/layout/includes/page/tags.pug b/layout/includes/page/tags.pug index b5b62cd..9c48197 100644 --- a/layout/includes/page/tags.pug +++ b/layout/includes/page/tags.pug @@ -1,2 +1,2 @@ -.tag-cloud-list.text-center +.tag-cloud-list.text-center !=cloudTags({source: site.tags, orderby: page.orderby || 'random', order: page.order || 1, minfontsize: 1.2, maxfontsize: 1.5, limit: 0, unit: 'em'}) \ No newline at end of file diff --git a/layout/includes/pagination.pug b/layout/includes/pagination.pug index 96a3d71..bbfc1eb 100644 --- a/layout/includes/pagination.pug +++ b/layout/includes/pagination.pug @@ -1,37 +1,37 @@ -- - var options = { - prev_text: '', - next_text: '', - mid_size: 1, - escape: false - } - -if globalPageType === 'post' - - let paginationOrder = theme.post_pagination === 1 ? { prev: page.prev, next: page.next } : { prev: page.next, next: page.prev } - - nav#pagination.pagination-post - each direction, key in paginationOrder - if direction - - const getPostDesc = direction.postDesc || postDesc(direction) - - let className = key === 'prev' ? (paginationOrder.next ? '' : 'full-width') : (paginationOrder.prev ? '' : 'full-width') - - className = getPostDesc ? className : className + ' no-desc' - - a.pagination-related(class=className href=url_for(direction.path) title=direction.title) - if direction.cover_type === 'img' - img.cover(src=url_for(direction.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt=`cover of ${key === 'prev' ? 'previous' : 'next'} post`) - else - .cover(style=`background: ${direction.cover || 'var(--default-bg-color)'}`) - - .info(class=key === 'prev' ? '' : 'text-right') - .info-1 - .info-item-1=_p(`pagination.${key}`) - .info-item-2!=direction.title - if getPostDesc - .info-2 - .info-item-1!=getPostDesc -else - nav#pagination - .pagination - if globalPageType === 'home' - - options.format = 'page/%d/#content-inner' +- + var options = { + prev_text: '', + next_text: '', + mid_size: 1, + escape: false + } + +if globalPageType === 'post' + - let paginationOrder = theme.post_pagination === 1 ? { prev: page.prev, next: page.next } : { prev: page.next, next: page.prev } + + nav#pagination.pagination-post + each direction, key in paginationOrder + if direction + - const getPostDesc = direction.postDesc || postDesc(direction) + - let className = key === 'prev' ? (paginationOrder.next ? '' : 'full-width') : (paginationOrder.prev ? '' : 'full-width') + - className = getPostDesc ? className : className + ' no-desc' + + a.pagination-related(class=className href=url_for(direction.path) title=direction.title) + if direction.cover_type === 'img' + img.cover(src=url_for(direction.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt=`cover of ${key === 'prev' ? 'previous' : 'next'} post`) + else + .cover(style=`background: ${direction.cover || 'var(--default-bg-color)'}`) + + .info(class=key === 'prev' ? '' : 'text-right') + .info-1 + .info-item-1=_p(`pagination.${key}`) + .info-item-2!=direction.title + if getPostDesc + .info-2 + .info-item-1!=getPostDesc +else + nav#pagination + .pagination + if globalPageType === 'home' + - options.format = 'page/%d/#content-inner' !=paginator(options) \ No newline at end of file diff --git a/layout/includes/post/outdate-notice.pug b/layout/includes/post/outdate-notice.pug index ef72772..b0cd21e 100644 --- a/layout/includes/post/outdate-notice.pug +++ b/layout/includes/post/outdate-notice.pug @@ -1,8 +1,8 @@ -- const { limit_day, message_prev, message_next, position} = theme.noticeOutdate -- const notice_data = { limitDay: limit_day, messagePrev: message_prev, messageNext: message_next, postUpdate: full_date(page.updated)} -if position === 'top' - #post-outdate-notice(data=notice_data hidden) - !=page.content -else - !=page.content +- const { limit_day, message_prev, message_next, position} = theme.noticeOutdate +- const notice_data = { limitDay: limit_day, messagePrev: message_prev, messageNext: message_next, postUpdate: full_date(page.updated)} +if position === 'top' + #post-outdate-notice(data=notice_data hidden) + !=page.content +else + !=page.content #post-outdate-notice(data=notice_data hidden) \ No newline at end of file diff --git a/layout/includes/post/post-copyright.pug b/layout/includes/post/post-copyright.pug index c76f4b4..1f7c50a 100644 --- a/layout/includes/post/post-copyright.pug +++ b/layout/includes/post/post-copyright.pug @@ -1,23 +1,23 @@ -if theme.post_copyright.enable && page.copyright !== false - - const author = page.copyright_author || config.author - - const authorHref = page.copyright_author_href || theme.post_copyright.author_href || config.url - - const url = page.copyright_url || page.permalink - - const info = page.copyright_info || _p('post.copyright.copyright_content', theme.post_copyright.license_url, theme.post_copyright.license, config.url, config.title) - .post-copyright - .post-copyright__author - span.post-copyright-meta - i.fas.fa-circle-user.fa-fw - = _p('post.copyright.author') + ": " - span.post-copyright-info - a(href=authorHref)= author - .post-copyright__type - span.post-copyright-meta - i.fas.fa-square-arrow-up-right.fa-fw - = _p('post.copyright.link') + ": " - span.post-copyright-info - a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url - .post-copyright__notice - span.post-copyright-meta - i.fas.fa-circle-exclamation.fa-fw - = _p('post.copyright.copyright_notice') + ": " +if theme.post_copyright.enable && page.copyright !== false + - const author = page.copyright_author || config.author + - const authorHref = page.copyright_author_href || theme.post_copyright.author_href || config.url + - const url = page.copyright_url || page.permalink + - const info = page.copyright_info || _p('post.copyright.copyright_content', theme.post_copyright.license_url, theme.post_copyright.license, config.url, config.title) + .post-copyright + .post-copyright__author + span.post-copyright-meta + i.fas.fa-circle-user.fa-fw + = _p('post.copyright.author') + ": " + span.post-copyright-info + a(href=authorHref)= author + .post-copyright__type + span.post-copyright-meta + i.fas.fa-square-arrow-up-right.fa-fw + = _p('post.copyright.link') + ": " + span.post-copyright-info + a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url + .post-copyright__notice + span.post-copyright-meta + i.fas.fa-circle-exclamation.fa-fw + = _p('post.copyright.copyright_notice') + ": " span.post-copyright-info!= info \ No newline at end of file diff --git a/layout/includes/post/reward.pug b/layout/includes/post/reward.pug index fe62f14..baf525c 100644 --- a/layout/includes/post/reward.pug +++ b/layout/includes/post/reward.pug @@ -1,12 +1,12 @@ -.post-reward - .reward-button - i.fas.fa-qrcode - = theme.reward.text || _p('donate') - .reward-main - ul.reward-all - each item in theme.reward.QR_code - - const clickTo = item.link || item.img - li.reward-item - a(href=url_for(clickTo) target='_blank') - img.post-qr-code-img(src=url_for(item.img) alt=item.text) +.post-reward + .reward-button + i.fas.fa-qrcode + = theme.reward.text || _p('donate') + .reward-main + ul.reward-all + each item in theme.reward.QR_code + - const clickTo = item.link || item.img + li.reward-item + a(href=url_for(clickTo) target='_blank') + img.post-qr-code-img(src=url_for(item.img) alt=item.text) .post-qr-code-desc=item.text \ No newline at end of file diff --git a/layout/includes/rightside.pug b/layout/includes/rightside.pug index abd1851..b7608ad 100644 --- a/layout/includes/rightside.pug +++ b/layout/includes/rightside.pug @@ -1,61 +1,61 @@ -- const { readmode, translate, darkmode, aside, chat } = theme -mixin rightsideItem(array) - each item in array - case item - when 'readmode' - if globalPageType === 'post' && readmode - button#readmode(type="button" title=_p('rightside.readmode_title')) - i.fas.fa-book-open - when 'translate' - if translate.enable - button#translateLink(type="button" title=_p('rightside.translate_title'))= translate.default - when 'darkmode' - if darkmode.enable && darkmode.button - button#darkmode(type="button" title=_p('rightside.night_mode_title')) - i.fas.fa-adjust - when 'hideAside' - if aside.enable && aside.button && page.aside !== false - button#hide-aside-btn(type="button" title=_p('rightside.aside')) - i.fas.fa-arrows-alt-h - when 'toc' - if showToc - button#mobile-toc-button.close(type="button" title=_p("rightside.toc")) - i.fas.fa-list-ul - when 'chat' - if chat.rightside_button && chat.use - button#chat-btn(type="button" title=_p("rightside.chat") style="display:none") - i.fas.fa-message - when 'comment' - if commentsJsLoad - a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment")) - i.fas.fa-comments - -#rightside - - const { enable, hide, show } = theme.rightside_item_order - - const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode','hideAside'] - - const showArray = enable ? show && show.split(',') : ['toc','chat','comment'] - - - #rightside-config-hide - if hideArray - +rightsideItem(hideArray) - #rightside-config-show - if enable - if hide - button#rightside-config(type="button" title=_p("rightside.setting")) - i.fas.fa-cog.fa-spin - else - if globalPageType === 'post' - if (readmode || translate.enable || (darkmode.enable && darkmode.button)) - button#rightside-config(type="button" title=_p("rightside.setting")) - i.fas.fa-cog.fa-spin - else if translate.enable || (darkmode.enable && darkmode.button) - button#rightside-config(type="button" title=_p("rightside.setting")) - i.fas.fa-cog.fa-spin - - if showArray - +rightsideItem(showArray) - - button#go-up(type="button" title=_p("rightside.back_to_top")) - span.scroll-percent +- const { readmode, translate, darkmode, aside, chat } = theme +mixin rightsideItem(array) + each item in array + case item + when 'readmode' + if globalPageType === 'post' && readmode + button#readmode(type="button" title=_p('rightside.readmode_title')) + i.fas.fa-book-open + when 'translate' + if translate.enable + button#translateLink(type="button" title=_p('rightside.translate_title'))= translate.default + when 'darkmode' + if darkmode.enable && darkmode.button + button#darkmode(type="button" title=_p('rightside.night_mode_title')) + i.fas.fa-adjust + when 'hideAside' + if aside.enable && aside.button && page.aside !== false + button#hide-aside-btn(type="button" title=_p('rightside.aside')) + i.fas.fa-arrows-alt-h + when 'toc' + if showToc + button#mobile-toc-button.close(type="button" title=_p("rightside.toc")) + i.fas.fa-list-ul + when 'chat' + if chat.rightside_button && chat.use + button#chat-btn(type="button" title=_p("rightside.chat") style="display:none") + i.fas.fa-message + when 'comment' + if commentsJsLoad + a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment")) + i.fas.fa-comments + +#rightside + - const { enable, hide, show } = theme.rightside_item_order + - const hideArray = enable ? hide && hide.split(',') : ['readmode','translate','darkmode','hideAside'] + - const showArray = enable ? show && show.split(',') : ['toc','chat','comment'] + + + #rightside-config-hide + if hideArray + +rightsideItem(hideArray) + #rightside-config-show + if enable + if hide + button#rightside-config(type="button" title=_p("rightside.setting")) + i.fas.fa-cog.fa-spin + else + if globalPageType === 'post' + if (readmode || translate.enable || (darkmode.enable && darkmode.button)) + button#rightside-config(type="button" title=_p("rightside.setting")) + i.fas.fa-cog.fa-spin + else if translate.enable || (darkmode.enable && darkmode.button) + button#rightside-config(type="button" title=_p("rightside.setting")) + i.fas.fa-cog.fa-spin + + if showArray + +rightsideItem(showArray) + + button#go-up(type="button" title=_p("rightside.back_to_top")) + span.scroll-percent i.fas.fa-arrow-up \ No newline at end of file diff --git a/layout/includes/sidebar.pug b/layout/includes/sidebar.pug index 178c420..22abeff 100644 --- a/layout/includes/sidebar.pug +++ b/layout/includes/sidebar.pug @@ -1,18 +1,18 @@ -if theme.menu - #sidebar - #menu-mask - #sidebar-menus - .avatar-img.text-center - img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.flink)}'` alt="avatar") - .site-data.text-center - a(href=`${url_for(config.archive_dir)}/`) - .headline= _p('aside.articles') - .length-num= site.posts.length - a(href=`${url_for(config.tag_dir)}/`) - .headline= _p('aside.tags') - .length-num= site.tags.length - a(href=`${url_for(config.category_dir)}/`) - .headline= _p('aside.categories') - .length-num= site.categories.length - +if theme.menu + #sidebar + #menu-mask + #sidebar-menus + .avatar-img.text-center + img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.flink)}'` alt="avatar") + .site-data.text-center + a(href=`${url_for(config.archive_dir)}/`) + .headline= _p('aside.articles') + .length-num= site.posts.length + a(href=`${url_for(config.tag_dir)}/`) + .headline= _p('aside.tags') + .length-num= site.tags.length + a(href=`${url_for(config.category_dir)}/`) + .headline= _p('aside.categories') + .length-num= site.categories.length + != partial('includes/header/menu_item', {}, { cache: true }) \ No newline at end of file diff --git a/layout/includes/third-party/abcjs/abcjs.pug b/layout/includes/third-party/abcjs/abcjs.pug index a75c37b..453f84b 100644 --- a/layout/includes/third-party/abcjs/abcjs.pug +++ b/layout/includes/third-party/abcjs/abcjs.pug @@ -1,17 +1,17 @@ -script. - (() => { - const abcjsInit = () => { - const abcjsFn = () => setTimeout(() => { - document.querySelectorAll(".abc-music-sheet").forEach(ele => { - if (ele.children.length > 0) return - ABCJS.renderAbc(ele, ele.innerHTML, {responsive: 'resize'}) - }) - }, 100) - - typeof ABCJS === 'object' ? abcjsFn() - : btf.getScript('!{url_for(theme.asset.abcjs_basic_js)}').then(abcjsFn) - } - - window.pjax ? abcjsInit() : window.addEventListener('load', abcjsInit) - btf.addGlobalFn('encrypt', abcjsInit, 'abcjs') +script. + (() => { + const abcjsInit = () => { + const abcjsFn = () => setTimeout(() => { + document.querySelectorAll(".abc-music-sheet").forEach(ele => { + if (ele.children.length > 0) return + ABCJS.renderAbc(ele, ele.innerHTML, {responsive: 'resize'}) + }) + }, 100) + + typeof ABCJS === 'object' ? abcjsFn() + : btf.getScript('!{url_for(theme.asset.abcjs_basic_js)}').then(abcjsFn) + } + + window.pjax ? abcjsInit() : window.addEventListener('load', abcjsInit) + btf.addGlobalFn('encrypt', abcjsInit, 'abcjs') })() \ No newline at end of file diff --git a/layout/includes/third-party/abcjs/index.pug b/layout/includes/third-party/abcjs/index.pug index d187d55..7ae7deb 100644 --- a/layout/includes/third-party/abcjs/index.pug +++ b/layout/includes/third-party/abcjs/index.pug @@ -1,3 +1,3 @@ -if theme.abcjs.enable - if theme.abcjs.per_page && (['post','page'].includes(globalPageType)) || page.abcjs - include ./abcjs.pug +if theme.abcjs.enable + if theme.abcjs.per_page && (['post','page'].includes(globalPageType)) || page.abcjs + include ./abcjs.pug diff --git a/layout/includes/third-party/aplayer.pug b/layout/includes/third-party/aplayer.pug index cf875b6..4e86609 100644 --- a/layout/includes/third-party/aplayer.pug +++ b/layout/includes/third-party/aplayer.pug @@ -1,23 +1,23 @@ -link(rel='stylesheet' href=url_for(theme.asset.aplayer_css) media="print" onload="this.media='all'") -script(src=url_for(theme.asset.aplayer_js)) -script(src=url_for(theme.asset.meting_js)) -if theme.pjax.enable - script. - (() => { - const destroyAplayer = () => { - if (window.aplayers) { - for (let i = 0; i < window.aplayers.length; i++) { - if (!window.aplayers[i].options.fixed) { - window.aplayers[i].destroy() - } - } - } - } - - const runMetingJS = () => { - typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() - } - - btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer') - btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS') - })() +link(rel='stylesheet' href=url_for(theme.asset.aplayer_css) media="print" onload="this.media='all'") +script(src=url_for(theme.asset.aplayer_js)) +script(src=url_for(theme.asset.meting_js)) +if theme.pjax.enable + script. + (() => { + const destroyAplayer = () => { + if (window.aplayers) { + for (let i = 0; i < window.aplayers.length; i++) { + if (!window.aplayers[i].options.fixed) { + window.aplayers[i].destroy() + } + } + } + } + + const runMetingJS = () => { + typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() + } + + btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer') + btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS') + })() diff --git a/layout/includes/third-party/card-post-count/artalk.pug b/layout/includes/third-party/card-post-count/artalk.pug index b5a1056..eeccef3 100644 --- a/layout/includes/third-party/card-post-count/artalk.pug +++ b/layout/includes/third-party/card-post-count/artalk.pug @@ -1,31 +1,31 @@ -- const { server, site } = theme.artalk - -script. - (() => { - const getArtalkCount = async() => { - try { - const eleGroup = document.querySelectorAll('#recent-posts .artalk-count') - const keyArray = Array.from(eleGroup).map(i => i.getAttribute('data-page-key')) - - const headerList = { - method: 'GET', - } - - const searchParams = new URLSearchParams({ - 'site_name': '!{site}', - 'page_keys': keyArray - }) - - const res = await fetch(`!{server}/api/v2/stats/page_comment?${searchParams}`, headerList) - const result = await res.json() - - keyArray.forEach((key, index) => { - eleGroup[index].textContent = result.data[key] || 0 - }) - } catch (err) { - console.error(err) - } - } - - window.pjax ? getArtalkCount() : window.addEventListener('load', getArtalkCount) +- const { server, site } = theme.artalk + +script. + (() => { + const getArtalkCount = async() => { + try { + const eleGroup = document.querySelectorAll('#recent-posts .artalk-count') + const keyArray = Array.from(eleGroup).map(i => i.getAttribute('data-page-key')) + + const headerList = { + method: 'GET', + } + + const searchParams = new URLSearchParams({ + 'site_name': '!{site}', + 'page_keys': keyArray + }) + + const res = await fetch(`!{server}/api/v2/stats/page_comment?${searchParams}`, headerList) + const result = await res.json() + + keyArray.forEach((key, index) => { + eleGroup[index].textContent = result.data[key] || 0 + }) + } catch (err) { + console.error(err) + } + } + + window.pjax ? getArtalkCount() : window.addEventListener('load', getArtalkCount) })() \ No newline at end of file diff --git a/layout/includes/third-party/card-post-count/disqus.pug b/layout/includes/third-party/card-post-count/disqus.pug index 92a2d5b..d039d9a 100644 --- a/layout/includes/third-party/card-post-count/disqus.pug +++ b/layout/includes/third-party/card-post-count/disqus.pug @@ -1,25 +1,25 @@ -- const { shortname, apikey } = theme.disqus -script. - (() => { - const getCount = async () => { - try { - const eleGroup = document.querySelectorAll('#recent-posts .disqus-count') - const cleanedLinks = Array.from(eleGroup).map(i => `thread:link=${i.href.replace(/#post-comment$/, '')}`); - - const res = await fetch(`https://disqus.com/api/3.0/threads/set.json?forum=!{shortname}&api_key=!{apikey}&${cleanedLinks.join('&')}`,{ - method: 'GET' - }) - const result = await res.json() - - eleGroup.forEach(i => { - const cleanedLink = i.href.replace(/#post-comment$/, '') - const urlData = result.response.find(data => data.link === cleanedLink) || { posts: 0 } - i.textContent = urlData.posts - }) - } catch (err) { - console.error(err) - } - } - - window.pjax ? getCount() : window.addEventListener('load', getCount) - })() +- const { shortname, apikey } = theme.disqus +script. + (() => { + const getCount = async () => { + try { + const eleGroup = document.querySelectorAll('#recent-posts .disqus-count') + const cleanedLinks = Array.from(eleGroup).map(i => `thread:link=${i.href.replace(/#post-comment$/, '')}`); + + const res = await fetch(`https://disqus.com/api/3.0/threads/set.json?forum=!{shortname}&api_key=!{apikey}&${cleanedLinks.join('&')}`,{ + method: 'GET' + }) + const result = await res.json() + + eleGroup.forEach(i => { + const cleanedLink = i.href.replace(/#post-comment$/, '') + const urlData = result.response.find(data => data.link === cleanedLink) || { posts: 0 } + i.textContent = urlData.posts + }) + } catch (err) { + console.error(err) + } + } + + window.pjax ? getCount() : window.addEventListener('load', getCount) + })() diff --git a/layout/includes/third-party/card-post-count/fb.pug b/layout/includes/third-party/card-post-count/fb.pug index e6daba1..408ec2e 100644 --- a/layout/includes/third-party/card-post-count/fb.pug +++ b/layout/includes/third-party/card-post-count/fb.pug @@ -1,18 +1,18 @@ -- const fbSDKVer = 'v20.0' -- const fbSDK = `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` - -script. - (()=>{ - function loadFBComment () { - if (typeof FB === 'object') FB.XFBML.parse(document.getElementById('recent-posts')) - else { - let ele = document.createElement('script') - ele.setAttribute('src','!{fbSDK}') - ele.setAttribute('async', 'true') - ele.setAttribute('defer', 'true') - ele.setAttribute('crossorigin', 'anonymous') - document.body.appendChild(ele) - } - } - window.pjax ? loadFBComment() : window.addEventListener('load', loadFBComment) - })() +- const fbSDKVer = 'v20.0' +- const fbSDK = `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` + +script. + (()=>{ + function loadFBComment () { + if (typeof FB === 'object') FB.XFBML.parse(document.getElementById('recent-posts')) + else { + let ele = document.createElement('script') + ele.setAttribute('src','!{fbSDK}') + ele.setAttribute('async', 'true') + ele.setAttribute('defer', 'true') + ele.setAttribute('crossorigin', 'anonymous') + document.body.appendChild(ele) + } + } + window.pjax ? loadFBComment() : window.addEventListener('load', loadFBComment) + })() diff --git a/layout/includes/third-party/card-post-count/index.pug b/layout/includes/third-party/card-post-count/index.pug index 5b2685c..0079318 100644 --- a/layout/includes/third-party/card-post-count/index.pug +++ b/layout/includes/third-party/card-post-count/index.pug @@ -1,16 +1,16 @@ -case theme.comments.use[0] - when 'Twikoo' - include ./twikoo.pug - when 'Disqus' - when 'Disqusjs' - include ./disqus.pug - when 'Valine' - include ./valine.pug - when 'Waline' - include ./waline.pug - when 'Facebook Comments' - include ./fb.pug - when 'Remark42' - include ./remark42.pug - when 'Artalk' +case theme.comments.use[0] + when 'Twikoo' + include ./twikoo.pug + when 'Disqus' + when 'Disqusjs' + include ./disqus.pug + when 'Valine' + include ./valine.pug + when 'Waline' + include ./waline.pug + when 'Facebook Comments' + include ./fb.pug + when 'Remark42' + include ./remark42.pug + when 'Artalk' include ./artalk.pug \ No newline at end of file diff --git a/layout/includes/third-party/card-post-count/remark42.pug b/layout/includes/third-party/card-post-count/remark42.pug index b67164f..5fbb840 100644 --- a/layout/includes/third-party/card-post-count/remark42.pug +++ b/layout/includes/third-party/card-post-count/remark42.pug @@ -1,18 +1,18 @@ -- const { host, siteId, option } = theme.remark42 - -script. - (()=>{ - window.remark_config = Object.assign({ - host: '!{host}', - site_id: '!{siteId}', - },!{JSON.stringify(option)}) - - function getCount () { - const s = document.createElement('script') - s.src = remark_config.host + '/web/counter.js' - s.defer = true - document.head.appendChild(s) - } - - window.pjax ? getCount() : window.addEventListener('load', getCount) +- const { host, siteId, option } = theme.remark42 + +script. + (()=>{ + window.remark_config = Object.assign({ + host: '!{host}', + site_id: '!{siteId}', + },!{JSON.stringify(option)}) + + function getCount () { + const s = document.createElement('script') + s.src = remark_config.host + '/web/counter.js' + s.defer = true + document.head.appendChild(s) + } + + window.pjax ? getCount() : window.addEventListener('load', getCount) })() \ No newline at end of file diff --git a/layout/includes/third-party/card-post-count/twikoo.pug b/layout/includes/third-party/card-post-count/twikoo.pug index 8d47c05..e104fa9 100644 --- a/layout/includes/third-party/card-post-count/twikoo.pug +++ b/layout/includes/third-party/card-post-count/twikoo.pug @@ -1,37 +1,37 @@ -script. - (() => { - const getCommentUrl = () => { - const eleGroup = document.querySelectorAll('#recent-posts .article-title') - let urlArray = [] - eleGroup.forEach(i=>{ - urlArray.push(i.getAttribute('href')) - }) - return urlArray - } - - const getCount = () => { - const runTwikoo = () => { - twikoo.getCommentsCount({ - envId: '!{theme.twikoo.envId}', - region: '!{theme.twikoo.region}', - urls: getCommentUrl(), - includeReply: false - }).then(function (res) { - document.querySelectorAll('#recent-posts .twikoo-count').forEach((item,index) => { - item.textContent = res[index].count - }) - }).catch(function (err) { - console.log(err) - }) - } - - if (typeof twikoo === 'object') { - runTwikoo() - } else { - btf.getScript('!{url_for(theme.asset.twikoo)}').then(runTwikoo) - } - } - - window.pjax ? getCount() : window.addEventListener('load', getCount) - +script. + (() => { + const getCommentUrl = () => { + const eleGroup = document.querySelectorAll('#recent-posts .article-title') + let urlArray = [] + eleGroup.forEach(i=>{ + urlArray.push(i.getAttribute('href')) + }) + return urlArray + } + + const getCount = () => { + const runTwikoo = () => { + twikoo.getCommentsCount({ + envId: '!{theme.twikoo.envId}', + region: '!{theme.twikoo.region}', + urls: getCommentUrl(), + includeReply: false + }).then(function (res) { + document.querySelectorAll('#recent-posts .twikoo-count').forEach((item,index) => { + item.textContent = res[index].count + }) + }).catch(function (err) { + console.log(err) + }) + } + + if (typeof twikoo === 'object') { + runTwikoo() + } else { + btf.getScript('!{url_for(theme.asset.twikoo)}').then(runTwikoo) + } + } + + window.pjax ? getCount() : window.addEventListener('load', getCount) + })() \ No newline at end of file diff --git a/layout/includes/third-party/card-post-count/valine.pug b/layout/includes/third-party/card-post-count/valine.pug index 1bbddde..6b583e2 100644 --- a/layout/includes/third-party/card-post-count/valine.pug +++ b/layout/includes/third-party/card-post-count/valine.pug @@ -1,20 +1,20 @@ -script. - (() => { - function loadValine () { - function initValine () { - let initData = { - el: '#vcomment', - appId: '#{theme.valine.appId}', - appKey: '#{theme.valine.appKey}', - serverURLs: '#{theme.valine.serverURLs}' - } - - const valine = new Valine(initData) - } - - if (typeof Valine === 'function') initValine() - else btf.getScript('!{url_for(theme.asset.valine)}').then(initValine) - } - - window.pjax ? loadValine() : window.addEventListener('load', loadValine) - })() +script. + (() => { + function loadValine () { + function initValine () { + let initData = { + el: '#vcomment', + appId: '#{theme.valine.appId}', + appKey: '#{theme.valine.appKey}', + serverURLs: '#{theme.valine.serverURLs}' + } + + const valine = new Valine(initData) + } + + if (typeof Valine === 'function') initValine() + else btf.getScript('!{url_for(theme.asset.valine)}').then(initValine) + } + + window.pjax ? loadValine() : window.addEventListener('load', loadValine) + })() diff --git a/layout/includes/third-party/card-post-count/waline.pug b/layout/includes/third-party/card-post-count/waline.pug index a8faf96..96e9657 100644 --- a/layout/includes/third-party/card-post-count/waline.pug +++ b/layout/includes/third-party/card-post-count/waline.pug @@ -1,21 +1,21 @@ -- const serverURL = theme.waline.serverURL.replace(/\/$/, '') -script. - (() => { - async function loadWaline () { - try { - const eleGroup = document.querySelectorAll('#recent-posts .waline-comment-count') - const keyArray = Array.from(eleGroup).map(i => i.getAttribute('data-path')) - - const res = await fetch(`!{serverURL}/api/comment?type=count&url=${keyArray}`, { method: 'GET' }) - const result = await res.json() - - result.data.forEach((count, index) => { - eleGroup[index].textContent = count - }) - } catch (err) { - console.error(err) - } - } - - window.pjax ? loadWaline() : window.addEventListener('load', loadWaline) - })() +- const serverURL = theme.waline.serverURL.replace(/\/$/, '') +script. + (() => { + async function loadWaline () { + try { + const eleGroup = document.querySelectorAll('#recent-posts .waline-comment-count') + const keyArray = Array.from(eleGroup).map(i => i.getAttribute('data-path')) + + const res = await fetch(`!{serverURL}/api/comment?type=count&url=${keyArray}`, { method: 'GET' }) + const result = await res.json() + + result.data.forEach((count, index) => { + eleGroup[index].textContent = count + }) + } catch (err) { + console.error(err) + } + } + + window.pjax ? loadWaline() : window.addEventListener('load', loadWaline) + })() diff --git a/layout/includes/third-party/chat/chatra.pug b/layout/includes/third-party/chat/chatra.pug index 0fad991..e4a6900 100644 --- a/layout/includes/third-party/chat/chatra.pug +++ b/layout/includes/third-party/chat/chatra.pug @@ -1,38 +1,38 @@ -//- https://chatra.io/help/api/ -script. - (() => { - window.ChatraID = '#{theme.chatra.id}' - window.Chatra = window.Chatra || function() { - (window.Chatra.q = window.Chatra.q || []).push(arguments) - } - - btf.getScript('https://call.chatra.io/chatra.js').then(() => { - const isChatBtn = !{theme.chat.rightside_button} - const isChatHideShow = !{theme.chat.button_hide_show} - - if (isChatBtn) { - const close = () => { - Chatra('minimizeWidget') - Chatra('hide') - } - - const open = () => { - Chatra('openChat', true) - Chatra('show') - } - - window.ChatraSetup = { startHidden: true } - - window.chatBtnFn = () => document.getElementById('chatra').classList.contains('chatra--expanded') ? close() : open() - - document.getElementById('chat-btn').style.display = 'block' - } else if (isChatHideShow) { - window.chatBtn = { - hide: () => Chatra('hide'), - show: () => Chatra('show') - } - } - }) - })() - - +//- https://chatra.io/help/api/ +script. + (() => { + window.ChatraID = '#{theme.chatra.id}' + window.Chatra = window.Chatra || function() { + (window.Chatra.q = window.Chatra.q || []).push(arguments) + } + + btf.getScript('https://call.chatra.io/chatra.js').then(() => { + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} + + if (isChatBtn) { + const close = () => { + Chatra('minimizeWidget') + Chatra('hide') + } + + const open = () => { + Chatra('openChat', true) + Chatra('show') + } + + window.ChatraSetup = { startHidden: true } + + window.chatBtnFn = () => document.getElementById('chatra').classList.contains('chatra--expanded') ? close() : open() + + document.getElementById('chat-btn').style.display = 'block' + } else if (isChatHideShow) { + window.chatBtn = { + hide: () => Chatra('hide'), + show: () => Chatra('show') + } + } + }) + })() + + diff --git a/layout/includes/third-party/chat/crisp.pug b/layout/includes/third-party/chat/crisp.pug index 08a1916..6485566 100644 --- a/layout/includes/third-party/chat/crisp.pug +++ b/layout/includes/third-party/chat/crisp.pug @@ -1,32 +1,32 @@ -script. - (() => { - window.$crisp = ['safe', true] - window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}" - - btf.getScript('https://client.crisp.chat/l.js').then(() => { - const isChatBtn = !{theme.chat.rightside_button} - const isChatHideShow = !{theme.chat.button_hide_show} - - if (isChatBtn) { - const open = () => { - $crisp.push(["do", "chat:show"]) - $crisp.push(["do", "chat:open"]) - } - - const close = () => $crisp.push(["do", "chat:hide"]) - - close() - - $crisp.push(["on", "chat:closed", close]) - - window.chatBtnFn = () => $crisp.is("chat:visible") ? close() : open() - - document.getElementById('chat-btn').style.display = 'block' - } else if (isChatHideShow) { - window.chatBtn = { - hide: () => $crisp.push(["do", "chat:hide"]), - show: () => $crisp.push(["do", "chat:show"]) - } - } - }) +script. + (() => { + window.$crisp = ['safe', true] + window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}" + + btf.getScript('https://client.crisp.chat/l.js').then(() => { + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} + + if (isChatBtn) { + const open = () => { + $crisp.push(["do", "chat:show"]) + $crisp.push(["do", "chat:open"]) + } + + const close = () => $crisp.push(["do", "chat:hide"]) + + close() + + $crisp.push(["on", "chat:closed", close]) + + window.chatBtnFn = () => $crisp.is("chat:visible") ? close() : open() + + document.getElementById('chat-btn').style.display = 'block' + } else if (isChatHideShow) { + window.chatBtn = { + hide: () => $crisp.push(["do", "chat:hide"]), + show: () => $crisp.push(["do", "chat:show"]) + } + } + }) })() \ No newline at end of file diff --git a/layout/includes/third-party/chat/index.pug b/layout/includes/third-party/chat/index.pug index 273d040..dada453 100644 --- a/layout/includes/third-party/chat/index.pug +++ b/layout/includes/third-party/chat/index.pug @@ -1,7 +1,7 @@ -case theme.chat.use - when 'chatra' - include ./chatra.pug - when 'tidio' - include ./tidio.pug - when 'crisp' +case theme.chat.use + when 'chatra' + include ./chatra.pug + when 'tidio' + include ./tidio.pug + when 'crisp' include ./crisp.pug \ No newline at end of file diff --git a/layout/includes/third-party/chat/tidio.pug b/layout/includes/third-party/chat/tidio.pug index f9d40ea..83ca1ec 100644 --- a/layout/includes/third-party/chat/tidio.pug +++ b/layout/includes/third-party/chat/tidio.pug @@ -1,45 +1,45 @@ -script. - (() => { - btf.getScript('//code.tidio.co/!{theme.tidio.public_key}.js').then(() => { - const isChatBtn = !{theme.chat.rightside_button} - const isChatHideShow = !{theme.chat.button_hide_show} - - if (isChatBtn) { - let isShow = false - const close = () => { - window.tidioChatApi.hide() - isShow = false - } - - const open = () => { - window.tidioChatApi.open() - window.tidioChatApi.show() - isShow = true - } - - const onTidioChatApiReady = () => { - window.tidioChatApi.hide() - window.tidioChatApi.on("close", close) - } - if (window.tidioChatApi) { - window.tidioChatApi.on("ready", onTidioChatApiReady) - } else { - document.addEventListener("tidioChat-ready", onTidioChatApiReady) - } - - window.chatBtnFn = () => { - if (!window.tidioChatApi) return - isShow ? close() : open() - } - - document.getElementById('chat-btn').style.display = 'block' - - } else if (isChatHideShow) { - window.chatBtn = { - hide: () => window.tidioChatApi && window.tidioChatApi.hide(), - show: () => window.tidioChatApi && window.tidioChatApi.show() - } - } - }) - })() - +script. + (() => { + btf.getScript('//code.tidio.co/!{theme.tidio.public_key}.js').then(() => { + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} + + if (isChatBtn) { + let isShow = false + const close = () => { + window.tidioChatApi.hide() + isShow = false + } + + const open = () => { + window.tidioChatApi.open() + window.tidioChatApi.show() + isShow = true + } + + const onTidioChatApiReady = () => { + window.tidioChatApi.hide() + window.tidioChatApi.on("close", close) + } + if (window.tidioChatApi) { + window.tidioChatApi.on("ready", onTidioChatApiReady) + } else { + document.addEventListener("tidioChat-ready", onTidioChatApiReady) + } + + window.chatBtnFn = () => { + if (!window.tidioChatApi) return + isShow ? close() : open() + } + + document.getElementById('chat-btn').style.display = 'block' + + } else if (isChatHideShow) { + window.chatBtn = { + hide: () => window.tidioChatApi && window.tidioChatApi.hide(), + show: () => window.tidioChatApi && window.tidioChatApi.show() + } + } + }) + })() + diff --git a/layout/includes/third-party/comments/artalk.pug b/layout/includes/third-party/comments/artalk.pug index 0113fc3..7d0e857 100644 --- a/layout/includes/third-party/comments/artalk.pug +++ b/layout/includes/third-party/comments/artalk.pug @@ -1,73 +1,73 @@ -- const { server, site, option } = theme.artalk -- const { use, lazyload } = theme.comments - -script. - (() => { - let artalkItem = null - const option = !{JSON.stringify(option)} - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - - const destroyArtalk = () => { - if (artalkItem) { - artalkItem.destroy() - artalkItem = null - } - } - - const artalkChangeMode = theme => artalkItem && artalkItem.setDarkMode(theme === 'dark') - - const initArtalk = (el = document, pageKey = location.pathname) => { - artalkItem = Artalk.init({ - el: el.querySelector('#artalk-wrap'), - server: '!{server}', - site: '!{site}', - darkMode: document.documentElement.getAttribute('data-theme') === 'dark', - ...option, - pageKey: isShuoshuo ? pageKey : (option && option.pageKey) || pageKey - }) - - if (GLOBAL_CONFIG.lightbox === 'null') return - artalkItem.on('list-loaded', () => { - artalkItem.ctx.get('list').getCommentNodes().forEach(comment => { - const $content = comment.getRender().$content - btf.loadLightbox($content.querySelectorAll('img:not([atk-emoticon])')) - }) - }) - - if (isShuoshuo) { - window.shuoshuoComment.destroyArtalk = () => { - destroyArtalk() - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - btf.addGlobalFn('pjaxSendOnce', destroyArtalk, 'destroyArtalk') - btf.addGlobalFn('themeChange', artalkChangeMode, 'artalk') - } - - const loadArtalk = async (el, pageKey) => { - if (typeof Artalk === 'object') initArtalk(el, pageKey) - else { - await btf.getCSS('!{theme.asset.artalk_css}') - await btf.getScript('!{theme.asset.artalk_js}') - initArtalk(el, pageKey) - } - } - - if (isShuoshuo) { - '!{use[0]}' === 'Artalk' - ? window.shuoshuoComment = { loadComment: loadArtalk } - : window.loadOtherComment = loadArtalk - return - } - - if ('!{use[0]}' === 'Artalk' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('artalk-wrap'), loadArtalk) - else setTimeout(loadArtalk, 100) - } else { - window.loadOtherComment = loadArtalk - } +- const { server, site, option } = theme.artalk +- const { use, lazyload } = theme.comments + +script. + (() => { + let artalkItem = null + const option = !{JSON.stringify(option)} + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + + const destroyArtalk = () => { + if (artalkItem) { + artalkItem.destroy() + artalkItem = null + } + } + + const artalkChangeMode = theme => artalkItem && artalkItem.setDarkMode(theme === 'dark') + + const initArtalk = (el = document, pageKey = location.pathname) => { + artalkItem = Artalk.init({ + el: el.querySelector('#artalk-wrap'), + server: '!{server}', + site: '!{site}', + darkMode: document.documentElement.getAttribute('data-theme') === 'dark', + ...option, + pageKey: isShuoshuo ? pageKey : (option && option.pageKey) || pageKey + }) + + if (GLOBAL_CONFIG.lightbox === 'null') return + artalkItem.on('list-loaded', () => { + artalkItem.ctx.get('list').getCommentNodes().forEach(comment => { + const $content = comment.getRender().$content + btf.loadLightbox($content.querySelectorAll('img:not([atk-emoticon])')) + }) + }) + + if (isShuoshuo) { + window.shuoshuoComment.destroyArtalk = () => { + destroyArtalk() + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + btf.addGlobalFn('pjaxSendOnce', destroyArtalk, 'destroyArtalk') + btf.addGlobalFn('themeChange', artalkChangeMode, 'artalk') + } + + const loadArtalk = async (el, pageKey) => { + if (typeof Artalk === 'object') initArtalk(el, pageKey) + else { + await btf.getCSS('!{theme.asset.artalk_css}') + await btf.getScript('!{theme.asset.artalk_js}') + initArtalk(el, pageKey) + } + } + + if (isShuoshuo) { + '!{use[0]}' === 'Artalk' + ? window.shuoshuoComment = { loadComment: loadArtalk } + : window.loadOtherComment = loadArtalk + return + } + + if ('!{use[0]}' === 'Artalk' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('artalk-wrap'), loadArtalk) + else setTimeout(loadArtalk, 100) + } else { + window.loadOtherComment = loadArtalk + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/disqus.pug b/layout/includes/third-party/comments/disqus.pug index eeca5c4..9fe6454 100644 --- a/layout/includes/third-party/comments/disqus.pug +++ b/layout/includes/third-party/comments/disqus.pug @@ -1,80 +1,80 @@ -- const disqusPageTitle = page.title.replace(/'/ig,"\\'") -- const { shortname, apikey } = theme.disqus -- const { use, lazyload, count } = theme.comments - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - - const disqusReset = conf => { - window.DISQUS && window.DISQUS.reset({ - reload: true, - config: conf - }) - } - - const loadDisqus = (el, path) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyDisqus = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - window.disqus_identifier = isShuoshuo ? path : '!{ url_for(page.path) }' - window.disqus_url = isShuoshuo ? location.origin + path : '!{ page.permalink }' - - const disqus_config = function () { - this.page.url = disqus_url - this.page.identifier = disqus_identifier - this.page.title = '!{ disqusPageTitle }' - } - - if (window.DISQUS) disqusReset(disqus_config) - else { - const script = document.createElement('script') - script.src = 'https://!{shortname}.disqus.com/embed.js' - script.setAttribute('data-timestamp', +new Date()) - document.head.appendChild(script) - } - - btf.addGlobalFn('themeChange', () => disqusReset(disqus_config), 'disqus') - } - - const getCount = async() => { - try { - const eleGroup = document.querySelector('#post-meta .disqus-comment-count') - if (!eleGroup) return - const cleanedLinks = eleGroup.href.replace(/#post-comment$/, '') - - const res = await fetch(`https://disqus.com/api/3.0/threads/set.json?forum=!{shortname}&api_key=!{apikey}&thread:link=${cleanedLinks}`,{ - method: 'GET' - }) - const result = await res.json() - - const count = result.response.length ? result.response[0].posts : 0 - eleGroup.textContent = count - } catch (err) { - console.error(err) - } - } - - if (isShuoshuo) { - '!{use[0]}' === 'Disqus' - ? window.shuoshuoComment = { loadComment: loadDisqus } - : window.loadOtherComment = loadDisqus - return - } - - if ('!{use[0]}' === 'Disqus' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('disqus_thread'), loadDisqus) - else { - loadDisqus() - !{ count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : '' } - } - } else { - window.loadOtherComment = loadDisqus - } - })() +- const disqusPageTitle = page.title.replace(/'/ig,"\\'") +- const { shortname, apikey } = theme.disqus +- const { use, lazyload, count } = theme.comments + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + + const disqusReset = conf => { + window.DISQUS && window.DISQUS.reset({ + reload: true, + config: conf + }) + } + + const loadDisqus = (el, path) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyDisqus = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + window.disqus_identifier = isShuoshuo ? path : '!{ url_for(page.path) }' + window.disqus_url = isShuoshuo ? location.origin + path : '!{ page.permalink }' + + const disqus_config = function () { + this.page.url = disqus_url + this.page.identifier = disqus_identifier + this.page.title = '!{ disqusPageTitle }' + } + + if (window.DISQUS) disqusReset(disqus_config) + else { + const script = document.createElement('script') + script.src = 'https://!{shortname}.disqus.com/embed.js' + script.setAttribute('data-timestamp', +new Date()) + document.head.appendChild(script) + } + + btf.addGlobalFn('themeChange', () => disqusReset(disqus_config), 'disqus') + } + + const getCount = async() => { + try { + const eleGroup = document.querySelector('#post-meta .disqus-comment-count') + if (!eleGroup) return + const cleanedLinks = eleGroup.href.replace(/#post-comment$/, '') + + const res = await fetch(`https://disqus.com/api/3.0/threads/set.json?forum=!{shortname}&api_key=!{apikey}&thread:link=${cleanedLinks}`,{ + method: 'GET' + }) + const result = await res.json() + + const count = result.response.length ? result.response[0].posts : 0 + eleGroup.textContent = count + } catch (err) { + console.error(err) + } + } + + if (isShuoshuo) { + '!{use[0]}' === 'Disqus' + ? window.shuoshuoComment = { loadComment: loadDisqus } + : window.loadOtherComment = loadDisqus + return + } + + if ('!{use[0]}' === 'Disqus' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('disqus_thread'), loadDisqus) + else { + loadDisqus() + !{ count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : '' } + } + } else { + window.loadOtherComment = loadDisqus + } + })() diff --git a/layout/includes/third-party/comments/disqusjs.pug b/layout/includes/third-party/comments/disqusjs.pug index ae7ff06..ef2a235 100644 --- a/layout/includes/third-party/comments/disqusjs.pug +++ b/layout/includes/third-party/comments/disqusjs.pug @@ -1,87 +1,87 @@ -- let disqusjsPageTitle = page.title && page.title.replace(/'/ig,"\\'") -- const { shortname:dqShortname, apikey:dqApikey, option:dqOption } = theme.disqusjs - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'== 'shuoshuo' - const dqOption = !{JSON.stringify(dqOption)} - - const destroyDisqusjs = () => { - disqusjs.destroy() - window.disqusjs = null - } - - const themeChange = (el, path) => { - destroyDisqusjs() - initDisqusjs(el, path) - } - - const initDisqusjs = (el = document, path) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyDisqusjs = () => { - destroyDisqusjs() - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - disqusjs = new DisqusJS({ - shortname: '!{dqShortname}', - title: '!{ disqusjsPageTitle }', - apikey: '!{dqApikey}', - ...dqOption, - identifier: isShuoshuo ? path : (dqOption && dqOption.identifier) || '!{ url_for(page.path) }', - url: isShuoshuo ? location.origin + path : (dqOption && dqOption.url) || '!{ page.permalink }' - }) - - disqusjs.render(el.querySelector('#disqusjs-wrap')) - - btf.addGlobalFn('themeChange', () => themeChange(el, path), 'disqusjs') - } - - const loadDisqusjs = async(el, path) => { - if (window.disqusJsLoad) initDisqusjs(el, path) - else { - await btf.getCSS('!{url_for(theme.asset.disqusjs_css)}') - await btf.getScript('!{url_for(theme.asset.disqusjs)}') - initDisqusjs(el, path) - window.disqusJsLoad = true - } - } - - const getCount = async() => { - try { - const eleGroup = document.querySelector('#post-meta .disqusjs-comment-count') - if (!eleGroup) return - const cleanedLinks = eleGroup.href.replace(/#post-comment$/, '') - - const res = await fetch(`https://disqus.com/api/3.0/threads/set.json?forum=!{dqShortname}&api_key=!{dqApikey}&thread:link=${cleanedLinks}`,{ - method: 'GET' - }) - const result = await res.json() - const count = result.response.length ? result.response[0].posts : 0 - eleGroup.textContent = count - } catch (err) { - console.error(err) - } - } - - if (isShuoshuo) { - '!{theme.comments.use[0]}' === 'Disqusjs' - ? window.shuoshuoComment = { loadComment: loadDisqusjs } - : window.loadOtherComment = loadDisqusjs - return - } - - if ('!{theme.comments.use[0]}' === 'Disqusjs' || !!{theme.comments.lazyload}) { - if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqusjs-wrap'), loadDisqusjs) - else { - loadDisqusjs() - !{ theme.comments.count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : '' } - } - } else { - window.loadOtherComment = loadDisqusjs - } +- let disqusjsPageTitle = page.title && page.title.replace(/'/ig,"\\'") +- const { shortname:dqShortname, apikey:dqApikey, option:dqOption } = theme.disqusjs + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'== 'shuoshuo' + const dqOption = !{JSON.stringify(dqOption)} + + const destroyDisqusjs = () => { + disqusjs.destroy() + window.disqusjs = null + } + + const themeChange = (el, path) => { + destroyDisqusjs() + initDisqusjs(el, path) + } + + const initDisqusjs = (el = document, path) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyDisqusjs = () => { + destroyDisqusjs() + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + disqusjs = new DisqusJS({ + shortname: '!{dqShortname}', + title: '!{ disqusjsPageTitle }', + apikey: '!{dqApikey}', + ...dqOption, + identifier: isShuoshuo ? path : (dqOption && dqOption.identifier) || '!{ url_for(page.path) }', + url: isShuoshuo ? location.origin + path : (dqOption && dqOption.url) || '!{ page.permalink }' + }) + + disqusjs.render(el.querySelector('#disqusjs-wrap')) + + btf.addGlobalFn('themeChange', () => themeChange(el, path), 'disqusjs') + } + + const loadDisqusjs = async(el, path) => { + if (window.disqusJsLoad) initDisqusjs(el, path) + else { + await btf.getCSS('!{url_for(theme.asset.disqusjs_css)}') + await btf.getScript('!{url_for(theme.asset.disqusjs)}') + initDisqusjs(el, path) + window.disqusJsLoad = true + } + } + + const getCount = async() => { + try { + const eleGroup = document.querySelector('#post-meta .disqusjs-comment-count') + if (!eleGroup) return + const cleanedLinks = eleGroup.href.replace(/#post-comment$/, '') + + const res = await fetch(`https://disqus.com/api/3.0/threads/set.json?forum=!{dqShortname}&api_key=!{dqApikey}&thread:link=${cleanedLinks}`,{ + method: 'GET' + }) + const result = await res.json() + const count = result.response.length ? result.response[0].posts : 0 + eleGroup.textContent = count + } catch (err) { + console.error(err) + } + } + + if (isShuoshuo) { + '!{theme.comments.use[0]}' === 'Disqusjs' + ? window.shuoshuoComment = { loadComment: loadDisqusjs } + : window.loadOtherComment = loadDisqusjs + return + } + + if ('!{theme.comments.use[0]}' === 'Disqusjs' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqusjs-wrap'), loadDisqusjs) + else { + loadDisqusjs() + !{ theme.comments.count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : '' } + } + } else { + window.loadOtherComment = loadDisqusjs + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/facebook_comments.pug b/layout/includes/third-party/comments/facebook_comments.pug index c62fa30..25945db 100644 --- a/layout/includes/third-party/comments/facebook_comments.pug +++ b/layout/includes/third-party/comments/facebook_comments.pug @@ -1,64 +1,64 @@ -- const fbSDKVer = 'v20.0' -- const fbSDK = `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` - -script. - (()=>{ - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'== 'shuoshuo' - - const loadFBComment = (el = document, path) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyFB = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '
') - - const themeNow = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light' - const $fbComment = el.getElementsByClassName('fb-comments')[0] - $fbComment.setAttribute('data-colorscheme',themeNow) - $fbComment.setAttribute('data-href', isShuoshuo ? '!{urlNoIndex(page.permalink)}' + '#' + path : '!{urlNoIndex(page.permalink)}') - - if (typeof FB === 'object') { - FB.XFBML.parse(document.getElementsByClassName('post-meta-commentcount')[0]) - FB.XFBML.parse(el.querySelector('#post-comment')) - } - else { - let ele = document.createElement('script') - ele.setAttribute('src','!{fbSDK}') - ele.setAttribute('async', 'true') - ele.setAttribute('defer', 'true') - ele.setAttribute('crossorigin', 'anonymous') - ele.setAttribute('id', 'facebook-jssdk') - document.getElementById('fb-root').insertAdjacentElement('afterbegin',ele) - } - } - - const fbModeChange = theme => { - const $fbComment = document.getElementsByClassName('fb-comments')[0] - if ($fbComment && typeof FB === 'object') { - $fbComment.setAttribute('data-colorscheme',theme) - FB.XFBML.parse(document.getElementById('post-comment')) - } - } - - btf.addGlobalFn('themeChange', fbModeChange, 'facebook_comments') - - if (isShuoshuo) { - '!{theme.comments.use[0]}' === 'Facebook Comments' - ? window.shuoshuoComment = { loadComment: loadFBComment } - : window.loadOtherComment = loadFBComment - return - } - - if ('!{theme.comments.use[0]}' === 'Facebook Comments' || !!{theme.comments.lazyload}) { - if (!{theme.comments.lazyload}) btf.loadComment(document.querySelector('#post-comment .fb-comments'), loadFBComment) - else loadFBComment() - } else { - window.loadOtherComment = loadFBComment - } - })() - +- const fbSDKVer = 'v20.0' +- const fbSDK = `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` + +script. + (()=>{ + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo'== 'shuoshuo' + + const loadFBComment = (el = document, path) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyFB = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '
') + + const themeNow = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light' + const $fbComment = el.getElementsByClassName('fb-comments')[0] + $fbComment.setAttribute('data-colorscheme',themeNow) + $fbComment.setAttribute('data-href', isShuoshuo ? '!{urlNoIndex(page.permalink)}' + '#' + path : '!{urlNoIndex(page.permalink)}') + + if (typeof FB === 'object') { + FB.XFBML.parse(document.getElementsByClassName('post-meta-commentcount')[0]) + FB.XFBML.parse(el.querySelector('#post-comment')) + } + else { + let ele = document.createElement('script') + ele.setAttribute('src','!{fbSDK}') + ele.setAttribute('async', 'true') + ele.setAttribute('defer', 'true') + ele.setAttribute('crossorigin', 'anonymous') + ele.setAttribute('id', 'facebook-jssdk') + document.getElementById('fb-root').insertAdjacentElement('afterbegin',ele) + } + } + + const fbModeChange = theme => { + const $fbComment = document.getElementsByClassName('fb-comments')[0] + if ($fbComment && typeof FB === 'object') { + $fbComment.setAttribute('data-colorscheme',theme) + FB.XFBML.parse(document.getElementById('post-comment')) + } + } + + btf.addGlobalFn('themeChange', fbModeChange, 'facebook_comments') + + if (isShuoshuo) { + '!{theme.comments.use[0]}' === 'Facebook Comments' + ? window.shuoshuoComment = { loadComment: loadFBComment } + : window.loadOtherComment = loadFBComment + return + } + + if ('!{theme.comments.use[0]}' === 'Facebook Comments' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.querySelector('#post-comment .fb-comments'), loadFBComment) + else loadFBComment() + } else { + window.loadOtherComment = loadFBComment + } + })() + diff --git a/layout/includes/third-party/comments/giscus.pug b/layout/includes/third-party/comments/giscus.pug index c370e98..c4b9389 100644 --- a/layout/includes/third-party/comments/giscus.pug +++ b/layout/includes/third-party/comments/giscus.pug @@ -1,82 +1,82 @@ -- 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. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - - const getGiscusTheme = theme => theme === 'dark' ? '!{dark_theme}' : '!{light_theme}' - - const createScriptElement = config => { - const ele = document.createElement('script') - Object.entries(config).forEach(([key, value]) => { - ele.setAttribute(key, value) - }) - return ele - } - - const loadGiscus = (el = document, key) => { - const mappingConfig = isShuoshuo - ? { 'data-mapping': 'specific', 'data-term': key } - : { 'data-mapping': (option && option['data-mapping']) || 'pathname' } - - const giscusConfig = { - src: '!{giscusUrl}', - 'data-repo': '!{repo}', - 'data-repo-id': '!{repo_id}', - 'data-category-id': '!{category_id}', - 'data-theme': getGiscusTheme(document.documentElement.getAttribute('data-theme')), - 'data-reactions-enabled': '1', - crossorigin: 'anonymous', - async: true, - ...option, - ...mappingConfig - } - - const scriptElement = createScriptElement(giscusConfig) - - el.querySelector('#giscus-wrap').appendChild(scriptElement) - - if (isShuoshuo) { - window.shuoshuoComment.destroyGiscus = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - } - - const changeGiscusTheme = theme => { - const iframe = document.querySelector('#giscus-wrap iframe') - if (iframe) { - const message = { - giscus: { - setConfig: { - theme: getGiscusTheme(theme) - } - } - } - iframe.contentWindow.postMessage(message, '!{giscusOriginUrl}') - } - } - - btf.addGlobalFn('themeChange', changeGiscusTheme, 'giscus') - - if (isShuoshuo) { - '!{use[0]}' === 'Giscus' - ? window.shuoshuoComment = { loadComment: loadGiscus } - : window.loadOtherComment = loadGiscus - return - } - - if ('!{use[0]}' === 'Giscus' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('giscus-wrap'), loadGiscus) - else loadGiscus() - } else { - window.loadOtherComment = loadGiscus - } - })() +- 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. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + + const getGiscusTheme = theme => theme === 'dark' ? '!{dark_theme}' : '!{light_theme}' + + const createScriptElement = config => { + const ele = document.createElement('script') + Object.entries(config).forEach(([key, value]) => { + ele.setAttribute(key, value) + }) + return ele + } + + const loadGiscus = (el = document, key) => { + const mappingConfig = isShuoshuo + ? { 'data-mapping': 'specific', 'data-term': key } + : { 'data-mapping': (option && option['data-mapping']) || 'pathname' } + + const giscusConfig = { + src: '!{giscusUrl}', + 'data-repo': '!{repo}', + 'data-repo-id': '!{repo_id}', + 'data-category-id': '!{category_id}', + 'data-theme': getGiscusTheme(document.documentElement.getAttribute('data-theme')), + 'data-reactions-enabled': '1', + crossorigin: 'anonymous', + async: true, + ...option, + ...mappingConfig + } + + const scriptElement = createScriptElement(giscusConfig) + + el.querySelector('#giscus-wrap').appendChild(scriptElement) + + if (isShuoshuo) { + window.shuoshuoComment.destroyGiscus = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + } + + const changeGiscusTheme = theme => { + const iframe = document.querySelector('#giscus-wrap iframe') + if (iframe) { + const message = { + giscus: { + setConfig: { + theme: getGiscusTheme(theme) + } + } + } + iframe.contentWindow.postMessage(message, '!{giscusOriginUrl}') + } + } + + btf.addGlobalFn('themeChange', changeGiscusTheme, 'giscus') + + if (isShuoshuo) { + '!{use[0]}' === 'Giscus' + ? window.shuoshuoComment = { loadComment: loadGiscus } + : window.loadOtherComment = loadGiscus + return + } + + if ('!{use[0]}' === 'Giscus' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('giscus-wrap'), loadGiscus) + else loadGiscus() + } else { + window.loadOtherComment = loadGiscus + } + })() diff --git a/layout/includes/third-party/comments/gitalk.pug b/layout/includes/third-party/comments/gitalk.pug index d13bcb3..8a201aa 100644 --- a/layout/includes/third-party/comments/gitalk.pug +++ b/layout/includes/third-party/comments/gitalk.pug @@ -1,64 +1,64 @@ -- const { client_id, client_secret, repo, owner, admin, option } = theme.gitalk - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - - const commentCount = n => { - const isCommentCount = document.querySelector('#post-meta .gitalk-comment-count') - if (isCommentCount) { - isCommentCount.textContent= n - } - } - - const initGitalk = (el, path) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyGitalk = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - const gitalk = new Gitalk({ - clientID: '!{client_id}', - clientSecret: '!{client_secret}', - repo: '!{repo}', - owner: '!{owner}', - admin: ['!{admin}'], - updateCountCallback: commentCount, - ...option, - id: isShuoshuo ? path : (option && option.id) || '!{md5(page.path)}' - }) - - gitalk.render('gitalk-container') - } - - const loadGitalk = async(el, path) => { - if (typeof Gitalk === 'function') initGitalk(el, path) - else { - await btf.getCSS('!{url_for(theme.asset.gitalk_css)}') - await btf.getScript('!{url_for(theme.asset.gitalk)}') - initGitalk(el, path) - } - } - - if (isShuoshuo) { - '!{theme.comments.use[0]}' === 'Gitalk' - ? window.shuoshuoComment = { loadComment: loadGitalk } - : window.loadOtherComment = loadGitalk - return - } - - if ('!{theme.comments.use[0]}' === 'Gitalk' || !!{theme.comments.lazyload}) { - if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk) - else loadGitalk() - } else { - window.loadOtherComment = loadGitalk - } - })() - - - +- const { client_id, client_secret, repo, owner, admin, option } = theme.gitalk + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + + const commentCount = n => { + const isCommentCount = document.querySelector('#post-meta .gitalk-comment-count') + if (isCommentCount) { + isCommentCount.textContent= n + } + } + + const initGitalk = (el, path) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyGitalk = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + const gitalk = new Gitalk({ + clientID: '!{client_id}', + clientSecret: '!{client_secret}', + repo: '!{repo}', + owner: '!{owner}', + admin: ['!{admin}'], + updateCountCallback: commentCount, + ...option, + id: isShuoshuo ? path : (option && option.id) || '!{md5(page.path)}' + }) + + gitalk.render('gitalk-container') + } + + const loadGitalk = async(el, path) => { + if (typeof Gitalk === 'function') initGitalk(el, path) + else { + await btf.getCSS('!{url_for(theme.asset.gitalk_css)}') + await btf.getScript('!{url_for(theme.asset.gitalk)}') + initGitalk(el, path) + } + } + + if (isShuoshuo) { + '!{theme.comments.use[0]}' === 'Gitalk' + ? window.shuoshuoComment = { loadComment: loadGitalk } + : window.loadOtherComment = loadGitalk + return + } + + if ('!{theme.comments.use[0]}' === 'Gitalk' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk) + else loadGitalk() + } else { + window.loadOtherComment = loadGitalk + } + })() + + + diff --git a/layout/includes/third-party/comments/index.pug b/layout/includes/third-party/comments/index.pug index 3b8ceff..001f0bf 100644 --- a/layout/includes/third-party/comments/index.pug +++ b/layout/includes/third-party/comments/index.pug @@ -1,46 +1,46 @@ -- let defaultComment = theme.comments.use[0] -hr.custom-hr -#post-comment - .comment-head - .comment-headline - i.fas.fa-comments.fa-fw - span= ' ' + _p('comment') - - if theme.comments.use.length > 1 - .comment-switch - span.first-comment=defaultComment - span#switch-btn - span.second-comment=theme.comments.use[1] - - - .comment-wrap - each name in theme.comments.use - div - case name - when 'Disqus' - #disqus_thread - when 'Valine' - #vcomment.vcomment - when 'Disqusjs' - #disqusjs-wrap - when 'Livere' - #lv-container(data-id="city" data-uid=theme.livere.uid) - when 'Gitalk' - #gitalk-container - when 'Utterances' - #utterances-wrap - when 'Twikoo' - #twikoo-wrap - when 'Waline' - #waline-wrap - when 'Giscus' - #giscus-wrap - when 'Facebook Comments' - .fb-comments(data-colorscheme = theme.display_mode === 'dark' ? 'dark' : 'light' - data-numposts= theme.facebook_comments.pageSize || 10 - data-order-by= theme.facebook_comments.order_by || 'social' - data-width="100%") - when 'Remark42' - #remark42 - when 'Artalk' - #artalk-wrap +- let defaultComment = theme.comments.use[0] +hr.custom-hr +#post-comment + .comment-head + .comment-headline + i.fas.fa-comments.fa-fw + span= ' ' + _p('comment') + + if theme.comments.use.length > 1 + .comment-switch + span.first-comment=defaultComment + span#switch-btn + span.second-comment=theme.comments.use[1] + + + .comment-wrap + each name in theme.comments.use + div + case name + when 'Disqus' + #disqus_thread + when 'Valine' + #vcomment.vcomment + when 'Disqusjs' + #disqusjs-wrap + when 'Livere' + #lv-container(data-id="city" data-uid=theme.livere.uid) + when 'Gitalk' + #gitalk-container + when 'Utterances' + #utterances-wrap + when 'Twikoo' + #twikoo-wrap + when 'Waline' + #waline-wrap + when 'Giscus' + #giscus-wrap + when 'Facebook Comments' + .fb-comments(data-colorscheme = theme.display_mode === 'dark' ? 'dark' : 'light' + data-numposts= theme.facebook_comments.pageSize || 10 + data-order-by= theme.facebook_comments.order_by || 'social' + data-width="100%") + when 'Remark42' + #remark42 + when 'Artalk' + #artalk-wrap diff --git a/layout/includes/third-party/comments/js.pug b/layout/includes/third-party/comments/js.pug index bf1d872..baa6223 100644 --- a/layout/includes/third-party/comments/js.pug +++ b/layout/includes/third-party/comments/js.pug @@ -1,26 +1,26 @@ -each name in theme.comments.use - case name - when 'Valine' - !=partial('includes/third-party/comments/valine', {}, {cache: true}) - when 'Disqus' - include ./disqus.pug - when 'Disqusjs' - include ./disqusjs.pug - when 'Livere' - !=partial('includes/third-party/comments/livere', {}, {cache: true}) - when 'Gitalk' - include ./gitalk.pug - when 'Utterances' - !=partial('includes/third-party/comments/utterances', {}, {cache: true}) - when 'Twikoo' - !=partial('includes/third-party/comments/twikoo', {}, {cache: true}) - when 'Waline' - !=partial('includes/third-party/comments/waline', {}, {cache: true}) - when 'Giscus' - !=partial('includes/third-party/comments/giscus', {}, {cache: true}) - when 'Facebook Comments' - include ./facebook_comments.pug - when 'Remark42' - !=partial('includes/third-party/comments/remark42', {}, {cache: true}) - when 'Artalk' +each name in theme.comments.use + case name + when 'Valine' + !=partial('includes/third-party/comments/valine', {}, {cache: true}) + when 'Disqus' + include ./disqus.pug + when 'Disqusjs' + include ./disqusjs.pug + when 'Livere' + !=partial('includes/third-party/comments/livere', {}, {cache: true}) + when 'Gitalk' + include ./gitalk.pug + when 'Utterances' + !=partial('includes/third-party/comments/utterances', {}, {cache: true}) + when 'Twikoo' + !=partial('includes/third-party/comments/twikoo', {}, {cache: true}) + when 'Waline' + !=partial('includes/third-party/comments/waline', {}, {cache: true}) + when 'Giscus' + !=partial('includes/third-party/comments/giscus', {}, {cache: true}) + when 'Facebook Comments' + include ./facebook_comments.pug + when 'Remark42' + !=partial('includes/third-party/comments/remark42', {}, {cache: true}) + when 'Artalk' !=partial('includes/third-party/comments/artalk', {}, {cache: true}) \ No newline at end of file diff --git a/layout/includes/third-party/comments/livere.pug b/layout/includes/third-party/comments/livere.pug index f55cd96..b1fe23d 100644 --- a/layout/includes/third-party/comments/livere.pug +++ b/layout/includes/third-party/comments/livere.pug @@ -1,47 +1,47 @@ -- const { use, lazyload } = theme.comments - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - - const loadLivere = (el, path) => { - window.livereOptions = { - refer: path || location.pathname - } - - if (isShuoshuo) { - window.shuoshuoComment.destroyLivere = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - if (typeof LivereTower === 'object') window.LivereTower.init() - else { - (function(d, s) { - var j, e = d.getElementsByTagName(s)[0]; - if (typeof LivereTower === 'function') { return; } - j = d.createElement(s); - j.src = 'https://cdn-city.livere.com/js/embed.dist.js'; - j.async = true; - e.parentNode.insertBefore(j, e); - })(document, 'script'); - } - } - - if (isShuoshuo) { - '!{use[0]}' === 'Livere' - ? window.shuoshuoComment = { loadComment: loadLivere } - : window.loadOtherComment = loadLivere - return - } - - if ('!{use[0]}' === 'Livere' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('lv-container'), loadLivere) - else loadLivere() - } else { - window.loadOtherComment = loadLivere - } +- const { use, lazyload } = theme.comments + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + + const loadLivere = (el, path) => { + window.livereOptions = { + refer: path || location.pathname + } + + if (isShuoshuo) { + window.shuoshuoComment.destroyLivere = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + if (typeof LivereTower === 'object') window.LivereTower.init() + else { + (function(d, s) { + var j, e = d.getElementsByTagName(s)[0]; + if (typeof LivereTower === 'function') { return; } + j = d.createElement(s); + j.src = 'https://cdn-city.livere.com/js/embed.dist.js'; + j.async = true; + e.parentNode.insertBefore(j, e); + })(document, 'script'); + } + } + + if (isShuoshuo) { + '!{use[0]}' === 'Livere' + ? window.shuoshuoComment = { loadComment: loadLivere } + : window.loadOtherComment = loadLivere + return + } + + if ('!{use[0]}' === 'Livere' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('lv-container'), loadLivere) + else loadLivere() + } else { + window.loadOtherComment = loadLivere + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/remark42.pug b/layout/includes/third-party/comments/remark42.pug index 67980cb..2ef7188 100644 --- a/layout/includes/third-party/comments/remark42.pug +++ b/layout/includes/third-party/comments/remark42.pug @@ -1,78 +1,78 @@ -- const { host, siteId, option } = theme.remark42 - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - - const loadScript = src => { - const script = document.createElement('script') - script.src = src - script.defer = true - document.head.appendChild(script) - } - - const addRemark42 = () => loadScript('!{host}/web/embed.js') - - const getCount = () => document.querySelector('.remark42__counter') && loadScript('!{host}/web/count.js') - - const destroyRemark42 = () => window.remark42Instance && window.remark42Instance.destroy() - - const initRemark42 = remark_config => { - if (window.REMARK42) { - destroyRemark42() - window.remark42Instance = window.REMARK42.createInstance({ - ...remark_config - }) - } - } - - const loadRemark42 = (el, path) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyRemark42 = () => { - destroyRemark42() - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - window.remark_config = { - host: '!{host}', - site_id: '!{siteId}', - theme: document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light', - ...option, - url: isShuoshuo ? window.location.origin + path : (option && option.url) || window.location.origin + window.location.pathname - } - - if (window.REMARK42) { - initRemark42(remark_config) - getCount() - } else { - addRemark42() - window.addEventListener('REMARK42::ready', () => { - initRemark42(remark_config) - getCount() - }) - } - } - - const remarkChangeMode = theme => window.REMARK42 && window.REMARK42.changeTheme(theme) - - btf.addGlobalFn('themeChange', remarkChangeMode, 'remark42') - - if (isShuoshuo) { - '!{theme.comments.use[0]}' === 'Remark42' - ? window.shuoshuoComment = { loadComment: loadRemark42 } - : window.loadOtherComment = loadRemark42 - return - } - - if ('!{theme.comments.use[0]}' === 'Remark42' || !!{theme.comments.lazyload}) { - if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('remark42'), loadRemark42) - else loadRemark42() - } else { - window.loadOtherComment = loadRemark42 - } +- const { host, siteId, option } = theme.remark42 + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + + const loadScript = src => { + const script = document.createElement('script') + script.src = src + script.defer = true + document.head.appendChild(script) + } + + const addRemark42 = () => loadScript('!{host}/web/embed.js') + + const getCount = () => document.querySelector('.remark42__counter') && loadScript('!{host}/web/count.js') + + const destroyRemark42 = () => window.remark42Instance && window.remark42Instance.destroy() + + const initRemark42 = remark_config => { + if (window.REMARK42) { + destroyRemark42() + window.remark42Instance = window.REMARK42.createInstance({ + ...remark_config + }) + } + } + + const loadRemark42 = (el, path) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyRemark42 = () => { + destroyRemark42() + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + window.remark_config = { + host: '!{host}', + site_id: '!{siteId}', + theme: document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light', + ...option, + url: isShuoshuo ? window.location.origin + path : (option && option.url) || window.location.origin + window.location.pathname + } + + if (window.REMARK42) { + initRemark42(remark_config) + getCount() + } else { + addRemark42() + window.addEventListener('REMARK42::ready', () => { + initRemark42(remark_config) + getCount() + }) + } + } + + const remarkChangeMode = theme => window.REMARK42 && window.REMARK42.changeTheme(theme) + + btf.addGlobalFn('themeChange', remarkChangeMode, 'remark42') + + if (isShuoshuo) { + '!{theme.comments.use[0]}' === 'Remark42' + ? window.shuoshuoComment = { loadComment: loadRemark42 } + : window.loadOtherComment = loadRemark42 + return + } + + if ('!{theme.comments.use[0]}' === 'Remark42' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('remark42'), loadRemark42) + else loadRemark42() + } else { + window.loadOtherComment = loadRemark42 + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/twikoo.pug b/layout/includes/third-party/comments/twikoo.pug index 31fec77..94bc424 100644 --- a/layout/includes/third-party/comments/twikoo.pug +++ b/layout/includes/third-party/comments/twikoo.pug @@ -1,64 +1,64 @@ -- const { envId, region, option } = theme.twikoo -- const { use, lazyload, count } = theme.comments - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - - const getCount = () => { - const countELement = document.getElementById('twikoo-count') - if(!countELement) return - twikoo.getCommentsCount({ - envId: '!{envId}', - region: '!{region}', - urls: [window.location.pathname], - includeReply: false - }).then(res => { - countELement.textContent = res[0].count - }).catch(err => { - console.error(err) - }) - } - - const init = (el = document, path = location.pathname) => { - twikoo.init({ - el: el.querySelector('#twikoo-wrap'), - envId: '!{envId}', - region: '!{region}', - onCommentLoaded: () => { - btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)')) - }, - ...option, - path: isShuoshuo ? path : (option && option.path) || path - }) - - !{count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : ''} - - isShuoshuo && (window.shuoshuoComment.destroyTwikoo = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - }) - } - - const loadTwikoo = (el, path) => { - if (typeof twikoo === 'object') setTimeout(() => init(el, path), 0) - else btf.getScript('!{url_for(theme.asset.twikoo)}').then(() => init(el, path)) - } - - if (isShuoshuo) { - '!{use[0]}' === 'Twikoo' - ? window.shuoshuoComment = { loadComment: loadTwikoo } - : window.loadOtherComment = loadTwikoo - return - } - - if ('!{use[0]}' === 'Twikoo' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo) - else loadTwikoo() - } else { - window.loadOtherComment = loadTwikoo - } +- const { envId, region, option } = theme.twikoo +- const { use, lazyload, count } = theme.comments + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + + const getCount = () => { + const countELement = document.getElementById('twikoo-count') + if(!countELement) return + twikoo.getCommentsCount({ + envId: '!{envId}', + region: '!{region}', + urls: [window.location.pathname], + includeReply: false + }).then(res => { + countELement.textContent = res[0].count + }).catch(err => { + console.error(err) + }) + } + + const init = (el = document, path = location.pathname) => { + twikoo.init({ + el: el.querySelector('#twikoo-wrap'), + envId: '!{envId}', + region: '!{region}', + onCommentLoaded: () => { + btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.tk-owo-emotion)')) + }, + ...option, + path: isShuoshuo ? path : (option && option.path) || path + }) + + !{count ? `GLOBAL_CONFIG_SITE.pageType === 'post' && getCount()` : ''} + + isShuoshuo && (window.shuoshuoComment.destroyTwikoo = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + }) + } + + const loadTwikoo = (el, path) => { + if (typeof twikoo === 'object') setTimeout(() => init(el, path), 0) + else btf.getScript('!{url_for(theme.asset.twikoo)}').then(() => init(el, path)) + } + + if (isShuoshuo) { + '!{use[0]}' === 'Twikoo' + ? window.shuoshuoComment = { loadComment: loadTwikoo } + : window.loadOtherComment = loadTwikoo + return + } + + if ('!{use[0]}' === 'Twikoo' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo) + else loadTwikoo() + } else { + window.loadOtherComment = loadTwikoo + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/utterances.pug b/layout/includes/third-party/comments/utterances.pug index 4836557..7084e77 100644 --- a/layout/includes/third-party/comments/utterances.pug +++ b/layout/includes/third-party/comments/utterances.pug @@ -1,63 +1,63 @@ -- const { use, lazyload } = theme.comments -- 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. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - const getUtterancesTheme = theme => theme === 'dark' ? '#{dark_theme}' : '#{light_theme}' - - const loadUtterances = (el = document, key) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyUtterances = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - const config = { - src: '!{utterancesUrl}', - repo: '!{repo}', - theme: getUtterancesTheme(document.documentElement.getAttribute('data-theme')), - crossorigin: 'anonymous', - async: true, - ...option, - 'issue-term': isShuoshuo ? key : (option && option['issue-term']) || '!{issue_term}' - } - - const ele = document.createElement('script') - Object.entries(config).forEach(([key, value]) => ele.setAttribute(key, value)) - el.querySelector('#utterances-wrap').appendChild(ele) - } - - const changeUtterancesTheme = theme => { - const iframe = document.querySelector('#utterances-wrap iframe') - if (iframe) { - const message = { - type: 'set-theme', - theme: getUtterancesTheme(theme) - }; - iframe.contentWindow.postMessage(message, '!{utterancesOriginUrl}') - } - } - - btf.addGlobalFn('themeChange', changeUtterancesTheme, 'utterances') - - if (isShuoshuo) { - '!{use[0]}' === 'Utterances' - ? window.shuoshuoComment = { loadComment: loadUtterances } - : window.loadOtherComment = loadUtterances - return - } - - if ('!{use[0]}' === 'Utterances' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances) - else loadUtterances() - } else { - window.loadOtherComment = loadUtterances - } +- const { use, lazyload } = theme.comments +- 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. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + const getUtterancesTheme = theme => theme === 'dark' ? '#{dark_theme}' : '#{light_theme}' + + const loadUtterances = (el = document, key) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyUtterances = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + const config = { + src: '!{utterancesUrl}', + repo: '!{repo}', + theme: getUtterancesTheme(document.documentElement.getAttribute('data-theme')), + crossorigin: 'anonymous', + async: true, + ...option, + 'issue-term': isShuoshuo ? key : (option && option['issue-term']) || '!{issue_term}' + } + + const ele = document.createElement('script') + Object.entries(config).forEach(([key, value]) => ele.setAttribute(key, value)) + el.querySelector('#utterances-wrap').appendChild(ele) + } + + const changeUtterancesTheme = theme => { + const iframe = document.querySelector('#utterances-wrap iframe') + if (iframe) { + const message = { + type: 'set-theme', + theme: getUtterancesTheme(theme) + }; + iframe.contentWindow.postMessage(message, '!{utterancesOriginUrl}') + } + } + + btf.addGlobalFn('themeChange', changeUtterancesTheme, 'utterances') + + if (isShuoshuo) { + '!{use[0]}' === 'Utterances' + ? window.shuoshuoComment = { loadComment: loadUtterances } + : window.loadOtherComment = loadUtterances + return + } + + if ('!{use[0]}' === 'Utterances' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances) + else loadUtterances() + } else { + window.loadOtherComment = loadUtterances + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/valine.pug b/layout/includes/third-party/comments/valine.pug index 9ac2c43..83ca9b5 100644 --- a/layout/includes/third-party/comments/valine.pug +++ b/layout/includes/third-party/comments/valine.pug @@ -1,60 +1,60 @@ -- const { use, lazyload } = theme.comments -- const { appId, appKey, avatar, serverURLs, visitor, option } = theme.valine - -- let emojiMaps = '""' -if site.data.valine - - emojiMaps = JSON.stringify(site.data.valine) - -script. - (() => { - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - - const initValine = (el, path) => { - if (isShuoshuo) { - window.shuoshuoComment.destroyValine = () => { - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - - const valineConfig = { - el: '#vcomment', - appId: '#{appId}', - appKey: '#{appKey}', - avatar: '#{avatar}', - serverURLs: '#{serverURLs}', - emojiMaps: !{emojiMaps}, - visitor: #{visitor}, - ...option, - path: isShuoshuo ? path : (option && option.path) || window.location.pathname - } - - new Valine(valineConfig) - } - - const loadValine = async (el, path) => { - if (typeof Valine === 'function') { - initValine(el, path) - } else { - await btf.getScript('!{url_for(theme.asset.valine)}') - initValine(el, path) - } - } - - if (isShuoshuo) { - '!{use[0]}' === 'Valine' - ? window.shuoshuoComment = { loadComment: loadValine } - : window.loadOtherComment = loadValine - return - } - - if ('!{use[0]}' === 'Valine' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('vcomment'),loadValine) - else setTimeout(loadValine, 0) - } else { - window.loadOtherComment = loadValine - } +- const { use, lazyload } = theme.comments +- const { appId, appKey, avatar, serverURLs, visitor, option } = theme.valine + +- let emojiMaps = '""' +if site.data.valine + - emojiMaps = JSON.stringify(site.data.valine) + +script. + (() => { + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + + const initValine = (el, path) => { + if (isShuoshuo) { + window.shuoshuoComment.destroyValine = () => { + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + + const valineConfig = { + el: '#vcomment', + appId: '#{appId}', + appKey: '#{appKey}', + avatar: '#{avatar}', + serverURLs: '#{serverURLs}', + emojiMaps: !{emojiMaps}, + visitor: #{visitor}, + ...option, + path: isShuoshuo ? path : (option && option.path) || window.location.pathname + } + + new Valine(valineConfig) + } + + const loadValine = async (el, path) => { + if (typeof Valine === 'function') { + initValine(el, path) + } else { + await btf.getScript('!{url_for(theme.asset.valine)}') + initValine(el, path) + } + } + + if (isShuoshuo) { + '!{use[0]}' === 'Valine' + ? window.shuoshuoComment = { loadComment: loadValine } + : window.loadOtherComment = loadValine + return + } + + if ('!{use[0]}' === 'Valine' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('vcomment'),loadValine) + else setTimeout(loadValine, 0) + } else { + window.loadOtherComment = loadValine + } })() \ No newline at end of file diff --git a/layout/includes/third-party/comments/waline.pug b/layout/includes/third-party/comments/waline.pug index 99657e7..a39c5dc 100644 --- a/layout/includes/third-party/comments/waline.pug +++ b/layout/includes/third-party/comments/waline.pug @@ -1,61 +1,61 @@ -- const { serverURL, option, pageview } = theme.waline -- const { lazyload, count, use } = theme.comments - -script. - (() => { - let initFn = window.walineFn || null - const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' - const option = !{JSON.stringify(option)} - - const destroyWaline = ele => ele.destroy() - - const initWaline = (Fn, el = document, path = window.location.pathname) => { - const waline = Fn({ - el: el.querySelector('#waline-wrap'), - serverURL: '!{serverURL}', - pageview: !{lazyload ? false : pageview}, - dark: 'html[data-theme="dark"]', - comment: !{lazyload ? false : count}, - ...option, - path: isShuoshuo ? path : (option && option.path) || path - }) - - if (isShuoshuo) { - window.shuoshuoComment.destroyWaline = () => { - destroyWaline(waline) - if (el.children.length) { - el.innerHTML = '' - el.classList.add('no-comment') - } - } - } - } - - const loadWaline = (el, path) => { - if (initFn) initWaline(initFn, el, path) - else { - btf.getCSS('!{url_for(theme.asset.waline_css)}') - .then(() => import('!{url_for(theme.asset.waline_js)}')) - .then(({ init }) => { - initFn = init || Waline.init - initWaline(initFn, el, path) - window.walineFn = initFn - }) - } - } - - if (isShuoshuo) { - '!{use[0]}' === 'Waline' - ? window.shuoshuoComment = { loadComment: loadWaline } - : window.loadOtherComment = loadWaline - return - } - - if ('!{use[0]}' === 'Waline' || !!{lazyload}) { - if (!{lazyload}) btf.loadComment(document.getElementById('waline-wrap'),loadWaline) - else setTimeout(loadWaline, 0) - } else { - window.loadOtherComment = loadWaline - } - })() - +- const { serverURL, option, pageview } = theme.waline +- const { lazyload, count, use } = theme.comments + +script. + (() => { + let initFn = window.walineFn || null + const isShuoshuo = GLOBAL_CONFIG_SITE.pageType === 'shuoshuo' + const option = !{JSON.stringify(option)} + + const destroyWaline = ele => ele.destroy() + + const initWaline = (Fn, el = document, path = window.location.pathname) => { + const waline = Fn({ + el: el.querySelector('#waline-wrap'), + serverURL: '!{serverURL}', + pageview: !{lazyload ? false : pageview}, + dark: 'html[data-theme="dark"]', + comment: !{lazyload ? false : count}, + ...option, + path: isShuoshuo ? path : (option && option.path) || path + }) + + if (isShuoshuo) { + window.shuoshuoComment.destroyWaline = () => { + destroyWaline(waline) + if (el.children.length) { + el.innerHTML = '' + el.classList.add('no-comment') + } + } + } + } + + const loadWaline = (el, path) => { + if (initFn) initWaline(initFn, el, path) + else { + btf.getCSS('!{url_for(theme.asset.waline_css)}') + .then(() => import('!{url_for(theme.asset.waline_js)}')) + .then(({ init }) => { + initFn = init || Waline.init + initWaline(initFn, el, path) + window.walineFn = initFn + }) + } + } + + if (isShuoshuo) { + '!{use[0]}' === 'Waline' + ? window.shuoshuoComment = { loadComment: loadWaline } + : window.loadOtherComment = loadWaline + return + } + + if ('!{use[0]}' === 'Waline' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('waline-wrap'),loadWaline) + else setTimeout(loadWaline, 0) + } else { + window.loadOtherComment = loadWaline + } + })() + diff --git a/layout/includes/third-party/effect.pug b/layout/includes/third-party/effect.pug index a3b2995..2addbe4 100644 --- a/layout/includes/third-party/effect.pug +++ b/layout/includes/third-party/effect.pug @@ -1,35 +1,35 @@ -if theme.fireworks && theme.fireworks.enable - canvas.fireworks(mobile=`${theme.fireworks.mobile}`) - script(src=url_for(theme.asset.fireworks)) - -if (theme.canvas_ribbon && theme.canvas_ribbon.enable) - script(defer id="ribbon" src=url_for(theme.asset.canvas_ribbon) size=theme.canvas_ribbon.size - alpha=theme.canvas_ribbon.alpha zIndex=theme.canvas_ribbon.zIndex mobile=`${theme.canvas_ribbon.mobile}` data-click=`${theme.canvas_ribbon.click_to_change}`) - -if (theme.canvas_fluttering_ribbon && theme.canvas_fluttering_ribbon.enable) - script(defer id="fluttering_ribbon" mobile=`${theme.canvas_fluttering_ribbon.mobile}` src=url_for(theme.asset.canvas_fluttering_ribbon)) - -if (theme.canvas_nest && theme.canvas_nest.enable) - script#canvas_nest(defer color=theme.canvas_nest.color opacity=theme.canvas_nest.opacity zIndex=theme.canvas_nest.zIndex count=theme.canvas_nest.count mobile=`${theme.canvas_nest.mobile}` src=url_for(theme.asset.canvas_nest)) - -if theme.activate_power_mode.enable - script(src=url_for(theme.asset.activate_power_mode)) - script. - POWERMODE.colorful = !{theme.activate_power_mode.colorful}; - POWERMODE.shake = !{theme.activate_power_mode.shake}; - POWERMODE.mobile = !{theme.activate_power_mode.mobile}; - document.body.addEventListener('input', POWERMODE); - -//- 鼠標特效 -if theme.click_heart && theme.click_heart.enable - script#click-heart(src=url_for(theme.asset.click_heart) async mobile=`${theme.click_heart.mobile}`) - -if theme.clickShowText && theme.clickShowText.enable - script#click-show-text( - src= url_for(theme.asset.clickShowText) - data-mobile= `${theme.clickShowText.mobile}` - data-text= theme.clickShowText.text.join(",") - data-fontsize= theme.clickShowText.fontSize - data-random= `${theme.clickShowText.random}` - async +if theme.fireworks && theme.fireworks.enable + canvas.fireworks(mobile=`${theme.fireworks.mobile}`) + script(src=url_for(theme.asset.fireworks)) + +if (theme.canvas_ribbon && theme.canvas_ribbon.enable) + script(defer id="ribbon" src=url_for(theme.asset.canvas_ribbon) size=theme.canvas_ribbon.size + alpha=theme.canvas_ribbon.alpha zIndex=theme.canvas_ribbon.zIndex mobile=`${theme.canvas_ribbon.mobile}` data-click=`${theme.canvas_ribbon.click_to_change}`) + +if (theme.canvas_fluttering_ribbon && theme.canvas_fluttering_ribbon.enable) + script(defer id="fluttering_ribbon" mobile=`${theme.canvas_fluttering_ribbon.mobile}` src=url_for(theme.asset.canvas_fluttering_ribbon)) + +if (theme.canvas_nest && theme.canvas_nest.enable) + script#canvas_nest(defer color=theme.canvas_nest.color opacity=theme.canvas_nest.opacity zIndex=theme.canvas_nest.zIndex count=theme.canvas_nest.count mobile=`${theme.canvas_nest.mobile}` src=url_for(theme.asset.canvas_nest)) + +if theme.activate_power_mode.enable + script(src=url_for(theme.asset.activate_power_mode)) + script. + POWERMODE.colorful = !{theme.activate_power_mode.colorful}; + POWERMODE.shake = !{theme.activate_power_mode.shake}; + POWERMODE.mobile = !{theme.activate_power_mode.mobile}; + document.body.addEventListener('input', POWERMODE); + +//- 鼠標特效 +if theme.click_heart && theme.click_heart.enable + script#click-heart(src=url_for(theme.asset.click_heart) async mobile=`${theme.click_heart.mobile}`) + +if theme.clickShowText && theme.clickShowText.enable + script#click-show-text( + src= url_for(theme.asset.clickShowText) + data-mobile= `${theme.clickShowText.mobile}` + data-text= theme.clickShowText.text.join(",") + data-fontsize= theme.clickShowText.fontSize + data-random= `${theme.clickShowText.random}` + async ) \ No newline at end of file diff --git a/layout/includes/third-party/math/chartjs.pug b/layout/includes/third-party/math/chartjs.pug index 235d8e4..e51c621 100644 --- a/layout/includes/third-party/math/chartjs.pug +++ b/layout/includes/third-party/math/chartjs.pug @@ -1,91 +1,91 @@ -- const { fontColor, borderColor, scale_ticks_backdropColor } = theme.chartjs - -script. - (() => { - const applyThemeDefaultsConfig = theme => { - if (theme === 'dark-mode') { - Chart.defaults.color = "!{fontColor.dark}" - Chart.defaults.borderColor = "!{borderColor.dark}" - Chart.defaults.scale.ticks.backdropColor = "!{scale_ticks_backdropColor.dark}" - } else { - Chart.defaults.color = "!{fontColor.light}" - Chart.defaults.borderColor = "!{borderColor.light}" - Chart.defaults.scale.ticks.backdropColor = "!{scale_ticks_backdropColor.light}" - } - } - - // Recursively traverse the config object and automatically apply theme-specific color schemes - const applyThemeConfig = (obj, theme) => { - if (typeof obj !== 'object' || obj === null) return - - Object.keys(obj).forEach(key => { - const value = obj[key] - // If the property is an object and has theme-specific options, apply them - if (typeof value === 'object' && value !== null) { - if (value[theme]) { - obj[key] = value[theme] // Apply the value for the current theme - } else { - // Recursively process child objects - applyThemeConfig(value, theme) - } - } - }) - } - - const runChartJS = ele => { - window.loadChartJS = true - - Array.from(ele).forEach((item, index) => { - const chartSrc = item.firstElementChild - const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID - const width = item.getAttribute('data-width') - const existingCanvas = document.getElementById(chartID) - - // If a canvas already exists, remove it to avoid rendering duplicates - if (existingCanvas) { - existingCanvas.parentNode.remove() - } - - const chartDefinition = chartSrc.textContent - const canvas = document.createElement('canvas') - canvas.id = chartID - - const div = document.createElement('div') - div.className = 'chartjs-wrap' - - if (width) { - div.style.width = width - } - - div.appendChild(canvas) - chartSrc.insertAdjacentElement('afterend', div) - - const ctx = document.getElementById(chartID).getContext('2d') - - const config = JSON.parse(chartDefinition) - - const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark-mode' : 'light-mode' - - // Set default styles (initial setup) - applyThemeDefaultsConfig(theme) - - // Automatically traverse the config and apply dual-mode color schemes - applyThemeConfig(config, theme) - - new Chart(ctx, config) - }) - } - - const loadChartJS = () => { - const chartJSEle = document.querySelectorAll('#article-container .chartjs-container') - if (chartJSEle.length === 0) return - - window.loadChartJS ? runChartJS(chartJSEle) : btf.getScript('!{url_for(theme.asset.chartjs)}').then(() => runChartJS(chartJSEle)) - } - - // Listen for theme change events - btf.addGlobalFn('themeChange', loadChartJS, 'chartjs') - btf.addGlobalFn('encrypt', loadChartJS, 'chartjs') - - window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS) - })() +- const { fontColor, borderColor, scale_ticks_backdropColor } = theme.chartjs + +script. + (() => { + const applyThemeDefaultsConfig = theme => { + if (theme === 'dark-mode') { + Chart.defaults.color = "!{fontColor.dark}" + Chart.defaults.borderColor = "!{borderColor.dark}" + Chart.defaults.scale.ticks.backdropColor = "!{scale_ticks_backdropColor.dark}" + } else { + Chart.defaults.color = "!{fontColor.light}" + Chart.defaults.borderColor = "!{borderColor.light}" + Chart.defaults.scale.ticks.backdropColor = "!{scale_ticks_backdropColor.light}" + } + } + + // Recursively traverse the config object and automatically apply theme-specific color schemes + const applyThemeConfig = (obj, theme) => { + if (typeof obj !== 'object' || obj === null) return + + Object.keys(obj).forEach(key => { + const value = obj[key] + // If the property is an object and has theme-specific options, apply them + if (typeof value === 'object' && value !== null) { + if (value[theme]) { + obj[key] = value[theme] // Apply the value for the current theme + } else { + // Recursively process child objects + applyThemeConfig(value, theme) + } + } + }) + } + + const runChartJS = ele => { + window.loadChartJS = true + + Array.from(ele).forEach((item, index) => { + const chartSrc = item.firstElementChild + const chartID = item.getAttribute('data-chartjs-id') || ('chartjs-' + index) // Use custom ID or default ID + const width = item.getAttribute('data-width') + const existingCanvas = document.getElementById(chartID) + + // If a canvas already exists, remove it to avoid rendering duplicates + if (existingCanvas) { + existingCanvas.parentNode.remove() + } + + const chartDefinition = chartSrc.textContent + const canvas = document.createElement('canvas') + canvas.id = chartID + + const div = document.createElement('div') + div.className = 'chartjs-wrap' + + if (width) { + div.style.width = width + } + + div.appendChild(canvas) + chartSrc.insertAdjacentElement('afterend', div) + + const ctx = document.getElementById(chartID).getContext('2d') + + const config = JSON.parse(chartDefinition) + + const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark-mode' : 'light-mode' + + // Set default styles (initial setup) + applyThemeDefaultsConfig(theme) + + // Automatically traverse the config and apply dual-mode color schemes + applyThemeConfig(config, theme) + + new Chart(ctx, config) + }) + } + + const loadChartJS = () => { + const chartJSEle = document.querySelectorAll('#article-container .chartjs-container') + if (chartJSEle.length === 0) return + + window.loadChartJS ? runChartJS(chartJSEle) : btf.getScript('!{url_for(theme.asset.chartjs)}').then(() => runChartJS(chartJSEle)) + } + + // Listen for theme change events + btf.addGlobalFn('themeChange', loadChartJS, 'chartjs') + btf.addGlobalFn('encrypt', loadChartJS, 'chartjs') + + window.pjax ? loadChartJS() : document.addEventListener('DOMContentLoaded', loadChartJS) + })() diff --git a/layout/includes/third-party/math/index.pug b/layout/includes/third-party/math/index.pug index 93302f8..a5bdf41 100644 --- a/layout/includes/third-party/math/index.pug +++ b/layout/includes/third-party/math/index.pug @@ -1,14 +1,14 @@ -case theme.math.use - when 'mathjax' - if (theme.math.per_page && (['post','page'].includes(globalPageType))) || page.mathjax - include ./mathjax.pug - - when 'katex' - if (theme.math.per_page && (['post','page'].includes(globalPageType))) || page.katex - include ./katex.pug - -if theme.mermaid.enable - include ./mermaid.pug - -if theme.chartjs.enable +case theme.math.use + when 'mathjax' + if (theme.math.per_page && (['post','page'].includes(globalPageType))) || page.mathjax + include ./mathjax.pug + + when 'katex' + if (theme.math.per_page && (['post','page'].includes(globalPageType))) || page.katex + include ./katex.pug + +if theme.mermaid.enable + include ./mermaid.pug + +if theme.chartjs.enable include ./chartjs.pug \ No newline at end of file diff --git a/layout/includes/third-party/math/katex.pug b/layout/includes/third-party/math/katex.pug index 0e4195d..6e429a5 100644 --- a/layout/includes/third-party/math/katex.pug +++ b/layout/includes/third-party/math/katex.pug @@ -1,16 +1,16 @@ -script. - (async () => { - const showKatex = () => { - document.querySelectorAll('#article-container .katex').forEach(el => el.classList.add('katex-show')) - } - - if (!window.katex_js_css) { - window.katex_js_css = true - await btf.getCSS('!{url_for(theme.asset.katex)}') - if (!{theme.math.katex.copy_tex}) { - await btf.getScript('!{url_for(theme.asset.katex_copytex)}') - } - } - - showKatex() +script. + (async () => { + const showKatex = () => { + document.querySelectorAll('#article-container .katex').forEach(el => el.classList.add('katex-show')) + } + + if (!window.katex_js_css) { + window.katex_js_css = true + await btf.getCSS('!{url_for(theme.asset.katex)}') + if (!{theme.math.katex.copy_tex}) { + await btf.getScript('!{url_for(theme.asset.katex_copytex)}') + } + } + + showKatex() })() \ No newline at end of file diff --git a/layout/includes/third-party/math/mathjax.pug b/layout/includes/third-party/math/mathjax.pug index f0483ef..e937dbc 100644 --- a/layout/includes/third-party/math/mathjax.pug +++ b/layout/includes/third-party/math/mathjax.pug @@ -1,47 +1,47 @@ -//- Mathjax 3 -- const { tags, enableMenu } = theme.math.mathjax -script. - (() => { - const loadMathjax = () => { - if (!window.MathJax) { - window.MathJax = { - tex: { - inlineMath: [['$', '$'], ['\\(', '\\)']], - tags: '!{tags}', - }, - chtml: { - scale: 1.1 - }, - options: { - enableMenu: !{enableMenu}, - renderActions: { - findScript: [10, doc => { - for (const node of document.querySelectorAll('script[type^="math/tex"]')) { - const display = !!node.type.match(/; *mode=display/) - const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display) - const text = document.createTextNode('') - node.parentNode.replaceChild(text, node) - math.start = {node: text, delim: '', n: 0} - math.end = {node: text, delim: '', n: 0} - doc.math.push(math) - } - }, ''] - } - } - } - - const script = document.createElement('script') - script.src = '!{url_for(theme.asset.mathjax)}' - script.id = 'MathJax-script' - script.async = true - document.head.appendChild(script) - } else { - MathJax.startup.document.state(0) - MathJax.texReset() - MathJax.typesetPromise() - } - } - - btf.addGlobalFn('encrypt', loadMathjax, 'mathjax') - window.pjax ? loadMathjax() : window.addEventListener('load', loadMathjax) +//- Mathjax 3 +- const { tags, enableMenu } = theme.math.mathjax +script. + (() => { + const loadMathjax = () => { + if (!window.MathJax) { + window.MathJax = { + tex: { + inlineMath: [['$', '$'], ['\\(', '\\)']], + tags: '!{tags}', + }, + chtml: { + scale: 1.1 + }, + options: { + enableMenu: !{enableMenu}, + renderActions: { + findScript: [10, doc => { + for (const node of document.querySelectorAll('script[type^="math/tex"]')) { + const display = !!node.type.match(/; *mode=display/) + const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display) + const text = document.createTextNode('') + node.parentNode.replaceChild(text, node) + math.start = {node: text, delim: '', n: 0} + math.end = {node: text, delim: '', n: 0} + doc.math.push(math) + } + }, ''] + } + } + } + + const script = document.createElement('script') + script.src = '!{url_for(theme.asset.mathjax)}' + script.id = 'MathJax-script' + script.async = true + document.head.appendChild(script) + } else { + MathJax.startup.document.state(0) + MathJax.texReset() + MathJax.typesetPromise() + } + } + + btf.addGlobalFn('encrypt', loadMathjax, 'mathjax') + window.pjax ? loadMathjax() : window.addEventListener('load', loadMathjax) })() \ No newline at end of file diff --git a/layout/includes/third-party/math/mermaid.pug b/layout/includes/third-party/math/mermaid.pug index a668659..d28049f 100644 --- a/layout/includes/third-party/math/mermaid.pug +++ b/layout/includes/third-party/math/mermaid.pug @@ -1,51 +1,51 @@ -script. - (() => { - const runMermaid = ele => { - window.loadMermaid = true - const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}' - - ele.forEach((item, index) => { - const mermaidSrc = item.firstElementChild - const mermaidThemeConfig = `%%{init:{ 'theme':'${theme}'}}%%\n` - const mermaidID = `mermaid-${index}` - const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent - - const renderFn = mermaid.render(mermaidID, mermaidDefinition) - const renderMermaid = svg => { - mermaidSrc.insertAdjacentHTML('afterend', svg) - } - - // mermaid v9 and v10 compatibility - typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({ svg }) => renderMermaid(svg)) - }) - } - - const codeToMermaid = () => { - const codeMermaidEle = document.querySelectorAll('pre > code.mermaid') - if (codeMermaidEle.length === 0) return - - codeMermaidEle.forEach(ele => { - const preEle = document.createElement('pre') - preEle.className = 'mermaid-src' - preEle.hidden = true - preEle.textContent = ele.textContent - const newEle = document.createElement('div') - newEle.className = 'mermaid-wrap' - newEle.appendChild(preEle) - ele.parentNode.replaceWith(newEle) - }) - } - - const loadMermaid = () => { - if (!{theme.mermaid.code_write}) codeToMermaid() - const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap') - if ($mermaid.length === 0) return - - const runMermaidFn = () => runMermaid($mermaid) - btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid') - window.loadMermaid ? runMermaidFn() : btf.getScript('!{url_for(theme.asset.mermaid)}').then(runMermaidFn) - } - - btf.addGlobalFn('encrypt', loadMermaid, 'mermaid') - window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid) +script. + (() => { + const runMermaid = ele => { + window.loadMermaid = true + const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}' + + ele.forEach((item, index) => { + const mermaidSrc = item.firstElementChild + const mermaidThemeConfig = `%%{init:{ 'theme':'${theme}'}}%%\n` + const mermaidID = `mermaid-${index}` + const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent + + const renderFn = mermaid.render(mermaidID, mermaidDefinition) + const renderMermaid = svg => { + mermaidSrc.insertAdjacentHTML('afterend', svg) + } + + // mermaid v9 and v10 compatibility + typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({ svg }) => renderMermaid(svg)) + }) + } + + const codeToMermaid = () => { + const codeMermaidEle = document.querySelectorAll('pre > code.mermaid') + if (codeMermaidEle.length === 0) return + + codeMermaidEle.forEach(ele => { + const preEle = document.createElement('pre') + preEle.className = 'mermaid-src' + preEle.hidden = true + preEle.textContent = ele.textContent + const newEle = document.createElement('div') + newEle.className = 'mermaid-wrap' + newEle.appendChild(preEle) + ele.parentNode.replaceWith(newEle) + }) + } + + const loadMermaid = () => { + if (!{theme.mermaid.code_write}) codeToMermaid() + const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap') + if ($mermaid.length === 0) return + + const runMermaidFn = () => runMermaid($mermaid) + btf.addGlobalFn('themeChange', runMermaidFn, 'mermaid') + window.loadMermaid ? runMermaidFn() : btf.getScript('!{url_for(theme.asset.mermaid)}').then(runMermaidFn) + } + + btf.addGlobalFn('encrypt', loadMermaid, 'mermaid') + window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid) })() \ No newline at end of file diff --git a/layout/includes/third-party/newest-comments/artalk.pug b/layout/includes/third-party/newest-comments/artalk.pug index 4e703b2..cf51638 100644 --- a/layout/includes/third-party/newest-comments/artalk.pug +++ b/layout/includes/third-party/newest-comments/artalk.pug @@ -1,67 +1,67 @@ -- const { server, site, option } = theme.artalk -- const avatarCdn = (option !== null && option.gravatar && option.gravatar.mirror) || '' -- const avatarDefault = (option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default)) || '' - -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'artalk-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const getAvatarValue = async () => { - const predefinedAvatarCdn = '!{avatarCdn}' - const predefinedAvatarDefault = '!{avatarDefault}' - - const avatarDefaultFormat = e => e.startsWith('d=') ? e : `d=${e}` - - if (predefinedAvatarCdn && predefinedAvatarDefault) { - return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) } - } - - try { - const res = await fetch('!{server}/api/v2/conf') - const result = await res.json() - const { mirror, params, default: defaults } = result.frontend_conf.gravatar - const avatarCdn = predefinedAvatarCdn || mirror - let avatarDefault = avatarDefaultFormat(predefinedAvatarDefault || params || defaults) - return { avatarCdn, avatarDefault} - } catch (e) { - console.error(e) - return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) } - } - } - - const searchParams = new URLSearchParams({ - 'site_name': '!{site}', - 'limit': '!{newestCommentsLimit * 2}', // Fetch more comments to filter pending comments - }) - - const getComment = async (ele) => { - try { - const res = await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`) - const result = await res.json() - const { avatarCdn, avatarDefault } = await getAvatarValue() - const artalk = result.data - .filter(e => !e.is_pending) // Filter pending comments - .slice(0, !{newestCommentsLimit}) // Limit the number of comments - .map(e => { - const avatar = avatarCdn && e.email_encrypted ? `${avatarCdn}${e.email_encrypted}?${avatarDefault}` : '' - return { - 'avatar': avatar, - 'content': changeContent(e.content_marked), - 'nick': e.nick, - 'url': e.page_url, - 'date': e.date, - } - }) - btf.saveToLocal.set(keyName, JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(artalk, ele) - } catch (e) { - console.log(e) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - } - } - - run(keyName, getComment) +- const { server, site, option } = theme.artalk +- const avatarCdn = (option !== null && option.gravatar && option.gravatar.mirror) || '' +- const avatarDefault = (option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default)) || '' + +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'artalk-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const getAvatarValue = async () => { + const predefinedAvatarCdn = '!{avatarCdn}' + const predefinedAvatarDefault = '!{avatarDefault}' + + const avatarDefaultFormat = e => e.startsWith('d=') ? e : `d=${e}` + + if (predefinedAvatarCdn && predefinedAvatarDefault) { + return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) } + } + + try { + const res = await fetch('!{server}/api/v2/conf') + const result = await res.json() + const { mirror, params, default: defaults } = result.frontend_conf.gravatar + const avatarCdn = predefinedAvatarCdn || mirror + let avatarDefault = avatarDefaultFormat(predefinedAvatarDefault || params || defaults) + return { avatarCdn, avatarDefault} + } catch (e) { + console.error(e) + return { avatarCdn: predefinedAvatarCdn, avatarDefault: avatarDefaultFormat(predefinedAvatarDefault) } + } + } + + const searchParams = new URLSearchParams({ + 'site_name': '!{site}', + 'limit': '!{newestCommentsLimit * 2}', // Fetch more comments to filter pending comments + }) + + const getComment = async (ele) => { + try { + const res = await fetch(`!{server}/api/v2/stats/latest_comments?${searchParams}`) + const result = await res.json() + const { avatarCdn, avatarDefault } = await getAvatarValue() + const artalk = result.data + .filter(e => !e.is_pending) // Filter pending comments + .slice(0, !{newestCommentsLimit}) // Limit the number of comments + .map(e => { + const avatar = avatarCdn && e.email_encrypted ? `${avatarCdn}${e.email_encrypted}?${avatarDefault}` : '' + return { + 'avatar': avatar, + 'content': changeContent(e.content_marked), + 'nick': e.nick, + 'url': e.page_url, + 'date': e.date, + } + }) + btf.saveToLocal.set(keyName, JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(artalk, ele) + } catch (e) { + console.log(e) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + } + } + + run(keyName, getComment) }) \ No newline at end of file diff --git a/layout/includes/third-party/newest-comments/common.pug b/layout/includes/third-party/newest-comments/common.pug index f3b88f5..9a0814d 100644 --- a/layout/includes/third-party/newest-comments/common.pug +++ b/layout/includes/third-party/newest-comments/common.pug @@ -1,61 +1,61 @@ -script. - window.newestComments = { - changeContent: content => { - if (content === '') return content - - content = content.replace(/]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link - content = content.replace(/]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url - content = content.replace(/
.*?<\/pre>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
-      content = content.replace(/.*?<\/code>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
-      content = content.replace(/<[^>]+>/g, "") // remove html tag
-
-      if (content.length > 150) {
-        content = content.substring(0, 150) + '...'
-      }
-      return content
-    },
-
-    generateHtml: (array, ele) => {
-      let result = ''
-
-      if (array.length) {
-        for (let i = 0; i < array.length; i++) {
-          result += '
' - - if (!{theme.aside.card_newest_comments.avatar} && array[i].avatar) { - const imgAttr = '!{theme.lazyload.enable && !theme.lazyload.native ? "data-lazy-src" : "src"}' - const lazyloadNative = '!{theme.lazyload.enable && theme.lazyload.native ? "loading=\"lazy\"" : ""}' - result += `${array[i].nick}` - } - - result += `
- ${array[i].content} -
${array[i].nick} /
-
` - } - } else { - result += '!{_p("aside.card_newest_comments.zero")}' - } - - ele.innerHTML = result - window.lazyLoadInstance && window.lazyLoadInstance.update() - window.pjax && window.pjax.refresh(ele) - }, - - newestCommentInit: (name, getComment) => { - const $dom = document.querySelector('#card-newest-comments .aside-list') - if ($dom) { - const data = btf.saveToLocal.get(name) - if (data) { - newestComments.generateHtml(JSON.parse(data), $dom) - } else { - getComment($dom) - } - } - }, - - run: (name, getComment) => { - newestComments.newestCommentInit(name, getComment) - btf.addGlobalFn('pjaxComplete', () => newestComments.newestCommentInit(name, getComment), name) - } +script. + window.newestComments = { + changeContent: content => { + if (content === '') return content + + content = content.replace(/]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link + content = content.replace(/]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url + content = content.replace(/
.*?<\/pre>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
+      content = content.replace(/.*?<\/code>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
+      content = content.replace(/<[^>]+>/g, "") // remove html tag
+
+      if (content.length > 150) {
+        content = content.substring(0, 150) + '...'
+      }
+      return content
+    },
+
+    generateHtml: (array, ele) => {
+      let result = ''
+
+      if (array.length) {
+        for (let i = 0; i < array.length; i++) {
+          result += '
' + + if (!{theme.aside.card_newest_comments.avatar} && array[i].avatar) { + const imgAttr = '!{theme.lazyload.enable && !theme.lazyload.native ? "data-lazy-src" : "src"}' + const lazyloadNative = '!{theme.lazyload.enable && theme.lazyload.native ? "loading=\"lazy\"" : ""}' + result += `${array[i].nick}` + } + + result += `
+ ${array[i].content} +
${array[i].nick} /
+
` + } + } else { + result += '!{_p("aside.card_newest_comments.zero")}' + } + + ele.innerHTML = result + window.lazyLoadInstance && window.lazyLoadInstance.update() + window.pjax && window.pjax.refresh(ele) + }, + + newestCommentInit: (name, getComment) => { + const $dom = document.querySelector('#card-newest-comments .aside-list') + if ($dom) { + const data = btf.saveToLocal.get(name) + if (data) { + newestComments.generateHtml(JSON.parse(data), $dom) + } else { + getComment($dom) + } + } + }, + + run: (name, getComment) => { + newestComments.newestCommentInit(name, getComment) + btf.addGlobalFn('pjaxComplete', () => newestComments.newestCommentInit(name, getComment), name) + } } \ No newline at end of file diff --git a/layout/includes/third-party/newest-comments/disqus-comment.pug b/layout/includes/third-party/newest-comments/disqus-comment.pug index e26bb41..040d5d0 100644 --- a/layout/includes/third-party/newest-comments/disqus-comment.pug +++ b/layout/includes/third-party/newest-comments/disqus-comment.pug @@ -1,34 +1,34 @@ -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'disqus-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const getComment = ele => { - fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{newestCommentsLimit}&api_key=!{apiKey}') - .then(response => response.json()) - .then(data => { - const disqusArray = data.response.map(item => { - return { - 'avatar': item.author.avatar.cache, - 'content': changeContent(item.message), - 'nick': item.author.name, - 'url': item.url, - 'date': item.createdAt - } - }) - - btf.saveToLocal.set(keyName, JSON.stringify(disqusArray), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(disqusArray, ele) - }).catch(e => { - console.error(e) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - }) - } - - run(keyName, getComment) - }) - - - +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'disqus-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const getComment = ele => { + fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{newestCommentsLimit}&api_key=!{apiKey}') + .then(response => response.json()) + .then(data => { + const disqusArray = data.response.map(item => { + return { + 'avatar': item.author.avatar.cache, + 'content': changeContent(item.message), + 'nick': item.author.name, + 'url': item.url, + 'date': item.createdAt + } + }) + + btf.saveToLocal.set(keyName, JSON.stringify(disqusArray), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(disqusArray, ele) + }).catch(e => { + console.error(e) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + }) + } + + run(keyName, getComment) + }) + + + diff --git a/layout/includes/third-party/newest-comments/github-issues.pug b/layout/includes/third-party/newest-comments/github-issues.pug index 7dc418c..5612c8a 100644 --- a/layout/includes/third-party/newest-comments/github-issues.pug +++ b/layout/includes/third-party/newest-comments/github-issues.pug @@ -1,62 +1,62 @@ -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'github-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const findTrueUrl = (array, ele) => { - Promise.all(array.map(item => - fetch(item.url).then(resp => resp.json()).then(data => { - let urlArray = data.body ? data.body.match(/(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/ig) : [] - if (!Array.isArray(urlArray) || urlArray.length === 0) { - urlArray = [`${data.html_url}`] - } - if (data.user.login === 'utterances-bot') { - return urlArray.pop() - } else { - return urlArray.shift() - } - }) - )).then(res => { - array = array.map((i,index)=> { - return { - ...i, - url: res[index] - } - }) - - btf.saveToLocal.set(keyName, JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(array, ele) - }); - } - - const getComment = ele => { - fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{newestCommentsLimit}&page=1',{ - "headers": { - Accept: 'application/vnd.github.v3.html+json' - } - }) - .then(response => response.json()) - .then(data => { - const githubArray = data.map(item => { - return { - 'avatar': item.user.avatar_url, - 'content': changeContent(item.body_html || item.body), - 'nick': item.user.login, - 'url': item.issue_url, - 'date': item.updated_at - } - }) - findTrueUrl(githubArray, ele) - }).catch(e => { - console.error(e) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - }) - } - run(keyName, getComment) - }) - - - - +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'github-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const findTrueUrl = (array, ele) => { + Promise.all(array.map(item => + fetch(item.url).then(resp => resp.json()).then(data => { + let urlArray = data.body ? data.body.match(/(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/ig) : [] + if (!Array.isArray(urlArray) || urlArray.length === 0) { + urlArray = [`${data.html_url}`] + } + if (data.user.login === 'utterances-bot') { + return urlArray.pop() + } else { + return urlArray.shift() + } + }) + )).then(res => { + array = array.map((i,index)=> { + return { + ...i, + url: res[index] + } + }) + + btf.saveToLocal.set(keyName, JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(array, ele) + }); + } + + const getComment = ele => { + fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{newestCommentsLimit}&page=1',{ + "headers": { + Accept: 'application/vnd.github.v3.html+json' + } + }) + .then(response => response.json()) + .then(data => { + const githubArray = data.map(item => { + return { + 'avatar': item.user.avatar_url, + 'content': changeContent(item.body_html || item.body), + 'nick': item.user.login, + 'url': item.issue_url, + 'date': item.updated_at + } + }) + findTrueUrl(githubArray, ele) + }).catch(e => { + console.error(e) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + }) + } + run(keyName, getComment) + }) + + + + diff --git a/layout/includes/third-party/newest-comments/index.pug b/layout/includes/third-party/newest-comments/index.pug index a2f2c0d..eedb4e7 100644 --- a/layout/includes/third-party/newest-comments/index.pug +++ b/layout/includes/third-party/newest-comments/index.pug @@ -1,34 +1,34 @@ -- let { use } = theme.comments - -if use - - - let forum,apiKey,userRepo - let { limit:newestCommentsLimit } = theme.aside.card_newest_comments - if (newestCommentsLimit > 10 || newestCommentsLimit < 1) newestCommentsLimit = 6 - - case use[0] - when 'Valine' - include ./valine.pug - when 'Waline' - include ./waline.pug - when 'Twikoo' - include ./twikoo-comment.pug - when 'Disqus' - - forum = theme.disqus.shortname - - apiKey = theme.disqus.apikey - include ./disqus-comment.pug - when 'Disqusjs' - - forum = theme.disqusjs.shortname - - apiKey = theme.disqusjs.apikey - include ./disqus-comment.pug - when 'Gitalk' - - let { repo,owner } = theme.gitalk - - userRepo = owner + '/' + repo - include ./github-issues.pug - when 'Utterances' - - userRepo = theme.utterances.repo - include ./github-issues.pug - when 'Remark42' - include ./remark42.pug - when 'Artalk' +- let { use } = theme.comments + +if use + - + let forum,apiKey,userRepo + let { limit:newestCommentsLimit } = theme.aside.card_newest_comments + if (newestCommentsLimit > 10 || newestCommentsLimit < 1) newestCommentsLimit = 6 + + case use[0] + when 'Valine' + include ./valine.pug + when 'Waline' + include ./waline.pug + when 'Twikoo' + include ./twikoo-comment.pug + when 'Disqus' + - forum = theme.disqus.shortname + - apiKey = theme.disqus.apikey + include ./disqus-comment.pug + when 'Disqusjs' + - forum = theme.disqusjs.shortname + - apiKey = theme.disqusjs.apikey + include ./disqus-comment.pug + when 'Gitalk' + - let { repo,owner } = theme.gitalk + - userRepo = owner + '/' + repo + include ./github-issues.pug + when 'Utterances' + - userRepo = theme.utterances.repo + include ./github-issues.pug + when 'Remark42' + include ./remark42.pug + when 'Artalk' include ./artalk.pug \ No newline at end of file diff --git a/layout/includes/third-party/newest-comments/remark42.pug b/layout/includes/third-party/newest-comments/remark42.pug index 4321b3b..a335968 100644 --- a/layout/includes/third-party/newest-comments/remark42.pug +++ b/layout/includes/third-party/newest-comments/remark42.pug @@ -1,31 +1,31 @@ -- const { host, siteId } = theme.remark42 -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'remark42-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const getComment = ele => { - fetch('!{host}/api/v1/last/!{newestCommentsLimit}?site=!{siteId}') - .then(response => response.json()) - .then(data => { - const remark42 = data.map(e => { - return { - 'avatar': e.user.picture, - 'content': changeContent(e.text), - 'nick': e.user.name, - 'url': e.locator.url, - 'date': e.time, - } - }) - btf.saveToLocal.set(keyName, JSON.stringify(remark42), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(remark42, ele) - }).catch(e => { - console.error(e) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - }) - } - - run(keyName, getComment) - }) +- const { host, siteId } = theme.remark42 +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'remark42-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const getComment = ele => { + fetch('!{host}/api/v1/last/!{newestCommentsLimit}?site=!{siteId}') + .then(response => response.json()) + .then(data => { + const remark42 = data.map(e => { + return { + 'avatar': e.user.picture, + 'content': changeContent(e.text), + 'nick': e.user.name, + 'url': e.locator.url, + 'date': e.time, + } + }) + btf.saveToLocal.set(keyName, JSON.stringify(remark42), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(remark42, ele) + }).catch(e => { + console.error(e) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + }) + } + + run(keyName, getComment) + }) diff --git a/layout/includes/third-party/newest-comments/twikoo-comment.pug b/layout/includes/third-party/newest-comments/twikoo-comment.pug index 772c8ec..250efa8 100644 --- a/layout/includes/third-party/newest-comments/twikoo-comment.pug +++ b/layout/includes/third-party/newest-comments/twikoo-comment.pug @@ -1,45 +1,45 @@ -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'twikoo-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const getComment = ele => { - const runTwikoo = () => { - twikoo.getRecentComments({ - envId: '!{theme.twikoo.envId}', - region: '!{theme.twikoo.region}', - pageSize: !{newestCommentsLimit}, - includeReply: true - }).then(res => { - const twikooArray = res.map(e => { - return { - 'content': changeContent(e.comment), - 'avatar': e.avatar, - 'nick': e.nick, - 'url': e.url + '#' + e.id, - 'date': new Date(e.created).toISOString() - } - }) - - btf.saveToLocal.set(keyName, JSON.stringify(twikooArray), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(twikooArray, ele) - }).catch(err => { - console.error(err) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - }) - } - - if (typeof twikoo === 'object') { - runTwikoo() - } else { - btf.getScript('!{url_for(theme.asset.twikoo)}').then(runTwikoo) - } - } - - run(keyName, getComment) - }) - - - +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'twikoo-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const getComment = ele => { + const runTwikoo = () => { + twikoo.getRecentComments({ + envId: '!{theme.twikoo.envId}', + region: '!{theme.twikoo.region}', + pageSize: !{newestCommentsLimit}, + includeReply: true + }).then(res => { + const twikooArray = res.map(e => { + return { + 'content': changeContent(e.comment), + 'avatar': e.avatar, + 'nick': e.nick, + 'url': e.url + '#' + e.id, + 'date': new Date(e.created).toISOString() + } + }) + + btf.saveToLocal.set(keyName, JSON.stringify(twikooArray), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(twikooArray, ele) + }).catch(err => { + console.error(err) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + }) + } + + if (typeof twikoo === 'object') { + runTwikoo() + } else { + btf.getScript('!{url_for(theme.asset.twikoo)}').then(runTwikoo) + } + } + + run(keyName, getComment) + }) + + + diff --git a/layout/includes/third-party/newest-comments/valine.pug b/layout/includes/third-party/newest-comments/valine.pug index 08af70c..6d7742c 100644 --- a/layout/includes/third-party/newest-comments/valine.pug +++ b/layout/includes/third-party/newest-comments/valine.pug @@ -1,51 +1,51 @@ -- let default_avatar = theme.valine.avatar - -script(src=url_for(theme.asset.blueimp_md5)) -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'valine-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const getIcon = (icon, mail) => { - if (icon) return icon - let defaultIcon = '!{ default_avatar ? `?d=${default_avatar}` : ''}' - let iconUrl = `https://gravatar.loli.net/avatar/${md5(mail.toLowerCase()) + defaultIcon}` - return iconUrl - } - - const getComment = ele => { - const serverURL = '!{theme.valine.serverURLs || `https://${theme.valine.appId.substring(0,8)}.api.lncldglobal.com` }' - - var settings = { - "method": "GET", - "headers": { - "X-LC-Id": '!{theme.valine.appId}', - "X-LC-Key": '!{theme.valine.appKey}', - "Content-Type": "application/json" - }, - } - - fetch(`${serverURL}/1.1/classes/Comment?limit=!{newestCommentsLimit}&order=-createdAt`,settings) - .then(response => response.json()) - .then(data => { - const valineArray = data.results.map(e => { - return { - 'avatar': getIcon(e.QQAvatar, e.mail), - 'content': changeContent(e.comment), - 'nick': e.nick, - 'url': e.url + '#' + e.objectId, - 'date': e.updatedAt, - } - }) - btf.saveToLocal.set(keyName, JSON.stringify(valineArray), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(valineArray, ele) - }).catch(e => { - console.error(e) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - }) - } - - run(keyName, getComment) - }) +- let default_avatar = theme.valine.avatar + +script(src=url_for(theme.asset.blueimp_md5)) +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'valine-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const getIcon = (icon, mail) => { + if (icon) return icon + let defaultIcon = '!{ default_avatar ? `?d=${default_avatar}` : ''}' + let iconUrl = `https://gravatar.loli.net/avatar/${md5(mail.toLowerCase()) + defaultIcon}` + return iconUrl + } + + const getComment = ele => { + const serverURL = '!{theme.valine.serverURLs || `https://${theme.valine.appId.substring(0,8)}.api.lncldglobal.com` }' + + var settings = { + "method": "GET", + "headers": { + "X-LC-Id": '!{theme.valine.appId}', + "X-LC-Key": '!{theme.valine.appKey}', + "Content-Type": "application/json" + }, + } + + fetch(`${serverURL}/1.1/classes/Comment?limit=!{newestCommentsLimit}&order=-createdAt`,settings) + .then(response => response.json()) + .then(data => { + const valineArray = data.results.map(e => { + return { + 'avatar': getIcon(e.QQAvatar, e.mail), + 'content': changeContent(e.comment), + 'nick': e.nick, + 'url': e.url + '#' + e.objectId, + 'date': e.updatedAt, + } + }) + btf.saveToLocal.set(keyName, JSON.stringify(valineArray), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(valineArray, ele) + }).catch(e => { + console.error(e) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + }) + } + + run(keyName, getComment) + }) diff --git a/layout/includes/third-party/newest-comments/waline.pug b/layout/includes/third-party/newest-comments/waline.pug index 72743ea..b8117ef 100644 --- a/layout/includes/third-party/newest-comments/waline.pug +++ b/layout/includes/third-party/newest-comments/waline.pug @@ -1,32 +1,32 @@ -- const serverURL = theme.waline.serverURL.replace(/\/$/, '') - -!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) - -script. - window.addEventListener('load', () => { - const keyName = 'waline-newest-comments' - const { changeContent, generateHtml, run } = window.newestComments - - const getComment = async (ele) => { - try { - const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{newestCommentsLimit}') - const result = await res.json() - const walineArray = result.data.map(e => { - return { - 'content': changeContent(e.comment), - 'avatar': e.avatar, - 'nick': e.nick, - 'url': e.url + '#' + e.objectId, - 'date': e.time || e.insertedAt - } - }) - btf.saveToLocal.set(keyName, JSON.stringify(walineArray), !{theme.aside.card_newest_comments.storage}/(60*24)) - generateHtml(walineArray, ele) - } catch (err) { - console.error(err) - ele.textContent= "!{_p('aside.card_newest_comments.error')}" - } - } - - run(keyName, getComment) - }) +- const serverURL = theme.waline.serverURL.replace(/\/$/, '') + +!= partial("includes/third-party/newest-comments/common.pug", {}, { cache: true }) + +script. + window.addEventListener('load', () => { + const keyName = 'waline-newest-comments' + const { changeContent, generateHtml, run } = window.newestComments + + const getComment = async (ele) => { + try { + const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{newestCommentsLimit}') + const result = await res.json() + const walineArray = result.data.map(e => { + return { + 'content': changeContent(e.comment), + 'avatar': e.avatar, + 'nick': e.nick, + 'url': e.url + '#' + e.objectId, + 'date': e.time || e.insertedAt + } + }) + btf.saveToLocal.set(keyName, JSON.stringify(walineArray), !{theme.aside.card_newest_comments.storage}/(60*24)) + generateHtml(walineArray, ele) + } catch (err) { + console.error(err) + ele.textContent= "!{_p('aside.card_newest_comments.error')}" + } + } + + run(keyName, getComment) + }) diff --git a/layout/includes/third-party/pjax.pug b/layout/includes/third-party/pjax.pug index c63caf1..a8094f1 100644 --- a/layout/includes/third-party/pjax.pug +++ b/layout/includes/third-party/pjax.pug @@ -1,63 +1,65 @@ -- var pjaxExclude = 'a:not([target="_blank"])' -if theme.pjax.exclude - each val in theme.pjax.exclude - - pjaxExclude += `:not([href="${val}"])` - -- let pjaxSelectors = ['head > title', '#config-diff', '#body-wrap', '#rightside-config-hide', '#rightside-config-show', '.js-pjax'] - -- let choose = theme.comments.use -if choose - if theme.Open_Graph_meta.enable && (choose.includes('Livere') || choose.includes('Utterances') || choose.includes('Giscus')) - - pjaxSelectors.unshift('meta[property="og:image"]', 'meta[property="og:title"]', 'meta[property="og:url"]') - if choose.includes('Utterances') || choose.includes('Giscus') - - pjaxSelectors.unshift('link[rel="canonical"]') - -script(src=url_for(theme.asset.pjax)) -script. - (() => { - const pjaxSelectors = !{JSON.stringify(pjaxSelectors)} - - window.pjax = new Pjax({ - elements: '!{pjaxExclude}', - selectors: pjaxSelectors, - cacheBust: false, - analytics: !{theme.google_analytics ? true : false}, - scrollRestoration: false - }) - - const triggerPjaxFn = (val) => { - if (!val) return - Object.values(val).forEach(fn => fn()) - } - - document.addEventListener('pjax:send', () => { - // removeEventListener - btf.removeGlobalFnEvent('pjaxSendOnce') - btf.removeGlobalFnEvent('themeChange') - - // reset readmode - const $bodyClassList = document.body.classList - if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode') - - triggerPjaxFn(window.globalFn.pjaxSend) - }) - - document.addEventListener('pjax:complete', () => { - btf.removeGlobalFnEvent('pjaxCompleteOnce') - document.querySelectorAll('script[data-pjax]').forEach(item => { - const newScript = document.createElement('script') - const content = item.text || item.textContent || item.innerHTML || "" - Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value)) - newScript.appendChild(document.createTextNode(content)) - item.parentNode.replaceChild(newScript, item) - }) - - triggerPjaxFn(window.globalFn.pjaxComplete) - }) - - document.addEventListener('pjax:error', e => { - if (e.request.status === 404) { - pjax.loadUrl('!{url_for("/404.html")}') - } - }) +- var pjaxExclude = 'a:not([target="_blank"])' +if theme.pjax.exclude + each val in theme.pjax.exclude + - pjaxExclude += `:not([href="${val}"])` + +- let pjaxSelectors = ['head > title', '#config-diff', '#body-wrap', '#rightside-config-hide', '#rightside-config-show', '.js-pjax'] + +- let choose = theme.comments.use +if choose + if choose.includes('Livere') || choose.includes('Utterances') || choose.includes('Giscus') + - pjaxSelectors.unshift('link[rel="canonical"]') + if theme.Open_Graph_meta.enable + - pjaxSelectors.unshift('meta[property="og:image"]', 'meta[property="og:title"]', 'meta[property="og:url"]', 'meta[property="og:description"]') + else + - pjaxSelectors.unshift('meta[name="description"]') + +script(src=url_for(theme.asset.pjax)) +script. + (() => { + const pjaxSelectors = !{JSON.stringify(pjaxSelectors)} + + window.pjax = new Pjax({ + elements: '!{pjaxExclude}', + selectors: pjaxSelectors, + cacheBust: false, + analytics: !{theme.google_analytics ? true : false}, + scrollRestoration: false + }) + + const triggerPjaxFn = (val) => { + if (!val) return + Object.values(val).forEach(fn => fn()) + } + + document.addEventListener('pjax:send', () => { + // removeEventListener + btf.removeGlobalFnEvent('pjaxSendOnce') + btf.removeGlobalFnEvent('themeChange') + + // reset readmode + const $bodyClassList = document.body.classList + if ($bodyClassList.contains('read-mode')) $bodyClassList.remove('read-mode') + + triggerPjaxFn(window.globalFn.pjaxSend) + }) + + document.addEventListener('pjax:complete', () => { + btf.removeGlobalFnEvent('pjaxCompleteOnce') + document.querySelectorAll('script[data-pjax]').forEach(item => { + const newScript = document.createElement('script') + const content = item.text || item.textContent || item.innerHTML || "" + Array.from(item.attributes).forEach(attr => newScript.setAttribute(attr.name, attr.value)) + newScript.appendChild(document.createTextNode(content)) + item.parentNode.replaceChild(newScript, item) + }) + + triggerPjaxFn(window.globalFn.pjaxComplete) + }) + + document.addEventListener('pjax:error', e => { + if (e.request.status === 404) { + window.location.href = e.request.responseURL + } + }) })() \ No newline at end of file diff --git a/layout/includes/third-party/prismjs.pug b/layout/includes/third-party/prismjs.pug index ee30e8b..b8bc784 100644 --- a/layout/includes/third-party/prismjs.pug +++ b/layout/includes/third-party/prismjs.pug @@ -1,23 +1,23 @@ -- const { prismjs_js, prismjs_autoloader, prismjs_lineNumber_js } = theme.asset -- const { prismjs, syntax_highlighter } = config -- const { enable, preprocess, line_number } = prismjs - -if (syntax_highlighter === 'prismjs' || enable) && !preprocess - script. - (() => { - window.Prism = window.Prism || {} - window.Prism.manual = true - - const highlightAll = () => { - window.Prism.highlightAll() - } - - window.addEventListener('load', highlightAll) - btf.addGlobalFn('pjaxComplete', highlightAll, 'prismjs') - btf.addGlobalFn('encrypt', highlightAll, 'prismjs') - })() - - script(src=url_for(prismjs_js)) - script(src=url_for(prismjs_autoloader)) - if (line_number) +- const { prismjs_js, prismjs_autoloader, prismjs_lineNumber_js } = theme.asset +- const { prismjs, syntax_highlighter } = config +- const { enable, preprocess, line_number } = prismjs + +if (syntax_highlighter === 'prismjs' || enable) && !preprocess + script. + (() => { + window.Prism = window.Prism || {} + window.Prism.manual = true + + const highlightAll = () => { + window.Prism.highlightAll() + } + + window.addEventListener('load', highlightAll) + btf.addGlobalFn('pjaxComplete', highlightAll, 'prismjs') + btf.addGlobalFn('encrypt', highlightAll, 'prismjs') + })() + + script(src=url_for(prismjs_js)) + script(src=url_for(prismjs_autoloader)) + if (line_number) script(src=url_for(prismjs_lineNumber_js)) \ No newline at end of file diff --git a/layout/includes/third-party/search/algolia.pug b/layout/includes/third-party/search/algolia.pug index 4ef6001..c0dd215 100644 --- a/layout/includes/third-party/search/algolia.pug +++ b/layout/includes/third-party/search/algolia.pug @@ -1,22 +1,22 @@ -#algolia-search - .search-dialog - nav.search-nav - span.search-dialog-title= _p('search.title') - button.search-close-button - i.fas.fa-times - - .search-wrap - #algolia-search-input - hr - #algolia-search-results - #algolia-hits - #algolia-pagination - #algolia-info - .algolia-stats - .algolia-poweredBy - - #search-mask - - script(src=url_for(theme.asset.algolia_search)) - script(src=url_for(theme.asset.instantsearch)) +#algolia-search + .search-dialog + nav.search-nav + span.search-dialog-title= _p('search.title') + button.search-close-button + i.fas.fa-times + + .search-wrap + #algolia-search-input + hr + #algolia-search-results + #algolia-hits + #algolia-pagination + #algolia-info + .algolia-stats + .algolia-poweredBy + + #search-mask + + script(src=url_for(theme.asset.algolia_search)) + script(src=url_for(theme.asset.instantsearch)) script(src=url_for(theme.asset.algolia_js)) \ No newline at end of file diff --git a/layout/includes/third-party/search/docsearch.pug b/layout/includes/third-party/search/docsearch.pug index b8e3140..bc23afa 100644 --- a/layout/includes/third-party/search/docsearch.pug +++ b/layout/includes/third-party/search/docsearch.pug @@ -1,29 +1,29 @@ -- const { placeholder, docsearch: { appId, apiKey, indexName, option } } = theme.search - -.docsearch-wrap - #docsearch(style="display:none") - link(rel="stylesheet" href=url_for(theme.asset.docsearch_css)) - script(src=url_for(theme.asset.docsearch_js)) - script. - (() => { - docsearch(Object.assign({ - appId: '!{appId}', - apiKey: '!{apiKey}', - indexName: '!{indexName}', - container: '#docsearch', - placeholder: '!{ placeholder || _p("search.input_placeholder")}', - }, !{JSON.stringify(option)})) - - const handleClick = () => { - document.querySelector('.DocSearch-Button').click() - } - - const searchClickFn = () => { - btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', handleClick) - } - - searchClickFn() - window.addEventListener('pjax:complete', searchClickFn) - })() - - +- const { placeholder, docsearch: { appId, apiKey, indexName, option } } = theme.search + +.docsearch-wrap + #docsearch(style="display:none") + link(rel="stylesheet" href=url_for(theme.asset.docsearch_css)) + script(src=url_for(theme.asset.docsearch_js)) + script. + (() => { + docsearch(Object.assign({ + appId: '!{appId}', + apiKey: '!{apiKey}', + indexName: '!{indexName}', + container: '#docsearch', + placeholder: '!{ placeholder || _p("search.input_placeholder")}', + }, !{JSON.stringify(option)})) + + const handleClick = () => { + document.querySelector('.DocSearch-Button').click() + } + + const searchClickFn = () => { + btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', handleClick) + } + + searchClickFn() + window.addEventListener('pjax:complete', searchClickFn) + })() + + diff --git a/layout/includes/third-party/search/index.pug b/layout/includes/third-party/search/index.pug index a9d0c69..f96f4f8 100644 --- a/layout/includes/third-party/search/index.pug +++ b/layout/includes/third-party/search/index.pug @@ -1,7 +1,7 @@ -case theme.search.use - when 'algolia_search' - include ./algolia.pug - when 'local_search' - include ./local-search.pug - when 'docsearch' +case theme.search.use + when 'algolia_search' + include ./algolia.pug + when 'local_search' + include ./local-search.pug + when 'docsearch' include ./docsearch.pug \ No newline at end of file diff --git a/layout/includes/third-party/search/local-search.pug b/layout/includes/third-party/search/local-search.pug index e459a94..6c28dfd 100644 --- a/layout/includes/third-party/search/local-search.pug +++ b/layout/includes/third-party/search/local-search.pug @@ -1,22 +1,22 @@ -#local-search - .search-dialog - nav.search-nav - span.search-dialog-title= _p('search.title') - span#loading-status - button.search-close-button - i.fas.fa-times - - #loading-database.text-center - i.fas.fa-spinner.fa-pulse - span= ' ' + _p("search.load_data") - - .search-wrap - #local-search-input - .local-search-box - input(placeholder=theme.search.placeholder || _p("search.input_placeholder") type="text").local-search-box--input - hr - #local-search-results - #local-search-stats-wrap - #search-mask - +#local-search + .search-dialog + nav.search-nav + span.search-dialog-title= _p('search.title') + span#loading-status + button.search-close-button + i.fas.fa-times + + #loading-database.text-center + i.fas.fa-spinner.fa-pulse + span= ' ' + _p("search.load_data") + + .search-wrap + #local-search-input + .local-search-box + input(placeholder=theme.search.placeholder || _p("search.input_placeholder") type="text").local-search-box--input + hr + #local-search-results + #local-search-stats-wrap + #search-mask + script(src=url_for(theme.asset.local_search)) \ No newline at end of file diff --git a/layout/includes/third-party/share/addtoany.pug b/layout/includes/third-party/share/addtoany.pug index d42f3be..e6633cb 100644 --- a/layout/includes/third-party/share/addtoany.pug +++ b/layout/includes/third-party/share/addtoany.pug @@ -1,10 +1,10 @@ -.addtoany - .a2a_kit.a2a_kit_size_32.a2a_default_style - - let addtoanyItem = theme.addtoany.item.split(',') - each name in addtoanyItem - a(class="a2a_button_" + name) - - a.a2a_dd(href="https://www.addtoany.com/share") -script(async src='https://static.addtoany.com/menu/page.js') - - +.addtoany + .a2a_kit.a2a_kit_size_32.a2a_default_style + - let addtoanyItem = theme.addtoany.item.split(',') + each name in addtoanyItem + a(class="a2a_button_" + name) + + a.a2a_dd(href="https://www.addtoany.com/share") +script(async src='https://static.addtoany.com/menu/page.js') + + diff --git a/layout/includes/third-party/share/index.pug b/layout/includes/third-party/share/index.pug index 447c589..c385bac 100644 --- a/layout/includes/third-party/share/index.pug +++ b/layout/includes/third-party/share/index.pug @@ -1,9 +1,9 @@ -- const { use } = theme.share - -if use - .post-share - case use - when 'addtoany' - !=partial('includes/third-party/share/addtoany', {}, {cache: true}) - when 'sharejs' +- const { use } = theme.share + +if use + .post-share + case use + when 'addtoany' + !=partial('includes/third-party/share/addtoany', {}, {cache: true}) + when 'sharejs' include ./share-js.pug \ No newline at end of file diff --git a/layout/includes/third-party/share/share-js.pug b/layout/includes/third-party/share/share-js.pug index 50d5528..403ccfe 100644 --- a/layout/includes/third-party/share/share-js.pug +++ b/layout/includes/third-party/share/share-js.pug @@ -1,4 +1,4 @@ -- const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img -.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'") +- const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img +.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'") script(src=url_for(theme.asset.sharejs) defer) \ No newline at end of file diff --git a/layout/includes/third-party/subtitle.pug b/layout/includes/third-party/subtitle.pug index 4689340..3969604 100644 --- a/layout/includes/third-party/subtitle.pug +++ b/layout/includes/third-party/subtitle.pug @@ -1,93 +1,93 @@ -- const { effect,source,sub,typed_option } = theme.subtitle -- let subContent = sub || new Array() - -script. - window.typedJSFn = { - init: str => { - window.typed = new Typed('#subtitle', Object.assign({ - strings: str, - startDelay: 300, - typeSpeed: 150, - loop: true, - backSpeed: 50, - }, !{JSON.stringify(typed_option)})) - }, - run: subtitleType => { - if (!{effect}) { - if (typeof Typed === 'function') { - subtitleType() - } else { - btf.getScript('!{url_for(theme.asset.typed)}').then(subtitleType) - } - } else { - subtitleType() - } - } - } - btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy') - -case source - when 1 - script. - function subtitleType () { - fetch('https://v1.hitokoto.cn') - .then(response => response.json()) - .then(data => { - if (!{effect}) { - const from = '出自 ' + data.from - const sub = !{JSON.stringify(subContent)} - sub.unshift(data.hitokoto, from) - typedJSFn.init(sub) - } else { - document.getElementById('subtitle').textContent = data.hitokoto - } - }) - } - typedJSFn.run(subtitleType) - - when 2 - script. - function subtitleType () { - btf.getScript('https://yijuzhan.com/api/word.php?m=js').then(() => { - const con = str[0] - if (!{effect}) { - const from = '出自 ' + str[1] - const sub = !{JSON.stringify(subContent)} - sub.unshift(con, from) - typedJSFn.init(sub) - } else { - document.getElementById('subtitle').textContent = con - } - }) - } - typedJSFn.run(subtitleType) - - when 3 - script. - function subtitleType () { - btf.getScript('https://sdk.jinrishici.com/v2/browser/jinrishici.js').then(() => { - jinrishici.load(result =>{ - if (!{effect}) { - const sub = !{JSON.stringify(subContent)} - const content = result.data.content - sub.unshift(content) - typedJSFn.init(sub) - } else { - document.getElementById('subtitle').textContent = result.data.content - } - }) - }) - } - typedJSFn.run(subtitleType) - - default - - subContent = subContent.length ? subContent : new Array(config.subtitle) - script. - function subtitleType () { - if (!{effect}) { - typedJSFn.init(!{JSON.stringify(subContent)}) - } else { - document.getElementById("subtitle").textContent = !{JSON.stringify(subContent[0])} - } - } +- const { effect,source,sub,typed_option } = theme.subtitle +- let subContent = sub || new Array() + +script. + window.typedJSFn = { + init: str => { + window.typed = new Typed('#subtitle', Object.assign({ + strings: str, + startDelay: 300, + typeSpeed: 150, + loop: true, + backSpeed: 50, + }, !{JSON.stringify(typed_option)})) + }, + run: subtitleType => { + if (!{effect}) { + if (typeof Typed === 'function') { + subtitleType() + } else { + btf.getScript('!{url_for(theme.asset.typed)}').then(subtitleType) + } + } else { + subtitleType() + } + } + } + btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy') + +case source + when 1 + script. + function subtitleType () { + fetch('https://v1.hitokoto.cn') + .then(response => response.json()) + .then(data => { + if (!{effect}) { + const from = '出自 ' + data.from + const sub = !{JSON.stringify(subContent)} + sub.unshift(data.hitokoto, from) + typedJSFn.init(sub) + } else { + document.getElementById('subtitle').textContent = data.hitokoto + } + }) + } + typedJSFn.run(subtitleType) + + when 2 + script. + function subtitleType () { + btf.getScript('https://yijuzhan.com/api/word.php?m=js').then(() => { + const con = str[0] + if (!{effect}) { + const from = '出自 ' + str[1] + const sub = !{JSON.stringify(subContent)} + sub.unshift(con, from) + typedJSFn.init(sub) + } else { + document.getElementById('subtitle').textContent = con + } + }) + } + typedJSFn.run(subtitleType) + + when 3 + script. + function subtitleType () { + btf.getScript('https://sdk.jinrishici.com/v2/browser/jinrishici.js').then(() => { + jinrishici.load(result =>{ + if (!{effect}) { + const sub = !{JSON.stringify(subContent)} + const content = result.data.content + sub.unshift(content) + typedJSFn.init(sub) + } else { + document.getElementById('subtitle').textContent = result.data.content + } + }) + }) + } + typedJSFn.run(subtitleType) + + default + - subContent = subContent.length ? subContent : new Array(config.subtitle) + script. + function subtitleType () { + if (!{effect}) { + typedJSFn.init(!{JSON.stringify(subContent)}) + } else { + document.getElementById("subtitle").textContent = !{JSON.stringify(subContent[0])} + } + } typedJSFn.run(subtitleType) \ No newline at end of file diff --git a/layout/includes/third-party/umami_analytics.pug b/layout/includes/third-party/umami_analytics.pug index 3534c20..7487425 100644 --- a/layout/includes/third-party/umami_analytics.pug +++ b/layout/includes/third-party/umami_analytics.pug @@ -1,65 +1,65 @@ -- let { serverURL, website_id, option, UV_PV } = theme.umami_analytics -- const isServerURL = !!serverURL -- const baseURL = serverURL ? serverURL.replace(/\/$/, '') : 'https://cloud.umami.is' -- const apiUrl = serverURL ? serverURL.replace(/\/$/, '') + '/api' : 'https://api.umami.is/v1' - -script. - (() => { - const option = !{JSON.stringify(option)} - const config = !{JSON.stringify(UV_PV)} - - const runTrack = () => { - umami.track(props => ({ ...props, url: window.location.pathname, title: GLOBAL_CONFIG_SITE.title })) - } - - const loadUmamiJS = () => { - btf.getScript('!{baseURL}/script.js', { - 'data-website-id': '!{website_id}', - 'data-auto-track': 'false', - ...option - }).then(runTrack) - } - - const getData = async (isPost) => { - const now = Date.now() - const keyUrl = isPost ? `&url=${window.location.pathname}` : '' - const headerList = { 'Accept': 'application/json' } - if (!{isServerURL}) headerList['Authorization'] = `Bearer ${config.token}` - else headerList['x-umami-api-key'] = config.token - const res = await fetch(`!{apiUrl}/websites/!{website_id}/stats?startAt=0000000000&endAt=${now}${keyUrl}`, { - method: "GET", - headers: headerList - }) - return await res.json() - } - - const insertData = async () => { - try { - if (GLOBAL_CONFIG_SITE.pageType === 'post' && config.page_pv) { - const pagePV = document.getElementById('umamiPV') - if (pagePV) { - const data = await getData(true) - pagePV.textContent = data.pageviews.value - } - } else { - const data = (config.site_uv || config.site_pv) && await getData() - if (config.site_uv) { - const siteUV = document.getElementById('umami-site-uv') - if (siteUV) siteUV.textContent = data.visitors.value - } - if (config.site_pv) { - const sitePV = document.getElementById('umami-site-pv') - if (sitePV) sitePV.textContent = data.pageviews.value - } - } - } catch (e) { - console.error('Failed to load Umami Analytics:', e) - } - } - - btf.addGlobalFn('pjaxComplete', runTrack, 'umami_analytics_run_track') - btf.addGlobalFn('pjaxComplete', insertData, 'umami_analytics_insert') - - loadUmamiJS() - insertData() +- let { serverURL, website_id, option, UV_PV } = theme.umami_analytics +- const isServerURL = !!serverURL +- const baseURL = serverURL ? serverURL.replace(/\/$/, '') : 'https://cloud.umami.is' +- const apiUrl = serverURL ? serverURL.replace(/\/$/, '') + '/api' : 'https://api.umami.is/v1' + +script. + (() => { + const option = !{JSON.stringify(option)} + const config = !{JSON.stringify(UV_PV)} + + const runTrack = () => { + umami.track(props => ({ ...props, url: window.location.pathname, title: GLOBAL_CONFIG_SITE.title })) + } + + const loadUmamiJS = () => { + btf.getScript('!{baseURL}/script.js', { + 'data-website-id': '!{website_id}', + 'data-auto-track': 'false', + ...option + }).then(runTrack) + } + + const getData = async (isPost) => { + const now = Date.now() + const keyUrl = isPost ? `&url=${window.location.pathname}` : '' + const headerList = { 'Accept': 'application/json' } + if (!{isServerURL}) headerList['Authorization'] = `Bearer ${config.token}` + else headerList['x-umami-api-key'] = config.token + const res = await fetch(`!{apiUrl}/websites/!{website_id}/stats?startAt=0000000000&endAt=${now}${keyUrl}`, { + method: "GET", + headers: headerList + }) + return await res.json() + } + + const insertData = async () => { + try { + if (GLOBAL_CONFIG_SITE.pageType === 'post' && config.page_pv) { + const pagePV = document.getElementById('umamiPV') + if (pagePV) { + const data = await getData(true) + pagePV.textContent = data.pageviews.value + } + } else { + const data = (config.site_uv || config.site_pv) && await getData() + if (config.site_uv) { + const siteUV = document.getElementById('umami-site-uv') + if (siteUV) siteUV.textContent = data.visitors.value + } + if (config.site_pv) { + const sitePV = document.getElementById('umami-site-pv') + if (sitePV) sitePV.textContent = data.pageviews.value + } + } + } catch (e) { + console.error('Failed to load Umami Analytics:', e) + } + } + + btf.addGlobalFn('pjaxComplete', runTrack, 'umami_analytics_run_track') + btf.addGlobalFn('pjaxComplete', insertData, 'umami_analytics_insert') + + loadUmamiJS() + insertData() })() \ No newline at end of file diff --git a/layout/includes/widget/card_ad.pug b/layout/includes/widget/card_ad.pug index b8e00fd..d088f0e 100644 --- a/layout/includes/widget/card_ad.pug +++ b/layout/includes/widget/card_ad.pug @@ -1,3 +1,3 @@ -if theme.ad && theme.ad.aside - .card-widget.ads-wrap - != theme.ad.aside +if theme.ad && theme.ad.aside + .card-widget.ads-wrap + != theme.ad.aside diff --git a/layout/includes/widget/card_announcement.pug b/layout/includes/widget/card_announcement.pug index 9e63627..a96d06d 100644 --- a/layout/includes/widget/card_announcement.pug +++ b/layout/includes/widget/card_announcement.pug @@ -1,6 +1,6 @@ -if theme.aside.card_announcement.enable - .card-widget.card-announcement - .item-headline - i.fas.fa-bullhorn.fa-shake - span= _p('aside.card_announcement') +if theme.aside.card_announcement.enable + .card-widget.card-announcement + .item-headline + i.fas.fa-bullhorn.fa-shake + span= _p('aside.card_announcement') .announcement_content!= theme.aside.card_announcement.content \ No newline at end of file diff --git a/layout/includes/widget/card_archives.pug b/layout/includes/widget/card_archives.pug index bb0e78e..0fcd17a 100644 --- a/layout/includes/widget/card_archives.pug +++ b/layout/includes/widget/card_archives.pug @@ -1,7 +1,7 @@ -if theme.aside.card_archives.enable - .card-widget.card-archives - - let type = theme.aside.card_archives.type || 'monthly' - - let format = theme.aside.card_archives.format || 'MMMM YYYY' - - let order = theme.aside.card_archives.order || -1 - - let limit = theme.aside.card_archives.limit === 0 ? 0 : theme.aside.card_archives.limit || 8 - != aside_archives({ type:type, format: format, order: order, limit: limit }) +if theme.aside.card_archives.enable + .card-widget.card-archives + - let type = theme.aside.card_archives.type || 'monthly' + - let format = theme.aside.card_archives.format || 'MMMM YYYY' + - let order = theme.aside.card_archives.order || -1 + - let limit = theme.aside.card_archives.limit === 0 ? 0 : theme.aside.card_archives.limit || 8 + != aside_archives({ type:type, format: format, order: order, limit: limit }) diff --git a/layout/includes/widget/card_author.pug b/layout/includes/widget/card_author.pug index 9f7e687..7a30df7 100644 --- a/layout/includes/widget/card_author.pug +++ b/layout/includes/widget/card_author.pug @@ -1,26 +1,26 @@ -if theme.aside.card_author.enable - .card-widget.card-info.text-center - .avatar-img - 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-description!= theme.aside.card_author.description || config.description - - .site-data - a(href=url_for(config.archive_dir) + '/') - .headline= _p('aside.articles') - .length-num= site.posts.length - a(href=url_for(config.tag_dir) + '/') - .headline= _p('aside.tags') - .length-num= site.tags.length - a(href=url_for(config.category_dir) + '/') - .headline= _p('aside.categories') - .length-num= site.categories.length - - if theme.aside.card_author.button.enable - a#card-info-btn(href=theme.aside.card_author.button.link) - i(class=theme.aside.card_author.button.icon) - span=theme.aside.card_author.button.text - - if(theme.social) - .card-info-social-icons - !=partial('includes/header/social', {}, {cache: true}) +if theme.aside.card_author.enable + .card-widget.card-info.text-center + .avatar-img + 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-description!= theme.aside.card_author.description || config.description + + .site-data + a(href=url_for(config.archive_dir) + '/') + .headline= _p('aside.articles') + .length-num= site.posts.length + a(href=url_for(config.tag_dir) + '/') + .headline= _p('aside.tags') + .length-num= site.tags.length + a(href=url_for(config.category_dir) + '/') + .headline= _p('aside.categories') + .length-num= site.categories.length + + if theme.aside.card_author.button.enable + a#card-info-btn(href=theme.aside.card_author.button.link) + i(class=theme.aside.card_author.button.icon) + span=theme.aside.card_author.button.text + + if(theme.social) + .card-info-social-icons + !=partial('includes/header/social', {}, {cache: true}) diff --git a/layout/includes/widget/card_bottom_self.pug b/layout/includes/widget/card_bottom_self.pug index e32907d..31ce298 100644 --- a/layout/includes/widget/card_bottom_self.pug +++ b/layout/includes/widget/card_bottom_self.pug @@ -1,9 +1,9 @@ -if site.data.widget && site.data.widget.bottom - each item in site.data.widget.bottom - .card-widget(class=item.class_name id=item.id_name style=item.order ? `order: ${item.order}` : '') - .item-headline - i(class=item.icon) - span=item.name - .item-content - !=item.html - +if site.data.widget && site.data.widget.bottom + each item in site.data.widget.bottom + .card-widget(class=item.class_name id=item.id_name style=item.order ? `order: ${item.order}` : '') + .item-headline + i(class=item.icon) + span=item.name + .item-content + !=item.html + diff --git a/layout/includes/widget/card_categories.pug b/layout/includes/widget/card_categories.pug index 529ea55..770d035 100644 --- a/layout/includes/widget/card_categories.pug +++ b/layout/includes/widget/card_categories.pug @@ -1,4 +1,4 @@ -if theme.aside.card_categories.enable - if site.categories.length - .card-widget.card-categories - !=aside_categories({ limit: theme.aside.card_categories.limit === 0 ? 0 : theme.aside.card_categories.limit || 8 , expand: theme.aside.card_categories.expand }) +if theme.aside.card_categories.enable + if site.categories.length + .card-widget.card-categories + !=aside_categories({ limit: theme.aside.card_categories.limit === 0 ? 0 : theme.aside.card_categories.limit || 8 , expand: theme.aside.card_categories.expand }) diff --git a/layout/includes/widget/card_newest_comment.pug b/layout/includes/widget/card_newest_comment.pug index 3a0bb18..6f7d5d2 100644 --- a/layout/includes/widget/card_newest_comment.pug +++ b/layout/includes/widget/card_newest_comment.pug @@ -1,7 +1,7 @@ -if theme.aside.card_newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0]) - .card-widget#card-newest-comments - .item-headline - i.fas.fa-comment-dots - span= _p('aside.card_newest_comments.headline') - .aside-list - span= _p('aside.card_newest_comments.loading_text') +if theme.aside.card_newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0]) + .card-widget#card-newest-comments + .item-headline + i.fas.fa-comment-dots + span= _p('aside.card_newest_comments.headline') + .aside-list + span= _p('aside.card_newest_comments.loading_text') diff --git a/layout/includes/widget/card_post_series.pug b/layout/includes/widget/card_post_series.pug index 38f857b..06b82d6 100644 --- a/layout/includes/widget/card_post_series.pug +++ b/layout/includes/widget/card_post_series.pug @@ -1,21 +1,21 @@ -if theme.aside.card_post_series.enable - - const array = fragment_cache('seriesArr', groupPosts) - .card-widget.card-post-series - .item-headline - i.fa-solid.fa-layer-group - span= theme.aside.card_post_series.series_title ? page.series : _p('aside.card_post_series') - .aside-list - each item in array[page.series] - - const { path, title = _p('no_title'), cover, cover_type, date:dateA } = item - - let link = url_for(path) - - let no_cover = cover === false || !theme.cover.aside_enable ? 'no-cover' : '' - .aside-list-item(class=no_cover) - if cover && theme.cover.aside_enable - a.thumbnail(href=link title=title) - if cover_type === 'img' - img(src=url_for(cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) - else - div(style=`background: ${cover}`) - .content - a.title(href=link title=title)= title - time(datetime=date_xml(dateA) title=_p('post.created') + ' ' + full_date(dateA)) #[=date(dateA, config.date_format)] +if theme.aside.card_post_series.enable + - const array = fragment_cache('seriesArr', groupPosts) + .card-widget.card-post-series + .item-headline + i.fa-solid.fa-layer-group + span= theme.aside.card_post_series.series_title ? page.series : _p('aside.card_post_series') + .aside-list + each item in array[page.series] + - const { path, title = _p('no_title'), cover, cover_type, date:dateA } = item + - let link = url_for(path) + - let no_cover = cover === false || !theme.cover.aside_enable ? 'no-cover' : '' + .aside-list-item(class=no_cover) + if cover && theme.cover.aside_enable + a.thumbnail(href=link title=title) + if cover_type === 'img' + img(src=url_for(cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) + else + div(style=`background: ${cover}`) + .content + a.title(href=link title=title)= title + time(datetime=date_xml(dateA) title=_p('post.created') + ' ' + full_date(dateA)) #[=date(dateA, config.date_format)] diff --git a/layout/includes/widget/card_post_toc.pug b/layout/includes/widget/card_post_toc.pug index cd30d50..93f350f 100644 --- a/layout/includes/widget/card_post_toc.pug +++ b/layout/includes/widget/card_post_toc.pug @@ -1,14 +1,14 @@ -- let tocNumber = typeof page.toc_number === 'boolean' ? page.toc_number : theme.toc.number -- let tocExpand = typeof page.toc_expand === 'boolean' ? page.toc_expand : theme.toc.expand -- let tocExpandClass = tocExpand ? 'is-expand' : '' - -#card-toc.card-widget - .item-headline - i.fas.fa-stream - span= _p('aside.card_toc') - span.toc-percentage - - if (page.encrypt == true) - .toc-content.toc-div-class(class=tocExpandClass style="display:none")!=toc(page.origin, {list_number: tocNumber}) - else - .toc-content(class=tocExpandClass)!=toc(page.content, {list_number: tocNumber}) +- let tocNumber = typeof page.toc_number === 'boolean' ? page.toc_number : theme.toc.number +- let tocExpand = typeof page.toc_expand === 'boolean' ? page.toc_expand : theme.toc.expand +- let tocExpandClass = tocExpand ? 'is-expand' : '' + +#card-toc.card-widget + .item-headline + i.fas.fa-stream + span= _p('aside.card_toc') + span.toc-percentage + + if (page.encrypt == true) + .toc-content.toc-div-class(class=tocExpandClass style="display:none")!=toc(page.origin, {list_number: tocNumber}) + else + .toc-content(class=tocExpandClass)!=toc(page.content, {list_number: tocNumber}) diff --git a/layout/includes/widget/card_recent_post.pug b/layout/includes/widget/card_recent_post.pug index dddf0fc..a8c4647 100644 --- a/layout/includes/widget/card_recent_post.pug +++ b/layout/includes/widget/card_recent_post.pug @@ -1,27 +1,27 @@ -if theme.aside.card_recent_post.enable - .card-widget.card-recent-post - .item-headline - i.fas.fa-history - span= _p('aside.card_recent_post') - .aside-list - - let postLimit = theme.aside.card_recent_post.limit === 0 ? site.posts.length : theme.aside.card_recent_post.limit || 5 - - let sort = theme.aside.card_recent_post.sort === 'updated' ? 'updated' : 'date' - - site.posts.sort(sort, -1).limit(postLimit).each(function(article){ - - let link = article.link || article.path - - let title = article.title || _p('no_title') - - let no_cover = article.cover === false || !theme.cover.aside_enable ? 'no-cover' : '' - - let post_cover = article.cover - .aside-list-item(class=no_cover) - if post_cover && theme.cover.aside_enable - a.thumbnail(href=url_for(link) title=title) - if article.cover_type === 'img' - img(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) - else - div(style=`background: ${post_cover}`) - .content - a.title(href=url_for(link) title=title)= title - if theme.aside.card_recent_post.sort === 'updated' - time(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated)) #[=date(article.updated, config.date_format)] - else - time(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date)) #[=date(article.date, config.date_format)] +if theme.aside.card_recent_post.enable + .card-widget.card-recent-post + .item-headline + i.fas.fa-history + span= _p('aside.card_recent_post') + .aside-list + - let postLimit = theme.aside.card_recent_post.limit === 0 ? site.posts.length : theme.aside.card_recent_post.limit || 5 + - let sort = theme.aside.card_recent_post.sort === 'updated' ? 'updated' : 'date' + - site.posts.sort(sort, -1).limit(postLimit).each(function(article){ + - let link = article.link || article.path + - let title = article.title || _p('no_title') + - let no_cover = article.cover === false || !theme.cover.aside_enable ? 'no-cover' : '' + - let post_cover = article.cover + .aside-list-item(class=no_cover) + if post_cover && theme.cover.aside_enable + a.thumbnail(href=url_for(link) title=title) + if article.cover_type === 'img' + img(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) + else + div(style=`background: ${post_cover}`) + .content + a.title(href=url_for(link) title=title)= title + if theme.aside.card_recent_post.sort === 'updated' + time(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated)) #[=date(article.updated, config.date_format)] + else + time(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date)) #[=date(article.date, config.date_format)] - }) \ No newline at end of file diff --git a/layout/includes/widget/card_tags.pug b/layout/includes/widget/card_tags.pug index 49296b7..b0aaa97 100644 --- a/layout/includes/widget/card_tags.pug +++ b/layout/includes/widget/card_tags.pug @@ -1,14 +1,14 @@ -if theme.aside.card_tags.enable - if site.tags.length - .card-widget.card-tags - .item-headline - i.fas.fa-tags - span= _p('aside.card_tags') - - - let { limit, orderby, order } = theme.aside.card_tags - - limit = limit === 0 ? 0 : limit || 40 - - if theme.aside.card_tags.color - .card-tag-cloud!= cloudTags({source: site.tags, orderby: orderby, order: order, minfontsize: 1.15, maxfontsize: 1.45, limit: limit, unit: 'em'}) - else - .card-tag-cloud!= tagcloud({orderby: orderby, order: order, min_font: 1.1, max_font: 1.5, amount: limit , color: true, start_color: '#999', end_color: '#99a9bf', unit: 'em'}) +if theme.aside.card_tags.enable + if site.tags.length + .card-widget.card-tags + .item-headline + i.fas.fa-tags + span= _p('aside.card_tags') + + - let { limit, orderby, order } = theme.aside.card_tags + - limit = limit === 0 ? 0 : limit || 40 + + if theme.aside.card_tags.color + .card-tag-cloud!= cloudTags({source: site.tags, orderby: orderby, order: order, minfontsize: 1.15, maxfontsize: 1.45, limit: limit, unit: 'em'}) + else + .card-tag-cloud!= tagcloud({orderby: orderby, order: order, min_font: 1.1, max_font: 1.5, amount: limit , color: true, start_color: '#999', end_color: '#99a9bf', unit: 'em'}) diff --git a/layout/includes/widget/card_top_self.pug b/layout/includes/widget/card_top_self.pug index 6e81059..3cbfca2 100644 --- a/layout/includes/widget/card_top_self.pug +++ b/layout/includes/widget/card_top_self.pug @@ -1,8 +1,8 @@ -if site.data.widget && site.data.widget.top - each item in site.data.widget.top - .card-widget(class=item.class_name id=item.id_name) - .item-headline - i(class=item.icon) - span=item.name - .item-content +if site.data.widget && site.data.widget.top + each item in site.data.widget.top + .card-widget(class=item.class_name id=item.id_name) + .item-headline + i(class=item.icon) + span=item.name + .item-content !=item.html \ No newline at end of file diff --git a/layout/includes/widget/card_webinfo.pug b/layout/includes/widget/card_webinfo.pug index 7ea4d98..6e481e4 100644 --- a/layout/includes/widget/card_webinfo.pug +++ b/layout/includes/widget/card_webinfo.pug @@ -1,44 +1,44 @@ -if theme.aside.card_webinfo.enable - .card-widget.card-webinfo - .item-headline - i.fas.fa-chart-line - span= _p('aside.card_webinfo.headline') - .webinfo - if theme.aside.card_webinfo.post_count - .webinfo-item - .item-name= `${_p('aside.card_webinfo.article_name')} :` - .item-count= site.posts.length - if theme.aside.card_webinfo.runtime_date - .webinfo-item - .item-name= `${_p('aside.card_webinfo.runtime.name')} :` - .item-count#runtimeshow(data-publishDate=date_xml(theme.aside.card_webinfo.runtime_date)) - i.fa-solid.fa-spinner.fa-spin - if theme.wordcount.enable && theme.wordcount.total_wordcount - .webinfo-item - .item-name= `${_p('aside.card_webinfo.site_wordcount')} :` - .item-count= totalcount(site) - if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.site_uv - .webinfo-item - .item-name= `${_p('aside.card_webinfo.site_uv_name')} :` - .item-count#umami-site-uv - i.fa-solid.fa-spinner.fa-spin - else if theme.busuanzi.site_uv - .webinfo-item - .item-name= `${_p('aside.card_webinfo.site_uv_name')} :` - .item-count#busuanzi_value_site_uv - i.fa-solid.fa-spinner.fa-spin - if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.site_pv - .webinfo-item - .item-name= `${_p('aside.card_webinfo.site_pv_name')} :` - .item-count#umami-site-pv - i.fa-solid.fa-spinner.fa-spin - else if theme.busuanzi.site_pv - .webinfo-item - .item-name= `${_p('aside.card_webinfo.site_pv_name')} :` - .item-count#busuanzi_value_site_pv - i.fa-solid.fa-spinner.fa-spin - if theme.aside.card_webinfo.last_push_date - .webinfo-item - .item-name= `${_p('aside.card_webinfo.last_push_date.name')} :` - .item-count#last-push-date(data-lastPushDate=date_xml(Date.now())) +if theme.aside.card_webinfo.enable + .card-widget.card-webinfo + .item-headline + i.fas.fa-chart-line + span= _p('aside.card_webinfo.headline') + .webinfo + if theme.aside.card_webinfo.post_count + .webinfo-item + .item-name= `${_p('aside.card_webinfo.article_name')} :` + .item-count= site.posts.length + if theme.aside.card_webinfo.runtime_date + .webinfo-item + .item-name= `${_p('aside.card_webinfo.runtime.name')} :` + .item-count#runtimeshow(data-publishDate=date_xml(theme.aside.card_webinfo.runtime_date)) + i.fa-solid.fa-spinner.fa-spin + if theme.wordcount.enable && theme.wordcount.total_wordcount + .webinfo-item + .item-name= `${_p('aside.card_webinfo.site_wordcount')} :` + .item-count= totalcount(site) + if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.site_uv + .webinfo-item + .item-name= `${_p('aside.card_webinfo.site_uv_name')} :` + .item-count#umami-site-uv + i.fa-solid.fa-spinner.fa-spin + else if theme.busuanzi.site_uv + .webinfo-item + .item-name= `${_p('aside.card_webinfo.site_uv_name')} :` + .item-count#busuanzi_value_site_uv + i.fa-solid.fa-spinner.fa-spin + if theme.umami_analytics.enable && theme.umami_analytics.UV_PV.site_pv + .webinfo-item + .item-name= `${_p('aside.card_webinfo.site_pv_name')} :` + .item-count#umami-site-pv + i.fa-solid.fa-spinner.fa-spin + else if theme.busuanzi.site_pv + .webinfo-item + .item-name= `${_p('aside.card_webinfo.site_pv_name')} :` + .item-count#busuanzi_value_site_pv + i.fa-solid.fa-spinner.fa-spin + if theme.aside.card_webinfo.last_push_date + .webinfo-item + .item-name= `${_p('aside.card_webinfo.last_push_date.name')} :` + .item-count#last-push-date(data-lastPushDate=date_xml(Date.now())) i.fa-solid.fa-spinner.fa-spin \ No newline at end of file diff --git a/layout/includes/widget/index.pug b/layout/includes/widget/index.pug index b298878..d9d3d01 100644 --- a/layout/includes/widget/index.pug +++ b/layout/includes/widget/index.pug @@ -1,36 +1,36 @@ -#aside-content.aside-content - //- post - if globalPageType === 'post' - - const tocStyle = page.toc_style_simple - - const tocStyleVal = tocStyle === true || tocStyle === false ? tocStyle : theme.toc.style_simple - if showToc && tocStyleVal - .sticky_layout - include ./card_post_toc.pug - else - !=partial('includes/widget/card_author', {}, {cache: true}) - !=partial('includes/widget/card_announcement', {}, {cache: true}) - !=partial('includes/widget/card_top_self', {}, {cache: true}) - .sticky_layout - if showToc - include ./card_post_toc.pug - if page.series - include ./card_post_series.pug - !=partial('includes/widget/card_recent_post', {}, {cache: true}) - !=partial('includes/widget/card_ad', {}, {cache: true}) - else - //- page - !=partial('includes/widget/card_author', {}, {cache: true}) - !=partial('includes/widget/card_announcement', {}, {cache: true}) - !=partial('includes/widget/card_top_self', {}, {cache: true}) - - .sticky_layout - if showToc - include ./card_post_toc.pug - !=partial('includes/widget/card_recent_post', {}, {cache: true}) - !=partial('includes/widget/card_ad', {}, {cache: true}) - !=partial('includes/widget/card_newest_comment', {}, {cache: true}) - !=partial('includes/widget/card_categories', {}, {cache: true}) - !=partial('includes/widget/card_tags', {}, {cache: true}) - !=partial('includes/widget/card_archives', {}, {cache: true}) - !=partial('includes/widget/card_webinfo', {}, {cache: true}) +#aside-content.aside-content + //- post + if globalPageType === 'post' + - const tocStyle = page.toc_style_simple + - const tocStyleVal = tocStyle === true || tocStyle === false ? tocStyle : theme.toc.style_simple + if showToc && tocStyleVal + .sticky_layout + include ./card_post_toc.pug + else + !=partial('includes/widget/card_author', {}, {cache: true}) + !=partial('includes/widget/card_announcement', {}, {cache: true}) + !=partial('includes/widget/card_top_self', {}, {cache: true}) + .sticky_layout + if showToc + include ./card_post_toc.pug + if page.series + include ./card_post_series.pug + !=partial('includes/widget/card_recent_post', {}, {cache: true}) + !=partial('includes/widget/card_ad', {}, {cache: true}) + else + //- page + !=partial('includes/widget/card_author', {}, {cache: true}) + !=partial('includes/widget/card_announcement', {}, {cache: true}) + !=partial('includes/widget/card_top_self', {}, {cache: true}) + + .sticky_layout + if showToc + include ./card_post_toc.pug + !=partial('includes/widget/card_recent_post', {}, {cache: true}) + !=partial('includes/widget/card_ad', {}, {cache: true}) + !=partial('includes/widget/card_newest_comment', {}, {cache: true}) + !=partial('includes/widget/card_categories', {}, {cache: true}) + !=partial('includes/widget/card_tags', {}, {cache: true}) + !=partial('includes/widget/card_archives', {}, {cache: true}) + !=partial('includes/widget/card_webinfo', {}, {cache: true}) !=partial('includes/widget/card_bottom_self', {}, {cache: true}) \ No newline at end of file diff --git a/layout/index.pug b/layout/index.pug index 7705655..94e6ec7 100644 --- a/layout/index.pug +++ b/layout/index.pug @@ -1,5 +1,5 @@ -extends includes/layout.pug - -block content - include ./includes/mixins/indexPostUI.pug +extends includes/layout.pug + +block content + include ./includes/mixins/indexPostUI.pug +indexPostUI \ No newline at end of file diff --git a/layout/page.pug b/layout/page.pug index 2374681..f980fde 100644 --- a/layout/page.pug +++ b/layout/page.pug @@ -1,32 +1,32 @@ -extends includes/layout.pug - -block content - - const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : '' - - 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 - .page-title= page.title - - case page.type - when 'tags' - include includes/page/tags.pug - +commentLoad - when 'link' - include includes/page/flink.pug - +commentLoad - when 'categories' - include includes/page/categories.pug - +commentLoad - when '404' - include includes/page/404.pug - when 'shuoshuo' - include includes/page/shuoshuo.pug - default - include includes/page/default-page.pug +extends includes/layout.pug + +block content + - const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : '' + - 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 + .page-title= page.title + + case page.type + when 'tags' + include includes/page/tags.pug + +commentLoad + when 'link' + include includes/page/flink.pug + +commentLoad + when 'categories' + include includes/page/categories.pug + +commentLoad + when '404' + include includes/page/404.pug + when 'shuoshuo' + include includes/page/shuoshuo.pug + default + include includes/page/default-page.pug +commentLoad \ No newline at end of file diff --git a/layout/post.pug b/layout/post.pug index 9a44282..46007fb 100644 --- a/layout/post.pug +++ b/layout/post.pug @@ -1,35 +1,35 @@ -extends includes/layout.pug - -block content - #post - if top_img === false - include includes/header/post-info.pug - - article#article-container.container.post-content - if theme.noticeOutdate.enable && page.noticeOutdate !== false - include includes/post/outdate-notice.pug - else - !=page.content - include includes/post/post-copyright.pug - .tag_share - if (page.tags.length > 0 && theme.post_meta.post.tags) - .post-meta__tag-list - each item, index in page.tags.data - a(href=url_for(item.path)).post-meta__tags #[=item.name] - include includes/third-party/share/index.pug - - if theme.reward.enable && theme.reward.QR_code - !=partial('includes/post/reward', {}, {cache: true}) - - //- ad - if theme.ad && theme.ad.post - .ads-wrap!=theme.ad.post - - if theme.post_pagination - include includes/pagination.pug - if theme.related_post && theme.related_post.enable - != related_posts(page,site.posts) - - if page.comments !== false && theme.comments.use - - var commentsJsLoad = true - !=partial('includes/third-party/comments/index', {}, {cache: true}) +extends includes/layout.pug + +block content + #post + if top_img === false + include includes/header/post-info.pug + + article#article-container.container.post-content + if theme.noticeOutdate.enable && page.noticeOutdate !== false + include includes/post/outdate-notice.pug + else + !=page.content + include includes/post/post-copyright.pug + .tag_share + if (page.tags.length > 0 && theme.post_meta.post.tags) + .post-meta__tag-list + each item, index in page.tags.data + a(href=url_for(item.path)).post-meta__tags #[=item.name] + include includes/third-party/share/index.pug + + if theme.reward.enable && theme.reward.QR_code + !=partial('includes/post/reward', {}, {cache: true}) + + //- ad + if theme.ad && theme.ad.post + .ads-wrap!=theme.ad.post + + if theme.post_pagination + include includes/pagination.pug + if theme.related_post && theme.related_post.enable + != related_posts(page,site.posts) + + if page.comments !== false && theme.comments.use + - var commentsJsLoad = true + !=partial('includes/third-party/comments/index', {}, {cache: true}) diff --git a/layout/tag.pug b/layout/tag.pug index 3d4c067..1022544 100644 --- a/layout/tag.pug +++ b/layout/tag.pug @@ -1,12 +1,12 @@ -extends includes/layout.pug - -block content - if theme.tag_ui == 'index' - include ./includes/mixins/indexPostUI.pug - +indexPostUI - else - include ./includes/mixins/article-sort.pug - #tag - .article-sort-title= _p('page.tag') + ' - ' + page.tag - +articleSort(page.posts) +extends includes/layout.pug + +block content + if theme.tag_ui == 'index' + include ./includes/mixins/indexPostUI.pug + +indexPostUI + else + include ./includes/mixins/article-sort.pug + #tag + .article-sort-title= _p('page.tag') + ' - ' + page.tag + +articleSort(page.posts) include includes/pagination.pug \ No newline at end of file diff --git a/package.json b/package.json index 094a021..27543bf 100644 --- a/package.json +++ b/package.json @@ -1,32 +1,32 @@ -{ - "name": "hexo-theme-butterfly", - "version": "5.3.2", - "description": "A Simple and Card UI Design theme for Hexo", - "main": "package.json", - "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" - }, - "keywords": [ - "hexo", - "theme", - "butterfly", - "Card UI Design", - "Jerry", - "hexo-theme-butterfly" - ], - "repository": { - "type" : "git", - "url" : "https://github.com/jerryc127/hexo-theme-butterfly.git" - }, - "bugs": { - "url": "https://github.com/jerryc127/hexo-theme-butterfly/issues", - "email": "my@crazywong.com" - }, - "dependencies": { - "hexo-renderer-stylus": "^3.0.1", - "hexo-renderer-pug": "^3.0.0" - }, - "homepage": "https://butterfly.js.org/", - "author": "Jerry ", - "license": "Apache-2.0" -} +{ + "name": "hexo-theme-butterfly", + "version": "5.3.3", + "description": "A Simple and Card UI Design theme for Hexo", + "main": "package.json", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "hexo", + "theme", + "butterfly", + "Card UI Design", + "Jerry", + "hexo-theme-butterfly" + ], + "repository": { + "type" : "git", + "url" : "https://github.com/jerryc127/hexo-theme-butterfly.git" + }, + "bugs": { + "url": "https://github.com/jerryc127/hexo-theme-butterfly/issues", + "email": "my@crazywong.com" + }, + "dependencies": { + "hexo-renderer-stylus": "^3.0.1", + "hexo-renderer-pug": "^3.0.0" + }, + "homepage": "https://butterfly.js.org/", + "author": "Jerry ", + "license": "Apache-2.0" +} diff --git a/plugins.yml b/plugins.yml index d0474e2..dd0e9d7 100644 --- a/plugins.yml +++ b/plugins.yml @@ -1,211 +1,211 @@ -abcjs_basic_js: - name: abcjs - file: dist/abcjs-basic-min.js - version: 6.4.4 -activate_power_mode: - name: butterfly-extsrc - file: dist/activate-power-mode.min.js - version: 1.1.4 -algolia_search: - name: algoliasearch - file: dist/lite/builds/browser.umd.js - version: 5.19.0 -aplayer_css: - name: aplayer - file: dist/APlayer.min.css - version: 1.10.1 -aplayer_js: - name: aplayer - file: dist/APlayer.min.js - version: 1.10.1 -artalk_css: - name: artalk - file: dist/Artalk.css - version: 2.9.1 -artalk_js: - name: artalk - file: dist/Artalk.js - version: 2.9.1 -blueimp_md5: - name: blueimp-md5 - file: js/md5.min.js - version: 2.19.0 -canvas_fluttering_ribbon: - name: butterfly-extsrc - file: dist/canvas-fluttering-ribbon.min.js - version: 1.1.4 -canvas_nest: - name: butterfly-extsrc - file: dist/canvas-nest.min.js - version: 1.1.4 -canvas_ribbon: - name: butterfly-extsrc - file: dist/canvas-ribbon.min.js - version: 1.1.4 -chartjs: - name: chart.js - file: dist/chart.umd.js - version: 4.4.7 -clickShowText: - name: butterfly-extsrc - file: dist/click-show-text.min.js - version: 1.1.4 -click_heart: - name: butterfly-extsrc - file: dist/click-heart.min.js - version: 1.1.4 -disqusjs: - name: disqusjs - file: dist/browser/disqusjs.es2015.umd.min.js - version: 3.0.2 -disqusjs_css: - name: disqusjs - file: dist/browser/styles/disqusjs.css - version: 3.0.2 -docsearch_css: - name: '@docsearch/css' - other_name: docsearch-css - file: dist/style.css - version: 3.8.2 -docsearch_js: - name: '@docsearch/js' - other_name: docsearch-js - file: dist/umd/index.js - version: 3.8.2 -egjs_infinitegrid: - name: '@egjs/infinitegrid' - other_name: egjs-infinitegrid - file: dist/infinitegrid.min.js - version: 4.12.0 -fancybox: - name: '@fancyapps/ui' - file: dist/fancybox/fancybox.umd.js - version: 5.0.36 - other_name: fancyapps-ui -fancybox_css: - name: '@fancyapps/ui' - file: dist/fancybox/fancybox.css - version: 5.0.36 - other_name: fancyapps-ui -fireworks: - name: butterfly-extsrc - file: dist/fireworks.min.js - version: 1.1.4 -fontawesome: - name: '@fortawesome/fontawesome-free' - file: css/all.min.css - other_name: font-awesome - version: 6.7.2 -gitalk: - name: gitalk - file: dist/gitalk.min.js - version: 1.8.0 -gitalk_css: - name: gitalk - file: dist/gitalk.css - version: 1.8.0 -instantpage: - name: instant.page - file: instantpage.js - version: 5.2.0 -instantsearch: - name: instantsearch.js - file: dist/instantsearch.production.min.js - version: 4.75.7 -katex: - name: katex - file: dist/katex.min.css - other_name: KaTeX - version: 0.16.19 -katex_copytex: - name: katex - file: dist/contrib/copy-tex.min.js - other_name: KaTeX - version: 0.16.19 -lazyload: - name: vanilla-lazyload - file: dist/lazyload.iife.min.js - version: 19.1.3 -mathjax: - name: mathjax - file: es5/tex-mml-chtml.js - version: 3.2.2 -medium_zoom: - name: medium-zoom - file: dist/medium-zoom.min.js - version: 1.1.0 -mermaid: - name: mermaid - file: dist/mermaid.min.js - version: 11.4.1 -meting_js: - name: butterfly-extsrc - file: metingjs/dist/Meting.min.js - version: 1.1.4 -pace_default_css: - name: pace-js - other_name: pace - file: themes/blue/pace-theme-minimal.css - version: 1.2.4 -pace_js: - name: pace-js - other_name: pace - file: pace.min.js - version: 1.2.4 -pjax: - name: pjax - file: pjax.min.js - version: 0.2.8 -prismjs_autoloader: - name: prismjs - file: plugins/autoloader/prism-autoloader.min.js - other_name: prism - version: 1.29.0 -prismjs_js: - name: prismjs - file: prism.js - other_name: prism - version: 1.29.0 -prismjs_lineNumber_js: - name: prismjs - file: plugins/line-numbers/prism-line-numbers.min.js - other_name: prism - version: 1.29.0 -sharejs: - name: butterfly-extsrc - file: sharejs/dist/js/social-share.min.js - version: 1.1.4 -sharejs_css: - name: butterfly-extsrc - file: sharejs/dist/css/share.min.css - version: 1.1.4 -snackbar: - name: node-snackbar - file: dist/snackbar.min.js - version: 0.1.16 -snackbar_css: - name: node-snackbar - file: dist/snackbar.min.css - version: 0.1.16 -twikoo: - name: twikoo - file: dist/twikoo.all.min.js - version: 1.6.41 -typed: - name: typed.js - file: dist/typed.umd.js - version: 2.1.0 -valine: - name: valine - file: dist/Valine.min.js - version: 1.5.3 -waline_css: - name: '@waline/client' - file: dist/waline.css - other_name: waline - version: 3.4.3 -waline_js: - name: '@waline/client' - file: dist/waline.js - other_name: waline - version: 3.4.3 +abcjs_basic_js: + name: abcjs + file: dist/abcjs-basic-min.js + version: 6.4.4 +activate_power_mode: + name: butterfly-extsrc + file: dist/activate-power-mode.min.js + version: 1.1.4 +algolia_search: + name: algoliasearch + file: dist/lite/builds/browser.umd.js + version: 5.20.2 +aplayer_css: + name: aplayer + file: dist/APlayer.min.css + version: 1.10.1 +aplayer_js: + name: aplayer + file: dist/APlayer.min.js + version: 1.10.1 +artalk_css: + name: artalk + file: dist/Artalk.css + version: 2.9.1 +artalk_js: + name: artalk + file: dist/Artalk.js + version: 2.9.1 +blueimp_md5: + name: blueimp-md5 + file: js/md5.min.js + version: 2.19.0 +canvas_fluttering_ribbon: + name: butterfly-extsrc + file: dist/canvas-fluttering-ribbon.min.js + version: 1.1.4 +canvas_nest: + name: butterfly-extsrc + file: dist/canvas-nest.min.js + version: 1.1.4 +canvas_ribbon: + name: butterfly-extsrc + file: dist/canvas-ribbon.min.js + version: 1.1.4 +chartjs: + name: chart.js + file: dist/chart.umd.js + version: 4.4.7 +clickShowText: + name: butterfly-extsrc + file: dist/click-show-text.min.js + version: 1.1.4 +click_heart: + name: butterfly-extsrc + file: dist/click-heart.min.js + version: 1.1.4 +disqusjs: + name: disqusjs + file: dist/browser/disqusjs.es2015.umd.min.js + version: 3.0.2 +disqusjs_css: + name: disqusjs + file: dist/browser/styles/disqusjs.css + version: 3.0.2 +docsearch_css: + name: '@docsearch/css' + other_name: docsearch-css + file: dist/style.css + version: 3.8.3 +docsearch_js: + name: '@docsearch/js' + other_name: docsearch-js + file: dist/umd/index.js + version: 3.8.3 +egjs_infinitegrid: + name: '@egjs/infinitegrid' + other_name: egjs-infinitegrid + file: dist/infinitegrid.min.js + version: 4.12.0 +fancybox: + name: '@fancyapps/ui' + file: dist/fancybox/fancybox.umd.js + version: 5.0.36 + other_name: fancyapps-ui +fancybox_css: + name: '@fancyapps/ui' + file: dist/fancybox/fancybox.css + version: 5.0.36 + other_name: fancyapps-ui +fireworks: + name: butterfly-extsrc + file: dist/fireworks.min.js + version: 1.1.4 +fontawesome: + name: '@fortawesome/fontawesome-free' + file: css/all.min.css + other_name: font-awesome + version: 6.7.2 +gitalk: + name: gitalk + file: dist/gitalk.min.js + version: 1.8.0 +gitalk_css: + name: gitalk + file: dist/gitalk.css + version: 1.8.0 +instantpage: + name: instant.page + file: instantpage.js + version: 5.2.0 +instantsearch: + name: instantsearch.js + file: dist/instantsearch.production.min.js + version: 4.77.3 +katex: + name: katex + file: dist/katex.min.css + other_name: KaTeX + version: 0.16.21 +katex_copytex: + name: katex + file: dist/contrib/copy-tex.min.js + other_name: KaTeX + version: 0.16.21 +lazyload: + name: vanilla-lazyload + file: dist/lazyload.iife.min.js + version: 19.1.3 +mathjax: + name: mathjax + file: es5/tex-mml-chtml.js + version: 3.2.2 +medium_zoom: + name: medium-zoom + file: dist/medium-zoom.min.js + version: 1.1.0 +mermaid: + name: mermaid + file: dist/mermaid.min.js + version: 11.4.1 +meting_js: + name: butterfly-extsrc + file: metingjs/dist/Meting.min.js + version: 1.1.4 +pace_default_css: + name: pace-js + other_name: pace + file: themes/blue/pace-theme-minimal.css + version: 1.2.4 +pace_js: + name: pace-js + other_name: pace + file: pace.min.js + version: 1.2.4 +pjax: + name: pjax + file: pjax.min.js + version: 0.2.8 +prismjs_autoloader: + name: prismjs + file: plugins/autoloader/prism-autoloader.min.js + other_name: prism + version: 1.29.0 +prismjs_js: + name: prismjs + file: prism.js + other_name: prism + version: 1.29.0 +prismjs_lineNumber_js: + name: prismjs + file: plugins/line-numbers/prism-line-numbers.min.js + other_name: prism + version: 1.29.0 +sharejs: + name: butterfly-extsrc + file: sharejs/dist/js/social-share.min.js + version: 1.1.4 +sharejs_css: + name: butterfly-extsrc + file: sharejs/dist/css/share.min.css + version: 1.1.4 +snackbar: + name: node-snackbar + file: dist/snackbar.min.js + version: 0.1.16 +snackbar_css: + name: node-snackbar + file: dist/snackbar.min.css + version: 0.1.16 +twikoo: + name: twikoo + file: dist/twikoo.all.min.js + version: 1.6.41 +typed: + name: typed.js + file: dist/typed.umd.js + version: 2.1.0 +valine: + name: valine + file: dist/Valine.min.js + version: 1.5.3 +waline_css: + name: '@waline/client' + file: dist/waline.css + other_name: waline + version: 3.5.2 +waline_js: + name: '@waline/client' + file: dist/waline.js + other_name: waline + version: 3.5.2 diff --git a/scripts/common/postDesc.js b/scripts/common/postDesc.js index e20e86e..f2d547f 100644 --- a/scripts/common/postDesc.js +++ b/scripts/common/postDesc.js @@ -1,36 +1,36 @@ -'use strict' - -const { stripHTML, truncate } = require('hexo-util') - -// Truncates the given content to a specified length, removing HTML tags and replacing newlines with spaces. -const truncateContent = (content, length) => { - return truncate(stripHTML(content), { length, separator: ' ' }).replace(/\n/g, ' ') -} - -// Generates a post description based on the provided data and theme configuration. -const postDesc = (data, hexo) => { - const { description, content, postDesc } = data - - if (postDesc) return postDesc - - const { length, method } = hexo.theme.config.index_post_content - - if (method === false) return - - let result - switch (method) { - case 1: - result = description - break - case 2: - result = description || truncateContent(content, length) - break - default: - result = truncateContent(content, length) - } - - data.postDesc = result - return result -} - -module.exports = { truncateContent, postDesc } +'use strict' + +const { stripHTML, truncate } = require('hexo-util') + +// Truncates the given content to a specified length, removing HTML tags and replacing newlines with spaces. +const truncateContent = (content, length) => { + return truncate(stripHTML(content), { length, separator: ' ' }).replace(/\n/g, ' ') +} + +// Generates a post description based on the provided data and theme configuration. +const postDesc = (data, hexo) => { + const { description, content, postDesc } = data + + if (postDesc) return postDesc + + const { length, method } = hexo.theme.config.index_post_content + + if (method === false) return + + let result + switch (method) { + case 1: + result = description + break + case 2: + result = description || truncateContent(content, length) + break + default: + result = truncateContent(content, length) + } + + data.postDesc = result + return result +} + +module.exports = { truncateContent, postDesc } diff --git a/scripts/events/404.js b/scripts/events/404.js index 17a05e9..157ef06 100644 --- a/scripts/events/404.js +++ b/scripts/events/404.js @@ -1,20 +1,20 @@ -/** - * Butterfly - * 404 error page - */ - -'use strict' - -hexo.extend.generator.register('404', function (locals) { - if (!hexo.theme.config.error_404.enable) return - return { - path: '404.html', - layout: ['page'], - data: { - type: '404', - top_img: false, - comments: false, - aside: false - } - } -}) +/** + * Butterfly + * 404 error page + */ + +'use strict' + +hexo.extend.generator.register('404', function (locals) { + if (!hexo.theme.config.error_404.enable) return + return { + path: '404.html', + layout: ['page'], + data: { + type: '404', + top_img: false, + comments: false, + aside: false + } + } +}) diff --git a/scripts/events/cdn.js b/scripts/events/cdn.js index b83404f..7d3e31e 100644 --- a/scripts/events/cdn.js +++ b/scripts/events/cdn.js @@ -1,97 +1,97 @@ -/** - * Butterfly - * Merge CDN - */ - -'use strict' - -const { version } = require('../../package.json') -const path = require('path') - -hexo.extend.filter.register('before_generate', () => { - const themeConfig = hexo.theme.config - const { CDN } = themeConfig - - const thirdPartySrc = hexo.render.renderSync({ path: path.join(hexo.theme_dir, '/plugins.yml'), engine: 'yaml' }) - const internalSrc = { - main: { - name: 'hexo-theme-butterfly', - file: 'js/main.js', - version - }, - utils: { - name: 'hexo-theme-butterfly', - file: 'js/utils.js', - version - }, - translate: { - name: 'hexo-theme-butterfly', - file: 'js/tw_cn.js', - version - }, - local_search: { - name: 'hexo-theme-butterfly', - file: 'js/search/local-search.js', - version - }, - algolia_js: { - name: 'hexo-theme-butterfly', - file: 'js/search/algolia.js', - version - } - } - - const minFile = file => { - return file.replace(/(? '.min' + ext) - } - - const createCDNLink = (data, type, cond = '') => { - Object.keys(data).forEach(key => { - let { name, version, file, other_name } = data[key] - const cdnjs_name = other_name || name - const cdnjs_file = file.replace(/^[lib|dist]*\/|browser\//g, '') - const min_cdnjs_file = minFile(cdnjs_file) - if (cond === 'internal') file = `source/${file}` - const min_file = minFile(file) - const verType = CDN.version ? (type === 'local' ? `?v=${version}` : `@${version}`) : '' - - const value = { - version, - name, - file, - cdnjs_file, - min_file, - min_cdnjs_file, - cdnjs_name - } - - const cdnSource = { - local: cond === 'internal' ? `${cdnjs_file + verType}` : `/pluginsSrc/${name}/${file + verType}`, - jsdelivr: `https://cdn.jsdelivr.net/npm/${name}${verType}/${min_file}`, - unpkg: `https://unpkg.com/${name}${verType}/${file}`, - cdnjs: `https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${min_cdnjs_file}`, - custom: (CDN.custom_format || '').replace(/\$\{(.+?)\}/g, (match, $1) => value[$1]) - } - - data[key] = cdnSource[type] - }) - - if (cond === 'internal') data.main_css = 'css/index.css' + (CDN.version ? `?v=${version}` : '') - return data - } - - // delete null value - const deleteNullValue = obj => { - if (!obj) return - for (const i in obj) { - obj[i] === null && delete obj[i] - } - return obj - } - - themeConfig.asset = Object.assign( - createCDNLink(internalSrc, CDN.internal_provider, 'internal'), - createCDNLink(thirdPartySrc, CDN.third_party_provider), - deleteNullValue(CDN.option) - ) -}) +/** + * Butterfly + * Merge CDN + */ + +'use strict' + +const { version } = require('../../package.json') +const path = require('path') + +hexo.extend.filter.register('before_generate', () => { + const themeConfig = hexo.theme.config + const { CDN } = themeConfig + + const thirdPartySrc = hexo.render.renderSync({ path: path.join(hexo.theme_dir, '/plugins.yml'), engine: 'yaml' }) + const internalSrc = { + main: { + name: 'hexo-theme-butterfly', + file: 'js/main.js', + version + }, + utils: { + name: 'hexo-theme-butterfly', + file: 'js/utils.js', + version + }, + translate: { + name: 'hexo-theme-butterfly', + file: 'js/tw_cn.js', + version + }, + local_search: { + name: 'hexo-theme-butterfly', + file: 'js/search/local-search.js', + version + }, + algolia_js: { + name: 'hexo-theme-butterfly', + file: 'js/search/algolia.js', + version + } + } + + const minFile = file => { + return file.replace(/(? '.min' + ext) + } + + const createCDNLink = (data, type, cond = '') => { + Object.keys(data).forEach(key => { + let { name, version, file, other_name } = data[key] + const cdnjs_name = other_name || name + const cdnjs_file = file.replace(/^[lib|dist]*\/|browser\//g, '') + const min_cdnjs_file = minFile(cdnjs_file) + if (cond === 'internal') file = `source/${file}` + const min_file = minFile(file) + const verType = CDN.version ? (type === 'local' ? `?v=${version}` : `@${version}`) : '' + + const value = { + version, + name, + file, + cdnjs_file, + min_file, + min_cdnjs_file, + cdnjs_name + } + + const cdnSource = { + local: cond === 'internal' ? `${cdnjs_file + verType}` : `/pluginsSrc/${name}/${file + verType}`, + jsdelivr: `https://cdn.jsdelivr.net/npm/${name}${verType}/${min_file}`, + unpkg: `https://unpkg.com/${name}${verType}/${file}`, + cdnjs: `https://cdnjs.cloudflare.com/ajax/libs/${cdnjs_name}/${version}/${min_cdnjs_file}`, + custom: (CDN.custom_format || '').replace(/\$\{(.+?)\}/g, (match, $1) => value[$1]) + } + + data[key] = cdnSource[type] + }) + + if (cond === 'internal') data.main_css = 'css/index.css' + (CDN.version ? `?v=${version}` : '') + return data + } + + // delete null value + const deleteNullValue = obj => { + if (!obj) return + for (const i in obj) { + obj[i] === null && delete obj[i] + } + return obj + } + + themeConfig.asset = Object.assign( + createCDNLink(internalSrc, CDN.internal_provider, 'internal'), + createCDNLink(thirdPartySrc, CDN.third_party_provider), + deleteNullValue(CDN.option) + ) +}) diff --git a/scripts/events/comment.js b/scripts/events/comment.js index 16da948..83a67e9 100644 --- a/scripts/events/comment.js +++ b/scripts/events/comment.js @@ -1,24 +1,24 @@ -/** - * Capitalize the first letter of comment name - */ - -hexo.extend.filter.register('before_generate', () => { - const themeConfig = hexo.theme.config - let { use } = themeConfig.comments - if (!use) return - - // Make sure use is an array - use = Array.isArray(use) ? use : use.split(',') - - // Capitalize the first letter of each comment name - use = use.map(item => - item.trim().toLowerCase().replace(/\b[a-z]/g, s => s.toUpperCase()) - ) - - // Disqus and Disqusjs conflict, only keep the first one - if (use.includes('Disqus') && use.includes('Disqusjs')) { - use = [use[0]] - } - - themeConfig.comments.use = use -}) +/** + * Capitalize the first letter of comment name + */ + +hexo.extend.filter.register('before_generate', () => { + const themeConfig = hexo.theme.config + let { use } = themeConfig.comments + if (!use) return + + // Make sure use is an array + use = Array.isArray(use) ? use : use.split(',') + + // Capitalize the first letter of each comment name + use = use.map(item => + item.trim().toLowerCase().replace(/\b[a-z]/g, s => s.toUpperCase()) + ) + + // Disqus and Disqusjs conflict, only keep the first one + if (use.includes('Disqus') && use.includes('Disqusjs')) { + use = [use[0]] + } + + themeConfig.comments.use = use +}) diff --git a/scripts/events/init.js b/scripts/events/init.js index 36304d8..dab4696 100644 --- a/scripts/events/init.js +++ b/scripts/events/init.js @@ -1,20 +1,20 @@ -hexo.extend.filter.register('before_generate', () => { - // Get first two digits of the Hexo version number - const { version, log, locals } = hexo - const hexoVer = version.replace(/(^.*\..*)\..*/, '$1') - - if (hexoVer < 5.3) { - log.error('Please update Hexo to V5.3.0 or higher!') - log.error('請把 Hexo 升級到 V5.3.0 或更高的版本!') - process.exit(-1) - } - - if (locals.get) { - const data = locals.get('data') - if (data && data.butterfly) { - log.error("'butterfly.yml' is deprecated. Please use '_config.butterfly.yml'") - log.error("'butterfly.yml' 已經棄用,請使用 '_config.butterfly.yml'") - process.exit(-1) - } - } -}) +hexo.extend.filter.register('before_generate', () => { + // Get first two digits of the Hexo version number + const { version, log, locals } = hexo + const hexoVer = version.replace(/(^.*\..*)\..*/, '$1') + + if (hexoVer < 5.3) { + log.error('Please update Hexo to V5.3.0 or higher!') + log.error('請把 Hexo 升級到 V5.3.0 或更高的版本!') + process.exit(-1) + } + + if (locals.get) { + const data = locals.get('data') + if (data && data.butterfly) { + log.error("'butterfly.yml' is deprecated. Please use '_config.butterfly.yml'") + log.error("'butterfly.yml' 已經棄用,請使用 '_config.butterfly.yml'") + process.exit(-1) + } + } +}) diff --git a/scripts/events/merge_config.js b/scripts/events/merge_config.js index c14c57c..eb27857 100644 --- a/scripts/events/merge_config.js +++ b/scripts/events/merge_config.js @@ -1,583 +1,583 @@ -const { deepMerge } = require('hexo-util') - -hexo.extend.filter.register('before_generate', () => { - const defaultConfig = { - nav: { - logo: null, - display_title: true, - fixed: false - }, - menu: null, - code_blocks: { - theme: 'light', - macStyle: false, - height_limit: false, - word_wrap: false, - copy: true, - language: true, - shrink: false, - fullpage: false - }, - social: null, - favicon: '/img/favicon.png', - avatar: { - img: '/img/butterfly-icon.png', - effect: false - }, - disable_top_img: false, - default_top_img: null, - index_img: null, - archive_img: null, - tag_img: null, - tag_per_img: null, - category_img: null, - category_per_img: null, - footer_img: false, - background: null, - cover: { - index_enable: true, - aside_enable: true, - archives_enable: true, - default_cover: null - }, - error_img: { - flink: '/img/friend_404.gif', - post_page: '/img/404.jpg' - }, - error_404: { - enable: false, - subtitle: 'Page Not Found', - background: '/img/error-page.png' - }, - post_meta: { - page: { - date_type: 'created', - date_format: 'date', - categories: true, - tags: false, - label: true - }, - post: { - position: 'left', - date_type: 'both', - date_format: 'date', - categories: true, - tags: 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: { - method: 3, - length: 500 - }, - toc: { - post: true, - page: false, - number: true, - expand: false, - style_simple: false, - scroll_percent: true - }, - post_copyright: { - enable: true, - decode: false, - author_href: null, - license: 'CC BY-NC-SA 4.0', - license_url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/' - }, - reward: { - enable: false, - text: null, - QR_code: null - }, - post_edit: { - enable: false, - url: null - }, - related_post: { - enable: true, - limit: 6, - date_type: 'created' - }, - post_pagination: 1, - noticeOutdate: { - enable: false, - style: 'flat', - limit_day: 365, - position: 'top', - message_prev: 'It has been', - message_next: 'days since the last update, the content of the article may be outdated.' - }, - footer: { - owner: { - enable: true, - since: 2019 - }, - custom_text: null, - copyright: true - }, - aside: { - enable: true, - hide: false, - button: true, - mobile: true, - position: 'right', - display: { - archive: true, - tag: true, - category: true - }, - card_author: { - enable: true, - description: null, - button: { - enable: true, - icon: 'fab fa-github', - text: 'Follow Me', - link: 'https://github.com/xxxxxx' - } - }, - card_announcement: { - enable: true, - content: 'This is my Blog' - }, - card_recent_post: { - enable: true, - limit: 5, - sort: 'date', - sort_order: null - }, - card_newest_comments: { - enable: false, - sort_order: null, - limit: 6, - storage: 10, - avatar: true - }, - card_categories: { - enable: true, - limit: 8, - expand: 'none', - sort_order: null - }, - card_tags: { - enable: true, - limit: 40, - color: false, - orderby: 'random', - order: 1, - sort_order: null - }, - card_archives: { - enable: true, - type: 'monthly', - format: 'MMMM YYYY', - order: -1, - limit: 8, - sort_order: null - }, - card_post_series: { - enable: true, - series_title: false, - orderBy: 'date', - order: -1 - }, - card_webinfo: { - enable: true, - post_count: true, - last_push_date: true, - sort_order: null, - runtime_date: null - } - }, - rightside_bottom: null, - translate: { - enable: false, - default: '繁', - defaultEncoding: 2, - translateDelay: 0, - msgToTraditionalChinese: '繁', - msgToSimplifiedChinese: '簡' - }, - readmode: true, - darkmode: { - enable: true, - button: true, - autoChangeMode: false, - start: null, - end: null - }, - rightside_scroll_percent: false, - rightside_item_order: { - enable: false, - hide: null, - show: null - }, - anchor: { - auto_update: false, - click_to_scroll: false - }, - photofigcaption: false, - copy: { - enable: true, - copyright: { - enable: false, - limit_count: 150 - } - }, - wordcount: { - enable: false, - post_wordcount: true, - 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: { - preload: false, - top_n_per_article: 1, - unescape: false, - CDN: null - }, - docsearch: { - appId: null, - apiKey: null, - indexName: null, - option: null - } - }, - share: { - use: 'sharejs', - sharejs: { - sites: 'facebook,twitter,wechat,weibo,qq' - }, - addtoany: { - item: 'facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link' - } - }, - comments: { - use: null, - text: true, - lazyload: false, - count: false, - card_post_count: false - }, - disqus: { - shortname: null, - apikey: null - }, - disqusjs: { - shortname: null, - apikey: null, - option: null - }, - livere: { - uid: null - }, - gitalk: { - client_id: null, - client_secret: null, - repo: null, - owner: null, - admin: null, - option: null - }, - valine: { - appId: null, - appKey: null, - avatar: 'monsterid', - serverURLs: null, - bg: null, - visitor: false, - option: null - }, - waline: { - serverURL: null, - bg: null, - pageview: false, - option: null - }, - utterances: { - repo: null, - issue_term: 'pathname', - light_theme: 'github-light', - dark_theme: 'photon-dark', - js: null, - option: null - }, - facebook_comments: { - app_id: null, - user_id: null, - pageSize: 10, - order_by: 'social', - lang: 'en_US' - }, - twikoo: { - envId: null, - region: null, - visitor: false, - option: null - }, - giscus: { - repo: null, - repo_id: null, - category_id: null, - light_theme: 'light', - dark_theme: 'dark', - js: null, - option: null - }, - remark42: { - host: null, - siteId: null, - option: null - }, - artalk: { - server: null, - site: null, - visitor: false, - option: null - }, - chat: { - use: null, - rightside_button: false, - button_hide_show: false - }, - chatra: { - id: null - }, - tidio: { - public_key: null - }, - crisp: { - website_id: null - }, - baidu_analytics: null, - google_analytics: null, - cloudflare_analytics: null, - microsoft_clarity: null, - umami_analytics: { - enable: false, - serverURL: null, - website_id: null, - option: null, - UV_PV: { - site_uv: false, - site_pv: false, - page_pv: false, - token: null - } - }, - google_adsense: { - enable: false, - auto_ads: true, - js: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', - client: null, - enable_page_level_ads: true - }, - ad: { - index: null, - aside: null, - post: null - }, - site_verification: null, - category_ui: null, - tag_ui: null, - rounded_corners_ui: true, - text_align_justify: false, - mask: { - header: true, - footer: true - }, - preloader: { - enable: false, - source: 1, - pace_css_url: null - }, - 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: { - enable: false, - colorful: true, - shake: true, - mobile: false - }, - canvas_ribbon: { - enable: false, - size: 150, - alpha: 0.6, - zIndex: -1, - click_to_change: false, - mobile: false - }, - canvas_fluttering_ribbon: { - enable: false, - mobile: false - }, - canvas_nest: { - enable: false, - color: '0,0,255', - opacity: 0.7, - zIndex: -1, - count: 99, - mobile: false - }, - fireworks: { - enable: false, - zIndex: 9999, - mobile: false - }, - click_heart: { - enable: false, - mobile: false - }, - clickShowText: { - enable: false, - text: null, - fontSize: '15px', - random: false, - mobile: false - }, - lightbox: null, - series: { - enable: false, - orderBy: 'title', - order: 1, - number: true - }, - abcjs: { - enable: false, - per_page: true - }, - mermaid: { - enable: false, - code_write: false, - theme: { - light: 'default', - dark: 'dark' - } - }, - chartjs: { - enable: false, - fontColor: { - light: 'rgba(0, 0, 0, 0.8)', - dark: 'rgba(255, 255, 255, 0.8)' - }, - borderColor: { - light: 'rgba(0, 0, 0, 0.1)', - dark: 'rgba(255, 255, 255, 0.2)' - }, - scale_ticks_backdropColor: { - light: 'transparent', - dark: 'transparent' - } - }, - note: { - style: 'flat', - icons: true, - border_radius: 3, - light_bg_offset: 0 - }, - pjax: { - enable: false, - exclude: null - }, - aplayerInject: { - enable: false, - per_page: true - }, - snackbar: { - enable: false, - position: 'bottom-left', - bg_light: '#49b1f5', - bg_dark: '#1f1f1f' - }, - instantpage: false, - lazyload: { - enable: false, - native: false, - field: 'site', - placeholder: null, - 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: { - enable: true, - option: null - }, - structured_data: true, - css_prefix: true, - inject: { - head: null, - bottom: null - }, - CDN: { - internal_provider: 'local', - third_party_provider: 'jsdelivr', - version: false, - custom_format: null, - option: null - } - } - - hexo.theme.config = deepMerge(defaultConfig, hexo.theme.config) -}, 1) +const { deepMerge } = require('hexo-util') + +hexo.extend.filter.register('before_generate', () => { + const defaultConfig = { + nav: { + logo: null, + display_title: true, + fixed: false + }, + menu: null, + code_blocks: { + theme: 'light', + macStyle: false, + height_limit: false, + word_wrap: false, + copy: true, + language: true, + shrink: false, + fullpage: false + }, + social: null, + favicon: '/img/favicon.png', + avatar: { + img: '/img/butterfly-icon.png', + effect: false + }, + disable_top_img: false, + default_top_img: null, + index_img: null, + archive_img: null, + tag_img: null, + tag_per_img: null, + category_img: null, + category_per_img: null, + footer_img: false, + background: null, + cover: { + index_enable: true, + aside_enable: true, + archives_enable: true, + default_cover: null + }, + error_img: { + flink: '/img/friend_404.gif', + post_page: '/img/404.jpg' + }, + error_404: { + enable: false, + subtitle: 'Page Not Found', + background: '/img/error-page.png' + }, + post_meta: { + page: { + date_type: 'created', + date_format: 'date', + categories: true, + tags: false, + label: true + }, + post: { + position: 'left', + date_type: 'both', + date_format: 'date', + categories: true, + tags: 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: { + method: 3, + length: 500 + }, + toc: { + post: true, + page: false, + number: true, + expand: false, + style_simple: false, + scroll_percent: true + }, + post_copyright: { + enable: true, + decode: false, + author_href: null, + license: 'CC BY-NC-SA 4.0', + license_url: 'https://creativecommons.org/licenses/by-nc-sa/4.0/' + }, + reward: { + enable: false, + text: null, + QR_code: null + }, + post_edit: { + enable: false, + url: null + }, + related_post: { + enable: true, + limit: 6, + date_type: 'created' + }, + post_pagination: 1, + noticeOutdate: { + enable: false, + style: 'flat', + limit_day: 365, + position: 'top', + message_prev: 'It has been', + message_next: 'days since the last update, the content of the article may be outdated.' + }, + footer: { + owner: { + enable: true, + since: 2019 + }, + custom_text: null, + copyright: true + }, + aside: { + enable: true, + hide: false, + button: true, + mobile: true, + position: 'right', + display: { + archive: true, + tag: true, + category: true + }, + card_author: { + enable: true, + description: null, + button: { + enable: true, + icon: 'fab fa-github', + text: 'Follow Me', + link: 'https://github.com/xxxxxx' + } + }, + card_announcement: { + enable: true, + content: 'This is my Blog' + }, + card_recent_post: { + enable: true, + limit: 5, + sort: 'date', + sort_order: null + }, + card_newest_comments: { + enable: false, + sort_order: null, + limit: 6, + storage: 10, + avatar: true + }, + card_categories: { + enable: true, + limit: 8, + expand: 'none', + sort_order: null + }, + card_tags: { + enable: true, + limit: 40, + color: false, + orderby: 'random', + order: 1, + sort_order: null + }, + card_archives: { + enable: true, + type: 'monthly', + format: 'MMMM YYYY', + order: -1, + limit: 8, + sort_order: null + }, + card_post_series: { + enable: true, + series_title: false, + orderBy: 'date', + order: -1 + }, + card_webinfo: { + enable: true, + post_count: true, + last_push_date: true, + sort_order: null, + runtime_date: null + } + }, + rightside_bottom: null, + translate: { + enable: false, + default: '繁', + defaultEncoding: 2, + translateDelay: 0, + msgToTraditionalChinese: '繁', + msgToSimplifiedChinese: '簡' + }, + readmode: true, + darkmode: { + enable: true, + button: true, + autoChangeMode: false, + start: null, + end: null + }, + rightside_scroll_percent: false, + rightside_item_order: { + enable: false, + hide: null, + show: null + }, + anchor: { + auto_update: false, + click_to_scroll: false + }, + photofigcaption: false, + copy: { + enable: true, + copyright: { + enable: false, + limit_count: 150 + } + }, + wordcount: { + enable: false, + post_wordcount: true, + 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: { + preload: false, + top_n_per_article: 1, + unescape: false, + CDN: null + }, + docsearch: { + appId: null, + apiKey: null, + indexName: null, + option: null + } + }, + share: { + use: 'sharejs', + sharejs: { + sites: 'facebook,twitter,wechat,weibo,qq' + }, + addtoany: { + item: 'facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link' + } + }, + comments: { + use: null, + text: true, + lazyload: false, + count: false, + card_post_count: false + }, + disqus: { + shortname: null, + apikey: null + }, + disqusjs: { + shortname: null, + apikey: null, + option: null + }, + livere: { + uid: null + }, + gitalk: { + client_id: null, + client_secret: null, + repo: null, + owner: null, + admin: null, + option: null + }, + valine: { + appId: null, + appKey: null, + avatar: 'monsterid', + serverURLs: null, + bg: null, + visitor: false, + option: null + }, + waline: { + serverURL: null, + bg: null, + pageview: false, + option: null + }, + utterances: { + repo: null, + issue_term: 'pathname', + light_theme: 'github-light', + dark_theme: 'photon-dark', + js: null, + option: null + }, + facebook_comments: { + app_id: null, + user_id: null, + pageSize: 10, + order_by: 'social', + lang: 'en_US' + }, + twikoo: { + envId: null, + region: null, + visitor: false, + option: null + }, + giscus: { + repo: null, + repo_id: null, + category_id: null, + light_theme: 'light', + dark_theme: 'dark', + js: null, + option: null + }, + remark42: { + host: null, + siteId: null, + option: null + }, + artalk: { + server: null, + site: null, + visitor: false, + option: null + }, + chat: { + use: null, + rightside_button: false, + button_hide_show: false + }, + chatra: { + id: null + }, + tidio: { + public_key: null + }, + crisp: { + website_id: null + }, + baidu_analytics: null, + google_analytics: null, + cloudflare_analytics: null, + microsoft_clarity: null, + umami_analytics: { + enable: false, + serverURL: null, + website_id: null, + option: null, + UV_PV: { + site_uv: false, + site_pv: false, + page_pv: false, + token: null + } + }, + google_adsense: { + enable: false, + auto_ads: true, + js: 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js', + client: null, + enable_page_level_ads: true + }, + ad: { + index: null, + aside: null, + post: null + }, + site_verification: null, + category_ui: null, + tag_ui: null, + rounded_corners_ui: true, + text_align_justify: false, + mask: { + header: true, + footer: true + }, + preloader: { + enable: false, + source: 1, + pace_css_url: null + }, + 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: { + enable: false, + colorful: true, + shake: true, + mobile: false + }, + canvas_ribbon: { + enable: false, + size: 150, + alpha: 0.6, + zIndex: -1, + click_to_change: false, + mobile: false + }, + canvas_fluttering_ribbon: { + enable: false, + mobile: false + }, + canvas_nest: { + enable: false, + color: '0,0,255', + opacity: 0.7, + zIndex: -1, + count: 99, + mobile: false + }, + fireworks: { + enable: false, + zIndex: 9999, + mobile: false + }, + click_heart: { + enable: false, + mobile: false + }, + clickShowText: { + enable: false, + text: null, + fontSize: '15px', + random: false, + mobile: false + }, + lightbox: null, + series: { + enable: false, + orderBy: 'title', + order: 1, + number: true + }, + abcjs: { + enable: false, + per_page: true + }, + mermaid: { + enable: false, + code_write: false, + theme: { + light: 'default', + dark: 'dark' + } + }, + chartjs: { + enable: false, + fontColor: { + light: 'rgba(0, 0, 0, 0.8)', + dark: 'rgba(255, 255, 255, 0.8)' + }, + borderColor: { + light: 'rgba(0, 0, 0, 0.1)', + dark: 'rgba(255, 255, 255, 0.2)' + }, + scale_ticks_backdropColor: { + light: 'transparent', + dark: 'transparent' + } + }, + note: { + style: 'flat', + icons: true, + border_radius: 3, + light_bg_offset: 0 + }, + pjax: { + enable: false, + exclude: null + }, + aplayerInject: { + enable: false, + per_page: true + }, + snackbar: { + enable: false, + position: 'bottom-left', + bg_light: '#49b1f5', + bg_dark: '#1f1f1f' + }, + instantpage: false, + lazyload: { + enable: false, + native: false, + field: 'site', + placeholder: null, + 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: { + enable: true, + option: null + }, + structured_data: true, + css_prefix: true, + inject: { + head: null, + bottom: null + }, + CDN: { + internal_provider: 'local', + third_party_provider: 'jsdelivr', + version: false, + custom_format: null, + option: null + } + } + + hexo.theme.config = deepMerge(defaultConfig, hexo.theme.config) +}, 1) diff --git a/scripts/events/stylus.js b/scripts/events/stylus.js index 15ca4ff..486a83e 100644 --- a/scripts/events/stylus.js +++ b/scripts/events/stylus.js @@ -1,24 +1,24 @@ -/** - * Stylus renderer - */ - -'use strict' - -hexo.extend.filter.register('stylus:renderer', style => { - const { syntax_highlighter: syntaxHighlighter, highlight, prismjs } = hexo.config - let { enable: highlightEnable, line_number: highlightLineNumber } = highlight - let { enable: prismjsEnable, line_number: prismjsLineNumber } = prismjs - - // for hexo > 7.0 - if (syntaxHighlighter) { - highlightEnable = syntaxHighlighter === 'highlight.js' - prismjsEnable = syntaxHighlighter === 'prismjs' - } - - style.define('$highlight_enable', highlightEnable) - .define('$highlight_line_number', highlightLineNumber) - .define('$prismjs_enable', prismjsEnable) - .define('$prismjs_line_number', prismjsLineNumber) - .define('$language', hexo.config.language) - // .import(`${this.source_dir.replace(/\\/g, '/')}_data/css/*`) -}) +/** + * Stylus renderer + */ + +'use strict' + +hexo.extend.filter.register('stylus:renderer', style => { + const { syntax_highlighter: syntaxHighlighter, highlight, prismjs } = hexo.config + let { enable: highlightEnable, line_number: highlightLineNumber } = highlight + let { enable: prismjsEnable, line_number: prismjsLineNumber } = prismjs + + // for hexo > 7.0 + if (syntaxHighlighter) { + highlightEnable = syntaxHighlighter === 'highlight.js' + prismjsEnable = syntaxHighlighter === 'prismjs' + } + + style.define('$highlight_enable', highlightEnable) + .define('$highlight_line_number', highlightLineNumber) + .define('$prismjs_enable', prismjsEnable) + .define('$prismjs_line_number', prismjsLineNumber) + .define('$language', hexo.config.language) + // .import(`${this.source_dir.replace(/\\/g, '/')}_data/css/*`) +}) diff --git a/scripts/events/welcome.js b/scripts/events/welcome.js index f4c018a..188763c 100644 --- a/scripts/events/welcome.js +++ b/scripts/events/welcome.js @@ -1,13 +1,13 @@ -hexo.on('ready', () => { - const { version } = require('../../package.json') - hexo.log.info(` - =================================================================== - ##### # # ##### ##### ###### ##### ###### # # # - # # # # # # # # # # # # # - ##### # # # # ##### # # ##### # # - # # # # # # # ##### # # # - # # # # # # # # # # # # - ##### #### # # ###### # # # ###### # - ${version} - ===================================================================`) -}) +hexo.on('ready', () => { + const { version } = require('../../package.json') + hexo.log.info(` + =================================================================== + ##### # # ##### ##### ###### ##### ###### # # # + # # # # # # # # # # # # # + ##### # # # # ##### # # ##### # # + # # # # # # # ##### # # # + # # # # # # # # # # # # + ##### #### # # ###### # # # ###### # + ${version} + ===================================================================`) +}) diff --git a/scripts/filters/post_lazyload.js b/scripts/filters/post_lazyload.js index 7ad6339..98aa681 100644 --- a/scripts/filters/post_lazyload.js +++ b/scripts/filters/post_lazyload.js @@ -1,31 +1,31 @@ -/** - * Butterfly - * lazyload - * replace src to data-lazy-src - */ - -'use strict' - -const urlFor = require('hexo-util').url_for.bind(hexo) - -const lazyload = htmlContent => { - if (hexo.theme.config.lazyload.native) { - return htmlContent.replace(/()/ig, '$1 loading=\'lazy\'$2') - } - - const bg = hexo.theme.config.lazyload.placeholder ? urlFor(hexo.theme.config.lazyload.placeholder) : 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' - return htmlContent.replace(/( { - const { enable, field } = hexo.theme.config.lazyload - if (!enable || field !== 'site') return - return lazyload(data) -}) - -hexo.extend.filter.register('after_post_render', data => { - const { enable, field } = hexo.theme.config.lazyload - if (!enable || field !== 'post') return - data.content = lazyload(data.content) - return data -}) +/** + * Butterfly + * lazyload + * replace src to data-lazy-src + */ + +'use strict' + +const urlFor = require('hexo-util').url_for.bind(hexo) + +const lazyload = htmlContent => { + if (hexo.theme.config.lazyload.native) { + return htmlContent.replace(/()/ig, '$1 loading=\'lazy\'$2') + } + + const bg = hexo.theme.config.lazyload.placeholder ? urlFor(hexo.theme.config.lazyload.placeholder) : 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' + return htmlContent.replace(/( { + const { enable, field } = hexo.theme.config.lazyload + if (!enable || field !== 'site') return + return lazyload(data) +}) + +hexo.extend.filter.register('after_post_render', data => { + const { enable, field } = hexo.theme.config.lazyload + if (!enable || field !== 'post') return + data.content = lazyload(data.content) + return data +}) diff --git a/scripts/filters/random_cover.js b/scripts/filters/random_cover.js index e7cc24d..7bccbee 100644 --- a/scripts/filters/random_cover.js +++ b/scripts/filters/random_cover.js @@ -1,82 +1,82 @@ -/** - * Random cover for posts - */ - -'use strict' - -hexo.extend.generator.register('post', locals => { - const previousIndexes = [] - - const getRandomCover = defaultCover => { - if (!defaultCover) return false - if (!Array.isArray(defaultCover)) return defaultCover - - const coverCount = defaultCover.length - - if (coverCount === 1) { - return defaultCover[0] - } - - const maxPreviousIndexes = coverCount === 2 ? 1 : (coverCount === 3 ? 2 : 3) - - let index - do { - index = Math.floor(Math.random() * coverCount) - } while (previousIndexes.includes(index) && previousIndexes.length < coverCount) - - previousIndexes.push(index) - if (previousIndexes.length > maxPreviousIndexes) { - previousIndexes.shift() - } - - return defaultCover[index] - } - - const handleImg = data => { - const imgTestReg = /\.(png|jpe?g|gif|svg|webp|avif)(\?.*)?$/i - let { cover: coverVal, top_img: topImg } = data - - // Add path to top_img and cover if post_asset_folder is enabled - if (hexo.config.post_asset_folder) { - if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) { - data.top_img = `${data.path}${topImg}` - } - if (coverVal && coverVal.indexOf('/') === -1 && imgTestReg.test(coverVal)) { - data.cover = `${data.path}${coverVal}` - } - } - - if (coverVal === false) return data - - // If cover is not set, use random cover - if (!coverVal) { - const { cover: { default_cover: defaultCover } } = hexo.theme.config - const randomCover = getRandomCover(defaultCover) - data.cover = randomCover - coverVal = randomCover // update coverVal - } - - if (coverVal && (coverVal.indexOf('//') !== -1 || imgTestReg.test(coverVal))) { - data.cover_type = 'img' - } - - return data - } - - // https://github.com/hexojs/hexo/blob/master/lib%2Fplugins%2Fgenerator%2Fpost.ts - const posts = locals.posts.sort('date').toArray() - const { length } = posts - - return posts.map((post, i) => { - if (i) post.prev = posts[i - 1] - if (i < length - 1) post.next = posts[i + 1] - - post.__post = true - - return { - data: handleImg(post), - layout: 'post', - path: post.path - } - }) -}) +/** + * Random cover for posts + */ + +'use strict' + +hexo.extend.generator.register('post', locals => { + const previousIndexes = [] + + const getRandomCover = defaultCover => { + if (!defaultCover) return false + if (!Array.isArray(defaultCover)) return defaultCover + + const coverCount = defaultCover.length + + if (coverCount === 1) { + return defaultCover[0] + } + + const maxPreviousIndexes = coverCount === 2 ? 1 : (coverCount === 3 ? 2 : 3) + + let index + do { + index = Math.floor(Math.random() * coverCount) + } while (previousIndexes.includes(index) && previousIndexes.length < coverCount) + + previousIndexes.push(index) + if (previousIndexes.length > maxPreviousIndexes) { + previousIndexes.shift() + } + + return defaultCover[index] + } + + const handleImg = data => { + const imgTestReg = /\.(png|jpe?g|gif|svg|webp|avif)(\?.*)?$/i + let { cover: coverVal, top_img: topImg } = data + + // Add path to top_img and cover if post_asset_folder is enabled + if (hexo.config.post_asset_folder) { + if (topImg && topImg.indexOf('/') === -1 && imgTestReg.test(topImg)) { + data.top_img = `${data.path}${topImg}` + } + if (coverVal && coverVal.indexOf('/') === -1 && imgTestReg.test(coverVal)) { + data.cover = `${data.path}${coverVal}` + } + } + + if (coverVal === false) return data + + // If cover is not set, use random cover + if (!coverVal) { + const { cover: { default_cover: defaultCover } } = hexo.theme.config + const randomCover = getRandomCover(defaultCover) + data.cover = randomCover + coverVal = randomCover // update coverVal + } + + if (coverVal && (coverVal.indexOf('//') !== -1 || imgTestReg.test(coverVal))) { + data.cover_type = 'img' + } + + return data + } + + // https://github.com/hexojs/hexo/blob/master/lib%2Fplugins%2Fgenerator%2Fpost.ts + const posts = locals.posts.sort('date').toArray() + const { length } = posts + + return posts.map((post, i) => { + if (i) post.prev = posts[i - 1] + if (i < length - 1) post.next = posts[i + 1] + + post.__post = true + + return { + data: handleImg(post), + layout: 'post', + path: post.path + } + }) +}) diff --git a/scripts/helpers/aside_archives.js b/scripts/helpers/aside_archives.js index df24317..dd07b57 100644 --- a/scripts/helpers/aside_archives.js +++ b/scripts/helpers/aside_archives.js @@ -1,118 +1,118 @@ -'use strict' - -hexo.extend.helper.register('aside_archives', function (options = {}) { - const { config, page, site, url_for, _p } = this - const { - archive_dir: archiveDir, - timezone, - language - } = config - - // Destructure and set default options with object destructuring - const { - type = 'monthly', - format = type === 'monthly' ? 'MMMM YYYY' : 'YYYY', - show_count: showCount = true, - order = -1, - limit, - transform - } = options - - // Optimize locale handling - const lang = toMomentLocale(page.lang || page.language || language) - - // Memoize comparison function to improve performance - const compareFunc = type === 'monthly' - ? (yearA, monthA, yearB, monthB) => yearA === yearB && monthA === monthB - : (yearA, yearB) => yearA === yearB - - // Early return if no posts - if (!site.posts.length) return '' - - // Use reduce for more efficient data processing - const data = site.posts - .sort('date', order) - .reduce((acc, post) => { - let date = post.date.clone() - if (timezone) date = date.tz(timezone) - - const year = date.year() - const month = date.month() + 1 - - if (lang) date = date.locale(lang) - - // Find or create archive entry - const lastEntry = acc[acc.length - 1] - if (!lastEntry || !compareFunc( - lastEntry.year, - lastEntry.month, - year, - month - )) { - acc.push({ - name: date.format(format), - year, - month, - count: 1 - }) - } else { - lastEntry.count++ - } - - return acc - }, []) - - // Create link generator function - const createArchiveLink = item => { - let url = `${archiveDir}/${item.year}/` - if (type === 'monthly') { - url += item.month < 10 ? `0${item.month}/` : `${item.month}/` - } - return url_for(url) - } - - // Limit results efficiently - const limitedData = limit > 0 - ? data.slice(0, Math.min(data.length, limit)) - : data - - // Use template literal for better readability - const archiveHeader = ` -
- - ${_p('aside.card_archives')} - ${data.length > limitedData.length - ? ` - - ` - : ''} -
- ` - - // Use map for generating list items, join for performance - const archiveList = ` - - ` - - return archiveHeader + archiveList -}) - -// Improved locale conversion function -const toMomentLocale = lang => { - if (!lang || ['en', 'default'].includes(lang)) return 'en' - return lang.toLowerCase().replace('_', '-') -} +'use strict' + +hexo.extend.helper.register('aside_archives', function (options = {}) { + const { config, page, site, url_for, _p } = this + const { + archive_dir: archiveDir, + timezone, + language + } = config + + // Destructure and set default options with object destructuring + const { + type = 'monthly', + format = type === 'monthly' ? 'MMMM YYYY' : 'YYYY', + show_count: showCount = true, + order = -1, + limit, + transform + } = options + + // Optimize locale handling + const lang = toMomentLocale(page.lang || page.language || language) + + // Memoize comparison function to improve performance + const compareFunc = type === 'monthly' + ? (yearA, monthA, yearB, monthB) => yearA === yearB && monthA === monthB + : (yearA, yearB) => yearA === yearB + + // Early return if no posts + if (!site.posts.length) return '' + + // Use reduce for more efficient data processing + const data = site.posts + .sort('date', order) + .reduce((acc, post) => { + let date = post.date.clone() + if (timezone) date = date.tz(timezone) + + const year = date.year() + const month = date.month() + 1 + + if (lang) date = date.locale(lang) + + // Find or create archive entry + const lastEntry = acc[acc.length - 1] + if (!lastEntry || !compareFunc( + lastEntry.year, + lastEntry.month, + year, + month + )) { + acc.push({ + name: date.format(format), + year, + month, + count: 1 + }) + } else { + lastEntry.count++ + } + + return acc + }, []) + + // Create link generator function + const createArchiveLink = item => { + let url = `${archiveDir}/${item.year}/` + if (type === 'monthly') { + url += item.month < 10 ? `0${item.month}/` : `${item.month}/` + } + return url_for(url) + } + + // Limit results efficiently + const limitedData = limit > 0 + ? data.slice(0, Math.min(data.length, limit)) + : data + + // Use template literal for better readability + const archiveHeader = ` +
+ + ${_p('aside.card_archives')} + ${data.length > limitedData.length + ? ` + + ` + : ''} +
+ ` + + // Use map for generating list items, join for performance + const archiveList = ` + + ` + + return archiveHeader + archiveList +}) + +// Improved locale conversion function +const toMomentLocale = lang => { + if (!lang || ['en', 'default'].includes(lang)) return 'en' + return lang.toLowerCase().replace('_', '-') +} diff --git a/scripts/helpers/aside_categories.js b/scripts/helpers/aside_categories.js index 4fb3135..faeba94 100644 --- a/scripts/helpers/aside_categories.js +++ b/scripts/helpers/aside_categories.js @@ -1,81 +1,81 @@ -'use strict' - -hexo.extend.helper.register('aside_categories', function (categories, options = {}) { - if (!categories || !Object.prototype.hasOwnProperty.call(categories, 'length')) { - options = categories || {} - categories = this.site.categories - } - - if (!categories || !categories.length) return '' - - const { config } = this - const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count') ? options.show_count : true - const depth = options.depth ? parseInt(options.depth, 10) : 0 - const orderby = options.orderby || 'name' - const order = options.order || 1 - const categoryDir = this.url_for(config.category_dir) - const limit = options.limit === 0 ? categories.length : (options.limit || categories.length) - const isExpand = options.expand !== 'none' - const expandClass = isExpand && options.expand === true ? 'expand' : '' - const buttonLabel = this._p('aside.more_button') - - const prepareQuery = parent => { - const query = parent ? { parent } : { parent: { $exists: false } } - return categories.find(query).sort(orderby, order).filter(cat => cat.length) - } - - const hierarchicalList = (remaining, level = 0, parent) => { - let result = '' - if (remaining > 0) { - prepareQuery(parent).forEach(cat => { - if (remaining > 0) { - remaining -= 1 - let child = '' - if (!depth || level + 1 < depth) { - const childList = hierarchicalList(remaining, level + 1, cat._id) - child = childList.result - remaining = childList.remaining - } - - const parentClass = isExpand && !parent && child ? 'parent' : '' - result += `
  • ` - result += `` - result += `${cat.name}` - - if (showCount) { - result += `${cat.length}` - } - - if (isExpand && !parent && child) { - result += `` - } - - result += '' - - if (child) { - result += `
      ${child}
    ` - } - - result += '
  • ' - } - }) - } - return { result, remaining } - } - - const list = hierarchicalList(limit) - - const moreButton = categories.length > limit - ? ` - ` - : '' - - return `
    - - ${this._p('aside.card_categories')} - ${moreButton} -
    -
      - ${list.result} -
    ` -}) +'use strict' + +hexo.extend.helper.register('aside_categories', function (categories, options = {}) { + if (!categories || !Object.prototype.hasOwnProperty.call(categories, 'length')) { + options = categories || {} + categories = this.site.categories + } + + if (!categories || !categories.length) return '' + + const { config } = this + const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count') ? options.show_count : true + const depth = options.depth ? parseInt(options.depth, 10) : 0 + const orderby = options.orderby || 'name' + const order = options.order || 1 + const categoryDir = this.url_for(config.category_dir) + const limit = options.limit === 0 ? categories.length : (options.limit || categories.length) + const isExpand = options.expand !== 'none' + const expandClass = isExpand && options.expand === true ? 'expand' : '' + const buttonLabel = this._p('aside.more_button') + + const prepareQuery = parent => { + const query = parent ? { parent } : { parent: { $exists: false } } + return categories.find(query).sort(orderby, order).filter(cat => cat.length) + } + + const hierarchicalList = (remaining, level = 0, parent) => { + let result = '' + if (remaining > 0) { + prepareQuery(parent).forEach(cat => { + if (remaining > 0) { + remaining -= 1 + let child = '' + if (!depth || level + 1 < depth) { + const childList = hierarchicalList(remaining, level + 1, cat._id) + child = childList.result + remaining = childList.remaining + } + + const parentClass = isExpand && !parent && child ? 'parent' : '' + result += `
  • ` + result += `` + result += `${cat.name}` + + if (showCount) { + result += `${cat.length}` + } + + if (isExpand && !parent && child) { + result += `` + } + + result += '' + + if (child) { + result += `
      ${child}
    ` + } + + result += '
  • ' + } + }) + } + return { result, remaining } + } + + const list = hierarchicalList(limit) + + const moreButton = categories.length > limit + ? ` + ` + : '' + + return `
    + + ${this._p('aside.card_categories')} + ${moreButton} +
    +
      + ${list.result} +
    ` +}) diff --git a/scripts/helpers/getArchiveLength.js b/scripts/helpers/getArchiveLength.js index 1ff35c8..bdeb87c 100644 --- a/scripts/helpers/getArchiveLength.js +++ b/scripts/helpers/getArchiveLength.js @@ -1,45 +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 -}) +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 +}) diff --git a/scripts/helpers/inject_head_js.js b/scripts/helpers/inject_head_js.js index 3cf31cb..5598674 100644 --- a/scripts/helpers/inject_head_js.js +++ b/scripts/helpers/inject_head_js.js @@ -1,155 +1,155 @@ -'use strict' - -hexo.extend.helper.register('inject_head_js', function () { - const { darkmode, aside, pjax } = this.theme - const start = darkmode.start || 6 - const end = darkmode.end || 18 - const { theme_color } = hexo.theme.config - const themeColorLight = theme_color && theme_color.enable ? theme_color.meta_theme_color_light : '#ffffff' - const themeColorDark = theme_color && theme_color.enable ? theme_color.meta_theme_color_dark : '#0d0d0d' - - const createCustomJs = () => ` - const saveToLocal = { - set: (key, value, ttl) => { - if (!ttl) return - const expiry = Date.now() + ttl * 86400000 - localStorage.setItem(key, JSON.stringify({ value, expiry })) - }, - get: key => { - const itemStr = localStorage.getItem(key) - if (!itemStr) return undefined - const { value, expiry } = JSON.parse(itemStr) - if (Date.now() > expiry) { - localStorage.removeItem(key) - return undefined - } - return value - } - } - - window.btf = { - saveToLocal, - getScript: (url, attr = {}) => new Promise((resolve, reject) => { - const script = document.createElement('script') - script.src = url - script.async = true - Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val)) - script.onload = script.onreadystatechange = () => { - if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve() - } - script.onerror = reject - document.head.appendChild(script) - }), - getCSS: (url, id) => new Promise((resolve, reject) => { - const link = document.createElement('link') - link.rel = 'stylesheet' - link.href = url - if (id) link.id = id - link.onload = link.onreadystatechange = () => { - if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve() - } - link.onerror = reject - document.head.appendChild(link) - }), - addGlobalFn: (key, fn, name = false, parent = window) => { - if (!${pjax.enable} && key.startsWith('pjax')) return - const globalFn = parent.globalFn || {} - globalFn[key] = globalFn[key] || {} - globalFn[key][name || Object.keys(globalFn[key]).length] = fn - parent.globalFn = globalFn - } - } - ` - - const createDarkmodeJs = () => { - if (!darkmode.enable) return '' - - let darkmodeJs = ` - const activateDarkMode = () => { - document.documentElement.setAttribute('data-theme', 'dark') - if (document.querySelector('meta[name="theme-color"]') !== null) { - document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorDark}') - } - } - const activateLightMode = () => { - document.documentElement.setAttribute('data-theme', 'light') - if (document.querySelector('meta[name="theme-color"]') !== null) { - document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorLight}') - } - } - - btf.activateDarkMode = activateDarkMode - btf.activateLightMode = activateLightMode - - const theme = saveToLocal.get('theme') - ` - - switch (darkmode.autoChangeMode) { - case 1: - darkmodeJs += ` - const mediaQueryDark = window.matchMedia('(prefers-color-scheme: dark)') - const mediaQueryLight = window.matchMedia('(prefers-color-scheme: light)') - - if (theme === undefined) { - if (mediaQueryLight.matches) activateLightMode() - else if (mediaQueryDark.matches) activateDarkMode() - else { - const hour = new Date().getHours() - const isNight = hour <= ${start} || hour >= ${end} - isNight ? activateDarkMode() : activateLightMode() - } - mediaQueryDark.addEventListener('change', () => { - if (saveToLocal.get('theme') === undefined) { - e.matches ? activateDarkMode() : activateLightMode() - } - }) - } else { - theme === 'light' ? activateLightMode() : activateDarkMode() - } - ` - break - case 2: - darkmodeJs += ` - const hour = new Date().getHours() - const isNight = hour <= ${start} || hour >= ${end} - if (theme === undefined) isNight ? activateDarkMode() : activateLightMode() - else theme === 'light' ? activateLightMode() : activateDarkMode() - ` - break - default: - darkmodeJs += ` - theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null - ` - } - - return darkmodeJs - } - - const createAsideStatusJs = () => { - if (!aside.enable || !aside.button) return '' - return ` - const asideStatus = saveToLocal.get('aside-status') - if (asideStatus !== undefined) { - document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide') - } - ` - } - - const createDetectAppleJs = () => ` - const detectApple = () => { - if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) { - document.documentElement.classList.add('apple') - } - } - detectApple() - ` - - return `` -}) +'use strict' + +hexo.extend.helper.register('inject_head_js', function () { + const { darkmode, aside, pjax } = this.theme + const start = darkmode.start || 6 + const end = darkmode.end || 18 + const { theme_color } = hexo.theme.config + const themeColorLight = theme_color && theme_color.enable ? theme_color.meta_theme_color_light : '#ffffff' + const themeColorDark = theme_color && theme_color.enable ? theme_color.meta_theme_color_dark : '#0d0d0d' + + const createCustomJs = () => ` + const saveToLocal = { + set: (key, value, ttl) => { + if (!ttl) return + const expiry = Date.now() + ttl * 86400000 + localStorage.setItem(key, JSON.stringify({ value, expiry })) + }, + get: key => { + const itemStr = localStorage.getItem(key) + if (!itemStr) return undefined + const { value, expiry } = JSON.parse(itemStr) + if (Date.now() > expiry) { + localStorage.removeItem(key) + return undefined + } + return value + } + } + + window.btf = { + saveToLocal, + getScript: (url, attr = {}) => new Promise((resolve, reject) => { + const script = document.createElement('script') + script.src = url + script.async = true + Object.entries(attr).forEach(([key, val]) => script.setAttribute(key, val)) + script.onload = script.onreadystatechange = () => { + if (!script.readyState || /loaded|complete/.test(script.readyState)) resolve() + } + script.onerror = reject + document.head.appendChild(script) + }), + getCSS: (url, id) => new Promise((resolve, reject) => { + const link = document.createElement('link') + link.rel = 'stylesheet' + link.href = url + if (id) link.id = id + link.onload = link.onreadystatechange = () => { + if (!link.readyState || /loaded|complete/.test(link.readyState)) resolve() + } + link.onerror = reject + document.head.appendChild(link) + }), + addGlobalFn: (key, fn, name = false, parent = window) => { + if (!${pjax.enable} && key.startsWith('pjax')) return + const globalFn = parent.globalFn || {} + globalFn[key] = globalFn[key] || {} + globalFn[key][name || Object.keys(globalFn[key]).length] = fn + parent.globalFn = globalFn + } + } + ` + + const createDarkmodeJs = () => { + if (!darkmode.enable) return '' + + let darkmodeJs = ` + const activateDarkMode = () => { + document.documentElement.setAttribute('data-theme', 'dark') + if (document.querySelector('meta[name="theme-color"]') !== null) { + document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorDark}') + } + } + const activateLightMode = () => { + document.documentElement.setAttribute('data-theme', 'light') + if (document.querySelector('meta[name="theme-color"]') !== null) { + document.querySelector('meta[name="theme-color"]').setAttribute('content', '${themeColorLight}') + } + } + + btf.activateDarkMode = activateDarkMode + btf.activateLightMode = activateLightMode + + const theme = saveToLocal.get('theme') + ` + + switch (darkmode.autoChangeMode) { + case 1: + darkmodeJs += ` + const mediaQueryDark = window.matchMedia('(prefers-color-scheme: dark)') + const mediaQueryLight = window.matchMedia('(prefers-color-scheme: light)') + + if (theme === undefined) { + if (mediaQueryLight.matches) activateLightMode() + else if (mediaQueryDark.matches) activateDarkMode() + else { + const hour = new Date().getHours() + const isNight = hour <= ${start} || hour >= ${end} + isNight ? activateDarkMode() : activateLightMode() + } + mediaQueryDark.addEventListener('change', () => { + if (saveToLocal.get('theme') === undefined) { + e.matches ? activateDarkMode() : activateLightMode() + } + }) + } else { + theme === 'light' ? activateLightMode() : activateDarkMode() + } + ` + break + case 2: + darkmodeJs += ` + const hour = new Date().getHours() + const isNight = hour <= ${start} || hour >= ${end} + if (theme === undefined) isNight ? activateDarkMode() : activateLightMode() + else theme === 'light' ? activateLightMode() : activateDarkMode() + ` + break + default: + darkmodeJs += ` + theme === 'dark' ? activateDarkMode() : theme === 'light' ? activateLightMode() : null + ` + } + + return darkmodeJs + } + + const createAsideStatusJs = () => { + if (!aside.enable || !aside.button) return '' + return ` + const asideStatus = saveToLocal.get('aside-status') + if (asideStatus !== undefined) { + document.documentElement.classList.toggle('hide-aside', asideStatus === 'hide') + } + ` + } + + const createDetectAppleJs = () => ` + const detectApple = () => { + if (/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)) { + document.documentElement.classList.add('apple') + } + } + detectApple() + ` + + return `` +}) diff --git a/scripts/helpers/page.js b/scripts/helpers/page.js index 3259640..9084919 100644 --- a/scripts/helpers/page.js +++ b/scripts/helpers/page.js @@ -1,147 +1,152 @@ -'use strict' - -const { truncateContent, postDesc } = require('../common/postDesc') -const { prettyUrls } = require('hexo-util') -const crypto = require('crypto') -const moment = require('moment-timezone') - -hexo.extend.helper.register('truncate', truncateContent) - -hexo.extend.helper.register('postDesc', data => { - return postDesc(data, hexo) -}) - -hexo.extend.helper.register('cloudTags', function (options = {}) { - const env = this - let { source, minfontsize, maxfontsize, limit, unit = 'px', orderby, order } = options - - if (limit > 0) { - source = source.limit(limit) - } - - const sizes = [...new Set(source.map(tag => tag.length).sort((a, b) => a - b))] - - 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) => - `font-size: ${parseFloat(size.toFixed(2)) + unit}; color: ${getRandomColor()};` - - const length = sizes.length - 1 - const result = source.sort(orderby, order).map(tag => { - const ratio = length ? sizes.indexOf(tag.length) / length : 0 - const size = minfontsize + ((maxfontsize - minfontsize) * ratio) - const style = generateStyle(size, unit) - return `${tag.name}` - }).join('') - - return result -}) - -hexo.extend.helper.register('urlNoIndex', function (url = null, trailingIndex = false, trailingHtml = false) { - return prettyUrls(url || this.url, { trailing_index: trailingIndex, trailing_html: trailingHtml }) -}) - -hexo.extend.helper.register('md5', function (path) { - return crypto.createHash('md5').update(decodeURI(this.url_for(path))).digest('hex') -}) - -hexo.extend.helper.register('injectHtml', data => { - return data ? data.join('') : '' -}) - -hexo.extend.helper.register('findArchivesTitle', function (page, menu, date) { - if (page.year) { - const dateStr = page.month ? `${page.year}-${page.month}` : `${page.year}` - const dateFormat = page.month ? hexo.theme.config.aside.card_archives.format : 'YYYY' - return date(dateStr, dateFormat) - } - - const defaultTitle = this._p('page.archives') - if (!menu) return defaultTitle - - const loop = (m) => { - for (const key in m) { - if (typeof m[key] === 'object') { - const result = loop(m[key]) - if (result) return result - } - - if (/\/archives\//.test(m[key])) { - return key - } - } - } - - return loop(menu) || defaultTitle -}) - -hexo.extend.helper.register('getBgPath', path => { - if (!path) return '' - - const absoluteUrlPattern = /^(?:[a-z][a-z\d+.-]*:)?\/\//i - const relativeUrlPattern = /^(\.\/|\.\.\/|\/|[^/]+\/).*$/ - const colorPattern = /^(#|rgb|rgba|hsl|hsla)/i - - if (colorPattern.test(path)) { - return `background-color: ${path};` - } else if (absoluteUrlPattern.test(path) || relativeUrlPattern.test(path)) { - return `background-image: url(${path});` - } else { - return `background: ${path};` - } -}) - -hexo.extend.helper.register('shuoshuoFN', (data, page) => { - const { limit } = page - let finalResult = '' - - // Check if limit.value is a valid date - const isValidDate = date => !isNaN(Date.parse(date)) - - // order by date - const orderByDate = data => data.sort((a, b) => Date.parse(b.date) - Date.parse(a.date)) - - // Apply number limit or time limit conditionally - const limitData = data => { - if (limit && limit.type === 'num' && limit.value > 0) { - return data.slice(0, limit.value) - } else if (limit && limit.type === 'date' && isValidDate(limit.value)) { - const limitDate = Date.parse(limit.value) - return data.filter(item => Date.parse(item.date) >= limitDate) - } - - return data - } - - orderByDate(data) - finalResult = limitData(data) - - // This is a hack method, because hexo treats time as UTC time - // so you need to manually convert the time zone - finalResult.forEach(item => { - const utcDate = moment.utc(item.date).format('YYYY-MM-DD HH:mm:ss') - item.date = moment.tz(utcDate, hexo.config.timezone).format('YYYY-MM-DD HH:mm:ss') - }) - - return finalResult -}) - -hexo.extend.helper.register('getPageType', (page, isHome) => { - const { layout, tag, category, type, archive } = page - if (layout) return layout - if (tag) return 'tag' - if (category) return 'category' - if (archive) return 'archive' - if (type) { - if (type === 'tags' || type === 'categories') return type - else return 'page' - } - if (isHome) return 'home' - return 'post' -}) +'use strict' + +const { truncateContent, postDesc } = require('../common/postDesc') +const { prettyUrls } = require('hexo-util') +const crypto = require('crypto') +const moment = require('moment-timezone') + +hexo.extend.helper.register('truncate', truncateContent) + +hexo.extend.helper.register('postDesc', data => { + return postDesc(data, hexo) +}) + +hexo.extend.helper.register('cloudTags', function (options = {}) { + const env = this + let { source, minfontsize, maxfontsize, limit, unit = 'px', orderby, order } = options + + if (limit > 0) { + source = source.limit(limit) + } + + const sizes = [...new Set(source.map(tag => tag.length).sort((a, b) => a - b))] + + 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) => + `font-size: ${parseFloat(size.toFixed(2)) + unit}; color: ${getRandomColor()};` + + const length = sizes.length - 1 + const result = source.sort(orderby, order).map(tag => { + const ratio = length ? sizes.indexOf(tag.length) / length : 0 + const size = minfontsize + ((maxfontsize - minfontsize) * ratio) + const style = generateStyle(size, unit) + return `${tag.name}` + }).join('') + + return result +}) + +hexo.extend.helper.register('urlNoIndex', function (url = null, trailingIndex = false, trailingHtml = false) { + return prettyUrls(url || this.url, { trailing_index: trailingIndex, trailing_html: trailingHtml }) +}) + +hexo.extend.helper.register('md5', function (path) { + return crypto.createHash('md5').update(decodeURI(this.url_for(path))).digest('hex') +}) + +hexo.extend.helper.register('injectHtml', data => { + return data ? data.join('') : '' +}) + +hexo.extend.helper.register('findArchivesTitle', function (page, menu, date) { + if (page.year) { + const dateStr = page.month ? `${page.year}-${page.month}` : `${page.year}` + const dateFormat = page.month ? hexo.theme.config.aside.card_archives.format : 'YYYY' + return date(dateStr, dateFormat) + } + + const defaultTitle = this._p('page.archives') + if (!menu) return defaultTitle + + const loop = (m) => { + for (const key in m) { + if (typeof m[key] === 'object') { + const result = loop(m[key]) + if (result) return result + } + + if (/\/archives\//.test(m[key])) { + return key + } + } + } + + return loop(menu) || defaultTitle +}) + +hexo.extend.helper.register('getBgPath', path => { + if (!path) return '' + + const absoluteUrlPattern = /^(?:[a-z][a-z\d+.-]*:)?\/\//i + const relativeUrlPattern = /^(\.\/|\.\.\/|\/|[^/]+\/).*$/ + const colorPattern = /^(#|rgb|rgba|hsl|hsla)/i + + if (colorPattern.test(path)) { + return `background-color: ${path};` + } else if (absoluteUrlPattern.test(path) || relativeUrlPattern.test(path)) { + return `background-image: url(${path});` + } else { + return `background: ${path};` + } +}) + +hexo.extend.helper.register('shuoshuoFN', (data, page) => { + const { limit } = page + let finalResult = '' + + // Check if limit.value is a valid date + const isValidDate = date => !isNaN(Date.parse(date)) + + // order by date + const orderByDate = data => data.sort((a, b) => Date.parse(b.date) - Date.parse(a.date)) + + // Apply number limit or time limit conditionally + const limitData = data => { + if (limit && limit.type === 'num' && limit.value > 0) { + return data.slice(0, limit.value) + } else if (limit && limit.type === 'date' && isValidDate(limit.value)) { + const limitDate = Date.parse(limit.value) + return data.filter(item => Date.parse(item.date) >= limitDate) + } + + return data + } + + orderByDate(data) + finalResult = limitData(data) + + // This is a hack method, because hexo treats time as UTC time + // so you need to manually convert the time zone + finalResult.forEach(item => { + const utcDate = moment.utc(item.date).format('YYYY-MM-DD HH:mm:ss') + item.date = moment.tz(utcDate, hexo.config.timezone).format('YYYY-MM-DD HH:mm:ss') + }) + + return finalResult +}) + +hexo.extend.helper.register('getPageType', (page, isHome) => { + const { layout, tag, category, type, archive } = page + if (layout) return layout + if (tag) return 'tag' + if (category) return 'category' + if (archive) return 'archive' + if (type) { + if (type === 'tags' || type === 'categories') return type + else return 'page' + } + if (isHome) return 'home' + return 'post' +}) + +hexo.extend.helper.register('getVersion', () => { + const { version } = require('../../package.json') + return { hexo: hexo.version, theme: version } +}) diff --git a/scripts/helpers/related_post.js b/scripts/helpers/related_post.js index 8059dbe..69d9aaa 100644 --- a/scripts/helpers/related_post.js +++ b/scripts/helpers/related_post.js @@ -1,97 +1,97 @@ -/* eslint-disable camelcase */ -/** - * Butterfly - * Related Posts - * According the tag - */ - -'use strict' - -const { postDesc } = require('../common/postDesc') - -hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { - let relatedPosts = [] - const tagsData = currentPost.tags - tagsData.length && tagsData.forEach(function (tag) { - allPosts.forEach(function (post) { - if (currentPost.path !== post.path && isTagRelated(tag.name, post.tags)) { - const getPostDesc = post.postDesc || postDesc(post, hexo) - const relatedPost = { - title: post.title, - path: post.path, - cover: post.cover, - cover_type: post.cover_type, - weight: 1, - updated: post.updated, - created: post.date, - postDesc: getPostDesc - } - const index = findItem(relatedPosts, 'path', post.path) - if (index !== -1) { - relatedPosts[index].weight += 1 - } else { - relatedPosts.push(relatedPost) - } - } - }) - }) - - if (relatedPosts.length === 0) { - return '' - } - let result = '' - const hexoConfig = hexo.config - const config = hexo.theme.config - - const limitNum = config.related_post.limit || 6 - const dateType = config.related_post.date_type || 'created' - const headlineLang = this._p('post.recommend') - - relatedPosts = relatedPosts.sort(compare('weight')) - - if (relatedPosts.length > 0) { - result += '