From 9ebe6c19256fabd6b514c37c3b577f88fc475797 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?CC=E5=BA=B7=E7=BA=B3=E7=99=BE=E5=B7=9D?= <ccknbc@qq.com>
Date: Fri, 9 Jun 2023 23:24:59 +0800
Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9E=20fix(meting):=20=E5=AE=98?=
 =?UTF-8?q?=E6=96=B9API=20=E8=B7=A8=E5=9F=9F=E5=AF=BC=E8=87=B4=E6=95=B0?=
 =?UTF-8?q?=E6=8D=AE=E8=8E=B7=E5=8F=96=E5=A4=B1=E8=B4=A5?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 _config.butterfly.yml                         |   5 +
 _config.yml                                   |   4 +-
 package-lock.json                             | 222 +++++++++---------
 package.json                                  |   2 +-
 source/blogroll/index.md                      |  71 ++++++
 source/music/index.md                         |  23 +-
 themes/butterfly/README.md                    |  12 +-
 themes/butterfly/README_CN.md                 |   8 +-
 themes/butterfly/_config.yml                  |   5 +
 .../layout/includes/header/index.pug          |   2 +-
 .../includes/loading/fullpage-loading.pug     |  34 +--
 .../layout/includes/mixins/post-ui.pug        |   4 +-
 .../butterfly/layout/includes/page/flink.pug  |  70 +++---
 themes/butterfly/layout/includes/sidebar.pug  |   2 +-
 .../third-party/card-post-count/artalk.pug    |  35 ++-
 .../third-party/card-post-count/waline.pug    |  24 +-
 .../includes/third-party/chat/chatra.pug      |  63 +++--
 .../includes/third-party/chat/crisp.pug       |  63 ++---
 .../includes/third-party/chat/daovoice.pug    |  66 +++---
 .../includes/third-party/chat/messenger.pug   |  60 ++---
 .../includes/third-party/chat/tidio.pug       |  70 +++---
 .../includes/third-party/comments/artalk.pug  |   5 +-
 .../includes/third-party/comments/index.pug   |   2 +-
 .../includes/third-party/comments/waline.pug  |   8 +-
 .../includes/third-party/math/mathjax.pug     |  13 +-
 .../includes/third-party/math/mermaid.pug     |  50 ++--
 .../third-party/newest-comments/artalk.pug    |  10 +-
 .../third-party/newest-comments/waline.pug    |  45 ++--
 .../layout/includes/third-party/pjax.pug      |   1 -
 .../layout/includes/third-party/subtitle.pug  |   2 +-
 .../layout/includes/widget/card_author.pug    |   2 +-
 .../includes/widget/card_newest_comment.pug   |   2 +-
 themes/butterfly/package.json                 |   2 +-
 themes/butterfly/plugins.yml                  |  18 +-
 themes/butterfly/scripts/events/init.js       |  18 +-
 .../source/css/_global/function.styl          |  24 ++
 .../butterfly/source/css/_global/index.styl   |  26 +-
 .../butterfly/source/css/_layout/footer.styl  |   4 +-
 themes/butterfly/source/css/_layout/head.styl |  16 +-
 themes/butterfly/source/css/_layout/post.styl |  11 +-
 .../source/css/_layout/third-party.styl       |  19 +-
 .../butterfly/source/css/_mode/darkmode.styl  |   6 +-
 .../butterfly/source/css/_mode/readmode.styl  |   3 +-
 themes/butterfly/source/css/_page/common.styl |   2 +-
 .../butterfly/source/css/_page/homepage.styl  |  10 +-
 .../butterfly/source/css/_search/index.styl   |  12 +-
 themes/butterfly/source/css/index.styl        |   8 +-
 themes/butterfly/source/js/main.js            |  18 +-
 themes/butterfly/source/js/utils.js           |  15 +-
 49 files changed, 673 insertions(+), 524 deletions(-)

diff --git a/_config.butterfly.yml b/_config.butterfly.yml
index 513d985c..382be64b 100644
--- a/_config.butterfly.yml
+++ b/_config.butterfly.yml
@@ -697,6 +697,11 @@ background: "linear-gradient(45deg,#fff1eb,#ace0f9)"
 # Footer Background
 footer_bg: "linear-gradient(135deg,#fff1eb,#ace0f9)"
 
+# Add mask to header or footer (为 header 或 footer 添加黑色半透遮罩)
+mask:
+  header: true
+  footer: true
+
 # the position of bottom right button/default unit: px (右下角按鈕距離底部的距離/默認單位為px)
 rightside-bottom:
 
diff --git a/_config.yml b/_config.yml
index 2d11d002..5d750dcc 100644
--- a/_config.yml
+++ b/_config.yml
@@ -255,8 +255,10 @@ mmedia:
         lrcType: 3
   meting:
     js: https://cdn1.tianli0.top/npm/meting/dist/Meting.min.js
-    api:
+    api: https://music.startly.cn/ # https://meting.ccknbc.cc/api (备用,支持 YouTube Spotify)
     default:
+      theme: '#8fbc8f'
+      list-folded: true
   dplayer:
     js: https://cdn1.tianli0.top/npm/dplayer/dist/DPlayer.min.js
     hls_js: https://cdn1.tianli0.top/npm/hls.js/dist/hls.min.js
diff --git a/package-lock.json b/package-lock.json
index 5454dc8c..b38f6c65 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -32,7 +32,7 @@
         "hexo-wordcount": "6.0.1",
         "hexo-yam": "8.0.0",
         "markdown-it-task-lists": "2.1.1",
-        "workbox-build": "6.6.1"
+        "workbox-build": "7.0.0"
       }
     },
     "node_modules/@adobe/css-tools": {
@@ -579,9 +579,9 @@
       }
     },
     "node_modules/@babel/plugin-proposal-private-property-in-object": {
-      "version": "7.21.0",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0.tgz",
-      "integrity": "sha512-ha4zfehbJjc5MmXBlHec1igel5TJXXLDDRbuJ4+XT2TJcyD9/V1919BA8gMvsdHcNMBy4WBUBiRb3nw/EQUtBw==",
+      "version": "7.21.11",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz",
+      "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==",
       "dependencies": {
         "@babel/helper-annotate-as-pure": "^7.18.6",
         "@babel/helper-create-class-features-plugin": "^7.21.0",
@@ -3064,9 +3064,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001492",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001492.tgz",
-      "integrity": "sha512-2efF8SAZwgAX1FJr87KWhvuJxnGJKOnctQa8xLOskAXNXq8oiuqgl6u1kk3fFpsp3GgvzlRjiK1sl63hNtFADw==",
+      "version": "1.0.30001495",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001495.tgz",
+      "integrity": "sha512-F6x5IEuigtUfU5ZMQK2jsy5JqUUlEFRVZq8bO2a+ysq5K7jD6PPc9YXZj78xDNS3uNchesp1Jw47YXEqr+Viyg==",
       "funding": [
         {
           "type": "opencollective",
@@ -4064,9 +4064,9 @@
       }
     },
     "node_modules/dotenv": {
-      "version": "16.1.2",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.2.tgz",
-      "integrity": "sha512-RiNjjDF5yr9NtjqJqmWYA/XZShmt3r8FtJgAaqTiYqb99SqT0+aw5xAwOIvjMyXsH/C9/fLNafFkkZDwRi1KHA==",
+      "version": "16.1.4",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.1.4.tgz",
+      "integrity": "sha512-m55RtE8AsPeJBpOIFKihEmqUcoVncQIwo7x9U8ZwLEZw9ZpXboz2c+rvog+jUaJvVrZ5kBOeYQBX5+8Aa/OZQw==",
       "engines": {
         "node": ">=12"
       },
@@ -4119,9 +4119,9 @@
       }
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.414",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.414.tgz",
-      "integrity": "sha512-RRuCvP6ekngVh2SAJaOKT/hxqc9JAsK+Pe0hP5tGQIfonU2Zy9gMGdJ+mBdyl/vNucMG6gkXYtuM4H/1giws5w=="
+      "version": "1.4.425",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.425.tgz",
+      "integrity": "sha512-wv1NufHxu11zfDbY4fglYQApMswleE9FL/DSeyOyauVXDZ+Kco96JK/tPfBUaDqfRarYp2WH2hJ/5UnVywp9Jg=="
     },
     "node_modules/emoji-regex": {
       "version": "8.0.0",
@@ -4490,9 +4490,9 @@
       "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
     },
     "node_modules/fast-xml-parser": {
-      "version": "4.2.2",
-      "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.2.tgz",
-      "integrity": "sha512-DLzIPtQqmvmdq3VUKR7T6omPK/VCRNqgFlGtbESfyhcH2R4I8EzK1/K6E8PkRCK2EabWrUHK32NjYRbEFnnz0Q==",
+      "version": "4.2.4",
+      "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.4.tgz",
+      "integrity": "sha512-fbfMDvgBNIdDJLdLOwacjFAPYt67tr31H9ZhWSm45CDAxvd0I6WTlSOUo7K2P/K5sA5JgMKG64PI3DMcaFdWpQ==",
       "funding": [
         {
           "type": "paypal",
@@ -11779,12 +11779,12 @@
       }
     },
     "node_modules/terser": {
-      "version": "5.17.6",
-      "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.6.tgz",
-      "integrity": "sha512-V8QHcs8YuyLkLHsJO5ucyff1ykrLVsR4dNnS//L5Y3NiSXpbK1J+WMVUs67eI0KTxs9JtHhgEQpXQVHlHI92DQ==",
+      "version": "5.17.7",
+      "resolved": "https://registry.npmjs.org/terser/-/terser-5.17.7.tgz",
+      "integrity": "sha512-/bi0Zm2C6VAexlGgLlVxA0P2lru/sdLyfCVaRMfKVo9nWxbmz7f/sD8VPybPeSUJaJcwmCJis9pBIhcVcG1QcQ==",
       "dependencies": {
-        "@jridgewell/source-map": "^0.3.2",
-        "acorn": "^8.5.0",
+        "@jridgewell/source-map": "^0.3.3",
+        "acorn": "^8.8.2",
         "commander": "^2.20.0",
         "source-map-support": "~0.5.20"
       },
@@ -12109,9 +12109,9 @@
       }
     },
     "node_modules/tslib": {
-      "version": "2.5.2",
-      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.2.tgz",
-      "integrity": "sha512-5svOrSA2w3iGFDs1HibEVBGbDrAY82bFQ3HZ3ixB+88nsbsWQoKqDRb5UBYAUPEzbBn6dAp5gRNXglySbx1MlA=="
+      "version": "2.5.3",
+      "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz",
+      "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w=="
     },
     "node_modules/tunnel-agent": {
       "version": "0.6.0",
@@ -12861,26 +12861,26 @@
       }
     },
     "node_modules/workbox-background-sync": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-6.6.1.tgz",
-      "integrity": "sha512-trJd3ovpWCvzu4sW0E8rV3FUyIcC0W8G+AZ+VcqzzA890AsWZlUGOTSxIMmIHVusUw/FDq1HFWfy/kC/WTRqSg==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.0.0.tgz",
+      "integrity": "sha512-S+m1+84gjdueM+jIKZ+I0Lx0BDHkk5Nu6a3kTVxP4fdj3gKouRNmhO8H290ybnJTOPfBDtTMXSQA/QLTvr7PeA==",
       "dependencies": {
         "idb": "^7.0.1",
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-broadcast-update": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-6.6.1.tgz",
-      "integrity": "sha512-fBhffRdaANdeQ1V8s692R9l/gzvjjRtydBOvR6WCSB0BNE2BacA29Z4r9/RHd9KaXCPl6JTdI9q0bR25YKP8TQ==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-7.0.0.tgz",
+      "integrity": "sha512-oUuh4jzZrLySOo0tC0WoKiSg90bVAcnE98uW7F8GFiSOXnhogfNDGZelPJa+6KpGBO5+Qelv04Hqx2UD+BJqNQ==",
       "dependencies": {
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-build": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-6.6.1.tgz",
-      "integrity": "sha512-INPgDx6aRycAugUixbKgiEQBWD0MPZqU5r0jyr24CehvNuLPSXp/wGOpdRJmts656lNiXwqV7dC2nzyrzWEDnw==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-7.0.0.tgz",
+      "integrity": "sha512-CttE7WCYW9sZC+nUYhQg3WzzGPr4IHmrPnjKiu3AMXsiNQKx+l4hHl63WTrnicLmKEKHScWDH8xsGBdrYgtBzg==",
       "dependencies": {
         "@apideck/better-ajv-errors": "^0.3.1",
         "@babel/core": "^7.11.1",
@@ -12904,21 +12904,21 @@
         "strip-comments": "^2.0.1",
         "tempy": "^0.6.0",
         "upath": "^1.2.0",
-        "workbox-background-sync": "6.6.1",
-        "workbox-broadcast-update": "6.6.1",
-        "workbox-cacheable-response": "6.6.1",
-        "workbox-core": "6.6.1",
-        "workbox-expiration": "6.6.1",
-        "workbox-google-analytics": "6.6.1",
-        "workbox-navigation-preload": "6.6.1",
-        "workbox-precaching": "6.6.1",
-        "workbox-range-requests": "6.6.1",
-        "workbox-recipes": "6.6.1",
-        "workbox-routing": "6.6.1",
-        "workbox-strategies": "6.6.1",
-        "workbox-streams": "6.6.1",
-        "workbox-sw": "6.6.1",
-        "workbox-window": "6.6.1"
+        "workbox-background-sync": "7.0.0",
+        "workbox-broadcast-update": "7.0.0",
+        "workbox-cacheable-response": "7.0.0",
+        "workbox-core": "7.0.0",
+        "workbox-expiration": "7.0.0",
+        "workbox-google-analytics": "7.0.0",
+        "workbox-navigation-preload": "7.0.0",
+        "workbox-precaching": "7.0.0",
+        "workbox-range-requests": "7.0.0",
+        "workbox-recipes": "7.0.0",
+        "workbox-routing": "7.0.0",
+        "workbox-strategies": "7.0.0",
+        "workbox-streams": "7.0.0",
+        "workbox-sw": "7.0.0",
+        "workbox-window": "7.0.0"
       },
       "engines": {
         "node": ">=16.0.0"
@@ -13023,114 +13023,114 @@
       }
     },
     "node_modules/workbox-cacheable-response": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-6.6.1.tgz",
-      "integrity": "sha512-85LY4veT2CnTCDxaVG7ft3NKaFbH6i4urZXgLiU4AiwvKqS2ChL6/eILiGRYXfZ6gAwDnh5RkuDbr/GMS4KSag==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-7.0.0.tgz",
+      "integrity": "sha512-0lrtyGHn/LH8kKAJVOQfSu3/80WDc9Ma8ng0p2i/5HuUndGttH+mGMSvOskjOdFImLs2XZIimErp7tSOPmu/6g==",
       "dependencies": {
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-core": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-6.6.1.tgz",
-      "integrity": "sha512-ZrGBXjjaJLqzVothoE12qTbVnOAjFrHDXpZe7coCb6q65qI/59rDLwuFMO4PcZ7jcbxY+0+NhUVztzR/CbjEFw=="
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-7.0.0.tgz",
+      "integrity": "sha512-81JkAAZtfVP8darBpfRTovHg8DGAVrKFgHpOArZbdFd78VqHr5Iw65f2guwjE2NlCFbPFDoez3D3/6ZvhI/rwQ=="
     },
     "node_modules/workbox-expiration": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-6.6.1.tgz",
-      "integrity": "sha512-qFiNeeINndiOxaCrd2DeL1Xh1RFug3JonzjxUHc5WkvkD2u5abY3gZL1xSUNt3vZKsFFGGORItSjVTVnWAZO4A==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-7.0.0.tgz",
+      "integrity": "sha512-MLK+fogW+pC3IWU9SFE+FRStvDVutwJMR5if1g7oBJx3qwmO69BNoJQVaMXq41R0gg3MzxVfwOGKx3i9P6sOLQ==",
       "dependencies": {
         "idb": "^7.0.1",
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-google-analytics": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-6.6.1.tgz",
-      "integrity": "sha512-1TjSvbFSLmkpqLcBsF7FuGqqeDsf+uAXO/pjiINQKg3b1GN0nBngnxLcXDYo1n/XxK4N7RaRrpRlkwjY/3ocuA==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-7.0.0.tgz",
+      "integrity": "sha512-MEYM1JTn/qiC3DbpvP2BVhyIH+dV/5BjHk756u9VbwuAhu0QHyKscTnisQuz21lfRpOwiS9z4XdqeVAKol0bzg==",
       "dependencies": {
-        "workbox-background-sync": "6.6.1",
-        "workbox-core": "6.6.1",
-        "workbox-routing": "6.6.1",
-        "workbox-strategies": "6.6.1"
+        "workbox-background-sync": "7.0.0",
+        "workbox-core": "7.0.0",
+        "workbox-routing": "7.0.0",
+        "workbox-strategies": "7.0.0"
       }
     },
     "node_modules/workbox-navigation-preload": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-6.6.1.tgz",
-      "integrity": "sha512-DQCZowCecO+wRoIxJI2V6bXWK6/53ff+hEXLGlQL4Rp9ZaPDLrgV/32nxwWIP7QpWDkVEtllTAK5h6cnhxNxDA==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-7.0.0.tgz",
+      "integrity": "sha512-juWCSrxo/fiMz3RsvDspeSLGmbgC0U9tKqcUPZBCf35s64wlaLXyn2KdHHXVQrb2cqF7I0Hc9siQalainmnXJA==",
       "dependencies": {
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-precaching": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-6.6.1.tgz",
-      "integrity": "sha512-K4znSJ7IKxCnCYEdhNkMr7X1kNh8cz+mFgx9v5jFdz1MfI84pq8C2zG+oAoeE5kFrUf7YkT5x4uLWBNg0DVZ5A==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-7.0.0.tgz",
+      "integrity": "sha512-EC0vol623LJqTJo1mkhD9DZmMP604vHqni3EohhQVwhJlTgyKyOkMrZNy5/QHfOby+39xqC01gv4LjOm4HSfnA==",
       "dependencies": {
-        "workbox-core": "6.6.1",
-        "workbox-routing": "6.6.1",
-        "workbox-strategies": "6.6.1"
+        "workbox-core": "7.0.0",
+        "workbox-routing": "7.0.0",
+        "workbox-strategies": "7.0.0"
       }
     },
     "node_modules/workbox-range-requests": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-6.6.1.tgz",
-      "integrity": "sha512-4BDzk28govqzg2ZpX0IFkthdRmCKgAKreontYRC5YsAPB2jDtPNxqx3WtTXgHw1NZalXpcH/E4LqUa9+2xbv1g==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-7.0.0.tgz",
+      "integrity": "sha512-SxAzoVl9j/zRU9OT5+IQs7pbJBOUOlriB8Gn9YMvi38BNZRbM+RvkujHMo8FOe9IWrqqwYgDFBfv6sk76I1yaQ==",
       "dependencies": {
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-recipes": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-6.6.1.tgz",
-      "integrity": "sha512-/oy8vCSzromXokDA+X+VgpeZJvtuf8SkQ8KL0xmRivMgJZrjwM3c2tpKTJn6PZA6TsbxGs3Sc7KwMoZVamcV2g==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-7.0.0.tgz",
+      "integrity": "sha512-DntcK9wuG3rYQOONWC0PejxYYIDHyWWZB/ueTbOUDQgefaeIj1kJ7pdP3LZV2lfrj8XXXBWt+JDRSw1lLLOnww==",
       "dependencies": {
-        "workbox-cacheable-response": "6.6.1",
-        "workbox-core": "6.6.1",
-        "workbox-expiration": "6.6.1",
-        "workbox-precaching": "6.6.1",
-        "workbox-routing": "6.6.1",
-        "workbox-strategies": "6.6.1"
+        "workbox-cacheable-response": "7.0.0",
+        "workbox-core": "7.0.0",
+        "workbox-expiration": "7.0.0",
+        "workbox-precaching": "7.0.0",
+        "workbox-routing": "7.0.0",
+        "workbox-strategies": "7.0.0"
       }
     },
     "node_modules/workbox-routing": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-6.6.1.tgz",
-      "integrity": "sha512-j4ohlQvfpVdoR8vDYxTY9rA9VvxTHogkIDwGdJ+rb2VRZQ5vt1CWwUUZBeD/WGFAni12jD1HlMXvJ8JS7aBWTg==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-7.0.0.tgz",
+      "integrity": "sha512-8YxLr3xvqidnbVeGyRGkaV4YdlKkn5qZ1LfEePW3dq+ydE73hUUJJuLmGEykW3fMX8x8mNdL0XrWgotcuZjIvA==",
       "dependencies": {
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-strategies": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-6.6.1.tgz",
-      "integrity": "sha512-WQLXkRnsk4L81fVPkkgon1rZNxnpdO5LsO+ws7tYBC6QQQFJVI6v98klrJEjFtZwzw/mB/HT5yVp7CcX0O+mrw==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-7.0.0.tgz",
+      "integrity": "sha512-dg3qJU7tR/Gcd/XXOOo7x9QoCI9nk74JopaJaYAQ+ugLi57gPsXycVdBnYbayVj34m6Y8ppPwIuecrzkpBVwbA==",
       "dependencies": {
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/workbox-streams": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-6.6.1.tgz",
-      "integrity": "sha512-maKG65FUq9e4BLotSKWSTzeF0sgctQdYyTMq529piEN24Dlu9b6WhrAfRpHdCncRS89Zi2QVpW5V33NX8PgH3Q==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-7.0.0.tgz",
+      "integrity": "sha512-moVsh+5to//l6IERWceYKGiftc+prNnqOp2sgALJJFbnNVpTXzKISlTIsrWY+ogMqt+x1oMazIdHj25kBSq/HQ==",
       "dependencies": {
-        "workbox-core": "6.6.1",
-        "workbox-routing": "6.6.1"
+        "workbox-core": "7.0.0",
+        "workbox-routing": "7.0.0"
       }
     },
     "node_modules/workbox-sw": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-6.6.1.tgz",
-      "integrity": "sha512-R7whwjvU2abHH/lR6kQTTXLHDFU2izht9kJOvBRYK65FbwutT4VvnUAJIgHvfWZ/fokrOPhfoWYoPCMpSgUKHQ=="
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.0.0.tgz",
+      "integrity": "sha512-SWfEouQfjRiZ7GNABzHUKUyj8pCoe+RwjfOIajcx6J5mtgKkN+t8UToHnpaJL5UVVOf5YhJh+OHhbVNIHe+LVA=="
     },
     "node_modules/workbox-window": {
-      "version": "6.6.1",
-      "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-6.6.1.tgz",
-      "integrity": "sha512-wil4nwOY58nTdCvif/KEZjQ2NP8uk3gGeRNy2jPBbzypU4BT4D9L8xiwbmDBpZlSgJd2xsT9FvSNU0gsxV51JQ==",
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-7.0.0.tgz",
+      "integrity": "sha512-j7P/bsAWE/a7sxqTzXo3P2ALb1reTfZdvVp6OJ/uLr/C2kZAMvjeWGm8V4htQhor7DOvYg0sSbFN2+flT5U0qA==",
       "dependencies": {
         "@types/trusted-types": "^2.0.2",
-        "workbox-core": "6.6.1"
+        "workbox-core": "7.0.0"
       }
     },
     "node_modules/wrap-ansi": {
diff --git a/package.json b/package.json
index d3e3bffe..a8756e05 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,6 @@
     "hexo-wordcount": "6.0.1",
     "hexo-yam": "8.0.0",
     "markdown-it-task-lists": "2.1.1",
-    "workbox-build": "6.6.1"
+    "workbox-build": "7.0.0"
   }
 }
diff --git a/source/blogroll/index.md b/source/blogroll/index.md
index ac9b44f9..8473e59c 100644
--- a/source/blogroll/index.md
+++ b/source/blogroll/index.md
@@ -34,6 +34,77 @@ xkFriend.init({
 {% btn '#post-comment',给 CC 留言,fa-solid fa-comments,outline green smaller %}
 或再次 PR  {% endnote %}
 
+<p style="padding:0 0 0 .8rem">
+    请<strong>勾选</strong>你符合的条件,满足所有条件才可评论申请:
+</p>
+<div id="friendlink_checkboxs" style="padding:0 0 0 1.6rem">
+    <p>
+        <label class="checkbox">
+            <input type="checkbox" id="checkbox1" onclick="checkForm()">
+            我已添加  <b>CC的部落格</b>的友情链接
+        </label>
+    </p>
+    <p>
+        <label class="checkbox">
+            <input type="checkbox" id="checkbox2" onclick="checkForm()">
+            我的链接主体为<b>个人</b>,网站类型为<b>博客</b>
+        </label>
+    </p>
+    <p>
+        <label class="checkbox">
+            <input type="checkbox" id="checkbox3" onclick="checkForm()">我的网站现在可以在中国大陆区域正常访问
+        </label>
+    </p>
+    <p>
+        <label class="checkbox">
+            <input type="checkbox" id="checkbox4" onclick="checkForm()">网站内容符合中国大陆法律法规
+        </label>
+    </p>
+    <p>
+        <label class="checkbox">
+            <input type="checkbox" id="checkbox5" onclick="checkForm()">我的网站可以在1分钟内加载完成首屏
+        </label>
+    </p>
+</div>
+
+<script>
+    var walineSubmit = document.getElementsByClassName("wl-comment")[0];
+    if (walineSubmit) {
+        walineSubmit.style.opacity = "0";
+    }
+    function checkForm() {
+        var checkbox1 = document.getElementById("checkbox1");
+        var checkbox2 = document.getElementById("checkbox2");
+        var checkbox3 = document.getElementById("checkbox3");
+        var checkbox4 = document.getElementById("checkbox4");
+        var checkbox5 = document.getElementById("checkbox5");
+        var walineSubmit = document.getElementsByClassName("wl-comment")[0];
+        if (checkbox1.checked && checkbox2.checked && checkbox3.checked && checkbox4.checked && checkbox5.checked) {
+            walineSubmit.style.opacity = "1";
+            walineSubmit.style.height = "auto";
+            walineSubmit.style.overflow = "auto";
+            var input = document.getElementsByClassName("wl-editor")[0];
+            let evt = new Event('input');
+            input.dispatchEvent(evt);
+            input.value = '昵称: \n博客链接: \n头像链接: \n描述: \n';
+            input.setSelectionRange(-1, -1);
+        } else {
+            walineSubmit.style.opacity = "0";
+            walineSubmit.style.height = "0";
+            walineSubmit.style.overflow = "hidden";
+        }
+    }
+</script>
+
+<style>
+    .wl-comment {
+        opacity: 0;
+        height: 0;
+        transition: opacity .5s, height .5s;
+        overflow: hidden;
+    }
+</style>
+
 <!-- {% link 顺便看看友链截图列表,您可复制使用啦, https://cdn1.tianli0.top/gh/ccknbc-actions/blogroll@webp/, https://cdn1.tianli0.top/www.jsdelivr.com/c903573129ce0afdbc8b006baf86dba514615495/img/logo-horizontal.svg %} -->
 
 <!-- {% ghcard ccknbc-actions/blogroll, theme=vue %}  -->
diff --git a/source/music/index.md b/source/music/index.md
index 3c43c9af..7380da38 100644
--- a/source/music/index.md
+++ b/source/music/index.md
@@ -7,8 +7,23 @@ comments: false
 translate_title: music
 subtitle: Music
 date: 2020-11-08 15:29:33
-updated: 2023-02-19 13:12:58
+updated: 2023-06-09 23:13:42
 ---
-{% note green 'fa-solid fa-dice-three' simple %}Three Man Down{% endnote %}
-{% mmedia "meting" "auto=https://music.163.com/#/artist?id=12838890" "theme:#8fbc8f" %}
-{% note info simple %}2022年8月22日 Ohm宣布因个人原因退出乐队,"TMD"因此也成为了缺少贝斯手的乐队{% endnote %}
\ No newline at end of file
+<link rel="stylesheet" href="https://cdn1.tianli0.top/npm/aplayer/dist/APlayer.min.css">
+<script src="https://cdn1.tianli0.top/npm/aplayer/dist/APlayer.min.js"></script>
+<script src="https://cdn1.tianli0.top/npm/meting/dist/Meting.min.js"></script>
+<script>var meting_api="https://music.startly.cn/?server=:server&type=:type&id=:id&auth=:auth&r=:r"</script>
+
+{% folding green open, Three Man Down × Tilly Birds %}
+<!-- {% note green 'fa-solid fa-dice-three' simple %}Three Man Down × Tilly Birds{% endnote %} -->
+<meting-js metin="meting" server="netease" type="playlist" id="5457110860" list-folded="true" theme="#8fbc8f">
+{% note info simple %}2022年8月22日 Ohm宣布因个人原因退出乐队,"TMD"因此也成为了缺少贝斯手的乐队{% endnote %}
+{% endfolding %}
+
+{% folding blue, 王铮亮 | 遇见才是最美的邂逅 %}
+<meting-js metin="meting" server="netease" type="playlist" id="7681620447" list-folded="true" theme="#8fbc8f">
+{% endfolding %}
+
+{% folding blue, 王铮亮2023“还是爱着”全国巡演 %}
+<meting-js metin="meting" server="netease" type="playlist" id="8448821577" list-folded="true" theme="#8fbc8f">
+{% endfolding %}
\ No newline at end of file
diff --git a/themes/butterfly/README.md b/themes/butterfly/README.md
index 284ff412..e0189ba3 100644
--- a/themes/butterfly/README.md
+++ b/themes/butterfly/README.md
@@ -1,7 +1,5 @@
 <div align="right">
-  Language:
-  🇺🇸
-  <a title="Chinese" href="/README_CN.md">🇨🇳</a>
+<a title="Chinese" href="/README_CN.md">中文</a>
 </div>
 
 # hexo-theme-butterfly
@@ -14,7 +12,7 @@
 
 ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png)
 
-Demo: 👍 [Butterfly](https://butterfly.js.org/)  ||   🤞 [CrazyWong](https://crazywong.com/)
+Demo: 👍 [Butterfly](https://butterfly.js.org/)  ||   🤞 [CrazyWong](https://blog.crazywong.com/)
 
 Docs: 📖 [Butterfly Docs](https://butterfly.js.org/posts/21cfbf15/)
 
@@ -62,17 +60,17 @@ npm i hexo-theme-butterfly
 
 - [x] Card UI Design
 - [X] Support sub-menu
-- [x] Two Column designs
+- [x] Two-column layout
 - [x] Responsive Web Design
 - [x] Dark Mode
 - [x] Pjax
 - [x] Read Mode
 - [x] Conversion between Traditional and Simplified Chinese
 - [X] TOC catalog is available for both computers and mobile phones
-- [X] Color themes (darker/pale night/light/ocean/mac/mac light), support custom colors
+- [X] Built-in Syntax Highlighting Themes (darker/pale night/light/ocean/mac/mac light), also support customization
 - [X] Code Blocks (Display code language/close or expand Code Blocks/Copy Button/word wrap)
 - [X] Disable copy/Add a Copyright Notice to the Copied Text
-- [X] Search (Algolia SearchZ/Local Search)
+- [X] Search (Algolia Search/Local Search)
 - [x] Mathjax and Katex
 - [x] Built-in 404 page
 - [x] WordCount
diff --git a/themes/butterfly/README_CN.md b/themes/butterfly/README_CN.md
index f67c2e38..441cd793 100644
--- a/themes/butterfly/README_CN.md
+++ b/themes/butterfly/README_CN.md
@@ -1,7 +1,5 @@
 <div align="right">
-  語言:
-  中文
-  <a title="English" href="/README.md">英文</a>
+  <a title="English" href="/README.md">English</a>
 </div>
 
 # hexo-theme-butterfly
@@ -14,7 +12,7 @@
 
 ![](https://cdn.jsdelivr.net/gh/jerryc127/CDN@m2/img/theme-butterfly-readme.png)
 
-預覽: 👍 [Butterfly](https://butterfly.js.org/)  ||  🤞 [CrazyWong](https://crazywong.com/)
+預覽: 👍 [Butterfly](https://butterfly.js.org/)  ||  🤞 [CrazyWong](https://blog.crazywong.com/)
 
 文檔: 📖 [Butterfly Docs](https://butterfly.js.org/posts/21cfbf15/)
 
@@ -72,7 +70,7 @@ theme: butterfly
 - [X] 內置多種代碼配色(darker/pale night/light/ocean/mac/mac light),可自定義代碼配色
 - [X] 代碼塊顯示代碼語言/關閉或展開代碼塊/代碼複製/代碼自動換行
 - [X] 可關閉文字複製/可開啟內容複製增加版權信息)
-- [X] 兩種搜索(Algolia搜索和本地搜索)
+- [X] 兩種搜索( Algolia 搜索和本地搜索)
 - [x] Mathjax 和 Katex
 - [x] 內置404頁面
 - [x] 顯示字數統計
diff --git a/themes/butterfly/_config.yml b/themes/butterfly/_config.yml
index aad06ef7..5c1b8d12 100644
--- a/themes/butterfly/_config.yml
+++ b/themes/butterfly/_config.yml
@@ -645,6 +645,11 @@ background:
 # Footer Background
 footer_bg: false
 
+# Add mask to header or footer (为 header 或 footer 添加黑色半透遮罩)
+mask:
+  header: true
+  footer: true
+
 # the position of bottom right button/default unit: px (右下角按鈕距離底部的距離/默認單位為px)
 rightside-bottom:
 
diff --git a/themes/butterfly/layout/includes/header/index.pug b/themes/butterfly/layout/includes/header/index.pug
index 5245d365..053ba1ad 100644
--- a/themes/butterfly/layout/includes/header/index.pug
+++ b/themes/butterfly/layout/includes/header/index.pug
@@ -44,7 +44,7 @@ header#page-header(class=`${isHomeClass+isFixedClass}` style=bg_img)
             span#subtitle
         if(theme.social)
           #site_social_icons
-            !=fragment_cache('social', function(){return partial('includes/header/social')})
+            !=partial('includes/header/social', {}, {cache: true})
       #scroll-down
         i.fa-solid.fa-angle-down.scroll-down-effects
     else
diff --git a/themes/butterfly/layout/includes/loading/fullpage-loading.pug b/themes/butterfly/layout/includes/loading/fullpage-loading.pug
index 5ca3d0db..4a2c8bf5 100644
--- a/themes/butterfly/layout/includes/loading/fullpage-loading.pug
+++ b/themes/butterfly/layout/includes/loading/fullpage-loading.pug
@@ -9,21 +9,25 @@
     .loading-word= _p('loading')
 
 script.
-  const preloader = {
-    endLoading: () => {
-      document.body.style.overflow = '';
-      document.getElementById('loading-box').classList.add("loaded")
-    },
-    initLoading: () => {
-      document.body.style.overflow = 'hidden';
-      document.getElementById('loading-box').classList.remove("loaded")
+  (()=>{
+    const $loadingBox = document.getElementById('loading-box')
+    const $body = document.body
+    const preloader = {
+      endLoading: () => {
+        $body.style.overflow = ''
+        $loadingBox.classList.add('loaded')
+      },
+      initLoading: () => {
+        $body.style.overflow = 'hidden'
+        $loadingBox.classList.remove('loaded')
+      }
     }
-  }
 
-  preloader.initLoading()
-  window.addEventListener('load',()=> { preloader.endLoading() })
+    preloader.initLoading()
+    window.addEventListener('load',() => { preloader.endLoading() })
 
-  if (!{theme.pjax && theme.pjax.enable}) {
-    document.addEventListener('pjax:send', () => { preloader.initLoading() })
-    document.addEventListener('pjax:complete', () => { preloader.endLoading() })
-  }
\ No newline at end of file
+    if (!{theme.pjax && theme.pjax.enable}) {
+      document.addEventListener('pjax:send', () => { preloader.initLoading() })
+      document.addEventListener('pjax:complete', () => { preloader.endLoading() })
+    }
+  })()
\ No newline at end of file
diff --git a/themes/butterfly/layout/includes/mixins/post-ui.pug b/themes/butterfly/layout/includes/mixins/post-ui.pug
index 098700e7..1a623563 100644
--- a/themes/butterfly/layout/includes/mixins/post-ui.pug
+++ b/themes/butterfly/layout/includes/mixins/post-ui.pug
@@ -70,7 +70,7 @@ mixin postUI(posts)
                 block
               span.article-meta-label= ' ' + _p('card_post_count')
           
-          if theme.comments.card_post_count
+          if theme.comments.card_post_count && theme.comments.use
             case theme.comments.use[0]
               when 'Disqus'
                 +countBlockInIndex
@@ -89,7 +89,7 @@ mixin postUI(posts)
               when 'Waline'
                 +countBlockInIndex
                   a(href=url_for(link) + '#post-comment')
-                    span.waline-comment-count(id=url_for(link))
+                    span.waline-comment-count(data-path=url_for(link))
                       i.fa-solid.fa-spinner.fa-spin
               when 'Twikoo'
                 +countBlockInIndex
diff --git a/themes/butterfly/layout/includes/page/flink.pug b/themes/butterfly/layout/includes/page/flink.pug
index 549b67aa..10d3893a 100644
--- a/themes/butterfly/layout/includes/page/flink.pug
+++ b/themes/butterfly/layout/includes/page/flink.pug
@@ -1,7 +1,10 @@
 #article-container
   .flink
-    - let pageContent = page.content
-    if page.flink_url
+    - let { content, random, flink_url } = page
+    - let pageContent = content
+
+    if flink_url || random
+      - const linkData = flink_url ? false : site.data.link || false
       script.
         (()=>{
           const replaceSymbol = (str) => {
@@ -9,35 +12,45 @@
           }
 
           let result = ""
-          fetch("!{url_for(page.flink_url)}")
-            .then(response => response.json())
-            .then(str => {
-              for(let i = 0; i < str.length; i++){
-                const replaceClassName = replaceSymbol(str[i].class_name)
-                const className = str[i].class_name ? `<h2 id="${replaceClassName}"><a href="#${replaceClassName}" class="headerlink" title="${str[i].class_name}"></a>${str[i].class_name}</h2>` : ""
-                const classDesc = str[i].class_desc ? `<div class="flink-desc">${str[i].class_desc}</div>` : ""
-                
-                let listResult = ""
-                const lists = str[i].link_list
-                for(let j = 0; j < lists.length; j++){
-                  listResult += `
-                    <div class="flink-list-item">
-                      <a href="${lists[j].link}" title="${lists[j].name}" target="_blank">
-                        <div class="flink-item-icon">
-                          <img class="no-lightbox" src="${lists[j].avatar}" onerror='this.onerror=null;this.src="!{url_for(theme.error_img.flink)}"' alt="${lists[j].name}" />
-                        </div>
-                        <div class="flink-item-name">${lists[j].name}</div> 
-                        <div class="flink-item-desc" title="${lists[j].descr}">${lists[j].descr}</div>
-                      </a>
-                    </div>`
-                }
+          const add = (str) => {
+            for(let i = 0; i < str.length; i++){
+              const replaceClassName = replaceSymbol(str[i].class_name)
+              const className = str[i].class_name ? `<h2 id="${replaceClassName}"><a href="#${replaceClassName}" class="headerlink" title="${str[i].class_name}"></a>${str[i].class_name}</h2>` : ""
+              const classDesc = str[i].class_desc ? `<div class="flink-desc">${str[i].class_desc}</div>` : ""
 
-                result += `${className}${classDesc} <div class="flink-list">${listResult}</div>`
+              let listResult = ""
+              const lists = str[i].link_list
+              if (!{random === true}) {
+                lists.sort(() => Math.random() - 0.5)
+              }
+              for(let j = 0; j < lists.length; j++){
+                listResult += `
+                  <div class="flink-list-item">
+                    <a href="${lists[j].link}" title="${lists[j].name}" target="_blank">
+                      <div class="flink-item-icon">
+                        <img class="no-lightbox" src="${lists[j].avatar}" onerror='this.onerror=null;this.src="!{url_for(theme.error_img.flink)}"' alt="${lists[j].name}" />
+                      </div>
+                      <div class="flink-item-name">${lists[j].name}</div> 
+                      <div class="flink-item-desc" title="${lists[j].descr}">${lists[j].descr}</div>
+                    </a>
+                  </div>`
               }
 
-              document.querySelector(".flink").insertAdjacentHTML("afterbegin", result)
-              window.lazyLoadInstance && window.lazyLoadInstance.update()
-            })
+              result += `${className}${classDesc} <div class="flink-list">${listResult}</div>`
+            }
+
+            document.querySelector(".flink").insertAdjacentHTML("afterbegin", result)
+            window.lazyLoadInstance && window.lazyLoadInstance.update()
+          }
+
+          const linkData = !{JSON.stringify(linkData)}
+          if (!{Boolean(flink_url)}) {
+            fetch("!{url_for(flink_url)}")
+              .then(response => response.json())
+              .then(add)
+          } else if (linkData) {
+            add(linkData)
+          }
         })()
 
     else
@@ -67,4 +80,3 @@
 
         - pageContent = result + pageContent
     != pageContent
-
diff --git a/themes/butterfly/layout/includes/sidebar.pug b/themes/butterfly/layout/includes/sidebar.pug
index 11bddf8c..66c67a9d 100644
--- a/themes/butterfly/layout/includes/sidebar.pug
+++ b/themes/butterfly/layout/includes/sidebar.pug
@@ -14,5 +14,5 @@
         .headline= _p('aside.categories') 
         .length-num= site.categories.length
 
-    hr
+    hr.custom-hr
     !=partial('includes/header/menu_item', {}, {cache: true})
diff --git a/themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug b/themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug
index ef4993e2..9e9aaed4 100644
--- a/themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug
+++ b/themes/butterfly/layout/includes/third-party/card-post-count/artalk.pug
@@ -2,19 +2,34 @@
 
 script.
   (() => {
-    const getArtalkCount = () => {
-      const runWidget = () => {
-        Artalk.loadCountWidget({
-          server: '!{server}',
-          site: '!{site}',
-          countEl: '.artalk-count'
+    const getArtalkCount = async() => {
+      try {
+        const eleGroup = document.querySelectorAll('#recent-posts .artalk-count')
+        const keyArray = Array.from(eleGroup).map(i => i.getAttribute('data-page-key'))
+
+        const headerList = {
+          method: 'POST',
+          headers: {
+            'Content-Type': 'application/x-www-form-urlencoded',
+            'Origin': window.location.origin
+          },
+          body: new URLSearchParams({
+            'site_name': '!{site}',
+            'type':'page_comment',
+            'page_keys': keyArray
+          })
+        }
+
+        const res = await fetch('!{server}/api/stat', headerList)
+        const result = await res.json()
+
+        keyArray.forEach((key, index) => {
+          eleGroup[index].textContent = result.data[key] || 0
         })
+      } catch (err) {
+        console.error(err)
       }
-
-      if (typeof Artalk === 'function') runWidget()
-      else getScript('!{theme.asset.artalk_js}').then(runWidget)
     }
 
-
     window.pjax ? getArtalkCount() : window.addEventListener('load', getArtalkCount)
   })()
\ No newline at end of file
diff --git a/themes/butterfly/layout/includes/third-party/card-post-count/waline.pug b/themes/butterfly/layout/includes/third-party/card-post-count/waline.pug
index e69237fa..c80da578 100644
--- a/themes/butterfly/layout/includes/third-party/card-post-count/waline.pug
+++ b/themes/butterfly/layout/includes/third-party/card-post-count/waline.pug
@@ -1,17 +1,19 @@
 script.
   (() => {
-    function loadWaline () {
-      function initWaline () {
-        let initData = {
-          el: null,
-          serverURL: '!{theme.waline.serverURL}',
-          comment: true
-        }
-        const waline = Waline.init(initData)
-      }
+    async function loadWaline () {
+      try {
+        const eleGroup = document.querySelectorAll('#recent-posts .waline-comment-count')
+        const keyArray = Array.from(eleGroup).map(i => i.getAttribute('data-path'))
 
-      if (typeof Waline === 'object') initWaline() 
-      else getScript('!{url_for(theme.asset.waline_js)}').then(initWaline)
+        const res = await fetch(`!{theme.waline.serverURL}/api/comment?type=count&url=${keyArray}`, { method: 'GET' })
+        const result = await res.json()
+        
+        result.data.forEach((count, index) => {
+          eleGroup[index].textContent = count
+        })
+      } catch (err) {
+        console.error(err)
+      }
     }
 
     window.pjax ? loadWaline() : window.addEventListener('load', loadWaline)
diff --git a/themes/butterfly/layout/includes/third-party/chat/chatra.pug b/themes/butterfly/layout/includes/third-party/chat/chatra.pug
index b6c12014..5cc7b5a9 100644
--- a/themes/butterfly/layout/includes/third-party/chat/chatra.pug
+++ b/themes/butterfly/layout/includes/third-party/chat/chatra.pug
@@ -1,33 +1,50 @@
 //- https://chatra.io/help/api/
 script.
-  (function(d, w, c) {
-      w.ChatraID = '#{theme.chatra.id}';
-      var s = d.createElement('script');
-      w[c] = w[c] || function() {
-          (w[c].q = w[c].q || []).push(arguments);
-      };
-      s.async = true;
-      s.src = 'https://call.chatra.io/chatra.js';
-      if (d.head) d.head.appendChild(s);
-  })(document, window, 'Chatra');
+  (() => {
+    const isChatBtn = !{theme.chat_btn}
+    const isChatHideShow = !{theme.chat_hide_show}
 
-  if (!{theme.chat_btn}) {
-    var chatBtnFn = () => {
-      var chatBtn = document.getElementById("chat_btn")
-      chatBtn.addEventListener("click", function(){
-        Chatra('openChat')
-      });
-    }
-    chatBtnFn()
-  } else {
-    if (!{theme.chat_hide_show}) {
-      function chatBtnHide () {
+    if (isChatBtn) {
+      const close = () => {
+        Chatra('minimizeWidget')
         Chatra('hide')
       }
-      function chatBtnShow () {
+
+      const open = () => {
+        Chatra('openChat', true)
         Chatra('show')
       }
+
+      window.ChatraSetup = {
+        startHidden: true
+      }
+    
+      window.chatBtnFn = () => {
+        const isShow = document.getElementById('chatra').classList.contains('chatra--expanded')
+        isShow ? close() : open()
+      }
+    } else if (isChatHideShow) {
+      window.chatBtn = {
+        hide: () => {
+          Chatra('hide')
+        },
+        show: () => {
+          Chatra('show')
+        }
+      }
     }
-  }
+
+    (function(d, w, c) {
+      w.ChatraID = '#{theme.chatra.id}'
+      var s = d.createElement('script')
+      w[c] = w[c] || function() {
+          (w[c].q = w[c].q || []).push(arguments)
+      }
+      s.async = true
+      s.src = 'https://call.chatra.io/chatra.js'
+      if (d.head) d.head.appendChild(s)
+    })(document, window, 'Chatra')
+
+  })()
 
 
diff --git a/themes/butterfly/layout/includes/third-party/chat/crisp.pug b/themes/butterfly/layout/includes/third-party/chat/crisp.pug
index cc57e8dd..6c8b6bf4 100644
--- a/themes/butterfly/layout/includes/third-party/chat/crisp.pug
+++ b/themes/butterfly/layout/includes/third-party/chat/crisp.pug
@@ -1,36 +1,45 @@
 script.
-  window.$crisp = [];
-  window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}";
-  (function () {
-    d = document;
-    s = d.createElement("script");
-    s.src = "https://client.crisp.chat/l.js";
-    s.async = 1;
-    d.getElementsByTagName("head")[0].appendChild(s);
-  })();
-  $crisp.push(["safe", true])
+  (() => {
+    window.$crisp = [];
+    window.CRISP_WEBSITE_ID = "!{theme.crisp.website_id}";
+    (function () {
+      d = document;
+      s = d.createElement("script");
+      s.src = "https://client.crisp.chat/l.js";
+      s.async = 1;
+      d.getElementsByTagName("head")[0].appendChild(s);
+    })();
+    $crisp.push(["safe", true])
 
-  if (!{theme.chat_btn}) {
-    $crisp.push(["do", "chat:hide"])
-    $crisp.push(["on", "chat:closed", function() {
-      $crisp.push(["do", "chat:hide"])
-    }])
-    var chatBtnFn = () => {
-      var chatBtn = document.getElementById("chat_btn")
-      chatBtn.addEventListener("click", function(){
+    const isChatBtn = !{theme.chat_btn}
+    const isChatHideShow = !{theme.chat_hide_show}
+
+    if (isChatBtn) {
+      const open = () => {
         $crisp.push(["do", "chat:show"])
         $crisp.push(["do", "chat:open"])
+      }
 
-      });
-    }
-    chatBtnFn()
-  } else {
-    if (!{theme.chat_hide_show}) {
-      function chatBtnHide () {
+      const close = () => {
         $crisp.push(["do", "chat:hide"])
       }
-      function chatBtnShow () {
-        $crisp.push(["do", "chat:show"])
+
+      close()
+      $crisp.push(["on", "chat:closed", function() {
+        close()
+      }])
+
+      window.chatBtnFn = () => {
+        $crisp.is("chat:visible") ? close() : open()
+      }
+    } else if (isChatHideShow) {
+      window.chatBtn = {
+        hide: () => {
+          $crisp.push(["do", "chat:hide"])
+        },
+        show: () => {
+          $crisp.push(["do", "chat:show"])
+        }
       }
     }
-  }
\ No newline at end of file
+  })()
\ No newline at end of file
diff --git a/themes/butterfly/layout/includes/third-party/chat/daovoice.pug b/themes/butterfly/layout/includes/third-party/chat/daovoice.pug
index 3c6b0649..5a7c33dc 100644
--- a/themes/butterfly/layout/includes/third-party/chat/daovoice.pug
+++ b/themes/butterfly/layout/includes/third-party/chat/daovoice.pug
@@ -1,40 +1,40 @@
 //- https://guide.daocloud.io/daovoice/javascript-api-5869833.html
 script.
-  (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice")
+  (() => {
+    (function(i,s,o,g,r,a,m){i["DaoVoiceObject"]=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;a.charset="utf-8";m.parentNode.insertBefore(a,m)})(window,document,"script",('https:' == document.location.protocol ? 'https:' : 'http:') + "//widget.daovoice.io/widget/!{theme.daovoice.app_id}.js","daovoice")
 
-script.
-  var isChatBtn = !{theme.chat_btn}
-  daovoice('init', {
-    app_id: '!{theme.daovoice.app_id}',},{
-    launcher: { 
-       disableLauncherIcon: isChatBtn // 悬浮 ICON 是否显示
-    },
-  });
-  daovoice('update');
+    const isChatBtn = !{theme.chat_btn}
+    const isChatHideShow = !{theme.chat_hide_show}
 
-  if (isChatBtn) {
-    var chatBtnFn = () => {
-      var chatBtn = document.getElementById("chat_btn")
-      chatBtn.addEventListener("click", function(){
-        daovoice('show')
-      });
-    }
-    chatBtnFn()
-  } else {
-    if (!{theme.chat_hide_show}) {
-      function chatBtnHide () {
-        daovoice('update', {},{
-          launcher: { 
-          disableLauncherIcon: true // 悬浮 ICON 是否显示
-          },
-        });
+    daovoice('init', {
+      app_id: '!{theme.daovoice.app_id}',},{
+      launcher: { 
+        disableLauncherIcon: isChatBtn
+      },
+    });
+    daovoice('update');
+
+    if (isChatBtn) {
+      window.chatBtnFn = () => {
+        const isShow = document.getElementById('daodream-messenger').classList.contains('daodream-messenger-active')
+        isShow ? daovoice('hide') : daovoice('show')
       }
-      function chatBtnShow () {
-        daovoice('update', {},{
-          launcher: { 
-          disableLauncherIcon: false // 悬浮 ICON 是否显示
-          },
-        });
+    } else if (isChatHideShow) {
+      window.chatBtn = {
+        hide: () => {
+          daovoice('update', {},{
+            launcher: {
+              disableLauncherIcon: true
+            }
+          })
+        },
+        show: () => {
+          daovoice('update', {}, {
+            launcher: {
+              disableLauncherIcon: false
+            }
+          })
+        }
       }
     }
-  }
\ No newline at end of file
+  })()
\ No newline at end of file
diff --git a/themes/butterfly/layout/includes/third-party/chat/messenger.pug b/themes/butterfly/layout/includes/third-party/chat/messenger.pug
index e5c9d885..3d244fc0 100644
--- a/themes/butterfly/layout/includes/third-party/chat/messenger.pug
+++ b/themes/butterfly/layout/includes/third-party/chat/messenger.pug
@@ -4,39 +4,41 @@
 #fb-customer-chat.fb-customerchat(page_id=pageID attribution='biz_inbox')
 
 script.
-  document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '<div id="fb-root"></div>')
+  (() => {
+    document.getElementById('fb-root') ? '' : document.body.insertAdjacentHTML('afterend', '<div id="fb-root"></div>')
 
-  window.fbAsyncInit = function() {
-    FB.init({
-      xfbml: true,
-      version: 'v16.0'
-    });
-  };
+    window.fbAsyncInit = function() {
+      FB.init({
+        xfbml: true,
+        version: 'v16.0'
+      });
+    };
 
-  (function(d, s, id) {
-    var js, fjs = d.getElementsByTagName(s)[0];
-    if (d.getElementById(id)) return;
-    js = d.createElement(s); js.id = id;
-    js.src = 'https://connect.facebook.net/!{lang}/sdk/xfbml.customerchat.js';
-    fjs.parentNode.insertBefore(js, fjs);
-  }(document, 'script', 'facebook-jssdk'));
+    (function(d, s, id) {
+      var js, fjs = d.getElementsByTagName(s)[0];
+      if (d.getElementById(id)) return;
+      js = d.createElement(s); js.id = id;
+      js.src = 'https://connect.facebook.net/!{lang}/sdk/xfbml.customerchat.js';
+      fjs.parentNode.insertBefore(js, fjs);
+    }(document, 'script', 'facebook-jssdk'));
 
-  if (!{theme.chat_btn}) {
-    var chatBtnFn = () => {
-      var chatBtn = document.getElementById("chat_btn")
-      chatBtn.addEventListener("click", function(){
-        FB.CustomerChat.show();
-      });
-    }
-    chatBtnFn()
-  } else {
-    if (!{theme.chat_hide_show}) {
-      function chatBtnHide () {
-        FB.CustomerChat.hide()
+    const isChatBtn = !{theme.chat_btn}
+    const isChatHideShow = !{theme.chat_hide_show}
+
+    if (isChatBtn) {
+      window.chatBtnFn = () => {
+        const isShow = document.querySelector('.fb_customer_chat_bounce_in_v2')
+        isShow ? FB.CustomerChat.hide() : FB.CustomerChat.show()
       }
-      function chatBtnShow () {
-        FB.CustomerChat.show(false)
+    } else if (isChatHideShow) {
+      window.chatBtn = {
+        hide: () => {
+          FB.CustomerChat.hide()
+        },
+        show: () => {
+          FB.CustomerChat.show(false)
+        }
       }
     }
-  }
+  })()
 
diff --git a/themes/butterfly/layout/includes/third-party/chat/tidio.pug b/themes/butterfly/layout/includes/third-party/chat/tidio.pug
index 6b0097fb..20104f53 100644
--- a/themes/butterfly/layout/includes/third-party/chat/tidio.pug
+++ b/themes/butterfly/layout/includes/third-party/chat/tidio.pug
@@ -1,41 +1,45 @@
 script(src=`//code.tidio.co/${theme.tidio.public_key}.js` async)
+script.
+  (() => {
+    const isChatBtn = !{theme.chat_btn}
+    const isChatHideShow = !{theme.chat_hide_show}
 
-if theme.chat_btn
-  script.
-    function onTidioChatApiReady() {
-      window.tidioChatApi.hide();
-      window.tidioChatApi.on("close", function() {
-        window.tidioChatApi.hide();
-      });
-    }
-    if (window.tidioChatApi) {
-      window.tidioChatApi.on("ready", onTidioChatApiReady);
-    } else {
-      document.addEventListener("tidioChat-ready", onTidioChatApiReady);
-    }
-
-    var chatBtnFn = () => {
-      document.getElementById("chat_btn").addEventListener("click", function(){
-        window.tidioChatApi.show();
-        window.tidioChatApi.open();
-      });
-    }
-    chatBtnFn()
+    if (isChatBtn) {
+      let isShow = false
+      const close = () => {
+        window.tidioChatApi.hide()
+        isShow = false
+      }
+      
+      const open = () => {
+        window.tidioChatApi.open()
+        window.tidioChatApi.show()
+        isShow = true
+      }
 
-else if theme.chat_hide_show
-  script.
-    function chatBtnHide () {
+      const onTidioChatApiReady = () => {
+        window.tidioChatApi.hide()
+        window.tidioChatApi.on("close", close)
+      }
       if (window.tidioChatApi) {
-        //- window.tidioChatApi.hide();
-        document.getElementById('tidio-chat').style.display= 'none'
+        window.tidioChatApi.on("ready", onTidioChatApiReady)
+      } else {
+        document.addEventListener("tidioChat-ready", onTidioChatApiReady)
       }
-    }
 
-    function chatBtnShow () {
-      if (window.tidioChatApi) {
-        //- window.tidioChatApi.show();
-        document.getElementById('tidio-chat').style.display= 'block'
-      } 
+      window.chatBtnFn = () => {
+        if (!window.tidioChatApi) return
+        isShow ? close() : open()
+      }
+    } else if (isChatHideShow) {
+      window.chatBtn = {
+        hide: () => {
+          window.tidioChatApi && window.tidioChatApi.hide()
+        },
+        show: () => {
+          window.tidioChatApi && window.tidioChatApi.show()
+        }
+      }
     }
-
+  })()
 
diff --git a/themes/butterfly/layout/includes/third-party/comments/artalk.pug b/themes/butterfly/layout/includes/third-party/comments/artalk.pug
index 0f7631e0..c5844ed0 100644
--- a/themes/butterfly/layout/includes/third-party/comments/artalk.pug
+++ b/themes/butterfly/layout/includes/third-party/comments/artalk.pug
@@ -23,11 +23,10 @@ script.
       })
     }
 
-    if (typeof window.artalkItem === 'object') setTimeout(()=>{initArtalk()},200)
+    if (typeof window.artalkItem === 'object') initArtalk()
     else {
       getCSS('!{theme.asset.artalk_css}').then(()=>{
-        typeof Artalk !== 'function' ? getScript('!{theme.asset.artalk_js}').then(initArtalk)
-                            : setTimeout(()=>{initArtalk()},200)
+        getScript('!{theme.asset.artalk_js}').then(initArtalk)
       })
     }
   }
diff --git a/themes/butterfly/layout/includes/third-party/comments/index.pug b/themes/butterfly/layout/includes/third-party/comments/index.pug
index 58cbd9c4..af345448 100644
--- a/themes/butterfly/layout/includes/third-party/comments/index.pug
+++ b/themes/butterfly/layout/includes/third-party/comments/index.pug
@@ -1,5 +1,5 @@
 - let defaultComment = theme.comments.use[0]
-hr
+hr.custom-hr
 #post-comment
   .comment-head
     .comment-headline
diff --git a/themes/butterfly/layout/includes/third-party/comments/waline.pug b/themes/butterfly/layout/includes/third-party/comments/waline.pug
index 29decbef..4c8204d1 100644
--- a/themes/butterfly/layout/includes/third-party/comments/waline.pug
+++ b/themes/butterfly/layout/includes/third-party/comments/waline.pug
@@ -14,13 +14,9 @@ script.
       }, !{JSON.stringify(option)}))
     }
 
-    const walineCSSLoad = document.getElementById('waline-css')
-
-    if (typeof Waline === 'object') {
-      walineCSSLoad ? initWaline() : getCSS('!{url_for(theme.asset.waline_css)}','waline-css').then(initWaline)
-    }
+    if (typeof Waline === 'object') initWaline()
     else {
-      getCSS('!{url_for(theme.asset.waline_css)}','waline-css').then(() => {
+      getCSS('!{url_for(theme.asset.waline_css)}').then(() => {
         getScript('!{url_for(theme.asset.waline_js)}').then(initWaline)
       })
       getCSS('!{url_for(theme.asset.waline_meta_css)}')
diff --git a/themes/butterfly/layout/includes/third-party/math/mathjax.pug b/themes/butterfly/layout/includes/third-party/math/mathjax.pug
index e1734b7b..470aa451 100644
--- a/themes/butterfly/layout/includes/third-party/math/mathjax.pug
+++ b/themes/butterfly/layout/includes/third-party/math/mathjax.pug
@@ -3,7 +3,7 @@ script.
   if (!window.MathJax) {
     window.MathJax = {
       tex: {
-        inlineMath: [ ['$','$'], ["\\(","\\)"]],
+        inlineMath: [['$', '$'], ['\\(', '\\)']],
         tags: 'ams'
       },
       chtml: {
@@ -21,16 +21,7 @@ script.
               math.end = {node: text, delim: '', n: 0}
               doc.math.push(math)
             }
-          }, ''],
-          insertScript: [200, () => {
-            document.querySelectorAll('mjx-container').forEach(node => {
-              if (node.hasAttribute('display')) {
-                btf.wrap(node, 'div', { class: 'mathjax-overflow' })
-              } else {
-                btf.wrap(node, 'span', { class: 'mathjax-overflow' })
-              }
-            });
-          }, '', false]
+          }, '']
         }
       }
     }
diff --git a/themes/butterfly/layout/includes/third-party/math/mermaid.pug b/themes/butterfly/layout/includes/third-party/math/mermaid.pug
index 3222a4a4..119a5dd5 100644
--- a/themes/butterfly/layout/includes/third-party/math/mermaid.pug
+++ b/themes/butterfly/layout/includes/third-party/math/mermaid.pug
@@ -1,30 +1,38 @@
 script.
   (() => {
-    const $mermaidWrap = document.querySelectorAll('#article-container .mermaid-wrap')
-    if ($mermaidWrap.length) {
-      window.runMermaid = () => {
-        window.loadMermaid = true
-        const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}'
-
-        Array.from($mermaidWrap).forEach((item, index) => {
-          const mermaidSrc = item.firstElementChild
-          const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n'
-          const mermaidID = 'mermaid-' + index
-          const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
-          mermaid.mermaidAPI.render(mermaidID, mermaidDefinition, (svgCode) => {
-            mermaidSrc.insertAdjacentHTML('afterend', svgCode)
+    const $mermaid = document.querySelectorAll('#article-container .mermaid-wrap')
+    if ($mermaid.length === 0) return
+    const runMermaid = () => {
+      window.loadMermaid = true
+      const theme = document.documentElement.getAttribute('data-theme') === 'dark' ? '!{theme.mermaid.theme.dark}' : '!{theme.mermaid.theme.light}'
+
+      Array.from($mermaid).forEach((item, index) => {
+        const mermaidSrc = item.firstElementChild
+        const mermaidThemeConfig = '%%{init:{ \'theme\':\'' + theme + '\'}}%%\n'
+        const mermaidID = 'mermaid-' + index
+        const mermaidDefinition = mermaidThemeConfig + mermaidSrc.textContent
+
+        const renderFn = mermaid.render(mermaidID, mermaidDefinition)
+
+        const renderV10 = () => {
+          renderFn.then(({svg}) => {
+            mermaidSrc.insertAdjacentHTML('afterend', svg)
           })
-        })
-      }
+        }
 
-      const loadMermaid = () => {
-        window.loadMermaid ? runMermaid() : getScript('!{url_for(theme.asset.mermaid)}').then(runMermaid)
-      }
+        const renderV9 = svg => {
+          mermaidSrc.insertAdjacentHTML('afterend', svg)
+        }
 
-      btf.addModeChange('mermaid', () => {
-        window.runMermaid()
+        typeof renderFn === 'string' ? renderV9(renderFn) : renderV10()
       })
+    }
 
-      window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
+    const loadMermaid = () => {
+      window.loadMermaid ? runMermaid() : getScript('!{url_for(theme.asset.mermaid)}').then(runMermaid)
     }
+
+    btf.addModeChange('mermaid', runMermaid)
+
+    window.pjax ? loadMermaid() : document.addEventListener('DOMContentLoaded', loadMermaid)
   })()
\ No newline at end of file
diff --git a/themes/butterfly/layout/includes/third-party/newest-comments/artalk.pug b/themes/butterfly/layout/includes/third-party/newest-comments/artalk.pug
index ccbc9466..e2e83bac 100644
--- a/themes/butterfly/layout/includes/third-party/newest-comments/artalk.pug
+++ b/themes/butterfly/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.default
+- const avatarDefault = option !== null && option.gravatar && (option.gravatar.params || option.gravatar.default)
 
 script.
   window.addEventListener('load', () => {
@@ -72,11 +72,13 @@ script.
         const res = await fetch('!{server}/api/stat', headerList)
         const result = await res.json()
         const avatarStr = await getSetting()
-        const avatarCdn = !{avatarCdn} || avatarStr.data.frontend_conf.gravatar.mirror
-        const avatarDefault = !{avatarDefault} || avatarStr.data.frontend_conf.gravatar.default
+        const { mirror, params, default:defaults } = avatarStr.data.frontend_conf.gravatar
+        const avatarCdn = !{avatarCdn} || mirror
+        let avatarDefault = !{avatarDefault} || params || defaults
+        avatarDefault = avatarDefault.startsWith('d=') ? avatarDefault : `d=${avatarDefault}`
         const artalk = result.data.map(function (e) {
           return {
-            'avatar': `${avatarCdn}${e.email_encrypted}?d=${avatarDefault}`,
+            'avatar': `${avatarCdn}${e.email_encrypted}?${avatarDefault}`,
             'content': changeContent(e.content_marked),
             'nick': e.nick,
             'url': e.page_url,
diff --git a/themes/butterfly/layout/includes/third-party/newest-comments/waline.pug b/themes/butterfly/layout/includes/third-party/newest-comments/waline.pug
index 95d17bb3..00a72d5f 100644
--- a/themes/butterfly/layout/includes/third-party/newest-comments/waline.pug
+++ b/themes/butterfly/layout/includes/third-party/newest-comments/waline.pug
@@ -1,6 +1,6 @@
 script.
   window.addEventListener('load', () => {
-    const changeContent = (content) => {
+    const changeContent = content => {
       if (content === '') return content
 
       content = content.replace(/<img.*?src="(.*?)"?[^\>]+>/ig, '[!{_p("aside.card_newest_comments.image")}]') // replace image link
@@ -41,31 +41,26 @@ script.
       window.pjax && window.pjax.refresh($dom)
     }
 
-    const getComment = () => {
-      const loadWaline = () => {
-        Waline.RecentComments({
-          serverURL: '!{theme.waline.serverURL}',
-          count: !{theme.newest_comments.limit}
-        }).then(({comments}) => {
-          const walineArray = comments.map(e => {
-            return {
-              'content': changeContent(e.comment),
-              'avatar': e.avatar,
-              'nick': e.nick,
-              'url': e.url + '#' + e.objectId,
-              'date': e.insertedAt,
-            }
-          })
-          saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.newest_comments.storage}/(60*24))
-          generateHtml(walineArray)
-        }).catch(e => {
-          const $dom = document.querySelector('#card-newest-comments .aside-list')
-          $dom.textContent= "!{_p('aside.card_newest_comments.error')}"
-        }) 
+    const getComment = async () => {
+      try {
+        const res = await fetch('!{theme.waline.serverURL}/api/comment?type=recent&count=!{theme.newest_comments.limit}', { method: 'GET' })
+        const result = await res.json()
+        const walineArray = result.data.map(e => {
+          return {
+            'content': changeContent(e.comment),
+            'avatar': e.avatar,
+            'nick': e.nick,
+            'url': e.url + '#' + e.objectId,
+            'date': e.time || e.insertedAt
+          }
+        })
+        saveToLocal.set('waline-newest-comments', JSON.stringify(walineArray), !{theme.newest_comments.storage}/(60*24))
+        generateHtml(walineArray)
+      } catch (err) {
+        console.error(err)
+        const $dom = document.querySelector('#card-newest-comments .aside-list')
+        $dom.textContent= "!{_p('aside.card_newest_comments.error')}"
       }
-
-      if (typeof Waline === 'object') loadWaline()
-      else getScript('!{url_for(theme.asset.waline_js)}').then(loadWaline)
     }
 
     const newestCommentInit = () => {
diff --git a/themes/butterfly/layout/includes/third-party/pjax.pug b/themes/butterfly/layout/includes/third-party/pjax.pug
index 24549d42..c368bd9f 100644
--- a/themes/butterfly/layout/includes/third-party/pjax.pug
+++ b/themes/butterfly/layout/includes/third-party/pjax.pug
@@ -62,7 +62,6 @@ script.
 
     GLOBAL_CONFIG.islazyload && window.lazyLoadInstance.update()
 
-    typeof chatBtnFn === 'function' && chatBtnFn()
     typeof panguInit === 'function' && panguInit()
 
     // google analytics
diff --git a/themes/butterfly/layout/includes/third-party/subtitle.pug b/themes/butterfly/layout/includes/third-party/subtitle.pug
index c409b586..0b4f6cc9 100644
--- a/themes/butterfly/layout/includes/third-party/subtitle.pug
+++ b/themes/butterfly/layout/includes/third-party/subtitle.pug
@@ -86,7 +86,7 @@ case source
         if (!{effect}) {
           typedJSFn.init(!{JSON.stringify(subContent)})
         } else {
-          document.getElementById("subtitle").textContent = '!{subContent[0]}'
+          document.getElementById("subtitle").textContent = !{JSON.stringify(subContent[0])}
         }
       }
       typedJSFn.run(subtitleType)
\ No newline at end of file
diff --git a/themes/butterfly/layout/includes/widget/card_author.pug b/themes/butterfly/layout/includes/widget/card_author.pug
index de71edb8..0a1e71ae 100644
--- a/themes/butterfly/layout/includes/widget/card_author.pug
+++ b/themes/butterfly/layout/includes/widget/card_author.pug
@@ -24,4 +24,4 @@ if theme.aside.card_author.enable
   
     if(theme.social)
         .card-info-social-icons.is-center
-          !=fragment_cache('social', function(){return partial('includes/header/social')}) 
+          !=partial('includes/header/social', {}, {cache: true})
diff --git a/themes/butterfly/layout/includes/widget/card_newest_comment.pug b/themes/butterfly/layout/includes/widget/card_newest_comment.pug
index 44f23119..078f9784 100644
--- a/themes/butterfly/layout/includes/widget/card_newest_comment.pug
+++ b/themes/butterfly/layout/includes/widget/card_newest_comment.pug
@@ -1,4 +1,4 @@
-if theme.newest_comments.enable && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0])
+if theme.newest_comments.enable && theme.comments.use && !['Livere','Facebook Comments','Giscus'].includes(theme.comments.use[0])
   .card-widget#card-newest-comments
     .item-headline
       i.fa-solid.fa-comment-dots
diff --git a/themes/butterfly/package.json b/themes/butterfly/package.json
index feeec136..6e97de22 100644
--- a/themes/butterfly/package.json
+++ b/themes/butterfly/package.json
@@ -1,6 +1,6 @@
 {
   "name": "hexo-theme-butterfly",
-  "version": "4.8.5",
+  "version": "4.9.0",
   "description": "A Simple and Card UI Design theme for Hexo",
   "main": "package.json",
   "scripts": {
diff --git a/themes/butterfly/plugins.yml b/themes/butterfly/plugins.yml
index 8a8bf1d6..82321722 100644
--- a/themes/butterfly/plugins.yml
+++ b/themes/butterfly/plugins.yml
@@ -1,11 +1,11 @@
 algolia_search:
   name: algoliasearch
   file: dist/algoliasearch-lite.umd.js
-  version: 4.17.0
+  version: 4.17.1
 instantsearch:
   name: instantsearch.js
   file: dist/instantsearch.production.min.js
-  version: 4.55.0
+  version: 4.56.1
 pjax:
   name: pjax
   file: pjax.min.js
@@ -78,7 +78,7 @@ katex_copytex:
 mermaid:
   name: mermaid
   file: dist/mermaid.min.js
-  version: 9.4.3
+  version: 10.2.2
 canvas_ribbon:
   name: butterfly-extsrc
   file: dist/canvas-ribbon.min.js
@@ -126,12 +126,12 @@ pangu:
 fancybox_css:
   name: '@fancyapps/ui'
   file: dist/fancybox/fancybox.css
-  version: 5.0.17
+  version: 5.0.19
   other_name: fancyapps-ui
 fancybox:
   name: '@fancyapps/ui'
   file: dist/fancybox/fancybox.umd.js
-  version: 5.0.17
+  version: 5.0.19
   other_name: fancyapps-ui
 medium_zoom:
   name: medium-zoom
@@ -188,11 +188,11 @@ prismjs_autoloader:
 artalk_js:
   name: artalk
   file: dist/Artalk.js
-  version: 2.5.4
+  version: 2.5.5
 artalk_css:
   name: artalk
   file: dist/Artalk.css
-  version: 2.5.4
+  version: 2.5.5
 pace_js:
   name: pace-js
   other_name: pace
@@ -211,12 +211,12 @@ docsearch_js:
   name: '@docsearch/js'
   other_name: docsearch-js
   file: dist/umd/index.js
-  version: 3.3.5
+  version: 3.4.0
 docsearch_css:
   name: '@docsearch/css'
   other_name: docsearch-css
   file: dist/style.css
-  version: 3.3.5
+  version: 3.4.0
 abcjs_basic_js:
   name: abcjs
   file: dist/abcjs-basic-min.js
diff --git a/themes/butterfly/scripts/events/init.js b/themes/butterfly/scripts/events/init.js
index 1bd0570d..36304d89 100644
--- a/themes/butterfly/scripts/events/init.js
+++ b/themes/butterfly/scripts/events/init.js
@@ -1,21 +1,19 @@
 hexo.extend.filter.register('before_generate', () => {
   // Get first two digits of the Hexo version number
-  const hexoVer = hexo.version.replace(/(^.*\..*)\..*/, '$1')
-  const logger = hexo.log
+  const { version, log, locals } = hexo
+  const hexoVer = version.replace(/(^.*\..*)\..*/, '$1')
 
   if (hexoVer < 5.3) {
-    logger.error('Please update Hexo to V5.3.0 or higher!')
-    logger.error('請把 Hexo 升級到 V5.3.0 或更高的版本!')
+    log.error('Please update Hexo to V5.3.0 or higher!')
+    log.error('請把 Hexo 升級到 V5.3.0 或更高的版本!')
     process.exit(-1)
   }
 
-  if (hexo.locals.get) {
-    const data = hexo.locals.get('data')
+  if (locals.get) {
+    const data = locals.get('data')
     if (data && data.butterfly) {
-      logger.error(
-        " 'butterfly.yml' is deprecated. Please use '_config.butterfly.yml' "
-      )
-      logger.error(" 'butterfly.yml' 已經棄用,請使用 '_config.butterfly.yml' ")
+      log.error("'butterfly.yml' is deprecated. Please use '_config.butterfly.yml'")
+      log.error("'butterfly.yml' 已經棄用,請使用 '_config.butterfly.yml'")
       process.exit(-1)
     }
   }
diff --git a/themes/butterfly/source/css/_global/function.styl b/themes/butterfly/source/css/_global/function.styl
index 21539ce5..57828126 100644
--- a/themes/butterfly/source/css/_global/function.styl
+++ b/themes/butterfly/source/css/_global/function.styl
@@ -72,6 +72,30 @@
       cursor: pointer
       transition: all .3s ease-out
 
+.custom-hr
+  position: relative
+  margin: 40px auto
+  border: 2px dashed var(--hr-border)
+
+  if hexo-config('hr_icon.enable')
+    width: calc(100% - 4px)
+
+    &:hover
+      &:before
+        left: calc(95% - 20px)
+
+    &:before
+      position: absolute
+      top: $hr-icon-top
+      left: 5%
+      z-index: 1
+      color: var(--hr-before-color)
+      content: $hr-icon
+      font-size: 20px
+      line-height: 1
+      transition: all 1s ease-in-out
+      @extend .fontawesomeIcon
+
 maxWidth600()
   @media screen and (max-width: 600px)
     {block}
diff --git a/themes/butterfly/source/css/_global/index.styl b/themes/butterfly/source/css/_global/index.styl
index b9933fe7..8bb57c71 100644
--- a/themes/butterfly/source/css/_global/index.styl
+++ b/themes/butterfly/source/css/_global/index.styl
@@ -34,6 +34,8 @@
   --headline-presudo: #a0a0a0
   --scrollbar-color: $scrollbar-color
   --default-bg-color: $theme-color
+  --zoom-bg: #fff
+  --mark-bg: alpha($dark-black, .3)
 
 body
   position: relative
@@ -96,30 +98,6 @@ h6
 *
   box-sizing: border-box
 
-hr
-  position: relative
-  margin: 40px auto
-  border: 2px dashed var(--hr-border)
-
-  if hexo-config('hr_icon.enable')
-    width: calc(100% - 4px)
-
-    &:hover
-      &:before
-        left: calc(95% - 20px)
-
-    &:before
-      position: absolute
-      top: $hr-icon-top
-      left: 5%
-      z-index: 1
-      color: var(--hr-before-color)
-      content: $hr-icon
-      font-size: 20px
-      line-height: 1
-      transition: all 1s ease-in-out
-      @extend .fontawesomeIcon
-
 .table-wrap
   overflow-x: scroll
   margin: 0 0 20px
diff --git a/themes/butterfly/source/css/_layout/footer.styl b/themes/butterfly/source/css/_layout/footer.styl
index 55cbc8c1..e398510b 100644
--- a/themes/butterfly/source/css/_layout/footer.styl
+++ b/themes/butterfly/source/css/_layout/footer.styl
@@ -5,12 +5,12 @@
   background-position: bottom
   background-size: cover
 
-  if hexo-config('footer_bg') != false
+  if hexo-config('footer_bg') != false && hexo-config('mask.footer')
     &:before
       position: absolute
       width: 100%
       height: 100%
-      background-color: alpha($dark-black, .5)
+      background-color: var(--mark-bg)
       content: ''
 
 #footer-wrap
diff --git a/themes/butterfly/source/css/_layout/head.styl b/themes/butterfly/source/css/_layout/head.styl
index 431905e2..d294d4e1 100644
--- a/themes/butterfly/source/css/_layout/head.styl
+++ b/themes/butterfly/source/css/_layout/head.styl
@@ -7,12 +7,13 @@
   background-repeat: no-repeat
   transition: all .5s
 
-  &:not(.not-top-img):before
-    position: absolute
-    width: 100%
-    height: 100%
-    background-color: alpha($dark-black, .3)
-    content: ''
+  if hexo-config('mask.header')
+    &:not(.not-top-img):before
+      position: absolute
+      width: 100%
+      height: 100%
+      background-color: var(--mark-bg)
+      content: ''
 
   // index
   &.full_page
@@ -97,9 +98,6 @@
     +maxWidth768()
       height: 360px
 
-    &:before
-      background-color: alpha($dark-black, .5)
-
   #post-info
     position: absolute
     bottom: 100px
diff --git a/themes/butterfly/source/css/_layout/post.styl b/themes/butterfly/source/css/_layout/post.styl
index 23755910..585f7fe9 100644
--- a/themes/butterfly/source/css/_layout/post.styl
+++ b/themes/butterfly/source/css/_layout/post.styl
@@ -65,6 +65,9 @@ beautify()
 
   ul > li
     list-style-type: circle
+  
+  hr
+    @extend .custom-hr
 
 #article-container
   word-wrap: break-word
@@ -156,14 +159,6 @@ beautify()
     else if hexo-config('beautify.field') == 'post'
       &.post-content
         beautify()
-  else
-    hr
-      margin: 20px 0
-      border: 1px inset
-      width 100%
-
-      &:before
-        content: none
 
 #post
   .tag_share
diff --git a/themes/butterfly/source/css/_layout/third-party.styl b/themes/butterfly/source/css/_layout/third-party.styl
index ecdf26e2..550d1760 100644
--- a/themes/butterfly/source/css/_layout/third-party.styl
+++ b/themes/butterfly/source/css/_layout/third-party.styl
@@ -82,15 +82,22 @@ if hexo-config('waline.bg')
       display: none
 
 // Mathjax
-.mathjax-overflow
+mjx-container
   overflow-x: auto
   overflow-y: hidden
-
-span.mathjax-overflow
-  display: inline-block
-  padding: 0 2px
+  padding-bottom: 4px
   max-width: 100%
-  vertical-align: bottom
+
+  &[display]
+    display: block !important
+    min-width: auto !important
+
+  &:not([display])
+    display: inline-grid !important
+
+mjx-assistive-mml
+  right: 0
+  bottom: 0
 
 .aplayer
   color: $font-black
diff --git a/themes/butterfly/source/css/_mode/darkmode.styl b/themes/butterfly/source/css/_mode/darkmode.styl
index a432d6bb..998ff812 100644
--- a/themes/butterfly/source/css/_mode/darkmode.styl
+++ b/themes/butterfly/source/css/_mode/darkmode.styl
@@ -38,10 +38,10 @@ if hexo-config('darkmode.enable') || hexo-config('display_mode') == 'dark'
     --hlexpand-bg: linear-gradient(180deg, rgba(lighten(#121212, 2), .6), rgba(lighten(#121212, 2), .9))
     --scrollbar-color: lighten(#121212, 5)
     --timeline-bg: lighten(#121212, 5)
+    --zoom-bg: #121212
+    --mark-bg: alpha($dark-black, .6)
 
-    #web_bg:before,
-    #footer:before,
-    #page-header:before
+    #web_bg:before
       position: absolute
       width: 100%
       height: 100%
diff --git a/themes/butterfly/source/css/_mode/readmode.styl b/themes/butterfly/source/css/_mode/readmode.styl
index 4e50c54a..2090e27e 100644
--- a/themes/butterfly/source/css/_mode/readmode.styl
+++ b/themes/butterfly/source/css/_mode/readmode.styl
@@ -54,8 +54,7 @@ if hexo-config('readmode')
       display: none
 
     #page-header.post-bg
-      background-color: transparent
-      background-image: none !important
+      background: none !important
 
       &:before
         opacity: 0
diff --git a/themes/butterfly/source/css/_page/common.styl b/themes/butterfly/source/css/_page/common.styl
index 0be8e498..32096a5d 100644
--- a/themes/butterfly/source/css/_page/common.styl
+++ b/themes/butterfly/source/css/_page/common.styl
@@ -18,7 +18,7 @@
     padding: 20px 5px
 
   +minWidth2000()
-    max-width: 1700px
+    max-width: 70%
 
   & > div:first-child:not(.recent-posts)
     @extend .cardHover
diff --git a/themes/butterfly/source/css/_page/homepage.styl b/themes/butterfly/source/css/_page/homepage.styl
index 6beba318..9269f972 100644
--- a/themes/butterfly/source/css/_page/homepage.styl
+++ b/themes/butterfly/source/css/_page/homepage.styl
@@ -8,7 +8,7 @@
     flex-direction: row
     align-items: center
     overflow: hidden
-    height: 18em
+    height: 16.8em
 
     +maxWidth768()
       flex-direction: column
@@ -24,7 +24,7 @@
 
     .post_cover
       overflow: hidden
-      width: 44%
+      width: 42%
       height: 100%
 
       +maxWidth768()
@@ -42,7 +42,7 @@
 
     & >.recent-post-info
       padding: 0 40px
-      width: 57%
+      width: 58%
 
       +maxWidth768()
         padding: 20px 20px 30px
@@ -57,7 +57,7 @@
       & > .article-title
         @extend .limit-more-line
         color: var(--text-highlight-color)
-        font-size: 1.72em
+        font-size: 1.55em
         line-height: 1.4
         transition: all .2s ease-in-out
         -webkit-line-clamp: 2
@@ -71,7 +71,7 @@
       & > .article-meta-wrap
         margin: 6px 0
         color: $theme-meta-color
-        font-size: 90%
+        font-size: .9em
 
         & > .post-meta-date
           cursor: default
diff --git a/themes/butterfly/source/css/_search/index.styl b/themes/butterfly/source/css/_search/index.styl
index 93d6ad89..669428b6 100644
--- a/themes/butterfly/source/css/_search/index.styl
+++ b/themes/butterfly/source/css/_search/index.styl
@@ -38,6 +38,10 @@
 
       &:hover
         color: $search-color
+  
+  hr
+    margin: 20px auto
+    @extend .custom-hr
 
 #search-mask
   position: fixed
@@ -47,4 +51,10 @@
   left: 0
   z-index: 1000
   display: none
-  background: rgba($dark-black, .6)
\ No newline at end of file
+  background: rgba($dark-black, .6)
+
+if hexo-config('algolia_search.enable')
+  @require 'algolia'
+
+if hexo-config('local_search.enable')
+  @require 'local-search'
\ No newline at end of file
diff --git a/themes/butterfly/source/css/index.styl b/themes/butterfly/source/css/index.styl
index 4ea1298b..57e7ca8f 100644
--- a/themes/butterfly/source/css/index.styl
+++ b/themes/butterfly/source/css/index.styl
@@ -15,10 +15,4 @@ if hexo-config('css_prefix')
 @import '_mode/*'
 
 // search
-if hexo-config('algolia_search.enable')
-  @import '_search/index'
-  @import '_search/algolia'
-
-if hexo-config('local_search') && hexo-config('local_search.enable')
-  @import '_search/index'
-  @import '_search/local-search'
+@import '_search/index'
\ No newline at end of file
diff --git a/themes/butterfly/source/js/main.js b/themes/butterfly/source/js/main.js
index e98ed032..4e503502 100644
--- a/themes/butterfly/source/js/main.js
+++ b/themes/butterfly/source/js/main.js
@@ -301,8 +301,7 @@ document.addEventListener('DOMContentLoaded', function () {
     let initTop = 0
     let isChatShow = true
     const $header = document.getElementById('page-header')
-    const isChatBtnHide = typeof chatBtnHide === 'function'
-    const isChatBtnShow = typeof chatBtnShow === 'function'
+    const isChatBtn = typeof chatBtn !== 'undefined'
     const isShowPercent = GLOBAL_CONFIG.percent.rightside
 
     // 當滾動條小于 56 的時候
@@ -324,14 +323,14 @@ document.addEventListener('DOMContentLoaded', function () {
       if (currentTop > 56) {
         if (isDown) {
           if ($header.classList.contains('nav-visible')) $header.classList.remove('nav-visible')
-          if (isChatBtnShow && isChatShow === true) {
-            chatBtnHide()
+          if (isChatBtn && isChatShow === true) {
+            window.chatBtn.hide()
             isChatShow = false
           }
         } else {
           if (!$header.classList.contains('nav-visible')) $header.classList.add('nav-visible')
-          if (isChatBtnHide && isChatShow === false) {
-            chatBtnShow()
+          if (isChatBtn && isChatShow === false) {
+            window.chatBtn.show()
             isChatShow = true
           }
         }
@@ -545,10 +544,12 @@ document.addEventListener('DOMContentLoaded', function () {
       saveToLocal.set('aside-status', saveStatus, 2)
       $htmlDom.toggle('hide-aside')
     },
-
     runMobileToc: () => {
       if (window.getComputedStyle(document.getElementById('card-toc')).getPropertyValue('opacity') === '0') window.mobileToc.open()
       else window.mobileToc.close()
+    },
+    toggleChatDisplay: () => {
+      window.chatBtnFn()
     }
   }
 
@@ -573,6 +574,9 @@ document.addEventListener('DOMContentLoaded', function () {
       case 'hide-aside-btn':
         rightSideFn.hideAsideBtn()
         break
+      case 'chat-btn':
+        rightSideFn.toggleChatDisplay()
+        break
       default:
         break
     }
diff --git a/themes/butterfly/source/js/utils.js b/themes/butterfly/source/js/utils.js
index 253c8ad8..adff39ca 100644
--- a/themes/butterfly/source/js/utils.js
+++ b/themes/butterfly/source/js/utils.js
@@ -186,10 +186,9 @@ const btf = {
   },
 
   unwrap: el => {
-    const elParentNode = el.parentNode
-    if (elParentNode !== document.body) {
-      elParentNode.parentNode.insertBefore(el, elParentNode)
-      elParentNode.parentNode.removeChild(elParentNode)
+    const parent = el.parentNode
+    if (parent && parent !== document.body) {
+      parent.replaceChild(el, parent)
     }
   },
 
@@ -211,13 +210,7 @@ const btf = {
     const service = GLOBAL_CONFIG.lightbox
 
     if (service === 'mediumZoom') {
-      const zoom = mediumZoom(ele)
-      zoom.on('open', e => {
-        const photoBg = document.documentElement.getAttribute('data-theme') === 'dark' ? '#121212' : '#fff'
-        zoom.update({
-          background: photoBg
-        })
-      })
+      mediumZoom(ele, { background: 'var(--zoom-bg)' })
     }
 
     if (service === 'fancybox') {