diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c3e26b6..d12e9e8 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -7,11 +7,12 @@ body: attributes: value: | 重要:請依照該模板來提交 - Please follow the template to create a new issue + Important: Please follow the template to create a new issue + - type: input id: butterfly-ver attributes: - label: 使用的 Butterfly 版本? | What version of Butterfly are you use? + label: 使用的 Butterfly 版本? | What version of Butterfly are you using? description: 檢視主題的 package.json | Check the theme's package.json validations: required: true @@ -19,17 +20,17 @@ body: - type: dropdown id: modify attributes: - label: 是否修改过主题文件? || Has the theme files been modified? + label: 是否修改過主題文件? | Has the theme files been modified? options: - 是 (Yes) - - 不是 (No) + - 否 (No) validations: required: true - type: dropdown id: browser attributes: - label: 使用的瀏覽器? || What browse are you using? + label: 使用的瀏覽器? | What browser are you using? options: - Chrome - Edge @@ -42,7 +43,7 @@ body: - type: dropdown id: platform attributes: - label: 使用的系統? || What operating system are you using? + label: 使用的系統? | What operating system are you using? options: - Windows - macOS @@ -56,8 +57,8 @@ body: - type: textarea id: dependencies attributes: - label: 依賴插件 | Package dependencies Information - description: 在 Hexo 根目錄下執行`npm ls --depth 0` | Run `npm ls --depth 0` in Hexo root directory + label: 依賴插件 | Package dependencies information + description: 在 Hexo 根目錄下執行 `npm ls --depth 0` | Run `npm ls --depth 0` in Hexo root directory render: Text validations: required: true @@ -75,8 +76,8 @@ body: - type: input id: website attributes: - label: 出現問題網站 | Website - description: 請提供下可復現網站地址 | Please supply a website url which can reproduce problem. - placeholder: + label: 出現問題的網站 | Website with the issue + description: 請提供可復現問題的網站地址 | Please provide a website URL where the problem can be reproduced. + placeholder: 請填寫具體的網址,不要填寫 localhost 網站 | Please provide a specific URL, do not use localhost. validations: - required: true + required: true \ No newline at end of file diff --git a/README.md b/README.md index 2939151..dfa63f8 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ 中文 +
+ + + # hexo-theme-butterfly ![master version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly/master?color=%231ab1ad&label=master) @@ -10,13 +14,15 @@ ![hexo version](https://img.shields.io/badge/hexo-5.3.0+-0e83c) ![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) +📢 Demo: [Butterfly](https://butterfly.js.org/) / [CrazyWong](https://blog.crazywong.com/) -📢 Demo: [Butterfly](https://butterfly.js.org/) || [CrazyWong](https://blog.crazywong.com/) +📖 Docs: [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) / [Chinese](https://butterfly.js.org/posts/21cfbf15/) -📖 Docs: [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) || [Chinese](https://butterfly.js.org/posts/21cfbf15/) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) + +
-Based on [hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody) theme. +--- ## 💻 Installation @@ -59,6 +65,7 @@ npm i hexo-theme-butterfly ## 🎉 Features - [x] Card UI Design +- [x] Rounded Design/Squared Design - [X] Support sub-menu - [x] Two-column layout - [x] Responsive Web Design diff --git a/README_CN.md b/README_CN.md index 7105630..bda0400 100644 --- a/README_CN.md +++ b/README_CN.md @@ -2,6 +2,10 @@ English +
+ + + # hexo-theme-butterfly ![master version](https://img.shields.io/github/package-json/v/jerryc127/hexo-theme-butterfly/master?color=%231ab1ad&label=master) @@ -10,13 +14,15 @@ ![hexo version](https://img.shields.io/badge/hexo-5.3.0+-0e83c) ![license](https://img.shields.io/github/license/jerryc127/hexo-theme-butterfly?color=FF5531) -![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) +📢 預覽: [Butterfly](https://butterfly.js.org/) / [CrazyWong](https://blog.crazywong.com/) -📢 預覽: [Butterfly](https://butterfly.js.org/) || [CrazyWong](https://blog.crazywong.com/) +📖 文檔: [中文](https://butterfly.js.org/posts/21cfbf15/) / [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) -📖 文檔: [中文](https://butterfly.js.org/posts/21cfbf15/) || [English](https://butterfly.js.org/en/posts/butterfly-docs-en-get-started/) +![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png) + +
-一款基於[hexo-theme-melody](https://github.com/Molunerfinn/hexo-theme-melody)修改的主題 +--- ## 💻 安裝 @@ -59,6 +65,7 @@ theme: butterfly ## 🎉 特色 - [x] 卡片化設計 +- [x] 圓角化設計/直角化設計 - [X] 支持二級目錄 - [x] 雙欄設計 - [x] 響應式主題 diff --git a/_config.yml b/_config.yml index 8ce3b49..cd7b323 100644 --- a/_config.yml +++ b/_config.yml @@ -1,99 +1,109 @@ -# Navigation bar settings (導航欄設置) -# see https://butterfly.js.org/posts/4aa8abbe/##導航欄設置-Navigation-bar-settings +# -------------------------------------- +# Hexo Butterfly Theme Configuration +# If you have any questions, please refer to the documentation +# Chinese: https://butterfly.js.org/ +# English: https://butterfly.js.org/en/ +# -------------------------------------- + +# -------------------------------------- +# Navigation Settings # -------------------------------------- nav: - logo: # image + # Navigation bar logo image + logo: display_title: true - fixed: false # fixed navigation bar + # Whether to fix navigation bar + fixed: false -# Menu 目錄 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 -# Code Blocks (代碼相關) +# -------------------------------------- +# Code Blocks Settings # -------------------------------------- -highlight_theme: light # darker / pale night / light / ocean / false -highlight_height_limit: false # unit: px -code_word_wrap: false - -# highlight toolbar -highlight_theme_macStyle: false # use mac style -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 -highlight_fullpage: true # true: add button to toggle full page - -# Social Settings (社交圖標設置) -# formal: +code_blocks: + # Code block theme: darker / pale night / light / ocean / false + theme: light + macStyle: false + # Code block height limit (unit: px) + height_limit: false + word_wrap: false + + # Toolbar + copy: true + language: true + # true: shrink the code blocks | false: expand the code blocks | none: expand code blocks and hide the button + shrink: false + fullpage: false + +# Social media links +# Formal: # icon: link || the description || color social: # fab fa-github: https://github.com/xxxxx || Github || '#24292e' # fas fa-envelope: mailto:xxxxxx@gmail.com || Email || '#4a7dbe' -# Image (圖片設置) +# -------------------------------------- +# Image Settings # -------------------------------------- -# Favicon(網站圖標) favicon: /img/favicon.png -# Avatar (頭像) avatar: - img: https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png + img: /img/butterfly-icon.png effect: false -# Disable all banner image +# Disable all banner images disable_top_img: false -# The banner image of home page -index_img: - -# If the banner of page not setting, it will show the top_img +# If the banner of page not setting, it will show the default_top_img default_top_img: +# The banner image of index page +index_img: + # The banner image of archive page archive_img: -# If the banner of tag page not setting, it will show the top_img -# note: tag page, not tags page (子標籤頁面的 top_img) +# Note: tag page, not tags page tag_img: -# The banner image of tag page -# format: +# The banner image of tag page, you can set the banner image for each tag +# 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) +# Note: category page, not categories page category_img: -# The banner image of category page -# format: +# The banner image of category page, you can set the banner image for each category +# Format: # - category name: xxxxx category_per_img: +# The background image of footer +footer_img: false + +# Website Background +# Can set it to color or image +# The formal of image: url(http://xxxxxx.com/xxx.jpg) +background: + cover: - # display the cover or not (是否顯示文章封面) + # Disable 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時,默認的封面顯示) + # When cover is not set, the default cover is displayed default_cover: - # - https://i.loli.net/2020/05/01/gkihqEjXxJ5UZ1C.jpg + # - xxx.jpg -# Replace Broken Images (替換無法顯示的圖片) +# Replace Broken Images error_img: flink: /img/friend_404.gif post_page: /img/404.jpg @@ -102,22 +112,68 @@ error_img: error_404: enable: false subtitle: 'Page Not Found' - background: https://i.loli.net/2020/05/19/aKOcLiyPl2JQdFD.png + background: /img/error-page.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 顯示描述性文字 + # Home Page + page: + # Choose: created / updated / both + date_type: created + # Choose: date / relative + date_format: date + categories: true + tags: false + label: true post: - position: left # left or center 文章頁標題位置 - 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 顯示描述性文字 + # Choose: left / center + position: left + # Choose: created / updated / both + date_type: both + # Choose: date / relative + date_format: date + categories: true + tags: true + label: true + +# -------------------------------------- +# Index page settings +# -------------------------------------- + +# The top_img settings of home page +# default: top img - full screen, site info - middle +# The position of site info, eg: 300px/300em/300rem/10% +index_site_info_top: +# The height of top_img, eg: 300px/300em/300rem +index_top_img_height: + +# The subtitle on homepage +subtitle: + enable: false + # Typewriter Effect + effect: true + # Customize typed.js + # https://github.com/mattboldt/typed.js/#customization + typed_option: + # Source - Call the third-party service API (Chinese only) + # It will show the source first, then show the content of sub + # Choose: false/1/2/3 + # false - disable the function + # 1 - hitokoto.cn + # 2 - yijuzhan.com + # 3 - jinrishici.com + source: false + # If you close the typewriter effect, the subtitle will only show the first line of sub + sub: + +# Article layout on the homepage +# 1: Cover on the left, info on the right +# 2: Cover on the right, info on the left +# 3: Cover and info alternate between left and right +# 4: Cover on top, info on the bottom +# 5: Info displayed on the cover +# 6: Masonry layout - Cover on top, info on the bottom +# 7: Masonry layout - Info displayed on the cover +index_layout: 3 # Display the article introduction on homepage # 1: description @@ -126,36 +182,20 @@ post_meta: # 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 - -# anchor -anchor: - # when you scroll, the URL will update according to header id. - auto_update: false - # Click the headline to scroll and update the anchor - click_to_scroll: false - -# figcaption (圖片描述文字) -photofigcaption: false - -# copy settings -# copyright: Add the copyright information after copied content (複製的內容後面加上版權信息) -copy: - enable: true - copyright: - enable: false - limit_count: 50 + # If you set method to 2 or 3, the length need to config + length: 500 -# Post +# -------------------------------------- +# Post Settings # -------------------------------------- -# toc (目錄) toc: post: true page: false number: true expand: false - style_simple: false # for post + # Only for post + style_simple: false scroll_percent: true post_copyright: @@ -188,43 +228,52 @@ post_edit: # Related Articles related_post: enable: true - limit: 6 # Number of posts displayed - date_type: created # or created or updated 文章日期顯示創建日或者更新日 + # Number of posts displayed + limit: 6 + # Choose: created / updated + date_type: created -# post_pagination (分頁) -# value: 1 || 2 || false +# Choose: 1 / 2 / false # 1: The 'next post' will link to old post # 2: The 'next post' will link to new post # false: disable pagination post_pagination: 1 -# Displays outdated notice for a post (文章過期提醒) +# 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 + # Style: simple / flat + style: flat + # When will it be shown + limit_day: 365 + # Position: top / bottom + position: top message_prev: It has been message_next: days since the last update, the content of the article may be outdated. +# -------------------------------------- # Footer Settings # -------------------------------------- footer: owner: enable: true - since: 2020 + since: 2019 custom_text: - copyright: true # Copyright of theme and framework + # Copyright of theme and framework + copyright: true -# aside (側邊欄) +# -------------------------------------- +# Aside Settings # -------------------------------------- aside: enable: true hide: false + # Show the button to hide the aside in bottom right button button: true - mobile: true # display on mobile - position: right # left or right + mobile: true + # Position: left / right + position: right display: archive: true tag: true @@ -242,64 +291,72 @@ aside: content: This is my Blog card_recent_post: enable: true - limit: 5 # if set 0 will show all - sort: date # date or updated - sort_order: # Don't modify the setting unless you know how it works + # If set 0 will show all + limit: 5 + # Sort: date / updated + sort: date + sort_order: + card_newest_comments: + enable: false + sort_order: + limit: 6 + # Unit: mins, save data to localStorage + storage: 10 + avatar: true card_categories: enable: true - limit: 8 # if set 0 will show all - expand: none # none/true/false - sort_order: # Don't modify the setting unless you know how it works + # If set 0 will show all + limit: 8 + # Choose: none / true / false + expand: none + sort_order: card_tags: enable: true - limit: 40 # if set 0 will show all + # If set 0 will show all + limit: 40 color: false - orderby: random # Order of tags, random/name/length - order: 1 # Sort of order. 1, asc for ascending; -1, desc for descending - sort_order: # Don't modify the setting unless you know how it works + # Order of tags, random/name/length + orderby: random + # Sort of order. 1, asc for ascending; -1, desc for descending + order: 1 + sort_order: card_archives: enable: true - type: monthly # yearly 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 - sort_order: # Don't modify the setting unless you know how it works + # Type: monthly / yearly + type: monthly + # Eg: YYYY年MM月 + format: MMMM YYYY + # Sort of order. 1, asc for ascending; -1, desc for descending + order: -1 + # If set 0 will show all + limit: 8 + sort_order: + card_post_series: + enable: true + # The title shows the series name + series_title: false + # Order by title or date + orderBy: 'date' + # Sort of order. 1, asc for ascending; -1, desc for descending + order: -1 card_webinfo: enable: true post_count: true last_push_date: true - sort_order: # Don't modify the setting unless you know how it works - card_post_series: - enable: true - series_title: false # The title shows the series name - orderBy: 'date' # Order by title or date - order: -1 # Sort of order. 1, asc for ascending; -1, desc for descending + sort_order: + # Time difference between publish date and now + # Formal: Month/Day/Year Time or Year/Month/Day Time + # Leave it empty if you don't enable this feature + runtime_date: -# 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 - sort_order: # Don't modify the setting unless you know how it works - limit: 6 - storage: 10 # unit: mins, save data to localStorage - avatar: true - -# Bottom right button (右下角按鈕) # -------------------------------------- +# Bottom right button +# -------------------------------------- + +# The distance between the bottom right button and the bottom (default unit: px) +rightside_bottom: -# Conversion between Traditional and Simplified Chinese (簡繁轉換) +# Conversion between Traditional and Simplified Chinese translate: enable: false # The text of a button @@ -313,130 +370,187 @@ translate: # The text of the button when the language is Traditional Chinese msgToSimplifiedChinese: '簡' -# Read Mode (閲讀模式) +# Read Mode readmode: true -# dark mode +# Dark Mode darkmode: enable: true # Toggle Button to switch dark/light mode button: true - # Switch dark/light mode automatically (自動切換 dark mode和 light mode) + # Switch dark/light mode automatically # autoChangeMode: 1 Following System Settings, if the system doesn't support dark mode, it will switch dark mode between 6 pm to 6 am # autoChangeMode: 2 Switch dark mode between 6 pm to 6 am # autoChangeMode: false autoChangeMode: false # Set the light mode time. The value is between 0 and 24. If not set, the default value is 6 and 18 - start: # 8 - end: # 22 + start: + end: -# show scroll percent in scroll-to-top button +# Show scroll percent in scroll-to-top button rightside_scroll_percent: false -# Don't modify the following settings unless you know how they work (非必要請不要修改 ) +# Don't modify the following settings unless you know how they work # Choose: readmode,translate,darkmode,hideAside,toc,chat,comment -# Don't repeat 不要重複 +# Don't repeat the same value rightside_item_order: enable: false - hide: # readmode,translate,darkmode,hideAside - show: # toc,chat,comment + # Default: readmode,translate,darkmode,hideAside + hide: + # Default: toc,chat,comment + show: -# 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) +# Global Settings +# -------------------------------------- -# MathJax -mathjax: - enable: false - per_page: false +anchor: + # When you scroll, the URL will update according to header id. + auto_update: false + # Click the headline to scroll and update the anchor + click_to_scroll: false + +photofigcaption: false -# KaTeX -katex: +copy: + enable: true + # Add the copyright information after copied content + copyright: + enable: false + limit_count: 150 + +# Need to install the hexo-wordcount plugin +wordcount: enable: false - per_page: false - hide_scrollbar: true + # Display the word count of the article in post meta + post_wordcount: true + # Display the time to read the article in post meta + min2read: true + # Display the total word count of the website in aside's webinfo + total_wordcount: true + +# Busuanzi count for PV / UV in site +busuanzi: + site_uv: true + site_pv: true + page_pv: true -# search (搜索) -# see https://butterfly.js.org/posts/ceeb73f/#搜索系統 +# -------------------------------------- +# Math # -------------------------------------- -# Algolia search -algolia_search: - enable: false - hits: - per_page: 6 +# About the per_page +# if you set it to true, it will load mathjax/katex script in each page +# if you set it to false, it will load mathjax/katex script according to your setting (add the 'mathjax: true' or 'katex: true' in page's front-matter) +math: + # Choose: mathjax, katex + # Leave it empty if you don't need math + use: + per_page: true + hide_scrollbar: false -# Local search -local_search: - enable: false - # Preload the search data when the page loads. - preload: false - # Show top n results per article, show all results by setting to -1 - top_n_per_article: 1 - # Unescape html strings to the readable one. - unescape: false - CDN: - -# Docsearch -docsearch: - enable: false - appId: - apiKey: - indexName: - option: + mathjax: + # Enable the contextual menu + enableMenu: true + # Choose: all / ams / none, This controls whether equations are numbered and how + tags: none + + katex: + # Enable the copy KaTeX formula + copy_tex: false -# Share System (分享) +# -------------------------------------- +# Search # -------------------------------------- -# Share.js -# https://github.com/overtrue/share.js -sharejs: - enable: true - sites: facebook,twitter,wechat,weibo,qq +search: + # Choose: algolia_search / local_search / docsearch + # leave it empty if you don't need search + use: + placeholder: -# AddToAny -# https://www.addtoany.com/ -addtoany: - enable: false - item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link + # Algolia Search + algolia_search: + # Number of search results per page + hitsPerPage: 6 + + # Local Search + local_search: + # Preload the search data when the page loads. + preload: false + # Show top n results per article, show all results by setting to -1 + top_n_per_article: 1 + # Unescape html strings to the readable one. + unescape: false + CDN: + + # Docsearch + # https://docsearch.algolia.com/ + docsearch: + appId: + apiKey: + indexName: + option: +# -------------------------------------- +# Share System +# -------------------------------------- + +share: + # Choose: sharejs / addtoany + # Leave it empty if you don't need share + use: sharejs + + # Share.js + # https://github.com/overtrue/share.js + sharejs: + sites: facebook,twitter,wechat,weibo,qq + + # AddToAny + # https://www.addtoany.com/ + addtoany: + item: facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link + +# -------------------------------------- # Comments System # -------------------------------------- comments: # Up to two comments system, the first will be shown as default + # Leave it empty if you don't need comments # Choose: Disqus/Disqusjs/Livere/Gitalk/Valine/Waline/Utterances/Facebook Comments/Twikoo/Giscus/Remark42/Artalk - 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. + # Format of two comments system : Disqus,Waline + use: + # Display the comment name next to the button + text: true + # Lazyload: The comment system will be load when comment element enters the browser's viewport. # If you set it to true, the comment count will be invalid lazyload: false - count: false # Display comment count in post's top_img - card_post_count: false # Display comment count in Home Page + # Display comment count in post's top_img + count: false + # Display comment count in Home Page + card_post_count: false -# disqus +# Disqus # https://disqus.com/ disqus: shortname: - apikey: # For newest comments widget + # For newest comments widget + apikey: # Alternative Disqus - Render comments with Disqus API -# DisqusJS 評論系統,可以實現在網路審查地區載入 Disqus 評論列表,兼容原版 # https://github.com/SukkaW/DisqusJS disqusjs: shortname: apikey: option: -# livere (來必力) +# Livere # https://www.livere.com/ livere: uid: -# gitalk +# Gitalk # https://github.com/gitalk/gitalk gitalk: client_id: @@ -446,26 +560,29 @@ gitalk: admin: option: -# valine +# Valine # https://valine.js.org valine: - appId: # leancloud application app id - appKey: # leancloud application app key - avatar: monsterid # gravatar style https://valine.js.org/#/avatar - 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 + appId: + appKey: + avatar: monsterid + # This configuration is suitable for domestic custom domain name users, overseas version will be automatically detected (no need to manually fill in) + serverURLs: + bg: + # Use Valine visitor count as the page view count visitor: false option: -# waline - A simple comment system with backend support fork from Valine +# Waline - A simple comment system with backend support fork from Valine # https://waline.js.org/ waline: - serverURL: # Waline server address url - bg: # waline background + serverURL: + bg: + # Use Waline pageview count as the page view count pageview: false option: -# utterances +# Utterances # https://utteranc.es/ utterances: repo: @@ -474,21 +591,26 @@ utterances: # Theme: github-light/github-dark/github-dark-orange/icy-dark/dark-blue/photon-dark light_theme: github-light dark_theme: photon-dark + js: + option: # Facebook Comments Plugin # https://developers.facebook.com/docs/plugins/comments/ facebook_comments: app_id: - user_id: # optional - pageSize: 10 # The number of comments to show - order_by: social # social/time/reverse_time - lang: zh_TW # Language en_US/zh_CN/zh_TW and so on + # optional + user_id: + pageSize: 10 + # Choose: social / time / reverse_time + order_by: social + lang: zh_TW # Twikoo # https://github.com/imaegoo/twikoo twikoo: envId: region: + # Use Twikoo visitor count as the page view count visitor: false option: @@ -498,16 +620,16 @@ giscus: repo: repo_id: category_id: - theme: - light: light - dark: dark + light_theme: light + dark_theme: dark + js: option: # Remark42 # https://remark42.com/docs/configuration/frontend/ remark42: - host: # Your Host URL - siteId: # Your Site ID + host: + siteId: option: # Artalk @@ -515,73 +637,66 @@ remark42: artalk: server: site: + # Use Artalk visitor count as the page view count visitor: false option: +# -------------------------------------- # 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 +chat: + # Choose: chatra/tidio/daovoice/crisp/messenger + # Leave it empty if you don't need chat + use: + # Chat Button [recommend] + # It will create a button in the bottom right corner of website, and hide the origin button + rightside_button: false + # The origin chat button is displayed when scrolling up, and the button is hidden when scrolling down + button_hide_show: false -# chatra # https://chatra.io/ chatra: - enable: false id: -# tidio # https://www.tidio.com/ tidio: - enable: false public_key: -# daovoice # http://dashboard.daovoice.io/app daovoice: - enable: false app_id: -# crisp # https://crisp.chat/en/ crisp: - enable: false website_id: -# messenger # https://developers.facebook.com/docs/messenger-platform/discovery/facebook-chat-plugin/ messenger: - enable: false pageID: - lang: zh_TW # Language en_US/zh_CN/zh_TW and so on + lang: zh_TW +# -------------------------------------- # Analysis # -------------------------------------- -# Baidu Analytics # https://tongji.baidu.com/web/welcome/login baidu_analytics: -# Google Analytics # https://analytics.google.com/analytics/web/ google_analytics: -# Cloudflare Analytics # https://www.cloudflare.com/zh-tw/web-analytics/ cloudflare_analytics: -# Microsoft Clarity # https://clarity.microsoft.com/ microsoft_clarity: +# -------------------------------------- # Advertisement # -------------------------------------- -# Google Adsense (谷歌廣告) +# Google Adsense google_adsense: enable: false auto_ads: true @@ -589,13 +704,18 @@ google_adsense: client: enable_page_level_ads: true -# Insert ads manually (手動插入廣告) -# ad: -# index: -# aside: -# post: +# Insert ads manually +# Leave it empty if you don't need ads +ad: + # Insert ads in the index (every three posts) + index: + # Insert ads in aside + aside: + # Insert ads in the post (before pagination) + post: -# Verification (站長驗證) +# -------------------------------------- +# Verification # -------------------------------------- site_verification: @@ -604,7 +724,8 @@ site_verification: # - name: baidu-site-verification # content: xxxxxxx -# Beautify/Effect (美化/效果) +# -------------------------------------- +# Beautify / Effect # -------------------------------------- # Theme color for customize @@ -628,63 +749,93 @@ site_verification: # meta_theme_color_light: "ffffff" # meta_theme_color_dark: "#0d0d0d" -# 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 +# Choose: index - same as Homepage UI / default - same as archives UI +# leave it empty or index +category_ui: +tag_ui: -# 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 +# Rounded corners for UI elements +rounded_corners_ui: true -# Stretches the lines so that each line has equal width(文字向兩側對齊,對最後一行無效) +# Stretches the lines so that each line has equal width text_align_justify: false -# 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 - -# Add mask to header or footer (为 header 或 footer 添加黑色半透遮罩) +# Add a mask to the header and footer mask: header: true footer: true -# the position of bottom right button/default unit: px (右下角按鈕距離底部的距離/默認單位為px) -rightside_bottom: +# Loading Animation +preloader: + enable: false + # source + # 1. fullpage-loading + # 2. pace (progress bar) + source: 1 + # pace theme (see https://codebyzach.github.io/pace/) + pace_css_url: -# Enter transitions (開啓網頁進入效果) +# Page Transition enter_transitions: true -# Typewriter Effect (打字效果) +# Default display mode - light (default) / dark +display_mode: light + +# Configuration for beautifying the content of the article +beautify: + enable: false + # Specify the field to beautify (site or post) + field: post + # Specify the icon to be used as a prefix for the title, such as '\f0c1' + title-prefix-icon: + # Specify the color of the title prefix icon, such as '#F47466' + title-prefix-icon-color: + +# Global font settings +# Don't modify the following settings unless you know how they work +font: + global-font-size: + code-font-size: + font-family: + code-font-family: + +# Font settings for the site title and site subtitle +blog_title_font: + font_link: + font-family: + +# The setting of divider icon +hr_icon: + enable: true + # The unicode value of Font Awesome icon, such as '\3423' + icon: + icon-top: + +# Typewriter Effect # https://github.com/disjukr/activate-power-mode activate_power_mode: enable: false - colorful: true # open particle animation (冒光特效) - shake: true # open shake (抖動特效) + colorful: true + shake: true mobile: false -# Background effects (背景特效) +# Background effects # -------------------------------------- -# canvas_ribbon (靜止彩帶背景) +# canvas_ribbon # See: https://github.com/hustcc/ribbon.js canvas_ribbon: enable: false + # The size of ribbon size: 150 + # The opacity of ribbon (0 ~ 1) alpha: 0.6 zIndex: -1 click_to_change: false mobile: false -# Fluttering Ribbon (動態彩帶) +# Fluttering Ribbon canvas_fluttering_ribbon: enable: false mobile: false @@ -693,24 +844,28 @@ canvas_fluttering_ribbon: # 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. + # Color of lines, default: '0,0,0'; RGB values: (R,G,B).(note: use ',' to separate.) + color: '0,0,255' + # The opacity of line (0~1) + opacity: 0.7 + # The z-index property of the background + zIndex: -1 + # The number of lines + count: 99 mobile: false -# Mouse click effects: fireworks (鼠標點擊效果: 煙火特效) +# Mouse click effects: fireworks fireworks: enable: false - zIndex: 9999 # -1 or 9999 + zIndex: 9999 mobile: false -# Mouse click effects: Heart symbol (鼠標點擊效果: 愛心) +# Mouse click effects: Heart symbol click_heart: enable: false mobile: false -# Mouse click effects: words (鼠標點擊效果: 文字) +# Mouse click effects: words clickShowText: enable: false text: @@ -721,113 +876,47 @@ clickShowText: random: false 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 - # Customize typed.js (配置typed.js) - # https://github.com/mattboldt/typed.js/#customization - typed_option: - # source 調用第三方服務 - # source: false 關閉調用 - # source: 1 調用一言網的一句話(簡體) https://hitokoto.cn/ - # source: 2 調用一句網(簡體) https://yijuzhan.com/ - # source: 3 調用今日詩詞(簡體) https://www.jinrishici.com/ - # subtitle 會先顯示 source , 再顯示 sub 的內容 - source: false - # 如果關閉打字效果,subtitle 只會顯示 sub 的第一行文字 - sub: - -# Loading Animation (加載動畫) -preloader: - enable: false - # source - # 1. fullpage-loading - # 2. pace (progress bar) - source: 1 - # pace theme (see https://codebyzach.github.io/pace/) - pace_css_url: - -# wordcount (字數統計) -# see https://butterfly.js.org/posts/ceeb73f/#字數統計 -wordcount: - enable: false - post_wordcount: true - min2read: true - total_wordcount: true - -# Lightbox (圖片大圖查看模式) # -------------------------------------- -# You can only choose one, or neither (只能選擇一個 或者 兩個都不選) +# Lightbox Settings +# -------------------------------------- -# medium-zoom +# Choose: fancybox / medium_zoom # https://github.com/francoischalifour/medium-zoom -medium_zoom: false - -# fancybox # https://fancyapps.com/fancybox/ -fancybox: true +# Leave it empty if you don't need lightbox +lightbox: -# Tag Plugins settings (標籤外掛) +# -------------------------------------- +# Tag Plugins settings # -------------------------------------- -# series (系列文章) +# Series series: - enable: true - orderBy: 'title' # Order by title or date - order: 1 # Sort of order. 1, asc for ascending; -1, desc for descending + enable: false + # Order by title or date + orderBy: 'title' + # Sort of order. 1, asc for ascending; -1, desc for descending + order: 1 number: true -# abcjs (樂譜渲染) -# See https://github.com/paulrosen/abcjs +# ABCJS - The ABC Music Notation Plugin +# https://github.com/paulrosen/abcjs abcjs: enable: false per_page: true # Mermaid -# See https://github.com/mermaid-js/mermaid +# https://github.com/mermaid-js/mermaid mermaid: - enable: true - # Write Mermaid diagrams using code blocks (以代碼塊形式書寫 Mermaid) - code_write: false - # Built-in themes: default/forest/dark/neutral + enable: false + # Write Mermaid diagrams using code blocks + code_write: false + # built-in themes: default / forest / dark / neutral theme: light: default dark: dark -# Note (Bootstrap Callout) +# Note - Bootstrap Callout note: # Note tag style values: # - simple bs-callout old alert style. Default. @@ -841,64 +930,65 @@ note: # Offset also applied to label tag variables. This option can work with disabled note tag. light_bg_offset: 0 -# other +# -------------------------------------- +# Other Settings # -------------------------------------- -# Pjax -# It may contain bugs and unstable, give feedback when you find the bugs. # https://github.com/MoOx/pjax pjax: enable: false + # Exclude the specified pages from pjax, such as '/music/' exclude: - # - xxxx - # - xxxx + # - /xxxxxx/ # Inject the css and script (aplayer/meting) aplayerInject: enable: false per_page: true -# Snackbar (Toast Notification 彈窗) +# Snackbar - Toast Notification # https://github.com/polonel/SnackBar -# position 彈窗位置 -# 可選 top-left / top-center / top-right / bottom-left / bottom-center / bottom-right +# position: top-left / top-center / top-right / bottom-left / bottom-center / bottom-right snackbar: enable: false position: bottom-left - bg_light: '#49b1f5' # The background color of Toast Notification in light mode - bg_dark: '#1f1f1f' # The background color of Toast Notification in dark mode + # The background color of Toast Notification in light mode and dark mode + bg_light: '#49b1f5' + bg_dark: '#1f1f1f' +# Instant.page # https://instant.page/ -# prefetch (預加載) instantpage: false +# Pangu - Insert a space between Chinese character and English character # https://github.com/vinta/pangu.js -# Insert a space between Chinese character and English character (中英文之間添加空格) pangu: enable: false - field: site # site/post + # Specify the field to use pangu (site or post) + field: site -# Lazyload (圖片懶加載) +# Lazyload # https://github.com/verlok/vanilla-lazyload lazyload: enable: false - field: site # site/post + # Specify the field to use lazyload (site or post) + field: site placeholder: blur: false # PWA # See https://github.com/JLHwung/hexo-offline # --------------- -# pwa: -# enable: false -# manifest: /pwa/manifest.json -# apple_touch_icon: /pwa/apple-touch-icon.png -# favicon_32_32: /pwa/32.png -# favicon_16_16: /pwa/16.png -# mask_icon: /pwa/safari-pinned-tab.svg +pwa: + enable: false + manifest: + apple_touch_icon: + favicon_32_32: + favicon_16_16: + mask_icon: # Open graph meta tags -# https://developers.facebook.com/docs/sharing/webmasters/ +# https://hexo.io/docs/helpers#open-graph Open_Graph_meta: enable: true option: @@ -915,29 +1005,24 @@ css_prefix: true # Inject # Insert the code to head (before '' tag) and the bottom (before '' tag) -# 插入代码到头部 之前 和 底部 之前 inject: head: # - bottom: # - -# CDN +# CDN Settings # Don't modify the following settings unless you know how they work -# 非必要請不要修改 CDN: - # The CDN provider of internal scripts (主題內部 js 的 cdn 配置) - # option: local/jsdelivr/unpkg/cdnjs/custom - # Dev version can only choose. ( dev版的主題只能設置為 local ) + # The CDN provider for internal and third-party scripts + # Options for both: local/jsdelivr/unpkg/cdnjs/custom + # Note: Dev version can only use 'local' for internal scripts + # Note: When setting third-party scripts to 'local', you need to install hexo-butterfly-extjs internal_provider: local - - # The CDN provider of third party scripts (第三方 js 的 cdn 配置) - # option: local/jsdelivr/unpkg/cdnjs/custom - # when set it to local, you need to install hexo-butterfly-extjs third_party_provider: jsdelivr # Add version number to url, true or false - version: true + version: false # Custom format # For example: https://cdn.staticfile.org/${cdnjs_name}/${version}/${min_cdnjs_file} @@ -998,4 +1083,4 @@ CDN: # utils: # valine: # waline_css: - # waline_js: \ No newline at end of file + # waline_js: diff --git a/languages/default.yml b/languages/default.yml index 59ddd22..bea841e 100644 --- a/languages/default.yml +++ b/languages/default.yml @@ -36,13 +36,11 @@ post: search: title: Search load_data: Loading the Database + input_placeholder: Search for Posts 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: - input_placeholder: Search for Posts hits_empty: "We didn't find any results for the search: ${query}" hits_stats: '${hits} results found' diff --git a/languages/en.yml b/languages/en.yml index 489b57b..26be42b 100644 --- a/languages/en.yml +++ b/languages/en.yml @@ -36,13 +36,11 @@ post: search: title: Search load_data: Loading the Database + input_placeholder: Search for Posts 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: - input_placeholder: Search for Posts hits_empty: "We didn't find any results for the search: ${query}" hits_stats: '${hits} results found' diff --git a/languages/zh-CN.yml b/languages/zh-CN.yml index b030079..18206ba 100644 --- a/languages/zh-CN.yml +++ b/languages/zh-CN.yml @@ -37,13 +37,11 @@ post: search: title: 搜索 load_data: 数据库加载中 + input_placeholder: 搜索文章 algolia_search: - input_placeholder: 搜索文章 hits_empty: '找不到您查询的内容:${query}' hits_stats: '找到 ${hits} 条结果,用时 ${time} 毫秒' - local_search: - input_placeholder: 搜索文章 hits_empty: '找不到您查询的内容:${query}' hits_stats: '共找到 ${hits} 篇文章' diff --git a/languages/zh-TW.yml b/languages/zh-TW.yml index 4ac63b8..929df60 100644 --- a/languages/zh-TW.yml +++ b/languages/zh-TW.yml @@ -15,7 +15,7 @@ page: card_post_count: 條評論 -no_title: 無標題 +no_title: 無題 post: created: 發表於 @@ -28,8 +28,8 @@ post: copyright: author: 文章作者 link: 文章連結 - copyright_notice: 版權聲明 - copyright_content: '本部落格所有文章除特別聲明外,均採用 + copyright_notice: 版權宣告 + copyright_content: '本部落格所有文章除特別宣告外,均採用 %s 許可協議。轉載請註明來自 %s!' recommend: 相關推薦 edit: 編輯 @@ -37,16 +37,14 @@ post: search: title: 搜尋 load_data: 資料庫載入中 + input_placeholder: 搜尋文章 algolia_search: - input_placeholder: 搜尋文章 hits_empty: '找不到您查詢的內容:${query}' hits_stats: '找到 ${hits} 條結果,用時 ${time} 毫秒' - local_search: - input_placeholder: 搜尋文章 hits_empty: '找不到您查詢的內容:${query}' hits_stats: '共找到 ${hits} 篇文章' - + pagination: prev: 上一篇 next: 下一篇 @@ -83,7 +81,7 @@ aside: link: 連結 code: 程式碼 card_toc: 目錄 - card_post_series: 文章系列 + card_post_series: 系列文章 date_suffix: just: 剛剛 @@ -99,7 +97,7 @@ rightside: readmode_title: 閱讀模式 translate_title: 簡繁轉換 night_mode_title: 淺色和深色模式轉換 - back_to_top: 返回頂部 + back_to_top: 回到頂部 toc: 目錄 scroll_to_comment: 直達評論 setting: 設定 @@ -110,7 +108,7 @@ copy_copyright: author: 作者 link: 連結 source: 來源 - info: 著作權歸作者所有。商業轉載請聯繫作者獲得授權,非商業轉載請註明出處。 + info: 著作權歸作者所有。商業轉載請聯絡作者獲得授權,非商業轉載請註明出處。 Snackbar: chs_to_cht: 你已切換為繁體中文 diff --git a/layout/category.pug b/layout/category.pug index 234a0af..092be9a 100644 --- a/layout/category.pug +++ b/layout/category.pug @@ -2,10 +2,8 @@ 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 + include ./includes/mixins/indexPostUI.pug + +indexPostUI else include ./includes/mixins/article-sort.pug #category diff --git a/layout/includes/404.pug b/layout/includes/404.pug deleted file mode 100644 index 4a022c8..0000000 --- a/layout/includes/404.pug +++ /dev/null @@ -1,12 +0,0 @@ -- var top_img_404 = theme.error_404.background || theme.default_top_img - -#body-wrap.error404 - include ./header/index.pug - - #error-wrap - .error-content - .error-img - img(src=url_for(top_img_404) alt='Page not found') - .error-info - h1.error_title= '404' - .error_subtitle= theme.error_404.subtitle || _p('error404') diff --git a/layout/includes/additional-js.pug b/layout/includes/additional-js.pug index f37d860..785e934 100644 --- a/layout/includes/additional-js.pug +++ b/layout/includes/additional-js.pug @@ -5,9 +5,9 @@ div if theme.translate.enable script(src=url_for(theme.asset.translate)) - if theme.medium_zoom + if theme.lightbox === 'medium_zoom' script(src=url_for(theme.asset.medium_zoom)) - else if theme.fancybox + else if theme.lightbox === 'fancybox' script(src=url_for(theme.asset.fancybox)) if theme.instantpage @@ -38,7 +38,7 @@ div != partial("includes/third-party/prismjs", {}, { cache: true }) - if theme.aside.enable && theme.newest_comments.enable + if theme.aside.enable && theme.aside.card_newest_comments.enable if theme.pjax.enable != partial("includes/third-party/newest-comments/index", {}, { cache: true }) else if (!is_post() && page.aside !== false) diff --git a/layout/includes/head.pug b/layout/includes/head.pug index 364965c..56c29f0 100644 --- a/layout/includes/head.pug +++ b/layout/includes/head.pug @@ -45,7 +45,7 @@ link(rel='stylesheet', href=url_for(theme.asset.fontawesome)) if (theme.snackbar && theme.snackbar.enable) link(rel='stylesheet', href=url_for(theme.asset.snackbar_css) media="print" onload="this.media='all'") -if theme.fancybox +if theme.lightbox === 'fancybox' link(rel='stylesheet' href=url_for(theme.asset.fancybox_css) media="print" onload="this.media='all'") !=fragment_cache('injectHeadJs', function(){return inject_head_js()}) diff --git a/layout/includes/head/Open_Graph.pug b/layout/includes/head/Open_Graph.pug index 8fe04e0..abde7e6 100644 --- a/layout/includes/head/Open_Graph.pug +++ b/layout/includes/head/Open_Graph.pug @@ -10,5 +10,7 @@ if theme.Open_Graph_meta.enable - != open_graph(ogOption) else - meta(name="description" content=page_description()) + - const description = page.description || page.content || page.title || config.description + if description + meta(name="description" content=truncate(description, 150)) diff --git a/layout/includes/head/config.pug b/layout/includes/head/config.pug index c24ecc0..f47a21f 100644 --- a/layout/includes/head/config.pug +++ b/layout/includes/head/config.pug @@ -1,28 +1,30 @@ - - let algolia = 'undefined'; - let env = process.env; - if (theme.algolia_search.enable) { + let algolia = 'undefined' + if (theme.search.use === 'algolia_search') { + const { ALGOLIA_APP_ID, ALGOLIA_API_KEY, ALGOLIA_INDEX_NAME } = process.env + const { appId, applicationID, apiKey, indexName } = config.algolia algolia = JSON.stringify({ - appId: 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, + appId: ALGOLIA_APP_ID || appId || applicationID, + apiKey: ALGOLIA_API_KEY || apiKey, + indexName: ALGOLIA_INDEX_NAME || indexName, + hitsPerPage: theme.search.algolia_search.hitsPerPage, // search languages languages: { - input_placeholder: _p("search.algolia_search.input_placeholder"), + input_placeholder: theme.search.placeholder || _p("search.input_placeholder"), hits_empty: _p("search.algolia_search.hits_empty"), hits_stats: _p("search.algolia_search.hits_stats"), } }) } - let localSearch = 'undefined'; - if (theme.local_search && theme.local_search.enable) { + let localSearch = 'undefined' + if (theme.search.use === 'local_search') { + const { CDN, preload, top_n_per_article, unescape } = theme.search.local_search localSearch = JSON.stringify({ - path: theme.local_search.CDN ? theme.local_search.CDN : config.root + config.search.path, - preload: theme.local_search.preload, - top_n_per_article: theme.local_search.top_n_per_article, - unescape: theme.local_search.unescape, + path: CDN || config.root + config.search.path, + preload, + top_n_per_article, + unescape, languages: { // search languages hits_empty: _p("search.local_search.hits_empty"), @@ -31,7 +33,7 @@ }) } - let translate = 'undefined'; + let translate = 'undefined' if (theme.translate && theme.translate.enable){ translate = JSON.stringify({ defaultEncoding: theme.translate.defaultEncoding, @@ -41,7 +43,7 @@ }) } - let copyright = 'undefined'; + let copyright = 'undefined' if (theme.copy.enable && theme.copy.copyright.enable){ copyright = JSON.stringify({ limitCount: theme.copy.copyright.limit_count, @@ -54,7 +56,7 @@ }) } - let Snackbar = 'undefined'; + let Snackbar = 'undefined' if (theme.snackbar && theme.snackbar.enable) { Snackbar = JSON.stringify({ chs_to_cht: _p("Snackbar.chs_to_cht"), @@ -67,7 +69,7 @@ }) } - let noticeOutdate = 'undefined'; + let noticeOutdate = 'undefined' if (theme.noticeOutdate && theme.noticeOutdate.enable) { noticeOutdate = JSON.stringify({ limitDay: theme.noticeOutdate.limit_day, @@ -77,17 +79,18 @@ }) } - let highlight = 'undefined'; - let syntaxHighlighter = config.syntax_highlighter; - let highlightEnable = syntaxHighlighter ? ['highlight.js', 'prismjs'].includes(syntaxHighlighter) : (config.highlight.enable || config.prismjs.enable); + let highlight = 'undefined' + let syntaxHighlighter = config.syntax_highlighter + let highlightEnable = syntaxHighlighter ? ['highlight.js', 'prismjs'].includes(syntaxHighlighter) : (config.highlight.enable || config.prismjs.enable) if (highlightEnable) { + const { copy, language, height_limit, fullpage, macStyle } = theme.code_blocks highlight = JSON.stringify({ plugin: syntaxHighlighter ? syntaxHighlighter : config.highlight.enable ? 'highlight.js' : 'prismjs', - highlightCopy: theme.highlight_copy, - highlightLang: theme.highlight_lang, - highlightHeightLimit: theme.highlight_height_limit, - highlightFullpage: theme.highlight_fullpage, - highlightMacStyle: theme.highlight_theme_macStyle + highlightCopy: copy, + highlightLang: language, + highlightHeightLimit: height_limit, + highlightFullpage: fullpage, + highlightMacStyle: macStyle }) } @@ -108,7 +111,7 @@ script. 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") : ""}', + runtime: '!{theme.aside.card_webinfo.runtime_date ? _p("aside.card_webinfo.runtime.unit") : ""}', dateSuffix: { just: '!{_p("date_suffix.just")}', min: '!{_p("date_suffix.min")}', @@ -117,7 +120,7 @@ script. month: '!{_p("date_suffix.month")}' }, copyright: !{copyright}, - lightbox: '!{ theme.medium_zoom ? "mediumZoom" : (theme.fancybox ? "fancybox" : "null" )}', + lightbox: '!{ theme.lightbox || 'null' }', Snackbar: !{Snackbar}, infinitegrid: { js: '!{url_for(theme.asset.egjs_infinitegrid)}', diff --git a/layout/includes/head/config_site.pug b/layout/includes/head/config_site.pug index 94cbb51..f457549 100644 --- a/layout/includes/head/config_site.pug +++ b/layout/includes/head/config_site.pug @@ -2,20 +2,17 @@ const titleVal = pageTitle.replace(/'/ig,"\\'") let isHighlightShrink - if (theme.highlight_shrink == 'none') isHighlightShrink = 'undefined' - else if (page.highlight_shrink === true || page.highlight_shrink === false) isHighlightShrink = page.highlight_shrink - else isHighlightShrink = theme.highlight_shrink + if (theme.code_blocks.shrink == 'none') isHighlightShrink = 'undefined' + else if (typeof page.highlight_shrink == 'boolean') isHighlightShrink = page.highlight_shrink + else isHighlightShrink = theme.code_blocks.shrink var showToc = false if (theme.aside.enable && page.aside !== false) { let tocEnable = false - if (is_post()) { - if (theme.toc.post) tocEnable = true - } else if (is_page()) { - if (theme.toc.page) tocEnable = true - } - const pageToc = page.toc === true || page.toc === false ? page.toc : tocEnable - showToc = pageToc && (toc(page.content) !== '' || page.encrypt == true ) + if (is_post() && theme.toc.post) tocEnable = true + else if (is_page() && theme.toc.page) tocEnable = true + const pageToc = typeof page.toc === 'boolean' ? page.toc : tocEnable + showToc = pageToc && (toc(page.content) !== '' || page.encrypt === true) } - diff --git a/layout/includes/header/index.pug b/layout/includes/header/index.pug index 33e01db..b72d14a 100644 --- a/layout/includes/header/index.pug +++ b/layout/includes/header/index.pug @@ -4,7 +4,7 @@ if !theme.disable_top_img && page.top_img !== false 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] + - 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] diff --git a/layout/includes/header/nav.pug b/layout/includes/header/nav.pug index cf50db3..3ef226e 100644 --- a/layout/includes/header/nav.pug +++ b/layout/includes/header/nav.pug @@ -5,17 +5,18 @@ nav#nav img.site-icon(src=url_for(theme.nav.logo) alt='Logo') if theme.nav.display_title span.site-name=config.title - + #menus - if (theme.algolia_search.enable || theme.local_search.enable || theme.docsearch.enable) + if (theme.search.use) #search-button span.site-page.social-icon.search i.fas.fa-search.fa-fw span=' '+_p('search.title') - !=partial('includes/header/menu_item', {}, {cache: true}) + if theme.menu + !=partial('includes/header/menu_item', {}, {cache: true}) - #toggle-menu - span.site-page - i.fas.fa-bars.fa-fw + #toggle-menu + span.site-page + i.fas.fa-bars.fa-fw diff --git a/layout/includes/layout.pug b/layout/includes/layout.pug index dde47c5..b240726 100644 --- a/layout/includes/layout.pug +++ b/layout/includes/layout.pug @@ -2,6 +2,7 @@ - page.aside = is_archive() ? theme.aside.display.archive: is_category() ? theme.aside.display.category : is_tag() ? theme.aside.display.tag : page.aside - var hideAside = !theme.aside.enable || page.aside === false ? 'hide-aside' : '' - var pageType = is_post() ? 'post' : 'page' +- pageType = page.type ? pageType + ' type-' + page.type : pageType doctype html html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside) @@ -16,32 +17,28 @@ html(lang=config.language data-theme=theme.display_mode class=htmlClassHideAside !=partial('includes/sidebar', {}, {cache: true}) - if page.type !== '404' - #body-wrap(class=pageType) - include ./header/index.pug + #body-wrap(class=pageType) + include ./header/index.pug - main#content-inner.layout(class=hideAside) - if body - div!= body - else - block content - if theme.aside.enable && page.aside !== false - include widget/index.pug - - - var footerBg = theme.footer_bg - if (footerBg) - if (footerBg === true) - - var footer_bg = bg_img - else - - var footer_bg = isImgOrUrl(theme.footer_bg) ? `background-image: url('${url_for(footerBg)}')` : `background: ${footerBg}` + main#content-inner.layout(class=hideAside) + if body + div!= body else - - var footer_bg = '' - - footer#footer(style=footer_bg) - !=partial('includes/footer', {}, {cache: true}) + block content + if theme.aside.enable && page.aside !== false + include widget/index.pug + + - var footerBg = theme.footer_img + if (footerBg) + if (footerBg === true) + - var footer_bg = bg_img + else + - var footer_bg = isImgOrUrl(theme.footer_bg) ? `background-image: url('${url_for(footerBg)}')` : `background: ${footerBg}` + else + - var footer_bg = '' - else - include ./404.pug + footer#footer(style=footer_bg) + !=partial('includes/footer', {}, {cache: true}) include ./rightside.pug include ./additional-js.pug \ No newline at end of file diff --git a/layout/includes/mixins/indexPostUI.pug b/layout/includes/mixins/indexPostUI.pug new file mode 100644 index 0000000..fcdad2e --- /dev/null +++ b/layout/includes/mixins/indexPostUI.pug @@ -0,0 +1,125 @@ +mixin indexPostUI() + - let indexLayout = theme.index_layout + - let masonryLayoutClass = (indexLayout === 6 || indexLayout === 7) ? 'masonry' : '' + #recent-posts.recent-posts.nc(class=masonryLayoutClass) + .recent-post-items + each article , index in page.posts.data + .recent-post-item + - + let link = article.link || article.path + let title = article.title || _p('no_title') + let leftOrRight = indexLayout === 3 + ? index%2 == 0 ? 'left' : 'right' + : indexLayout === 2 ? 'right' : '' + let post_cover = article.cover + let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : '' + - + if post_cover && theme.cover.index_enable + .post_cover(class=leftOrRight) + a(href=url_for(link) title=title) + if article.cover_type === 'img' + img.post-bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) + else + div.post-bg(style=`background: ${post_cover}`) + .recent-post-info(class=no_cover) + a.article-title(href=url_for(link) title=title) + if (is_home() && (article.top || article.sticky > 0)) + i.fas.fa-thumbtack.sticky + = title + .article-meta-wrap + if (theme.post_meta.page.date_type) + span.post-meta-date + if (theme.post_meta.page.date_type === 'both') + i.far.fa-calendar-alt + span.article-meta-label=_p('post.created') + time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format) + span.article-meta-separator | + i.fas.fa-history + span.article-meta-label=_p('post.updated') + time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format) + else + - let data_type_updated = theme.post_meta.page.date_type === 'updated' + - let date_type = data_type_updated ? 'updated' : 'date' + - let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt' + - let date_title = data_type_updated ? _p('post.updated') : _p('post.created') + i(class=date_icon) + span.article-meta-label=date_title + time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format) + if (theme.post_meta.page.categories && article.categories.data.length > 0) + span.article-meta + span.article-meta-separator | + each item, index in article.categories.data + i.fas.fa-inbox + a(href=url_for(item.path)).article-meta__categories #[=item.name] + if (index < article.categories.data.length - 1) + i.fas.fa-angle-right.article-meta-link + if (theme.post_meta.page.tags && article.tags.length > 0) + span.article-meta.tags + span.article-meta-separator | + each item, index in article.tags.data + i.fas.fa-tag + a(href=url_for(item.path)).article-meta__tags #[=item.name] + if (index < article.tags.data.length - 1) + span.article-meta-link #[='•'] + + mixin countBlockInIndex + - needLoadCountJs = true + span.article-meta + span.article-meta-separator | + i.fas.fa-comments + if block + block + span.article-meta-label= ' ' + _p('card_post_count') + + if theme.comments.card_post_count && theme.comments.use + case theme.comments.use[0] + when 'Disqus' + when 'Disqusjs' + +countBlockInIndex + a.disqus-count(href=full_url_for(link) + '#post-comment') + i.fa-solid.fa-spinner.fa-spin + when 'Valine' + +countBlockInIndex + a(href=url_for(link) + '#post-comment') + span.valine-comment-count(data-xid=url_for(link)) + i.fa-solid.fa-spinner.fa-spin + when 'Waline' + +countBlockInIndex + a(href=url_for(link) + '#post-comment') + span.waline-comment-count(data-path=url_for(link)) + i.fa-solid.fa-spinner.fa-spin + when 'Twikoo' + +countBlockInIndex + a.twikoo-count(href=url_for(link) + '#post-comment') + i.fa-solid.fa-spinner.fa-spin + when 'Facebook Comments' + +countBlockInIndex + a(href=url_for(link) + '#post-comment') + span.fb-comments-count(data-href=urlNoIndex(article.permalink)) + when 'Remark42' + +countBlockInIndex + a(href=url_for(link) + '#post-comment') + span.remark42__counter(data-url=urlNoIndex(article.permalink)) + i.fa-solid.fa-spinner.fa-spin + when 'Artalk' + +countBlockInIndex + a(href=url_for(link) + '#post-comment') + span.artalk-count(data-page-key=url_for(link)) + i.fa-solid.fa-spinner.fa-spin + + //- Display the article introduction on homepage + case theme.index_post_content.method + when false + - break + when 1 + .content!= article.description + when 2 + .content!= article.description || truncate(article.content, theme.index_post_content.length) + default + .content!= truncate(article.content, theme.index_post_content.length) + + if theme.ad && theme.ad.index + if (index + 1) % 3 == 0 + .recent-post-item.ads-wrap!=theme.ad.index + + include ../pagination.pug \ No newline at end of file diff --git a/layout/includes/mixins/post-ui.pug b/layout/includes/mixins/post-ui.pug deleted file mode 100644 index bd545e4..0000000 --- a/layout/includes/mixins/post-ui.pug +++ /dev/null @@ -1,129 +0,0 @@ -mixin postUI(posts) - each article , index in page.posts.data - .recent-post-item - - - let link = article.link || article.path - let title = article.title || _p('no_title') - const position = theme.cover.position - let leftOrRight = position === 'both' - ? index%2 == 0 ? 'left' : 'right' - : position === 'left' ? 'left' : 'right' - let post_cover = article.cover - let no_cover = article.cover === false || !theme.cover.index_enable ? 'no-cover' : '' - - - if post_cover && theme.cover.index_enable - .post_cover(class=leftOrRight) - a(href=url_for(link) title=title) - if article.cover_type === 'img' - img.post-bg(src=url_for(post_cover) onerror=`this.onerror=null;this.src='${url_for(theme.error_img.post_page)}'` alt=title) - else - div.post-bg(style=`background: ${post_cover}`) - .recent-post-info(class=no_cover) - a.article-title(href=url_for(link) title=title) - if (is_home() && (article.top || article.sticky > 0)) - i.fas.fa-thumbtack.sticky - = title - .article-meta-wrap - if (theme.post_meta.page.date_type) - span.post-meta-date - if (theme.post_meta.page.date_type === 'both') - i.far.fa-calendar-alt - span.article-meta-label=_p('post.created') - time.post-meta-date-created(datetime=date_xml(article.date) title=_p('post.created') + ' ' + full_date(article.date))=date(article.date, config.date_format) - span.article-meta-separator | - i.fas.fa-history - span.article-meta-label=_p('post.updated') - time.post-meta-date-updated(datetime=date_xml(article.updated) title=_p('post.updated') + ' ' + full_date(article.updated))=date(article.updated, config.date_format) - else - - let data_type_updated = theme.post_meta.page.date_type === 'updated' - - let date_type = data_type_updated ? 'updated' : 'date' - - let date_icon = data_type_updated ? 'fas fa-history' :'far fa-calendar-alt' - - let date_title = data_type_updated ? _p('post.updated') : _p('post.created') - i(class=date_icon) - span.article-meta-label=date_title - time(datetime=date_xml(article[date_type]) title=date_title + ' ' + full_date(article[date_type]))=date(article[date_type], config.date_format) - if (theme.post_meta.page.categories && article.categories.data.length > 0) - span.article-meta - span.article-meta-separator | - each item, index in article.categories.data - i.fas.fa-inbox - a(href=url_for(item.path)).article-meta__categories #[=item.name] - if (index < article.categories.data.length - 1) - i.fas.fa-angle-right.article-meta-link - if (theme.post_meta.page.tags && article.tags.data.length > 0) - span.article-meta.tags - span.article-meta-separator | - each item, index in article.tags.data - i.fas.fa-tag - a(href=url_for(item.path)).article-meta__tags #[=item.name] - if (index < article.tags.data.length - 1) - span.article-meta-link #[='•'] - - mixin countBlockInIndex - - needLoadCountJs = true - span.article-meta - span.article-meta-separator | - i.fas.fa-comments - if block - block - span.article-meta-label= ' ' + _p('card_post_count') - - if theme.comments.card_post_count && theme.comments.use - case theme.comments.use[0] - when 'Disqus' - when 'Disqusjs' - +countBlockInIndex - a.disqus-count(href=full_url_for(link) + '#post-comment') - i.fa-solid.fa-spinner.fa-spin - when 'Valine' - +countBlockInIndex - a(href=url_for(link) + '#post-comment') - span.valine-comment-count(data-xid=url_for(link)) - i.fa-solid.fa-spinner.fa-spin - when 'Waline' - +countBlockInIndex - a(href=url_for(link) + '#post-comment') - span.waline-comment-count(data-path=url_for(link)) - i.fa-solid.fa-spinner.fa-spin - when 'Twikoo' - +countBlockInIndex - a.twikoo-count(href=url_for(link) + '#post-comment') - i.fa-solid.fa-spinner.fa-spin - when 'Facebook Comments' - +countBlockInIndex - a(href=url_for(link) + '#post-comment') - span.fb-comments-count(data-href=urlNoIndex(article.permalink)) - when 'Remark42' - +countBlockInIndex - a(href=url_for(link) + '#post-comment') - span.remark42__counter(data-url=urlNoIndex(article.permalink)) - i.fa-solid.fa-spinner.fa-spin - when 'Artalk' - +countBlockInIndex - a(href=url_for(link) + '#post-comment') - span.artalk-count(data-page-key=url_for(link)) - i.fa-solid.fa-spinner.fa-spin - - //- Display the article introduction on homepage - case theme.index_post_content.method - when false - - break - when 1 - .content!= article.description - when 2 - if article.description - .content!= article.description - else - - const content = strip_html(article.content) - - let expert = content.substring(0, theme.index_post_content.length) - - content.length > theme.index_post_content.length ? expert += ' ...' : '' - .content!= expert - default - - const content = strip_html(article.content) - - let expert = content.substring(0, theme.index_post_content.length) - - content.length > theme.index_post_content.length ? expert += ' ...' : '' - .content!= expert - - if theme.ad && theme.ad.index - if (index + 1) % 3 == 0 - .recent-post-item.ads-wrap!=theme.ad.index diff --git a/layout/includes/page/404.pug b/layout/includes/page/404.pug new file mode 100644 index 0000000..9444204 --- /dev/null +++ b/layout/includes/page/404.pug @@ -0,0 +1,8 @@ +- var top_img_404 = theme.error_404.background || theme.default_top_img + +.error-content + .error-img + img(src=url_for(top_img_404) alt='Page not found') + .error-info + h1.error_title= '404' + .error_subtitle= theme.error_404.subtitle || _p('error404') diff --git a/layout/includes/page/shuoshuo.pug b/layout/includes/page/shuoshuo.pug new file mode 100644 index 0000000..745b048 --- /dev/null +++ b/layout/includes/page/shuoshuo.pug @@ -0,0 +1,103 @@ +//- - author: +//- avatar: +//- date: +//- content: +//- tags: +//- - tag1 +//- - tag2 + + +- page.comments = false +- page.toc = false +#article-container + if page.shuoshuo_url + script. + (() => { + const loadShuoshuo = async () => { + try { + const fetchContent = await fetch('!{url_for(page.shuoshuo_url)}') + const shuoshuo = await fetchContent.json() + + let start = 0 + const container = document.getElementById('article-container') + + const addData = data => { + const cLength = data.length + const end = start + 10 > cLength ? cLength : start + 10 + let result = '' + data.slice(start, end).forEach((item) => { + result += ` +
+
+
+ +
+
+
${item.author || '!{config.author}'}
+
${btf.diffDate(item.date, true)}
+
+
+
+ ${item.content} +
+ +
+ ` + }) + + start = end + container.insertAdjacentHTML('beforeend', result) + + if (start >= cLength) { + observer.disconnect() + } else { + setTimeout(() => observer.observe(container.lastElementChild), 100) + } + + window.lazyLoadInstance.update() + btf.loadLightbox(document.querySelectorAll('#article-container img:not(.no-lightbox)')) + } + + addData(shuoshuo) + + const observer = new IntersectionObserver((entries) => { + if (entries[0].isIntersecting) { + observer.unobserve(entries[0].target) + addData(shuoshuo) + } + }, { + root: null, + rootMargin: '0px', + threshold: 1.0 + }) + + if (container.lastElementChild) { + observer.observe(container.lastElementChild) + } + } catch (e) { + console.error(e) + } + } + + window.pjax ? loadShuoshuo() : window.addEventListener('load', loadShuoshuo) + })() + else + if site.data.shuoshuo + each i in site.data.shuoshuo + .shuoshuo-item + .shuoshuo-item-header + .shuoshuo-avatar + img.no-lightbox(src=i.avatar || url_for(theme.avatar.img)) + .shuoshuo-info + .shuoshuo-author=i.author || config.author + .shuoshuo-date=relative_date(i.date) + .shuoshuo-content + !=markdown(i.content) + .shuoshuo-footer + .shuoshuo-tags + each tag in i.tags + span.shuoshuo-tag=tag \ No newline at end of file diff --git a/layout/includes/page/tags.pug b/layout/includes/page/tags.pug index ed7d22c..b579112 100644 --- a/layout/includes/page/tags.pug +++ b/layout/includes/page/tags.pug @@ -1,2 +1,2 @@ .tag-cloud-list.is-center - !=cloudTags({source: site.tags, orderby: page.orderby || 'random', order: page.order || 1, minfontsize: 1.2, maxfontsize: 2.1, limit: 0, unit: 'em'}) \ No newline at end of file + !=cloudTags({source: site.tags, orderby: page.orderby || 'random', order: page.order || 1, minfontsize: 1.2, maxfontsize: 1.5, limit: 0, unit: 'em'}) \ No newline at end of file diff --git a/layout/includes/pagination.pug b/layout/includes/pagination.pug index 2af0e00..7cbe946 100644 --- a/layout/includes/pagination.pug +++ b/layout/includes/pagination.pug @@ -12,27 +12,25 @@ if is_post() nav#pagination.pagination-post if(prev) - var hasPageNext = next ? 'pull-left' : 'pull-full' - .prev-post(class=hasPageNext) - a(href=url_for(prev.path) title=prev.title) - if prev.cover_type === 'img' - img.cover(src=url_for(prev.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of previous post') - else - .cover(style=`background: ${prev.cover || 'var(--default-bg-color)'}`) - .pagination-info - .label=_p('pagination.prev') - .prev_info=prev.title + a.prev-post(class=hasPageNext href=url_for(prev.path) title=prev.title) + if prev.cover_type === 'img' + img.cover(src=url_for(prev.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of previous post') + else + .cover(style=`background: ${prev.cover || 'var(--default-bg-color)'}`) + .pagination-info + .label=_p('pagination.prev') + .prev_info=prev.title if(next) - var hasPagePrev = prev ? 'pull-right' : 'pull-full' - .next-post(class=hasPagePrev) - a(href=url_for(next.path) title=next.title) - if next.cover_type === 'img' - img.cover(src=url_for(next.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of next post') - else - .cover(style=`background: ${next.cover || 'var(--default-bg-color)'}`) - .pagination-info - .label=_p('pagination.next') - .next_info=next.title + a.next-post(class=hasPagePrev href=url_for(next.path) title=next.title) + if next.cover_type === 'img' + img.cover(src=url_for(next.cover) onerror=`onerror=null;src='${url_for(theme.error_img.post_page)}'` alt='cover of next post') + else + .cover(style=`background: ${next.cover || 'var(--default-bg-color)'}`) + .pagination-info + .label=_p('pagination.next') + .next_info=next.title else nav#pagination .pagination diff --git a/layout/includes/rightside.pug b/layout/includes/rightside.pug index 377813d..01c8021 100644 --- a/layout/includes/rightside.pug +++ b/layout/includes/rightside.pug @@ -1,4 +1,4 @@ -- const { readmode, translate, darkmode, aside, chat_btn } = theme +- const { readmode, translate, darkmode, aside, chat } = theme mixin rightsideItem(array) each item in array case item @@ -22,9 +22,9 @@ mixin rightsideItem(array) button#mobile-toc-button.close(type="button" title=_p("rightside.toc")) i.fas.fa-list-ul when 'chat' - if chat_btn + if chat.rightside_button && chat.use button#chat-btn(type="button" title=_p("rightside.chat")) - i.fas.fa-sms + i.fas.fa-message when 'comment' if commentsJsLoad a#to_comment(href="#post-comment" title=_p("rightside.scroll_to_comment")) diff --git a/layout/includes/sidebar.pug b/layout/includes/sidebar.pug index 66c67a9..c4aefff 100644 --- a/layout/includes/sidebar.pug +++ b/layout/includes/sidebar.pug @@ -1,18 +1,18 @@ -#sidebar - #menu-mask - #sidebar-menus - .avatar-img.is-center - img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar") - .sidebar-site-data.site-data.is-center - a(href=url_for(config.archive_dir) + '/') - .headline= _p('aside.articles') - .length-num= site.posts.length - a(href=url_for(config.tag_dir) + '/' ) - .headline= _p('aside.tags') - .length-num= site.tags.length - a(href=url_for(config.category_dir) + '/') - .headline= _p('aside.categories') - .length-num= site.categories.length +if theme.menu + #sidebar + #menu-mask + #sidebar-menus + .avatar-img.is-center + img(src=url_for(theme.avatar.img) onerror=`onerror=null;src='${theme.error_img.flink}'` alt="avatar") + .site-data.is-center + a(href=url_for(config.archive_dir) + '/') + .headline= _p('aside.articles') + .length-num= site.posts.length + a(href=url_for(config.tag_dir) + '/' ) + .headline= _p('aside.tags') + .length-num= site.tags.length + a(href=url_for(config.category_dir) + '/') + .headline= _p('aside.categories') + .length-num= site.categories.length - hr.custom-hr - !=partial('includes/header/menu_item', {}, {cache: true}) + !=partial('includes/header/menu_item', {}, {cache: true}) diff --git a/layout/includes/third-party/aplayer.pug b/layout/includes/third-party/aplayer.pug index e049ea0..cf875b6 100644 --- a/layout/includes/third-party/aplayer.pug +++ b/layout/includes/third-party/aplayer.pug @@ -14,10 +14,10 @@ if theme.pjax.enable } } - const loadMeting = () => { + const runMetingJS = () => { typeof loadMeting === 'function' && document.getElementsByClassName('aplayer').length && loadMeting() } btf.addGlobalFn('pjaxSend', destroyAplayer, 'destroyAplayer') - btf.addGlobalFn('pjaxComplete', loadMeting, 'loadMeting') + btf.addGlobalFn('pjaxComplete', loadMeting, 'runMetingJS') })() diff --git a/layout/includes/third-party/card-post-count/fb.pug b/layout/includes/third-party/card-post-count/fb.pug index 75d6b4a..fb504d3 100644 --- a/layout/includes/third-party/card-post-count/fb.pug +++ b/layout/includes/third-party/card-post-count/fb.pug @@ -1,5 +1,5 @@ - const fbSDKVer = 'v16.0' -- const fbSDK = theme.messenger.enable ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` +- const fbSDK = theme.chat.use === 'messenger' ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` script. (()=>{ diff --git a/layout/includes/third-party/chat/chatra.pug b/layout/includes/third-party/chat/chatra.pug index 5cc7b5a..928ac19 100644 --- a/layout/includes/third-party/chat/chatra.pug +++ b/layout/includes/third-party/chat/chatra.pug @@ -1,8 +1,8 @@ //- https://chatra.io/help/api/ script. (() => { - const isChatBtn = !{theme.chat_btn} - const isChatHideShow = !{theme.chat_hide_show} + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} if (isChatBtn) { const close = () => { diff --git a/layout/includes/third-party/chat/crisp.pug b/layout/includes/third-party/chat/crisp.pug index 6c8b6bf..24c8c1c 100644 --- a/layout/includes/third-party/chat/crisp.pug +++ b/layout/includes/third-party/chat/crisp.pug @@ -11,8 +11,8 @@ script. })(); $crisp.push(["safe", true]) - const isChatBtn = !{theme.chat_btn} - const isChatHideShow = !{theme.chat_hide_show} + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} if (isChatBtn) { const open = () => { diff --git a/layout/includes/third-party/chat/daovoice.pug b/layout/includes/third-party/chat/daovoice.pug index 5a7c33d..41ccfeb 100644 --- a/layout/includes/third-party/chat/daovoice.pug +++ b/layout/includes/third-party/chat/daovoice.pug @@ -3,8 +3,8 @@ script. (() => { (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice") - const isChatBtn = !{theme.chat_btn} - const isChatHideShow = !{theme.chat_hide_show} + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} daovoice('init', { app_id: '!{theme.daovoice.app_id}',},{ diff --git a/layout/includes/third-party/chat/index.pug b/layout/includes/third-party/chat/index.pug index 4b6bda6..6fa1131 100644 --- a/layout/includes/third-party/chat/index.pug +++ b/layout/includes/third-party/chat/index.pug @@ -1,10 +1,11 @@ -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.crisp && theme.crisp.enable - include ./crisp.pug -else if theme.messenger && theme.messenger.enable - include ./messenger.pug \ No newline at end of file +case theme.chat.use + when 'chatra' + include ./chatra.pug + when 'tidio' + include ./tidio.pug + when 'daovoice' + include ./daovoice.pug + when 'crisp' + include ./crisp.pug + when 'messenger' + include ./messenger.pug \ No newline at end of file diff --git a/layout/includes/third-party/chat/messenger.pug b/layout/includes/third-party/chat/messenger.pug index 3d244fc..41eef4a 100644 --- a/layout/includes/third-party/chat/messenger.pug +++ b/layout/includes/third-party/chat/messenger.pug @@ -22,8 +22,8 @@ script. fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); - const isChatBtn = !{theme.chat_btn} - const isChatHideShow = !{theme.chat_hide_show} + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} if (isChatBtn) { window.chatBtnFn = () => { diff --git a/layout/includes/third-party/chat/tidio.pug b/layout/includes/third-party/chat/tidio.pug index 20104f5..a4194c4 100644 --- a/layout/includes/third-party/chat/tidio.pug +++ b/layout/includes/third-party/chat/tidio.pug @@ -1,8 +1,8 @@ script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async) script. (() => { - const isChatBtn = !{theme.chat_btn} - const isChatHideShow = !{theme.chat_hide_show} + const isChatBtn = !{theme.chat.rightside_button} + const isChatHideShow = !{theme.chat.button_hide_show} if (isChatBtn) { let isShow = false diff --git a/layout/includes/third-party/comments/artalk.pug b/layout/includes/third-party/comments/artalk.pug index aadfabc..646a424 100644 --- a/layout/includes/third-party/comments/artalk.pug +++ b/layout/includes/third-party/comments/artalk.pug @@ -25,7 +25,7 @@ script. artalkItem.destroy() } - btf.addGlobalFn('pjax', destroyArtalk, 'destroyArtalk') + btf.addGlobalFn('pjaxSendOnce', destroyArtalk, 'destroyArtalk') } const loadArtalk = async () => { diff --git a/layout/includes/third-party/comments/facebook_comments.pug b/layout/includes/third-party/comments/facebook_comments.pug index f0cc916..b6617ec 100644 --- a/layout/includes/third-party/comments/facebook_comments.pug +++ b/layout/includes/third-party/comments/facebook_comments.pug @@ -1,5 +1,5 @@ - const fbSDKVer = 'v16.0' -- const fbSDK = theme.messenger.enable ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` +- const fbSDK = theme.chat.use === 'messenger' ? `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk/xfbml.customerchat.js#xfbml=1&version=${fbSDKVer}` : `https://connect.facebook.net/${theme.facebook_comments.lang}/sdk.js#xfbml=1&version=${fbSDKVer}` script. (()=>{ diff --git a/layout/includes/third-party/comments/giscus.pug b/layout/includes/third-party/comments/giscus.pug index 3e1b518..b55a4ec 100644 --- a/layout/includes/third-party/comments/giscus.pug +++ b/layout/includes/third-party/comments/giscus.pug @@ -1,13 +1,11 @@ -- const { repo, repo_id, category_id, theme:themes, option } = theme.giscus -- const giscusUrl = theme.asset.giscus || 'https://giscus.app/client.js' -- const giscusOriginUrl = new URL(giscusUrl).origin - const { use, lazyload } = theme.comments +- const { repo, repo_id, category_id, light_theme, dark_theme, js, option } = theme.giscus +- const giscusUrl = js || 'https://giscus.app/client.js' +- const giscusOriginUrl = new URL(giscusUrl).origin script. (()=>{ - const getGiscusTheme = theme => { - return theme === 'dark' ? '!{themes.dark}' : '!{themes.light}' - } + const getGiscusTheme = theme => theme === 'dark' ? '!{dark_theme}' : '!{light_theme}' const loadGiscus = () => { const config = Object.assign({ @@ -30,17 +28,17 @@ script. } const changeGiscusTheme = theme => { - const sendMessage = message => { - const iframe = document.querySelector('iframe.giscus-frame') - if (!iframe) return - iframe.contentWindow.postMessage({ giscus: message }, '!{giscusOriginUrl}') - } - - sendMessage({ - setConfig: { - theme: getGiscusTheme(theme) + const iframe = document.querySelector('#giscus-wrap iframe') + if (iframe) { + const message = { + giscus: { + setConfig: { + theme: getGiscusTheme(theme) + } + } } - }); + iframe.contentWindow.postMessage(message, '!{giscusOriginUrl}') + } } btf.addGlobalFn('themeChange', changeGiscusTheme, 'giscus') diff --git a/layout/includes/third-party/comments/utterances.pug b/layout/includes/third-party/comments/utterances.pug index 0ca01e7..1fdc0da 100644 --- a/layout/includes/third-party/comments/utterances.pug +++ b/layout/includes/third-party/comments/utterances.pug @@ -1,34 +1,42 @@ - const { use, lazyload } = theme.comments -- const { repo, issue_term, light_theme, dark_theme } = theme.utterances +- const { repo, issue_term, light_theme, dark_theme, js, option } = theme.utterances +- const utterancesUrl = js || 'https://utteranc.es/client.js' +- const utterancesOriginUrl = new URL(utterancesUrl).origin script. (() => { + const getUtterancesTheme = theme => theme === 'dark' ? '#{dark_theme}' : '#{light_theme}' + const loadUtterances = () => { - let ele = document.createElement('script') - ele.id = 'utterances_comment' - ele.src = 'https://utteranc.es/client.js' - ele.setAttribute('repo', '!{repo}') - ele.setAttribute('issue-term', '!{issue_term}') - const nowTheme = document.documentElement.getAttribute('data-theme') === 'dark' ? '#{dark_theme}' : '#{light_theme}' - ele.setAttribute('theme', nowTheme) - ele.crossOrigin = 'anonymous' - ele.async = true + const config = Object.assign({ + id: 'utterances_comment', + src: '!{utterancesUrl}', + repo: '!{repo}', + 'issue-term': '!{issue_term}', + theme: getUtterancesTheme(document.documentElement.getAttribute('data-theme')), + crossorigin: 'anonymous', + async: true + },!{JSON.stringify(option)}) + + const ele = document.createElement('script') + for (let key in config) { + ele.setAttribute(key, config[key]) + } document.getElementById('utterances-wrap').appendChild(ele) } - const utterancesTheme = theme => { - const iframe = document.querySelector('.utterances-frame') + const changeUtterancesTheme = theme => { + const iframe = document.querySelector('#utterances-wrap iframe') if (iframe) { - const theme = theme === 'dark' ? '#{dark_theme}' : '#{light_theme}' const message = { type: 'set-theme', - theme: theme + theme: getUtterancesTheme(theme) }; - iframe.contentWindow.postMessage(message, 'https://utteranc.es'); + iframe.contentWindow.postMessage(message, '!{utterancesOriginUrl}') } } - btf.addGlobalFn('themeChange', utterancesTheme, 'utterances') + btf.addGlobalFn('themeChange', changeUtterancesTheme, 'utterances') if ('!{use[0]}' === 'Utterances' || !!{lazyload}) { if (!{lazyload}) btf.loadComment(document.getElementById('utterances-wrap'), loadUtterances) diff --git a/layout/includes/third-party/comments/waline.pug b/layout/includes/third-party/comments/waline.pug index 0b0ce4a..47ef32f 100644 --- a/layout/includes/third-party/comments/waline.pug +++ b/layout/includes/third-party/comments/waline.pug @@ -19,7 +19,7 @@ script. waline.destroy() } - btf.addGlobalFn('pjax', destroyWaline, 'destroyWaline') + btf.addGlobalFn('pjaxSendOnce', destroyWaline, 'destroyWaline') } const loadWaline = () => { diff --git a/layout/includes/third-party/math/index.pug b/layout/includes/third-party/math/index.pug index 2b16302..cf4741d 100644 --- a/layout/includes/third-party/math/index.pug +++ b/layout/includes/third-party/math/index.pug @@ -1,18 +1,19 @@ -if theme.mathjax && theme.mathjax.enable - if theme.mathjax.per_page - if is_post() || is_page() - include ./mathjax.pug - else - if page.mathjax - include ./mathjax.pug +case theme.math.use + when 'mathjax' + if theme.math.per_page + if is_post() || is_page() + include ./mathjax.pug + else + if page.mathjax + include ./mathjax.pug -if theme.katex && theme.katex.enable - if theme.katex.per_page - if is_post() || is_page() - include ./katex.pug - else - if page.katex - include ./katex.pug + when 'katex' + if theme.math.per_page + if is_post() || is_page() + 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/layout/includes/third-party/math/katex.pug b/layout/includes/third-party/math/katex.pug index 4303063..c38a4b4 100644 --- a/layout/includes/third-party/math/katex.pug +++ b/layout/includes/third-party/math/katex.pug @@ -1,2 +1,16 @@ -link(rel="stylesheet" type="text/css" href=url_for(theme.asset.katex)) -script(src=url_for(theme.asset.katex_copytex)) \ No newline at end of file +script. + (async () => { + const showKatex = () => { + const mathElements = document.querySelectorAll('#article-container .katex') + mathElements.length && mathElements.forEach((el) => { + el.classList.add('katex-show') + }) + } + if (!window.katex_js_css) { + window.katex_js_css = true + await btf.getCSS('!{url_for(theme.asset.katex)}') + if (!{theme.math.katex.copy_tex}) await btf.getScript('!{url_for(theme.asset.katex_copytex)}') + } + + showKatex() + })() \ No newline at end of file diff --git a/layout/includes/third-party/math/mathjax.pug b/layout/includes/third-party/math/mathjax.pug index 0baefdc..75775b5 100644 --- a/layout/includes/third-party/math/mathjax.pug +++ b/layout/includes/third-party/math/mathjax.pug @@ -1,4 +1,5 @@ //- Mathjax 3 +- const { tags, enableMenu } = theme.math.mathjax script. (() => { const loadMathjax = () => { @@ -6,12 +7,13 @@ script. window.MathJax = { tex: { inlineMath: [['$', '$'], ['\\(', '\\)']], - tags: 'ams' + tags: '!{tags}', }, chtml: { scale: 1.1 }, options: { + enableMenu: !{enableMenu}, renderActions: { findScript: [10, doc => { for (const node of document.querySelectorAll('script[type^="math/tex"]')) { diff --git a/layout/includes/third-party/math/mermaid.pug b/layout/includes/third-party/math/mermaid.pug index f2590c6..21898c3 100644 --- a/layout/includes/third-party/math/mermaid.pug +++ b/layout/includes/third-party/math/mermaid.pug @@ -11,18 +11,12 @@ script. const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent const renderFn = mermaid.render(mermaidID, mermaidDefinition) - - const renderV10 = () => { - renderFn.then(({svg}) => { - mermaidSrc.insertAdjacentHTML('afterend', svg) - }) - } - - const renderV9 = svg => { + const renderMermaid = svg => { mermaidSrc.insertAdjacentHTML('afterend', svg) } - typeof renderFn === 'string' ? renderV9(renderFn) : renderV10() + // mermaid v9 and v10 compatibility + typeof renderFn === 'string' ? renderMermaid(renderFn) : renderFn.then(({svg}) => renderMermaid(svg)) }) } @@ -31,9 +25,13 @@ script. if (codeMermaidEle.length === 0) return codeMermaidEle.forEach(ele => { + const preEle = document.createElement('pre') + preEle.className = 'mermaid-src' + preEle.hidden = true + preEle.textContent = ele.textContent const newEle = document.createElement('div') newEle.className = 'mermaid-wrap' - newEle.innerHTML = `` + newEle.appendChild(preEle) ele.parentNode.replaceWith(newEle) }) } diff --git a/layout/includes/third-party/newest-comments/artalk.pug b/layout/includes/third-party/newest-comments/artalk.pug index 03ad068..bec42d2 100644 --- a/layout/includes/third-party/newest-comments/artalk.pug +++ b/layout/includes/third-party/newest-comments/artalk.pug @@ -1,6 +1,6 @@ - const { server, site, option } = theme.artalk -- const avatarCdn = option !== null && option.gravatar && option.gravatar.mirror -- const avatarDefault = option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default) +- const avatarCdn = (option !== null && option.gravatar && option.gravatar.mirror) || '' +- const avatarDefault = (option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default)) || '' script. window.addEventListener('load', () => { @@ -25,7 +25,7 @@ script. for (let i = 0; i < array.length; i++) { result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } @@ -60,7 +60,7 @@ script. const searchParams = new URLSearchParams({ 'site_name': '!{site}', - 'limit': '!{theme.newest_comments.limit}', + 'limit': '!{theme.aside.card_newest_comments.limit}', }) const getComment = async () => { @@ -69,8 +69,8 @@ script. const result = await res.json() const avatarStr = await getSetting() const { mirror, params, default:defaults } = avatarStr.frontend_conf.gravatar - const avatarCdn = !{avatarCdn} || mirror - let avatarDefault = !{avatarDefault} || params || defaults + const avatarCdn = '!{avatarCdn}' || mirror + let avatarDefault = '!{avatarDefault}' || params || defaults avatarDefault = avatarDefault.startsWith('d=') ? avatarDefault : `d=${avatarDefault}` const artalk = result.data.map(function (e) { return { @@ -81,7 +81,7 @@ script. 'date': e.date, } }) - btf.saveToLocal.set('artalk-newest-comments', JSON.stringify(artalk), !{theme.newest_comments.storage}/(60*24)) + btf.saveToLocal.set('artalk-newest-comments', JSON.stringify(artalk), !{theme.aside.card_newest_comments.storage}/(60*24)) generateHtml(artalk) } catch (e) { console.log(e) diff --git a/layout/includes/third-party/newest-comments/disqus-comment.pug b/layout/includes/third-party/newest-comments/disqus-comment.pug index 93feec5..e62c5f7 100644 --- a/layout/includes/third-party/newest-comments/disqus-comment.pug +++ b/layout/includes/third-party/newest-comments/disqus-comment.pug @@ -15,7 +15,7 @@ script. } const getComment = () => { - fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{theme.newest_comments.limit}&api_key=!{apiKey}') + fetch('https://disqus.com/api/3.0/forums/listPosts.json?forum=!{forum}&related=thread&limit=!{theme.aside.card_newest_comments.limit}&api_key=!{apiKey}') .then(response => response.json()) .then(data => { const disqusArray = data.response.map(item => { @@ -28,7 +28,7 @@ script. } }) - btf.saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), !{theme.newest_comments.storage}/(60*24)) + btf.saveToLocal.set('disqus-newest-comments', JSON.stringify(disqusArray), !{theme.aside.card_newest_comments.storage}/(60*24)) generateHtml(disqusArray) }).catch(e => { const $dom = document.querySelector('#card-newest-comments .aside-list') @@ -43,7 +43,7 @@ script. for (let i = 0; i < array.length; i++) { result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } diff --git a/layout/includes/third-party/newest-comments/github-issues.pug b/layout/includes/third-party/newest-comments/github-issues.pug index 59f7cd7..46d9547 100644 --- a/layout/includes/third-party/newest-comments/github-issues.pug +++ b/layout/includes/third-party/newest-comments/github-issues.pug @@ -35,13 +35,13 @@ script. } }) - btf.saveToLocal.set('github-newest-comments', JSON.stringify(array), !{theme.newest_comments.storage}/(60*24)) + btf.saveToLocal.set('github-newest-comments', JSON.stringify(array), !{theme.aside.card_newest_comments.storage}/(60*24)) generateHtml(array) }); } const getComment = () => { - fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.newest_comments.limit}&page=1',{ + fetch('https://api.github.com/repos/!{userRepo}/issues/comments?sort=updated&direction=desc&per_page=!{theme.aside.card_newest_comments.limit}&page=1',{ "headers": { Accept: 'application/vnd.github.v3.html+json' } @@ -72,7 +72,7 @@ script. for (let i = 0; i < array.length; i++) { result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } diff --git a/layout/includes/third-party/newest-comments/remark42.pug b/layout/includes/third-party/newest-comments/remark42.pug index 2e2e432..680f826 100644 --- a/layout/includes/third-party/newest-comments/remark42.pug +++ b/layout/includes/third-party/newest-comments/remark42.pug @@ -23,7 +23,7 @@ script. for (let i = 0; i < array.length; i++) { result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } @@ -44,7 +44,7 @@ script. } const getComment = () => { - fetch('!{host}/api/v1/last/!{theme.newest_comments.limit}?site=!{siteId}') + fetch('!{host}/api/v1/last/!{theme.aside.card_newest_comments.limit}?site=!{siteId}') .then(response => response.json()) .then(data => { const remark42 = data.map(function (e) { @@ -56,7 +56,7 @@ script. 'date': e.time, } }) - btf.saveToLocal.set('remark42-newest-comments', JSON.stringify(remark42), !{theme.newest_comments.storage}/(60*24)) + btf.saveToLocal.set('remark42-newest-comments', JSON.stringify(remark42), !{theme.aside.card_newest_comments.storage}/(60*24)) generateHtml(remark42) }).catch(e => { const $dom = document.querySelector('#card-newest-comments .aside-list') diff --git a/layout/includes/third-party/newest-comments/twikoo-comment.pug b/layout/includes/third-party/newest-comments/twikoo-comment.pug index 7ea418a..35caf59 100644 --- a/layout/includes/third-party/newest-comments/twikoo-comment.pug +++ b/layout/includes/third-party/newest-comments/twikoo-comment.pug @@ -5,7 +5,7 @@ script. content = content.replace(/]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link content = content.replace(/]+?href=["']?([^"']+)["']?[^>]*>([^<]+)<\/a>/gi, '[!{_p("aside.card_newest_comments.link")}]') // replace url - content = content.replace(/
.*?<\/pre>/gi, '[!{_p("aside.card_newest_comments.code")}]') // replace code
+      content = content.replace(/
.*?<\/pre>/gi, '[!{_p("aside.card_aside.card_aside.card_newest_comments.code")}]') // replace code
       content = content.replace(/<[^>]+>/g,"") // remove html tag
 
       if (content.length > 150) {
@@ -19,7 +19,7 @@ script.
         twikoo.getRecentComments({
           envId: '!{theme.twikoo.envId}',
           region: '!{theme.twikoo.region}',
-          pageSize: !{theme.newest_comments.limit},
+          pageSize: !{theme.aside.card_newest_comments.limit},
           includeReply: true
         }).then(function (res) {
           const twikooArray = res.map(e => {
@@ -32,7 +32,7 @@ script.
             }
           })
 
-          btf.saveToLocal.set('twikoo-newest-comments', JSON.stringify(twikooArray), !{theme.newest_comments.storage}/(60*24))
+          btf.saveToLocal.set('twikoo-newest-comments', JSON.stringify(twikooArray), !{theme.aside.card_newest_comments.storage}/(60*24))
           generateHtml(twikooArray)
         }).catch(function (err) {
           const $dom = document.querySelector('#card-newest-comments .aside-list')
@@ -54,7 +54,7 @@ script.
         for (let i = 0; i < array.length; i++) {
           result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } diff --git a/layout/includes/third-party/newest-comments/valine.pug b/layout/includes/third-party/newest-comments/valine.pug index 55f0a91..e0159b9 100644 --- a/layout/includes/third-party/newest-comments/valine.pug +++ b/layout/includes/third-party/newest-comments/valine.pug @@ -31,7 +31,7 @@ script. for (let i = 0; i < array.length; i++) { result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } @@ -63,7 +63,7 @@ script. }, } - fetch(`${serverURL}/1.1/classes/Comment?limit=!{theme.newest_comments.limit}&order=-createdAt`,settings) + fetch(`${serverURL}/1.1/classes/Comment?limit=!{theme.aside.card_newest_comments.limit}&order=-createdAt`,settings) .then(response => response.json()) .then(data => { const valineArray = data.results.map(function (e) { @@ -75,7 +75,7 @@ script. 'date': e.updatedAt, } }) - btf.saveToLocal.set('valine-newest-comments', JSON.stringify(valineArray), !{theme.newest_comments.storage}/(60*24)) + btf.saveToLocal.set('valine-newest-comments', JSON.stringify(valineArray), !{theme.aside.card_newest_comments.storage}/(60*24)) generateHtml(valineArray) }).catch(e => { const $dom = document.querySelector('#card-newest-comments .aside-list') diff --git a/layout/includes/third-party/newest-comments/waline.pug b/layout/includes/third-party/newest-comments/waline.pug index a5eb0cc..b1888cb 100644 --- a/layout/includes/third-party/newest-comments/waline.pug +++ b/layout/includes/third-party/newest-comments/waline.pug @@ -23,7 +23,7 @@ script. for (let i = 0; i < array.length; i++) { result += '
' - if (!{theme.newest_comments.avatar}) { + if (!{theme.aside.card_newest_comments.avatar}) { const name = '!{theme.lazyload.enable ? "data-lazy-src" : "src"}' result += `${array[i].nick}` } @@ -45,7 +45,7 @@ script. const getComment = async () => { try { - const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{theme.newest_comments.limit}', { method: 'GET' }) + const res = await fetch('!{serverURL}/api/comment?type=recent&count=!{theme.aside.card_newest_comments.limit}', { method: 'GET' }) const result = await res.json() const walineArray = result.data.map(e => { return { @@ -56,7 +56,7 @@ script. 'date': e.time || e.insertedAt } }) - btf.saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.newest_comments.storage}/(60*24)) + btf.saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.aside.card_newest_comments.storage}/(60*24)) generateHtml(walineArray) } catch (err) { console.error(err) diff --git a/layout/includes/third-party/pjax.pug b/layout/includes/third-party/pjax.pug index 0872385..55e386c 100644 --- a/layout/includes/third-party/pjax.pug +++ b/layout/includes/third-party/pjax.pug @@ -32,7 +32,7 @@ script. document.addEventListener('pjax:send', function () { // removeEventListener - btf.removeGlobalFnEvent('pjax') + btf.removeGlobalFnEvent('pjaxSendOnce') btf.removeGlobalFnEvent('themeChange') //reset readmode @@ -43,6 +43,7 @@ script. }) document.addEventListener('pjax:complete', () => { + btf.removeGlobalFnEvent('pjaxCompleteOnce') document.querySelectorAll('script[data-pjax]').forEach(item => { const newScript = document.createElement('script') const content = item.text || item.textContent || item.innerHTML || "" diff --git a/layout/includes/third-party/search/docsearch.pug b/layout/includes/third-party/search/docsearch.pug index 9adad8b..b8e3140 100644 --- a/layout/includes/third-party/search/docsearch.pug +++ b/layout/includes/third-party/search/docsearch.pug @@ -1,4 +1,4 @@ -- const { appId, apiKey, indexName, option } = theme.docsearch +- const { placeholder, docsearch: { appId, apiKey, indexName, option } } = theme.search .docsearch-wrap #docsearch(style="display:none") @@ -11,6 +11,7 @@ apiKey: '!{apiKey}', indexName: '!{indexName}', container: '#docsearch', + placeholder: '!{ placeholder || _p("search.input_placeholder")}', }, !{JSON.stringify(option)})) const handleClick = () => { diff --git a/layout/includes/third-party/search/index.pug b/layout/includes/third-party/search/index.pug index 160df79..a9d0c69 100644 --- a/layout/includes/third-party/search/index.pug +++ b/layout/includes/third-party/search/index.pug @@ -1,6 +1,7 @@ -if theme.algolia_search.enable - include ./algolia.pug -else if theme.local_search.enable - include ./local-search.pug -else if theme.docsearch.enable - include ./docsearch.pug \ No newline at end of file +case theme.search.use + when 'algolia_search' + include ./algolia.pug + when 'local_search' + include ./local-search.pug + when 'docsearch' + include ./docsearch.pug \ No newline at end of file diff --git a/layout/includes/third-party/search/local-search.pug b/layout/includes/third-party/search/local-search.pug index f22f05b..af96ab0 100644 --- a/layout/includes/third-party/search/local-search.pug +++ b/layout/includes/third-party/search/local-search.pug @@ -13,7 +13,7 @@ .search-wrap #local-search-input .local-search-box - input(placeholder=_p("search.local_search.input_placeholder") type="text").local-search-box--input + input(placeholder=theme.search.placeholder || _p("search.input_placeholder") type="text").local-search-box--input hr #local-search-results #local-search-stats-wrap diff --git a/layout/includes/third-party/share/index.pug b/layout/includes/third-party/share/index.pug index f8122c0..447c589 100644 --- a/layout/includes/third-party/share/index.pug +++ b/layout/includes/third-party/share/index.pug @@ -1,5 +1,9 @@ -.post_share - if theme.sharejs.enable - include ./share-js.pug - else if theme.addtoany.enable - !=partial('includes/third-party/share/addtoany', {}, {cache: true}) +- const { use } = theme.share + +if use + .post-share + case use + when 'addtoany' + !=partial('includes/third-party/share/addtoany', {}, {cache: true}) + when 'sharejs' + include ./share-js.pug \ No newline at end of file diff --git a/layout/includes/third-party/share/share-js.pug b/layout/includes/third-party/share/share-js.pug index 612332c..50d5528 100644 --- a/layout/includes/third-party/share/share-js.pug +++ b/layout/includes/third-party/share/share-js.pug @@ -1,4 +1,4 @@ - const coverVal = page.cover_type === 'img' ? page.cover : theme.avatar.img -.social-share(data-image=url_for(coverVal) data-sites= theme.sharejs.sites) +.social-share(data-image=url_for(coverVal) data-sites= theme.share.sharejs.sites) link(rel='stylesheet' href=url_for(theme.asset.sharejs_css) media="print" onload="this.media='all'") script(src=url_for(theme.asset.sharejs) defer) \ No newline at end of file diff --git a/layout/includes/third-party/subtitle.pug b/layout/includes/third-party/subtitle.pug index c5fed4c..4689340 100644 --- a/layout/includes/third-party/subtitle.pug +++ b/layout/includes/third-party/subtitle.pug @@ -3,7 +3,7 @@ script. window.typedJSFn = { - init: (str) => { + init: str => { window.typed = new Typed('#subtitle', Object.assign({ strings: str, startDelay: 300, @@ -12,7 +12,7 @@ script. backSpeed: 50, }, !{JSON.stringify(typed_option)})) }, - run: (subtitleType) => { + run: subtitleType => { if (!{effect}) { if (typeof Typed === 'function') { subtitleType() @@ -24,7 +24,7 @@ script. } } } - btf.addGlobalFn('pjaxSend', () => { typed.destroy() }, 'typedDestroy') + btf.addGlobalFn('pjaxSendOnce', () => { typed.destroy() }, 'typedDestroy') case source when 1 diff --git a/layout/includes/widget/card_author.pug b/layout/includes/widget/card_author.pug index 0a1e71a..c4f01d4 100644 --- a/layout/includes/widget/card_author.pug +++ b/layout/includes/widget/card_author.pug @@ -1,12 +1,11 @@ if theme.aside.card_author.enable - .card-widget.card-info - .is-center - .avatar-img - img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar") - .author-info__name= config.author - .author-info__description!= theme.aside.card_author.description || config.description + .card-widget.card-info.is-center + .avatar-img + img(src=url_for(theme.avatar.img) onerror=`this.onerror=null;this.src='` + url_for(theme.error_img.flink) + `'` alt="avatar") + .author-info-name= config.author + .author-info-description!= theme.aside.card_author.description || config.description - .card-info-data.site-data.is-center + .site-data a(href=url_for(config.archive_dir) + '/') .headline= _p('aside.articles') .length-num= site.posts.length @@ -23,5 +22,5 @@ if theme.aside.card_author.enable span=theme.aside.card_author.button.text if(theme.social) - .card-info-social-icons.is-center - !=partial('includes/header/social', {}, {cache: true}) + .card-info-social-icons + !=partial('includes/header/social', {}, {cache: true}) diff --git a/layout/includes/widget/card_newest_comment.pug b/layout/includes/widget/card_newest_comment.pug index a7a213c..3a0bb18 100644 --- a/layout/includes/widget/card_newest_comment.pug +++ b/layout/includes/widget/card_newest_comment.pug @@ -1,4 +1,4 @@ -if theme.newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0]) +if theme.aside.card_newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0]) .card-widget#card-newest-comments .item-headline i.fas.fa-comment-dots diff --git a/layout/includes/widget/card_webinfo.pug b/layout/includes/widget/card_webinfo.pug index 9ff3de0..acf3048 100644 --- a/layout/includes/widget/card_webinfo.pug +++ b/layout/includes/widget/card_webinfo.pug @@ -8,10 +8,10 @@ if theme.aside.card_webinfo.enable .webinfo-item .item-name= _p('aside.card_webinfo.article_name') + " :" .item-count= site.posts.length - if theme.runtimeshow.enable + if theme.aside.card_webinfo.runtime_date .webinfo-item .item-name= _p('aside.card_webinfo.runtime.name') + " :" - .item-count#runtimeshow(data-publishDate=date_xml(theme.runtimeshow.publish_date)) + .item-count#runtimeshow(data-publishDate=date_xml(theme.aside.card_webinfo.runtime_date)) i.fa-solid.fa-spinner.fa-spin if theme.wordcount.enable && theme.wordcount.total_wordcount .webinfo-item diff --git a/layout/index.pug b/layout/index.pug index 2655cb4..7705655 100644 --- a/layout/index.pug +++ b/layout/index.pug @@ -1,7 +1,5 @@ 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 + include ./includes/mixins/indexPostUI.pug + +indexPostUI \ No newline at end of file diff --git a/layout/page.pug b/layout/page.pug index 6c810ef..eb2663e 100644 --- a/layout/page.pug +++ b/layout/page.pug @@ -1,20 +1,32 @@ extends includes/layout.pug block content - #page - if top_img === false + - const noCardLayout = ['shuoshuo', '404'].includes(page.type) ? 'nc' : '' + - var commentsJsLoad = false + + mixin commentLoad + if page.comments !== false && theme.comments.use + - commentsJsLoad = true + !=partial('includes/third-party/comments/index', {}, {cache: true}) + + #page(class=noCardLayout) + if top_img === false && page.title h1.page-title= page.title case page.type when 'tags' include includes/page/tags.pug + +commentLoad when 'link' include includes/page/flink.pug + +commentLoad when 'categories' include includes/page/categories.pug + +commentLoad + when '404' + include includes/page/404.pug + when 'shuoshuo' + include includes/page/shuoshuo.pug default include includes/page/default-page.pug - - if page.comments !== false && theme.comments && theme.comments.use - - var commentsJsLoad = true - !=partial('includes/third-party/comments/index', {}, {cache: true}) \ No newline at end of file + +commentLoad \ No newline at end of file diff --git a/layout/post.pug b/layout/post.pug index f54ab7a..07c696e 100644 --- a/layout/post.pug +++ b/layout/post.pug @@ -8,7 +8,7 @@ block content article#article-container.post-content!=page.content include includes/post/post-copyright.pug .tag_share - if (theme.post_meta.post.tags) + if (page.tags.length > 0 && theme.post_meta.post.tags) .post-meta__tag-list each item, index in page.tags.data a(href=url_for(item.path)).post-meta__tags #[=item.name] @@ -26,7 +26,7 @@ block content if theme.related_post && theme.related_post.enable != related_posts(page,site.posts) - if page.comments !== false && theme.comments && theme.comments.use + if page.comments !== false && theme.comments.use - var commentsJsLoad = true !=partial('includes/third-party/comments/index', {}, {cache: true}) \ No newline at end of file diff --git a/layout/tag.pug b/layout/tag.pug index 9f99658..3d4c067 100644 --- a/layout/tag.pug +++ b/layout/tag.pug @@ -2,10 +2,8 @@ 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 + include ./includes/mixins/indexPostUI.pug + +indexPostUI else include ./includes/mixins/article-sort.pug #tag diff --git a/package.json b/package.json index 8235a6b..3945458 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hexo-theme-butterfly", - "version": "4.14.0-b3", + "version": "5.0.0-b1", "description": "A Simple and Card UI Design theme for Hexo", "main": "package.json", "scripts": { diff --git a/plugins.yml b/plugins.yml index 60f69ae..8ff8f85 100644 --- a/plugins.yml +++ b/plugins.yml @@ -1,7 +1,7 @@ abcjs_basic_js: name: abcjs file: dist/abcjs-basic-min.js - version: 6.3.0 + version: 6.4.1 activate_power_mode: name: butterfly-extsrc file: dist/activate-power-mode.min.js @@ -9,7 +9,7 @@ activate_power_mode: algolia_search: name: algoliasearch file: dist/algoliasearch-lite.umd.js - version: 4.23.2 + version: 4.24.0 aplayer_css: name: aplayer file: dist/APlayer.min.css @@ -21,11 +21,11 @@ aplayer_js: artalk_css: name: artalk file: dist/Artalk.css - version: 2.8.3 + version: 2.8.7 artalk_js: name: artalk file: dist/Artalk.js - version: 2.8.3 + version: 2.8.7 blueimp_md5: name: blueimp-md5 file: js/md5.min.js @@ -62,26 +62,26 @@ docsearch_css: name: '@docsearch/css' other_name: docsearch-css file: dist/style.css - version: 3.6.0 + version: 3.6.1 docsearch_js: name: '@docsearch/js' other_name: docsearch-js file: dist/umd/index.js - version: 3.6.0 + version: 3.6.1 egjs_infinitegrid: name: '@egjs/infinitegrid' other_name: egjs-infinitegrid file: dist/infinitegrid.min.js - version: 4.11.1 + version: 4.12.0 fancybox: name: '@fancyapps/ui' file: dist/fancybox/fancybox.umd.js - version: 5.0.35 + version: 5.0.36 other_name: fancyapps-ui fancybox_css: name: '@fancyapps/ui' file: dist/fancybox/fancybox.css - version: 5.0.35 + version: 5.0.36 other_name: fancyapps-ui fireworks: name: butterfly-extsrc @@ -91,7 +91,7 @@ fontawesome: name: '@fortawesome/fontawesome-free' file: css/all.min.css other_name: font-awesome - version: 6.5.1 + version: 6.6.0 gitalk: name: gitalk file: dist/gitalk.min.js @@ -107,21 +107,21 @@ instantpage: instantsearch: name: instantsearch.js file: dist/instantsearch.production.min.js - version: 4.66.1 + version: 4.73.3 katex: name: katex file: dist/katex.min.css other_name: KaTeX - version: 0.16.10 + version: 0.16.11 katex_copytex: name: katex file: dist/contrib/copy-tex.min.js other_name: KaTeX - version: 0.16.10 + version: 0.16.11 lazyload: name: vanilla-lazyload file: dist/lazyload.iife.min.js - version: 19.0.5 + version: 19.1.3 mathjax: name: mathjax file: es5/tex-mml-chtml.js @@ -133,7 +133,7 @@ medium_zoom: mermaid: name: mermaid file: dist/mermaid.min.js - version: 10.9.0 + version: 10.9.1 meting_js: name: butterfly-extsrc file: metingjs/dist/Meting.min.js @@ -190,7 +190,7 @@ snackbar_css: twikoo: name: twikoo file: dist/twikoo.all.min.js - version: 1.6.32 + version: 1.6.38 typed: name: typed.js file: dist/typed.umd.js @@ -198,14 +198,14 @@ typed: valine: name: valine file: dist/Valine.min.js - version: 1.5.1 + version: 1.5.2 waline_css: name: '@waline/client' file: dist/waline.css other_name: waline - version: 3.1.3 + version: 3.3.0 waline_js: name: '@waline/client' file: dist/waline.js other_name: waline - version: 3.1.3 + version: 3.3.0 diff --git a/scripts/events/404.js b/scripts/events/404.js index 02491ce..17a05e9 100644 --- a/scripts/events/404.js +++ b/scripts/events/404.js @@ -12,7 +12,9 @@ hexo.extend.generator.register('404', function (locals) { layout: ['page'], data: { type: '404', - top_img: false + top_img: false, + comments: false, + aside: false } } }) diff --git a/scripts/events/merge_config.js b/scripts/events/merge_config.js index 8aa538f..ebca510 100644 --- a/scripts/events/merge_config.js +++ b/scripts/events/merge_config.js @@ -1,3 +1,5 @@ +const { deepMerge } = require('hexo-util') + hexo.extend.filter.register('before_generate', () => { const defaultConfig = { nav: { @@ -6,33 +8,36 @@ hexo.extend.filter.register('before_generate', () => { fixed: false }, menu: null, - highlight_theme: 'light', - highlight_theme_macStyle: false, - highlight_copy: true, - highlight_lang: true, - highlight_shrink: false, - highlight_fullpage: true, - highlight_height_limit: false, - code_word_wrap: false, + code_blocks: { + theme: 'light', + macStyle: false, + height_limit: false, + word_wrap: false, + copy: true, + language: true, + shrink: false, + fullpage: false + }, social: null, favicon: '/img/favicon.png', avatar: { - img: 'https://i.loli.net/2021/02/24/5O1day2nriDzjSu.png', + img: '/img/butterfly-icon.png', effect: false }, disable_top_img: false, - index_img: null, default_top_img: null, + index_img: null, archive_img: null, tag_img: null, tag_per_img: null, category_img: null, category_per_img: null, + footer_img: false, + background: null, cover: { index_enable: true, aside_enable: true, archives_enable: true, - position: 'both', default_cover: null }, error_img: { @@ -42,7 +47,7 @@ hexo.extend.filter.register('before_generate', () => { error_404: { enable: false, subtitle: 'Page Not Found', - background: 'https://i.loli.net/2020/05/19/aKOcLiyPl2JQdFD.png' + background: '/img/error-page.png' }, post_meta: { page: { @@ -61,22 +66,20 @@ hexo.extend.filter.register('before_generate', () => { label: true } }, + index_site_info_top: null, + index_top_img_height: null, + subtitle: { + enable: false, + effect: true, + typed_option: null, + source: false, + sub: null + }, + index_layout: 3, index_post_content: { method: 3, length: 500 }, - anchor: { - auto_update: false, - click_to_scroll: false - }, - photofigcaption: false, - copy: { - enable: true, - copyright: { - enable: false, - limit_count: 50 - } - }, toc: { post: true, page: false, @@ -110,7 +113,7 @@ hexo.extend.filter.register('before_generate', () => { noticeOutdate: { enable: false, style: 'flat', - limit_day: 500, + limit_day: 365, position: 'top', message_prev: 'It has been', message_next: 'days since the last update, the content of the article may be outdated.' @@ -118,7 +121,7 @@ hexo.extend.filter.register('before_generate', () => { footer: { owner: { enable: true, - since: 2020 + since: 2019 }, custom_text: null, copyright: true @@ -154,6 +157,13 @@ hexo.extend.filter.register('before_generate', () => { sort: 'date', sort_order: null }, + card_newest_comments: { + enable: false, + sort_order: null, + limit: 6, + storage: 10, + avatar: true + }, card_categories: { enable: true, limit: 8, @@ -176,35 +186,21 @@ hexo.extend.filter.register('before_generate', () => { limit: 8, sort_order: null }, - card_webinfo: { - enable: true, - post_count: true, - last_push_date: true, - sort_order: null - }, card_post_series: { enable: true, series_title: false, orderBy: 'date', order: -1 + }, + card_webinfo: { + enable: true, + post_count: true, + last_push_date: true, + sort_order: null, + runtime_date: null } }, - busuanzi: { - site_uv: true, - site_pv: true, - page_pv: true - }, - runtimeshow: { - enable: false, - publish_date: null - }, - newest_comments: { - enable: false, - sort_order: null, - limit: 6, - storage: 10, - avatar: true - }, + rightside_bottom: null, translate: { enable: false, default: '繁', @@ -227,42 +223,68 @@ hexo.extend.filter.register('before_generate', () => { hide: null, show: null }, - mathjax: { - enable: false, - per_page: false - }, - katex: { - enable: false, - per_page: false, - hide_scrollbar: true + anchor: { + auto_update: false, + click_to_scroll: false }, - algolia_search: { - enable: false, - hits: { - per_page: 6 + photofigcaption: false, + copy: { + enable: true, + copyright: { + enable: false, + limit_count: 150 } }, - local_search: { + wordcount: { enable: false, - preload: false, - top_n_per_article: 1, - unescape: false, - CDN: null + post_wordcount: true, + min2read: true, + total_wordcount: true }, - docsearch: { - enable: false, - appId: null, - apiKey: null, - indexName: null, - option: null + busuanzi: { + site_uv: true, + site_pv: true, + page_pv: true }, - sharejs: { - enable: true, - sites: 'facebook,twitter,wechat,weibo,qq' + math: { + use: null, + per_page: true, + hide_scrollbar: false, + mathjax: { + enableMenu: true, + tags: 'none' + }, + katex: { + copy_tex: false + } }, - addtoany: { - enable: false, - item: 'facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link' + search: { + use: null, + placeholder: null, + algolia_search: { + hitsPerPage: 6 + }, + local_search: { + preload: false, + top_n_per_article: 1, + unescape: false, + CDN: null + }, + docsearch: { + appId: null, + apiKey: null, + indexName: null, + option: null + } + }, + share: { + use: 'sharejs', + sharejs: { + sites: 'facebook,twitter,wechat,weibo,qq' + }, + addtoany: { + item: 'facebook,twitter,wechat,sina_weibo,facebook_messenger,email,copy_link' + } }, comments: { use: null, @@ -310,7 +332,9 @@ hexo.extend.filter.register('before_generate', () => { repo: null, issue_term: 'pathname', light_theme: 'github-light', - dark_theme: 'photon-dark' + dark_theme: 'photon-dark', + js: null, + option: null }, facebook_comments: { app_id: null, @@ -329,10 +353,9 @@ hexo.extend.filter.register('before_generate', () => { repo: null, repo_id: null, category_id: null, - theme: { - light: 'light', - dark: 'dark' - }, + light_theme: 'light', + dark_theme: 'dark', + js: null, option: null }, remark42: { @@ -346,26 +369,24 @@ hexo.extend.filter.register('before_generate', () => { visitor: false, option: null }, - chat_btn: false, - chat_hide_show: false, + chat: { + use: null, + rightside_button: false, + button_hide_show: false + }, chatra: { - enable: false, id: null }, tidio: { - enable: false, public_key: null }, daovoice: { - enable: false, app_id: null }, crisp: { - enable: false, website_id: null }, messenger: { - enable: false, pageID: null, lang: 'zh_TW' }, @@ -380,20 +401,48 @@ hexo.extend.filter.register('before_generate', () => { client: null, enable_page_level_ads: true }, + ad: { + index: null, + aside: null, + post: null + }, site_verification: null, - index_site_info_top: null, - index_top_img_height: null, category_ui: null, tag_ui: null, + rounded_corners_ui: true, text_align_justify: false, - background: null, - footer_bg: false, mask: { header: true, footer: true }, - rightside_bottom: null, + preloader: { + enable: false, + source: 1, + pace_css_url: null + }, enter_transitions: true, + display_mode: 'light', + beautify: { + enable: false, + field: 'post', + 'title-prefix-icon': null, + 'title-prefix-icon-color': null + }, + font: { + 'global-font-size': null, + 'code-font-size': null, + 'font-family': null, + 'code-font-family': null + }, + blog_title_font: { + font_link: null, + 'font-family': null + }, + hr_icon: { + enable: true, + icon: null, + 'icon-top': null + }, activate_power_mode: { enable: false, colorful: true, @@ -436,50 +485,9 @@ hexo.extend.filter.register('before_generate', () => { random: false, mobile: false }, - display_mode: 'light', - beautify: { - enable: false, - field: 'post', - 'title-prefix-icon': null, - 'title-prefix-icon-color': null - }, - font: { - 'global-font-size': null, - 'code-font-size': null, - 'font-family': null, - 'code-font-family': null - }, - blog_title_font: { - font_link: null, - 'font-family': null - }, - hr_icon: { - enable: true, - icon: null, - 'icon-top': null - }, - subtitle: { - enable: false, - effect: true, - typed_option: null, - source: false, - sub: null - }, - preloader: { - enable: false, - source: 1, - pace_css_url: null - }, - wordcount: { - enable: false, - post_wordcount: true, - min2read: true, - total_wordcount: true - }, - medium_zoom: false, - fancybox: true, + lightbox: null, series: { - enable: true, + enable: false, orderBy: 'title', order: 1, number: true @@ -527,6 +535,14 @@ hexo.extend.filter.register('before_generate', () => { placeholder: null, blur: false }, + pwa: { + enable: false, + manifest: null, + apple_touch_icon: null, + favicon_32_32: null, + favicon_16_16: null, + mask_icon: null + }, Open_Graph_meta: { enable: true, option: null @@ -539,11 +555,11 @@ hexo.extend.filter.register('before_generate', () => { CDN: { internal_provider: 'local', third_party_provider: 'jsdelivr', - version: true, + version: false, custom_format: null, option: null } } - hexo.theme.config = Object.assign(defaultConfig, hexo.theme.config) + hexo.theme.config = deepMerge(defaultConfig, hexo.theme.config) }, 1) diff --git a/scripts/events/stylus.js b/scripts/events/stylus.js index 4756318..15ca4ff 100644 --- a/scripts/events/stylus.js +++ b/scripts/events/stylus.js @@ -19,5 +19,6 @@ hexo.extend.filter.register('stylus:renderer', style => { .define('$highlight_line_number', highlightLineNumber) .define('$prismjs_enable', prismjsEnable) .define('$prismjs_line_number', prismjsLineNumber) + .define('$language', hexo.config.language) // .import(`${this.source_dir.replace(/\\/g, '/')}_data/css/*`) }) diff --git a/scripts/helpers/findArchiveLength.js b/scripts/helpers/findArchiveLength.js deleted file mode 100644 index 152b15e..0000000 --- a/scripts/helpers/findArchiveLength.js +++ /dev/null @@ -1,58 +0,0 @@ -hexo.extend.helper.register('getArchiveLength', function () { - const { archive_generator: archiveGenerator } = hexo.config - if (archiveGenerator && archiveGenerator.enable === false) return this.site.posts.length - const { yearly, monthly, daily } = archiveGenerator - const { year, month, day } = this.page - if (yearly === false || !year) return this.site.posts.length - - const posts = this.site.posts.sort('date') - - const compareFunc = (type, y1, m1, d1, y2, m2, d2) => { - switch (type) { - case 'year': - return y1 === y2 - case 'month': - return y1 === y2 && m1 === m2 - case 'day': - return y1 === y2 && m1 === m2 && d1 === d2 - default: - return false - } - } - - const generateDateObj = (type) => { - return posts.reduce((dateObj, post) => { - const date = post.date.clone() - const year = date.year() - const month = date.month() + 1 - const day = date.date() - const lastData = dateObj[dateObj.length - 1] - - if (!lastData || !compareFunc(type, lastData.year, lastData.month, lastData.day, year, month, day)) { - const name = type === 'year' ? year : type === 'month' ? `${year}-${month}` : `${year}-${month}-${day}` - dateObj.push({ - name, - year, - month, - day, - count: 1 - }) - } else { - lastData.count++ - } - - return dateObj - }, []) - } - - const data = this.fragment_cache('createArchiveObj', () => { - const dateObjs = [] - if (yearly) dateObjs.push(...generateDateObj('year')) - if (monthly) dateObjs.push(...generateDateObj('month')) - if (daily) dateObjs.push(...generateDateObj('day')) - return dateObjs - }) - - const name = month ? (day ? `${year}-${month}-${day}` : `${year}-${month}`) : year - return data.find(item => item.name === name).count -}) diff --git a/scripts/helpers/getArchiveLength.js b/scripts/helpers/getArchiveLength.js new file mode 100644 index 0000000..1ff35c8 --- /dev/null +++ b/scripts/helpers/getArchiveLength.js @@ -0,0 +1,45 @@ +hexo.extend.helper.register('getArchiveLength', function () { + const archiveGenerator = hexo.config.archive_generator + const posts = this.site.posts + + const { yearly, monthly, daily } = archiveGenerator + const { year, month, day } = this.page + + // Archives Page + if (!year) return posts.length + + // Function to generate a unique key based on the granularity + const getKey = (post, type) => { + const date = post.date.clone() + const y = date.year() + const m = date.month() + 1 + const d = date.date() + if (type === 'year') return `${y}` + if (type === 'month') return `${y}-${m}` + if (type === 'day') return `${y}-${m}-${d}` + } + + // Create a map to count posts per period + const mapData = this.fragment_cache('createArchiveObj', () => { + const map = new Map() + posts.forEach(post => { + const keyYear = getKey(post, 'year') + const keyMonth = getKey(post, 'month') + const keyDay = getKey(post, 'day') + + if (yearly) map.set(keyYear, (map.get(keyYear) || 0) + 1) + if (monthly) map.set(keyMonth, (map.get(keyMonth) || 0) + 1) + if (daily) map.set(keyDay, (map.get(keyDay) || 0) + 1) + }) + return map + }) + + // Determine the appropriate key to fetch based on current page context + let key + if (yearly && year) key = `${year}` + if (monthly && month) key = `${year}-${month}` + if (daily && day) key = `${year}-${month}-${day}` + + // Return the count for the current period or default to the total posts + return mapData.get(key) || posts.length +}) diff --git a/scripts/helpers/inject_head_js.js b/scripts/helpers/inject_head_js.js index 417d851..574d18e 100644 --- a/scripts/helpers/inject_head_js.js +++ b/scripts/helpers/inject_head_js.js @@ -1,6 +1,12 @@ /** * Butterfly * inject js to head + * + * addGlobalFn + * pjaxSendOnce - remove in pjaxSend + * pjaxCompleteOnce - remove in pjaxComplete + * pjaxSend - run in pjaxSend + * pjaxComplete - run in pjaxComplete */ 'use strict' diff --git a/scripts/helpers/page.js b/scripts/helpers/page.js index 6c773e3..72ef5be 100644 --- a/scripts/helpers/page.js +++ b/scripts/helpers/page.js @@ -1,18 +1,10 @@ 'use strict' -const { stripHTML, escapeHTML, prettyUrls } = require('hexo-util') +const { stripHTML, prettyUrls, truncate } = 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, 150) - .trim() - ).replace(/\n/g, ' ') - return description - } +hexo.extend.helper.register('truncate', (content, length) => { + return truncate(stripHTML(content), { length, separator: ' ' }).replace(/\n/g, ' ') }) hexo.extend.helper.register('cloudTags', function (options = {}) { @@ -32,13 +24,26 @@ hexo.extend.helper.register('cloudTags', function (options = {}) { sizes.push(length) }) + const getRandomColor = () => { + const randomColor = () => Math.floor(Math.random() * 201) + const r = randomColor() + const g = randomColor() + const b = randomColor() + // 確保顏色不是太暗,通過增加一個最低值 + return `rgb(${Math.max(r, 50)}, ${Math.max(g, 50)}, ${Math.max(b, 50)})` + } + + const generateStyle = (size, unit) => { + const fontSize = parseFloat(size.toFixed(2)) + unit + const color = getRandomColor() + return `font-size: ${fontSize}; color: ${color};` + } + const length = sizes.length - 1 source.sort(orderby, order).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}` + const style = generateStyle(size, unit) result += `${tag.name}` }) return result @@ -84,5 +89,5 @@ hexo.extend.helper.register('findArchivesTitle', function (page, menu, date) { hexo.extend.helper.register('isImgOrUrl', function (path) { const imgTestReg = /\.(png|jpe?g|gif|svg|webp)(\?.*)?$/i - return path.indexOf('//') !== -1 || imgTestReg.test(path) + return path.includes('//') || imgTestReg.test(path) }) diff --git a/scripts/helpers/related_post.js b/scripts/helpers/related_post.js index 9a46f68..46f4381 100644 --- a/scripts/helpers/related_post.js +++ b/scripts/helpers/related_post.js @@ -8,9 +8,10 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { let relatedPosts = [] - currentPost.tags.forEach(function (tag) { + const tagsData = currentPost.tags + tagsData.length && tagsData.forEach(function (tag) { allPosts.forEach(function (post) { - if (isTagRelated(tag.name, post.tags)) { + if (currentPost.path !== post.path && isTagRelated(tag.name, post.tags)) { const relatedPost = { title: post.title, path: post.path, @@ -24,13 +25,12 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { if (index !== -1) { relatedPosts[index].weight += 1 } else { - if (currentPost.path !== post.path) { - relatedPosts.push(relatedPost) - } + relatedPosts.push(relatedPost) } } }) }) + if (relatedPosts.length === 0) { return '' } @@ -52,7 +52,7 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { for (let i = 0; i < Math.min(relatedPosts.length, limitNum); i++) { const cover = relatedPosts[i].cover || 'var(--default-bg-color)' const title = this.escape_html(relatedPosts[i].title) - result += `' + result += '
' } result += '
' @@ -72,29 +72,14 @@ hexo.extend.helper.register('related_posts', function (currentPost, allPosts) { } }) -function isTagRelated (tagName, TBDtags) { - let result = false - TBDtags.forEach(function (tag) { - if (tagName === tag.name) { - result = true - } - }) - return result +function isTagRelated (tagName, tags) { + return tags.some(tag => tag.name === tagName) } function findItem (arrayToSearch, attr, val) { - for (let i = 0; i < arrayToSearch.length; i++) { - if (arrayToSearch[i][attr] === val) { - return i - } - } - return -1 + return arrayToSearch.findIndex(item => item[attr] === val) } function compare (attr) { - return function (a, b) { - const val1 = a[attr] - const val2 = b[attr] - return val2 - val1 - } + return (a, b) => b[attr] - a[attr] } diff --git a/scripts/tag/gallery.js b/scripts/tag/gallery.js index f8bceb6..2753eed 100644 --- a/scripts/tag/gallery.js +++ b/scripts/tag/gallery.js @@ -19,6 +19,7 @@ const gallery = (args, content) => { if (args[0] === 'url') { [type, dataStr, button] = args // url,[link],[lazyload] + dataStr = urlFor(dataStr) } else { [button] = args // [lazyload] const regex = /!\[(.*?)\]\(([^\s]*)\s*(?:["'](.*?)["']?)?\s*\)/g @@ -39,9 +40,7 @@ const gallery = (args, content) => { } return `` } diff --git a/scripts/tag/label.js b/scripts/tag/label.js index 4c9e692..cae17ca 100644 --- a/scripts/tag/label.js +++ b/scripts/tag/label.js @@ -8,7 +8,7 @@ const addLabel = args => { const [text, className = 'default'] = args - return `${text} ` + return `${text}` } hexo.extend.tag.register('label', addLabel, { ends: false }) diff --git a/scripts/tag/series.js b/scripts/tag/series.js index 4a901df..8108836 100644 --- a/scripts/tag/series.js +++ b/scripts/tag/series.js @@ -63,7 +63,7 @@ function series (args) { result += `
  • ${ele.title}
  • ` }) - return series.number ? `
      ${result}
    ` : `
      ${result}
    ` + return series.number ? `
      ${result}
    ` : `
      ${result}
    ` } hexo.extend.tag.register('series', series, { ends: false }) diff --git a/scripts/tag/tabs.js b/scripts/tag/tabs.js index 6ec87de..29321fd 100644 --- a/scripts/tag/tabs.js +++ b/scripts/tag/tabs.js @@ -9,7 +9,7 @@ const postTabs = (args, content) => { const tabBlock = /\n([\w\W\s\S]*?)/g args = args.join(' ').split(',') - const tabName = args[0] + const tabName = args[0] || 'tab' const tabActive = Number(args[1]) || 0 const matches = [] let match @@ -18,8 +18,6 @@ const postTabs = (args, content) => { let tabContent = '' let noDefault = true - !tabName && hexo.log.warn('Tabs block must have unique name!') - while ((match = tabBlock.exec(content)) !== null) { matches.push(match[1], match[2]) } @@ -29,34 +27,31 @@ const postTabs = (args, content) => { let postContent = matches[i + 1] let tabCaption = tabParameters[0] || '' let tabIcon = tabParameters[1] || '' - let tabHref = '' postContent = hexo.render.renderSync({ text: postContent, engine: 'markdown' }).trim() tabId += 1 - tabHref = (tabName + ' ' + tabId).toLowerCase().split(' ').join('-'); - ((tabCaption.length === 0) && (tabIcon.length === 0)) && (tabCaption = tabName + ' ' + tabId) + if (tabCaption.length === 0 && tabIcon.length === 0) tabCaption = tabName + ' ' + tabId - const isOnlyicon = tabIcon.length > 0 && tabCaption.length === 0 ? ' style="text-align: center;"' : '' const icon = tabIcon.trim() - tabIcon.length > 0 && (tabIcon = ``) + tabIcon.length > 0 && (tabIcon = ``) let isActive = '' if ((tabActive > 0 && tabActive === tabId) || (tabActive === 0 && tabId === 1)) { isActive = ' active' noDefault = false } - tabNav += `` - tabContent += `
    ${postContent}
    ` + tabNav += `` + tabContent += `
    ${postContent}
    ` } const toTop = '
    ' - tabNav = `` + tabNav = `` tabContent = `
    ${tabContent}
    ` - return `
    ${tabNav + tabContent + toTop}
    ` + return `
    ${tabNav + tabContent + toTop}
    ` } hexo.extend.tag.register('tabs', postTabs, { ends: true }) diff --git a/source/css/_global/function.styl b/source/css/_global/function.styl index 85d96db..a210c52 100644 --- a/source/css/_global/function.styl +++ b/source/css/_global/function.styl @@ -15,12 +15,16 @@ text-rendering: auto -webkit-font-smoothing: antialiased +addBorderRadius(x = 6) + if hexo-config('rounded_corners_ui') + border-radius: unit(x, 'px') + // card hover .cardHover - border-radius: 8px background: var(--card-bg) box-shadow: var(--card-box-shadow) transition: all .3s + addBorderRadius(8) &:hover box-shadow: var(--card-hover-box-shadow) @@ -37,11 +41,10 @@ .postImgHover &:hover .cover - opacity: .8 + opacity: .7 transform: scale(1.1) .cover - position: absolute width: 100% height: 100% opacity: .4 @@ -96,6 +99,12 @@ transition: all 1s ease-in-out @extend .fontawesomeIcon +.verticalCenter + position: absolute + top: 50% + width: 100% + transform: translate(0, -50%) + maxWidth600() @media screen and (max-width: 600px) {block} @@ -112,6 +121,10 @@ maxWidth1024() @media screen and (max-width: 1024px) {block} +minWidth1024() + @media screen and (min-width: 1024px) + {block} + maxWidth900() @media screen and (max-width: 900px) {block} @@ -261,4 +274,4 @@ if hexo-config('avatar.effect') == true transform: translateX(200px) 100% - transform: translateX(0) \ No newline at end of file + transform: translateX(0) diff --git a/source/css/_global/index.styl b/source/css/_global/index.styl index 1f55e41..0a4373f 100644 --- a/source/css/_global/index.styl +++ b/source/css/_global/index.styl @@ -15,7 +15,9 @@ --tab-button-hover-bg: $tab-button-hover-bg --tab-button-active-bg: $tab-button-active-bg --card-bg: $card-bg + --card-meta: $theme-meta-color --sidebar-bg: $sidebar-background + --sidebar-menu-bg: $white --btn-hover-color: $button-hover-color --btn-color: $button-color --btn-bg: $button-bg @@ -39,6 +41,7 @@ body position: relative + overflow-y: scroll min-height: 100% background: var(--global-bg) color: var(--font-color) @@ -52,6 +55,12 @@ body user-select: none -webkit-user-select: none +// scrollbar - firefox +@-moz-document url-prefix() + * + scrollbar-width: thin + scrollbar-color: var(--scrollbar-color) transparent + // scrollbar - chrome/safari *::-webkit-scrollbar width: 5px @@ -63,11 +72,6 @@ body *::-webkit-scrollbar-track background-color: transparent -// scrollbar - firefox -* - scrollbar-width: thin - scrollbar-color: var(--scrollbar-color) transparent - input::placeholder color: var(--font-color) @@ -104,11 +108,34 @@ h6 overflow-x: scroll margin: 0 0 20px + if hexo-config('rounded_corners_ui') + $borderRadius = 5px + border-radius: $borderRadius + + table + border-radius: $borderRadius + + thead > tr:first-child + th:first-child + border-top-left-radius: $borderRadius + + th:last-child + border-top-right-radius: $borderRadius + + tbody > tr:last-child + td:first-child + border-bottom-left-radius: $borderRadius + + td:last-child + border-bottom-right-radius: $borderRadius + table display: table width: 100% border-spacing: 0 - border-collapse: collapse + border-collapse: separate + border-top: 1px solid var(--light-grey) + border-left: 1px solid var(--light-grey) empty-cells: show thead @@ -118,6 +145,8 @@ table td padding: 6px 12px border: 1px solid var(--light-grey) + border-top: none + border-left: none vertical-align: middle *::selection @@ -147,8 +176,8 @@ if $site-name-font #site-title, #site-subtitle, .site-name, - #aside-content .author-info__name, - #aside-content .author-info__description + #aside-content .author-info-name, + #aside-content .author-info-description font-family: $site-name-font .is-center @@ -183,10 +212,11 @@ if hexo-config('lazyload.enable') && hexo-config('lazyload.blur') && !hexo-confi blockquote margin: 0 0 20px - padding: 12px 15px - border-left: 3px solid $blockquote-padding-color + padding: 7px 15px + border-left: 4px solid $blockquote-padding-color background-color: var(--blockquote-bg) color: var(--blockquote-color) + addBorderRadius() footer cite diff --git a/source/css/_highlight/highlight.styl b/source/css/_highlight/highlight.styl index 370390c..16d3ea3 100644 --- a/source/css/_highlight/highlight.styl +++ b/source/css/_highlight/highlight.styl @@ -1,6 +1,6 @@ -$highlight_theme = hexo-config('highlight_theme') -$highlight_macstyle = hexo-config('highlight_theme_macStyle') -wordWrap = $highlight_enable && !$highlight_line_number && hexo-config('code_word_wrap') +$highlight_theme = hexo-config('code_blocks.theme') +$highlight_macstyle = hexo-config('code_blocks.macStyle') +wordWrap = $highlight_enable && !$highlight_line_number && hexo-config('code_blocks.word_wrap') @require 'theme' @@ -47,9 +47,10 @@ $code-block code font-size: $code-font-size font-family: $code-font-family !important + addBorderRadius() code - padding: 2px 4px + padding: 2px 5px background: $code-background color: $code-foreground @@ -66,6 +67,7 @@ $code-block figure.highlight @extend $code-block position: relative + addBorderRadius() pre margin: 0 @@ -104,9 +106,10 @@ $code-block background: var(--hltools-bg) color: var(--hltools-color) font-size: $code-font-size + overflow: hidden & > * - margin: 0 3px + padding: 5px i cursor: pointer @@ -124,7 +127,7 @@ $code-block if !$highlight_macstyle & > .macStyle - margin: 0 + padding: 0 .code-lang flex: 1 @@ -133,16 +136,17 @@ $code-block font-size: 1.15em user-select: none -webkit-user-select: none + padding 2px .copy-notice padding-right: 2px opacity: 0 transition: opacity .4s - if hexo-config('highlight_lang') + if hexo-config('code_blocks.language') .code-lang flex: 1 - else if (!$highlight_macstyle && hexo-config('highlight_shrink') != 'none') + else if (!$highlight_macstyle && hexo-config('code_blocks.shrink') != 'none') & > div:nth-child(2) flex: 1 else @@ -168,8 +172,6 @@ if $highlight_macstyle -webkit-transform: translateZ(0) .highlight-tools - padding: 0 10px - .macStyle display: flex @@ -191,15 +193,15 @@ if $highlight_macstyle .mac-maximize background: #35cd4b - if hexo-config('highlight_shrink') != 'none' - & > div:nth-child(2) + if hexo-config('code_blocks.shrink') != 'none' + & > :nth-child(2) order: 8 &.closed .expand transform: rotate(90deg) -if hexo-config('highlight_height_limit') +if hexo-config('code_blocks.height_limit') #article-container .code-expand-btn position: absolute @@ -228,7 +230,7 @@ if hexo-config('highlight_height_limit') & ~ table, & ~ pre overflow: hidden - height: unit(hexo-config('highlight_height_limit'), px) + height: unit(hexo-config('code_blocks.height_limit'), px) @keyframes code-expand-key 0% @@ -240,7 +242,7 @@ if hexo-config('highlight_height_limit') 100% opacity: .6 -if hexo-config('highlight_fullpage') +if hexo-config('code_blocks.fullpage') #article-container figure.highlight.code-fullpage position: fixed diff --git a/source/css/_highlight/highlight/diff.styl b/source/css/_highlight/highlight/diff.styl index 83f3e17..6d8db97 100644 --- a/source/css/_highlight/highlight/diff.styl +++ b/source/css/_highlight/highlight/diff.styl @@ -1,6 +1,8 @@ figure.highlight table - scrollbar-color: var(--hlscrollbar-bg) transparent + // scrollbar - firefox + @-moz-document url-prefix() + scrollbar-color: var(--hlscrollbar-bg) transparent &::-webkit-scrollbar-thumb background: var(--hlscrollbar-bg) diff --git a/source/css/_highlight/prismjs/index.styl b/source/css/_highlight/prismjs/index.styl index 1b73837..1427826 100644 --- a/source/css/_highlight/prismjs/index.styl +++ b/source/css/_highlight/prismjs/index.styl @@ -6,7 +6,9 @@ if $highlight_theme != false #article-container pre[class*='language-'] - scrollbar-color: var(--hlscrollbar-bg) transparent + // scrollbar - firefox + @-moz-document url-prefix() + scrollbar-color: var(--hlscrollbar-bg) transparent &::-webkit-scrollbar-thumb background: var(--hlscrollbar-bg) diff --git a/source/css/_highlight/prismjs/line-number.styl b/source/css/_highlight/prismjs/line-number.styl index e37215b..97b2133 100644 --- a/source/css/_highlight/prismjs/line-number.styl +++ b/source/css/_highlight/prismjs/line-number.styl @@ -10,7 +10,7 @@ position: relative line-height: $line-height-code-block - if hexo-config('code_word_wrap') + if hexo-config('code_blocks.word_wrap') white-space: pre-wrap else white-space: inherit diff --git a/source/css/_layout/aside.styl b/source/css/_layout/aside.styl index f9c1bae..a716c01 100644 --- a/source/css/_layout/aside.styl +++ b/source/css/_layout/aside.styl @@ -8,19 +8,14 @@ padding-right: 15px +maxWidth900() + margin-top: 20px width: 100% - > .card-widget:first-child - margin-top: 0 - - +maxWidth900() - margin-top: 20px - .card-widget @extend .cardHover position: relative overflow: hidden - margin-top: 20px + margin-bottom: 20px padding: 20px 24px if hexo-config('aside.mobile') == false @@ -28,16 +23,19 @@ &:not(#card-toc) display: none + &:last-child + margin-bottom: 0 + .card-info .author-info - &__name + &-name font-weight: 500 font-size: 1.57em - &__description + &-description margin-top: -.42em - .card-info-data + .site-data margin: 14px 0 4px .card-info-social-icons @@ -61,6 +59,7 @@ color: var(--btn-color) text-align: center line-height: 2.4 + addBorderRadius(7) &:hover background-color: var(--btn-hover-color) @@ -86,6 +85,7 @@ a display: inline-block padding: 0 4px + line-height: 1.8 &:hover color: $text-hover !important @@ -112,8 +112,9 @@ .thumbnail overflow: hidden - width: w = 4.2em + width: w = 4em height: w + addBorderRadius() :first-child @extend .imgHover @@ -130,14 +131,14 @@ & > time, & > .name display: block - color: $theme-meta-color - font-size: 85% + color: var(--card-meta) + font-size: .85em & > .title, & > .comment @extend .limit-more-line color: var(--font-color) - font-size: 95% + // font-size: 95% line-height: 1.5 -webkit-line-clamp: 2 @@ -158,13 +159,16 @@ a display: flex flex-direction: row - padding: 3px 10px + padding: 2px 8px + margin: 2px 0 color: var(--font-color) - transition: all .4s + transition: all .3s + addBorderRadius() &:hover - padding: 3px 17px + padding: 2px 12px background-color: var(--text-bg-hover) + color: var(--white) span @extend .limit-one-line @@ -288,9 +292,10 @@ .toc-link display: block margin: 4px 0 - padding: 1px 6px + padding: 1px 8px color: var(--toc-link-color) transition: all .2s ease-in-out + addBorderRadius() &:hover color: $theme-color @@ -397,9 +402,9 @@ .card-recent-post order: hexo-config('aside.card_recent_post.sort_order') - if hexo-config('newest_comments.sort_order') + if hexo-config('aside.card_newest_comments.sort_order') #card-newest-comments - order: hexo-config('newest_comments.sort_order') + order: hexo-config('aside.card_newest_comments.sort_order') if hexo-config('aside.card_categories.sort_order') .card-categories diff --git a/source/css/_layout/chat.styl b/source/css/_layout/chat.styl index ea12227..6b9551b 100644 --- a/source/css/_layout/chat.styl +++ b/source/css/_layout/chat.styl @@ -1,17 +1,18 @@ // chat -if hexo-config('chat_btn') == true && hexo-config('chatra.enable') - #chatra:not(.chatra--expanded) - visibility: hidden !important - width: 1px !important - height: 1px !important - opacity: 0 !important - pointer-events: none +if hexo-config('chat.rightside_button') == true + if hexo-config('chat.use') == 'chatra' + #chatra:not(.chatra--expanded) + visibility: hidden !important + width: 1px !important + height: 1px !important + opacity: 0 !important + pointer-events: none -if hexo-config('chat_btn') == true && hexo-config('messenger.enable') - .fb_dialog, - .fb-customerchat - visibility: hidden !important - width: 1px !important - height: 1px !important - opacity: 0 !important - pointer-events: none \ No newline at end of file + if hexo-config('chat.use') == 'messenger' + .fb_dialog, + .fb-customerchat + visibility: hidden !important + width: 1px !important + height: 1px !important + opacity: 0 !important + pointer-events: none diff --git a/source/css/_layout/footer.styl b/source/css/_layout/footer.styl index e398510..69553f3 100644 --- a/source/css/_layout/footer.styl +++ b/source/css/_layout/footer.styl @@ -5,7 +5,7 @@ background-position: bottom background-size: cover - if hexo-config('footer_bg') != false && hexo-config('mask.footer') + if hexo-config('footer_img') != false && hexo-config('mask.footer') &:before position: absolute width: 100% diff --git a/source/css/_layout/head.styl b/source/css/_layout/head.styl index 79274f5..06e89d4 100644 --- a/source/css/_layout/head.styl +++ b/source/css/_layout/head.styl @@ -146,6 +146,7 @@ background: rgba(255, 255, 255, .8) box-shadow: 0 5px 6px -5px alpha($grey, .6) transition: transform .2s ease-in-out, opacity .2s ease-in-out + will-change: transform #blog-info color: var(--font-color) @@ -345,10 +346,10 @@ margin-top: 8px padding: 0 width: max-content - border-radius: 5px background-color: var(--sidebar-bg) box-shadow: 0 5px 20px -4px rgba($dark-black, .5) animation: sub_menus .3s .1s ease both + addBorderRadius(5) &:before position: absolute @@ -364,13 +365,14 @@ &:hover background: var(--text-bg-hover) - &:first-child - border-top-left-radius: 5px - border-top-right-radius: 5px + if hexo-config('rounded_corners_ui') + &:first-child + border-top-left-radius: 5px + border-top-right-radius: 5px - &:last-child - border-bottom-right-radius: 5px - border-bottom-left-radius: 5px + &:last-child + border-bottom-right-radius: 5px + border-bottom-left-radius: 5px a display: inline-block diff --git a/source/css/_layout/pagination.styl b/source/css/_layout/pagination.styl index 6d729e3..3deedeb 100644 --- a/source/css/_layout/pagination.styl +++ b/source/css/_layout/pagination.styl @@ -37,47 +37,40 @@ .prev-post, .next-post @extend .postImgHover + position: relative + overflow: hidden width: 50% + height: 150px +maxWidth768() width: 100% - a - position: relative - display: block - overflow: hidden - height: 150px - &.pagination-post overflow: hidden margin-top: 40px width: 100% background: $dark-black + addBorderRadius() .layout - & > .recent-posts - .pagination - & > * - display: inline-block - margin: 0 6px - width: w = 2.5em - height: w - line-height: w + .pagination + & > * + display: inline-block + margin: 0 6px + width: w = 2.5em + height: w + line-height: w - & > *:not(.space) - @extend .cardHover + & > *:not(.space) + @extend .cardHover - &:hover - background: var(--btn-hover-color) - color: var(--btn-color) + &:hover + background: var(--btn-hover-color) + color: var(--btn-color) + +#archive + .pagination + margin-top: 30px - & > div:not(.recent-posts) - .pagination - .page-number - display: inline-block - margin: 0 4px - min-width: w = 24px - height: w - text-align: center - line-height: w - cursor: pointer + & > *:not(.space) + box-shadow: none \ No newline at end of file diff --git a/source/css/_layout/post.styl b/source/css/_layout/post.styl index b5a8583..589ad2f 100644 --- a/source/css/_layout/post.styl +++ b/source/css/_layout/post.styl @@ -87,6 +87,7 @@ beautify() margin: 0 auto 20px max-width: 100% transition: filter 375ms ease-in .2s + addBorderRadius() p margin: 0 0 16px @@ -98,7 +99,6 @@ beautify() margin: 0 3px padding: 3px 5px border: 1px solid #b4b4b4 - border-radius: 3px background-color: #f8f8f8 box-shadow: 0 1px 3px rgba(0, 0, 0, .25), 0 2px 1px 0 rgba(255, 255, 255, .6) inset color: #34495e @@ -107,6 +107,7 @@ beautify() font-size: .9em font-family: Monaco, 'Ubuntu Mono', monospace line-height: 1em + addBorderRadius(3) if hexo-config('anchor.click_to_scroll') h1, @@ -181,7 +182,7 @@ beautify() background: $light-blue color: var(--white) - .post_share + .post-share display: inline-block float: right margin: 8px 0 0 @@ -203,6 +204,7 @@ beautify() padding: 10px 16px border: 1px solid var(--light-grey) transition: box-shadow .3s ease-in-out + addBorderRadius() &:before @extend .fontawesomeIcon @@ -238,9 +240,9 @@ beautify() position: relative margin: 0 0 20px padding: .5em 1.2em - border-radius: 3px background-color: $noticeOutdate-bg color: $noticeOutdate-color + addBorderRadius(3) if hexo-config('noticeOutdate.style') == 'flat' padding: .5em 1em .5em 2.6em diff --git a/source/css/_layout/relatedposts.styl b/source/css/_layout/relatedposts.styl index e064202..744ca14 100644 --- a/source/css/_layout/relatedposts.styl +++ b/source/css/_layout/relatedposts.styl @@ -7,7 +7,7 @@ font-size: 1.43em & > .relatedPosts-list - & > div + & > a position: relative display: inline-block overflow: hidden @@ -17,6 +17,7 @@ background: $dark-black vertical-align: bottom @extend .postImgHover + addBorderRadius() +maxWidth768() margin: 2px @@ -27,11 +28,8 @@ width: calc(100% - 4px) .content - position: absolute - top: 50% padding: 0 20px - width: 100% - transform: translate(0, -50%) + @extend .verticalCenter .date color: var(--light-grey) diff --git a/source/css/_layout/reward.styl b/source/css/_layout/reward.styl index 4043aa2..5cf3a62 100644 --- a/source/css/_layout/reward.styl +++ b/source/css/_layout/reward.styl @@ -14,6 +14,7 @@ background: var(--btn-bg) color: var(--btn-color) cursor: pointer + addBorderRadius() i margin-right: 5px @@ -33,12 +34,12 @@ display: none padding: 0 0 15px width: 100% + addBorderRadius() .reward-all display: inline-block margin: 0 padding: 20px 10px - border-radius: 4px background: var(--reward-pop) &:before diff --git a/source/css/_layout/rightside.styl b/source/css/_layout/rightside.styl index 7d2832c..45c9726 100644 --- a/source/css/_layout/rightside.styl +++ b/source/css/_layout/rightside.styl @@ -32,12 +32,12 @@ margin-bottom: 5px width: w = 35px height: w - border-radius: 5px background-color: var(--btn-bg) color: var(--btn-color) text-align: center font-size: 16px line-height: w + addBorderRadius(5) &:hover background-color: var(--btn-hover-color) diff --git a/source/css/_layout/sidebar.styl b/source/css/_layout/sidebar.styl index e058f7c..1f30593 100644 --- a/source/css/_layout/sidebar.styl +++ b/source/css/_layout/sidebar.styl @@ -26,27 +26,33 @@ & > .avatar-img margin: 20px auto - .sidebar-site-data + .site-data padding: 0 10px hr margin: 20px auto .menus_items - padding: 0 10px + margin: 20px + padding: 15px + background: var(--sidebar-menu-bg) + box-shadow: 0 0 1px 1px rgba(7, 17, 27, .05) + addBorderRadius(10) .site-page @extend .limit-one-line position: relative display: block - padding: 3px 28px 3px 20px - border-radius: 6px + margin: 4px 0 + padding: 2px 23px 2px 15px color: var(--font-color) font-size: 1.15em cursor: pointer + addBorderRadius(6) &:hover background: var(--text-bg-hover) + color: var(--white) i:first-child width: 15% @@ -55,8 +61,8 @@ &.group & > i:last-child position: absolute - top: .78em - right: 13px + top: .6em + right: 10px transition: transform .3s &.hide diff --git a/source/css/_layout/third-party.styl b/source/css/_layout/third-party.styl index bc3226a..aa20ed4 100644 --- a/source/css/_layout/third-party.styl +++ b/source/css/_layout/third-party.styl @@ -79,31 +79,45 @@ if hexo-config('mermaid.enable') margin: 0 0 .8em padding: 6px 0 16px -.katex-display - overflow: auto hidden - padding: 5px +if hexo-config('math.use') + .katex-display + overflow: auto hidden + padding: 5px - if hexo-config('katex') && hexo-config('katex.hide_scrollbar') - &::-webkit-scrollbar - display: none + .katex-show + display: block + + .katex + display: none + + &.katex-show + display: inline + + if hexo-config('math.hide_scrollbar') + .katex-display, + mjx-container + scrollbar-width: none + + &::-webkit-scrollbar + display: none -// Mathjax -mjx-container - overflow-x: auto - overflow-y: hidden - padding-bottom: 4px - max-width: 100% + // Mathjax + mjx-container + overflow-x: auto + overflow-y: hidden + padding-bottom: 4px + max-width: 100% - &[display] - display: block !important - min-width: auto !important + &[display] + display: block !important + min-width: auto !important - &:not([display]) - display: inline-grid !important + &:not([display]) + display: inline-grid !important -mjx-assistive-mml - right: 0 - bottom: 0 + mjx-assistive-mml + right: 0 + bottom: 0 .aplayer color: $font-black diff --git a/source/css/_mode/darkmode.styl b/source/css/_mode/darkmode.styl index 2251ee8..de4b749 100644 --- a/source/css/_mode/darkmode.styl +++ b/source/css/_mode/darkmode.styl @@ -16,6 +16,7 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' --tab-button-active-bg: #121212 --card-bg: #121212 --sidebar-bg: #121212 + --sidebar-menu-bg: lighten(#121212, 5) --btn-hover-color: lighten(#121212, 40) --btn-color: alpha(#FFFFFF, .7) --btn-bg: lighten(#121212, 5) @@ -139,4 +140,21 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark' #card-toc +maxWidth900() - background: lighten(#121212, 5) \ No newline at end of file + background: lighten(#121212, 5) + + // artalk + .artalk.atk-dark-mode, + .atk-layer-wrap.atk-dark-mode + --at-color-font: alpha(#FFFFFF, .7) + --at-color-meta: alpha(#FFFFFF, .7) + --at-color-grey: alpha(#FFFFFF, .7) + + .atk-send-btn, + .atk-badge + color: alpha(#FFFFFF, .7) !important + + // waline + #waline-wrap + --waline-color: alpha(#FFFFFF, .7) + --waline-dark-grey: alpha(#FFFFFF, .7) + --waline-info-color: alpha(#FFFFFF, .5) \ No newline at end of file diff --git a/source/css/_mode/readmode.styl b/source/css/_mode/readmode.styl index 906b50f..8ead478 100644 --- a/source/css/_mode/readmode.styl +++ b/source/css/_mode/readmode.styl @@ -37,11 +37,11 @@ if hexo-config('readmode') z-index: 100 width: 40px height: 40px - border-radius: 8px background: var(--exit-btn-bg) color: var(--exit-btn-color) font-size: 16px transition: background .3s + addBorderRadius(8) +maxWidth768() top: initial diff --git a/source/css/_page/404.styl b/source/css/_page/404.styl index ea8e056..5bd23c4 100644 --- a/source/css/_page/404.styl +++ b/source/css/_page/404.styl @@ -1,69 +1,66 @@ if hexo-config('error_404.enable') - .error404 - #error-wrap - position: absolute - top: 50% - right: 0 - left: 0 - margin: 0 auto - padding: 60px 20px 0 - max-width: 1000px - transform: translate(0, -50%) + .type-404 + .error-content + @extend .cardHover + overflow: hidden + margin: 0 20px + height: 360px - .error-content - @extend .cardHover + +maxWidth768() + margin: 0 + height: 500px + + .error-img + display: inline-block overflow: hidden - margin: 0 20px - height: 360px + width: 50% + height: 100% +maxWidth768() - margin: 0 - height: 500px + width: 100% + height: 45% - .error-img - display: inline-block - overflow: hidden - width: 50% - height: 100% + img + @extend .imgHover + background-color: $theme-color - +maxWidth768() - width: 100% - height: 45% + .error-info + display: inline-flex + flex-direction: column + justify-content: center + align-content: center + width: 50% + height: 100% + vertical-align: top + text-align: center - img - @extend .imgHover - background-color: $theme-color + if $site-name-font + font-family: $site-name-font - .error-info - display: inline-flex - flex-direction: column - justify-content: center - align-content: center - width: 50% - height: 100% - vertical-align: top - text-align: center + +maxWidth768() + width: 100% + height: 55% - if $site-name-font - font-family: $site-name-font + .error_title + margin-top: -.6em + font-size: 9em +maxWidth768() - width: 100% - height: 55% + font-size: 8em - .error_title - margin-top: -.6em - font-size: 9em + .error_subtitle + @extend .limit-more-line + margin-top: -3em + word-break: break-word + font-size: 1.6em + -webkit-line-clamp: 2 - +maxWidth768() - font-size: 8em + .nc + margin-top: 5% + padding: 0 20px - .error_subtitle - @extend .limit-more-line - margin-top: -3em - word-break: break-word - font-size: 1.6em - -webkit-line-clamp: 2 + #footer + display: none & + #rightside display: none \ No newline at end of file diff --git a/source/css/_page/archives.styl b/source/css/_page/archives.styl index 309e00c..35efa6b 100644 --- a/source/css/_page/archives.styl +++ b/source/css/_page/archives.styl @@ -78,8 +78,8 @@ border-color: var(--pseudo-hover) &-time - color: $theme-meta-color - font-size: 95% + color: var(--card-meta) + font-size: .85em time padding-left: 6px @@ -88,7 +88,7 @@ &-title @extend .limit-more-line color: var(--font-color) - font-size: 1.1em + font-size: 1.05em transition: all .3s -webkit-line-clamp: 2 @@ -98,8 +98,13 @@ &-img overflow: hidden - width: 80px - height: 80px + width: 100px + height: 70px + addBorderRadius() + + +maxWidth768() + width: 70px + height: 70px :first-child @extend .imgHover diff --git a/source/css/_page/categories.styl b/source/css/_page/categories.styl index 8b80107..9e65061 100644 --- a/source/css/_page/categories.styl +++ b/source/css/_page/categories.styl @@ -16,7 +16,7 @@ .category-list-count margin-left: 8px - color: $theme-meta-color + color: var(--card-meta) &:before content: '(' diff --git a/source/css/_page/common.styl b/source/css/_page/common.styl index 32096a5..9e25c20 100644 --- a/source/css/_page/common.styl +++ b/source/css/_page/common.styl @@ -20,7 +20,7 @@ +minWidth2000() max-width: 70% - & > div:first-child:not(.recent-posts) + & > div:first-child:not(.nc) @extend .cardHover align-self: flex-start padding: 50px 40px diff --git a/source/css/_page/flink.styl b/source/css/_page/flink.styl index 57dd50a..db01b6c 100644 --- a/source/css/_page/flink.styl +++ b/source/css/_page/flink.styl @@ -14,9 +14,9 @@ margin: 15px 7px width: calc(100% / 3 - 15px) height: 90px - border-radius: 8px line-height: 17px -webkit-transform: translateZ(0) + addBorderRadius(8) +maxWidth1024() width: calc(50% - 15px) !important @@ -56,7 +56,7 @@ margin: 15px 10px width: 60px height: 60px - border-radius: 35px + border-radius: 7px transition: width .3s ease-out img diff --git a/source/css/_page/homepage.styl b/source/css/_page/homepage.styl index e81311a..84883f7 100644 --- a/source/css/_page/homepage.styl +++ b/source/css/_page/homepage.styl @@ -1,21 +1,39 @@ -#recent-posts - & > .recent-post-item:not(:first-child) - margin-top: 20px +$indexLayout = hexo-config('index_layout') || 1 +$indexEnable = hexo-config('cover.index_enable') - & > .recent-post-item +#recent-posts + .recent-post-item @extend .cardHover - display: flex - flex-direction: row - align-items: center + position: relative overflow: hidden - height: 16.8em + margin-bottom: 20px + + if $indexLayout == 6 || ($indexLayout == 7) + display: inline-block + width: calc(100% / 2 - 8px) + vertical-align: top + + +maxWidth768() + width: 100% - +maxWidth768() - flex-direction: column - height: auto + +minWidth2000() + width: calc(100% / 3 - 8px) + + if $indexLayout == 1 || ($indexLayout == 2 || ($indexLayout == 3)) + display: flex + flex-direction: row + align-items: center + height: 16.8em + + +maxWidth768() + flex-direction: column + height: auto + + +minWidth2000() + height: 18.8em &:hover - img.post-bg + .post-bg transform: scale(1.1) &.ads-wrap @@ -24,36 +42,77 @@ .post_cover overflow: hidden - width: 42% - height: 100% - +maxWidth768() + if ($indexLayout != 5 && ($indexLayout != 7)) + +maxWidth768() + width: 100% + height: 230px + + if $indexLayout == 1 || ($indexLayout == 2 || ($indexLayout == 3)) + width: 42% + height: 100% + + &.right + order: 1 + + +maxWidth768() + order: 0 + + if $indexLayout == 4 || ($indexLayout == 5 || ($indexLayout == 6 || ($indexLayout == 7))) width: 100% - height: 230px + + if ($indexLayout == 5 || ($indexLayout == 7)) + height: 17em + else + height: 230px + + if ($indexLayout == 5 || ($indexLayout == 7)) && $indexEnable + &:before + position: absolute + z-index: 1 + width: 100% + height: 100% + background-color: rgba(18, 18, 18, .4) + content: '' + backdrop-filter: blur(3px) .post-bg + z-index: -4 @extend .imgHover - &.right - order: 1 - - +maxWidth768() - order: 0 - & >.recent-post-info - padding: 0 40px - width: 58% - +maxWidth768() padding: 20px 20px 30px width: 100% - &.no-cover - width: 100% + if $indexLayout == 1 || ($indexLayout == 2 || ($indexLayout == 3)) + padding: 0 40px + width: 58% + + if $indexLayout == 4 || ($indexLayout == 5 || ($indexLayout == 6 || ($indexLayout == 7))) + padding: 30px 30px 25px + + if ($indexLayout == 5 || ($indexLayout == 7)) && $indexEnable + &:not(.no-cover) + position: absolute + top: 50% + z-index: 2 + width: 100% + color: var(--text-highlight-color) + transform: translateY(-50%) + --text-highlight-color: rgba(255, 255, 255, 1) + --card-meta: rgba(255, 255, 255, .7) + &.no-cover +maxWidth768() padding: 30px 20px + if $indexLayout == 1 || ($indexLayout == 2 || ($indexLayout == 3)) + width: 100% + + if $indexLayout == 4 || ($indexLayout == 5 || ($indexLayout == 6 || ($indexLayout == 7))) + padding: 35px 30px + & > .article-title @extend .limit-more-line color: var(--text-highlight-color) @@ -75,7 +134,7 @@ & > .article-meta-wrap margin: 6px 0 - color: $theme-meta-color + color: var(--card-meta) font-size: .9em & > .post-meta-date @@ -104,7 +163,7 @@ display: none a - color: $theme-meta-color + color: var(--card-meta) &:hover color: $text-hover diff --git a/source/css/_page/shuoshuo.styl b/source/css/_page/shuoshuo.styl new file mode 100644 index 0000000..b7f8609 --- /dev/null +++ b/source/css/_page/shuoshuo.styl @@ -0,0 +1,53 @@ +#article-container + .shuoshuo-item + @extend .cardHover + margin-bottom: 20px + padding: 35px 30px 30px + + +maxWidth768() + padding: 25px 20px 20px + + .shuoshuo-item-header + display: flex + align-items: center + + .shuoshuo-avatar + overflow: hidden + width: 40px + height: 40px + border-radius: 40px + + img + margin: 0 + width: 100% + height: 100% + + .shuoshuo-info + margin-left: 10px + line-height: 1.5 + + .shuoshuo-date + color: #858585 + font-size: .8em + + .shuoshuo-content + padding: 15px 0 10px + + & > *:last-child + margin-bottom: 0 + + .shuoshuo-tag + display: inline-block + margin-right: 8px + padding: 0 8px + width: fit-content + border: 1px solid $light-blue + border-radius: 12px + color: $light-blue + font-size: .85em + cursor: default + transition: all .2s ease-in-out + + &:hover + background: $light-blue + color: var(--white) diff --git a/source/css/_page/tags.styl b/source/css/_page/tags.styl index bce33ae..d8f407a 100644 --- a/source/css/_page/tags.styl +++ b/source/css/_page/tags.styl @@ -2,12 +2,16 @@ &-list a display: inline-block - padding: 0 8px + margin: 2px + padding: 2px 7px + line-height: 1.7 transition: all .3s + addBorderRadius(5) &:hover - color: $text-hover !important - transform: scale(1.1) + background: var(--btn-bg) !important + box-shadow: 2px 2px 6px rgba(0, 0, 0, .2) + color: var(--btn-color) !important +maxWidth768() zoom: .85 diff --git a/source/css/_search/algolia.styl b/source/css/_search/algolia.styl index b2f4067..87f36c4 100644 --- a/source/css/_search/algolia.styl +++ b/source/css/_search/algolia.styl @@ -10,6 +10,11 @@ background: var(--search-bg) color: var(--search-input-color) + .ais-SearchBox-loadingIndicator + position: absolute + top: 18px + left: 67px + .ais-Hits-list margin: 0 padding: 0 @@ -66,7 +71,7 @@ #algolia-hits > div - overflow-y: scroll + overflow-y: overlay margin: 0 -20px padding: 0 22px max-height: calc(80vh - 240px) diff --git a/source/css/_search/index.styl b/source/css/_search/index.styl index 669428b..79986d5 100644 --- a/source/css/_search/index.styl +++ b/source/css/_search/index.styl @@ -7,9 +7,9 @@ margin-left: -300px padding: 20px width: 600px - border-radius: 8px background: var(--search-bg) --search-height: 100vh + addBorderRadius(8) +maxWidth768() top: 0 @@ -53,8 +53,7 @@ display: none background: rgba($dark-black, .6) -if hexo-config('algolia_search.enable') +if hexo-config('search.use') == 'algolia_search' @require 'algolia' - -if hexo-config('local_search.enable') +else if hexo-config('search.use') == 'local_search' @require 'local-search' \ No newline at end of file diff --git a/source/css/_tags/button.styl b/source/css/_tags/button.styl index c4b2c3a..51ff9da 100644 --- a/source/css/_tags/button.styl +++ b/source/css/_tags/button.styl @@ -10,6 +10,7 @@ background-color: var(--btn-beautify-color, $btn-default-color) color: $btn-color line-height: 2 + addBorderRadius() for $type in $color-types &.{$type} diff --git a/source/css/_tags/gallery.styl b/source/css/_tags/gallery.styl index 2c0aa95..fc817e7 100644 --- a/source/css/_tags/gallery.styl +++ b/source/css/_tags/gallery.styl @@ -6,13 +6,16 @@ margin: 6px 4px width: calc(50% - 8px) height: 250px - border-radius: 8px + border-radius: 10px background: $dark-black -webkit-transform: translate3d(0, 0, 0) +maxWidth600() width: calc(100% - 8px) + +minWidth1024() + width: calc(100% / 3 - 8px) + &:hover img opacity: .4 @@ -95,8 +98,12 @@ padding: 0 0 16px .gallery-container - margin: 0 0 16px + margin: 0 0 20px text-align: center + opacity: 0 + + &.loaded + opacity: 1 img display: initial @@ -109,18 +116,20 @@ button margin-top: 25px - padding: 10px - width: 9em - border-radius: 5px + padding: 8px 14px background: var(--btn-bg) color: var(--btn-color) font-weight: bold font-size: 1.1em transition: all .3s + addBorderRadius(5) &:hover background: var(--btn-hover-color) + i + margin-left: 4px + .loading-container display: inline-block overflow: hidden diff --git a/source/css/_tags/hide.styl b/source/css/_tags/hide.styl index 2442e93..a379397 100644 --- a/source/css/_tags/hide.styl +++ b/source/css/_tags/hide.styl @@ -6,6 +6,7 @@ padding: 5px 18px background: $tag-hide-bg color: var(--white) + addBorderRadius() &:hover background-color: var(--btn-hover-color) @@ -35,6 +36,7 @@ .toggle margin-bottom: 20px border: 1px solid $tag-hide-toggle-bg + addBorderRadius() & > .toggle-button padding: 6px 15px diff --git a/source/css/_tags/label.styl b/source/css/_tags/label.styl index d7b814e..5b08c50 100644 --- a/source/css/_tags/label.styl +++ b/source/css/_tags/label.styl @@ -1,7 +1,7 @@ .hl-label padding: 2px 4px - border-radius: 3px color: $btn-color + addBorderRadius(3) &.default background-color: $btn-default-color diff --git a/source/css/_tags/series.styl b/source/css/_tags/series.styl new file mode 100644 index 0000000..5c9139e --- /dev/null +++ b/source/css/_tags/series.styl @@ -0,0 +1,5 @@ +#article-container + .series-items + a + &:hover + color: var(--pseudo-hover) \ No newline at end of file diff --git a/source/css/_tags/tabs.styl b/source/css/_tags/tabs.styl index 2447a1b..0d176a6 100644 --- a/source/css/_tags/tabs.styl +++ b/source/css/_tags/tabs.styl @@ -6,6 +6,8 @@ border-right: 1px solid var(--tab-border-color) border-bottom: 1px solid var(--tab-border-color) border-left: 1px solid var(--tab-border-color) + addBorderRadius() + overflow: hidden > .nav-tabs display: flex diff --git a/source/css/var.styl b/source/css/var.styl index 09e4129..4605a31 100644 --- a/source/css/var.styl +++ b/source/css/var.styl @@ -13,8 +13,11 @@ $code-foreground = $themeColorEnable && hexo-config('theme_color.code_foreground $code-background = $themeColorEnable && hexo-config('theme_color.code_background') ? convert(hexo-config('theme_color.code_background')) : rgba(27, 31, 35, .05) $theme-toc-color = $themeColorEnable && hexo-config('theme_color.toc_color') ? convert(hexo-config('theme_color.toc_color')) : $strong-cyan // font -$dafault-font-family = -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif -$dafault-code-font = consolas, Menlo, 'PingFang SC', 'Microsoft YaHei', sans-serif + +$chinseFont = $language == 'zh-CN' ? 'Microsoft YaHei' : 'Microsoft JhengHei' +$dafault-font-family = -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', $chinseFont, sans-serif +$dafault-code-font = consolas, Menlo, 'PingFang SC', $chinseFont, sans-serif + $font-family = hexo-config('font.font-family') ? unquote(hexo-config('font.font-family')) : $dafault-font-family $code-font-family = hexo-config('font.code-font-family') ? unquote(hexo-config('font.code-font-family')) : $dafault-code-font $site-name-font = hexo-config('blog_title_font.font-family') && unquote(hexo-config('blog_title_font.font-family')) @@ -59,7 +62,7 @@ $sticky-color = $light-orange $theme-meta-color = $themeColorEnable && hexo-config('theme_color.meta_color') ? convert(hexo-config('theme_color.meta_color')) : #858585 // sidebar $sidebar-background = #f6f8fa -$sidebar-width = 300px +$sidebar-width = 330px // aside $toc-link-color = #666261 $toc-mobile-width = calc(100% - 80px) diff --git a/source/img/butterfly-icon.png b/source/img/butterfly-icon.png new file mode 100644 index 0000000..3992d77 Binary files /dev/null and b/source/img/butterfly-icon.png differ diff --git a/source/img/error-page.png b/source/img/error-page.png new file mode 100644 index 0000000..9d1de96 Binary files /dev/null and b/source/img/error-page.png differ diff --git a/source/img/favicon.ico b/source/img/favicon.ico new file mode 100644 index 0000000..56d07f5 Binary files /dev/null and b/source/img/favicon.ico differ diff --git a/source/img/favicon.png b/source/img/favicon.png deleted file mode 100644 index 862ebe8..0000000 Binary files a/source/img/favicon.png and /dev/null differ diff --git a/source/js/main.js b/source/js/main.js index 0d2b82f..d5371ed 100644 --- a/source/js/main.js +++ b/source/js/main.js @@ -1,11 +1,9 @@ -document.addEventListener('DOMContentLoaded', function () { +document.addEventListener('DOMContentLoaded', () => { let headerContentWidth, $nav let mobileSidebarOpen = false const adjustMenu = init => { - const getAllWidth = ele => { - return Array.from(ele).reduce((width, i) => width + i.offsetWidth, 0) - } + const getAllWidth = ele => Array.from(ele).reduce((width, i) => width + i.offsetWidth, 0) if (init) { const blogInfoWidth = getAllWidth(document.querySelector('#blog-info > a').children) @@ -27,16 +25,13 @@ document.addEventListener('DOMContentLoaded', function () { // sidebar menus const sidebarFn = { open: () => { - btf.sidebarPaddingR() - document.body.style.overflow = 'hidden' + btf.overflowPaddingR.add() btf.animateIn(document.getElementById('menu-mask'), 'to_show 0.5s') document.getElementById('sidebar-menus').classList.add('open') mobileSidebarOpen = true }, close: () => { - const $body = document.body - $body.style.overflow = '' - $body.style.paddingRight = '' + btf.overflowPaddingR.remove() btf.animateOut(document.getElementById('menu-mask'), 'to_hide 0.5s') document.getElementById('sidebar-menus').classList.remove('open') mobileSidebarOpen = false @@ -72,7 +67,7 @@ document.addEventListener('DOMContentLoaded', function () { const isPrismjs = plugin === 'prismjs' const highlightShrinkClass = isHighlightShrink === true ? 'closed' : '' - const highlightShrinkEle = isHighlightShrink !== undefined ? '
    ' : '' + const highlightShrinkEle = isHighlightShrink !== undefined ? '' : '' const highlightCopyEle = highlightCopy ? '
    ' : '' const highlightMacStyleEle = '
    ' const highlightFullpageEle = highlightFullpage ? '' : '' @@ -111,9 +106,7 @@ document.addEventListener('DOMContentLoaded', function () { $buttonParent.classList.remove('copy-true') } - const highlightShrinkFn = ele => { - ele.classList.toggle('closed') - } + const highlightShrinkFn = ele => ele.classList.toggle('closed') const codeFullpage = (item, clickEle) => { const wrapEle = item.closest('figure.highlight') @@ -124,47 +117,44 @@ document.addEventListener('DOMContentLoaded', function () { clickEle.classList.toggle('fa-up-right-and-down-left-from-center', !isFullpage) } - const highlightToolsFn = function (e) { + const highlightToolsFn = e => { const $target = e.target.classList - if ($target.contains('expand')) highlightShrinkFn(this) - else if ($target.contains('copy-button')) highlightCopyFn(this, e.target) - else if ($target.contains('fullpage-button')) codeFullpage(this, e.target) - } - - const expandCode = function () { - this.classList.toggle('expand-done') - } - - // 获取隐藏状态下元素的真实高度 - const getActualHeight = function (item) { - let tmp = [] - let hidden = [] - function fix() { - - let current = item - while (current !== document.body && current != null) { - if (window.getComputedStyle(current).display === 'none') { - hidden.push(current) - } - current = current.parentNode + const currentElement = e.currentTarget + if ($target.contains('expand')) highlightShrinkFn(currentElement) + else if ($target.contains('copy-button')) highlightCopyFn(currentElement, e.target) + else if ($target.contains('fullpage-button')) codeFullpage(currentElement, e.target) + } + + const expandCode = e => e.currentTarget.classList.toggle('expand-done') + + // 獲取隱藏狀態下元素的真實高度 + const getActualHeight = item => { + const hiddenElements = new Map() + + const fix = () => { + let current = item + while (current !== document.body && current != null) { + if (window.getComputedStyle(current).display === 'none') { + hiddenElements.set(current, current.getAttribute('style') || '') } - let style = 'visibility: hidden !important; display: block !important; ' - - hidden.forEach(function (elem) { - var thisStyle = elem.getAttribute('style') || '' - tmp.push(thisStyle) - elem.setAttribute('style', thisStyle ? thisStyle + ';' + style : style) - }) - } - function restore() { - hidden.forEach((elem, idx) => { - let _tmp = tmp[idx] - if( _tmp === '' ) elem.removeAttribute('style') - else elem.setAttribute('style', _tmp) - }) + current = current.parentNode + } + + const style = 'visibility: hidden !important; display: block !important;' + hiddenElements.forEach((originalStyle, elem) => { + elem.setAttribute('style', originalStyle ? originalStyle + ';' + style : style) + }) + } + + const restore = () => { + hiddenElements.forEach((originalStyle, elem) => { + if (originalStyle === '') elem.removeAttribute('style') + else elem.setAttribute('style', originalStyle) + }) } + fix() - let height = item.offsetHeight + const height = item.offsetHeight restore() return height } @@ -236,7 +226,7 @@ document.addEventListener('DOMContentLoaded', function () { * justified-gallery 圖庫排版 */ - const fetchUrl = async (url) => { + const fetchUrl = async url => { const response = await fetch(url) return await response.json() } @@ -254,10 +244,6 @@ document.addEventListener('DOMContentLoaded', function () { // useRecycle: false }) - if (tabs) { - btf.addGlobalFn('igOfTabs', () => { ig.destroy() }, false, tabs) - } - const replaceDq = str => str.replace(/"/g, '"') // replace double quotes to " const getItems = (nextGroupKey, count) => { @@ -274,7 +260,7 @@ document.addEventListener('DOMContentLoaded', function () { const alt = item.alt ? `alt="${replaceDq(item.alt)}"` : '' const title = item.title ? `title="${replaceDq(item.title)}"` : '' - nextItems.push(`
    + nextItems.push(`
    `) } @@ -284,16 +270,14 @@ document.addEventListener('DOMContentLoaded', function () { const buttonText = GLOBAL_CONFIG.infinitegrid.buttonText const addButton = item => { const button = document.createElement('button') - button.textContent = buttonText + button.innerHTML = buttonText + '' - const buttonFn = e => { - e.target.removeEventListener('click', buttonFn) - e.target.remove() + button.addEventListener('click', e => { + e.target.closest('button').remove() btf.setLoading.add(item) appendItem(ig.getGroups().length + 1, 10) - } + }, { once: true }) - button.addEventListener('click', buttonFn) item.insertAdjacentElement('afterend', button) } @@ -302,8 +286,22 @@ document.addEventListener('DOMContentLoaded', function () { } const maxGroupKey = Math.ceil(dataLength / 10) + let isLayoutHidden = false const completeFn = e => { + if (tabs) { + const parentNode = item.parentNode + + if (isLayoutHidden) { + parentNode.style.visibility = 'visible' + } + + if (item.offsetHeight === 0) { + parentNode.style.visibility = 'hidden' + isLayoutHidden = true + } + } + const { updated, isResize, mounted } = e if (!updated.length || !mounted.length || isResize) { return @@ -313,7 +311,7 @@ document.addEventListener('DOMContentLoaded', function () { if (ig.getGroups().length === maxGroupKey) { btf.setLoading.remove(item) - ig.off('renderComplete', completeFn) + !tabs && ig.off('renderComplete', completeFn) return } @@ -342,29 +340,30 @@ document.addEventListener('DOMContentLoaded', function () { ig.renderItems() } - btf.addGlobalFn('justifiedGallery', () => { ig.destroy() }) + btf.addGlobalFn('pjaxSendOnce', () => { ig.destroy() }) } const addJustifiedGallery = async (ele, tabs = false) => { const init = async () => { for (const item of ele) { - if (btf.isHidden(item)) continue - if (tabs && item.classList.contains('loaded')) { - item.querySelector('.gallery-items').innerHTML = '' - const button = item.querySelector(':scope > button') - const loadingContainer = item.querySelector(':scope > .loading-container') - button && button.remove() - loadingContainer && loadingContainer.remove() - } + if (btf.isHidden(item) || item.classList.contains('loaded')) continue const isButton = item.getAttribute('data-button') === 'true' - const text = item.firstElementChild.textContent + const children = item.firstElementChild + const text = children.textContent + children.textContent = '' item.classList.add('loaded') - const content = item.getAttribute('data-type') === 'url' ? await fetchUrl(text) : JSON.parse(text) - runJustifiedGallery(item.lastElementChild, content, isButton, tabs) + try { + const content = item.getAttribute('data-type') === 'url' ? await fetchUrl(text) : JSON.parse(text) + runJustifiedGallery(children, content, isButton, tabs) + } catch (e) { + console.error('Gallery data parsing failed:', e) + } } } + if (!ele.length) return + if (typeof InfiniteGrid === 'function') { init() } else { @@ -399,12 +398,18 @@ document.addEventListener('DOMContentLoaded', function () { const isChatBtn = typeof chatBtn !== 'undefined' const isShowPercent = GLOBAL_CONFIG.percent.rightside - // 當滾動條小于 56 的時候 - if (document.body.scrollHeight <= innerHeight) { - $rightside.classList.add('rightside-show') - return + // 檢查文檔高度是否小於視窗高度 + const checkDocumentHeight = () => { + if (document.body.scrollHeight <= innerHeight) { + $rightside.classList.add('rightside-show') + return true + } + return false } + // 如果文檔高度小於視窗高度,直接返回 + if (checkDocumentHeight()) return + // find the scroll direction const scrollDirection = currentTop => { const result = currentTop > initTop // true is down & false is up @@ -444,10 +449,7 @@ document.addEventListener('DOMContentLoaded', function () { } isShowPercent && rightsideScrollPercent(currentTop) - - if (document.body.scrollHeight <= innerHeight) { - $rightside.classList.add('rightside-show') - } + checkDocumentHeight() }, 300) btf.addEventListenerPjax(window, 'scroll', scrollTask, { passive: true }) @@ -487,13 +489,15 @@ document.addEventListener('DOMContentLoaded', function () { btf.addEventListenerPjax($cardToc, 'click', tocItemClickFn) autoScrollToc = item => { - const activePosition = item.getBoundingClientRect().top - const sidebarScrollTop = $cardToc.scrollTop - if (activePosition > (document.documentElement.clientHeight - 100)) { - $cardToc.scrollTop = sidebarScrollTop + 150 - } - if (activePosition < 100) { - $cardToc.scrollTop = sidebarScrollTop - 150 + const sidebarHeight = $cardToc.clientHeight + const itemOffsetTop = item.offsetTop + const itemHeight = item.clientHeight + const scrollTop = $cardToc.scrollTop + const offset = itemOffsetTop - scrollTop + const middlePosition = (sidebarHeight - itemHeight) / 2 + + if (offset !== middlePosition) { + $cardToc.scrollTop = scrollTop + (offset - middlePosition) } } @@ -504,21 +508,23 @@ document.addEventListener('DOMContentLoaded', function () { // find head position & add active class const $articleList = $article.querySelectorAll('h1,h2,h3,h4,h5,h6') let detectItem = '' + const findHeadPosition = top => { - if (top === 0) { - return false - } + if (top === 0) return false let currentId = '' let currentIndex = '' - $articleList.forEach((ele, index) => { + for (let i = 0; i < $articleList.length; i++) { + const ele = $articleList[i] if (top > btf.getEleTop(ele) - 80) { const id = ele.id currentId = id ? '#' + encodeURI(id) : '' - currentIndex = index + currentIndex = i + } else { + break } - }) + } if (detectItem === currentIndex) return @@ -527,24 +533,21 @@ document.addEventListener('DOMContentLoaded', function () { detectItem = currentIndex if (isToc) { - $cardToc.querySelectorAll('.active').forEach(i => { i.classList.remove('active') }) - - if (currentId === '') { - return - } - - const currentActive = $tocLink[currentIndex] - currentActive.classList.add('active') + $cardToc.querySelectorAll('.active').forEach(i => i.classList.remove('active')) - setTimeout(() => { - autoScrollToc(currentActive) - }, 0) + if (currentId) { + const currentActive = $tocLink[currentIndex] + currentActive.classList.add('active') - if (isExpand) return - let parent = currentActive.parentNode + setTimeout(() => autoScrollToc(currentActive), 0) - for (; !parent.matches('.toc'); parent = parent.parentNode) { - if (parent.matches('li')) parent.classList.add('active') + if (!isExpand) { + let parent = currentActive.parentNode + while (!parent.matches('.toc')) { + if (parent.matches('li')) parent.classList.add('active') + parent = parent.parentNode + } + } } } } @@ -630,7 +633,7 @@ document.addEventListener('DOMContentLoaded', function () { btf.saveToLocal.set('aside-status', saveStatus, 2) $htmlDom.toggle('hide-aside') }, - 'mobile-toc-button': function (p, item) { // Show mobile toc + 'mobile-toc-button': (p, item) => { // Show mobile toc const tocEle = document.getElementById('card-toc') tocEle.style.transition = 'transform 0.3s ease-in-out' @@ -655,10 +658,10 @@ document.addEventListener('DOMContentLoaded', function () { } } - document.getElementById('rightside').addEventListener('click', function (e) { + document.getElementById('rightside').addEventListener('click', e => { const $target = e.target.closest('[id]') if ($target && rightSideFn[$target.id]) { - rightSideFn[$target.id](this, $target) + rightSideFn[$target.id](e.currentTarget, $target) } }) @@ -673,15 +676,17 @@ document.addEventListener('DOMContentLoaded', function () { target.classList.toggle('hide') } - document.querySelector('#sidebar-menus .menus_items').addEventListener('click', handleClickOfSubMenu) + const menusItems = document.querySelector('#sidebar-menus .menus_items') + menusItems && menusItems.addEventListener('click', handleClickOfSubMenu) } /** * 手机端目录点击 */ const openMobileMenu = () => { - const handleClick = () => { sidebarFn.open() } - btf.addEventListenerPjax(document.getElementById('toggle-menu'), 'click', handleClick) + const toggleMenu = document.getElementById('toggle-menu') + if (!toggleMenu) return + btf.addEventListenerPjax(toggleMenu, 'click', () => { sidebarFn.open() }) } /** @@ -749,62 +754,45 @@ document.addEventListener('DOMContentLoaded', function () { const clickFnOfTagHide = () => { const hideButtons = document.querySelectorAll('#article-container .hide-button') if (!hideButtons.length) return - const handleClick = function (e) { - const $this = this - $this.classList.add('open') - const $fjGallery = $this.nextElementSibling.querySelectorAll('.gallery-container') - $fjGallery.length && addJustifiedGallery($fjGallery) - } - - hideButtons.forEach(item => { - item.addEventListener('click', handleClick, { once: true }) - }) + hideButtons.forEach(item => item.addEventListener('click', e => { + const currentTarget = e.currentTarget + currentTarget.classList.add('open') + addJustifiedGallery(currentTarget.nextElementSibling.querySelectorAll('.gallery-container')) + }, { once: true })) } const tabsFn = () => { - const navTabsElement = document.querySelectorAll('#article-container .tabs') - if (!navTabsElement.length) return - - const removeAndAddActiveClass = (elements, detect) => { - Array.from(elements).forEach(element => { - element.classList.remove('active') - if (element === detect || element.id === detect) { - element.classList.add('active') - } + const navTabsElements = document.querySelectorAll('#article-container .tabs') + if (!navTabsElements.length) return + + const setActiveClass = (elements, activeIndex) => { + elements.forEach((el, index) => { + el.classList.toggle('active', index === activeIndex) }) } - const addTabNavEventListener = (item, isJustifiedGallery) => { - const navClickHandler = function (e) { - const target = e.target.closest('button') - if (target.classList.contains('active')) return - removeAndAddActiveClass(this.children, target) - this.classList.remove('no-default') - const tabId = target.getAttribute('data-href') - const tabContent = this.nextElementSibling - removeAndAddActiveClass(tabContent.children, tabId) - if (isJustifiedGallery) { - btf.removeGlobalFnEvent('igOfTabs', this) - const justifiedGalleryItems = tabContent.querySelectorAll(`:scope > #${tabId} .gallery-container`) - justifiedGalleryItems.length && addJustifiedGallery(justifiedGalleryItems, this) - } - } - btf.addEventListenerPjax(item.firstElementChild, 'click', navClickHandler) + const handleNavClick = e => { + const target = e.target.closest('button') + if (!target || target.classList.contains('active')) return + + const navItems = [...e.currentTarget.children] + const tabContents = [...e.currentTarget.nextElementSibling.children] + const indexOfButton = navItems.indexOf(target) + setActiveClass(navItems, indexOfButton) + e.currentTarget.classList.remove('no-default') + setActiveClass(tabContents, indexOfButton) + addJustifiedGallery(tabContents[indexOfButton].querySelectorAll('.gallery-container'), true) } - const addTabToTopEventListener = item => { - const btnClickHandler = (e) => { - const target = e.target.closest('button') - if (!target) return - btf.scrollToDest(btf.getEleTop(item), 300) + const handleToTopClick = tabElement => e => { + if (e.target.closest('button')) { + btf.scrollToDest(btf.getEleTop(tabElement), 300) } - btf.addEventListenerPjax(item.lastElementChild, 'click', btnClickHandler) } - navTabsElement.forEach(item => { - const isJustifiedGallery = !!item.querySelectorAll('.gallery-container') - addTabNavEventListener(item, isJustifiedGallery) - addTabToTopEventListener(item) + navTabsElements.forEach(tabElement => { + btf.addEventListenerPjax(tabElement.firstElementChild, 'click', handleNavClick) + btf.addEventListenerPjax(tabElement.lastElementChild, 'click', handleToTopClick(tabElement)) }) } @@ -812,7 +800,7 @@ document.addEventListener('DOMContentLoaded', function () { const cardCategory = document.querySelector('#aside-cat-list.expandBtn') if (!cardCategory) return - const handleToggleBtn = (e) => { + const handleToggleBtn = e => { const target = e.target if (target.nodeName === 'I') { e.preventDefault() @@ -825,10 +813,10 @@ document.addEventListener('DOMContentLoaded', function () { const switchComments = () => { const switchBtn = document.getElementById('switch-btn') if (!switchBtn) return + let switchDone = false - const commentContainer = document.getElementById('post-comment') const handleSwitchBtn = () => { - commentContainer.classList.toggle('move') + document.getElementById('post-comment').classList.toggle('move') if (!switchDone && typeof loadOtherComment === 'function') { switchDone = true loadOtherComment() @@ -865,28 +853,45 @@ document.addEventListener('DOMContentLoaded', function () { }, 'lazyload') } - const relativeDate = function (selector) { + const relativeDate = selector => { selector.forEach(item => { - const timeVal = item.getAttribute('datetime') - item.textContent = btf.diffDate(timeVal, true) + item.textContent = btf.diffDate(item.getAttribute('datetime'), true) item.style.display = 'inline' }) } - const unRefreshFn = function () { + const justifiedIndexPostUI = () => { + const recentPostsElement = document.getElementById('recent-posts') + if (!(recentPostsElement && recentPostsElement.classList.contains('masonry'))) return + + const init = () => { + const masonryItem = new InfiniteGrid.MasonryInfiniteGrid('.recent-post-items', { + gap: { horizontal: 10, vertical: 20 }, + useTransform: true, + useResizeObserver: true + }) + masonryItem.renderItems() + btf.addGlobalFn('pjaxCompleteOnce', () => { masonryItem.destroy() }, 'removeJustifiedIndexPostUI') + } + + typeof InfiniteGrid === 'function' ? init() : btf.getScript(`${GLOBAL_CONFIG.infinitegrid.js}`).then(init) + } + + const unRefreshFn = () => { window.addEventListener('resize', () => { adjustMenu(false) mobileSidebarOpen && btf.isHidden(document.getElementById('toggle-menu')) && sidebarFn.close() }) - document.getElementById('menu-mask').addEventListener('click', e => { sidebarFn.close() }) + const menuMask = document.getElementById('menu-mask') + menuMask && menuMask.addEventListener('click', () => { sidebarFn.close() }) clickFnOfSubMenu() GLOBAL_CONFIG.islazyload && lazyloadImg() GLOBAL_CONFIG.copyright !== undefined && addCopyright() if (GLOBAL_CONFIG.autoDarkmode) { - window.matchMedia('(prefers-color-scheme: dark)').addListener(e => { + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', e => { if (btf.saveToLocal.get('theme') !== undefined) return e.matches ? handleThemeChange('dark') : handleThemeChange('light') }) @@ -896,11 +901,7 @@ document.addEventListener('DOMContentLoaded', function () { const forPostFn = () => { addHighlightTool() addPhotoFigcaption() - - btf.removeGlobalFnEvent('justifiedGallery') - const galleryContainer = document.querySelectorAll('#article-container .gallery-container') - galleryContainer.length && addJustifiedGallery(galleryContainer) - + addJustifiedGallery(document.querySelectorAll('#article-container .gallery-container')) runLightbox() scrollFnToDo() addTableWrap() @@ -910,6 +911,7 @@ document.addEventListener('DOMContentLoaded', function () { const refreshFn = () => { initAdjust() + justifiedIndexPostUI() if (GLOBAL_CONFIG_SITE.isPost) { GLOBAL_CONFIG.noticeOutdate !== undefined && addPostOutdateNotice() diff --git a/source/js/search/algolia.js b/source/js/search/algolia.js index 9ce7b0e..814a00c 100644 --- a/source/js/search/algolia.js +++ b/source/js/search/algolia.js @@ -1,43 +1,51 @@ window.addEventListener('load', () => { + const { algolia } = GLOBAL_CONFIG + const { appId, apiKey, indexName, hitsPerPage = 5, languages } = algolia + + if (!appId || !apiKey || !indexName) { + return console.error('Algolia setting is invalid!') + } + const $searchMask = document.getElementById('search-mask') const $searchDialog = document.querySelector('#algolia-search .search-dialog') + const animateElements = show => { + const action = show ? 'animateIn' : 'animateOut' + const maskAnimation = show ? 'to_show 0.5s' : 'to_hide 0.5s' + const dialogAnimation = show ? 'titleScale 0.5s' : 'search_close .5s' + btf[action]($searchMask, maskAnimation) + btf[action]($searchDialog, dialogAnimation) + } + + const fixSafariHeight = () => { + if (window.innerWidth < 768) { + $searchDialog.style.setProperty('--search-height', `${window.innerHeight}px`) + } + } + const openSearch = () => { - const bodyStyle = document.body.style - bodyStyle.width = '100%' - bodyStyle.overflow = 'hidden' - btf.animateIn($searchMask, 'to_show 0.5s') - btf.animateIn($searchDialog, 'titleScale 0.5s') + btf.overflowPaddingR.add() + animateElements(true) setTimeout(() => { document.querySelector('#algolia-search .ais-SearchBox-input').focus() }, 100) - // shortcut: ESC - document.addEventListener('keydown', function f (event) { + const handleEscape = event => { if (event.code === 'Escape') { closeSearch() - document.removeEventListener('keydown', f) + document.removeEventListener('keydown', handleEscape) } - }) + } + document.addEventListener('keydown', handleEscape) fixSafariHeight() window.addEventListener('resize', fixSafariHeight) } const closeSearch = () => { - const bodyStyle = document.body.style - bodyStyle.width = '' - bodyStyle.overflow = '' - btf.animateOut($searchDialog, 'search_close .5s') - btf.animateOut($searchMask, 'to_hide 0.5s') + btf.overflowPaddingR.remove() + animateElements(false) window.removeEventListener('resize', fixSafariHeight) } - // fix safari - const fixSafariHeight = () => { - if (window.innerWidth < 768) { - $searchDialog.style.setProperty('--search-height', window.innerHeight + 'px') - } - } - const searchClickFn = () => { btf.addEventListenerPjax(document.querySelector('#search-button > .search'), 'click', openSearch) } @@ -47,11 +55,9 @@ window.addEventListener('load', () => { document.querySelector('#algolia-search .search-close-button').addEventListener('click', closeSearch) } - const cutContent = content => { - if (content === '') return '' - + const cutContent = (content) => { + if (!content) return '' const firstOccur = content.indexOf('') - let start = firstOccur - 30 let end = firstOccur + 120 let pre = '' @@ -70,108 +76,98 @@ window.addEventListener('load', () => { post = '...' } - const matchContent = pre + content.substring(start, end) + post - return matchContent + return `${pre}${content.substring(start, end)}${post}` } - const algolia = GLOBAL_CONFIG.algolia - const isAlgoliaValid = algolia.appId && algolia.apiKey && algolia.indexName - if (!isAlgoliaValid) { - return console.error('Algolia setting is invalid!') - } + const disableDiv = [ + document.getElementById('algolia-hits'), + document.getElementById('algolia-pagination'), + document.querySelector('#algolia-info .algolia-stats') + ] const search = instantsearch({ - indexName: algolia.indexName, - /* global algoliasearch */ - searchClient: algoliasearch(algolia.appId, algolia.apiKey), + indexName, + searchClient: algoliasearch(appId, apiKey), searchFunction (helper) { - helper.state.query && helper.search() + disableDiv.forEach(item => { + item.style.display = helper.state.query ? '' : 'none' + }) + if (helper.state.query) helper.search() } }) - const configure = instantsearch.widgets.configure({ - hitsPerPage: 5 - }) - - const searchBox = instantsearch.widgets.searchBox({ - container: '#algolia-search-input', - showReset: false, - showSubmit: false, - placeholder: GLOBAL_CONFIG.algolia.languages.input_placeholder, - showLoadingIndicator: true - }) - - const hits = instantsearch.widgets.hits({ - container: '#algolia-hits', - templates: { - item (data) { - const link = data.permalink ? data.permalink : (GLOBAL_CONFIG.root + data.path) - const result = data._highlightResult - const content = result.contentStripTruncate - ? cutContent(result.contentStripTruncate.value) - : result.contentStrip - ? cutContent(result.contentStrip.value) - : result.content - ? cutContent(result.content.value) - : '' - return ` - - ${result.title.value || 'no-title'} -

    ${content}

    -
    ` - }, - empty: function (data) { - return ( - '
    ' + - GLOBAL_CONFIG.algolia.languages.hits_empty.replace(/\$\{query}/, data.query) + - '
    ' - ) + const widgets = [ + instantsearch.widgets.configure({ hitsPerPage }), + instantsearch.widgets.searchBox({ + container: '#algolia-search-input', + showReset: false, + showSubmit: false, + placeholder: languages.input_placeholder, + showLoadingIndicator: true + }), + instantsearch.widgets.hits({ + container: '#algolia-hits', + templates: { + item (data) { + const link = data.permalink || (GLOBAL_CONFIG.root + data.path) + const result = data._highlightResult + const content = result.contentStripTruncate + ? cutContent(result.contentStripTruncate.value) + : result.contentStrip + ? cutContent(result.contentStrip.value) + : result.content + ? cutContent(result.content.value) + : '' + return ` + + ${result.title.value || 'no-title'} + ${content ? `
    ${content}
    ` : ''} +
    ` + }, + empty (data) { + return `
    ${languages.hits_empty.replace(/\$\{query}/, data.query)}
    ` + } } - } - }) - - const stats = instantsearch.widgets.stats({ - container: '#algolia-info > .algolia-stats', - templates: { - text: function (data) { - const stats = GLOBAL_CONFIG.algolia.languages.hits_stats - .replace(/\$\{hits}/, data.nbHits) - .replace(/\$\{time}/, data.processingTimeMS) - return ( - `
    ${stats}` - ) + }), + instantsearch.widgets.stats({ + container: '#algolia-info > .algolia-stats', + templates: { + text (data) { + const stats = languages.hits_stats + .replace(/\$\{hits}/, data.nbHits) + .replace(/\$\{time}/, data.processingTimeMS) + return `
    ${stats}` + } } - } - }) - - const powerBy = instantsearch.widgets.poweredBy({ - container: '#algolia-info > .algolia-poweredBy' - }) - - const pagination = instantsearch.widgets.pagination({ - container: '#algolia-pagination', - totalPages: 5, - templates: { - first: '', - last: '', - previous: '', - next: '' - } - }) - - search.addWidgets([configure, searchBox, hits, stats, powerBy, pagination]) // add the widgets to the instantsearch instance + }), + instantsearch.widgets.poweredBy({ + container: '#algolia-info > .algolia-poweredBy' + }), + instantsearch.widgets.pagination({ + container: '#algolia-pagination', + totalPages: 5, + templates: { + first: '', + last: '', + previous: '', + next: '' + } + }) + ] + search.addWidgets(widgets) search.start() - searchClickFn() searchFnOnce() window.addEventListener('pjax:complete', () => { - !btf.isHidden($searchMask) && closeSearch() + if (!btf.isHidden($searchMask)) closeSearch() searchClickFn() }) - window.pjax && search.on('render', () => { - window.pjax.refresh(document.getElementById('algolia-hits')) - }) + if (window.pjax) { + search.on('render', () => { + window.pjax.refresh(document.getElementById('algolia-hits')) + }) + } }) diff --git a/source/js/search/local-search.js b/source/js/search/local-search.js index 0eecff6..0b21774 100644 --- a/source/js/search/local-search.js +++ b/source/js/search/local-search.js @@ -301,9 +301,7 @@ window.addEventListener('load', () => { } const openSearch = () => { - const bodyStyle = document.body.style - bodyStyle.width = '100%' - bodyStyle.overflow = 'hidden' + btf.overflowPaddingR.add() btf.animateIn($searchMask, 'to_show 0.5s') btf.animateIn($searchDialog, 'titleScale 0.5s') setTimeout(() => { input.focus() }, 300) @@ -325,9 +323,7 @@ window.addEventListener('load', () => { } const closeSearch = () => { - const bodyStyle = document.body.style - bodyStyle.width = '' - bodyStyle.overflow = '' + btf.overflowPaddingR.remove() btf.animateOut($searchDialog, 'search_close .5s') btf.animateOut($searchMask, 'to_hide 0.5s') window.removeEventListener('resize', fixSafariHeight) diff --git a/source/js/tw_cn.js b/source/js/tw_cn.js index fc3d4fa..9ac846d 100644 --- a/source/js/tw_cn.js +++ b/source/js/tw_cn.js @@ -1,57 +1,42 @@ -document.addEventListener('DOMContentLoaded', function () { +document.addEventListener('DOMContentLoaded', () => { const { defaultEncoding, translateDelay, msgToTraditionalChinese, msgToSimplifiedChinese } = GLOBAL_CONFIG.translate const snackbarData = GLOBAL_CONFIG.Snackbar - let currentEncoding = defaultEncoding const targetEncodingCookie = 'translate-chn-cht' - let targetEncoding = - btf.saveToLocal.get(targetEncodingCookie) === undefined - ? defaultEncoding - : Number(btf.saveToLocal.get('translate-chn-cht')) - let translateButtonObject + + let currentEncoding = defaultEncoding + let targetEncoding = Number(btf.saveToLocal.get(targetEncodingCookie)) || defaultEncoding + const translateButtonObject = document.getElementById('translateLink') const isSnackbar = snackbarData !== undefined - function setLang () { + const setLang = () => { document.documentElement.lang = targetEncoding === 1 ? 'zh-TW' : 'zh-CN' } - function translateText (txt) { - if (txt === '' || txt == null) return '' + const translateText = (txt) => { + if (!txt) return '' if (currentEncoding === 1 && targetEncoding === 2) return Simplized(txt) - else if (currentEncoding === 2 && targetEncoding === 1) { - return Traditionalized(txt) - } else return txt + if (currentEncoding === 2 && targetEncoding === 1) return Traditionalized(txt) + return txt } - function translateBody (fobj) { - let objs - if (typeof fobj === 'object') objs = fobj.childNodes - else objs = document.body.childNodes + const translateBody = (fobj) => { + const objs = typeof fobj === 'object' ? fobj.childNodes : document.body.childNodes for (let i = 0; i < objs.length; i++) { const obj = objs.item(i) - if ( - '||BR|HR|'.indexOf('|' + obj.tagName + '|') > 0 || - obj === translateButtonObject - ) { - continue - } - if (obj.title !== '' && obj.title != null) { - obj.title = translateText(obj.title) - } - if (obj.alt !== '' && obj.alt != null) obj.alt = translateText(obj.alt) - if (obj.placeholder !== '' && obj.placeholder != null) { obj.placeholder = translateText(obj.placeholder) } - if ( - obj.tagName === 'INPUT' && - obj.value !== '' && - obj.type !== 'text' && - obj.type !== 'hidden' - ) { + if ('BR|HR'.includes(obj.tagName) || obj === translateButtonObject) continue + + if (obj.title) obj.title = translateText(obj.title) + if (obj.alt) obj.alt = translateText(obj.alt) + if (obj.placeholder) obj.placeholder = translateText(obj.placeholder) + if (obj.tagName === 'INPUT' && obj.value && obj.type !== 'text' && obj.type !== 'hidden') { obj.value = translateText(obj.value) } if (obj.nodeType === 3) obj.data = translateText(obj.data) else translateBody(obj) } } - function translatePage () { + + const translatePage = () => { if (targetEncoding === 1) { currentEncoding = 1 targetEncoding = 2 @@ -68,13 +53,10 @@ document.addEventListener('DOMContentLoaded', function () { translateBody() } - function JTPYStr () { - return '万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗姜娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岳岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪漤潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊犟状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郄郏郐郑郓郦郧郸酝酦酱酽酾酿释里鉅鉴銮錾钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铍铎铏铐铑铒铕铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗错锚锜锞锟锠锡锢锣锤锥锦锨锩锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镆镇镈镉镊镌镍镎镏镐镑镒镕镖镗镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镶长门闩闪闫闬闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陧陨险随隐隶隽难雏雠雳雾霁霉霭靓静靥鞑鞒鞯鞴韦韧韨韩韪韫韬韵页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓魇魉鱼鱽鱾鱿鲀鲁鲂鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹯鹰鹱鹲鹳鹴鹾麦麸黄黉黡黩黪黾龙历志制一台皋准复猛钟注范签' - } - function FTPYStr () { - return '萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳曆厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備複夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍薑婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺嶽崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦濫瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郤郟鄶鄭鄆酈鄖鄲醞醱醬釅釃釀釋裏钜鑒鑾鏨釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鈍鈔鍾鈉鋇鋼鈑鈐鑰欽鈞鎢鉤鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鈰鉉鉈鉍鈹鐸鉶銬銠鉺銪鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺錯錨錡錁錕錩錫錮鑼錘錐錦鍁錈錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鏌鎮鎛鎘鑷鐫鎳鎿鎦鎬鎊鎰鎔鏢鏜鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔鑣鑞鑲長門閂閃閆閈閉問闖閏闈閑閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隉隕險隨隱隸雋難雛讎靂霧霽黴靄靚靜靨韃鞽韉韝韋韌韍韓韙韞韜韻頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飆飛饗饜飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢魘魎魚魛魢魷魨魯魴魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鯵鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鱉鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鴬鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鶤鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺鸇鷹鸌鸏鸛鸘鹺麥麩黃黌黶黷黲黽龍歷誌製壹臺臯準復勐鐘註範籤' - } - function Traditionalized (cc) { + const JTPYStr = () => '万与丑专业丛东丝丢两严丧个丬丰临为丽举么义乌乐乔习乡书买乱争于亏云亘亚产亩亲亵亸亿仅从仑仓仪们价众优伙会伛伞伟传伤伥伦伧伪伫体余佣佥侠侣侥侦侧侨侩侪侬俣俦俨俩俪俭债倾偬偻偾偿傥傧储傩儿兑兖党兰关兴兹养兽冁内冈册写军农冢冯冲决况冻净凄凉凌减凑凛几凤凫凭凯击凼凿刍划刘则刚创删别刬刭刽刿剀剂剐剑剥剧劝办务劢动励劲劳势勋勐勚匀匦匮区医华协单卖卢卤卧卫却卺厂厅历厉压厌厍厕厢厣厦厨厩厮县参叆叇双发变叙叠叶号叹叽吁后吓吕吗吣吨听启吴呒呓呕呖呗员呙呛呜咏咔咙咛咝咤咴咸哌响哑哒哓哔哕哗哙哜哝哟唛唝唠唡唢唣唤唿啧啬啭啮啰啴啸喷喽喾嗫呵嗳嘘嘤嘱噜噼嚣嚯团园囱围囵国图圆圣圹场坂坏块坚坛坜坝坞坟坠垄垅垆垒垦垧垩垫垭垯垱垲垴埘埙埚埝埯堑堕塆墙壮声壳壶壸处备复够头夸夹夺奁奂奋奖奥妆妇妈妩妪妫姗姜娄娅娆娇娈娱娲娴婳婴婵婶媪嫒嫔嫱嬷孙学孪宁宝实宠审宪宫宽宾寝对寻导寿将尔尘尧尴尸尽层屃屉届属屡屦屿岁岂岖岗岘岙岚岛岭岳岽岿峃峄峡峣峤峥峦崂崃崄崭嵘嵚嵛嵝嵴巅巩巯币帅师帏帐帘帜带帧帮帱帻帼幂幞干并广庄庆庐庑库应庙庞废庼廪开异弃张弥弪弯弹强归当录彟彦彻径徕御忆忏忧忾怀态怂怃怄怅怆怜总怼怿恋恳恶恸恹恺恻恼恽悦悫悬悭悯惊惧惨惩惫惬惭惮惯愍愠愤愦愿慑慭憷懑懒懔戆戋戏戗战戬户扎扑扦执扩扪扫扬扰抚抛抟抠抡抢护报担拟拢拣拥拦拧拨择挂挚挛挜挝挞挟挠挡挢挣挤挥挦捞损捡换捣据捻掳掴掷掸掺掼揸揽揿搀搁搂搅携摄摅摆摇摈摊撄撑撵撷撸撺擞攒敌敛数斋斓斗斩断无旧时旷旸昙昼昽显晋晒晓晔晕晖暂暧札术朴机杀杂权条来杨杩杰极构枞枢枣枥枧枨枪枫枭柜柠柽栀栅标栈栉栊栋栌栎栏树栖样栾桊桠桡桢档桤桥桦桧桨桩梦梼梾检棂椁椟椠椤椭楼榄榇榈榉槚槛槟槠横樯樱橥橱橹橼檐檩欢欤欧歼殁殇残殒殓殚殡殴毁毂毕毙毡毵氇气氢氩氲汇汉污汤汹沓沟没沣沤沥沦沧沨沩沪沵泞泪泶泷泸泺泻泼泽泾洁洒洼浃浅浆浇浈浉浊测浍济浏浐浑浒浓浔浕涂涌涛涝涞涟涠涡涢涣涤润涧涨涩淀渊渌渍渎渐渑渔渖渗温游湾湿溃溅溆溇滗滚滞滟滠满滢滤滥滦滨滩滪漤潆潇潋潍潜潴澜濑濒灏灭灯灵灾灿炀炉炖炜炝点炼炽烁烂烃烛烟烦烧烨烩烫烬热焕焖焘煅煳熘爱爷牍牦牵牺犊犟状犷犸犹狈狍狝狞独狭狮狯狰狱狲猃猎猕猡猪猫猬献獭玑玙玚玛玮环现玱玺珉珏珐珑珰珲琎琏琐琼瑶瑷璇璎瓒瓮瓯电画畅畲畴疖疗疟疠疡疬疮疯疱疴痈痉痒痖痨痪痫痴瘅瘆瘗瘘瘪瘫瘾瘿癞癣癫癯皑皱皲盏盐监盖盗盘眍眦眬着睁睐睑瞒瞩矫矶矾矿砀码砖砗砚砜砺砻砾础硁硅硕硖硗硙硚确硷碍碛碜碱碹磙礼祎祢祯祷祸禀禄禅离秃秆种积称秽秾稆税稣稳穑穷窃窍窑窜窝窥窦窭竖竞笃笋笔笕笺笼笾筑筚筛筜筝筹签简箓箦箧箨箩箪箫篑篓篮篱簖籁籴类籼粜粝粤粪粮糁糇紧絷纟纠纡红纣纤纥约级纨纩纪纫纬纭纮纯纰纱纲纳纴纵纶纷纸纹纺纻纼纽纾线绀绁绂练组绅细织终绉绊绋绌绍绎经绐绑绒结绔绕绖绗绘给绚绛络绝绞统绠绡绢绣绤绥绦继绨绩绪绫绬续绮绯绰绱绲绳维绵绶绷绸绹绺绻综绽绾绿缀缁缂缃缄缅缆缇缈缉缊缋缌缍缎缏缐缑缒缓缔缕编缗缘缙缚缛缜缝缞缟缠缡缢缣缤缥缦缧缨缩缪缫缬缭缮缯缰缱缲缳缴缵罂网罗罚罢罴羁羟羡翘翙翚耢耧耸耻聂聋职聍联聩聪肃肠肤肷肾肿胀胁胆胜胧胨胪胫胶脉脍脏脐脑脓脔脚脱脶脸腊腌腘腭腻腼腽腾膑臜舆舣舰舱舻艰艳艹艺节芈芗芜芦苁苇苈苋苌苍苎苏苘苹茎茏茑茔茕茧荆荐荙荚荛荜荞荟荠荡荣荤荥荦荧荨荩荪荫荬荭荮药莅莜莱莲莳莴莶获莸莹莺莼萚萝萤营萦萧萨葱蒇蒉蒋蒌蓝蓟蓠蓣蓥蓦蔷蔹蔺蔼蕲蕴薮藁藓虏虑虚虫虬虮虽虾虿蚀蚁蚂蚕蚝蚬蛊蛎蛏蛮蛰蛱蛲蛳蛴蜕蜗蜡蝇蝈蝉蝎蝼蝾螀螨蟏衅衔补衬衮袄袅袆袜袭袯装裆裈裢裣裤裥褛褴襁襕见观觃规觅视觇览觉觊觋觌觍觎觏觐觑觞触觯詟誉誊讠计订讣认讥讦讧讨让讪讫训议讯记讱讲讳讴讵讶讷许讹论讻讼讽设访诀证诂诃评诅识诇诈诉诊诋诌词诎诏诐译诒诓诔试诖诗诘诙诚诛诜话诞诟诠诡询诣诤该详诧诨诩诪诫诬语诮误诰诱诲诳说诵诶请诸诹诺读诼诽课诿谀谁谂调谄谅谆谇谈谊谋谌谍谎谏谐谑谒谓谔谕谖谗谘谙谚谛谜谝谞谟谠谡谢谣谤谥谦谧谨谩谪谫谬谭谮谯谰谱谲谳谴谵谶谷豮贝贞负贠贡财责贤败账货质贩贪贫贬购贮贯贰贱贲贳贴贵贶贷贸费贺贻贼贽贾贿赀赁赂赃资赅赆赇赈赉赊赋赌赍赎赏赐赑赒赓赔赕赖赗赘赙赚赛赜赝赞赟赠赡赢赣赪赵赶趋趱趸跃跄跖跞践跶跷跸跹跻踊踌踪踬踯蹑蹒蹰蹿躏躜躯车轧轨轩轪轫转轭轮软轰轱轲轳轴轵轶轷轸轹轺轻轼载轾轿辀辁辂较辄辅辆辇辈辉辊辋辌辍辎辏辐辑辒输辔辕辖辗辘辙辚辞辩辫边辽达迁过迈运还这进远违连迟迩迳迹适选逊递逦逻遗遥邓邝邬邮邹邺邻郁郄郏郐郑郓郦郧郸酝酦酱酽酾酿释里鉅鉴銮錾钆钇针钉钊钋钌钍钎钏钐钑钒钓钔钕钖钗钘钙钚钛钝钞钟钠钡钢钣钤钥钦钧钨钩钪钫钬钭钮钯钰钱钲钳钴钵钶钷钸钹钺钻钼钽钾钿铀铁铂铃铄铅铆铈铉铊铋铍铎铏铐铑铒铕铗铘铙铚铛铜铝铞铟铠铡铢铣铤铥铦铧铨铪铫铬铭铮铯铰铱铲铳铴铵银铷铸铹铺铻铼铽链铿销锁锂锃锄锅锆锇锈锉锊锋锌锍锎锏锐锑锒锓锔锕锖锗错锚锜锞锟锠锡锢锣锤锥锦锨锩锫锬锭键锯锰锱锲锳锴锵锶锷锸锹锺锻锼锽锾锿镀镁镂镃镆镇镈镉镊镌镍镎镏镐镑镒镕镖镗镙镚镛镜镝镞镟镠镡镢镣镤镥镦镧镨镩镪镫镬镭镮镯镰镱镲镳镴镶长门闩闪闫闬闭问闯闰闱闲闳间闵闶闷闸闹闺闻闼闽闾闿阀阁阂阃阄阅阆阇阈阉阊阋阌阍阎阏阐阑阒阓阔阕阖阗阘阙阚阛队阳阴阵阶际陆陇陈陉陕陧陨险随隐隶隽难雏雠雳雾霁霉霭靓静靥鞑鞒鞯鞴韦韧韨韩韪韫韬韵页顶顷顸项顺须顼顽顾顿颀颁颂颃预颅领颇颈颉颊颋颌颍颎颏颐频颒颓颔颕颖颗题颙颚颛颜额颞颟颠颡颢颣颤颥颦颧风飏飐飑飒飓飔飕飖飗飘飙飚飞飨餍饤饥饦饧饨饩饪饫饬饭饮饯饰饱饲饳饴饵饶饷饸饹饺饻饼饽饾饿馀馁馂馃馄馅馆馇馈馉馊馋馌馍馎馏馐馑馒馓馔馕马驭驮驯驰驱驲驳驴驵驶驷驸驹驺驻驼驽驾驿骀骁骂骃骄骅骆骇骈骉骊骋验骍骎骏骐骑骒骓骔骕骖骗骘骙骚骛骜骝骞骟骠骡骢骣骤骥骦骧髅髋髌鬓魇魉鱼鱽鱾鱿鲀鲁鲂鲄鲅鲆鲇鲈鲉鲊鲋鲌鲍鲎鲏鲐鲑鲒鲓鲔鲕鲖鲗鲘鲙鲚鲛鲜鲝鲞鲟鲠鲡鲢鲣鲤鲥鲦鲧鲨鲩鲪鲫鲬鲭鲮鲯鲰鲱鲲鲳鲴鲵鲶鲷鲸鲹鲺鲻鲼鲽鲾鲿鳀鳁鳂鳃鳄鳅鳆鳇鳈鳉鳊鳋鳌鳍鳎鳏鳐鳑鳒鳓鳔鳕鳖鳗鳘鳙鳛鳜鳝鳞鳟鳠鳡鳢鳣鸟鸠鸡鸢鸣鸤鸥鸦鸧鸨鸩鸪鸫鸬鸭鸮鸯鸰鸱鸲鸳鸴鸵鸶鸷鸸鸹鸺鸻鸼鸽鸾鸿鹀鹁鹂鹃鹄鹅鹆鹇鹈鹉鹊鹋鹌鹍鹎鹏鹐鹑鹒鹓鹔鹕鹖鹗鹘鹚鹛鹜鹝鹞鹟鹠鹡鹢鹣鹤鹥鹦鹧鹨鹩鹪鹫鹬鹭鹯鹰鹱鹲鹳鹴鹾麦麸黄黉黡黩黪黾龙历志制一台皋准复猛钟注范签' + const FTPYStr = () => '萬與醜專業叢東絲丟兩嚴喪個爿豐臨為麗舉麼義烏樂喬習鄉書買亂爭於虧雲亙亞產畝親褻嚲億僅從侖倉儀們價眾優夥會傴傘偉傳傷倀倫傖偽佇體餘傭僉俠侶僥偵側僑儈儕儂俁儔儼倆儷儉債傾傯僂僨償儻儐儲儺兒兌兗黨蘭關興茲養獸囅內岡冊寫軍農塚馮衝決況凍淨淒涼淩減湊凜幾鳳鳧憑凱擊氹鑿芻劃劉則剛創刪別剗剄劊劌剴劑剮劍剝劇勸辦務勱動勵勁勞勢勳猛勩勻匭匱區醫華協單賣盧鹵臥衛卻巹廠廳曆厲壓厭厙廁廂厴廈廚廄廝縣參靉靆雙發變敘疊葉號歎嘰籲後嚇呂嗎唚噸聽啟吳嘸囈嘔嚦唄員咼嗆嗚詠哢嚨嚀噝吒噅鹹呱響啞噠嘵嗶噦嘩噲嚌噥喲嘜嗊嘮啢嗩唕喚呼嘖嗇囀齧囉嘽嘯噴嘍嚳囁嗬噯噓嚶囑嚕劈囂謔團園囪圍圇國圖圓聖壙場阪壞塊堅壇壢壩塢墳墜壟壟壚壘墾坰堊墊埡墶壋塏堖塒塤堝墊垵塹墮壪牆壯聲殼壺壼處備複夠頭誇夾奪奩奐奮獎奧妝婦媽嫵嫗媯姍薑婁婭嬈嬌孌娛媧嫻嫿嬰嬋嬸媼嬡嬪嬙嬤孫學孿寧寶實寵審憲宮寬賓寢對尋導壽將爾塵堯尷屍盡層屭屜屆屬屢屨嶼歲豈嶇崗峴嶴嵐島嶺嶽崠巋嶨嶧峽嶢嶠崢巒嶗崍嶮嶄嶸嶔崳嶁脊巔鞏巰幣帥師幃帳簾幟帶幀幫幬幘幗冪襆幹並廣莊慶廬廡庫應廟龐廢廎廩開異棄張彌弳彎彈強歸當錄彠彥徹徑徠禦憶懺憂愾懷態慫憮慪悵愴憐總懟懌戀懇惡慟懨愷惻惱惲悅愨懸慳憫驚懼慘懲憊愜慚憚慣湣慍憤憒願懾憖怵懣懶懍戇戔戲戧戰戩戶紮撲扡執擴捫掃揚擾撫拋摶摳掄搶護報擔擬攏揀擁攔擰撥擇掛摯攣掗撾撻挾撓擋撟掙擠揮撏撈損撿換搗據撚擄摑擲撣摻摜摣攬撳攙擱摟攪攜攝攄擺搖擯攤攖撐攆擷擼攛擻攢敵斂數齋斕鬥斬斷無舊時曠暘曇晝曨顯晉曬曉曄暈暉暫曖劄術樸機殺雜權條來楊榪傑極構樅樞棗櫪梘棖槍楓梟櫃檸檉梔柵標棧櫛櫳棟櫨櫟欄樹棲樣欒棬椏橈楨檔榿橋樺檜槳樁夢檮棶檢欞槨櫝槧欏橢樓欖櫬櫚櫸檟檻檳櫧橫檣櫻櫫櫥櫓櫞簷檁歡歟歐殲歿殤殘殞殮殫殯毆毀轂畢斃氈毿氌氣氫氬氳彙漢汙湯洶遝溝沒灃漚瀝淪滄渢溈滬濔濘淚澩瀧瀘濼瀉潑澤涇潔灑窪浹淺漿澆湞溮濁測澮濟瀏滻渾滸濃潯濜塗湧濤澇淶漣潿渦溳渙滌潤澗漲澀澱淵淥漬瀆漸澠漁瀋滲溫遊灣濕潰濺漵漊潷滾滯灩灄滿瀅濾濫灤濱灘澦濫瀠瀟瀲濰潛瀦瀾瀨瀕灝滅燈靈災燦煬爐燉煒熗點煉熾爍爛烴燭煙煩燒燁燴燙燼熱煥燜燾煆糊溜愛爺牘犛牽犧犢強狀獷獁猶狽麅獮獰獨狹獅獪猙獄猻獫獵獼玀豬貓蝟獻獺璣璵瑒瑪瑋環現瑲璽瑉玨琺瓏璫琿璡璉瑣瓊瑤璦璿瓔瓚甕甌電畫暢佘疇癤療瘧癘瘍鬁瘡瘋皰屙癰痙癢瘂癆瘓癇癡癉瘮瘞瘺癟癱癮癭癩癬癲臒皚皺皸盞鹽監蓋盜盤瞘眥矓著睜睞瞼瞞矚矯磯礬礦碭碼磚硨硯碸礪礱礫礎硜矽碩硤磽磑礄確鹼礙磧磣堿镟滾禮禕禰禎禱禍稟祿禪離禿稈種積稱穢穠穭稅穌穩穡窮竊竅窯竄窩窺竇窶豎競篤筍筆筧箋籠籩築篳篩簹箏籌簽簡籙簀篋籜籮簞簫簣簍籃籬籪籟糴類秈糶糲粵糞糧糝餱緊縶糸糾紆紅紂纖紇約級紈纊紀紉緯紜紘純紕紗綱納紝縱綸紛紙紋紡紵紖紐紓線紺絏紱練組紳細織終縐絆紼絀紹繹經紿綁絨結絝繞絰絎繪給絢絳絡絕絞統綆綃絹繡綌綏絛繼綈績緒綾緓續綺緋綽緔緄繩維綿綬繃綢綯綹綣綜綻綰綠綴緇緙緗緘緬纜緹緲緝縕繢緦綞緞緶線緱縋緩締縷編緡緣縉縛縟縝縫縗縞纏縭縊縑繽縹縵縲纓縮繆繅纈繚繕繒韁繾繰繯繳纘罌網羅罰罷羆羈羥羨翹翽翬耮耬聳恥聶聾職聹聯聵聰肅腸膚膁腎腫脹脅膽勝朧腖臚脛膠脈膾髒臍腦膿臠腳脫腡臉臘醃膕齶膩靦膃騰臏臢輿艤艦艙艫艱豔艸藝節羋薌蕪蘆蓯葦藶莧萇蒼苧蘇檾蘋莖蘢蔦塋煢繭荊薦薘莢蕘蓽蕎薈薺蕩榮葷滎犖熒蕁藎蓀蔭蕒葒葤藥蒞蓧萊蓮蒔萵薟獲蕕瑩鶯蓴蘀蘿螢營縈蕭薩蔥蕆蕢蔣蔞藍薊蘺蕷鎣驀薔蘞藺藹蘄蘊藪槁蘚虜慮虛蟲虯蟣雖蝦蠆蝕蟻螞蠶蠔蜆蠱蠣蟶蠻蟄蛺蟯螄蠐蛻蝸蠟蠅蟈蟬蠍螻蠑螿蟎蠨釁銜補襯袞襖嫋褘襪襲襏裝襠褌褳襝褲襇褸襤繈襴見觀覎規覓視覘覽覺覬覡覿覥覦覯覲覷觴觸觶讋譽謄訁計訂訃認譏訐訌討讓訕訖訓議訊記訒講諱謳詎訝訥許訛論訩訟諷設訪訣證詁訶評詛識詗詐訴診詆謅詞詘詔詖譯詒誆誄試詿詩詰詼誠誅詵話誕詬詮詭詢詣諍該詳詫諢詡譸誡誣語誚誤誥誘誨誑說誦誒請諸諏諾讀諑誹課諉諛誰諗調諂諒諄誶談誼謀諶諜謊諫諧謔謁謂諤諭諼讒諮諳諺諦謎諞諝謨讜謖謝謠謗諡謙謐謹謾謫譾謬譚譖譙讕譜譎讞譴譫讖穀豶貝貞負貟貢財責賢敗賬貨質販貪貧貶購貯貫貳賤賁貰貼貴貺貸貿費賀貽賊贄賈賄貲賃賂贓資賅贐賕賑賚賒賦賭齎贖賞賜贔賙賡賠賧賴賵贅賻賺賽賾贗讚贇贈贍贏贛赬趙趕趨趲躉躍蹌蹠躒踐躂蹺蹕躚躋踴躊蹤躓躑躡蹣躕躥躪躦軀車軋軌軒軑軔轉軛輪軟轟軲軻轤軸軹軼軤軫轢軺輕軾載輊轎輈輇輅較輒輔輛輦輩輝輥輞輬輟輜輳輻輯轀輸轡轅轄輾轆轍轔辭辯辮邊遼達遷過邁運還這進遠違連遲邇逕跡適選遜遞邐邏遺遙鄧鄺鄔郵鄒鄴鄰鬱郤郟鄶鄭鄆酈鄖鄲醞醱醬釅釃釀釋裏钜鑒鑾鏨釓釔針釘釗釙釕釷釺釧釤鈒釩釣鍆釹鍚釵鈃鈣鈈鈦鈍鈔鍾鈉鋇鋼鈑鈐鑰欽鈞鎢鉤鈧鈁鈥鈄鈕鈀鈺錢鉦鉗鈷缽鈳鉕鈽鈸鉞鑽鉬鉭鉀鈿鈾鐵鉑鈴鑠鉛鉚鈰鉉鉈鉍鈹鐸鉶銬銠鉺銪鋏鋣鐃銍鐺銅鋁銱銦鎧鍘銖銑鋌銩銛鏵銓鉿銚鉻銘錚銫鉸銥鏟銃鐋銨銀銣鑄鐒鋪鋙錸鋱鏈鏗銷鎖鋰鋥鋤鍋鋯鋨鏽銼鋝鋒鋅鋶鐦鐧銳銻鋃鋟鋦錒錆鍺錯錨錡錁錕錩錫錮鑼錘錐錦鍁錈錇錟錠鍵鋸錳錙鍥鍈鍇鏘鍶鍔鍤鍬鍾鍛鎪鍠鍰鎄鍍鎂鏤鎡鏌鎮鎛鎘鑷鐫鎳鎿鎦鎬鎊鎰鎔鏢鏜鏍鏰鏞鏡鏑鏃鏇鏐鐔钁鐐鏷鑥鐓鑭鐠鑹鏹鐙鑊鐳鐶鐲鐮鐿鑔鑣鑞鑲長門閂閃閆閈閉問闖閏闈閑閎間閔閌悶閘鬧閨聞闥閩閭闓閥閣閡閫鬮閱閬闍閾閹閶鬩閿閽閻閼闡闌闃闠闊闋闔闐闒闕闞闤隊陽陰陣階際陸隴陳陘陝隉隕險隨隱隸雋難雛讎靂霧霽黴靄靚靜靨韃鞽韉韝韋韌韍韓韙韞韜韻頁頂頃頇項順須頊頑顧頓頎頒頌頏預顱領頗頸頡頰頲頜潁熲頦頤頻頮頹頷頴穎顆題顒顎顓顏額顳顢顛顙顥纇顫顬顰顴風颺颭颮颯颶颸颼颻飀飄飆飆飛饗饜飣饑飥餳飩餼飪飫飭飯飲餞飾飽飼飿飴餌饒餉餄餎餃餏餅餑餖餓餘餒餕餜餛餡館餷饋餶餿饞饁饃餺餾饈饉饅饊饌饢馬馭馱馴馳驅馹駁驢駔駛駟駙駒騶駐駝駑駕驛駘驍罵駰驕驊駱駭駢驫驪騁驗騂駸駿騏騎騍騅騌驌驂騙騭騤騷騖驁騮騫騸驃騾驄驏驟驥驦驤髏髖髕鬢魘魎魚魛魢魷魨魯魴魺鮁鮃鯰鱸鮋鮓鮒鮊鮑鱟鮍鮐鮭鮚鮳鮪鮞鮦鰂鮜鱠鱭鮫鮮鮺鯗鱘鯁鱺鰱鰹鯉鰣鰷鯀鯊鯇鮶鯽鯒鯖鯪鯕鯫鯡鯤鯧鯝鯢鯰鯛鯨鯵鯴鯔鱝鰈鰏鱨鯷鰮鰃鰓鱷鰍鰒鰉鰁鱂鯿鰠鼇鰭鰨鰥鰩鰟鰜鰳鰾鱈鱉鰻鰵鱅鰼鱖鱔鱗鱒鱯鱤鱧鱣鳥鳩雞鳶鳴鳲鷗鴉鶬鴇鴆鴣鶇鸕鴨鴞鴦鴒鴟鴝鴛鴬鴕鷥鷙鴯鴰鵂鴴鵃鴿鸞鴻鵐鵓鸝鵑鵠鵝鵒鷳鵜鵡鵲鶓鵪鶤鵯鵬鵮鶉鶊鵷鷫鶘鶡鶚鶻鶿鶥鶩鷊鷂鶲鶹鶺鷁鶼鶴鷖鸚鷓鷚鷯鷦鷲鷸鷺鸇鷹鸌鸏鸛鸘鹺麥麩黃黌黶黷黲黽龍歷誌製壹臺臯準復勐鐘註範籤' + + const Traditionalized = (cc) => { let str = '' const ss = JTPYStr() const tt = FTPYStr() @@ -85,7 +67,8 @@ document.addEventListener('DOMContentLoaded', function () { } return str } - function Simplized (cc) { + + const Simplized = (cc) => { let str = '' const ss = JTPYStr() const tt = FTPYStr() @@ -97,8 +80,7 @@ document.addEventListener('DOMContentLoaded', function () { return str } - function translateInitialization () { - translateButtonObject = document.getElementById('translateLink') + const translateInitialization = () => { if (translateButtonObject) { if (currentEncoding !== targetEncoding) { translateButtonObject.textContent = diff --git a/source/js/utils.js b/source/js/utils.js index be1f32b..3ac6f0a 100644 --- a/source/js/utils.js +++ b/source/js/utils.js @@ -47,12 +47,28 @@ return throttled }, - sidebarPaddingR: () => { - const innerWidth = window.innerWidth - const clientWidth = document.body.clientWidth - const paddingRight = innerWidth - clientWidth - if (innerWidth !== clientWidth) { - document.body.style.paddingRight = paddingRight + 'px' + overflowPaddingR: { + add: () => { + const innerWidth = window.innerWidth + const clientWidth = document.body.clientWidth + const paddingRight = innerWidth - clientWidth + + if (paddingRight > 0) { + document.body.style.paddingRight = `${paddingRight}px` + document.body.style.overflow = 'hidden' + const menuElement = document.querySelector('#page-header.nav-fixed #menus') + if (menuElement) { + menuElement.style.paddingRight = `${paddingRight}px` + } + } + }, + remove: () => { + document.body.style.paddingRight = '' + document.body.style.overflow = '' + const menuElement = document.querySelector('#page-header.nav-fixed #menus') + if (menuElement) { + menuElement.style.paddingRight = '' + } } }, @@ -69,28 +85,24 @@ }) }, - diffDate: (d, more = false) => { + diffDate: (inputDate, more = false) => { const dateNow = new Date() - const datePost = new Date(d) - const dateDiff = dateNow.getTime() - datePost.getTime() - const minute = 1000 * 60 - const hour = minute * 60 - const day = hour * 24 - const month = day * 30 + const datePost = new Date(inputDate) + const diffMs = dateNow - datePost + const diffSec = diffMs / 1000 + const diffMin = diffSec / 60 + const diffHour = diffMin / 60 + const diffDay = diffHour / 24 + const diffMonth = diffDay / 30 const { dateSuffix } = GLOBAL_CONFIG - if (!more) return parseInt(dateDiff / day) + if (!more) return Math.floor(diffDay) - const monthCount = dateDiff / month - const dayCount = dateDiff / day - const hourCount = dateDiff / hour - const minuteCount = dateDiff / minute - - if (monthCount > 12) return datePost.toISOString().slice(0, 10) - if (monthCount >= 1) return `${parseInt(monthCount)} ${dateSuffix.month}` - if (dayCount >= 1) return `${parseInt(dayCount)} ${dateSuffix.day}` - if (hourCount >= 1) return `${parseInt(hourCount)} ${dateSuffix.hour}` - if (minuteCount >= 1) return `${parseInt(minuteCount)} ${dateSuffix.min}` + if (diffMonth > 24) return datePost.toISOString().slice(0, 10) + if (diffMonth >= 3) return `${Math.floor(diffMonth)} ${dateSuffix.month}` + if (diffDay >= 3) return `${Math.floor(diffDay)} ${dateSuffix.day}` + if (diffHour >= 3) return `${Math.floor(diffHour)} ${dateSuffix.hour}` + if (diffMin >= 1) return `${Math.floor(diffMin)} ${dateSuffix.min}` return dateSuffix.just }, @@ -109,7 +121,7 @@ }, scrollToDest: (pos, time = 500) => { - const currentPos = window.pageYOffset + const currentPos = window.scrollY const isNavFixed = document.getElementById('page-header').classList.contains('fixed') if (currentPos > pos || isNavFixed) pos = pos - 70 @@ -121,22 +133,16 @@ return } - let start = null - pos = +pos - window.requestAnimationFrame(function step (currentTime) { - start = !start ? currentTime : start - const progress = currentTime - start - if (currentPos < pos) { - window.scrollTo(0, ((pos - currentPos) * progress / time) + currentPos) - } else { - window.scrollTo(0, currentPos - ((currentPos - pos) * progress / time)) - } - if (progress < time) { - window.requestAnimationFrame(step) - } else { - window.scrollTo(0, pos) + const startTime = performance.now() + const animate = currentTime => { + const timeElapsed = currentTime - startTime + const progress = Math.min(timeElapsed / time, 1) + window.scrollTo(0, currentPos + (pos - currentPos) * progress) + if (progress < 1) { + requestAnimationFrame(animate) } - }) + } + requestAnimationFrame(animate) }, animateIn: (ele, text) => { @@ -179,7 +185,7 @@ loadLightbox: ele => { const service = GLOBAL_CONFIG.lightbox - if (service === 'mediumZoom') { + if (service === 'medium_zoom') { mediumZoom(ele, { background: 'var(--zoom-bg)' }) } @@ -243,7 +249,7 @@ } }, - updateAnchor: (anchor) => { + updateAnchor: anchor => { if (anchor !== window.location.hash) { if (!anchor) anchor = location.pathname const title = GLOBAL_CONFIG_SITE.title @@ -254,33 +260,37 @@ } }, - getScrollPercent: (currentTop, ele) => { - const docHeight = ele.clientHeight - const winHeight = document.documentElement.clientHeight - const headerHeight = ele.offsetTop - const contentMath = (docHeight > winHeight) ? (docHeight - winHeight) : (document.documentElement.scrollHeight - winHeight) - const scrollPercent = (currentTop - headerHeight) / (contentMath) - const scrollPercentRounded = Math.round(scrollPercent * 100) - const percentage = (scrollPercentRounded > 100) ? 100 : (scrollPercentRounded <= 0) ? 0 : scrollPercentRounded - return percentage - }, + getScrollPercent: (() => { + let docHeight, winHeight, headerHeight, contentMath + + return (currentTop, ele) => { + if (!docHeight || ele.clientHeight !== docHeight) { + docHeight = ele.clientHeight + winHeight = window.innerHeight + headerHeight = ele.offsetTop + contentMath = Math.max(docHeight - winHeight, document.documentElement.scrollHeight - winHeight) + } + + const scrollPercent = (currentTop - headerHeight) / contentMath + return Math.max(0, Math.min(100, Math.round(scrollPercent * 100))) + } + })(), addEventListenerPjax: (ele, event, fn, option = false) => { ele.addEventListener(event, fn, option) - btf.addGlobalFn('pjax', () => { + btf.addGlobalFn('pjaxSendOnce', () => { ele.removeEventListener(event, fn, option) }) }, removeGlobalFnEvent: (key, parent = window) => { - const { globalFn = {} } = parent - const keyObj = globalFn[key] || {} - const keyArr = Object.keys(keyObj) - if (!keyArr.length) return - keyArr.forEach(i => { - keyObj[i]() - }) - delete parent.globalFn[key] + const globalFn = parent.globalFn || {} + const keyObj = globalFn[key] + if (!keyObj) return + + Object.keys(keyObj).forEach(i => keyObj[i]()) + + delete globalFn[key] } }