diff --git a/themes/butterfly/LICENSE b/themes/butterfly/LICENSE new file mode 100644 index 0000000..7a4a3ea --- /dev/null +++ b/themes/butterfly/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/themes/butterfly/README.md b/themes/butterfly/README.md new file mode 100644 index 0000000..8ee13da --- /dev/null +++ b/themes/butterfly/README.md @@ -0,0 +1,96 @@ +# hexo-theme-butterfly + +![version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly) +![https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff](https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff) +![hexo version](https://img.shields.io/badge/hexo-4.2+-0e83c) +![npm download](https://img.shields.io/npm/dw/hexo-theme-butterfly?color=green) +![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531) + +Demo: 👍 [Butterfly](https://butterfly.js.org/) || 🤞 [JerryC](https://jerryc.me/) + +Docs: 📖 [Butterfly Docs](https://butterfly.js.org/posts/21cfbf15/) + +Based on [hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody) theme. + +## Installation + +### GIT + +> If you are in Mainland China, you can download in [Gitee](https://gitee.com/iamjerryw/hexo-theme-butterfly) + +Stable branch [recommend]: + +``` +git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +Dev branch: + +``` +git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +### NPM + +> It supports Hexo 5.0.0 or later + +In Hexo site root directory + +```powershell +npm i hexo-theme-butterfly +``` + +## Configuration + + Set theme in the hexo work folder's root config file `_config.yml`: + +> theme: butterfly + + If you don't have pug & stylus renderer, try this: + +> npm install hexo-renderer-pug hexo-renderer-stylus + +## Features + +- [x] Card UI Design +- [X] Support sub-menu +- [x] Two Column designs +- [x] Responsive Web Design +- [x] Dark Mode +- [x] Pjax +- [x] Read Mode +- [x] Conversion between Traditional and Simplified Chinese +- [X] TOC catalog is available for both computers and mobile phones +- [X] Color themes (darker/pale night/light/ocean/mac/mac light), support custom colors +- [X] Code Blocks (Display code language/close or expand Code Blocks/Copy Button/word wrap) +- [X] Disable copy/Add a Copyright Notice to the Copied Text +- [X] Search (Algolia SearchZ/Local Search) +- [x] Mathjax and Katex +- [x] Built-in 404 page +- [x] WordCount +- [x] Related articles +- [x] Displays outdated notice for a post +- [x] Share (AddThis/Sharejs/Addtoany) +- [X] Comment (Disqus/Disqusjs/Livere/Gitalk/Valine/Utterances/Facebook Comments) +- [x] Multiple Comment System Support +- [x] Online Chats (Chatra/Tidio/Daovoice/Gitter/Crisp) +- [x] Web analytics (Baidu Analytics/Google Analytics/Tencent Analytics/CNZZ Analytics) +- [x] Google AdSense +- [x] Webmaster Verification (google/Bing/Baidu/360/Yandex) +- [x] Change website colour scheme +- [x] Typewriter Effect: activate_power_mode +- [x] Background effects (Canvas ribbon/canvas_ribbon_piao/canvas_nest) +- [x] Mouse click effects (Fireworks/Heart/Text) +- [x] Preloader/Loading Animation +- [x] Busuanzi visitor counter +- [x] Medium Zoom/Fancybox +- [x] Mermaid +- [x] Justified Gallery +- [x] Lazyload images +- [x] Instantpage/Pangu/Snackbar notification toast/PWA...... + +## Screenshots + +![](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 diff --git a/themes/butterfly/README_CN.md b/themes/butterfly/README_CN.md new file mode 100644 index 0000000..3a6e6a8 --- /dev/null +++ b/themes/butterfly/README_CN.md @@ -0,0 +1,96 @@ +# hexo-theme-butterfly + +![version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly) +![https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff](https://img.shields.io/npm/v/hexo-theme-butterfly?color=%09%23bf00ff) +![hexo version](https://img.shields.io/badge/hexo-4.2+-0e83c) +![npm download](https://img.shields.io/npm/dw/hexo-theme-butterfly?color=green) +![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531) + + +預覽: 👍 [Butterfly](https://butterfly.js.org/) || 🤞 [JerryC](https://jerryc.me/) + +文檔: 📖 [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 中下載。 + +在博客根目錄裡安裝穩定版【推薦】 + +```powershell +git clone -b master https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +如果想要安裝比較新的dev分支,可以 + +```powershell +git clone -b dev https://github.com/jerryc127/hexo-theme-butterfly.git themes/butterfly +``` + +### npm 安裝 + +> 此方法只支持Hexo 5.0.0以上版本 + +在博客根目錄裡 + +```powershell +npm i hexo-theme-butterfly +``` + +## 應用主題 +修改hexo配置文件`_config.yml`,把主題改為`Butterfly` + +``` +theme: butterfly +``` + +>如果你沒有pug以及stylus的渲染器,請下載安裝: npm install hexo-renderer-pug hexo-renderer-stylus --save + +## 特色 + +- [x] 卡片化設計 +- [X] 支持二級目錄 +- [x] 雙欄設計 +- [x] 響應式主題 +- [x] 夜間模式 +- [x] Pjax +- [x] 文章閲讀模式 +- [x] 簡體和繁體轉換 +- [X] 電腦和手機都可查看TOC目錄 +- [X] 內置多種代碼配色(darker/pale night/light/ocean/mac/mac light),可自定義代碼配色 +- [X] 代碼塊顯示代碼語言/關閉或展開代碼塊/代碼複製/代碼自動換行 +- [X] 可關閉文字複製/可開啟內容複製增加版權信息) +- [X] 兩種搜索(Algolia搜索和本地搜索) +- [x] Mathjax 和 Katex +- [x] 內置404頁面 +- [x] 顯示字數統計 +- [x] 顯示相關文章 +- [x] 過期文章提醒 +- [x] 多種分享系統(AddThis/Sharejs/Addtoany) +- [X] 多種評論系統(Disqus/Disqusjs/Livere/Gitalk/Valine/Utterances/Facebook Comments) +- [x] 支持雙評論部署 +- [x] 多種在線聊天(Chatra/Tidio/Daovoice/Gitter/Crisp) +- [x] 多種分析系統(百度分析/谷歌分析/騰訊分析/CNZZ分析) +- [x] 谷歌廣告/手動廣告位置 +- [x] 各種站長驗證(Google/Bing/Baidu/360/Yandex) +- [x] 修改網站配色 +- [x] 打字特效 activate_power_mode +- [x] 多種背景特效(靜止彩帶/動態彩帶/Canvas Nest) +- [x] 多種鼠標點擊特效(煙花/文字/愛心) +- [x] 內置一種 Preloader 加載動畫 +- [x] 不蒜子訪問統計 +- [x] 兩種大圖模式(Medium Zoom/Fancybox) +- [x] Mermaid 圖表顯示 +- [x] 照片牆 +- [x] 圖片懶加載 +- [x] Instantpage/Pangu/Snackbar彈窗/PWA...... + +## 截圖 + +![](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 diff --git a/themes/butterfly/_config.yml b/themes/butterfly/_config.yml new file mode 100644 index 0000000..5b2a2a1 --- /dev/null +++ b/themes/butterfly/_config.yml @@ -0,0 +1,914 @@ +# Main menu navigation (導航目錄) +# -------------------------------------- + +# format: name: link || icon +# sub-menu +# name || icon: +# name || link || icon + +menu: + # Home: / || fas fa-home + # Archives: /archives/ || fas fa-archive + # Tags: /tags/ || fas fa-tags + # Categories: /categories/ || fas fa-folder-open + # List||fas fa-list: + # - Music || /music/ || fas fa-music + # - Movie || /movies/ || fas fa-video + # 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 (代碼相關) +# -------------------------------------- + +highlight_theme: light # darker / pale night / light / ocean / mac / mac light / false +highlight_copy: true # copy button +highlight_lang: true # show the code language +highlight_shrink: false # true: shrink the code blocks / false: expand the code blocks | none: expand code blocks and hide the button +code_word_wrap: false + +# copy settings +# copyright: Add the copyright information after copied content (複製的內容後面加上版權信息) +copy: + enable: true + copyright: + enable: false + limit_count: 50 + +# social settings (社交圖標設置) +# formal: +# icon: link || the description +social: + fab fa-github: https://github.com/dengtongyu|| Github + fas fa-envelope: mailto:dengtongyu123@163.com || Email + +# search (搜索) +# -------------------------------------- + +# Algolia search +algolia_search: + enable: false + hits: + per_page: 6 + +# Local search +local_search: + enable: false + +# Math (數學) +# -------------------------------------- +# About the per_page +# if you set it to true, it will load mathjax/katex script in each page (true 表示每一頁都加載js) +# if you set it to false, it will load mathjax/katex script according to your setting (add the 'mathjax: true' in page's front-matter) +# (false 需要時加載,須在使用的 Markdown Front-matter 加上 mathjax: true) + +# MathJax +mathjax: + enable: false + per_page: false + +# KaTeX +katex: + enable: false + per_page: false + hide_scrollbar: true + +# Image (圖片設置) +# -------------------------------------- + +# Favicon(網站圖標) +favicon: /img/favicon.png + +# Avatar (頭像) +avatar: + img: /images/v2-498e45cff82e401ae43378031b8fc740_1440w.jpg + effect: false + +# The banner image of home page +index_img: + +# If the banner of page not setting, it will show the top_img +default_top_img: /images/v2-1497fa6a5de2596909dc2af7a6233e37_1440w.jpg + +# The banner image of archive page +archive_img: + +# If the banner of tag page not setting, it will show the top_img +# note: tag page, not tags page (子標籤頁面的 top_img) +tag_img: + +# The banner image of tag page +# format: +# - tag name: xxxxx +tag_per_img: + +# If the banner of category page not setting, it will show the top_img +# note: category page, not categories page (子分類頁面的 top_img) +category_img: + +# The banner image of category page +# format: +# - category name: xxxxx +category_per_img: + +cover: + # display the cover or not (是否顯示文章封面) + index_enable: true + aside_enable: true + archives_enable: true + # the position of cover in home page (封面顯示的位置) + # left/right/both + position: both + # When cover is not set, the default cover is displayed (當沒有設置cover時,默認的封面顯示) + default_cover: + # - https://i.loli.net/2020/05/01/gkihqEjXxJ5UZ1C.jpg + +# Replace Broken Images (替換無法顯示的圖片) +error_img: + flink: /img/friend_404.gif + post_page: /img/404.jpg + +# A simple 404 page +error_404: + enable: false + subtitle: 'Page Not Found' + background: https://i.loli.net/2020/05/19/aKOcLiyPl2JQdFD.png + +post_meta: + page: # Home Page + date_type: created # created or updated or both 主頁文章日期是創建日或者更新日或都顯示 + date_format: date # date/relative 顯示日期還是相對日期 + categories: true # true or false 主頁是否顯示分類 + tags: false # true or false 主頁是否顯示標籤 + label: true # true or false 顯示描述性文字 + post: + date_type: both # created or updated or both 文章頁日期是創建日或者更新日或都顯示 + date_format: date # date/relative 顯示日期還是相對日期 + categories: true # true or false 文章頁是否顯示分類 + tags: true # true or false 文章頁是否顯示標籤 + label: true # true or false 顯示描述性文字 + +# wordcount (字數統計) +wordcount: + enable: false + post_wordcount: true + min2read: true + total_wordcount: true + +# Display the article introduction on homepage +# 1: description +# 2: both (if the description exists, it will show description, or show the auto_excerpt) +# 3: auto_excerpt (default) +# false: do not show the article introduction +index_post_content: + method: 3 + length: 500 # if you set method to 2 or 3, the length need to config + +# Post +# -------------------------------------- + +# toc (目錄) +toc: + enable: true + number: true + +post_copyright: + enable: true + decode: false + license: CC BY-NC-SA 4.0 + license_url: https://creativecommons.org/licenses/by-nc-sa/4.0/ + +# Sponsor/reward +reward: + enable: false + QR_code: + # - img: /img/wechat.jpg + # link: + # text: wechat + # - img: /img/alipay.jpg + # link: + # text: alipay + +# Related Articles +related_post: + enable: true + limit: 6 # Number of posts displayed + date_type: created # or created or updated 文章日期顯示創建日或者更新日 + +# figcaption (圖片描述文字) +photofigcaption: false + +# 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 + style: flat # style: simple/flat + limit_day: 500 # When will it be shown + position: top # position: top/bottom + message_prev: It has been + message_next: days since the last update, the content of the article may be outdated. + +# Share System (分享功能) +# -------------------------------------- + +# AddThis +# https://www.addthis.com/ +addThis: + enable: false + pubid: + +# Share.js +# https://github.com/overtrue/share.js +sharejs: + enable: true + sites: facebook,twitter,wechat,weibo,qq + +# AddToAny +# https://www.addtoany.com/ +addtoany: + enable: false + item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link + +# Comments System +# -------------------------------------- + +comments: + # Up to two comments system, the first will be shown as default + # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Utterances/Facebook Comments + 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 + lazyload: false + count: false # Display comment count in top_img + +# disqus +# https://disqus.com/ +disqus: + shortname: + +# Alternative Disqus - Render comments with Disqus API +# DisqusJS 評論系統,可以實現在網路審查地區載入 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: + +# livere (來必力) +# https://www.livere.com/ +livere: + uid: + +# gitalk +# https://github.com/gitalk/gitalk +gitalk: + client_id: + client_secret: + repo: + owner: + admin: + language: zh-CN # 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 + +# valine +# https://valine.js.org +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) + option: + +# utterances +# https://utteranc.es/ +utterances: + repo: + # Issue Mapping: pathname/url/title/og:title + issue_term: pathname + # Theme: github-light/github-dark/github-dark-orange/icy-dark/dark-blue/photon-dark + light_theme: github-light + dark_theme: photon-dark + +# Facebook Comments Plugin +# https://developers.facebook.com/docs/plugins/comments/ +facebook_comments: + app_id: + user_id: # optional + pageSize: 10 # The number of comments to show + order_by: social # social/time/reverse_time + lang: zh_CN # Language en_US/zh_CN/zh_TW and so on + +# Twikoo +# https://github.com/imaegoo/twikoo +twikoo: + +# Chat Services +# -------------------------------------- + +# Chat Button [recommend] +# It will create a button in the bottom right corner of website, and hide the origin button +chat_btn: false + +# The origin chat button is displayed when scrolling up, and the button is hidden when scrolling down +chat_hide_show: false + +# chatra +# https://chatra.io/ +chatra: + enable: false + id: + +# tidio +# https://www.tidio.com/ +tidio: + enable: false + public_key: + +# daovoice +# http://daovoice.io/ +daovoice: + enable: false + app_id: + +# gitter +# https://gitter.im/ +gitter: + enable: false + room: + +# crisp +# https://crisp.chat/en/ +crisp: + enable: false + website_id: + +# Footer Settings +# -------------------------------------- +footer: + owner: + enable: true + since: 2020 + custom_text: + copyright: true # Copyright of theme and framework + ICP: # Chinese ICP License + enable: false + url: + text: + icon: /img/icp.png + +# Analysis +# -------------------------------------- + +# Baidu Analytics +# https://tongji.baidu.com/web/welcome/login +baidu_analytics: + +# Google 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: + +# Advertisement +# -------------------------------------- + +# Google Adsense (谷歌廣告) +google_adsense: + enable: false + auto_ads: true + js: https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js + client: + enable_page_level_ads: true + +# Insert ads manually (手動插入廣告) +# ad: +# index: +# aside: +# post: + +# Verification (站長驗證) +# -------------------------------------- + +# Google Webmaster tools verification setting +# See: https://www.google.com/webmasters/ +google_site_verification: + +# Bing Webmaster tools verification setting +# See: https://www.bing.com/webmaster/ +bing_site_verification: + +# Baidu Webmaster tools verification setting +# See: https://ziyuan.baidu.com/site/ +baidu_site_verification: + +# 360 Webmaster tools verification setting +# see http://zhanzhang.so.com/ +qihu_site_verification: + +# Yandex Webmaster tools verification setting +# see https://webmaster.yandex.com/ +yandex_site_verification: + +# Beautify/Effect (美化/效果) +# -------------------------------------- + +# Theme color for customize +# Notice: color value must in double quotes like "#000" or may cause error! + +# theme_color: +# enable: true +# main: "#49B1F5" +# paginator: "#00c4b6" +# button_hover: "#FF7242" +# text_selection: "#00c4b6" +# link_color: "#99a9bf" +# meta_color: "#858585" +# hr_color: "#A4D8FA" +# code_foreground: "#F47466" +# code_background: "rgba(27, 31, 35, .05)" +# toc_color: "#00c4b6" +# blockquote_padding_color: "#49b1f5" +# blockquote_background_color: "#49b1f5" + +# The top_img settings of home page +# default: top img - full screen, site info - middle (默認top_img全屏,site_info在中間) +# The position of site info, eg: 300px/300em/300rem/10% (主頁標題距離頂部距離) +index_site_info_top: +# The height of top_img, eg: 300px/300em/300rem (主頁top_img高度) +index_top_img_height: + +# The user interface setting of category and tag page (category和tag頁的UI設置) +# index - same as Homepage UI (index 值代表 UI將與首頁的UI一樣) +# default - same as archives UI 默認跟archives頁面UI一樣 +category_ui: # 留空或 index +tag_ui: # 留空或 index + +# Website Background (設置網站背景) +# can set it to color or image (可設置圖片 或者 顔色) +# The formal of image: url(http://xxxxxx.com/xxx.jpg) +background: + +# Footer Background +footer_bg: false + +# the position of bottom right button/default unit: px (右下角按鈕距離底部的距離/默認單位為px) +rightside-bottom: + +# Enter transitions (開啓網頁進入效果) +enter_transitions: true + +# Background effects (背景特效) +# -------------------------------------- + +# canvas_ribbon (靜止彩帶背景) +# See: https://github.com/hustcc/ribbon.js +canvas_ribbon: + enable: false + size: 150 + alpha: 0.6 + zIndex: -1 + click_to_change: false + mobile: false + +# Fluttering Ribbon (動態彩帶) +canvas_fluttering_ribbon: + enable: false + mobile: false + +# canvas_nest +# https://github.com/hustcc/canvas-nest.js +canvas_nest: + enable: false + color: '0,0,255' #color of lines, default: '0,0,0'; RGB values: (R,G,B).(note: use ',' to separate.) + opacity: 0.7 # the opacity of line (0~1), default: 0.5. + zIndex: -1 # z-index property of the background, default: -1. + count: 99 # the number of lines, default: 99. + mobile: false + +# Typewriter Effect (打字效果) +# https://github.com/disjukr/activate-power-mode +activate_power_mode: + enable: false + colorful: true # open particle animation (冒光特效) + shake: true # open shake (抖動特效) + mobile: false + +# Mouse click effects: fireworks (鼠標點擊效果: 煙火特效) +fireworks: + enable: false + zIndex: 9999 # -1 or 9999 + mobile: false + +# Mouse click effects: Heart symbol (鼠標點擊效果: 愛心) +click_heart: + enable: false + mobile: false + +# Mouse click effects: words (鼠標點擊效果: 文字) +ClickShowText: + enable: false + text: + # - I + # - LOVE + # - YOU + fontSize: 15px + mobile: false + +# Default display mode (網站默認的顯示模式) +# light (default) / dark +display_mode: light + +# Beautify (美化頁面顯示) +beautify: + enable: false + field: post # site/post + title-prefix-icon: '\f0c1' + title-prefix-icon-color: '#F47466' + +# Global font settings +# Don't modify the following settings unless you know how they work (非必要不要修改) +font: + global-font-size: + code-font-size: + font-family: + code-font-family: + +# Font settings for the site title and site subtitle +# 左上角網站名字 主頁居中網站名字 +blog_title_font: + font_link: + font-family: + +# The setting of divider icon (水平分隔線圖標設置) +hr_icon: + enable: true + icon: # the unicode value of Font Awesome icon, such as '\3423' + icon-top: + +# the subtitle on homepage (主頁subtitle) +subtitle: + enable: false + # Typewriter Effect (打字效果) + effect: true + # loop (循環打字) + loop: true + # source調用第三方服務 + # source: false 關閉調用 + # source: 1 調用搏天api的隨機語錄(簡體) https://api.btstu.cn/ + # source: 2 調用一言網的一句話(簡體) https://hitokoto.cn/ + # source: 3 調用一句網(簡體) http://yijuzhan.com/ + # source: 4 調用今日詩詞(簡體) https://www.jinrishici.com/ + # subtitle 會先顯示 source , 再顯示 sub 的內容 + source: false + # 如果有英文逗號' , ',請使用轉義字元 , + # 如果有英文雙引號' " ',請使用轉義字元 " + # 開頭不允許轉義字元,如需要,請把整個句子用雙引號包住 + # 如果關閉打字效果,subtitle只會顯示sub的第一行文字 + sub: + +# Loading Animation (加載動畫) +preloader: true + +# aside (側邊欄) +# -------------------------------------- + +aside: + enable: true + hide: false + button: true + mobile: true # display on mobile + position: right # left or right + card_author: + enable: true + description: + button: + icon: fab fa-github + text: Follow Me + link: https://github.com/dengtongyu + card_announcement: + enable: true + content: 世界纷纷扰扰,我只想做一个安静的攻城狮。 + card_recent_post: + enable: true + limit: 5 # if set 0 will show all + sort: date # date or updated + card_categories: + enable: true + limit: 8 # if set 0 will show all + expand: none # none/true/false + card_tags: + enable: true + limit: 40 # if set 0 will show all + color: false + card_archives: + enable: true + type: monthly # yearly or monthly + format: MMMM YYYY # eg: YYYY年MM月 + order: -1 # Sort of order. 1, asc for ascending; -1, desc for descending + limit: 8 # if set 0 will show all + card_webinfo: + enable: true + post_count: true + last_push_date: true + +# busuanzi count for PV / UV in site +# 訪問人數 +busuanzi: + site_uv: true + site_pv: true + page_pv: true + +# Time difference between publish date and now (網頁運行時間) +# Formal: Month/Day/Year Time or Year/Month/Day Time +runtimeshow: + enable: false + publish_date: + +# Aside widget - Newest Comments +newest_comments: + enable: false + limit: 6 + avatar: true + leancloud: + enable: false + appId: # leancloud application app id + appKey: # leancloud application app key + serverURL: # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in) + default_avatar: # mp/identicon/monsterid/wavatar/retro/robohash/blank + github_issues: + enable: false + repo: + disqus: + enable: false + forum: + api_key: + +# Bottom right button (右下角按鈕) +# -------------------------------------- + +# Conversion between Traditional and Simplified Chinese (簡繁轉換) +translate: + enable: false + # The text of a button + default: 繁 + # the language of website (1 - Traditional Chinese/ 2 - Simplified Chinese) + defaultEncoding: 2 + # Time delay + translateDelay: 0 + # The text of the button when the language is Simplified Chinese + msgToTraditionalChinese: '繁' + # The text of the button when the language is Traditional Chinese + msgToSimplifiedChinese: '簡' + +# Read Mode (閲讀模式) +readmode: true + +# dark mode +darkmode: + enable: true + # Toggle Button to switch dark/light mode + button: true + # Switch dark/light mode automatically (自動切換 dark mode和 light mode) + # autoChangeMode: 1 Following System Settings, if the system doesn't support dark mode, it will switch dark mode between 6 pm to 6 am + # autoChangeMode: 2 Switch dark mode between 6 pm to 6 am + # autoChangeMode: false + autoChangeMode: false + +# Lightbox (圖片大圖查看模式) +# -------------------------------------- +# You can only choose one, or neither (只能選擇一個 或者 兩個都不選) + +# medium-zoom +# https://github.com/francoischalifour/medium-zoom +medium_zoom: false + +# fancybox +# http://fancyapps.com/fancybox/3/ +fancybox: true + +# Tag Plugins settings (標籤外掛) +# -------------------------------------- + +# mermaid +# see https://github.com/knsv/mermaid +mermaid: + enable: false + # built-in themes: default/forest/dark/neutral + theme: default + +# Note (Bootstrap Callout) +note: + # Note tag style values: + # - simple bs-callout old alert style. Default. + # - modern bs-callout new (v2-v3) alert style. + # - flat flat callout style with background, like on Mozilla or StackOverflow. + # - disabled disable all CSS styles import of note tag. + style: flat + icons: true + border_radius: 3 + # Offset lighter of background in % for modern and flat styles (modern: -12 | 12; flat: -18 | 6). + # Offset also applied to label tag variables. This option can work with disabled note tag. + light_bg_offset: 0 + +# other +# -------------------------------------- + +# Artitalk +# see https://artitalk.js.org/ +artitalk: + appId: + appKey: + option: + +# Pjax [Beta] +# It may contain bugs and unstable, give feedback when you find the bugs. +# https://github.com/MoOx/pjax +pjax: + enable: false + exclude: + # - xxxx + # - xxxx + +# Inject the css and script (aplayer/meting) +aplayerInject: + enable: false + per_page: true + +# Snackbar (Toast Notification 彈窗) +# https://github.com/polonel/SnackBar +# position 彈窗位置 +# 可選 top-left / top-center / top-right / bottom-left / bottom-center / bottom-right +snackbar: + enable: false + position: bottom-left + bg_light: '#49b1f5' # The background color of Toast Notification in light mode + bg_dark: '#121212' # The background color of Toast Notification in dark mode + +# Baidu Push (百度推送) +baidu_push: false + +# https://instant.page/ +# prefetch (預加載) +instantpage: false + +# https://github.com/vinta/pangu.js +# Insert a space between Chinese character and English character (中英文之間添加空格) +pangu: + enable: false + field: site # site/post + +# Lazyload (圖片懶加載) +# https://github.com/verlok/lazyload +lazyload: + enable: false + post: /img/loading.gif + +# PWA +# See https://github.com/JLHwung/hexo-offline +# --------------- +# pwa: +# enable: false +# manifest: /image/pwa/manifest.json +# apple_touch_icon: /image/pwa/apple-touch-icon.png +# favicon_32_32: /image/pwa/32.png +# favicon_16_16: /image/pwa/16.png +# mask_icon: /image/pwa/safari-pinned-tab.svg + +# Disable Baidu transformation on mobile devices (禁止百度轉碼) +disable_baidu_transformation: true + +# Open graph meta tags +# https://developers.facebook.com/docs/sharing/webmasters/ +Open_Graph_meta: true + +# Caches the contents in a fragment, speed up the generation (開啟hexo自帶的緩存,加快生成速度) +fragment_cache: true + +# Inject +# Insert the code to head (before '' tag) and the bottom (before '' tag) +# 插入代码到头部 之前 和 底部 之前 +inject: + head: + # - + bottom: + # - + +# CDN +# Don't modify the following settings unless you know how they work +# 非必要請不要修改 +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 + + # 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 + 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 + + # 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: 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 + + # 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-copytex@latest/dist/katex-copytex.min.js + katex_copytex_css: https://cdn.jsdelivr.net/npm/katex-copytex@latest/dist/katex-copytex.min.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: 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 + + # 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 + + # 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 + + # 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 + + artitalk: https://cdn.jsdelivr.net/npm/artitalk diff --git a/themes/butterfly/languages/default.yml b/themes/butterfly/languages/default.yml new file mode 100644 index 0000000..d1699c3 --- /dev/null +++ b/themes/butterfly/languages/default.yml @@ -0,0 +1,114 @@ +footer: + framework: Framework + theme: Theme + +copy: + success: Copy successfully + error: Copy error + noSupport: The browser does not support + +page: + articles: Articles + tag: Tag + category: Category + archives: Archives + +sticky: Sticky +no_title: No title + +post: + created: Created + updated: Updated + wordcount: Word count + min2read: Reading time + min2read_unit: min + page_pv: Post View + comments: Comments + copyright: + author: Author + link: Link + copyright_notice: Copyright Notice + copyright_content: 'All articles in this blog are licensed under %s unless stating additionally.' + recommend: Related Articles + +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}" + powered_by: Powered by + +pagination: + prev: Previous Post + next: Next Post + +comment: Comment + +aside: + articles: Articles + tags: Tags + categories: Categories + card_announcement: Announcement + card_categories: Categories + card_tags: Tags + card_archives: Archives + card_recent_post: Recent Post + card_webinfo: + headline: Info + article_name: Article + runtime: + name: Run time + unit: days + last_push_date: + name: Last Push + site_wordcount: Total Count + site_uv_name: UV + site_pv_name: PV + more_button: More + card_newest_comments: + headline: Newest Comments + loading_text: loading... + error: Unable to get the data, please make sure the settings are correct. + card_toc: Catalog + +date_suffix: + just: Just + min: minutes ago + hour: hours ago + day: days ago + month: months ago + +donate: Donate +share: Share + +rightside: + readmode_title: Read Mode + translate_title: Switch Between Traditional Chinese And Simplified Chinese + night_mode_title: Switch Between Light And Dark Mode + back_to_top: Back To Top + toc: Table Of Contents + scroll_to_comment: Scroll To Comments + setting: Setting + +copy_copyright: + author: Author + link: Link + source: Source + info: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source. + +Snackbar: + chs_to_cht: Traditional Chinese Activated Manually + cht_to_chs: Simplified Chinese Activated Manually + day_to_night: Dark Mode Activated Manually + night_to_day: Light Mode Activated Manually + +loading: Loading... + +error404: + error_title: Page not found + back_button: Go back home diff --git a/themes/butterfly/languages/en.yml b/themes/butterfly/languages/en.yml new file mode 100644 index 0000000..d1699c3 --- /dev/null +++ b/themes/butterfly/languages/en.yml @@ -0,0 +1,114 @@ +footer: + framework: Framework + theme: Theme + +copy: + success: Copy successfully + error: Copy error + noSupport: The browser does not support + +page: + articles: Articles + tag: Tag + category: Category + archives: Archives + +sticky: Sticky +no_title: No title + +post: + created: Created + updated: Updated + wordcount: Word count + min2read: Reading time + min2read_unit: min + page_pv: Post View + comments: Comments + copyright: + author: Author + link: Link + copyright_notice: Copyright Notice + copyright_content: 'All articles in this blog are licensed under %s unless stating additionally.' + recommend: Related Articles + +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}" + powered_by: Powered by + +pagination: + prev: Previous Post + next: Next Post + +comment: Comment + +aside: + articles: Articles + tags: Tags + categories: Categories + card_announcement: Announcement + card_categories: Categories + card_tags: Tags + card_archives: Archives + card_recent_post: Recent Post + card_webinfo: + headline: Info + article_name: Article + runtime: + name: Run time + unit: days + last_push_date: + name: Last Push + site_wordcount: Total Count + site_uv_name: UV + site_pv_name: PV + more_button: More + card_newest_comments: + headline: Newest Comments + loading_text: loading... + error: Unable to get the data, please make sure the settings are correct. + card_toc: Catalog + +date_suffix: + just: Just + min: minutes ago + hour: hours ago + day: days ago + month: months ago + +donate: Donate +share: Share + +rightside: + readmode_title: Read Mode + translate_title: Switch Between Traditional Chinese And Simplified Chinese + night_mode_title: Switch Between Light And Dark Mode + back_to_top: Back To Top + toc: Table Of Contents + scroll_to_comment: Scroll To Comments + setting: Setting + +copy_copyright: + author: Author + link: Link + source: Source + info: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source. + +Snackbar: + chs_to_cht: Traditional Chinese Activated Manually + cht_to_chs: Simplified Chinese Activated Manually + day_to_night: Dark Mode Activated Manually + night_to_day: Light Mode Activated Manually + +loading: Loading... + +error404: + error_title: Page not found + back_button: Go back home diff --git a/themes/butterfly/languages/zh-CN.yml b/themes/butterfly/languages/zh-CN.yml new file mode 100644 index 0000000..2a1a762 --- /dev/null +++ b/themes/butterfly/languages/zh-CN.yml @@ -0,0 +1,116 @@ +footer: + framework: 框架 + theme: 主题 + +copy: + success: 复制成功 + error: 复制错误 + noSupport: 浏览器不支持 + +page: + articles: 文章总览 + tag: 标签 + category: 分类 + archives: 归档 + +sticky: 置顶 +no_title: 无题 + +post: + created: 发表于 + updated: 更新于 + wordcount: 字数总计 + min2read: 阅读时长 + min2read_unit: 分钟 + page_pv: 阅读量 + comments: 评论数 + copyright: + author: 文章作者 + link: 文章链接 + copyright_notice: 版权声明 + copyright_content: '本博客所有文章除特别声明外,均采用 + %s 许可协议。转载请注明来自 %s!' + recommend: 相关推荐 + +search: 搜索 +algolia_search: + input_placeholder: 搜索文章 + hits_empty: '找不到您查询的内容:${query}' + hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' + +local_search: + label: 本地搜索 + input_placeholder: 搜索文章 + hits_empty: '找不到您查询的内容:${query}' + powered: '提供支持' + by: 由 + +pagination: + prev: 上一篇 + next: 下一篇 + +comment: 评论 + +aside: + articles: 文章 + tags: 标签 + categories: 分类 + card_announcement: 公告 + card_categories: 分类 + card_tags: 标签 + card_archives: 归档 + card_recent_post: 最新文章 + card_webinfo: + headline: 网站资讯 + article_name: 文章数目 + runtime: + name: 已运行时间 + unit: 天 + last_push_date: + name: 最后更新时间 + site_wordcount: 本站总字数 + site_uv_name: 本站访客数 + site_pv_name: 本站总访问量 + more_button: 查看更多 + card_newest_comments: + headline: 最新评论 + loading_text: 正在加载中... + error: 无法获取资料,请确认相关配置是否正确 + card_toc: 目录 + +date_suffix: + just: 刚刚 + min: 分钟前 + hour: 小时前 + day: 天前 + month: 个月前 + +donate: 打赏 +share: 分享 + +rightside: + readmode_title: 阅读模式 + translate_title: 简繁转换 + night_mode_title: 浅色和深色模式转换 + back_to_top: 回到顶部 + toc: 目录 + scroll_to_comment: 直达评论 + setting: 设置 + +copy_copyright: + author: 作者 + link: 链接 + source: 来源 + info: 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 + +Snackbar: + chs_to_cht: 你已切换为繁体 + cht_to_chs: 你已切换为简体 + day_to_night: 你已切换为深色模式 + night_to_day: 你已切换为浅色模式 + +loading: 加载中... + +error404: + error_title: 页面没有找到 + back_button: 回到主页 diff --git a/themes/butterfly/languages/zh-TW.yml b/themes/butterfly/languages/zh-TW.yml new file mode 100644 index 0000000..2b30d2a --- /dev/null +++ b/themes/butterfly/languages/zh-TW.yml @@ -0,0 +1,116 @@ +footer: + framework: 框架 + theme: 主題 + +copy: + success: 複製成功 + error: 複製錯誤 + noSupport: 瀏覽器不支援 + +page: + articles: 文章總覽 + tag: 標籤 + category: 分類 + archives: 歸檔 + +sticky: 置頂 +no_title: 無題 + +post: + created: 發表於 + updated: 更新於 + wordcount: 字數總計 + min2read: 閲讀時長 + min2read_unit: 分鐘 + page_pv: 閱讀量 + comments: 評論數 + copyright: + author: 文章作者 + link: 文章連結 + copyright_notice: 版權聲明 + copyright_content: '本部落格所有文章除特別聲明外,均採用 + %s 許可協議。轉載請註明來自 %s!' + recommend: 相關推薦 + +search: 搜尋 +algolia_search: + input_placeholder: 搜尋文章 + hits_empty: '找不到您查詢的內容:${query}' + hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' + +local_search: + label: 本地搜尋 + input_placeholder: 搜尋文章 + hits_empty: '找不到您查詢的內容:${query}' + powered: '提供支援' + by: 由 + +pagination: + prev: 上一篇 + next: 下一篇 + +comment: 評論 + +aside: + articles: 文章 + tags: 標籤 + categories: 分類 + card_announcement: 公告 + card_categories: 分類 + card_tags: 標籤 + card_archives: 歸檔 + card_recent_post: 最新文章 + card_webinfo: + headline: 網站資訊 + article_name: 文章數目 + runtime: + name: 已運行時間 + unit: 天 + last_push_date: + name: 最後更新時間 + site_wordcount: 本站總字數 + site_uv_name: 本站訪客數 + site_pv_name: 本站總訪問量 + more_button: 檢視更多 + card_newest_comments: + headline: 最新評論 + loading_text: 正在加載中... + error: 無法獲取資料,請確認相關配置是否正確 + card_toc: 目錄 + +date_suffix: + just: 剛剛 + min: 分鐘前 + hour: 小時前 + day: 天前 + month: 個月前 + +donate: 打賞 +share: 分享 + +rightside: + readmode_title: 閱讀模式 + translate_title: 簡繁轉換 + night_mode_title: 淺色和深色模式轉換 + back_to_top: 回到頂部 + toc: 目錄 + scroll_to_comment: 直達評論 + setting: 設定 + +copy_copyright: + author: 作者 + link: 連結 + source: 來源 + info: 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。 + +Snackbar: + chs_to_cht: 你已切換為繁體 + cht_to_chs: 你已切換為簡體 + day_to_night: 你已切換為深色模式 + night_to_day: 你已切換為淺色模式 + +loading: 載入中... + +error404: + error_title: 頁面沒有找到 + back_button: 回到主頁 diff --git a/themes/butterfly/layout/404.pug b/themes/butterfly/layout/404.pug new file mode 100644 index 0000000..364b7cf --- /dev/null +++ b/themes/butterfly/layout/404.pug @@ -0,0 +1,28 @@ +- var top_img = theme.error_404.background || theme.default_top_img +- var bg_img = `background-image: url(${url_for(top_img)})` + +doctype html +html(lang=config.language data-theme=theme.display_mode) + head + include includes/head.pug + body + if theme.preloader + !=partial('includes/loading/loading', {}, {cache:theme.fragment_cache}) + + if theme.fireworks && theme.fireworks.enable + canvas.fireworks + + if theme.background + #web_bg + + #error-wrap + .error-content + .error-img(style=bg_img) + .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') + + include includes/additional-js.pug diff --git a/themes/butterfly/layout/archive.pug b/themes/butterfly/layout/archive.pug new file mode 100644 index 0000000..faa485c --- /dev/null +++ b/themes/butterfly/layout/archive.pug @@ -0,0 +1,8 @@ +extends includes/layout.pug + +block content + include ./includes/mixins/article-sort.pug + #archive + .article-sort-title= _p('page.articles') + ' - ' + site.posts.length + +articleSort(page.posts) + include includes/pagination.pug \ No newline at end of file diff --git a/themes/butterfly/layout/category.pug b/themes/butterfly/layout/category.pug new file mode 100644 index 0000000..01ad990 --- /dev/null +++ b/themes/butterfly/layout/category.pug @@ -0,0 +1,14 @@ +extends includes/layout.pug + +block content + if theme.category_ui == 'index' + include ./includes/mixins/post-ui.pug + #recent-posts.recent-posts.category_ui + +postUI + include includes/pagination.pug + else + include ./includes/mixins/article-sort.pug + #category + .article-sort-title= _p('page.category') + ' - ' + page.category + +articleSort(page.posts) + include includes/pagination.pug \ No newline at end of file diff --git a/themes/butterfly/layout/includes/additional-js.pug b/themes/butterfly/layout/includes/additional-js.pug new file mode 100644 index 0000000..8d912b7 --- /dev/null +++ b/themes/butterfly/layout/includes/additional-js.pug @@ -0,0 +1,74 @@ +div + script(src=url_for(theme.CDN.jquery)) + script(src=url_for(theme.CDN.utils)) + script(src=url_for(theme.CDN.main)) + + if theme.translate && theme.translate.enable + script(src=url_for(theme.CDN.translate)) + + if theme.medium_zoom + script(src=url_for(theme.CDN.medium_zoom)) + else if theme.fancybox + script(src=url_for(theme.CDN.fancybox)) + + if theme.instantpage + script(src=url_for(theme.CDN.instantpage) type="module" defer) + + if theme.lazyload.enable + script(src=url_for(theme.CDN.lazyload)) + + if (theme.snackbar && theme.snackbar.enable) + script(src=url_for(theme.CDN.snackbar)) + + if theme.pangu && theme.pangu.enable + !=partial('includes/third-party/pangu.pug', {}, {cache:theme.fragment_cache}) + + //- search + if theme.algolia_search.enable + 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:theme.fragment_cache}) + + .js-pjax + if theme.subtitle.enable && is_home() && theme.index_img !== false + include ./third-party/subtitle.pug + + if page.type === 'artitalk' + include ./third-party/artitalk.pug + + include ./third-party/math/index.pug + + if commentsJsLoad + include ./third-party/comments/js.pug + + if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv + script(async src=url_for(theme.CDN.busuanzi)) + + !=partial('includes/third-party/prismjs', {}, {cache:theme.fragment_cache}) + + if theme.aside.enable && theme.newest_comments.enable + if theme.pjax.enable + !=partial('includes/third-party/newest-comments/index', {}, {cache:theme.fragment_cache}) + else if (!is_post() && page.aside !== false) + !=partial('includes/third-party/newest-comments/index', {}, {cache:theme.fragment_cache}) + + !=fragment_cache('injectBottom', function(){return injectHtml(theme.inject.bottom)}) + + !=partial('includes/third-party/effect', {}, {cache:theme.fragment_cache}) + + !=partial('includes/third-party/chat/index', {}, {cache:theme.fragment_cache}) + + if theme.aplayerInject && theme.aplayerInject.enable + if theme.pjax.enable || theme.aplayerInject.per_page + include ./third-party/aplayer.pug + else if page.aplayer + include ./third-party/aplayer.pug + + if theme.pjax.enable + !=partial('includes/third-party/pjax', {}, {cache:theme.fragment_cache}) + + !=partial('includes/third-party/baidu_push', {}, {cache:theme.fragment_cache}) + \ No newline at end of file diff --git a/themes/butterfly/layout/includes/footer.pug b/themes/butterfly/layout/includes/footer.pug new file mode 100644 index 0000000..fc612f9 --- /dev/null +++ b/themes/butterfly/layout/includes/footer.pug @@ -0,0 +1,23 @@ +#footer-wrap + if theme.footer.owner.enable + - var now = new Date() + - var nowYear = now.getFullYear() + if theme.footer.owner.since && theme.footer.owner.since != nowYear + .copyright!= `©${theme.footer.owner.since} - ${nowYear} By ${config.author}` + else + .copyright!= `©${nowYear} By ${config.author}` + if theme.footer.copyright + .framework-info + span= _p('footer.framework') + ' ' + a(href='https://hexo.io')= 'Hexo' + span.footer-separator | + span= _p('footer.theme') + ' ' + a(href='https://github.com/jerryc127/hexo-theme-butterfly')= 'Butterfly' + if theme.footer.custom_text + .footer_custom_text!=`${theme.footer.custom_text}` + if theme.footer.ICP.enable + .icp + a(href=theme.footer.ICP.url) + if theme.footer.ICP.icon + img.icp-icon(src=url_for(theme.footer.ICP.icon) alt='ICP') + span=theme.footer.ICP.text diff --git a/themes/butterfly/layout/includes/head.pug b/themes/butterfly/layout/includes/head.pug new file mode 100644 index 0000000..ec8a57a --- /dev/null +++ b/themes/butterfly/layout/includes/head.pug @@ -0,0 +1,84 @@ +- var pageTitle +- if (is_archive()) pageTitle = _p('page.archives') +- else if (is_tag()) pageTitle = _p('page.tag') + ': ' + page.tag +- 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 pageTitle = page.title || config.title || '' + +- var isSubtitle = config.subtitle ? ' - ' + config.subtitle : '' +- var tabTitle = is_home() || !pageTitle ? config.title + isSubtitle : pageTitle + ' | ' + config.title + +- var pageKeywords +- if (page.keywords) pageKeywords = Array.isArray(page.keywords) ? (page.keywords).join(',') : ([]).join(',') || page.keywords +- else if (page.tags && page.tags.length) pageKeywords = page.tags.data.map(function(tag) {return tag.name;}).join(',') +- else pageKeywords = Array.isArray(config.keywords) ? (config.keywords).join(','): ([]).join(',') || config.keywords +- var pageAuthor = config.email ? config.author + ',' + config.email : config.author +- var pageCopyright = config.copyright || config.author +- var themeColor = theme.display_mode === 'dark' ? '#0d0d0d' : '#ffffff' + +meta(charset='UTF-8') +meta(http-equiv="X-UA-Compatible" content="IE=edge") +meta(name="viewport" content="width=device-width,initial-scale=1") +title= tabTitle +if pageKeywords + meta(name="keywords" content=pageKeywords) +meta(name="author" content=pageAuthor) +meta(name="copyright" content=pageCopyright) +meta(name ="format-detection" content="telephone=no") +meta(name="theme-color" content=themeColor) + +if theme.disable_baidu_transformation + meta(http-equiv="Cache-Control" content="no-transform") + meta(http-equiv="Cache-Control" content="no-siteapp") + +//- Open_Graph +include ./head/Open_Graph.pug + +!=favicon_tag(theme.favicon || config.favicon) +link(rel="canonical" href=urlNoIndex()) + +//- 預解析 +!=partial('includes/head/preconnect', {}, {cache:theme.fragment_cache}) + +//- 網站驗證 +!=partial('includes/head/site_verification', {}, {cache:theme.fragment_cache}) + +//- PWA +if (theme.pwa && theme.pwa.enable) + !=partial('includes/head/pwa', {}, {cache:theme.fragment_cache}) + +//- main css +link(rel='stylesheet', href=url_for(theme.CDN.main_css)) +link(rel='stylesheet', href=url_for(theme.CDN.fontawesome)) + +if theme.fancybox + link(rel='stylesheet', href=url_for(theme.CDN.fancybox_css)) + +if (theme.snackbar && theme.snackbar.enable) + link(rel='stylesheet', href=url_for(theme.CDN.snackbar_css)) + +if theme.algolia_search.enable + link(rel='stylesheet' href=url_for(theme.CDN.algolia_search_css)) + script(src=url_for(theme.CDN.algolia_search) defer) + +//- google_adsense +!=partial('includes/head/google_adsense', {}, {cache:theme.fragment_cache}) + +//- analytics +!=partial('includes/head/analytics', {}, {cache:theme.fragment_cache}) + +//- font +if theme.blog_title_font && theme.blog_title_font.font_link + link(rel='stylesheet' href=url_for(theme.blog_title_font.font_link)) + +//- global config +!=partial('includes/head/config', {}, {cache:theme.fragment_cache}) + +include ./head/config_site.pug +include ./head/noscript.pug + +!=partial('includes/head/js', {}, {cache:theme.fragment_cache}) + +!=fragment_cache('injectHead', function(){return injectHtml(theme.inject.head)}) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/head/Open_Graph.pug b/themes/butterfly/layout/includes/head/Open_Graph.pug new file mode 100644 index 0000000..7d5c59c --- /dev/null +++ b/themes/butterfly/layout/includes/head/Open_Graph.pug @@ -0,0 +1,11 @@ +if theme.Open_Graph_meta + - let contentType = is_post() ? 'article' : 'website' + - let metaImage = full_url_for(page.cover || theme.avatar.img) + - let fb_appId = theme.facebook_comments.app_id || '' + - let fb_admins = theme.facebook_comments.user_id || '' + + != open_graph({type: contentType, image: metaImage, fb_admins: fb_admins, fb_app_id: fb_appId}) + +else + meta(name="description" content=page_description()) + diff --git a/themes/butterfly/layout/includes/head/analytics.pug b/themes/butterfly/layout/includes/head/analytics.pug new file mode 100644 index 0000000..f4379b5 --- /dev/null +++ b/themes/butterfly/layout/includes/head/analytics.pug @@ -0,0 +1,32 @@ +if theme.baidu_analytics + script. + var _hmt = _hmt || []; + (function() { + var hm = document.createElement("script"); + hm.src = "https://hm.baidu.com/hm.js?!{theme.baidu_analytics}"; + var s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(hm, s); + })(); + +if theme.google_analytics + script(async src=`https://www.googletagmanager.com/gtag/js?id=${theme.google_analytics}`) + script. + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', '!{theme.google_analytics}'); + +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/themes/butterfly/layout/includes/head/config.pug b/themes/butterfly/layout/includes/head/config.pug new file mode 100644 index 0000000..99e3001 --- /dev/null +++ b/themes/butterfly/layout/includes/head/config.pug @@ -0,0 +1,160 @@ +- + let algolia = 'undefined'; + let env = process.env; + if (theme.algolia_search.enable) { + algolia = JSON.stringify({ + appId: env.ALGOLIA_APP_ID || config.algolia.appId || config.algolia.applicationID, + apiKey: env.ALGOLIA_API_KEY || config.algolia.apiKey, + indexName: env.ALGOLIA_INDEX_NAME || config.algolia.indexName, + 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") + } + }) + } + + let localSearch = 'undefined'; + if (theme.local_search && theme.local_search.enable) { + localSearch = JSON.stringify({ + path: config.search.path, + languages: { + // search languages + hits_empty: _p("local_search.hits_empty") + } + }) + } + + let translate = 'undefined'; + if (theme.translate && theme.translate.enable){ + translate = JSON.stringify({ + defaultEncoding: theme.translate.defaultEncoding, + translateDelay: theme.translate.translateDelay, + msgToTraditionalChinese: theme.translate.msgToTraditionalChinese, + msgToSimplifiedChinese: theme.translate.msgToSimplifiedChinese + }) + } + + let copyright = 'undefined'; + if (theme.copy.enable && theme.copy.copyright.enable){ + copyright = JSON.stringify({ + limitCount: theme.copy.copyright.limit_count, + languages: { + author: _p("copy_copyright.author") + ': ' + config.author, + link: _p("copy_copyright.link") + ': ', + source: _p("copy_copyright.source") + ': ' + config.title, + info: _p("copy_copyright.info") + } + }) + } + + let ClickShowText = 'undefined'; + if (theme.ClickShowText && theme.ClickShowText.enable) { + ClickShowText = JSON.stringify({ + text: theme.ClickShowText.text.join(","), + fontSize: theme.ClickShowText.fontSize + }) + } + + let Snackbar = 'undefined'; + if (theme.snackbar && theme.snackbar.enable) { + Snackbar = JSON.stringify({ + chs_to_cht: _p("Snackbar.chs_to_cht"), + cht_to_chs: _p("Snackbar.cht_to_chs"), + day_to_night: _p("Snackbar.day_to_night"), + night_to_day: _p("Snackbar.night_to_day"), + bgLight: theme.snackbar.bg_light, + bgDark: theme.snackbar.bg_dark, + position: theme.snackbar.position, + }) + } + + let noticeOutdate = 'undefined'; + if (theme.noticeOutdate && theme.noticeOutdate.enable) { + noticeOutdate = JSON.stringify({ + limitDay: theme.noticeOutdate.limit_day, + position: theme.noticeOutdate.position, + messagePrev: theme.noticeOutdate.message_prev, + messageNext: theme.noticeOutdate.message_next, + }) + } + + let highlight = 'undefined'; + if ((config.highlight && config.highlight.enable) || (config.prismjs && config.prismjs.enable)) { + highlight = JSON.stringify({ + plugin: config.highlight.enable ? 'highlighjs' : 'prismjs', + highlightCopy: theme.highlight_copy, + highlightLang: theme.highlight_lang + }) + } + +script. + var GLOBAL_CONFIG = { + root: '!{config.root}', + algolia: !{algolia}, + localSearch: !{localSearch}, + translate: !{translate}, + noticeOutdate: !{noticeOutdate}, + highlight: !{highlight}, + copy: { + success: '!{_p("copy.success")}', + error: '!{_p("copy.error")}', + noSupport: '!{_p("copy.noSupport")}' + }, + relativeDate: { + homepage: !{theme.post_meta.page.date_format === 'relative'}, + post: !{theme.post_meta.post.date_format === 'relative'} + }, + runtime: '!{theme.runtimeshow.enable ? _p("aside.card_webinfo.runtime.unit") : ""}', + date_suffix: { + just: '!{_p("date_suffix.just")}', + min: '!{_p("date_suffix.min")}', + hour: '!{_p("date_suffix.hour")}', + day: '!{_p("date_suffix.day")}', + month: '!{_p("date_suffix.month")}' + }, + copyright: !{copyright}, + ClickShowText: !{ClickShowText}, + lightbox: '!{ theme.medium_zoom ? "mediumZoom" : (theme.fancybox ? "fancybox" : "null" )}', + Snackbar: !{Snackbar}, + justifiedGallery: { + js: '!{theme.CDN.justifiedGallery_js}', + css: '!{theme.CDN.justifiedGallery_css}' + }, + isPhotoFigcaption: !{theme.photofigcaption}, + islazyload: !{theme.lazyload.enable}, + isanchor: !{theme.anchor} + }; + + var saveToLocal = { + set: function setWithExpiry(key, value, ttl) { + const now = new Date() + const expiryDay = ttl * 86400000 + const item = { + value: value, + expiry: now.getTime() + expiryDay, + } + localStorage.setItem(key, JSON.stringify(item)) + }, + + get: function getWithExpiry(key) { + const itemStr = localStorage.getItem(key) + + if (!itemStr) { + return undefined + } + const item = JSON.parse(itemStr) + const now = new Date() + + if (now.getTime() > item.expiry) { + localStorage.removeItem(key) + return undefined + } + return item.value + } + } + + + diff --git a/themes/butterfly/layout/includes/head/config_site.pug b/themes/butterfly/layout/includes/head/config_site.pug new file mode 100644 index 0000000..19eb732 --- /dev/null +++ b/themes/butterfly/layout/includes/head/config_site.pug @@ -0,0 +1,19 @@ +- + 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 + + const pageToc = page.toc === true || page.toc === false ? page.toc : theme.toc.enable + const showToc = is_post() && theme.aside.enable && pageToc && (toc(page.content) !== '' || page.encrypt == true ) +- + +script#config_change + . + var GLOBAL_CONFIG_SITE = { + isPost: !{is_post()}, + isHome: !{is_home()}, + isHighlightShrink: !{isHighlightShrink}, + isToc: !{showToc}, + postUpdate: '!{full_date(page.updated)}' + } diff --git a/themes/butterfly/layout/includes/head/google_adsense.pug b/themes/butterfly/layout/includes/head/google_adsense.pug new file mode 100644 index 0000000..3ef1af9 --- /dev/null +++ b/themes/butterfly/layout/includes/head/google_adsense.pug @@ -0,0 +1,9 @@ +if (theme.google_adsense && theme.google_adsense.enable) + script(async src=theme.google_adsense.js) + + if theme.google_adsense.auto_ads + script. + (adsbygoogle = window.adsbygoogle || []).push({ + google_ad_client: '!{theme.google_adsense.client}', + enable_page_level_ads: '!{theme.google_adsense.enable_page_level_ads}' + }); \ No newline at end of file diff --git a/themes/butterfly/layout/includes/head/js.pug b/themes/butterfly/layout/includes/head/js.pug new file mode 100644 index 0000000..058b80a --- /dev/null +++ b/themes/butterfly/layout/includes/head/js.pug @@ -0,0 +1,65 @@ +script + | (function () { + + if theme.darkmode.enable + | window.activateDarkMode = function () { + | document.documentElement.setAttribute('data-theme', 'dark') + | if (document.querySelector('meta[name="theme-color"]') !== null) { + | document.querySelector('meta[name="theme-color"]').setAttribute('content', '#0d0d0d') + | } + | } + | window.activateLightMode = function () { + | document.documentElement.setAttribute('data-theme', 'light') + | if (document.querySelector('meta[name="theme-color"]') !== null) { + | document.querySelector('meta[name="theme-color"]').setAttribute('content', '#ffffff') + | } + | } + + | const autoChangeMode = '#{theme.darkmode.autoChangeMode}' + | const t = saveToLocal.get('theme') + | if (autoChangeMode === '1') { + | const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches + | const isLightMode = window.matchMedia('(prefers-color-scheme: light)').matches + | const isNotSpecified = window.matchMedia('(prefers-color-scheme: no-preference)').matches + | const hasNoSupport = !isDarkMode && !isLightMode && !isNotSpecified + + | if (t === undefined) { + | if (isLightMode) activateLightMode() + | else if (isDarkMode) activateDarkMode() + | else if (isNotSpecified || hasNoSupport) { + | const now = new Date() + | const hour = now.getHours() + | const isNight = hour <= 6 || hour >= 18 + | isNight ? activateDarkMode() : activateLightMode() + | } + | window.matchMedia('(prefers-color-scheme: dark)').addListener(function (e) { + | if (saveToLocal.get('theme') === undefined) { + | e.matches ? activateDarkMode() : activateLightMode() + | } + | }) + | } else if (t === 'light') activateLightMode() + | else activateDarkMode() + | } else if (autoChangeMode === '2') { + | const now = new Date() + | const hour = now.getHours() + | const isNight = hour <= 6 || hour >= 18 + | if (t === undefined) isNight ? activateDarkMode() : activateLightMode() + | else if (t === 'light') activateLightMode() + | else activateDarkMode() + | } else { + | if (t === 'dark') activateDarkMode() + | else if (t === 'light') activateLightMode() + | } + + if theme.aside.enable && theme.aside.button + | const asideStatus = saveToLocal.get('aside-status') + | if (asideStatus !== undefined) { + | if (asideStatus === 'hide') { + | document.documentElement.classList.add('hide-aside') + | } else { + | document.documentElement.classList.remove('hide-aside') + | } + | } + + | })() + diff --git a/themes/butterfly/layout/includes/head/noscript.pug b/themes/butterfly/layout/includes/head/noscript.pug new file mode 100644 index 0000000..cc3befa --- /dev/null +++ b/themes/butterfly/layout/includes/head/noscript.pug @@ -0,0 +1,14 @@ +noscript. + \ No newline at end of file diff --git a/themes/butterfly/layout/includes/head/preconnect.pug b/themes/butterfly/layout/includes/head/preconnect.pug new file mode 100644 index 0000000..3d7b9e9 --- /dev/null +++ b/themes/butterfly/layout/includes/head/preconnect.pug @@ -0,0 +1,22 @@ +link(rel="preconnect" href="//cdn.jsdelivr.net") + +if theme.google_analytics + link(rel="preconnect" href="//www.google-analytics.com" crossorigin) + +if theme.baidu_analytics + link(rel="preconnect" href="//hm.baidu.com") + +if theme.tencent_analytics + link(rel="preconnect" href="//pingjs.qq.com") + +if theme.cnzz_analytics + link(rel="preconnect" href="//s4.cnzz.com") + +if theme.blog_title_font && theme.blog_title_font.font_link && theme.blog_title_font.font_link.indexOf('//fonts.googleapis.com') != -1 + link(rel="preconnect" href="//fonts.googleapis.com" crossorigin) + +if theme.busuanzi.site_uv || theme.busuanzi.site_pv || theme.busuanzi.page_pv + link(rel="preconnect" href="//busuanzi.ibruce.info") + +if theme.baidu_push + link(rel="preconnect" href="//zz.bdstatic.com") diff --git a/themes/butterfly/layout/includes/head/pwa.pug b/themes/butterfly/layout/includes/head/pwa.pug new file mode 100644 index 0000000..e9152f2 --- /dev/null +++ b/themes/butterfly/layout/includes/head/pwa.pug @@ -0,0 +1,11 @@ +link(rel="manifest" href=url_for(theme.pwa.manifest)) +if(theme.pwa.theme_color) + meta(name="msapplication-TileColor" content=theme.pwa.theme_color) +if(theme.pwa.apple_touch_icon) + link(rel="apple-touch-icon" sizes="180x180" href=url_for(theme.pwa.apple_touch_icon)) +if(theme.pwa.favicon_32_32) + link(rel="icon" type="image/png" sizes="32x32" href=url_for(theme.pwa.favicon_32_32)) +if(theme.pwa.favicon_16_16) + link(rel="icon" type="image/png" sizes="16x16" href=url_for(theme.pwa.favicon_16_16)) +if(theme.pwa.mask_icon) + link(rel="mask-icon" href=url_for(theme.pwa.mask_icon) color="#5bbad5") diff --git a/themes/butterfly/layout/includes/head/site_verification.pug b/themes/butterfly/layout/includes/head/site_verification.pug new file mode 100644 index 0000000..cae5742 --- /dev/null +++ b/themes/butterfly/layout/includes/head/site_verification.pug @@ -0,0 +1,14 @@ +if theme.google_site_verification + meta(name="google-site-verification" content=theme.google_site_verification) + +if theme.bing_site_verification + meta(name="msvalidate.01" content=theme.bing_site_verification) + +if theme.baidu_site_verification + meta(name="baidu-site-verification" content=theme.baidu_site_verification) + +if theme.qihu_site_verification + meta(name="360-site-verification" content=theme.qihu_site_verification) + +if theme.yandex_site_verification + meta(name="yandex-verification" content=theme.yandex_site_verification) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/header/index.pug b/themes/butterfly/layout/includes/header/index.pug new file mode 100644 index 0000000..4fe2e2c --- /dev/null +++ b/themes/butterfly/layout/includes/header/index.pug @@ -0,0 +1,48 @@ +if page.top_img !== false + if is_post() + - var top_img = page.top_img || page.cover || page.randomcover || theme.default_top_img + else if is_page() + - var top_img = page.top_img || theme.default_top_img + else if is_tag() + - var top_img = theme.tag_per_img && theme.tag_per_img[page.tag] + - top_img = top_img ? top_img : (theme.tag_img !== false ? theme.tag_img || theme.default_top_img : false) + else if is_category() + - var top_img = theme.category_per_img && theme.category_per_img[page.category] + - top_img = top_img ? top_img : (theme.category_img !== false ? theme.category_img || theme.default_top_img : false) + else if is_home() + - var top_img = theme.index_img !== false ? theme.index_img || theme.default_top_img : false + else if is_archive() + - var top_img = theme.archive_img !== false ? theme.archive_img || theme.default_top_img : false + else + - var top_img = page.top_img || theme.default_top_img + + if top_img !== false + - var imgSource = top_img && top_img.indexOf('/') !== -1 ? `background-image: url(${url_for(top_img)})` : `background: ${top_img}` + - var bg_img = top_img ? imgSource : '' + - var site_title = is_archive() ? _p('page.archives') : page.title || page.tag || page.category || config.title + - var isHomeClass = is_home() ? 'full_page' : 'not-index-bg' + - is_post() ? isHomeClass = 'post-bg' : isHomeClass + else + - var isHomeClass = 'no-top-img' +else + - var top_img = false + - var isHomeClass = 'no-top-img' + +header#page-header(class=isHomeClass style=bg_img) + !=partial('includes/header/nav', {}, {cache:theme.fragment_cache}) + if top_img !== false + if is_post() + include ./post-info.pug + else if is_home() + #site-info + h1#site-title=site_title + #site-subtitle + span#subtitle + if(theme.social) + #site_social_icons + !=fragment_cache('social', function(){return partial('includes/header/social')}) + #scroll-down + i.fas.fa-angle-down.scroll-down-effects + else + #page-site-info + h1#site-title=site_title diff --git a/themes/butterfly/layout/includes/header/menu_item.pug b/themes/butterfly/layout/includes/header/menu_item.pug new file mode 100644 index 0000000..7feff6b --- /dev/null +++ b/themes/butterfly/layout/includes/header/menu_item.pug @@ -0,0 +1,26 @@ +if theme.menu + //- for mobile sidebar + - let sidebarChildHide = theme.hide_sidebar_menu_child ? 'hide' : '' + + .menus_items + each value, label in theme.menu + if !Array.isArray(value) + .menus_item + a.site-page(href=url_for(trim(value.split('||')[0]))) + if value.split('||')[1] + i.fa-fw(class=trim(value.split('||')[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) + ul.menus_item_child + each i in value + li + a.site-page(href=url_for(trim(i.split('||')[1]))) + if i.split('||')[2] + i.fa-fw(class=trim(i.split('||')[2])) + span=' '+trim(i.split('||')[0]) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/header/nav.pug b/themes/butterfly/layout/includes/header/nav.pug new file mode 100644 index 0000000..332adf6 --- /dev/null +++ b/themes/butterfly/layout/includes/header/nav.pug @@ -0,0 +1,17 @@ +nav#nav + span#blog_name + a#site-name(href=url_for('/')) #[=config.title] + + span#menus + if (theme.algolia_search.enable || theme.local_search.enable) + #search_button + a.site-page.social-icon.search + i.fas.fa-search.fa-fw + span=' '+_p('search') + !=fragment_cache('menus', function(){return partial('includes/header/menu_item')}) + + span#toggle-menu.close + a.site-page + i.fas.fa-bars.fa-fw + + diff --git a/themes/butterfly/layout/includes/header/post-info.pug b/themes/butterfly/layout/includes/header/post-info.pug new file mode 100644 index 0000000..2d94928 --- /dev/null +++ b/themes/butterfly/layout/includes/header/post-info.pug @@ -0,0 +1,82 @@ +#post-info + h1.post-title= page.title || _p('no_title') + + #post-meta + .meta-firstline + if (theme.post_meta.post.date_type) + span.post-meta-date + if (theme.post_meta.post.date_type === 'both') + i.far.fa-calendar-alt.fa-fw.post-meta-icon + span.post-meta-label= _p('post.created') + time.post-meta-date-created(datetime=date_xml(page.date) title=_p('post.created') + ' ' + full_date(page.date))=date(page.date, config.date_format) + span.post-meta-separator | + i.fas.fa-history.fa-fw.post-meta-icon + span.post-meta-label= _p('post.updated') + time.post-meta-date-updated(datetime=date_xml(page.updated) title=_p('post.updated') + ' ' + full_date(page.updated))=date(page.updated, config.date_format) + else + - let data_type_update = theme.post_meta.post.date_type === 'updated' + - let date_type = data_type_update ? 'updated' : 'date' + - let date_icon = data_type_update ? 'fas fa-history' :'far fa-calendar-alt' + - let data_info = data_type_update ? _p('post.updated') : _p('post.created') + i.fa-fw.post-meta-icon(class=date_icon) + span.post-meta-label= data_info + time(datetime=date_xml(page[date_type]) title=date_title + ' ' + full_date(page[date_type]))=date(page[date_type], config.date_format) + if (theme.post_meta.post.categories && page.categories.data.length > 0) + span.post-meta-categories + if (theme.post_meta.post.date_type) + span.post-meta-separator | + + each item, index in page.categories.data + i.fas.fa-inbox.fa-fw.post-meta-icon + a(href=url_for(item.path)).post-meta-categories #[=item.name] + if (index < page.categories.data.length - 1) + i.fas.fa-angle-right.post-meta-separator + + .meta-secondline + - let postWordcount = theme.wordcount.enable && (theme.wordcount.post_wordcount || theme.wordcount.min2read) + if (postWordcount) + span.post-meta-separator | + span.post-meta-wordcount + if theme.wordcount.post_wordcount + i.far.fa-file-word.fa-fw.post-meta-icon + span.post-meta-label= _p('post.wordcount') + ':' + span.word-count= wordcount(page.content) + if theme.wordcount.min2read + span.post-meta-separator | + if theme.wordcount.min2read + i.far.fa-clock.fa-fw.post-meta-icon + span.post-meta-label= _p('post.min2read') + ':' + span= min2read(page.content, {cn: 350, en: 160}) + _p('post.min2read_unit') + + if theme.busuanzi.page_pv + span.post-meta-separator | + span.post-meta-pv-cv + i.far.fa-eye.fa-fw.post-meta-icon + span.post-meta-label=_p('post.page_pv') + ':' + span#busuanzi_value_page_pv + + if !theme.comments.lazyload && page.comments !== false && theme.comments.use && theme.comments.count + - var whichCount = theme.comments.use[0] + if whichCount !== 'Livere' && whichCount !== 'Utterances' + span.post-meta-separator | + span.post-meta-commentcount + if whichCount === 'Disqus' || whichCount === 'Disqusjs' + i.far.fa-comments.fa-fw.post-meta-icon + span.post-meta-label= _p('post.comments') + ':' + span.disqus-comment-count.comment-count + a(href=full_url_for(page.path) + '#disqus_thread') + else if whichCount === 'Valine' + i.far.fa-comments.fa-fw.post-meta-icon + span.post-meta-label= _p('post.comments') + ':' + a(href=url_for(page.path) + '#post-comment' itemprop="discussionUrl") + span.valine-comment-count.comment-count(data-xid=url_for(page.path) itemprop="commentCount") + else if whichCount === 'Gitalk' + i.far.fa-comments.fa-fw.post-meta-icon + span.post-meta-label= _p('post.comments') + ':' + a(href=url_for(page.path) + '#post-comment') + span.gitalk-comment-count.comment-count + else if whichCount === 'Facebook Comments' + i.far.fa-comments.fa-fw.post-meta-icon + span.post-meta-label= _p('post.comments') + ':' + a.comment-count(href=url_for(page.path) + '#post-comment') + span.fb-comments-count(data-href=urlNoIndex()) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/header/social.pug b/themes/butterfly/layout/includes/header/social.pug new file mode 100644 index 0000000..80adfe9 --- /dev/null +++ b/themes/butterfly/layout/includes/header/social.pug @@ -0,0 +1,4 @@ +each url, icon in theme.social + a.social-icon(href=url_for(trim(url.split('||')[0])) target="_blank" + title=url.split('||')[1] === undefined ? '' : trim(url.split('||')[1])) + i(class=icon) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/layout.pug b/themes/butterfly/layout/includes/layout.pug new file mode 100644 index 0000000..e3a5b8c --- /dev/null +++ b/themes/butterfly/layout/includes/layout.pug @@ -0,0 +1,42 @@ +- var htmlClassHideAside = theme.aside.enable && theme.aside.hide ? 'hide-aside' : '' +- var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : '' + +doctype html +html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside) + head + include ./head.pug + body + if theme.preloader + !=partial('includes/loading/loading', {}, {cache:theme.fragment_cache}) + + if theme.background + #web_bg + + !=partial('includes/sidebar', {}, {cache:theme.fragment_cache}) + + #body-wrap + include ./header/index.pug + + main#content-inner.layout(class=hideAside) + if body + div!= body + else + block content + if theme.aside.enable && page.aside !== false + include widget/index.pug + + - var footerBg = theme.footer_bg + if (footerBg) + if (footerBg === true) + - var footer_bg = bg_img + else + - var footer_bg = theme.footer_bg.indexOf('/') !== -1 ? `background-image: url(${url_for(footerBg)})` : `background: ${footerBg}` + else + - var footer_bg = '' + + footer#footer(style=footer_bg) + !=partial('includes/footer', {}, {cache:theme.fragment_cache}) + + include ./rightside.pug + !=partial('includes/third-party/search/index', {}, {cache:theme.fragment_cache}) + include ./additional-js.pug \ No newline at end of file diff --git a/themes/butterfly/layout/includes/loading/loading-js.pug b/themes/butterfly/layout/includes/loading/loading-js.pug new file mode 100644 index 0000000..6bf7f2d --- /dev/null +++ b/themes/butterfly/layout/includes/loading/loading-js.pug @@ -0,0 +1,13 @@ +script. + var preloader = { + endLoading: () => { + document.body.style.overflow = 'auto'; + document.getElementById('loading-box').classList.add("loaded") + }, + initLoading: () => { + document.body.style.overflow = ''; + document.getElementById('loading-box').classList.remove("loaded") + + } + } + window.addEventListener('load',()=> {preloader.endLoading()}) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/loading/loading.pug b/themes/butterfly/layout/includes/loading/loading.pug new file mode 100644 index 0000000..2e4b65f --- /dev/null +++ b/themes/butterfly/layout/includes/loading/loading.pug @@ -0,0 +1,9 @@ +#loading-box + .loading-left-bg + .loading-right-bg + .spinner-box + .configure-border-1 + .configure-core + .configure-border-2 + .configure-core + .loading-word= _p('loading') diff --git a/themes/butterfly/layout/includes/mixins/article-sort.pug b/themes/butterfly/layout/includes/mixins/article-sort.pug new file mode 100644 index 0000000..c2f1b5e --- /dev/null +++ b/themes/butterfly/layout/includes/mixins/article-sort.pug @@ -0,0 +1,23 @@ +mixin articleSort(posts) + .article-sort + - var year + - posts.each(function (article) { + - let tempYear = date(article.date, 'YYYY') + - let no_cover = article.cover === false || !theme.cover.archives_enable ? 'no-article-cover' : '' + - let title = article.title || _p('no_title') + if tempYear !== year + - year = tempYear + .article-sort-item.year= year + .article-sort-item(class=no_cover) + if article.cover && theme.cover.archives_enable + a.article-sort-item-img(href=url_for(article.path) title=title) + if theme.lazyload.enable + img(data-lazy-src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`) + else + img(src=url_for(article.cover) alt=title onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'`) + .article-sort-item-info + .article-sort-item-time + i.far.fa-calendar-alt + time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))= date(article.date, config.date_format) + a.article-sort-item-title(href=url_for(article.path) title=title)= title + - }) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/mixins/post-ui.pug b/themes/butterfly/layout/includes/mixins/post-ui.pug new file mode 100644 index 0000000..7748b8e --- /dev/null +++ b/themes/butterfly/layout/includes/mixins/post-ui.pug @@ -0,0 +1,81 @@ +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' : '' + if post_cover && theme.cover.index_enable + .post_cover(class=leftOrRight) + a(href=url_for(link) title=title) + if theme.lazyload.enable + img.post_bg(data-lazy-src=url_for(post_cover) onerror=`this.onerror=null;this.src='`+ url_for(theme.error_img.post_page) + `'` alt=title) + else + 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 + .article-meta-wrap + if (is_home() && (article.top || article.sticky > 0)) + span.article-meta + i.fas.fa-thumbtack.article-meta__icon.sticky + span.sticky= _p('sticky') + span.article-meta__separator | + if (theme.post_meta.page.date_type) + span.post-meta-date + if (theme.post_meta.page.date_type === 'both') + i.far.fa-calendar-alt + span.article-meta-label=_p('post.created') + time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format) + span.article-meta__separator | + i.fas.fa-history + span.article-meta-label=_p('post.updated') + time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format) + else + - let data_type_updated = theme.post_meta.page.date_type === 'updated' + - let date_type = data_type_updated ? 'updated' : 'date' + - let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt' + - let date_title = data_type_updated ? _p('post.updated') : _p('post.created') + i(class=date_icon) + span.article-meta-label=date_title + time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format) + if (theme.post_meta.page.categories && article.categories.data.length > 0) + span.article-meta + span.article-meta__separator | + i.fas.fa-inbox.article-meta__icon + 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 + if (theme.post_meta.page.tags && article.tags.data.length > 0) + span.article-meta.tags + span.article-meta__separator | + i.fas.fa-tag.article-meta__icon + 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 #[='•'] + + //- Display the article introduction on homepage + case theme.index_post_content.method + when false + - break + when 1 + .content!= article.description + when 2 + if article.description + .content!= article.description + else + - const content = strip_html(article.content) + - let expert = content.substring(0, theme.index_post_content.length) + - content.length > theme.index_post_content.length ? expert += ' ...' : '' + .content!= expert + default + - const content = strip_html(article.content) + - let expert = content.substring(0, theme.index_post_content.length) + - content.length > theme.index_post_content.length ? expert += ' ...' : '' + .content!= expert + + if theme.ad && theme.ad.index + if (index + 1) % 3 == 0 + .recent-post-item.ad-height!=theme.ad.index diff --git a/themes/butterfly/layout/includes/page/artitalk.pug b/themes/butterfly/layout/includes/page/artitalk.pug new file mode 100644 index 0000000..c5128bb --- /dev/null +++ b/themes/butterfly/layout/includes/page/artitalk.pug @@ -0,0 +1,4 @@ +if top_img === false + h1.page-title= page.title + +#artitalk_main \ No newline at end of file diff --git a/themes/butterfly/layout/includes/page/categories.pug b/themes/butterfly/layout/includes/page/categories.pug new file mode 100644 index 0000000..dbdc980 --- /dev/null +++ b/themes/butterfly/layout/includes/page/categories.pug @@ -0,0 +1,5 @@ +.category-lists + .category-title.is-center= _p('page.category') + | - + span.category-amount= site.categories.length + div!= list_categories() \ No newline at end of file diff --git a/themes/butterfly/layout/includes/page/default-page.pug b/themes/butterfly/layout/includes/page/default-page.pug new file mode 100644 index 0000000..2d9cdda --- /dev/null +++ b/themes/butterfly/layout/includes/page/default-page.pug @@ -0,0 +1,4 @@ +#article-container + if top_img === false + h1.page-title= page.title + != page.content \ No newline at end of file diff --git a/themes/butterfly/layout/includes/page/flink.pug b/themes/butterfly/layout/includes/page/flink.pug new file mode 100644 index 0000000..48bcf32 --- /dev/null +++ b/themes/butterfly/layout/includes/page/flink.pug @@ -0,0 +1,19 @@ +.flink#article-container + 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") + if theme.lazyload.enable + img(data-lazy-src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name ) + else + img(src=url_for(item.avatar) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt=item.name ) + span.flink-item-name= item.name + span.flink-item-desc(title=item.descr)= item.descr + != page.content + diff --git a/themes/butterfly/layout/includes/page/tags.pug b/themes/butterfly/layout/includes/page/tags.pug new file mode 100644 index 0000000..4d57e43 --- /dev/null +++ b/themes/butterfly/layout/includes/page/tags.pug @@ -0,0 +1,5 @@ +.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/themes/butterfly/layout/includes/pagination.pug b/themes/butterfly/layout/includes/pagination.pug new file mode 100644 index 0000000..ab09c1a --- /dev/null +++ b/themes/butterfly/layout/includes/pagination.pug @@ -0,0 +1,39 @@ +- + var options = { + prev_text: '', + next_text: '', + mid_size: 1, + escape: false + } + +if(!is_post()) + nav#pagination + div.pagination + !=paginator(options) +else + nav#pagination.pagination-post + if(page.prev) + - var hasPageNext = page.next ? 'pull-left' : 'pull-full' + .prev-post(class=hasPageNext) + - var pagination_cover = page.prev.cover === false ? page.prev.randomcover : page.prev.cover + a(href=url_for(page.prev.path)) + if theme.lazyload.enable + img.prev-cover(data-lazy-src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` ) + else + img.prev-cover(src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` ) + .pagination-info + .label=_p('pagination.prev') + .prev_info=page.prev.title + + if(page.next) + - var hasPagePrev = page.prev ? 'pull-right' : 'pull-full' + - var pagination_cover = page.next.cover == false ? page.next.randomcover : page.next.cover + .next-post(class=hasPagePrev) + a(href=url_for(page.next.path)) + if theme.lazyload.enable + img.next-cover(data-lazy-src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'`) + else + img.next-cover(src=url_for(pagination_cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'`) + .pagination-info + .label=_p('pagination.next') + .next_info=page.next.title \ No newline at end of file diff --git a/themes/butterfly/layout/includes/post/post-copyright.pug b/themes/butterfly/layout/includes/post/post-copyright.pug new file mode 100644 index 0000000..dfa346d --- /dev/null +++ b/themes/butterfly/layout/includes/post/post-copyright.pug @@ -0,0 +1,17 @@ +if theme.post_copyright.enable && page.copyright !== false + - let author = page.copyright_author ? page.copyright_author : config.author + - let authorHref = page.copyright_author_href ? page.copyright_author_href : `mailto:${config.email}` + - let url = page.copyright_url ? page.copyright_url : page.permalink + - let info = page.copyright_info ? page.copyright_info : _p('post.copyright.copyright_content', theme.post_copyright.license_url, theme.post_copyright.license, config.url, config.title) + .post-copyright + .post-copyright__author + span.post-copyright-meta= _p('post.copyright.author') + ": " + span.post-copyright-info + a(href=authorHref)=author + .post-copyright__type + span.post-copyright-meta= _p('post.copyright.link') + ": " + span.post-copyright-info + a(href=url_for(url))= theme.post_copyright.decode ? decodeURI(url) : url + .post-copyright__notice + span.post-copyright-meta= _p('post.copyright.copyright_notice') + ": " + span.post-copyright-info!= info diff --git a/themes/butterfly/layout/includes/post/reward.pug b/themes/butterfly/layout/includes/post/reward.pug new file mode 100644 index 0000000..1bf9381 --- /dev/null +++ b/themes/butterfly/layout/includes/post/reward.pug @@ -0,0 +1,16 @@ +.post-reward + .reward-button + i.fas.fa-qrcode + = ' ' + _p('donate') + .reward-main + ul.reward-all + each item in theme.reward.QR_code + - var clickTo = (item.itemlist||item).link ? (item.itemlist||item).link : (item.itemlist||item).img + li.reward-item + a(href=clickTo target='_blank') + if theme.lazyload.enable + img.post-qr-code-img(data-lazy-src=url_for((item.itemlist||item).img) alt=(item.itemlist||item).text) + else + img.post-qr-code-img(src=url_for((item.itemlist||item).img) alt=(item.itemlist||item).text) + .post-qr-code-desc=(item.itemlist||item).text + diff --git a/themes/butterfly/layout/includes/rightside.pug b/themes/butterfly/layout/includes/rightside.pug new file mode 100644 index 0000000..9a9e491 --- /dev/null +++ b/themes/butterfly/layout/includes/rightside.pug @@ -0,0 +1,33 @@ +#rightside + #rightside-config-hide + if is_post() && theme.readmode + button#readmode(type="button" title=_p('rightside.readmode_title')) + i.fas.fa-book-open + 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") + i.fas.fa-arrows-alt-h + #rightside-config-show + if is_post() + if (theme.readmode || theme.translate.enable || (theme.darkmode.enable && theme.darkmode.button)) + button#rightside_config(type="button" title=_p("rightside.setting")) + i.fas.fa-cog + if showToc && theme.aside.mobile + 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) + button#rightside_config(type="button" title=_p("rightside.setting")) + i.fas.fa-cog + + 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/themes/butterfly/layout/includes/sidebar.pug b/themes/butterfly/layout/includes/sidebar.pug new file mode 100644 index 0000000..43c0b2c --- /dev/null +++ b/themes/butterfly/layout/includes/sidebar.pug @@ -0,0 +1,31 @@ +#sidebar + #menu-mask + #sidebar-menus + .author-avatar + if theme.lazyload.enable + img.avatar-img(data-lazy-src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar") + else + img.avatar-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 + + 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 + + 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 + !=fragment_cache('menus', function(){return partial('includes/header/menu_item')}) diff --git a/themes/butterfly/layout/includes/third-party/aplayer.pug b/themes/butterfly/layout/includes/third-party/aplayer.pug new file mode 100644 index 0000000..c7aa010 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/aplayer.pug @@ -0,0 +1,3 @@ +link(rel='stylesheet' href=url_for(theme.CDN.aplayer_css)) +script(src=url_for(theme.CDN.aplayer_js)) +script(src=url_for(theme.CDN.meting_js)) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/artitalk.pug b/themes/butterfly/layout/includes/third-party/artitalk.pug new file mode 100644 index 0000000..40490fb --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/artitalk.pug @@ -0,0 +1,24 @@ +- let option = theme.artitalk.option ? JSON.stringify(theme.artitalk.option) : false + +script. + (()=>{ + let setting = { + appId: '!{theme.artitalk.appId}', + appKey: '!{theme.artitalk.appKey}', + } + + if (!{Boolean(option)}) { + const otherSetting = !{option} + setting = Object.assign({}, setting, otherSetting) + } + + const init = () => { + new Artitalk(setting) + } + + if (typeof Artitalk === 'function') { + init() + } else { + $.getScript('!{theme.CDN.artitalk}',init) + } + })() \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/baidu_push.pug b/themes/butterfly/layout/includes/third-party/baidu_push.pug new file mode 100644 index 0000000..13faf11 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/baidu_push.pug @@ -0,0 +1,15 @@ +if theme.baidu_push + script. + (function(){ + const bp = document.createElement('script'); + const curProtocol = window.location.protocol.split(':')[0]; + if (curProtocol === 'https'){ + bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; + } + else{ + bp.src = 'http://push.zhanzhang.baidu.com/push.js'; + } + bp.dataset.pjax = '' + const s = document.getElementsByTagName("script")[0]; + s.parentNode.insertBefore(bp, s); + })() \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/chat/chatra.pug b/themes/butterfly/layout/includes/third-party/chat/chatra.pug new file mode 100644 index 0000000..b6c1201 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/chat/chatra.pug @@ -0,0 +1,33 @@ +//- https://chatra.io/help/api/ +script. + (function(d, w, c) { + w.ChatraID = '#{theme.chatra.id}'; + var s = d.createElement('script'); + w[c] = w[c] || function() { + (w[c].q = w[c].q || []).push(arguments); + }; + s.async = true; + s.src = 'https://call.chatra.io/chatra.js'; + if (d.head) d.head.appendChild(s); + })(document, window, 'Chatra'); + + if (!{theme.chat_btn}) { + var chatBtnFn = () => { + var chatBtn = document.getElementById("chat_btn") + chatBtn.addEventListener("click", function(){ + Chatra('openChat') + }); + } + chatBtnFn() + } else { + if (!{theme.chat_hide_show}) { + function chatBtnHide () { + Chatra('hide') + } + function chatBtnShow () { + Chatra('show') + } + } + } + + diff --git a/themes/butterfly/layout/includes/third-party/chat/crisp.pug b/themes/butterfly/layout/includes/third-party/chat/crisp.pug new file mode 100644 index 0000000..cc57e8d --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/chat/crisp.pug @@ -0,0 +1,36 @@ +script. + window.$crisp = []; + window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}"; + (function () { + d = document; + s = d.createElement("script"); + s.src = "https://client.crisp.chat/l.js"; + s.async = 1; + d.getElementsByTagName("head")[0].appendChild(s); + })(); + $crisp.push(["safe", true]) + + if (!{theme.chat_btn}) { + $crisp.push(["do", "chat:hide"]) + $crisp.push(["on", "chat:closed", function() { + $crisp.push(["do", "chat:hide"]) + }]) + var chatBtnFn = () => { + var chatBtn = document.getElementById("chat_btn") + chatBtn.addEventListener("click", function(){ + $crisp.push(["do", "chat:show"]) + $crisp.push(["do", "chat:open"]) + + }); + } + chatBtnFn() + } else { + if (!{theme.chat_hide_show}) { + function chatBtnHide () { + $crisp.push(["do", "chat:hide"]) + } + function chatBtnShow () { + $crisp.push(["do", "chat:show"]) + } + } + } \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/chat/daovoice.pug b/themes/butterfly/layout/includes/third-party/chat/daovoice.pug new file mode 100644 index 0000000..3c6b064 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/chat/daovoice.pug @@ -0,0 +1,40 @@ +//- https://guide.daocloud.io/daovoice/javascript-api-5869833.html +script. + (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice") + +script. + var isChatBtn = !{theme.chat_btn} + daovoice('init', { + app_id: '!{theme.daovoice.app_id}',},{ + launcher: { + disableLauncherIcon: isChatBtn // 悬浮 ICON 是否显示 + }, + }); + daovoice('update'); + + if (isChatBtn) { + var chatBtnFn = () => { + var chatBtn = document.getElementById("chat_btn") + chatBtn.addEventListener("click", function(){ + daovoice('show') + }); + } + chatBtnFn() + } else { + if (!{theme.chat_hide_show}) { + function chatBtnHide () { + daovoice('update', {},{ + launcher: { + disableLauncherIcon: true // 悬浮 ICON 是否显示 + }, + }); + } + function chatBtnShow () { + daovoice('update', {},{ + launcher: { + disableLauncherIcon: false // 悬浮 ICON 是否显示 + }, + }); + } + } + } \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/chat/gitter.pug b/themes/butterfly/layout/includes/third-party/chat/gitter.pug new file mode 100644 index 0000000..46f979a --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/chat/gitter.pug @@ -0,0 +1,43 @@ +if theme.chat_btn + script. + ((window.gitter = {}).chat = {}).options = { + disableDefaultChat: true, + }; + document.addEventListener('gitter-sidecar-ready', (e) => { + const GitterChat = e.detail.Chat + let chat + + function initGitter () { + chat = new GitterChat({ + room: '#{theme.gitter.room}', + activationElement: '#chat_btn' + }); + } + + initGitter() + + if (!{theme.pjax.enable}) { + document.addEventListener('pjax:complete', () => { + chat.destroy() + initGitter() + }) + } + + }) +else + script. + ((window.gitter = {}).chat = {}).options = { + room: '#{theme.gitter.room}', + }; + + if (!{theme.chat_hide_show}) { + function chatBtnHide () { + document.getElementsByClassName('gitter-open-chat-button')[0].style.display= 'none' + } + + function chatBtnShow () { + document.getElementsByClassName('gitter-open-chat-button')[0].style.display= 'block' + } + } + +script(src="https://sidecar.gitter.im/dist/sidecar.v1.js" async defer) diff --git a/themes/butterfly/layout/includes/third-party/chat/index.pug b/themes/butterfly/layout/includes/third-party/chat/index.pug new file mode 100644 index 0000000..db78a34 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/chat/index.pug @@ -0,0 +1,10 @@ +if theme.chatra && theme.chatra.enable + include ./chatra.pug +else if theme.tidio && theme.tidio.enable + include ./tidio.pug +else if theme.daovoice && theme.daovoice.enable + include ./daovoice.pug +else if theme.gitter && theme.gitter.enable + include ./gitter.pug +else if theme.crisp && theme.crisp.enable + include ./crisp.pug \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/chat/tidio.pug b/themes/butterfly/layout/includes/third-party/chat/tidio.pug new file mode 100644 index 0000000..6b0097f --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/chat/tidio.pug @@ -0,0 +1,41 @@ +script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async) + +if theme.chat_btn + script. + function onTidioChatApiReady() { + window.tidioChatApi.hide(); + window.tidioChatApi.on("close", function() { + window.tidioChatApi.hide(); + }); + } + if (window.tidioChatApi) { + window.tidioChatApi.on("ready", onTidioChatApiReady); + } else { + document.addEventListener("tidioChat-ready", onTidioChatApiReady); + } + + var chatBtnFn = () => { + document.getElementById("chat_btn").addEventListener("click", function(){ + window.tidioChatApi.show(); + window.tidioChatApi.open(); + }); + } + chatBtnFn() + +else if theme.chat_hide_show + script. + function chatBtnHide () { + if (window.tidioChatApi) { + //- window.tidioChatApi.hide(); + document.getElementById('tidio-chat').style.display= 'none' + } + } + + function chatBtnShow () { + if (window.tidioChatApi) { + //- window.tidioChatApi.show(); + document.getElementById('tidio-chat').style.display= 'block' + } + } + + diff --git a/themes/butterfly/layout/includes/third-party/comments/disqus.pug b/themes/butterfly/layout/includes/third-party/comments/disqus.pug new file mode 100644 index 0000000..fd44d2a --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/disqus.pug @@ -0,0 +1,45 @@ +script. + function loadDisqus () { + var disqus_config = function () { + this.page.url = '!{ page.permalink }' + this.page.identifier = '!{ page.path }' + this.page.title = '!{ page.title }' + }; + + window.disqusReset = () => { + DISQUS.reset({ + reload: true, + config: disqus_config + }) + } + + if (window.DISQUS) disqusReset() + else { + (function() { + var d = document, s = d.createElement('script'); + s.src = 'https://!{theme.disqus.shortname}.disqus.com/embed.js'; + s.setAttribute('data-timestamp', +new Date()); + (d.head || d.body).appendChild(s); + })(); + } + } + + if ('!{theme.comments.use[0]}' === 'Disqus' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqus_thread'), loadDisqus) + else loadDisqus() + } else { + function loadOtherComment () { + loadDisqus() + } + } + +if is_post() && !theme.comments.lazyload && theme.comments.count && theme.comments.use[0] === 'Disqus' + script. + if (window.DISQUSWIDGETS === undefined) { + var d = document, s = d.createElement('script'); + s.src = 'https://!{theme.disqus.shortname}.disqus.com/count.js'; + s.id = 'dsq-count-scr'; + (d.head || d.body).appendChild(s); + } else { + DISQUSWIDGETS.getCount({reset: true}); + } diff --git a/themes/butterfly/layout/includes/third-party/comments/disqusjs.pug b/themes/butterfly/layout/includes/third-party/comments/disqusjs.pug new file mode 100644 index 0000000..e2f3136 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/disqusjs.pug @@ -0,0 +1,58 @@ +- let disqusjsApi = theme.disqusjs.api || 'https://disqus.skk.moe/disqus/' +script. + function loadDisqusjs () { + function addDisqusjsCSS () { + const ele = document.createElement('link') + ele.rel = 'stylesheet' + ele.href= '!{url_for(theme.CDN.disqusjs_css)}' + document.getElementsByTagName('head')[0].appendChild(ele) + } + + function initDisqusjs () { + window.DISQUS = null + new DisqusJS({ + shortname: '!{theme.disqusjs.shortname}', + siteName: '!{theme.disqusjs.siteName}', + identifier: '!{ page.path }', + url: '!{ page.permalink }', + title: '!{ page.title }', + api: '!{disqusjsApi}', + apikey: '!{theme.disqusjs.apikey}', + nocomment: '!{theme.disqusjs.nocomment}', + admin: '!{theme.disqusjs.admin}', + adminLabel: '!{theme.disqusjs.adminLabel}' + }); + } + + window.disqusReset = initDisqusjs + + if (window.disqusJsLoad) initDisqusjs() + else { + addDisqusjsCSS() + $.getScript('!{url_for(theme.CDN.disqusjs)}', initDisqusjs) + window.disqusJsLoad = true + } + } + + if ('!{theme.comments.use[0]}' === 'Disqusjs' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('disqus_thread'), loadDisqusjs) + else loadDisqusjs() + } + else { + function loadOtherComment () { + loadDisqusjs() + } + } + + +if is_post() && !theme.comments.lazyload && theme.comments.count && theme.comments.use[0] === 'Disqusjs' + script. + if (window.DISQUSWIDGETS === undefined) { + var d = document, s = d.createElement('script'); + s.src = 'https://!{theme.disqus.shortname}.disqus.com/count.js'; + s.id = 'dsq-count-scr'; + (d.head || d.body).appendChild(s); + } else { + DISQUSWIDGETS.getCount({reset: true}); + } + diff --git a/themes/butterfly/layout/includes/third-party/comments/facebook_comments.pug b/themes/butterfly/layout/includes/third-party/comments/facebook_comments.pug new file mode 100644 index 0000000..cf28c34 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/facebook_comments.pug @@ -0,0 +1,26 @@ +#fb-root +script. + function loadFBComment () { + var themeNow = document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light' + document.getElementsByClassName('fb-comments')[0].setAttribute('data-colorscheme',themeNow) + + 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=v7.0') + ele.setAttribute('async', 'true') + ele.setAttribute('defer', 'true') + ele.setAttribute('crossorigin', 'anonymous') + document.getElementById('fb-root').insertAdjacentElement('afterbegin',ele) + } + } + + if ('!{theme.comments.use[0]}' === 'Facebook Comments' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.querySelector('#post-comment .fb-comments'), loadFBComment) + else loadFBComment() + } else { + function loadOtherComment () { + loadFBComment() + } + } + diff --git a/themes/butterfly/layout/includes/third-party/comments/gitalk.pug b/themes/butterfly/layout/includes/third-party/comments/gitalk.pug new file mode 100644 index 0000000..08bc422 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/gitalk.pug @@ -0,0 +1,52 @@ +script. + function addGitalkSource () { + const ele = document.createElement('link') + ele.rel = 'stylesheet' + ele.href= '!{url_for(theme.CDN.gitalk_css)}' + document.getElementsByTagName('head')[0].appendChild(ele) + } + + function loadGitalk () { + function initGitalk () { + var gitalk = new Gitalk({ + clientID: '!{theme.gitalk.client_id}', + clientSecret: '!{theme.gitalk.client_secret}', + repo: '!{theme.gitalk.repo}', + 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 + }) + gitalk.render('gitalk-container') + } + + if (typeof Gitalk === 'function') initGitalk() + else { + addGitalkSource() + $.getScript('!{url_for(theme.CDN.gitalk)}', initGitalk) + } + } + + function commentCount(n){ + let isCommentCount = document.querySelector('#post-meta .gitalk-comment-count') + if (isCommentCount) { + isCommentCount.innerHTML= n + } + } + + if ('!{theme.comments.use[0]}' === 'Gitalk' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('gitalk-container'), loadGitalk) + else loadGitalk() + } else { + function loadOtherComment () { + loadGitalk() + } + } + + + diff --git a/themes/butterfly/layout/includes/third-party/comments/index.pug b/themes/butterfly/layout/includes/third-party/comments/index.pug new file mode 100644 index 0000000..9f8b4b6 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/index.pug @@ -0,0 +1,38 @@ +- let defaultComment = theme.comments.use[0] +hr +#post-comment + .comment-head + .comment-headline + i.fas.fa-comments.fa-fw + span= ' ' + _p('comment') + + if theme.comments.use.length > 1 + #comment-switch + span.first-comment=defaultComment + span.switch-btn + span.second-comment=theme.comments.use[1] + + + .comment-wrap + each name in theme.comments.use + div + case name + when 'Disqus' + #disqus_thread + when 'Valine' + #vcomment.vcomment + when 'Disqusjs' + #disqus_thread + when 'Livere' + #lv-container(data-id="city" data-uid=theme.livere.uid) + when 'Gitalk' + #gitalk-container + when 'Utterances' + #utterances-wrap + when 'Twikoo' + #twikoo + when 'Facebook Comments' + .fb-comments(data-colorscheme = theme.display_mode === 'dark' ? 'dark' : 'light' + data-numposts= theme.facebook_comments.pageSize || 10 + data-order-by= theme.facebook_comments.order_by || 'social' + data-width="100%") diff --git a/themes/butterfly/layout/includes/third-party/comments/js.pug b/themes/butterfly/layout/includes/third-party/comments/js.pug new file mode 100644 index 0000000..07a6f12 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/js.pug @@ -0,0 +1,18 @@ +each name in theme.comments.use + case name + when 'Valine' + !=partial('includes/third-party/comments/valine', {}, {cache:theme.fragment_cache}) + when 'Disqus' + include ./disqus.pug + when 'Disqusjs' + include ./disqusjs.pug + when 'Livere' + !=partial('includes/third-party/comments/livere', {}, {cache:theme.fragment_cache}) + when 'Gitalk' + include ./gitalk.pug + when 'Utterances' + !=partial('includes/third-party/comments/utterances', {}, {cache:theme.fragment_cache}) + when 'Twikoo' + !=partial('includes/third-party/comments/twikoo', {}, {cache:theme.fragment_cache}) + when 'Facebook Comments' + !=partial('includes/third-party/comments/facebook_comments', {}, {cache:theme.fragment_cache}) diff --git a/themes/butterfly/layout/includes/third-party/comments/livere.pug b/themes/butterfly/layout/includes/third-party/comments/livere.pug new file mode 100644 index 0000000..85b6d78 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/livere.pug @@ -0,0 +1,26 @@ +script. + function loadLivere () { + if (typeof LivereTower === 'object') { + window.LivereTower.init() + } + else { + (function(d, s) { + var j, e = d.getElementsByTagName(s)[0]; + if (typeof LivereTower === 'function') { return; } + j = d.createElement(s); + j.src = 'https://cdn-city.livere.com/js/embed.dist.js'; + j.async = true; + e.parentNode.insertBefore(j, e); + })(document, 'script'); + } + } + + if ('!{theme.comments.use[0]}' === 'Livere' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('lv-container'), loadLivere) + else loadLivere() + } + else { + function loadOtherComment () { + loadLivere() + } + } \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/comments/twikoo.pug b/themes/butterfly/layout/includes/third-party/comments/twikoo.pug new file mode 100644 index 0000000..1e49ecd --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/twikoo.pug @@ -0,0 +1,24 @@ +script. + function loadTwikoo () { + function init () { + twikoo.init({ + envId: '!{theme.twikoo}' + }) + } + + if (typeof twikoo.init === 'function') { + init() + } else { + $.getScript('!{theme.CDN.twikoo}', init) + } + } + + if ('!{theme.comments.use[0]}' === 'Twikoo' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('twikoo'), loadTwikoo) + else loadTwikoo() + } else { + function loadOtherComment () { + loadTwikoo() + } + } + diff --git a/themes/butterfly/layout/includes/third-party/comments/utterances.pug b/themes/butterfly/layout/includes/third-party/comments/utterances.pug new file mode 100644 index 0000000..dbd422f --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/utterances.pug @@ -0,0 +1,34 @@ +script. + function loadUtterances () { + let ele = document.createElement('script') + ele.setAttribute('id', 'utterances_comment') + ele.setAttribute('src', '!{url_for(theme.CDN.utterances)}') + ele.setAttribute('repo', '!{theme.utterances.repo}') + ele.setAttribute('issue-term', '!{theme.utterances.issue_term}') + let nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{theme.utterances.dark_theme}' : '#{theme.utterances.light_theme}' + ele.setAttribute('theme', nowTheme) + ele.setAttribute('crossorigin', 'anonymous') + ele.setAttribute('async', 'true') + document.getElementById('utterances-wrap').insertAdjacentElement('afterbegin',ele) + } + + function utterancesTheme () { + if (document.querySelector('.utterances-frame')) { + 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'); + } + } + + if ('!{theme.comments.use[0]}' === 'Utterances' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances) + else loadUtterances() + } else { + function loadOtherComment () { + loadUtterances() + } + } diff --git a/themes/butterfly/layout/includes/third-party/comments/valine.pug b/themes/butterfly/layout/includes/third-party/comments/valine.pug new file mode 100644 index 0000000..6e09a81 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/comments/valine.pug @@ -0,0 +1,51 @@ +- let option = theme.valine.option ? JSON.stringify(theme.valine.option) : false +- let emojiMaps = '""' +if site.data.valine + - emojiMaps = JSON.stringify(site.data.valine) + +script. + function loadValine () { + function initValine () { + let initData = { + 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, + } + + if (!{Boolean(theme.valine.requiredFields)}) { + initData.requiredFields= ('!{theme.valine.requiredFields}'.split(',')) + } + + if (!{Boolean(option)}) { + const otherData = !{option} + initData = Object.assign({}, initData, otherData) + } + + const valine = new Valine(initData) + } + + if (typeof Valine === 'function') initValine() + else $.getScript('!{url_for(theme.CDN.valine)}', initValine) + } + + if ('!{theme.comments.use[0]}' === 'Valine' || !!{theme.comments.lazyload}) { + if (!{theme.comments.lazyload}) btf.loadComment(document.querySelector('#vcomment'),loadValine) + else setTimeout(() => loadValine(), 0) + } else { + function loadOtherComment () { + loadValine() + } + } + + diff --git a/themes/butterfly/layout/includes/third-party/effect.pug b/themes/butterfly/layout/includes/third-party/effect.pug new file mode 100644 index 0000000..9cd4051 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/effect.pug @@ -0,0 +1,28 @@ +if theme.fireworks && theme.fireworks.enable + canvas.fireworks(mobile=`${theme.fireworks.mobile}`) + script(src=url_for(theme.CDN.fireworks)) + +if (theme.canvas_ribbon && theme.canvas_ribbon.enable) + script(defer id="ribbon" src=url_for(theme.CDN.canvas_ribbon) size=theme.canvas_ribbon.size + alpha=theme.canvas_ribbon.alpha zIndex=theme.canvas_ribbon.zIndex mobile=`${theme.canvas_ribbon.mobile}` data-click=`${theme.canvas_ribbon.click_to_change}`) + +if (theme.canvas_fluttering_ribbon && theme.canvas_fluttering_ribbon.enable) + script(defer id="fluttering_ribbon" mobile=`${theme.canvas_fluttering_ribbon.mobile}` src=url_for(theme.CDN.canvas_fluttering_ribbon)) + +if (theme.canvas_nest && theme.canvas_nest.enable) + script#canvas_nest(defer color=theme.canvas_nest.color opacity=theme.canvas_nest.opacity zIndex=theme.canvas_nest.zIndex count=theme.canvas_nest.count mobile=`${theme.canvas_nest.mobile}` src=url_for(theme.CDN.canvas_nest)) + +if theme.activate_power_mode.enable + script(src=url_for(theme.CDN.activate_power_mode)) + script. + POWERMODE.colorful = !{theme.activate_power_mode.colorful}; + POWERMODE.shake = !{theme.activate_power_mode.shake}; + POWERMODE.mobile = !{theme.activate_power_mode.mobile}; + document.body.addEventListener('input', POWERMODE); + +//- 鼠標特效 +if theme.click_heart && theme.click_heart.enable + script#click-heart(src=url_for(theme.CDN.click_heart) async mobile=`${theme.click_heart.mobile}`) + +if theme.ClickShowText && theme.ClickShowText.enable + script#click-show-text(src=url_for(theme.CDN.ClickShowText) async mobile=`${theme.ClickShowText.mobile}`) diff --git a/themes/butterfly/layout/includes/third-party/math/index.pug b/themes/butterfly/layout/includes/third-party/math/index.pug new file mode 100644 index 0000000..4ce6692 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/math/index.pug @@ -0,0 +1,18 @@ +if theme.mathjax && theme.mathjax.enable + if theme.mathjax.per_page + if(!is_tag() && !is_category() && !is_archive() && !is_home()) + include ./mathjax.pug + else + if page.mathjax + include ./mathjax.pug + +if theme.katex && theme.katex.enable + if theme.katex.per_page + if(!is_tag() && !is_category() && !is_archive() && !is_home()) + include ./katex.pug + else + if page.katex + include ./katex.pug + +if theme.mermaid.enable + include ./mermaid.pug \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/math/katex.pug b/themes/butterfly/layout/includes/third-party/math/katex.pug new file mode 100644 index 0000000..6690428 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/math/katex.pug @@ -0,0 +1,7 @@ +link(rel="stylesheet" type="text/css" href=theme.CDN.katex) +script(src=url_for(theme.CDN.katex_copytex)) +link(rel="stylesheet" type="text/css" href=theme.CDN.katex_copytex_css) +script. + $(function () { + $('span.katex-display').wrap('
') + }) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/math/mathjax.pug b/themes/butterfly/layout/includes/third-party/math/mathjax.pug new file mode 100644 index 0000000..c87965f --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/math/mathjax.pug @@ -0,0 +1,53 @@ +//- Mathjax 3 +//- http://docs.mathjax.org/en/latest/upgrading/v2.html#changes-in-the-mathjax-api +//- https://github.com/mathjax/MathJax/issues/2209 +//- http://docs.mathjax.org/en/latest/options/input/tex.html#the-configuration-block +//- http://docs.mathjax.org/en/latest/web/typeset.html#resetting-automatic-equation-numbering + +script. + if (!window.MathJax) { + window.MathJax = { + loader: { + source: { + '[tex]/amsCd': '[tex]/amscd' + } + }, + tex: { + inlineMath: [ ['$','$'], ["\\(","\\)"]], + tags: 'ams' + }, + options: { + renderActions: { + findScript: [10, doc => { + for (const node of document.querySelectorAll('script[type^="math/tex"]')) { + const display = !!node.type.match(/; *mode=display/) + const math = new doc.options.MathItem(node.textContent, doc.inputJax[0], display) + const text = document.createTextNode('') + node.parentNode.replaceChild(text, node) + math.start = {node: text, delim: '', n: 0} + math.end = {node: text, delim: '', n: 0} + doc.math.push(math) + } + }, ''], + addClass: [200,() => { + document.querySelectorAll('mjx-container:not([display=\'true\']').forEach( node => { + const target = node.parentNode + if (!target.classList.contains('has-jax')) { + target.classList.add('mathjax-overflow') + } + }) + }, '', false] + } + } + } + + const script = document.createElement('script') + script.src = '!{theme.CDN.mathjax}' + script.id = 'MathJax-script' + script.async = true + document.head.appendChild(script) + } else { + MathJax.startup.document.state(0) + MathJax.texReset() + MathJax.typeset() + } \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/math/mermaid.pug b/themes/butterfly/layout/includes/third-party/math/mermaid.pug new file mode 100644 index 0000000..b872a79 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/math/mermaid.pug @@ -0,0 +1,15 @@ +script. + if (document.getElementsByClassName('mermaid').length) { + if (window.mermaidJsLoad) mermaid.init() + else { + $.getScript('!{theme.CDN.mermaid}', function () { + window.mermaidJsLoad = true + mermaid.initialize({ + theme: '!{theme.mermaid.theme}', + }) + !{theme.pjax.enable} && mermaid.init() + }) + } + } + + diff --git a/themes/butterfly/layout/includes/third-party/newest-comments/disqus-comment.pug b/themes/butterfly/layout/includes/third-party/newest-comments/disqus-comment.pug new file mode 100644 index 0000000..5ed18db --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/newest-comments/disqus-comment.pug @@ -0,0 +1,74 @@ +script. + window.addEventListener('load', () => { + const changeContent = (content) => { + if (content === '') return content + + content = content.replace(/<[^>]+>/g,"") // remove html tag + content = content.replace(/(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|webp)/g, '') // remove image link + content = content.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, '') // remove url + + if (content.length > 150) { + content = content.substring(0,150) + '...' + } + return content + } + + const getDisqusComment = () => { + let disqusArray = [] + $.getJSON('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{theme.newest_comments.disqus.forum}&related=thread&limit=!{theme.newest_comments.limit}&api_key=!{theme.newest_comments.disqus.api_key}', function(data){ + $.each(data.response, (i, item) => { + disqusArray.push({ + 'avatar': item.author.avatar.cache, + 'content': changeContent(item.message), + 'nick': item.author.name, + 'url': item.url, + 'date': item.createdAt + }) + }) + // set expiry to 10 min + saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), 10/(60*24)) + generateHtml(disqusArray) + }).fail(()=>{ + const $dom = document.querySelector('#card-newest-comments .aside-list') + $dom.innerHTML= "!{_p('aside.card_newest_comments.error')}" + }) + } + + const generateHtml = array => { + let result = '' + + for (let i = 0; i < array.length; i++) { + result += '
' + + if (!{theme.newest_comments.avatar}) { + result += `${array[i].nick}` + } + + result += `
+ ${array[i].content} +
${array[i].nick}
+
` + } + + let $dom = document.querySelector('#card-newest-comments .aside-list') + $dom.innerHTML= result + window.pjax && window.pjax.refresh($dom) + } + + const newestCommentInit = () => { + if (document.querySelector('#card-newest-comments .aside-list')) { + const data = saveToLocal.get('disqus-newest-comments') + if (data) { + generateHtml(JSON.parse(data)) + } else { + getDisqusComment() + } + } + } + + newestCommentInit() + document.addEventListener('pjax:complete', newestCommentInit) + }) + + + diff --git a/themes/butterfly/layout/includes/third-party/newest-comments/github-issues.pug b/themes/butterfly/layout/includes/third-party/newest-comments/github-issues.pug new file mode 100644 index 0000000..e7e7bbc --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/newest-comments/github-issues.pug @@ -0,0 +1,74 @@ +script. + window.addEventListener('load', () => { + const changeContent = (content) => { + if (content === '') return content + + content = content.replace(/<[^>]+>/g,"") // remove html tag + content = content.replace(/(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|webp)/g, '') // remove image link + content = content.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, '') // remove url + + if (content.length > 150) { + content = content.substring(0,150) + '...' + } + return content + } + + const getGithubIssues = () => { + let githubArray = [] + $.getJSON('https://api.github.com/repos/!{theme.newest_comments.github_issues.repo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.newest_comments.limit}&page=1', (data) => { + $.each(data, (index, item) => { + githubArray.push({ + 'avatar': item.user.avatar_url, + 'content': changeContent(item.body), + 'nick': item.user.login, + 'url': item.html_url, + 'date': item.updated_at + }) + }) + saveToLocal.set('github-newest-comments', JSON.stringify(githubArray), 10/(60*24)) + generateHtml(githubArray) + }).fail(()=>{ + const $dom = document.querySelector('#card-newest-comments .aside-list') + $dom.innerHTML= "!{_p('aside.card_newest_comments.error')}" + }) + } + + const generateHtml = array => { + let result = '' + + for (let i = 0; i < array.length; i++) { + result += '
' + + if (!{theme.newest_comments.avatar}) { + result += `${array[i].nick}` + } + + result += `
+ ${array[i].content} +
${array[i].nick}
+
` + } + + let $dom = document.querySelector('#card-newest-comments .aside-list') + $dom.innerHTML= result + window.pjax && window.pjax.refresh($dom) + } + + const newestCommentInit = () => { + if (document.querySelector('#card-newest-comments .aside-list')) { + const data = saveToLocal.get('github-newest-comments') + if (data) { + generateHtml(JSON.parse(data)) + } else { + getGithubIssues() + } + } + } + + newestCommentInit() + document.addEventListener('pjax:complete', newestCommentInit) + }) + + + + diff --git a/themes/butterfly/layout/includes/third-party/newest-comments/index.pug b/themes/butterfly/layout/includes/third-party/newest-comments/index.pug new file mode 100644 index 0000000..24b51a7 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/newest-comments/index.pug @@ -0,0 +1,6 @@ +if theme.newest_comments.leancloud.enable + include ./leancloud.pug +else if theme.newest_comments.github_issues.enable + include ./github-issues.pug +else if theme.newest_comments.disqus.enable + include ./disqus-comment.pug \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/newest-comments/leancloud.pug b/themes/butterfly/layout/includes/third-party/newest-comments/leancloud.pug new file mode 100644 index 0000000..2e6910a --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/newest-comments/leancloud.pug @@ -0,0 +1,99 @@ +script(src="https://cdn.jsdelivr.net/npm/blueimp-md5@2.17.0/js/md5.min.js") +script. + window.addEventListener('load', () => { + const changeContent = (content) => { + if (content === '') return content + + content = content.replace(/<[^>]+>/g,"") // remove html tag + content = content.replace(/(http(s?):)([/|.|\w|\s|-])*\.(?:jpg|jpeg|gif|png|webp)/g, '') // remove image link + content = content.replace(/(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gi, '') // remove url + + if (content.length > 150) { + content = content.substring(0,150) + '...' + } + return content + } + + const getIcon = (icon, mail) => { + if (icon) return icon + let defaultIcon = '!{ theme.newest_comments.leancloud.default_avatar ? `?d=${theme.newest_comments.leancloud.default_avatar}` : ''}' + let iconUrl = `https://gravatar.loli.net/avatar/${md5(mail.toLowerCase()) + defaultIcon}` + return iconUrl + } + + const generateHtml = array => { + let result = '' + + for (let i = 0; i < array.length; i++) { + result += '
' + + if (!{theme.newest_comments.avatar}) { + result += `${array[i].nick}` + } + + result += `
+ ${array[i].content} +
${array[i].nick}
+
` + } + + let $dom = document.querySelector('#card-newest-comments .aside-list') + $dom.innerHTML= result + window.pjax && window.pjax.refresh($dom) + } + + const getValineData = () => { + let serverURL = '' + if (!{Boolean(theme.newest_comments.leancloud.serverURL)}) { + serverURL = '!{theme.newest_comments.leancloud.serverURL}' + } else { + serverURL = 'https://!{theme.newest_comments.leancloud.appId.substring(0,8)}.api.lncldglobal.com' + } + + var settings = { + "url": `${serverURL}/1.1/classes/Comment?limit=!{theme.newest_comments.limit}&order=-createdAt`, + "method": "GET", + "timeout": 0, + "headers": { + "X-LC-Id": '!{theme.newest_comments.leancloud.appId}', + "X-LC-Key": '!{theme.newest_comments.leancloud.appKey}', + "Content-Type": "application/json" + }, + } + + $.ajax(settings).done((response) => { + var valineArray = [] + response.results.forEach((e)=>{ + valineArray.push({ + 'avatar': e.QQAvatar, + 'content': changeContent(e.comment), + 'mail': e.mail, + 'nick': e.nick, + 'url': e.url, + 'date': e.createdAt, + }) + }) + + saveToLocal.set('leancloud-newest-comments', JSON.stringify(valineArray), 10/(60*24)) + generateHtml(valineArray) + + }).fail(()=>{ + const $dom = document.querySelector('#card-newest-comments .aside-list') + $dom.innerHTML= "!{_p('aside.card_newest_comments.error')}" + }) + } + + const newestCommentInit = () => { + if (document.querySelector('#card-newest-comments .aside-list')) { + const data = saveToLocal.get('leancloud-newest-comments') + if (data) { + generateHtml(JSON.parse(data)) + } else { + getValineData() + } + } + } + + newestCommentInit() + document.addEventListener('pjax:complete', newestCommentInit) + }) diff --git a/themes/butterfly/layout/includes/third-party/pangu.pug b/themes/butterfly/layout/includes/third-party/pangu.pug new file mode 100644 index 0000000..229c69b --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/pangu.pug @@ -0,0 +1,19 @@ +script. + function panguFn () { + if (typeof pangu === 'object') pangu.spacingElementById('content-inner') + else { + $.getScript('!{url_for(theme.CDN.pangu)}', () => { + pangu.spacingElementById('content-inner') + }) + } + } + + function panguInit () { + if (!{theme.pangu.field === 'post'}){ + GLOBAL_CONFIG_SITE.isPost && panguFn() + } else { + panguFn() + } + } + + document.addEventListener('DOMContentLoaded', panguFn) diff --git a/themes/butterfly/layout/includes/third-party/pjax.pug b/themes/butterfly/layout/includes/third-party/pjax.pug new file mode 100644 index 0000000..e3c63be --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/pjax.pug @@ -0,0 +1,78 @@ +- var pjaxExclude = 'a:not([target="_blank"])' +if theme.pjax.exclude + each val in theme.pjax.exclude + - pjaxExclude = pjaxExclude + `:not([href="${val}"])` + +script(src=url_for(theme.CDN.pjax)) +script. + let pjaxSelectors = [ + 'title', + '#config_change', + '#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"]') + } + + var pjax = new Pjax({ + elements: '!{pjaxExclude}', + selectors: pjaxSelectors, + cacheBust: false, + analytics: !{theme.google_analytics ? true : false}, + scrollRestoration: false + }) + + document.addEventListener('pjax:complete', function () { + window.refreshFn() + + $('script[data-pjax]').each(function () { + $(this).parent().append($(this).remove()) + }) + + GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update() + + typeof chatBtnFn === 'function' && chatBtnFn() + typeof panguInit === 'function' && panguInit() + + if (typeof gtag === 'function') { + gtag('config', '!{theme.google_analytics}', {'page_path': window.location.pathname}); + } + + typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() + + // Analytics + if (!{theme.tencent_analytics ? true : false}) { + MtaH5.pgv() + } + + // prismjs + typeof Prism === 'object' && Prism.highlightAll() + + typeof preloader === 'object' && preloader.endLoading() + }) + + + document.addEventListener('pjax:send', function () { + typeof preloader === 'object' && preloader.initLoading() + + if (window.aplayers) { + for (let i = 0; i < window.aplayers.length; i++) { + if (!window.aplayers[i].options.fixed) { + window.aplayers[i].destroy() + } + } + } + + typeof typed === 'object' && typed.destroy() + + $(window).off('scroll') + + //reset readmode + $('body').hasClass('read-mode') && $('body').removeClass('read-mode') + + }) + diff --git a/themes/butterfly/layout/includes/third-party/prismjs.pug b/themes/butterfly/layout/includes/third-party/prismjs.pug new file mode 100644 index 0000000..b277e25 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/prismjs.pug @@ -0,0 +1,5 @@ +if config.prismjs && config.prismjs.enable && !config.prismjs.preprocess + script(src=url_for(theme.CDN.prismjs_js)) + script(src=url_for(theme.CDN.prismjs_autoloader)) + if config.prismjs.line_number + script(src=url_for(theme.CDN.prismjs_lineNumber_js)) diff --git a/themes/butterfly/layout/includes/third-party/search/algolia.pug b/themes/butterfly/layout/includes/third-party/search/algolia.pug new file mode 100644 index 0000000..6d22886 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/search/algolia.pug @@ -0,0 +1,13 @@ +#algolia-search + .search-dialog + #algolia-search-title.search-dialog__title Algolia + #algolia-input-panel + #algolia-search-input + hr + #algolia-search-results + #algolia-hits + #algolia-pagination + #algolia-stats + span.search-close-button + i.fas.fa-times + #search-mask diff --git a/themes/butterfly/layout/includes/third-party/search/index.pug b/themes/butterfly/layout/includes/third-party/search/index.pug new file mode 100644 index 0000000..c1bd03a --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/search/index.pug @@ -0,0 +1,4 @@ +if theme.algolia_search.enable + include ./algolia.pug +else if theme.local_search.enable + include ./local-search.pug \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/search/local-search.pug b/themes/butterfly/layout/includes/third-party/search/local-search.pug new file mode 100644 index 0000000..69570a2 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/search/local-search.pug @@ -0,0 +1,24 @@ +#local-search + .search-dialog + #local-search-title.search-dialog__title=_p("local_search.label") + #local-input-panel + #local-search-input + .local-search-box + input(placeholder=_p("local_search.input_placeholder") type="text").local-search-box--input + hr + #local-search-results + #local-hits + #local-stats + #hr.local-search-stats__hr + case config.language + when "zh-CN" + span=_p("local_search.by") + | #[a(href="https://github.com/wzpan/hexo-generator-search" style={'color': '#49B1F5'}) hexo-generator-search] + | #[span=_p("local_search.powered")] + when "en" + default + span=_p("local_search.powered_by") + | #[a(href="https://github.com/wzpan/hexo-generator-search" style={'color': '#49B1F5'}) hexo-generator-search] + span.search-close-button + i.fas.fa-times + #search-mask \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/share/add-this.pug b/themes/butterfly/layout/includes/third-party/share/add-this.pug new file mode 100644 index 0000000..ab44267 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/share/add-this.pug @@ -0,0 +1,2 @@ +.addthis_inline_share_toolbox +script(src=`//s7.addthis.com/js/300/addthis_widget.js#pubid=${theme.addThis.pubid}` async) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/share/addtoany.pug b/themes/butterfly/layout/includes/third-party/share/addtoany.pug new file mode 100644 index 0000000..a0a7aa2 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/share/addtoany.pug @@ -0,0 +1,10 @@ +.addtoany + .a2a_kit.a2a_kit_size_32.a2a_default_style + - let addtoanyItem = theme.addtoany.item.split(',') + each name in addtoanyItem + a(class="a2a_button_" + name) + + a.a2a_dd(href="https://www.addtoany.com/share") +script(async src=url_for(theme.CDN.addtoany)) + + diff --git a/themes/butterfly/layout/includes/third-party/share/index.pug b/themes/butterfly/layout/includes/third-party/share/index.pug new file mode 100644 index 0000000..41892a6 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/share/index.pug @@ -0,0 +1,7 @@ +.post_share + if theme.addThis.enable + !=partial('includes/third-party/share/add-this', {}, {cache:theme.fragment_cache}) + else if theme.sharejs.enable + include ./share-js.pug + else if theme.addtoany.enable + !=partial('includes/third-party/share/addtoany', {}, {cache:theme.fragment_cache}) diff --git a/themes/butterfly/layout/includes/third-party/share/share-js.pug b/themes/butterfly/layout/includes/third-party/share/share-js.pug new file mode 100644 index 0000000..538c905 --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/share/share-js.pug @@ -0,0 +1,3 @@ +.social-share(data-image=url_for(page.cover|| theme.avatar.img) data-sites= theme.sharejs.sites) +link(rel="stylesheet" href=url_for(theme.CDN.sharejs_css)) +script(src=url_for(theme.CDN.sharejs) defer) \ No newline at end of file diff --git a/themes/butterfly/layout/includes/third-party/subtitle.pug b/themes/butterfly/layout/includes/third-party/subtitle.pug new file mode 100644 index 0000000..ad995cc --- /dev/null +++ b/themes/butterfly/layout/includes/third-party/subtitle.pug @@ -0,0 +1,138 @@ +- var source = theme.subtitle.source +case source + when 1 + script. + function subtitleType () { + $.getJSON('https://api.btstu.cn/yan/api.php?charset=utf-8&encode=json',function (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)}', subtitleType) + } else { + subtitleType() + } + + when 2 + script. + function subtitleType () { + $.getJSON('https://v1.hitokoto.cn', function (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', { + strings: sub, + startDelay: 300, + typeSpeed: 150, + loop: !{theme.subtitle.loop}, + backSpeed: 50, + }) + } else { + document.getElementById('subtitle').innerHTML = data.hitokoto + } + }) + } + + if (!{theme.subtitle.effect}) { + if (typeof Typed === 'function') subtitleType() + else $.getScript('!{url_for(theme.CDN.typed)}', subtitleType) + } else { + subtitleType() + } + + when 3 + script. + function subtitleType () { + $.getScript('http://yijuzhan.com/api/word.php?m=js', function () { + 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', { + strings: sub, + startDelay: 300, + typeSpeed: 150, + loop: !{theme.subtitle.loop}, + backSpeed: 50, + }) + } else { + document.getElementById('subtitle').innerHTML = con + } + }) + } + + if (!{theme.subtitle.effect}) { + if (typeof Typed === 'function') subtitleType() + else $.getScript('!{url_for(theme.CDN.typed)}', subtitleType) + } else { + subtitleType() + } + + when 4 + script. + function subtitleType () { + $.getScript('https://sdk.jinrishici.com/v2/browser/jinrishici.js',function () { + 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', { + strings: sub, + startDelay: 300, + typeSpeed: 150, + loop: !{theme.subtitle.loop}, + backSpeed: 50, + }) + } else { + document.getElementById('subtitle').innerHTML = result.data.content + } + }) + }) + } + + if (!{theme.subtitle.effect}) { + if (typeof Typed === 'function') subtitleType() + else $.getScript('!{url_for(theme.CDN.typed)}', subtitleType) + } else { + subtitleType() + } + + default + script. + function subtitleType () { + if (!{theme.subtitle.effect}) { + var typed = new Typed("#subtitle", { + strings: "!{theme.subtitle.sub}".split(","), + startDelay: 300, + typeSpeed: 150, + loop: !{theme.subtitle.loop}, + backSpeed: 50 + }) + } else { + document.getElementById("subtitle").innerHTML = '!{theme.subtitle.sub[0]}' + } + } + + if (!{theme.subtitle.effect}) { + if (typeof Typed === 'function') subtitleType() + else $.getScript('!{url_for(theme.CDN.typed)}', subtitleType) + } else { + subtitleType() + } \ No newline at end of file diff --git a/themes/butterfly/layout/includes/widget/card_ad.pug b/themes/butterfly/layout/includes/widget/card_ad.pug new file mode 100644 index 0000000..c05f774 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_ad.pug @@ -0,0 +1,2 @@ +.card-widget.card-ad + != theme.ad.aside diff --git a/themes/butterfly/layout/includes/widget/card_announcement.pug b/themes/butterfly/layout/includes/widget/card_announcement.pug new file mode 100644 index 0000000..5f6fbd1 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_announcement.pug @@ -0,0 +1,6 @@ +.card-widget.card-announcement + .card-content + .item-headline + i.fas.fa-bullhorn.card-announcement-animation + span= _p('aside.card_announcement') + .announcement_content!= theme.aside.card_announcement.content \ No newline at end of file diff --git a/themes/butterfly/layout/includes/widget/card_archives.pug b/themes/butterfly/layout/includes/widget/card_archives.pug new file mode 100644 index 0000000..dfb5775 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_archives.pug @@ -0,0 +1,11 @@ +.card-widget.card-archives + .card-content + .item-headline + i.fas.fa-archive + span= _p('aside.card_archives') + + - let type = theme.aside.card_archives.type || 'monthly' + - let format = theme.aside.card_archives.format || 'MMMM YYYY' + - let order = theme.aside.card_archives.order || -1 + - let limit = theme.aside.card_archives.limit === 0 ? 0 : theme.aside.card_archives.limit || 8 + != aside_archives({ type:type, format: format, order: order, limit: limit }) diff --git a/themes/butterfly/layout/includes/widget/card_author.pug b/themes/butterfly/layout/includes/widget/card_author.pug new file mode 100644 index 0000000..b1faefb --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_author.pug @@ -0,0 +1,36 @@ +.card-widget.card-info + .card-content + .card-info-avatar.is-center + if theme.lazyload.enable + img.avatar-img(data-lazy-src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar") + else + img.avatar-img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar") + .author-info__name= config.author + .author-info__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 + + 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 + + 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 + + a#card-info-btn.button--animated(href=theme.aside.card_author.button.link) + i(class=theme.aside.card_author.button.icon) + span=theme.aside.card_author.button.text + + if(theme.social) + .card-info-social-icons.is-center + !=fragment_cache('social', function(){return partial('includes/header/social')}) diff --git a/themes/butterfly/layout/includes/widget/card_categories.pug b/themes/butterfly/layout/includes/widget/card_categories.pug new file mode 100644 index 0000000..55c1827 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_categories.pug @@ -0,0 +1,9 @@ +if site.categories.length + .card-widget.card-categories + .card-content + .item-headline + i.fas.fa-folder-open + span= _p('aside.card_categories') + !=aside_categories({ limit: theme.aside.card_categories.limit === 0 ? 0 : theme.aside.card_categories.limit || 8 , expand: theme.aside.card_categories.expand }) + + diff --git a/themes/butterfly/layout/includes/widget/card_newest_comment.pug b/themes/butterfly/layout/includes/widget/card_newest_comment.pug new file mode 100644 index 0000000..76a19aa --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_newest_comment.pug @@ -0,0 +1,7 @@ +.card-widget#card-newest-comments + .card-content + .item-headline + i.fas.fa-bolt + span= _p('aside.card_newest_comments.headline') + .aside-list + span= _p('aside.card_newest_comments.loading_text') diff --git a/themes/butterfly/layout/includes/widget/card_post_toc.pug b/themes/butterfly/layout/includes/widget/card_post_toc.pug new file mode 100644 index 0000000..065a457 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_post_toc.pug @@ -0,0 +1,13 @@ +- let tocNumber = page.toc_number !== undefined ? page.toc_number : theme.toc.number + +#card-toc.card-widget + .card-content + .item-headline + i.fas.fa-stream + span= _p('aside.card_toc') + + if (page.encrypt == true) + .toc-content.toc-div-class(style="display:none")!=toc(page.origin, {list_number: tocNumber}) + else + .toc-content!=toc(page.content, {list_number: tocNumber}) + \ No newline at end of file diff --git a/themes/butterfly/layout/includes/widget/card_recent_post.pug b/themes/butterfly/layout/includes/widget/card_recent_post.pug new file mode 100644 index 0000000..03cba6e --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_recent_post.pug @@ -0,0 +1,27 @@ +.card-widget.card-recent-post + .card-content + .item-headline + i.fas.fa-history + span= _p('aside.card_recent_post') + .aside-list + - let postLimit = theme.aside.card_recent_post.limit === 0 ? site.posts.length : theme.aside.card_recent_post.limit || 5 + - let sort = theme.aside.card_recent_post.sort === 'updated' ? 'updated' : 'date' + - site.posts.sort(sort, -1).limit(postLimit).each(function(article){ + - let link = article.link || article.path + - let title = article.title || _p('no_title') + - let no_cover = article.cover === false || !theme.cover.aside_enable ? 'no-cover' : '' + - let post_cover = article.cover + .aside-list-item(class=no_cover) + if post_cover && theme.cover.aside_enable + a.thumbnail(href=url_for(link) title=title) + if theme.lazyload.enable + img(data-lazy-src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) + else + img(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) + .content + a.title(href=url_for(link) title=title)= title + if theme.aside.card_recent_post.sort === 'updated' + time(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated)) #[=date(article.updated, config.date_format)] + else + time(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date)) #[=date(article.date, config.date_format)] + - }) diff --git a/themes/butterfly/layout/includes/widget/card_tags.pug b/themes/butterfly/layout/includes/widget/card_tags.pug new file mode 100644 index 0000000..4ca6ee6 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_tags.pug @@ -0,0 +1,12 @@ +if site.tags.length + .card-widget.card-tags + .card-content + .item-headline + i.fas.fa-tags + span= _p('aside.card_tags') + + - let tagLimit = theme.aside.card_tags.limit === 0 ? 0 : theme.aside.card_tags.limit || 40 + if theme.aside.card_tags.color + .card-tag-cloud!= cloudTags({source: site.tags, minfontsize: 1.1, maxfontsize: 1.5, limit: tagLimit, unit: 'em'}) + else + .card-tag-cloud!= tagcloud({min_font: 1.1, max_font: 1.5, amount: tagLimit , color: true, start_color: '#999', end_color: '#99a9bf', unit: 'em'}) diff --git a/themes/butterfly/layout/includes/widget/card_webinfo.pug b/themes/butterfly/layout/includes/widget/card_webinfo.pug new file mode 100644 index 0000000..ab96147 --- /dev/null +++ b/themes/butterfly/layout/includes/widget/card_webinfo.pug @@ -0,0 +1,31 @@ +.card-widget.card-webinfo + .card-content + .item-headline + i.fas.fa-chart-line + span= _p('aside.card_webinfo.headline') + .webinfo + if theme.aside.card_webinfo.post_count + .webinfo-item + .item-name= _p('aside.card_webinfo.article_name') + " :" + .item-count= site.posts.length + if theme.runtimeshow.enable + .webinfo-item + .item-name= _p('aside.card_webinfo.runtime.name') + " :" + .item-count#runtimeshow(data-publishDate=date_xml(theme.runtimeshow.publish_date)) + if theme.wordcount.enable && theme.wordcount.total_wordcount + .webinfo-item + .item-name=_p('aside.card_webinfo.site_wordcount') + " :" + .item-count=totalcount(site) + if theme.busuanzi.site_uv + .webinfo-item + .item-name= _p('aside.card_webinfo.site_uv_name') + " :" + .item-count#busuanzi_value_site_uv + if theme.busuanzi.site_pv + .webinfo-item + .item-name= _p('aside.card_webinfo.site_pv_name') + " :" + .item-count#busuanzi_value_site_pv + if theme.aside.card_webinfo.last_push_date + .webinfo-item + .item-name= _p('aside.card_webinfo.last_push_date.name') + " :" + .item-count#last-push-date(data-lastPushDate=date_xml(Date.now())) + diff --git a/themes/butterfly/layout/includes/widget/index.pug b/themes/butterfly/layout/includes/widget/index.pug new file mode 100644 index 0000000..ec2a80e --- /dev/null +++ b/themes/butterfly/layout/includes/widget/index.pug @@ -0,0 +1,28 @@ +#aside_content.aside_content + if theme.aside.card_author.enable + !=partial('includes/widget/card_author', {}, {cache:theme.fragment_cache}) + if theme.aside.card_announcement.enable + !=partial('includes/widget/card_announcement', {}, {cache:theme.fragment_cache}) + .sticky_layout + if is_post() + if showToc + include ./card_post_toc.pug + if theme.aside.card_recent_post.enable + !=partial('includes/widget/card_recent_post', {}, {cache:theme.fragment_cache}) + if theme.ad && theme.ad.aside + !=partial('includes/widget/card_ad', {}, {cache:theme.fragment_cache}) + else + if theme.aside.card_recent_post.enable + !=partial('includes/widget/card_recent_post', {}, {cache:theme.fragment_cache}) + if theme.ad && theme.ad.aside + !=partial('includes/widget/card_ad', {}, {cache:theme.fragment_cache}) + if theme.newest_comments.enable + !=partial('includes/widget/card_newest_comment', {}, {cache:theme.fragment_cache}) + if theme.aside.card_categories.enable + !=partial('includes/widget/card_categories', {}, {cache:theme.fragment_cache}) + if theme.aside.card_tags.enable + !=partial('includes/widget/card_tags', {}, {cache:theme.fragment_cache}) + if theme.aside.card_archives.enable + !=partial('includes/widget/card_archives', {}, {cache:theme.fragment_cache}) + if theme.aside.card_webinfo.enable + !=partial('includes/widget/card_webinfo', {}, {cache:theme.fragment_cache}) \ No newline at end of file diff --git a/themes/butterfly/layout/index.pug b/themes/butterfly/layout/index.pug new file mode 100644 index 0000000..2655cb4 --- /dev/null +++ b/themes/butterfly/layout/index.pug @@ -0,0 +1,7 @@ +extends includes/layout.pug + +block content + include ./includes/mixins/post-ui.pug + #recent-posts.recent-posts + +postUI + include includes/pagination.pug \ No newline at end of file diff --git a/themes/butterfly/layout/page.pug b/themes/butterfly/layout/page.pug new file mode 100644 index 0000000..474580d --- /dev/null +++ b/themes/butterfly/layout/page.pug @@ -0,0 +1,19 @@ +extends includes/layout.pug + +block content + #page + case page.type + when 'tags' + include includes/page/tags.pug + when 'link' + include includes/page/flink.pug + when 'categories' + include includes/page/categories.pug + when 'artitalk' + include includes/page/artitalk.pug + default + include includes/page/default-page.pug + + if page.comments !== false && theme.comments && theme.comments.use + - var commentsJsLoad = true + !=partial('includes/third-party/comments/index', {}, {cache:theme.fragment_cache}) \ No newline at end of file diff --git a/themes/butterfly/layout/post.pug b/themes/butterfly/layout/post.pug new file mode 100644 index 0000000..c57d99e --- /dev/null +++ b/themes/butterfly/layout/post.pug @@ -0,0 +1,31 @@ +extends includes/layout.pug + +block content + #post + if top_img === false + include includes/header/post-info.pug + + article#article-container.post-content!=page.content + include includes/post/post-copyright.pug + .tag_share + if (theme.post_meta.post.tags) + .post-meta__tag-list + each item, index in page.tags.data + a(href=url_for(item.path)).post-meta__tags #[=item.name] + include includes/third-party/share/index.pug + + if theme.reward.enable + !=partial('includes/post/reward', {}, {cache:theme.fragment_cache}) + + //- ad + if theme.ad && theme.ad.post + .post-ad!=theme.ad.post + + include includes/pagination.pug + if theme.related_post && theme.related_post.enable + != related_posts(page,site.posts) + + if page.comments !== false && theme.comments && theme.comments.use + - var commentsJsLoad = true + !=partial('includes/third-party/comments/index', {}, {cache:theme.fragment_cache}) + \ No newline at end of file diff --git a/themes/butterfly/layout/tag.pug b/themes/butterfly/layout/tag.pug new file mode 100644 index 0000000..9f99658 --- /dev/null +++ b/themes/butterfly/layout/tag.pug @@ -0,0 +1,14 @@ +extends includes/layout.pug + +block content + if theme.tag_ui == 'index' + include ./includes/mixins/post-ui.pug + #recent-posts.recent-posts + +postUI + include includes/pagination.pug + else + include ./includes/mixins/article-sort.pug + #tag + .article-sort-title= _p('page.tag') + ' - ' + page.tag + +articleSort(page.posts) + include includes/pagination.pug \ No newline at end of file diff --git a/themes/butterfly/package.json b/themes/butterfly/package.json new file mode 100644 index 0000000..180092b --- /dev/null +++ b/themes/butterfly/package.json @@ -0,0 +1,32 @@ +{ + "name": "hexo-theme-butterfly", + "version": "3.3.0", + "description": "A Simple and Card UI Design theme for Hexo", + "main": "package.json", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [ + "hexo", + "theme", + "butterfly", + "Card UI Design", + "Jerry", + "hexo-theme-butterfly" + ], + "repository": { + "type" : "git", + "url" : "https://github.com/jerryc127/hexo-theme-butterfly.git" + }, + "bugs": { + "url": "https://github.com/jerryc127/hexo-theme-butterfly/issues", + "email": "wong@jerryc.me" + }, + "dependencies": { + "hexo-renderer-stylus": "^2.0.1", + "hexo-renderer-pug": "^1.0.0" + }, + "homepage": "https://demo.jerryc.me/", + "author": "Jerry ", + "license": "Apache-2.0" +} diff --git a/themes/butterfly/scripts/events/404.js b/themes/butterfly/scripts/events/404.js new file mode 100644 index 0000000..c37daae --- /dev/null +++ b/themes/butterfly/scripts/events/404.js @@ -0,0 +1,15 @@ +/** + * Butterfly + * 404 error page + */ + +'use strict' + +hexo.extend.generator.register('404', function (locals) { + if (!hexo.theme.config.error_404.enable) return + return { + path: '404.html', + data: locals.posts, + layout: ['404'] + } +}) diff --git a/themes/butterfly/scripts/events/init.js b/themes/butterfly/scripts/events/init.js new file mode 100644 index 0000000..c198e9e --- /dev/null +++ b/themes/butterfly/scripts/events/init.js @@ -0,0 +1,27 @@ +const logger = require('hexo-log')() + +hexo.extend.filter.register('before_generate', () => { + // Get first two digits of the Hexo version number + var hexoVer = hexo.version.replace(/(^.*\..*)\..*/, '$1') + + if (hexoVer < 5) { + logger.error('Please update Hexo to V5.0.0 or higher!') + logger.error('請把 Hexo 升級到 V5.0.0 或更高的版本!') + process.exit(-1) + } + + if (hexo.locals.get) { + const data = hexo.locals.get('data') + if (data && data.butterfly) { + logger.error(" 'butterfly.yml' is deprecated. Please use '_config.butterfly.yml' ") + logger.error(" 'butterfly.yml' 已經棄用,請使用 '_config.butterfly.yml' ") + 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/themes/butterfly/scripts/events/welcome.js b/themes/butterfly/scripts/events/welcome.js new file mode 100644 index 0000000..f6650f9 --- /dev/null +++ b/themes/butterfly/scripts/events/welcome.js @@ -0,0 +1,17 @@ +const logger = require('hexo-log')() + +hexo.on('ready', () => { + const { version } = require('../../package.json') + logger.info(` + =================================================================== + + ##### # # ##### ##### ###### ##### ###### # # # + # # # # # # # # # # # # # + ##### # # # # ##### # # ##### # # + # # # # # # # ##### # # # + # # # # # # # # # # # # + ##### #### # # ###### # # # ###### # + + ${version} + ===================================================================`) +}) diff --git a/themes/butterfly/scripts/filters/post_lazyload.js b/themes/butterfly/scripts/filters/post_lazyload.js new file mode 100644 index 0000000..c279633 --- /dev/null +++ b/themes/butterfly/scripts/filters/post_lazyload.js @@ -0,0 +1,16 @@ +/** + * Butterfly + * lazyload + * replace src to data-lazy-src + */ + +'use strict' + +const urlFor = require('hexo-util').url_for.bind(hexo) + +hexo.extend.filter.register('after_post_render', data => { + if (!hexo.theme.config.lazyload.enable) return + const bg = hexo.theme.config.lazyload.post ? urlFor(hexo.theme.config.lazyload.post) : 'data:image/gif;base64,R0lGODdhAQABAPAAAMPDwwAAACwAAAAAAQABAAACAkQBADs=' + data.content = data.content.replace(/( yearA === yearB && monthA === monthB + : (yearA, monthA, yearB, monthB) => yearA === yearB + const limit = options.limit + const moreButton = this._p('aside.more_button') + let result = '' + + if (!format) { + format = type === 'monthly' ? 'MMMM YYYY' : 'YYYY' + } + + const posts = this.site.posts.sort('date', order) + if (!posts.length) return result + + const data = [] + let length = 0 + + posts.forEach(post => { + // Clone the date object to avoid pollution + let date = post.date.clone() + + if (timezone) date = date.tz(timezone) + + const year = date.year() + const month = date.month() + 1 + const lastData = data[length - 1] + + if (!lastData || !compareFunc(lastData.year, lastData.month, year, month)) { + if (lang) date = date.locale(lang) + const name = date.format(format) + length = data.push({ + name, + year, + month, + count: 1 + }) + } else { + lastData.count++ + } + }) + + const link = item => { + let url = `${archiveDir}/${item.year}/` + + if (type === 'monthly') { + if (item.month < 10) url += '0' + url += `${item.month}/` + } + + return this.url_for(url) + } + + result += '' + return result +}) + +const toMomentLocale = function (lang) { + if (lang === undefined) { + return undefined + } + + // moment.locale('') equals moment.locale('en') + // moment.locale(null) equals moment.locale('en') + if (!lang || lang === 'en' || lang === 'default') { + return 'en' + } + return lang.toLowerCase().replace('_', '-') +} diff --git a/themes/butterfly/scripts/helpers/aside_categories.js b/themes/butterfly/scripts/helpers/aside_categories.js new file mode 100644 index 0000000..a787bad --- /dev/null +++ b/themes/butterfly/scripts/helpers/aside_categories.js @@ -0,0 +1,96 @@ +/** + * Butterfly + * for aside categories + */ + +'use strict' + +hexo.extend.helper.register('aside_categories', function (categories, options) { + if (!options && (!categories || !Object.prototype.hasOwnProperty.call(categories, 'length')) + ) { + options = categories + categories = this.site.categories + } + + if (!categories || !categories.length) return '' + options = options || {} + const { config } = this + const showCount = Object.prototype.hasOwnProperty.call(options, 'show_count') + ? options.show_count + : true + const depth = options.depth ? parseInt(options.depth, 10) : 0 + const orderby = options.orderby || 'name' + const order = options.order || 1 + const categoryDir = this.url_for(config.category_dir) + const limit = options.limit === 0 ? categories.length : options.limit + const isExpand = options.expand !== 'none' + const expandClass = isExpand && options.expand === true ? 'expand' : '' + + const buttonLabel = this._p('aside.more_button') + const prepareQuery = (parent) => { + const query = {} + if (parent) { query.parent = parent } else { query.parent = { $exists: false } } + return categories.find(query).sort(orderby, order).filter((cat) => cat.length) + } + + const hierarchicalList = (t, level, parent, topparent = true) => { + let result = '' + const isTopParent = topparent + if (t > 0) { + prepareQuery(parent).forEach((cat, i) => { + if (t > 0) { + t = t - 1 + let child + if (!depth || level + 1 < depth) { + const childList = hierarchicalList(t, level + 1, cat._id, false) + child = childList[0] + t = childList[1] + } + + const parentClass = isExpand && isTopParent && child ? 'parent' : '' + + result += `
  • ` + + result += `` + + result += `${cat.name}` + + if (showCount) { + result += `${cat.length}` + } + + if (isExpand && isTopParent && child) { + result += `` + } + + result += '' + + result += '
  • ' + + if (child) { + result += `` + } + } + }) + } + + return [result, t] + } + + const list = hierarchicalList(limit, 0) + + const moreButton = function () { + let moreHtml = '' + if (categories.length <= limit) return '' + moreHtml += '
  • ' + moreHtml += ` + ${buttonLabel}
  • ` + + return moreHtml + } + + return `` +}) diff --git a/themes/butterfly/scripts/helpers/page.js b/themes/butterfly/scripts/helpers/page.js new file mode 100644 index 0000000..fd44158 --- /dev/null +++ b/themes/butterfly/scripts/helpers/page.js @@ -0,0 +1,72 @@ +/** + * Butterfly + * @example + * page_description() + * cloudTags(source, minfontsize, maxfontsize, limit) + */ + +'use strict' + +const { stripHTML, escapeHTML, prettyUrls } = require('hexo-util') +const crypto = require('crypto') + +hexo.extend.helper.register('page_description', function () { + const { config, page } = this + let description = page.description || page.content || page.title || config.description + + if (description) { + description = escapeHTML(stripHTML(description).substring(0, 200) + .trim() + ).replace(/\n/g, ' ') + return description + } +}) + +hexo.extend.helper.register('cloudTags', function (options = {}) { + const env = this + let source = options.source + const minfontsize = options.minfontsize + const maxfontsize = options.maxfontsize + const limit = options.limit + const unit = options.unit || 'px' + + let result = '' + if (limit > 0) { + source = source.limit(limit) + } + + const sizes = [] + source.sort('length').forEach(tag => { + const { length } = tag + if (sizes.includes(length)) return + sizes.push(length) + }) + + const length = sizes.length - 1 + source.forEach(tag => { + const ratio = length ? sizes.indexOf(tag.length) / length : 0 + const size = minfontsize + ((maxfontsize - minfontsize) * ratio) + let style = `font-size: ${parseFloat(size.toFixed(2))}${unit};` + const color = 'rgb(' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ', ' + Math.floor(Math.random() * 201) + ')' // 0,0,0 -> 200,200,200 + style += ` color: ${color}` + result += `${tag.name}` + }) + return result +}) + +hexo.extend.helper.register('urlNoIndex', function () { + return prettyUrls(this.url, { trailing_index: false, trailing_html: false }) +}) + +hexo.extend.helper.register('md5', function (path) { + return crypto.createHash('md5').update(decodeURI(this.url_for(path))).digest('hex') +}) + +hexo.extend.helper.register('injectHtml', function (data) { + let result = '' + if (!data) return '' + for (let i = 0; i < data.length; i++) { + result += data[i] + } + return result +}) diff --git a/themes/butterfly/scripts/helpers/related_post.js b/themes/butterfly/scripts/helpers/related_post.js new file mode 100644 index 0000000..24992b4 --- /dev/null +++ b/themes/butterfly/scripts/helpers/related_post.js @@ -0,0 +1,123 @@ +/** + * Butterfly + * Related Posts + * According the tag + */ + +'use strict' + +hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { + let relatedPosts = [] + currentPost.tags.forEach(function (tag) { + allPosts.forEach(function (post) { + if (isTagRelated(tag.name, post.tags)) { + const relatedPost = { + title: post.title, + path: post.path, + cover: post.cover, + randomcover: post.randomcover, + weight: 1, + updated: post.updated, + created: post.date + } + const index = findItem(relatedPosts, 'path', post.path) + if (index !== -1) { + relatedPosts[index].weight += 1 + } else { + if (currentPost.path !== post.path) { + relatedPosts.push(relatedPost) + } + } + } + }) + }) + if (relatedPosts.length === 0) { + return '' + } + let result = '' + const hexoConfig = hexo.config + const config = hexo.theme.config + + const limitNum = config.related_post.limit || 6 + const dateType = config.related_post.date_type || 'created' + const headlineLang = this._p('post.recommend') + const lazySrc = config.lazyload.enable ? 'data-lazy-src' : 'src' + + relatedPosts = relatedPosts.sort(compare('weight')) + + if (relatedPosts.length > 0) { + result += '