diff --git a/README.md b/README.md index 54757a8ca..ef8372c10 100644 --- a/README.md +++ b/README.md @@ -14,17 +14,17 @@ ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) -Demo: 👍 [Butterfly](https://butterfly.js.org/) || 🤞 [MYW](https://immyw.com/) +Demo: 👍 [Butterfly](https://butterfly.js.org/) || 🤞 [CrazyWong](https://crazywong.com/) Docs: 📖 [Butterfly Docs](https://butterfly.js.org/posts/21cfbf15/) Based on [hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody) theme. -## Installation +## 💻 Installation ### GIT -> If you are in Mainland China, you can download in [Gitee](https://gitee.com/iamjerryw/hexo-theme-butterfly) +> If you are in Mainland China, you can download in [Gitee](https://gitee.com/immyw/hexo-theme-butterfly.git) Stable branch [recommend]: @@ -48,7 +48,7 @@ In Hexo site root directory npm i hexo-theme-butterfly ``` -## Configuration +## ⚙ Configuration Set theme in the hexo work folder's root config file `_config.yml`: @@ -58,7 +58,7 @@ npm i hexo-theme-butterfly > npm install hexo-renderer-pug hexo-renderer-stylus -## Features +## 🎉 Features - [x] Card UI Design - [X] Support sub-menu @@ -79,7 +79,7 @@ npm i hexo-theme-butterfly - [x] Related articles - [x] Displays outdated notice for a post - [x] Share (AddThis/Sharejs/Addtoany) -- [X] Comment (Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo) +- [X] Comment (Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus) - [x] Multiple Comment System Support - [x] Online Chats (Chatra/Tidio/Daovoice/Gitter/Crisp) - [x] Web analytics @@ -97,7 +97,13 @@ npm i hexo-theme-butterfly - [x] Lazyload images - [x] Instantpage/Pangu/Snackbar notification toast/PWA...... -## Screenshots +## ✨ 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) diff --git a/README_CN.md b/README_CN.md index 672126914..5d7e0bb4a 100644 --- a/README_CN.md +++ b/README_CN.md @@ -14,17 +14,17 @@ ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) -預覽: 👍 [Butterfly](https://butterfly.js.org/) || 🤞 [MYW](https://immyw.com/) +預覽: 👍 [Butterfly](https://butterfly.js.org/) || 🤞 [CrazyWong](https://crazywong.com/) 文檔: 📖 [Butterfly Docs](https://butterfly.js.org/posts/21cfbf15/) 一款基於[hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody)修改的主題 -## 安裝 +## 💻 安裝 ### Git 安裝 -> 本倉庫同時上傳到 [Gitee](https://gitee.com/iamjerryw/hexo-theme-butterfly),如果你訪問 Github 緩慢,可從 Gitee 中下載。 +> 本倉庫同時上傳到 [Gitee](https://gitee.com/immyw/hexo-theme-butterfly.git),如果你訪問 Github 緩慢,可從 Gitee 中下載。 在博客根目錄裡安裝穩定版【推薦】 @@ -48,7 +48,8 @@ git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/bu npm i hexo-theme-butterfly ``` -## 應用主題 +## ⚙ 應用主題 + 修改hexo配置文件`_config.yml`,把主題改為`Butterfly` ``` @@ -57,7 +58,7 @@ theme: butterfly >如果你沒有pug以及stylus的渲染器,請下載安裝: npm install hexo-renderer-pug hexo-renderer-stylus --save -## 特色 +## 🎉 特色 - [x] 卡片化設計 - [X] 支持二級目錄 @@ -78,7 +79,7 @@ theme: butterfly - [x] 顯示相關文章 - [x] 過期文章提醒 - [x] 多種分享系統(AddThis/Sharejs/Addtoany) -- [X] 多種評論系統(Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo) +- [X] 多種評論系統(Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus) - [x] 支持雙評論部署 - [x] 多種在線聊天(Chatra/Tidio/Daovoice/Gitter/Crisp) - [x] 多種分析系統 @@ -96,11 +97,17 @@ theme: butterfly - [x] 圖片懶加載 - [x] Instantpage/Pangu/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) ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN/img/theme-butterfly-readme-homepage-1.png) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN/img/theme-butterfly-readme-homepage-2.png) \ No newline at end of file +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN/img/theme-butterfly-readme-homepage-2.png) diff --git a/_config.yml b/_config.yml index 830d49807..deb3c755e 100644 --- a/_config.yml +++ b/_config.yml @@ -1,11 +1,7 @@ # Main menu navigation (導航目錄) +# see https://butterfly.js.org/posts/4aa8abbe/#導航菜單 # -------------------------------------- -# format: name: link || icon -# sub-menu -# name || icon: -# name: link || icon - menu: # Home: / || fas fa-home # Archives: /archives/ || fas fa-archive @@ -17,9 +13,6 @@ menu: # Link: /link/ || fas fa-link # About: /about/ || fas fa-heart -# Hide the child menu items in mobile sidebar -hide_sidebar_menu_child: false - # Code Blocks (代碼相關) # -------------------------------------- @@ -170,14 +163,20 @@ index_post_content: method: 3 length: 500 # if you set method to 2 or 3, the length need to config +# anchor +# when you scroll in post, the URL will update according to header id. +anchor: false + # Post # -------------------------------------- # toc (目錄) toc: - enable: true + post: true + page: false number: true - style_simple: false + expand: false + style_simple: false # for post post_copyright: enable: true @@ -220,10 +219,6 @@ photofigcaption: false # false: disable pagination post_pagination: 1 -# anchor -# when you scroll in post, the URL will update according to header id. -anchor: false - # Displays outdated notice for a post (文章過期提醒) noticeOutdate: enable: false @@ -259,10 +254,8 @@ addtoany: comments: # Up to two comments system, the first will be shown as default - # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo - use: - # - Valine - # - Disqus + # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus + use: # Valine,Disqus text: true # Display the comment name next to the button # 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 @@ -281,12 +274,8 @@ disqus: # https://github.com/SukkaW/DisqusJS disqusjs: shortname: - siteName: apikey: - api: - nocomment: # display when a blog post or an article has no comment attached - admin: - adminLabel: + option: # livere (來必力) # https://www.livere.com/ @@ -301,11 +290,6 @@ gitalk: repo: owner: admin: - language: en # en, zh-CN, zh-TW, es-ES, fr, ru - perPage: 10 # Pagination size, with maximum 100. - distractionFreeMode: false # Facebook-like distraction free mode. - pagerDirection: last # Comment sorting direction, available values are last and first. - createIssueManually: false # Gitalk will create a corresponding github issue for your every single page automatically option: # valine @@ -313,17 +297,9 @@ gitalk: valine: appId: # leancloud application app id appKey: # leancloud application app key - pageSize: 10 # comment list page size avatar: monsterid # gravatar style https://valine.js.org/#/avatar - lang: en # i18n: zh-CN/zh-TW/en/ja - placeholder: Please leave your footprints # valine comment input placeholder (like: Please leave your footprints) - guest_info: nick,mail,link # valine comment header info (nick/mail/link) - recordIP: false # Record reviewer IP serverURLs: # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in) bg: # valine background - emojiCDN: # emoji CDN - enableQQ: false # enable the Nickname box to automatically get QQ Nickname and QQ Avatar - requiredFields: nick,mail # required fields (nick/mail) visitor: false option: @@ -331,8 +307,6 @@ valine: # https://waline.js.org/ waline: serverURL: # Waline server address url - avatar: monsterid # gravatar style https://zh-tw.gravatar.com/site/implement/images/#default-image - avatarCDN: # Gravatar CDN baseURL bg: # waline background visitor: false option: @@ -364,6 +338,17 @@ twikoo: visitor: false option: +# Giscus +# https://giscus.app/ +giscus: + repo: + repo_id: + category_id: + theme: + light: light + dark: dark + option: + # Chat Services # -------------------------------------- @@ -424,10 +409,6 @@ baidu_analytics: # https://analytics.google.com/analytics/web/ google_analytics: -# Tencent Analytics ID -# https://mta.qq.com -tencent_analytics: - # CNZZ Analytics # https://www.umeng.com/ cnzz_analytics: @@ -486,6 +467,7 @@ site_verification: # toc_color: "#00c4b6" # blockquote_padding_color: "#49b1f5" # blockquote_background_color: "#49b1f5" +# scrollbar_color: "#49b1f5" # The top_img settings of home page # default: top img - full screen, site info - middle (默認top_img全屏,site_info在中間) @@ -580,8 +562,8 @@ display_mode: light beautify: enable: false field: post # site/post - title-prefix-icon: '\f0c1' - title-prefix-icon-color: '#F47466' + title-prefix-icon: # '\f0c1' + title-prefix-icon-color: # '#F47466' # Global font settings # Don't modify the following settings unless you know how they work (非必要不要修改) @@ -610,18 +592,14 @@ subtitle: effect: true # loop (循環打字) loop: true - # source調用第三方服務 + # source 調用第三方服務 # source: false 關閉調用 - # source: 1 調用搏天api的隨機語錄(簡體) - # source: 2 調用一言網的一句話(簡體) - # source: 3 調用一句網(簡體) - # source: 4 調用今日詩詞(簡體) + # source: 1 調用一言網的一句話(簡體) https://hitokoto.cn/ + # source: 2 調用一句網(簡體) http://yijuzhan.com/ + # source: 3 調用今日詩詞(簡體) https://www.jinrishici.com/ # subtitle 會先顯示 source , 再顯示 sub 的內容 source: false - # 如果有英文逗號' , ',請使用轉義字元 , - # 如果有英文雙引號' " ',請使用轉義字元 " - # 開頭不允許轉義字元,如需要,請把整個句子用雙引號包住 - # 如果關閉打字效果,subtitle只會顯示sub的第一行文字 + # 如果關閉打字效果,subtitle 只會顯示 sub 的第一行文字 sub: # Loading Animation (加載動畫) @@ -699,9 +677,6 @@ newest_comments: # Bottom right button (右下角按鈕) # -------------------------------------- -# Change font size -change_font_size: false - # Conversion between Traditional and Simplified Chinese (簡繁轉換) translate: enable: false @@ -730,6 +705,14 @@ darkmode: # autoChangeMode: false autoChangeMode: false +# Don't modify the following settings unless you know how they work (非必要請不要修改 ) +# Choose: readmode,translate,darkmode,hideAside,toc,chat,comment +# Don't repeat 不要重複 +rightside_item_order: + enable: false + hide: # readmode,translate,darkmode,hideAside + show: # toc,chat,comment + # Lightbox (圖片大圖查看模式) # -------------------------------------- # You can only choose one, or neither (只能選擇一個 或者 兩個都不選) @@ -750,7 +733,9 @@ fancybox: true mermaid: enable: false # built-in themes: default/forest/dark/neutral - theme: default + theme: + light: default + dark: dark # Note (Bootstrap Callout) note: @@ -843,86 +828,87 @@ inject: # 非必要請不要修改 CDN: # main - main_css: /css/index.css - jquery: https://cdn.jsdelivr.net/npm/jquery@latest/dist/jquery.min.js - main: /js/main.js - utils: /js/utils.js + main_css: + main: + utils: # pjax - pjax: https://cdn.jsdelivr.net/npm/pjax/pjax.min.js + pjax: # comments - gitalk: https://cdn.jsdelivr.net/npm/gitalk@latest/dist/gitalk.min.js - gitalk_css: https://cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.css - valine: https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js - disqusjs: https://cdn.jsdelivr.net/npm/disqusjs@1/dist/disqus.js - disqusjs_css: https://cdn.jsdelivr.net/npm/disqusjs@1/dist/disqusjs.css - utterances: https://utteranc.es/client.js - twikoo: https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js - waline: https://cdn.jsdelivr.net/npm/@waline/client/dist/Waline.min.js + gitalk: + gitalk_css: + blueimp_md5: + valine: + disqusjs: + disqusjs_css: + utterances: + twikoo: + waline: + giscus: # share - addtoany: https://static.addtoany.com/menu/page.js - sharejs: https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js - sharejs_css: https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css + addtoany: + sharejs: + sharejs_css: # search - local_search: /js/search/local-search.js - algolia_js: /js/search/algolia.js - algolia_search: https://cdn.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.js - algolia_search_css: https://cdn.jsdelivr.net/npm/instantsearch.js@2.10.5/dist/instantsearch.min.css + local_search: + algolia_js: + algolia_search_v4: + instantsearch_v4: # math - mathjax: https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js - katex: https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css - katex_copytex: https://cdn.jsdelivr.net/npm/katex@latest/dist/contrib/copy-tex.min.js - katex_copytex_css: https://cdn.jsdelivr.net/npm/katex@latest/dist/contrib/copy-tex.css - mermaid: https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js + mathjax: + katex: + katex_copytex: + katex_copytex_css: + mermaid: # count - busuanzi: //busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js + busuanzi: # background effect - canvas_ribbon: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-ribbon.min.js - canvas_fluttering_ribbon: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-fluttering-ribbon.min.js - canvas_nest: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js + canvas_ribbon: + canvas_fluttering_ribbon: + canvas_nest: - lazyload: https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js - instantpage: https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js - typed: https://cdn.jsdelivr.net/npm/typed.js/lib/typed.min.js - pangu: https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js + lazyload: + instantpage: + typed: + pangu: # photo - fancybox_css: https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.css - fancybox: https://cdn.jsdelivr.net/npm/@fancyapps/fancybox@latest/dist/jquery.fancybox.min.js - medium_zoom: https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js + fancybox_css_v4: + fancybox_v4: + medium_zoom: # snackbar - snackbar_css: https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css - snackbar: https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js + snackbar_css: + snackbar: # effect - activate_power_mode: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js - fireworks: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/fireworks.min.js - click_heart: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js - ClickShowText: https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-show-text.min.js + activate_power_mode: + fireworks: + click_heart: + ClickShowText: # fontawesome - fontawesome: https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css + fontawesome: # Conversion between Traditional and Simplified Chinese - translate: /js/tw_cn.js + translate: - # justifiedGallery - justifiedGallery_js: https://cdn.jsdelivr.net/npm/justifiedGallery/dist/js/jquery.justifiedGallery.min.js - justifiedGallery_css: https://cdn.jsdelivr.net/npm/justifiedGallery/dist/css/justifiedGallery.min.css + # flickr-justified-gallery + flickr_justified_gallery_js: + flickr_justified_gallery_css: # aplayer - aplayer_css: https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css - aplayer_js: https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js - meting_js: https://cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js + aplayer_css: + aplayer_js: + meting_js: # Prism.js - prismjs_js: https://cdn.jsdelivr.net/npm/prismjs/prism.min.js - prismjs_lineNumber_js: https://cdn.jsdelivr.net/npm/prismjs/plugins/line-numbers/prism-line-numbers.min.js - prismjs_autoloader: https://cdn.jsdelivr.net/npm/prismjs/plugins/autoloader/prism-autoloader.min.js \ No newline at end of file + prismjs_js: + prismjs_lineNumber_js: + prismjs_autoloader: \ No newline at end of file diff --git a/languages/default.yml b/languages/default.yml index 3e0cd285e..8cb00208e 100644 --- a/languages/default.yml +++ b/languages/default.yml @@ -34,16 +34,18 @@ post: recommend: Related Articles edit: Edited on -search: Search -algolia_search: - input_placeholder: Search for Posts - hits_empty: "We didn't find any results for the search: ${query}." - hits_stats: '${hits} results found in ${time} ms' - -local_search: - label: Local search - input_placeholder: Search for Posts - hits_empty: "We didn't find any results for the search: ${query}" +search: + title: Search + load_data: Loading the Database + algolia_search: + input_placeholder: Search for Posts + hits_empty: "We didn't find any results for the search: ${query}." + hits_stats: '${hits} results found in ${time} ms' + + local_search: + label: Local search + input_placeholder: Search for Posts + hits_empty: "We didn't find any results for the search: ${query}" pagination: prev: Previous Post @@ -94,8 +96,6 @@ share: Share rightside: readmode_title: Read Mode - font_plus_title: Increase font size - font_minus_title: Decrease font size translate_title: Toggle Between Traditional Chinese And Simplified Chinese night_mode_title: Toggle Between Light And Dark Mode back_to_top: Back To Top @@ -118,6 +118,4 @@ Snackbar: loading: Loading... -error404: - error_title: Page not found - back_button: Go back home +error404: Page not found diff --git a/languages/en.yml b/languages/en.yml index 40aabfb15..dc31ed7f4 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -34,16 +34,18 @@ post: recommend: Related Articles edit: Edited on -search: Search -algolia_search: - input_placeholder: Search for Posts - hits_empty: "We didn't find any results for the search: ${query}." - hits_stats: '${hits} results found in ${time} ms' - -local_search: - label: Local search - input_placeholder: Search for Posts - hits_empty: "We didn't find any results for the search: ${query}" +search: + title: Search + load_data: Loading the Database + algolia_search: + input_placeholder: Search for Posts + hits_empty: "We didn't find any results for the search: ${query}." + hits_stats: '${hits} results found in ${time} ms' + + local_search: + label: Local search + input_placeholder: Search for Posts + hits_empty: "We didn't find any results for the search: ${query}" pagination: prev: Previous Post @@ -94,8 +96,6 @@ share: Share rightside: readmode_title: Read Mode - font_plus_title: Increase font size - font_minus_title: Decrease font size translate_title: Switch Between Traditional Chinese And Simplified Chinese night_mode_title: Switch Between Light And Dark Mode back_to_top: Back To Top @@ -118,6 +118,4 @@ Snackbar: loading: Loading... -error404: - error_title: Page not found - back_button: Go back home +error404: Page not found diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml index a48bf3e13..f3460b197 100644 --- a/languages/zh-CN.yml +++ b/languages/zh-CN.yml @@ -35,16 +35,18 @@ post: recommend: 相关推荐 edit: 编辑 -search: 搜索 -algolia_search: - input_placeholder: 搜索文章 - hits_empty: '找不到您查询的内容:${query}' - hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' - -local_search: - label: 本地搜索 - input_placeholder: 搜索文章 - hits_empty: '找不到您查询的内容:${query}' +search: + title: 搜索 + load_data: 数据库加载中 + algolia_search: + input_placeholder: 搜索文章 + hits_empty: '找不到您查询的内容:${query}' + hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' + + local_search: + label: 本地搜索 + input_placeholder: 搜索文章 + hits_empty: '找不到您查询的内容:${query}' pagination: prev: 上一篇 @@ -95,8 +97,6 @@ share: 分享 rightside: readmode_title: 阅读模式 - font_plus_title: 放大字体 - font_minus_title: 缩小字体 translate_title: 简繁转换 night_mode_title: 浅色和深色模式转换 back_to_top: 回到顶部 @@ -119,6 +119,4 @@ Snackbar: loading: 加载中... -error404: - error_title: 页面没有找到 - back_button: 回到主页 +error404: 页面没有找到 diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml index 23563317f..1019eb7f2 100644 --- a/languages/zh-TW.yml +++ b/languages/zh-TW.yml @@ -35,16 +35,18 @@ post: recommend: 相關推薦 edit: 編輯 -search: 搜尋 -algolia_search: - input_placeholder: 搜尋文章 - hits_empty: '找不到您查詢的內容:${query}' - hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' - -local_search: - label: 本地搜尋 - input_placeholder: 搜尋文章 - hits_empty: '找不到您查詢的內容:${query}' +search: + title: 搜尋 + load_data: 資料庫載入中 + algolia_search: + input_placeholder: 搜尋文章 + hits_empty: '找不到您查詢的內容:${query}' + hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' + + local_search: + label: 本地搜尋 + input_placeholder: 搜尋文章 + hits_empty: '找不到您查詢的內容:${query}' pagination: prev: 上一篇 @@ -65,7 +67,7 @@ aside: headline: 網站資訊 article_name: 文章數目 runtime: - name: 已運行時間 + name: 已執行時間 unit: 天 last_push_date: name: 最後更新時間 @@ -80,7 +82,7 @@ aside: zero: 沒有評論 image: 圖片 link: 連結 - code: 代碼 + code: 程式碼 card_toc: 目錄 date_suffix: @@ -95,8 +97,6 @@ share: 分享 rightside: readmode_title: 閱讀模式 - font_plus_title: 放大字型 - font_minus_title: 縮小字型 translate_title: 簡繁轉換 night_mode_title: 淺色和深色模式轉換 back_to_top: 回到頂部 @@ -119,6 +119,4 @@ Snackbar: loading: 載入中... -error404: - error_title: 頁面沒有找到 - back_button: 回到主頁 +error404: 頁面沒有找到 diff --git a/layout/category.pug b/layout/category.pug index 5dc21d58c..234a0af65 100644 --- a/layout/category.pug +++ b/layout/category.pug @@ -3,9 +3,9 @@ extends includes/layout.pug block content if theme.category_ui == 'index' include ./includes/mixins/post-ui.pug - #recent-posts.recent-posts.category_ui + #recent-posts.recent-posts.category_ui +postUI - include includes/pagination.pug + include includes/pagination.pug else include ./includes/mixins/article-sort.pug #category diff --git a/layout/includes/404.pug b/layout/includes/404.pug index 5d370c005..4a022c85e 100644 --- a/layout/includes/404.pug +++ b/layout/includes/404.pug @@ -1,17 +1,12 @@ -- var top_img = theme.error_404.background || theme.default_top_img -- var bg_img = `background-image: url('${url_for(top_img)}')` +- var top_img_404 = theme.error_404.background || theme.default_top_img #body-wrap.error404 - div(style='display: none') - include ./header/index.pug + include ./header/index.pug #error-wrap .error-content - .error-img(style=bg_img) + .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 - a.button--animated(href=config.root) - i.fas.fa-rocket - = _p('error404.back_button') - + .error_subtitle= theme.error_404.subtitle || _p('error404') diff --git a/layout/includes/additional-js.pug b/layout/includes/additional-js.pug index d125cd7c5..79fc8b46e 100644 --- a/layout/includes/additional-js.pug +++ b/layout/includes/additional-js.pug @@ -7,9 +7,11 @@ div if theme.medium_zoom script(src=url_for(theme.CDN.medium_zoom)) + else if theme.fancybox + script(src=url_for(theme.CDN.fancybox_v4)) if theme.instantpage - script(src=url_for(theme.CDN.instantpage) type="module") + script(src=url_for(theme.CDN.instantpage), type='module') if theme.lazyload.enable script(src=url_for(theme.CDN.lazyload)) @@ -18,21 +20,23 @@ div script(src=url_for(theme.CDN.snackbar)) if theme.pangu.enable - !=partial('includes/third-party/pangu.pug', {}, {cache: true}) + != partial("includes/third-party/pangu.pug", {}, { cache: true }) //- search if theme.algolia_search.enable + script(src=url_for(theme.CDN.algolia_search_v4)) + script(src=url_for(theme.CDN.instantsearch_v4)) script(src=url_for(theme.CDN.algolia_js)) else if theme.local_search.enable script(src=url_for(theme.CDN.local_search)) if theme.preloader - !=partial('includes/loading/loading-js', {}, {cache: true}) + != partial("includes/loading/loading-js", {}, { cache: true }) .js-pjax if needLoadCountJs - !=partial('includes/third-party/card-post-count/index', {}, {cache: true}) - + != partial("includes/third-party/card-post-count/index", {}, { cache: true }) + if loadSubJs include ./third-party/subtitle.pug @@ -41,20 +45,20 @@ div if commentsJsLoad include ./third-party/comments/js.pug - !=partial('includes/third-party/prismjs', {}, {cache: true}) + != partial("includes/third-party/prismjs", {}, { cache: true }) if theme.aside.enable && theme.newest_comments.enable if theme.pjax.enable - !=partial('includes/third-party/newest-comments/index', {}, {cache: true}) + != partial("includes/third-party/newest-comments/index", {}, { cache: true }) else if (!is_post() && page.aside !== false) - !=partial('includes/third-party/newest-comments/index', {}, {cache: true}) + != partial("includes/third-party/newest-comments/index", {}, { cache: true }) + + != fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)}) - !=fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)}) + != partial("includes/third-party/effect", {}, { cache: true }) - !=partial('includes/third-party/effect', {}, {cache: true}) + != partial("includes/third-party/chat/index", {}, { cache: true }) - !=partial('includes/third-party/chat/index', {}, {cache: true}) - if theme.aplayerInject && theme.aplayerInject.enable if theme.pjax.enable || theme.aplayerInject.per_page include ./third-party/aplayer.pug @@ -62,7 +66,7 @@ div include ./third-party/aplayer.pug if theme.pjax.enable - !=partial('includes/third-party/pjax', {}, {cache: true}) - + != partial("includes/third-party/pjax", {}, { cache: true }) + if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv script(async data-pjax src=url_for(theme.CDN.busuanzi)) diff --git a/layout/includes/head.pug b/layout/includes/head.pug index 5708d7ce5..5263e3527 100644 --- a/layout/includes/head.pug +++ b/layout/includes/head.pug @@ -4,7 +4,7 @@ - else if (is_category()) pageTitle = _p('page.category') + ': ' + page.category - else if (is_month()) pageTitle += ': ' + page.month + '/' + page.year - else if (is_year()) pageTitle += ': ' + page.year -- else if (is_current('/404.html', [strict])) pageTitle = _p('error404.error_title') +- else if (is_current('/404.html', [strict])) pageTitle = _p('error404') - else pageTitle = page.title || config.title || '' - var isSubtitle = config.subtitle ? ' - ' + config.subtitle : '' @@ -20,7 +20,7 @@ meta(charset='UTF-8') meta(http-equiv="X-UA-Compatible" content="IE=edge") -meta(name="viewport" content="width=device-width,initial-scale=1") +meta(name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no") title= tabTitle if pageKeywords meta(name="keywords" content=pageKeywords) @@ -52,9 +52,8 @@ link(rel='stylesheet', href=url_for(theme.CDN.fontawesome) media="print" onload= if (theme.snackbar && theme.snackbar.enable) link(rel='stylesheet', href=url_for(theme.CDN.snackbar_css) media="print" onload="this.media='all'") -if theme.algolia_search.enable - link(rel='stylesheet' href=url_for(theme.CDN.algolia_search_css) media="print" onload="this.media='all'") - script(src=url_for(theme.CDN.algolia_search) defer) +if theme.fancybox + link(rel='stylesheet' href=url_for(theme.CDN.fancybox_css_v4) media="print" onload="this.media='all'") //- google_adsense !=partial('includes/head/google_adsense', {}, {cache: true}) diff --git a/layout/includes/head/analytics.pug b/layout/includes/head/analytics.pug index 4873ebf35..6452528c2 100644 --- a/layout/includes/head/analytics.pug +++ b/layout/includes/head/analytics.pug @@ -16,18 +16,6 @@ if theme.google_analytics gtag('js', new Date()); gtag('config', '!{theme.google_analytics}'); -if theme.tencent_analytics - script. - var _mtac = {}; - (function() { - var mta = document.createElement("script"); - mta.src = "//pingjs.qq.com/h5/stats.js?v2.0.4"; - mta.setAttribute("name", "MTAH5"); - mta.setAttribute("sid", "!{theme.tencent_analytics}"); - var s = document.getElementsByTagName("script")[0]; - s.parentNode.insertBefore(mta, s); - })(); - if theme.cnzz_analytics script(async data-pjax src=`https://s4.cnzz.com/z_stat.php?id=${theme.cnzz_analytics}&web_id=${theme.cnzz_analytics}`) diff --git a/layout/includes/head/config.pug b/layout/includes/head/config.pug index 9dd4f3b00..49fe4fe47 100644 --- a/layout/includes/head/config.pug +++ b/layout/includes/head/config.pug @@ -9,9 +9,9 @@ hits: theme.algolia_search.hits, // search languages languages: { - input_placeholder: _p("algolia_search.input_placeholder"), - hits_empty: _p("algolia_search.hits_empty"), - hits_stats: _p("algolia_search.hits_stats") + input_placeholder: _p("search.algolia_search.input_placeholder"), + hits_empty: _p("search.algolia_search.hits_empty"), + hits_stats: _p("search.algolia_search.hits_stats"), } }) } @@ -22,7 +22,7 @@ path: config.search.path, languages: { // search languages - hits_empty: _p("local_search.hits_empty") + hits_empty: _p("search.local_search.hits_empty"), } }) } @@ -112,17 +112,12 @@ script. lightbox: '!{ theme.medium_zoom ? "mediumZoom" : (theme.fancybox ? "fancybox" : "null" )}', Snackbar: !{Snackbar}, source: { - jQuery: '!{url_for(theme.CDN.jquery)}', justifiedGallery: { - js: '!{url_for(theme.CDN.justifiedGallery_js)}', - css: '!{url_for(theme.CDN.justifiedGallery_css)}' - }, - fancybox: { - js: '!{url_for(theme.CDN.fancybox)}', - css: '!{url_for(theme.CDN.fancybox_css)}' + js: '!{url_for(theme.CDN.flickr_justified_gallery_js)}', + css: '!{url_for(theme.CDN.flickr_justified_gallery_css)}' } }, isPhotoFigcaption: !{theme.photofigcaption}, islazyload: !{theme.lazyload.enable}, - isanchor: !{theme.anchor} + isAnchor: !{theme.anchor} } diff --git a/layout/includes/head/config_site.pug b/layout/includes/head/config_site.pug index 1d78e982c..220c55f31 100644 --- a/layout/includes/head/config_site.pug +++ b/layout/includes/head/config_site.pug @@ -1,13 +1,22 @@ - + const titleVal = pageTitle.replace(/'/ig,"\\'") + let isHighlightShrink if (theme.highlight_shrink == 'none') isHighlightShrink = 'undefined' else if (page.highlight_shrink === true || page.highlight_shrink === false) isHighlightShrink = page.highlight_shrink else isHighlightShrink = theme.highlight_shrink - var pageToc = page.toc === true || page.toc === false ? page.toc : theme.toc.enable - var showToc = is_post() && theme.aside.enable && pageToc && (toc(page.content) !== '' || page.encrypt == true ) - - let titleVal = pageTitle.replace(/'/ig,"\\'") + var showToc = false + if (theme.aside.enable) { + let tocEnable = false + if (is_post()) { + if (theme.toc.post) tocEnable = true + } else if (is_page()) { + if (theme.toc.page) tocEnable = true + } + const pageToc = page.toc === true || page.toc === false ? page.toc : tocEnable + showToc = pageToc && (toc(page.content) !== '' || page.encrypt == true ) + } - script#config-diff. diff --git a/layout/includes/head/preconnect.pug b/layout/includes/head/preconnect.pug index 73231c75e..d010b0533 100644 --- a/layout/includes/head/preconnect.pug +++ b/layout/includes/head/preconnect.pug @@ -6,9 +6,6 @@ if theme.google_analytics if theme.baidu_analytics link(rel="preconnect" href="//hm.baidu.com") -if theme.tencent_analytics - link(rel="preconnect" href="//pingjs.qq.com") - if theme.cnzz_analytics link(rel="preconnect" href="//s4.cnzz.com") diff --git a/layout/includes/header/menu_item.pug b/layout/includes/header/menu_item.pug index 5a63994da..d172db74a 100644 --- a/layout/includes/header/menu_item.pug +++ b/layout/includes/header/menu_item.pug @@ -1,26 +1,27 @@ if theme.menu - //- for mobile sidebar - - let sidebarChildHide = theme.hide_sidebar_menu_child ? 'hide' : '' - .menus_items each value, label in theme.menu if typeof value !== 'object' .menus_item - a.site-page(href=url_for(trim(value.split('||')[0]))) - if value.split('||')[1] - i.fa-fw(class=trim(value.split('||')[1])) + - const valueArray = value.split('||') + a.site-page(href=url_for(trim(valueArray[0]))) + if valueArray[1] + i.fa-fw(class=trim(valueArray[1])) span=' '+label else .menus_item - a.site-page(href='javascript:void(0);') - if label.split('||')[1] - i.fa-fw(class=trim(label.split('||')[1])) - span=' '+ trim(label.split('||')[0]) - i.fas.fa-chevron-down.expand(class=sidebarChildHide) + - const labelArray = label.split('||') + - const hideClass = labelArray[2] && trim(labelArray[2]) === 'hide' ? 'hide' : '' + a.site-page.group(class=`${hideClass}` href='javascript:void(0);') + if labelArray[1] + i.fa-fw(class=trim(labelArray[1])) + span=' '+ trim(labelArray[0]) + i.fas.fa-chevron-down ul.menus_item_child each val,lab in value + - const valArray = val.split('||') li - a.site-page.child(href=url_for(trim(val.split('||')[0]))) - if val.split('||')[1] - i.fa-fw(class=trim(val.split('||')[1])) + a.site-page.child(href=url_for(trim(valArray[0]))) + if valArray[1] + i.fa-fw(class=trim(valArray[1])) span=' '+ lab \ No newline at end of file diff --git a/layout/includes/header/nav.pug b/layout/includes/header/nav.pug index 2b4d3dac8..7b516e990 100644 --- a/layout/includes/header/nav.pug +++ b/layout/includes/header/nav.pug @@ -7,7 +7,7 @@ nav#nav #search-button a.site-page.social-icon.search i.fas.fa-search.fa-fw - span=' '+_p('search') + span=' '+_p('search.title') !=partial('includes/header/menu_item', {}, {cache: true}) #toggle-menu diff --git a/layout/includes/header/post-info.pug b/layout/includes/header/post-info.pug index 1edae7292..61b2e7bd3 100644 --- a/layout/includes/header/post-info.pug +++ b/layout/includes/header/post-info.pug @@ -21,9 +21,9 @@ - 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 data_info = data_type_update ? _p('post.updated') : _p('post.created') + - 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= data_info + 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 diff --git a/layout/includes/mixins/post-ui.pug b/layout/includes/mixins/post-ui.pug index cdf62ee5d..d2cb0147e 100644 --- a/layout/includes/mixins/post-ui.pug +++ b/layout/includes/mixins/post-ui.pug @@ -1,14 +1,19 @@ mixin postUI(posts) each article , index in page.posts.data .recent-post-item - - let link = article.link || article.path - - let title = article.title || _p('no_title') - - let leftOrRight = index%2 == 0 ? 'left_radius' : 'right_radius' - - let post_cover = article.cover - - let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : '' + - + let link = article.link || article.path + let title = article.title || _p('no_title') + const position = theme.cover.position + let leftOrRight = position === 'both' + ? index%2 == 0 ? 'left' : 'right' + : position === 'left' ? 'left' : 'right' + let post_cover = article.cover + let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : '' + - if post_cover && theme.cover.index_enable .post_cover(class=leftOrRight) - a(href=url_for(link) title=title) + a(href=url_for(link) title=title) img.post_bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='`+ url_for(theme.error_img.post_page) + `'` alt=title) .recent-post-info(class=no_cover) a.article-title(href=url_for(link) title=title)= title @@ -17,14 +22,14 @@ mixin postUI(posts) span.article-meta i.fas.fa-thumbtack.sticky span.sticky= _p('sticky') - span.article-meta__separator | + span.article-meta-separator | if (theme.post_meta.page.date_type) span.post-meta-date - if (theme.post_meta.page.date_type === 'both') + 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 | + 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) @@ -38,25 +43,25 @@ mixin postUI(posts) 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 | + span.article-meta-separator | i.fas.fa-inbox each item, index in article.categories.data a(href=url_for(item.path)).article-meta__categories #[=item.name] if (index < article.categories.data.length - 1) - i.fas.fa-angle-right + i.fas.fa-angle-right.article-meta-link if (theme.post_meta.page.tags && article.tags.data.length > 0) span.article-meta.tags - span.article-meta__separator | + span.article-meta-separator | i.fas.fa-tag each item, index in article.tags.data a(href=url_for(item.path)).article-meta__tags #[=item.name] if (index < article.tags.data.length - 1) - span.article-meta__link #[='•'] + span.article-meta-link #[='•'] mixin countBlockInIndex - needLoadCountJs = true span.article-meta - span.article-meta__separator | + span.article-meta-separator | i.fas.fa-comments if block block diff --git a/layout/includes/page/categories.pug b/layout/includes/page/categories.pug index dbdc98063..79153c8d7 100644 --- a/layout/includes/page/categories.pug +++ b/layout/includes/page/categories.pug @@ -1,5 +1 @@ -.category-lists - .category-title.is-center= _p('page.category') - | - - span.category-amount= site.categories.length - div!= list_categories() \ No newline at end of file +.category-lists!= list_categories() \ No newline at end of file diff --git a/layout/includes/page/default-page.pug b/layout/includes/page/default-page.pug index 2d9cdda6e..e7057f73a 100644 --- a/layout/includes/page/default-page.pug +++ b/layout/includes/page/default-page.pug @@ -1,4 +1,2 @@ #article-container - if top_img === false - h1.page-title= page.title != page.content \ No newline at end of file diff --git a/layout/includes/page/flink.pug b/layout/includes/page/flink.pug index 65b91d86b..59032c99c 100644 --- a/layout/includes/page/flink.pug +++ b/layout/includes/page/flink.pug @@ -1,21 +1,68 @@ #article-container - if top_img === false - h1.page-title= page.title - .flink - if site.data.link - each i in site.data.link - if i.class_name - h2!= i.class_name - if i.class_desc - .flink-desc!=i.class_desc - .flink-list - each item in i.link_list - .flink-list-item - a(href=url_for(item.link) title=item.name target="_blank") - .flink-item-icon - img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name ) - .flink-item-name= item.name - .flink-item-desc(title=item.descr)= item.descr + if page.flink_url + script. + (()=>{ + const replaceSymbol = (str) => { + return str.replace(/[\p{P}\p{S}]/gu, '-') + } + + let result = '' + fetch('!{url_for(page.flink_url)}') + .then(response => response.json()) + .then(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 + for(let j = 0; j < lists.length; j++){ + listResult += ` + ` + } + + result += `${className}${classDesc} ` + } + + document.querySelector('.flink').insertAdjacentHTML('afterbegin', result) + }) + })() + + 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} ` + + - page.content = result + page.content != page.content diff --git a/layout/includes/page/tags.pug b/layout/includes/page/tags.pug index 4d57e4374..8caac11b4 100644 --- a/layout/includes/page/tags.pug +++ b/layout/includes/page/tags.pug @@ -1,5 +1,2 @@ -.tag-cloud-title.is-center= _p('page.tag') - | - - span.tag-cloud-amount= site.tags.length .tag-cloud-list.is-center !=cloudTags({source: site.tags, minfontsize: 1.2, maxfontsize: 2.1, limit: 0, unit: 'em'}) \ No newline at end of file diff --git a/layout/includes/post/reward.pug b/layout/includes/post/reward.pug index 41bb3c999..71daa9857 100644 --- a/layout/includes/post/reward.pug +++ b/layout/includes/post/reward.pug @@ -1,5 +1,5 @@ .post-reward - .reward-button.button--animated + .reward-button i.fas.fa-qrcode = ' ' + _p('donate') .reward-main diff --git a/layout/includes/rightside.pug b/layout/includes/rightside.pug index a52f6a1c5..39a742b8f 100644 --- a/layout/includes/rightside.pug +++ b/layout/includes/rightside.pug @@ -1,38 +1,60 @@ +- const { readmode, translate, darkmode, aside, chat_btn } = theme +mixin rightsideItem(array) + each item in array + case item + when 'readmode' + if is_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_btn + button#chat_btn(type="button" title=_p("rightside.chat_btn")) + i.fas.fa-sms + 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 is_post() && theme.readmode - button#readmode(type="button" title=_p('rightside.readmode_title')) - i.fas.fa-book-open - if theme.change_font_size - button#font-plus(type="button" title=_p('rightside.font_plus_title')) - i.fas.fa-plus - button#font-minus(type="button" title=_p('rightside.font_minus_title')) - i.fas.fa-minus - if theme.translate.enable - button#translateLink(type="button" title=_p('rightside.translate_title'))= theme.translate.default - if theme.darkmode.enable && theme.darkmode.button - button#darkmode(type="button" title=_p('rightside.night_mode_title')) - i.fas.fa-adjust - if theme.aside.enable && theme.aside.button && page.aside !== false - button#hide-aside-btn(type="button" title=_p('rightside.aside')) - i.fas.fa-arrows-alt-h + if hideArray + +rightsideItem(hideArray) #rightside-config-show - if is_post() - if (theme.readmode || theme.translate.enable || (theme.darkmode.enable && theme.darkmode.button) || theme.change_font_size) + if enable + if hide button#rightside_config(type="button" title=_p("rightside.setting")) i.fas.fa-cog.fa-spin - if showToc - button#mobile-toc-button.close(type="button" title=_p("rightside.toc")) - i.fas.fa-list-ul - else if theme.translate.enable || (theme.darkmode.enable && theme.darkmode.button) || theme.change_font_size - button#rightside_config(type="button" title=_p("rightside.setting")) - i.fas.fa-cog.fa-spin + else + if is_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) - if theme.chat_btn - button#chat_btn(type="button" title=_p("rightside.chat_btn")) - i.fas.fa-sms - if commentsJsLoad - a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment")) - i.fas.fa-comments button#go-up(type="button" title=_p("rightside.back_to_top")) i.fas.fa-arrow-up \ No newline at end of file diff --git a/layout/includes/sidebar.pug b/layout/includes/sidebar.pug index d8a66a37c..45a97ee04 100644 --- a/layout/includes/sidebar.pug +++ b/layout/includes/sidebar.pug @@ -3,26 +3,21 @@ #sidebar-menus .avatar-img.is-center img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar") - .site-data - if site.posts.length - .data-item.is-center - .data-item-link - a(href=url_for(config.archive_dir) + '/') - .headline= _p('aside.articles') - .length-num= site.posts.length + .site-data.is-center + .data-item + a(href=url_for(config.archive_dir) + '/') + .headline= _p('aside.articles') + .length-num= site.posts.length - if site.tags.length - .data-item.is-center - .data-item-link - a(href=url_for(config.tag_dir) + '/' ) - .headline= _p('aside.tags') - .length-num= site.tags.length + .data-item + a(href=url_for(config.tag_dir) + '/' ) + .headline= _p('aside.tags') + .length-num= site.tags.length + + .data-item + a(href=url_for(config.category_dir) + '/') + .headline= _p('aside.categories') + .length-num= site.categories.length - if site.categories.length - .data-item.is-center - .data-item-link - a(href=url_for(config.category_dir) + '/') - .headline= _p('aside.categories') - .length-num= site.categories.length hr !=partial('includes/header/menu_item', {}, {cache: true}) diff --git a/layout/includes/third-party/comments/disqusjs.pug b/layout/includes/third-party/comments/disqusjs.pug index e88849aee..268c16f3e 100644 --- a/layout/includes/third-party/comments/disqusjs.pug +++ b/layout/includes/third-party/comments/disqusjs.pug @@ -1,4 +1,3 @@ -- let disqusjsApi = theme.disqusjs.api || 'https://disqus.skk.moe/disqus/' - let disqusjsPageTitle = page.title.replace(/'/ig,"\\'") script. @@ -12,20 +11,16 @@ script. function initDisqusjs () { window.DISQUS = null - new DisqusJS({ + new DisqusJS(Object.assign({ shortname: '!{theme.disqusjs.shortname}', - siteName: '!{theme.disqusjs.siteName}', identifier: '!{ page.path }', url: '!{ page.permalink }', title: '!{ disqusjsPageTitle }', - api: '!{disqusjsApi}', apikey: '!{theme.disqusjs.apikey}', - nocomment: '!{theme.disqusjs.nocomment}', - admin: '!{theme.disqusjs.admin}', - adminLabel: '!{theme.disqusjs.adminLabel}' - }); + },!{JSON.stringify(theme.disqusjs.option)})) } + window.disqusReset = initDisqusjs if (window.disqusJsLoad) initDisqusjs() diff --git a/layout/includes/third-party/comments/facebook_comments.pug b/layout/includes/third-party/comments/facebook_comments.pug index 03cf3cd13..54807cc70 100644 --- a/layout/includes/third-party/comments/facebook_comments.pug +++ b/layout/includes/third-party/comments/facebook_comments.pug @@ -7,7 +7,7 @@ script. if (typeof FB === 'object') FB.XFBML.parse() else { let ele = document.createElement('script') - ele.setAttribute('src','https://connect.facebook.net/!{theme.facebook_comments.lang}/sdk.js#xfbml=1&version=v10.0') + ele.setAttribute('src','https://connect.facebook.net/!{theme.facebook_comments.lang}/sdk.js#xfbml=1&version=v11.0') ele.setAttribute('async', 'true') ele.setAttribute('defer', 'true') ele.setAttribute('crossorigin', 'anonymous') diff --git a/layout/includes/third-party/comments/giscus.pug b/layout/includes/third-party/comments/giscus.pug new file mode 100644 index 000000000..b09bf5a75 --- /dev/null +++ b/layout/includes/third-party/comments/giscus.pug @@ -0,0 +1,49 @@ +- const { repo, repo_id, category_id, option } = theme.giscus +- const themes = theme.giscus.theme +script. + function loadGiscus () { + let nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{themes.dark}' : '!{themes.light}' + + const config = Object.assign({ + src: '!{theme.CDN.giscus}', + 'data-repo': '!{repo}', + 'data-repo-id': '!{repo_id}', + 'data-category-id': '!{category_id}', + 'data-mapping': 'pathname', + 'data-theme': nowTheme, + 'data-reactions-enabled': '1', + crossorigin: 'anonymous', + async: true + },!{JSON.stringify(option)}) + + let ele = document.createElement('script') + for (let key in config) { + ele.setAttribute(key, config[key]) + } + document.getElementById('giscus-wrap').insertAdjacentElement('afterbegin',ele) + } + + function changeGiscusTheme () { + const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{themes.dark}' : '!{themes.light}' + + function sendMessage(message) { + const iframe = document.querySelector('iframe.giscus-frame'); + if (!iframe) return; + iframe.contentWindow.postMessage({ giscus: message }, 'https://giscus.app'); + } + + sendMessage({ + setConfig: { + theme: theme + } + }); + } + + if ('!{theme.comments.use[0]}' === 'Giscus' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('giscus-wrap'), loadGiscus) + else loadGiscus() + } else { + function loadOtherComment () { + loadGiscus() + } + } diff --git a/layout/includes/third-party/comments/gitalk.pug b/layout/includes/third-party/comments/gitalk.pug index 8e78386a0..06ecfd964 100644 --- a/layout/includes/third-party/comments/gitalk.pug +++ b/layout/includes/third-party/comments/gitalk.pug @@ -15,11 +15,6 @@ script. owner: '!{theme.gitalk.owner}', admin: ['!{theme.gitalk.admin}'], id: '!{md5(page.path)}', - language: '!{theme.gitalk.language}', - perPage: !{theme.gitalk.perPage}, - distractionFreeMode: !{theme.gitalk.distractionFreeMode}, - pagerDirection: '!{theme.gitalk.pagerDirection}', - createIssueManually: !{theme.gitalk.createIssueManually}, updateCountCallback: commentCount },!{JSON.stringify(theme.gitalk.option)})) diff --git a/layout/includes/third-party/comments/index.pug b/layout/includes/third-party/comments/index.pug index 3bab3bb21..6c725d651 100644 --- a/layout/includes/third-party/comments/index.pug +++ b/layout/includes/third-party/comments/index.pug @@ -33,6 +33,8 @@ hr #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 diff --git a/layout/includes/third-party/comments/js.pug b/layout/includes/third-party/comments/js.pug index 0b0445121..1acd8d329 100644 --- a/layout/includes/third-party/comments/js.pug +++ b/layout/includes/third-party/comments/js.pug @@ -16,5 +16,7 @@ each name in theme.comments.use !=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' !=partial('includes/third-party/comments/facebook_comments', {}, {cache: true}) diff --git a/layout/includes/third-party/comments/twikoo.pug b/layout/includes/third-party/comments/twikoo.pug index 8fcf32f78..d7a883150 100644 --- a/layout/includes/third-party/comments/twikoo.pug +++ b/layout/includes/third-party/comments/twikoo.pug @@ -1,42 +1,48 @@ +- const { envId, region, option } = theme.twikoo +- const { use, lazyload, count } = theme.comments + script. (()=>{ - const $countDom = document.getElementById('twikoo-count') const init = () => { twikoo.init(Object.assign({ el: '#twikoo-wrap', - envId: '!{theme.twikoo.envId}', - region: '!{theme.twikoo.region}' - }, !{JSON.stringify(theme.twikoo.option)})) + envId: '!{envId}', + region: '!{region}', + onCommentLoaded: function () { + btf.loadLightbox(document.querySelectorAll('#twikoo .tk-content img:not(.vemoji)')) + } + }, !{JSON.stringify(option)})) } const getCount = () => { twikoo.getCommentsCount({ - envId: '!{theme.twikoo.envId}', - region: '!{theme.twikoo.region}', + envId: '!{envId}', + region: '!{region}', urls: [window.location.pathname], includeReply: false }).then(function (res) { - $countDom.innerText = res[0].count + document.getElementById('twikoo-count').innerText = res[0].count }).catch(function (err) { console.error(err); }); } - const loadTwikoo = (bool = false) => { + const runFn = () => { + init() + !{count ? 'GLOBAL_CONFIG_SITE.isPost && getCount()' : ''} + } + + const loadTwikoo = () => { if (typeof twikoo === 'object') { - init() - bool && $countDom && setTimeout(getCount,0) - } else { - getScript('!{theme.CDN.twikoo}').then(()=> { - init() - bool && $countDom && setTimeout(getCount,0) - }) - } + setTimeout(runFn,0) + return + } + getScript('!{theme.CDN.twikoo}').then(runFn) } - if ('!{theme.comments.use[0]}' === 'Twikoo' || !!{theme.comments.lazyload}) { - if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo) - else loadTwikoo(true) + if ('!{use[0]}' === 'Twikoo' || !!{lazyload}) { + if (!{lazyload}) btf.loadComment(document.getElementById('twikoo-wrap'), loadTwikoo) + else loadTwikoo() } else { window.loadOtherComment = () => { loadTwikoo() diff --git a/layout/includes/third-party/comments/utterances.pug b/layout/includes/third-party/comments/utterances.pug index dbd422f13..25cccf228 100644 --- a/layout/includes/third-party/comments/utterances.pug +++ b/layout/includes/third-party/comments/utterances.pug @@ -13,13 +13,13 @@ script. } function utterancesTheme () { - if (document.querySelector('.utterances-frame')) { + const iframe = document.querySelector('.utterances-frame') + if (iframe) { const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{theme.utterances.dark_theme}' : '#{theme.utterances.light_theme}' const message = { type: 'set-theme', theme: theme }; - const iframe = document.querySelector('.utterances-frame'); iframe.contentWindow.postMessage(message, 'https://utteranc.es'); } } diff --git a/layout/includes/third-party/comments/valine.pug b/layout/includes/third-party/comments/valine.pug index d5121bc82..91b3110d8 100644 --- a/layout/includes/third-party/comments/valine.pug +++ b/layout/includes/third-party/comments/valine.pug @@ -9,18 +9,10 @@ script. el: '#vcomment', appId: '#{theme.valine.appId}', appKey: '#{theme.valine.appKey}', - placeholder: '#{theme.valine.placeholder}', avatar: '#{theme.valine.avatar}', - meta: '#{theme.valine.guest_info }'.split(','), - pageSize: '#{theme.valine.pageSize}', - lang: '#{theme.valine.lang}', - recordIP: #{theme.valine.recordIP}, serverURLs: '#{theme.valine.serverURLs}', - emojiCDN: '#{theme.valine.emojiCDN}', emojiMaps: !{emojiMaps}, - enableQQ: #{theme.valine.enableQQ}, path: window.location.pathname, - requiredFields: [!{theme.valine.requiredFields ? JSON.stringify(theme.valine.requiredFields).split(',') : ''}], visitor: #{theme.valine.visitor} }, !{JSON.stringify(theme.valine.option)})) } diff --git a/layout/includes/third-party/comments/waline.pug b/layout/includes/third-party/comments/waline.pug index 2407e4a7c..cfd05c258 100644 --- a/layout/includes/third-party/comments/waline.pug +++ b/layout/includes/third-party/comments/waline.pug @@ -1,4 +1,4 @@ -- const { serverURL, avatar, avatarCDN, visitor, option } = theme.waline +- const { serverURL, visitor, option } = theme.waline script. function loadWaline () { @@ -6,15 +6,13 @@ script. const waline = new Waline(Object.assign({ el: '#waline-wrap', serverURL: '!{serverURL}', - avatar: '#{avatar}', - avatarCDN: '!{avatarCDN || "https://sdn.geekzu.org/avatar/"}', path: location.pathname, visitor: !{visitor}, dark: 'html[data-theme="dark"]' }, !{JSON.stringify(option)})) } - if (typeof Waline === 'function') initWaline() + if (typeof Waline === 'function') initWaline() else getScript('!{url_for(theme.CDN.waline)}').then(initWaline) } diff --git a/layout/includes/third-party/math/mermaid.pug b/layout/includes/third-party/math/mermaid.pug index 801ce2167..31dda5e37 100644 --- a/layout/includes/third-party/math/mermaid.pug +++ b/layout/includes/third-party/math/mermaid.pug @@ -1,15 +1,26 @@ script. - if (document.getElementsByClassName('mermaid').length) { - if (window.mermaidJsLoad) mermaid.init() - else { - getScript('!{theme.CDN.mermaid}').then(() => { - window.mermaidJsLoad = true - mermaid.initialize({ - theme: '!{theme.mermaid.theme}', + (() => { + const $mermaidWrap = document.querySelectorAll('#article-container .mermaid-wrap') + if ($mermaidWrap.length) { + window.runMermaid = () => { + window.loadMermaid = true + const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}' + + Array.from($mermaidWrap).forEach((item, index) => { + const mermaidSrc = item.firstElementChild + const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n' + const mermaidID = 'mermaid-' + index + const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent + mermaid.mermaidAPI.render(mermaidID, mermaidDefinition, (svgCode) => { + mermaidSrc.insertAdjacentHTML('afterend', svgCode) + }) }) - !{theme.pjax.enable} && mermaid.init() - }) - } - } + } + const loadMermaid = () => { + window.loadMermaid ? runMermaid() : getScript('!{theme.CDN.mermaid}').then(runMermaid) + } + window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid) + } + })() \ 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 896faab29..5b95e74c7 100644 --- a/layout/includes/third-party/newest-comments/disqus-comment.pug +++ b/layout/includes/third-party/newest-comments/disqus-comment.pug @@ -49,7 +49,7 @@ script. } result += `
- ${array[i].content} + ${array[i].content}
${array[i].nick}
` } diff --git a/layout/includes/third-party/newest-comments/github-issues.pug b/layout/includes/third-party/newest-comments/github-issues.pug index 04fa27c33..2153b1159 100644 --- a/layout/includes/third-party/newest-comments/github-issues.pug +++ b/layout/includes/third-party/newest-comments/github-issues.pug @@ -75,7 +75,7 @@ script. } result += `
- ${array[i].content} + ${array[i].content}
${array[i].nick} /
` } diff --git a/layout/includes/third-party/newest-comments/twikoo-comment.pug b/layout/includes/third-party/newest-comments/twikoo-comment.pug index d8cea8c00..71b28038c 100644 --- a/layout/includes/third-party/newest-comments/twikoo-comment.pug +++ b/layout/includes/third-party/newest-comments/twikoo-comment.pug @@ -60,7 +60,7 @@ script. } result += `
- ${array[i].content} + ${array[i].content}
${array[i].nick} /
` } diff --git a/layout/includes/third-party/newest-comments/valine.pug b/layout/includes/third-party/newest-comments/valine.pug index 809da74fd..dd39b138d 100644 --- a/layout/includes/third-party/newest-comments/valine.pug +++ b/layout/includes/third-party/newest-comments/valine.pug @@ -1,6 +1,6 @@ - let default_avatar = theme.valine.avatar -script(src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.17.0/js/md5.min.js") +script(src=url_for(theme.CDN.blueimp_md5)) script. window.addEventListener('load', () => { const changeContent = (content) => { @@ -37,7 +37,7 @@ script. } result += `
- ${array[i].content} + ${array[i].content}
${array[i].nick} /
` } diff --git a/layout/includes/third-party/newest-comments/waline.pug b/layout/includes/third-party/newest-comments/waline.pug index 2b9b63014..ce0039ec2 100644 --- a/layout/includes/third-party/newest-comments/waline.pug +++ b/layout/includes/third-party/newest-comments/waline.pug @@ -16,13 +16,6 @@ script. return content } - const getIcon = (ava,mail) => { - if (ava) return ava - let defaultIcon = '!{ avatar ? `?d=${avatar}` : ''}' - let iconUrl = "!{avatarCDN ? avatarCDN : 'https://gravatar.loli.net/avatar/'}" + mail + defaultIcon - return iconUrl - } - const generateHtml = array => { let result = '' @@ -36,7 +29,7 @@ script. } result += `
- ${array[i].content} + ${array[i].content}
${array[i].nick} /
` } @@ -59,10 +52,10 @@ script. const walineArray = res.comments.map(e => { return { 'content': changeContent(e.comment), - 'avatar': getIcon(e.QQAvatar,e.mail), + 'avatar': e.avatar, 'nick': e.nick, 'url': e.url + '#' + e.objectId, - 'date': e.updatedAt, + 'date': e.insertedAt, } }) saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.newest_comments.storage}/(60*24)) diff --git a/layout/includes/third-party/pjax.pug b/layout/includes/third-party/pjax.pug index f3b581271..87266633b 100644 --- a/layout/includes/third-party/pjax.pug +++ b/layout/includes/third-party/pjax.pug @@ -3,20 +3,18 @@ if theme.pjax.exclude each val in theme.pjax.exclude - pjaxExclude = pjaxExclude + `:not([href="${val}"])` +- let pjaxSelectors = ['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 && (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.CDN.pjax)) script. - let pjaxSelectors = [ - 'title', - '#config-diff', - '#body-wrap', - '#rightside-config-hide', - '#rightside-config-show', - '.js-pjax' - ] - - if (!{Boolean(theme.Open_Graph_meta && theme.comments.use && theme.comments.use.includes('Livere'))}) { - pjaxSelectors.unshift('meta[property="og:image"]', 'meta[property="og:title"]', 'meta[property="og:url"]') - } + let pjaxSelectors = !{JSON.stringify(pjaxSelectors)} var pjax = new Pjax({ elements: '!{pjaxExclude}', @@ -74,11 +72,6 @@ script. typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() - // Analytics - if (!{theme.tencent_analytics ? true : false}) { - MtaH5.pgv() - } - // prismjs typeof Prism === 'object' && Prism.highlightAll() diff --git a/layout/includes/third-party/search/algolia.pug b/layout/includes/third-party/search/algolia.pug index 6d22886b1..e2d427e65 100644 --- a/layout/includes/third-party/search/algolia.pug +++ b/layout/includes/third-party/search/algolia.pug @@ -1,13 +1,16 @@ #algolia-search .search-dialog - #algolia-search-title.search-dialog__title Algolia - #algolia-input-panel + nav.search-nav + span.search-dialog-title= 'Algolia' + button.search-close-button + i.fas.fa-times + + .search-wrap #algolia-search-input - hr - #algolia-search-results - #algolia-hits - #algolia-pagination - #algolia-stats - span.search-close-button - i.fas.fa-times + hr + #algolia-search-results + #algolia-hits + #algolia-pagination + #algolia-stats + #search-mask diff --git a/layout/includes/third-party/search/local-search.pug b/layout/includes/third-party/search/local-search.pug index dec1569d6..4aa6ff398 100644 --- a/layout/includes/third-party/search/local-search.pug +++ b/layout/includes/third-party/search/local-search.pug @@ -1,12 +1,20 @@ #local-search .search-dialog - #local-search-title.search-dialog__title=_p("local_search.label") - #local-input-panel + nav.search-nav + span.search-dialog-title=_p("search.local_search.label") + span#loading-status + button.search-close-button + i.fas.fa-times + + #loading-database.is-center + i.fas.fa-spinner.fa-pulse + span= ' ' + _p("search.load_data") + + .search-wrap #local-search-input .local-search-box - input(placeholder=_p("local_search.input_placeholder") type="text").local-search-box--input - hr - #local-search-results - span.search-close-button - i.fas.fa-times + input(placeholder=_p("search.local_search.input_placeholder") type="text").local-search-box--input + hr + #local-search-results + #search-mask \ No newline at end of file diff --git a/layout/includes/third-party/subtitle.pug b/layout/includes/third-party/subtitle.pug index ee0f58371..21d705a2a 100644 --- a/layout/includes/third-party/subtitle.pug +++ b/layout/includes/third-party/subtitle.pug @@ -1,53 +1,22 @@ -- let source = theme.subtitle.source +- const { effect,loop,source,sub } = theme.subtitle +- let subContent = sub || new Array() case source when 1 - script. - function subtitleType () { - fetch('https://api.btstu.cn/yan/api.php?charset=utf-8&encode=json') - .then(response => response.json()) - .then(data => { - if (!{theme.subtitle.effect}) { - var sub = "!{theme.subtitle.sub}".length == 0 ? new Array() : "!{theme.subtitle.sub}".split(',') - var both = sub.unshift(data.text) - typed = new Typed('#subtitle', { - strings: sub, - startDelay: 300, - typeSpeed: 150, - loop: !{theme.subtitle.loop}, - backSpeed: 50, - }) - } else { - document.getElementById('subtitle').innerHTML = data.text - } - }) - } - - if (!{theme.subtitle.effect}) { - if (typeof Typed === 'function') { - subtitleType() - } else { - getScript('!{url_for(theme.CDN.typed)}').then(subtitleType) - } - } else { - subtitleType() - } - - when 2 script. function subtitleType () { fetch('https://v1.hitokoto.cn') .then(response => response.json()) .then(data => { - if (!{theme.subtitle.effect}) { - var from = '出自 ' + data.from - var sub = "!{theme.subtitle.sub}".length == 0 ? new Array() : "!{theme.subtitle.sub}".split(',') - var both = sub.unshift(data.hitokoto, from) - var typed = new Typed('#subtitle', { + if (!{effect}) { + const from = '出自 ' + data.from + const sub = !{JSON.stringify(subContent)} + sub.unshift(data.hitokoto, from) + window.typed = new Typed('#subtitle', { strings: sub, startDelay: 300, typeSpeed: 150, - loop: !{theme.subtitle.loop}, + loop: !{loop}, backSpeed: 50, }) } else { @@ -56,7 +25,7 @@ case source }) } - if (!{theme.subtitle.effect}) { + if (!{effect}) { if (typeof Typed === 'function') { subtitleType() } else { @@ -66,20 +35,20 @@ case source subtitleType() } - when 3 + when 2 script. function subtitleType () { getScript('https://yijuzhan.com/api/word.php?m=js').then(() => { - var con = str[0] - if (!{theme.subtitle.effect}) { - var from = '出自 ' + str[1] - var sub = "!{theme.subtitle.sub}".length == 0 ? new Array() : "!{theme.subtitle.sub}".split(',') - var both = sub.unshift(con, from) - var typed = new Typed('#subtitle', { + const con = str[0] + if (!{effect}) { + const from = '出自 ' + str[1] + const sub = !{JSON.stringify(subContent)} + sub.unshift(con, from) + window.typed = new Typed('#subtitle', { strings: sub, startDelay: 300, typeSpeed: 150, - loop: !{theme.subtitle.loop}, + loop: !{loop}, backSpeed: 50, }) } else { @@ -88,7 +57,7 @@ case source }) } - if (!{theme.subtitle.effect}) { + if (!{effect}) { if (typeof Typed === 'function') { subtitleType() } else { @@ -98,20 +67,20 @@ case source subtitleType() } - when 4 + when 3 script. function subtitleType () { getScript('https://sdk.jinrishici.com/v2/browser/jinrishici.js').then(() => { - jinrishici.load(function (result) { - if (!{theme.subtitle.effect}) { - var sub = "!{theme.subtitle.sub}".length == 0 ? new Array() : "!{theme.subtitle.sub}".split(',') - var content = result.data.content - var both = sub.unshift(content) - var typed = new Typed('#subtitle', { + jinrishici.load(result =>{ + if (!{effect}) { + const sub = !{JSON.stringify(subContent)} + const content = result.data.content + sub.unshift(content) + window.typed = new Typed('#subtitle', { strings: sub, startDelay: 300, typeSpeed: 150, - loop: !{theme.subtitle.loop}, + loop: !{loop}, backSpeed: 50, }) } else { @@ -121,7 +90,7 @@ case source }) } - if (!{theme.subtitle.effect}) { + if (!{effect}) { if (typeof Typed === 'function') { subtitleType() } else { @@ -132,22 +101,23 @@ case source } default + - subContent = subContent.length ? subContent : new Array(config.subtitle) script. function subtitleType () { - if (!{theme.subtitle.effect}) { - var typed = new Typed("#subtitle", { - strings: "!{theme.subtitle.sub}".split(","), + if (!{effect}) { + window.typed = new Typed("#subtitle", { + strings: !{JSON.stringify(subContent)}, startDelay: 300, typeSpeed: 150, - loop: !{theme.subtitle.loop}, + loop: !{loop}, backSpeed: 50 }) } else { - document.getElementById("subtitle").innerHTML = '!{theme.subtitle.sub[0]}' + document.getElementById("subtitle").innerHTML = '!{subContent[0]}' } } - if (!{theme.subtitle.effect}) { + if (!{effect}) { if (typeof Typed === 'function') { subtitleType() } else { diff --git a/layout/includes/widget/card_author.pug b/layout/includes/widget/card_author.pug index 57b1f9dad..0fa860af0 100644 --- a/layout/includes/widget/card_author.pug +++ b/layout/includes/widget/card_author.pug @@ -6,27 +6,24 @@ if theme.aside.card_author.enable .author-info__name= config.author .author-info__description!= theme.aside.card_author.description || config.description - .card-info-data - if site.posts.length - .card-info-data-item.is-center - a(href=url_for(config.archive_dir) + '/') - .headline= _p('aside.articles') - .length-num= site.posts.length + .card-info-data.is-center + .card-info-data-item + a(href=url_for(config.archive_dir) + '/') + .headline= _p('aside.articles') + .length-num= site.posts.length - if site.tags.length - .card-info-data-item.is-center - a(href=url_for(config.tag_dir) + '/') - .headline= _p('aside.tags') - .length-num= site.tags.length + .card-info-data-item + a(href=url_for(config.tag_dir) + '/') + .headline= _p('aside.tags') + .length-num= site.tags.length - if site.categories.length - .card-info-data-item.is-center - a(href=url_for(config.category_dir) + '/') - .headline= _p('aside.categories') - .length-num= site.categories.length + .card-info-data-item + 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.button--animated(href=theme.aside.card_author.button.link) + 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 diff --git a/layout/includes/widget/card_newest_comment.pug b/layout/includes/widget/card_newest_comment.pug index 4c3d4beaa..7350ee7ac 100644 --- a/layout/includes/widget/card_newest_comment.pug +++ b/layout/includes/widget/card_newest_comment.pug @@ -1,4 +1,4 @@ -if theme.newest_comments.enable +if theme.newest_comments.enable && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0]) .card-widget#card-newest-comments .item-headline i.fas.fa-comment-dots diff --git a/layout/includes/widget/card_post_toc.pug b/layout/includes/widget/card_post_toc.pug index 3874dc772..415422192 100644 --- a/layout/includes/widget/card_post_toc.pug +++ b/layout/includes/widget/card_post_toc.pug @@ -1,12 +1,15 @@ - let tocNumber = page.toc_number !== undefined ? page.toc_number : theme.toc.number +- let tocExpand = page.toc_expand !== undefined ? 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(style="display:none")!=toc(page.origin, {list_number: tocNumber}) + .toc-content.toc-div-class(class=tocExpandClass style="display:none")!=toc(page.origin, {list_number: tocNumber}) else - .toc-content!=toc(page.content, {list_number: tocNumber}) + .toc-content(class=tocExpandClass)!=toc(page.content, {list_number: tocNumber}) \ No newline at end of file diff --git a/layout/includes/widget/index.pug b/layout/includes/widget/index.pug index f9b993067..5f44ae963 100644 --- a/layout/includes/widget/index.pug +++ b/layout/includes/widget/index.pug @@ -1,13 +1,15 @@ #aside-content.aside-content //- post if is_post() - if showToc && theme.toc.style_simple + - 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}) + !=partial('includes/widget/card_top_self', {}, {cache: true}) .sticky_layout if showToc include ./card_post_toc.pug @@ -20,6 +22,8 @@ !=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}) diff --git a/layout/page.pug b/layout/page.pug index 2fb8b7ebb..6c810ef7e 100644 --- a/layout/page.pug +++ b/layout/page.pug @@ -2,6 +2,9 @@ extends includes/layout.pug block content #page + if top_img === false + h1.page-title= page.title + case page.type when 'tags' include includes/page/tags.pug diff --git a/package.json b/package.json index 6b7b5e820..e2a30fed9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-butterfly", - "version": "3.8.4", + "version": "4.0.0", "description": "A Simple and Card UI Design theme for Hexo", "main": "package.json", "scripts": { @@ -20,13 +20,13 @@ }, "bugs": { "url": "https://github.com/jerryc127/hexo-theme-butterfly/issues", - "email": "i@immyw.com" + "email": "my@crazywong.com" }, "dependencies": { "hexo-renderer-stylus": "^2.0.1", "hexo-renderer-pug": "^2.0.0" }, "homepage": "https://butterfly.js.org/", - "author": "Jerry ", + "author": "Jerry ", "license": "Apache-2.0" } diff --git a/scripts/events/config.js b/scripts/events/config.js new file mode 100644 index 000000000..8c680cfb7 --- /dev/null +++ b/scripts/events/config.js @@ -0,0 +1,128 @@ +/** + * Butterfly + * 1. Merge CDN + * 2. Capitalize the first letter of comment name + */ + +'use strict' + +hexo.extend.filter.register('before_generate', () => { + const themeConfig = hexo.theme.config + + /** + * Merge CDN + */ + + const defaultCDN = { + main_css: '/css/index.css', + main: '/js/main.js', + utils: '/js/utils.js', + + // pjax + pjax: 'https://cdn.jsdelivr.net/npm/pjax/pjax.min.js', + + // comments + gitalk: 'https://cdn.jsdelivr.net/npm/gitalk@latest/dist/gitalk.min.js', + gitalk_css: 'https://cdn.jsdelivr.net/npm/gitalk/dist/gitalk.min.css', + blueimp_md5: 'https://cdn.jsdelivr.net/npm/blueimp-md5/js/md5.min.js', + valine: 'https://cdn.jsdelivr.net/npm/valine/dist/Valine.min.js', + disqusjs: 'https://cdn.jsdelivr.net/npm/disqusjs@1/dist/disqus.js', + disqusjs_css: 'https://cdn.jsdelivr.net/npm/disqusjs@1/dist/disqusjs.css', + utterances: 'https://utteranc.es/client.js', + twikoo: 'https://cdn.jsdelivr.net/npm/twikoo/dist/twikoo.all.min.js', + waline: 'https://cdn.jsdelivr.net/npm/@waline/client/dist/Waline.min.js', + giscus: 'https://giscus.app/client.js', + + // share + addtoany: 'https://static.addtoany.com/menu/page.js', + sharejs: 'https://cdn.jsdelivr.net/npm/social-share.js/dist/js/social-share.min.js', + sharejs_css: 'https://cdn.jsdelivr.net/npm/social-share.js/dist/css/share.min.css', + + // search + local_search: '/js/search/local-search.js', + algolia_js: '/js/search/algolia.js', + algolia_search_v4: 'https://cdn.jsdelivr.net/npm/algoliasearch@4/dist/algoliasearch-lite.umd.js', + instantsearch_v4: 'https://cdn.jsdelivr.net/npm/instantsearch.js@4/dist/instantsearch.production.min.js', + + // math + mathjax: 'https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js', + katex: 'https://cdn.jsdelivr.net/npm/katex@latest/dist/katex.min.css', + katex_copytex: 'https://cdn.jsdelivr.net/npm/katex@latest/dist/contrib/copy-tex.min.js', + katex_copytex_css: 'https://cdn.jsdelivr.net/npm/katex@latest/dist/contrib/copy-tex.css', + mermaid: 'https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js', + + // count + busuanzi: '//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js', + + // background effect + canvas_ribbon: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-ribbon.min.js', + canvas_fluttering_ribbon: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-fluttering-ribbon.min.js', + canvas_nest: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/canvas-nest.min.js', + + lazyload: 'https://cdn.jsdelivr.net/npm/vanilla-lazyload/dist/lazyload.iife.min.js', + instantpage: 'https://cdn.jsdelivr.net/npm/instant.page/instantpage.min.js', + typed: 'https://cdn.jsdelivr.net/npm/typed.js/lib/typed.min.js', + pangu: 'https://cdn.jsdelivr.net/npm/pangu/dist/browser/pangu.min.js', + + // photo + fancybox_css_v4: 'https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.css', + fancybox_v4: 'https://cdn.jsdelivr.net/npm/@fancyapps/ui/dist/fancybox.umd.js', + medium_zoom: 'https://cdn.jsdelivr.net/npm/medium-zoom/dist/medium-zoom.min.js', + + // snackbar + snackbar_css: 'https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.css', + snackbar: 'https://cdn.jsdelivr.net/npm/node-snackbar/dist/snackbar.min.js', + + // effect + activate_power_mode: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/activate-power-mode.min.js', + fireworks: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/fireworks.min.js', + click_heart: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-heart.min.js', + ClickShowText: 'https://cdn.jsdelivr.net/npm/butterfly-extsrc@1/dist/click-show-text.min.js', + + // fontawesome + fontawesome: 'https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free/css/all.min.css', + + // Conversion between Traditional and Simplified Chinese + translate: '/js/tw_cn.js', + + // flickr-justified-gallery + flickr_justified_gallery_js: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.js', + flickr_justified_gallery_css: 'https://cdn.jsdelivr.net/npm/flickr-justified-gallery@2/dist/fjGallery.min.css', + + // aplayer + aplayer_css: 'https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.css', + aplayer_js: 'https://cdn.jsdelivr.net/npm/aplayer/dist/APlayer.min.js', + meting_js: 'https://cdn.jsdelivr.net/gh/metowolf/MetingJS@1.2/dist/Meting.min.js', + + // Prism.js + prismjs_js: 'https://cdn.jsdelivr.net/npm/prismjs/prism.min.js', + prismjs_lineNumber_js: 'https://cdn.jsdelivr.net/npm/prismjs/plugins/line-numbers/prism-line-numbers.min.js', + prismjs_autoloader: 'https://cdn.jsdelivr.net/npm/prismjs/plugins/autoloader/prism-autoloader.min.js' + } + + // delete null value + const deleteNullValue = obj => { + for (const i in obj) { + obj[i] === null && delete obj[i] + } + return obj + } + + themeConfig.CDN = Object.assign(defaultCDN, deleteNullValue(themeConfig.CDN)) + + /** + * Capitalize the first letter of comment name + */ + + let { use } = themeConfig.comments + + if (!use) return + + if (typeof use === 'string') { + use = use.split(',') + } + + const newArray = use.map(item => item.toLowerCase().replace(/^\S/, s => s.toUpperCase())) + + themeConfig.comments.use = newArray +}) diff --git a/scripts/events/init.js b/scripts/events/init.js index 76f78ef5f..b2703197e 100644 --- a/scripts/events/init.js +++ b/scripts/events/init.js @@ -18,10 +18,4 @@ hexo.extend.filter.register('before_generate', () => { process.exit(-1) } } - - // let stylus to get the hexo highlight config - const themeConfig = hexo.theme.config - const hexoConfig = hexo.config - themeConfig.highlight_settings = hexoConfig.highlight - themeConfig.prismjs_settings = hexoConfig.prismjs }) diff --git a/scripts/events/stylus.js b/scripts/events/stylus.js new file mode 100644 index 000000000..4b95538dc --- /dev/null +++ b/scripts/events/stylus.js @@ -0,0 +1,15 @@ +/** + * stylus + */ + +'use strict' + +hexo.extend.filter.register('stylus:renderer', function (style) { + const { highlight, prismjs } = hexo.config + style + .define('$highlight_enable', highlight && highlight.enable) + .define('$highlight_line_number', highlight && highlight.line_number) + .define('$prismjs_enable', prismjs && prismjs.enable) + .define('$prismjs_line_number', prismjs && prismjs.line_number) + // .import(this.source_dir.replace(/\\/g, '/') + '_data/css/*') +}) diff --git a/scripts/filters/post_lazyload.js b/scripts/filters/post_lazyload.js index 0b21de977..c4267d1cc 100644 --- a/scripts/filters/post_lazyload.js +++ b/scripts/filters/post_lazyload.js @@ -9,7 +9,7 @@ const urlFor = require('hexo-util').url_for.bind(hexo) function lazyload (htmlContent) { - const bg = hexo.theme.config.lazyload.placeholder ? urlFor(hexo.theme.config.lazyload.placeholder) : 'data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=' + const bg = hexo.theme.config.lazyload.placeholder ? urlFor(hexo.theme.config.lazyload.placeholder) : 'data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7' return htmlContent.replace(/( { - if (GLOBAL_CONFIG_SITE.isHome && /iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){ + if(/iPad|iPhone|iPod|Macintosh/.test(navigator.userAgent)){ document.documentElement.classList.add('apple') } } detectApple() ` - if (pjax.enable) { - detectApple += 'document.addEventListener(\'pjax:complete\', detectApple)' - } - } - - return `` + return `` }) diff --git a/scripts/tag/button.js b/scripts/tag/button.js index 791a8e335..33a0e53b4 100644 --- a/scripts/tag/button.js +++ b/scripts/tag/button.js @@ -21,7 +21,7 @@ function btn (args) { icon = icon.trim() option = option.trim() - return `${icon.length ? `` : ''}${text.length ? `${text}` : ''}` } diff --git a/scripts/tag/gallery.js b/scripts/tag/gallery.js index 6bec4c452..acccd0b3e 100644 --- a/scripts/tag/gallery.js +++ b/scripts/tag/gallery.js @@ -8,7 +8,7 @@ const urlFor = require('hexo-util').url_for.bind(hexo) function gallery (args, content) { - return `' ) } - }, - cssClasses: { - item: 'algolia-hit-item' } }) - ) + ]) - search.addWidget( + search.addWidgets([ instantsearch.widgets.stats({ container: '#algolia-stats', templates: { - body: function (data) { + text: function (data) { + const icon = '' const stats = GLOBAL_CONFIG.algolia.languages.hits_stats .replace(/\$\{hits}/, data.nbHits) .replace(/\$\{time}/, data.processingTimeMS) return ( - '
' + - stats + - '' + `
${stats}` ) } } }) - ) + ]) - search.addWidget( + search.addWidgets([ instantsearch.widgets.pagination({ container: '#algolia-pagination', - scrollTo: false, - showFirstLast: false, - labels: { + totalPages: 5, + templates: { first: '', last: '', previous: '', next: '' - }, - cssClasses: { - root: 'pagination', - item: 'pagination-item', - link: 'page-number', - active: 'current', - disabled: 'disabled-item' } }) - ) + ]) search.start() window.pjax && search.on('render', () => { diff --git a/source/js/search/local-search.js b/source/js/search/local-search.js index 5b134457b..de2db620d 100644 --- a/source/js/search/local-search.js +++ b/source/js/search/local-search.js @@ -1,10 +1,12 @@ window.addEventListener('load', () => { let loadFlag = false - const openSearch = function () { - document.body.style.cssText = 'width: 100%;overflow: hidden' - document.querySelector('#local-search .search-dialog').style.display = 'block' - document.querySelector('#local-search-input input').focus() - btf.fadeIn(document.getElementById('search-mask'), 0.5) + const openSearch = () => { + const bodyStyle = document.body.style + bodyStyle.width = '100%' + bodyStyle.overflow = 'hidden' + btf.animateIn(document.getElementById('search-mask'), 'to_show 0.5s') + btf.animateIn(document.querySelector('#local-search .search-dialog'), 'titleScale 0.5s') + setTimeout(() => { document.querySelector('#local-search-input input').focus() }, 100) if (!loadFlag) { search(GLOBAL_CONFIG.localSearch.path) loadFlag = true @@ -18,12 +20,12 @@ window.addEventListener('load', () => { }) } - const closeSearch = function () { - document.body.style.cssText = "width: '';overflow: ''" - const $searchDialog = document.querySelector('#local-search .search-dialog') - $searchDialog.style.animation = 'search_close .5s' - setTimeout(() => { $searchDialog.style.cssText = "display: none; animation: ''" }, 500) - btf.fadeOut(document.getElementById('search-mask'), 0.5) + const closeSearch = () => { + const bodyStyle = document.body.style + bodyStyle.width = '' + bodyStyle.overflow = '' + btf.animateOut(document.querySelector('#local-search .search-dialog'), 'search_close .5s') + btf.animateOut(document.getElementById('search-mask'), 'to_hide 0.5s') } // click function @@ -41,107 +43,122 @@ window.addEventListener('load', () => { searchClickFn() }) - function search (path) { - fetch(GLOBAL_CONFIG.root + path) - .then(response => response.text()) - .then(str => new window.DOMParser().parseFromString(str, 'text/xml')) - .then(data => { - const datas = [...data.querySelectorAll('entry')].map(function (item) { - const content = item.querySelector('content') - return { - title: item.querySelector('title').textContent, - content: content ? content.textContent : '', - url: item.querySelector('url').textContent - } - }) + async function search (path) { + let datas = [] + const typeF = path.split('.')[1] + const response = await fetch(GLOBAL_CONFIG.root + path) + if (typeF === 'json') { + datas = await response.json() + } else if (typeF === 'xml') { + const res = await response.text() + const t = await new window.DOMParser().parseFromString(res, 'text/xml') + const a = await t + datas = [...a.querySelectorAll('entry')].map(function (item) { + return { + title: item.querySelector('title').textContent, + content: item.querySelector('content').textContent, + url: item.querySelector('url').textContent + } + }) + } + if (response.ok) { + const $loadDataItem = document.getElementById('loading-database') + $loadDataItem.nextElementSibling.style.display = 'block' + $loadDataItem.remove() + } - const $input = document.querySelector('#local-search-input input') - const $resultContent = document.getElementById('local-search-results') - $input.addEventListener('input', function () { - let str = '
' - const keywords = this.value.trim().toLowerCase().split(/[\s]+/) - $resultContent.innerHTML = '' - if (this.value.trim().length <= 0) return - let count = 0 - // perform local searching - datas.forEach(function (data) { - let isMatch = true - if (!data.title || data.title.trim() === '') { - data.title = 'Untitled' - } - let dataTitle = data.title.trim().toLowerCase() - const dataContent = data.content.trim().replace(/<[^>]+>/g, '').toLowerCase() - const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url - let indexTitle = -1 - let indexContent = -1 - let firstOccur = -1 - // only match artiles with not empty titles and contents - if (dataTitle !== '' || dataContent !== '') { - keywords.forEach(function (keyword, i) { - indexTitle = dataTitle.indexOf(keyword) - indexContent = dataContent.indexOf(keyword) - if (indexTitle < 0 && indexContent < 0) { - isMatch = false - } else { - if (indexContent < 0) { - indexContent = 0 - } - if (i === 0) { - firstOccur = indexContent - } - } - }) - } else { + const $input = document.querySelector('#local-search-input input') + const $resultContent = document.getElementById('local-search-results') + const $loadingStatus = document.getElementById('loading-status') + $input.addEventListener('input', function () { + const keywords = this.value.trim().toLowerCase().split(/[\s]+/) + if (keywords[0] !== '') $loadingStatus.innerHTML = '' + + $resultContent.innerHTML = '' + let str = '
' + if (this.value.trim().length <= 0) return + let count = 0 + // perform local searching + datas.forEach(function (data) { + let isMatch = true + if (!data.title || data.title.trim() === '') { + data.title = '' + } + let dataTitle = data.title.trim().toLowerCase() + const dataContent = data.content ? data.content.trim().replace(/<[^>]+>/g, '').toLowerCase() : '' + const dataUrl = data.url.startsWith('/') ? data.url : GLOBAL_CONFIG.root + data.url + let indexTitle = -1 + let indexContent = -1 + let firstOccur = -1 + // only match artiles with not empty titles and contents + if (dataTitle !== '' || dataContent !== '') { + keywords.forEach(function (keyword, i) { + indexTitle = dataTitle.indexOf(keyword) + indexContent = dataContent.indexOf(keyword) + if (indexTitle < 0 && indexContent < 0) { isMatch = false + } else { + if (indexContent < 0) { + indexContent = 0 + } + if (i === 0) { + firstOccur = indexContent + } } + }) + } else { + isMatch = false + } - // show search results - if (isMatch) { - const content = data.content.trim().replace(/<[^>]+>/g, '') - if (firstOccur >= 0) { - // cut out 130 characters - let start = firstOccur - 30 - let end = firstOccur + 100 + // show search results + if (isMatch) { + const content = data.content.trim().replace(/<[^>]+>/g, '') + if (firstOccur >= 0) { + // cut out 130 characters + // let start = firstOccur - 30 < 0 ? 0 : firstOccur - 30 + // let end = firstOccur + 50 > content.length ? content.length : firstOccur + 50 + let start = firstOccur - 30 + let end = firstOccur + 100 - if (start < 0) { - start = 0 - } + if (start < 0) { + start = 0 + } - if (start === 0) { - end = 100 - } + if (start === 0) { + end = 100 + } - if (end > content.length) { - end = content.length - } + if (end > content.length) { + end = content.length + } - let matchContent = content.substring(start, end) + let matchContent = content.substring(start, end) - // highlight all keywords - keywords.forEach(function (keyword) { - const regS = new RegExp(keyword, 'gi') - matchContent = matchContent.replace(regS, '' + keyword + '') - dataTitle = dataTitle.replace(regS, '' + keyword + '') - }) + // highlight all keywords + keywords.forEach(function (keyword) { + const regS = new RegExp(keyword, 'gi') + matchContent = matchContent.replace(regS, '' + keyword + '') + dataTitle = dataTitle.replace(regS, '' + keyword + '') + }) - str += '
' + dataTitle + '' - count += 1 + str += '
' + dataTitle + '' + count += 1 - if (dataContent !== '') { - str += '

' + matchContent + '...

' - } - } - str += '
' + if (dataContent !== '') { + str += '

' + matchContent + '...

' } - }) - if (count === 0) { - str += '
' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) + - '
' } str += '
' - $resultContent.innerHTML = str - window.pjax && window.pjax.refresh($resultContent) - }) + } }) + if (count === 0) { + str += '
' + GLOBAL_CONFIG.localSearch.languages.hits_empty.replace(/\$\{query}/, this.value.trim()) + + '
' + } + str += '
' + $resultContent.innerHTML = str + if (keywords[0] !== '') $loadingStatus.innerHTML = '' + window.pjax && window.pjax.refresh($resultContent) + }) } }) diff --git a/source/js/utils.js b/source/js/utils.js index 8fa5d8a0e..b3e5df095 100644 --- a/source/js/utils.js +++ b/source/js/utils.js @@ -58,34 +58,18 @@ const btf = { } }, - snackbarShow: (text, showAction, duration) => { - const sa = (typeof showAction !== 'undefined') ? showAction : false - const dur = (typeof duration !== 'undefined') ? duration : 2000 - const position = GLOBAL_CONFIG.Snackbar.position - const bg = document.documentElement.getAttribute('data-theme') === 'light' ? GLOBAL_CONFIG.Snackbar.bgLight : GLOBAL_CONFIG.Snackbar.bgDark + snackbarShow: (text, showAction = false, duration = 2000) => { + const { position, bgLight, bgDark } = GLOBAL_CONFIG.Snackbar + const bg = document.documentElement.getAttribute('data-theme') === 'light' ? bgLight : bgDark Snackbar.show({ text: text, backgroundColor: bg, - showAction: sa, - duration: dur, + showAction: showAction, + duration: duration, pos: position }) }, - initJustifiedGallery: function (selector) { - if (!(selector instanceof jQuery)) { - selector = $(selector) - } - selector.each(function (i, o) { - if ($(this).is(':visible')) { - $(this).justifiedGallery({ - rowHeight: 220, - margins: 4 - }) - } - }) - }, - diffDate: (d, more = false) => { const dateNow = new Date() const datePost = new Date(d) @@ -135,15 +119,11 @@ const btf = { } }, - scrollToDest: (pos, time) => { - if (pos < 0 || time < 0) { - return - } - - const currentPos = window.scrollY || window.screenTop + scrollToDest: (pos, time = 500) => { + const currentPos = window.pageYOffset if (currentPos > pos) pos = pos - 70 - if ('CSS' in window && CSS.supports('scroll-behavior', 'smooth')) { + if ('scrollBehavior' in document.documentElement.style) { window.scrollTo({ top: pos, behavior: 'smooth' @@ -152,39 +132,35 @@ const btf = { } let start = null - time = time || 500 + pos = +pos window.requestAnimationFrame(function step (currentTime) { start = !start ? currentTime : start + const progress = currentTime - start if (currentPos < pos) { - const progress = currentTime - start window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos) - if (progress < time) { - window.requestAnimationFrame(step) - } else { - window.scrollTo(0, pos) - } } else { - const progress = currentTime - start window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time)) - if (progress < time) { - window.requestAnimationFrame(step) - } else { - window.scrollTo(0, pos) - } + } + if (progress < time) { + window.requestAnimationFrame(step) + } else { + window.scrollTo(0, pos) } }) }, - fadeIn: (ele, time) => { - ele.style.cssText = `display:block;animation: to_show ${time}s` + animateIn: (ele, text) => { + ele.style.display = 'block' + ele.style.animation = text }, - fadeOut: (ele, time) => { + animateOut: (ele, text) => { ele.addEventListener('animationend', function f () { - ele.style.cssText = "display: none; animation: '' " + ele.style.display = '' + ele.style.animation = '' ele.removeEventListener('animationend', f) }) - ele.style.animation = `to_hide ${time}s` + ele.style.animation = text }, getParents: (elem, selector) => { @@ -204,7 +180,6 @@ const btf = { }, /** - * * @param {*} selector * @param {*} eleType the type of create element * @param {*} options object key: value @@ -226,14 +201,6 @@ const btf = { } }, - isJqueryLoad: fn => { - if (typeof jQuery === 'undefined') { - getScript(GLOBAL_CONFIG.source.jQuery).then(fn) - } else { - fn() - } - }, - isHidden: ele => ele.offsetHeight === 0 && ele.offsetWidth === 0, getEleTop: ele => { @@ -246,6 +213,65 @@ const btf = { } return actualTop - } + }, + + loadLightbox: ele => { + const service = GLOBAL_CONFIG.lightbox + if (service === 'mediumZoom') { + const zoom = mediumZoom(ele) + zoom.on('open', e => { + const photoBg = document.documentElement.getAttribute('data-theme') === 'dark' ? '#121212' : '#fff' + zoom.update({ + background: photoBg + }) + }) + } + + if (service === 'fancybox') { + ele.forEach(i => { + if (i.parentNode.tagName !== 'A') { + const dataSrc = i.dataset.lazySrc || i.src + const dataCaption = i.title || i.alt || '' + btf.wrap(i, 'a', { href: dataSrc, 'data-fancybox': 'gallery', 'data-caption': dataCaption, 'data-thumb': dataSrc }) + } + }) + + if (!window.fancyboxRun) { + Fancybox.bind('[data-fancybox]', { + Hash: false, + Thumbs: { + autoStart: false + } + }) + window.fancyboxRun = true + } + } + }, + + initJustifiedGallery: function (selector) { + selector.forEach(function (i) { + if (!btf.isHidden(i)) { + fjGallery(i, { + itemSelector: '.fj-gallery-item', + rowHeight: 220, + gutter: 4, + onJustify: function () { + this.$container.style.opacity = '1' + } + }) + } + }) + }, + + updateAnchor: (anchor) => { + if (anchor !== window.location.hash) { + if (!anchor) anchor = location.pathname + const title = GLOBAL_CONFIG_SITE.title + window.history.replaceState({ + url: location.href, + title: title + }, title, anchor) + } + } }