From 08e8327c7b290094390aed4bc2ad3c0e0717f8b3 Mon Sep 17 00:00:00 2001
From: Wcowin <1135801806@qq.com>
Date: Tue, 3 Jun 2025 15:11:05 +0800
Subject: [PATCH] 25/6/3
---
.../plugin/git-committers/page-authors.json | 2 +-
docs/blog/index.md | 1 +
docs/blog/posts/update2025.md | 2 +-
.../__pycache__/ai_summary.cpython-311.pyc | Bin 0 -> 18473 bytes
.../__pycache__/reading_time.cpython-311.pyc | Bin 0 -> 10341 bytes
.../__pycache__/socialmedia.cpython-311.pyc | Bin 0 -> 1347 bytes
docs/overrides/hooks/ai_summary.py | 393 +
docs/overrides/hooks/reading_time.py | 255 +
mkdocs.yml | 4 +-
.../13352c45213bc8b828bab035a8bdf5b8.json | 6 +
.../1b4e1af979077c14c74bbed4bef9c267.json | 6 +
.../277b36310e56b2d1abf896f3be1decbe.json | 6 +
.../3d9da43a479c2f295e2ac1fd9b1d4145.json | 6 +
.../41af14f53464f96f48f956e0a80c7fac.json | 6 +
.../5babf7c4c0d88d50ac56ea5a64bece7f.json | 6 +
.../63c53d3efcef0bbfa3517cc57124ea22.json | 6 +
.../676d241d1f71cee7979d1437ab409429.json | 6 +
.../6e3557e004b1983d54297433aa07fe32.json | 6 +
.../7312994b59876da56cecf87e6ce38b89.json | 6 +
.../77612039e8879ec0a34732497e4d927b.json | 6 +
.../78377a142b37e49176adad2a7dc5ea03.json | 6 +
.../88d3fe972a711ac574cdb224f89be6f8.json | 6 +
.../89458e1939eedd5696536b60dff41f99.json | 6 +
.../93960e1d1b82fdcade6022ecf95972c4.json | 6 +
.../ab758b5aa76ff31704c3afef8781f32b.json | 6 +
.../b4fdcb1514d03b4a0bfa36bce929faae.json | 6 +
.../bd5eaaa9ad0f9655b0296602b3e4df7d.json | 6 +
.../c8088321e603b20469a9826a88748350.json | 6 +
.../cb9d4d1856da4475fdde51c070fbc24d.json | 6 +
.../cee9dfb7bfb56fa9e63e493a418499c3.json | 6 +
.../d117ae5382dbad25458d5b090dcb8c42.json | 6 +
site/404.html | 451 ++
site/CNAME | 1 +
site/ZH-TW/index.html | 2842 +++++++
site/about/assets/stylesheets/portfolio.css | 577 ++
site/about/geren/index.html | 3171 ++++++++
site/about/resume/index.html | 2718 +++++++
site/about/sty/portfolio.css | 596 ++
site/about/test/index.html | 3845 ++++++++++
site/about/zcw/index.html | 2945 ++++++++
site/about/个人简历.pdf | Bin 0 -> 311614 bytes
site/assets/images/favicon.png | Bin 0 -> 1870 bytes
.../assets/javascripts/bundle.13a4f30d.min.js | 16 +
.../javascripts/bundle.13a4f30d.min.js.map | 7 +
.../javascripts/lunr/min/lunr.ar.min.js | 1 +
.../javascripts/lunr/min/lunr.da.min.js | 18 +
.../javascripts/lunr/min/lunr.de.min.js | 18 +
.../javascripts/lunr/min/lunr.du.min.js | 18 +
.../javascripts/lunr/min/lunr.el.min.js | 1 +
.../javascripts/lunr/min/lunr.es.min.js | 18 +
.../javascripts/lunr/min/lunr.fi.min.js | 18 +
.../javascripts/lunr/min/lunr.fr.min.js | 18 +
.../javascripts/lunr/min/lunr.he.min.js | 1 +
.../javascripts/lunr/min/lunr.hi.min.js | 1 +
.../javascripts/lunr/min/lunr.hu.min.js | 18 +
.../javascripts/lunr/min/lunr.hy.min.js | 1 +
.../javascripts/lunr/min/lunr.it.min.js | 18 +
.../javascripts/lunr/min/lunr.ja.min.js | 1 +
.../javascripts/lunr/min/lunr.jp.min.js | 1 +
.../javascripts/lunr/min/lunr.kn.min.js | 1 +
.../javascripts/lunr/min/lunr.ko.min.js | 1 +
.../javascripts/lunr/min/lunr.multi.min.js | 1 +
.../javascripts/lunr/min/lunr.nl.min.js | 18 +
.../javascripts/lunr/min/lunr.no.min.js | 18 +
.../javascripts/lunr/min/lunr.pt.min.js | 18 +
.../javascripts/lunr/min/lunr.ro.min.js | 18 +
.../javascripts/lunr/min/lunr.ru.min.js | 18 +
.../javascripts/lunr/min/lunr.sa.min.js | 1 +
.../lunr/min/lunr.stemmer.support.min.js | 1 +
.../javascripts/lunr/min/lunr.sv.min.js | 18 +
.../javascripts/lunr/min/lunr.ta.min.js | 1 +
.../javascripts/lunr/min/lunr.te.min.js | 1 +
.../javascripts/lunr/min/lunr.th.min.js | 1 +
.../javascripts/lunr/min/lunr.tr.min.js | 18 +
.../javascripts/lunr/min/lunr.vi.min.js | 1 +
.../javascripts/lunr/min/lunr.zh.min.js | 1 +
site/assets/javascripts/lunr/tinyseg.js | 206 +
site/assets/javascripts/lunr/wordcut.js | 6708 +++++++++++++++++
.../workers/search.d50fe291.min.js | 42 +
.../workers/search.d50fe291.min.js.map | 7 +
site/assets/stylesheets/main.342714a4.min.css | 1 +
.../stylesheets/main.342714a4.min.css.map | 1 +
.../stylesheets/palette.06af60db.min.css | 1 +
.../stylesheets/palette.06af60db.min.css.map | 1 +
site/blog/2021/12/18/博客文章测试/index.html | 2818 +++++++
.../2022/06/06/2022网站更新记录/index.html | 2897 +++++++
.../2023/12/21/2023网站更新记录/index.html | 3080 ++++++++
.../2024/01/01/2024网站更新记录/index.html | 3298 ++++++++
.../2025/01/01/2025网站更新记录/index.html | 3033 ++++++++
site/blog/MIT/index.html | 2759 +++++++
site/blog/Mkdocs/mkdocs1/index.html | 3120 ++++++++
site/blog/Mkdocs/mkdocs2/index.html | 4399 +++++++++++
site/blog/Mkdocs/mkdocs3/index.html | 2767 +++++++
site/blog/Mkdocs/mkdocsblog/index.html | 2810 +++++++
site/blog/Mkdocs/mkfirst/index.html | 3006 ++++++++
site/blog/archive/2021/index.html | 2617 +++++++
site/blog/archive/2022/index.html | 2636 +++++++
site/blog/archive/2023/index.html | 2729 +++++++
site/blog/archive/2024/index.html | 2857 +++++++
site/blog/archive/2025/index.html | 2695 +++++++
site/blog/category/hello-world/index.html | 2617 +++++++
site/blog/category/网站更新记录/index.html | 3192 ++++++++
site/blog/index.html | 3249 ++++++++
site/blog/websitebeauty/404/index.html | 3933 ++++++++++
.../websitebeauty/Relativeaddress/index.html | 2969 ++++++++
site/blog/websitebeauty/accelerate/index.html | 2898 +++++++
site/blog/websitebeauty/backgroud/index.html | 3720 +++++++++
site/blog/websitebeauty/footer/index.html | 3042 ++++++++
site/blog/websitebeauty/header/index.html | 2849 +++++++
site/blog/websitebeauty/linktech/index.html | 3105 ++++++++
site/blog/websitebeauty/mkcomments/index.html | 3248 ++++++++
site/blog/websitebeauty/mkdocsfont/index.html | 3233 ++++++++
site/blog/websitebeauty/mkpdf/index.html | 2790 +++++++
site/blog/websitebeauty/shubiao/index.html | 3034 ++++++++
site/blog/websitebeauty/time/index.html | 2971 ++++++++
site/blog/websitebeauty/webtalknow/index.html | 2874 +++++++
.../blog/websitebeauty/yuanjiaohua/index.html | 3539 +++++++++
site/develop/Markdown/MWeb/index.html | 3512 +++++++++
site/develop/Markdown/markdown/index.html | 3904 ++++++++++
site/develop/designbeauty/db1/index.html | 2925 +++++++
.../designbeauty/my-to-desihn/index.html | 2801 +++++++
site/develop/git/index.html | 3366 +++++++++
site/develop/lighthouse/index.html | 2767 +++++++
site/develop/vercel/index.html | 2766 +++++++
site/en/index.html | 2836 +++++++
site/img/apple-line.png | Bin 0 -> 4020 bytes
site/index.html | 2851 +++++++
site/javascripts/backgroud.js | 142 +
site/javascripts/extra.js | 62 +
site/javascripts/mathjax-config.js | 28 +
site/javascripts/mathjax.js | 16 +
site/javascripts/rellax.min.js | 14 +
site/javascripts/shortcuts.js | 7 +
site/javascripts/shubiao.js | 83 +
site/javascripts/view.js | 22 +
site/link/index.html | 2937 ++++++++
site/liuyanban/index.html | 2835 +++++++
site/overrides/404.html | 451 ++
.../__pycache__/ai_summary.cpython-311.pyc | Bin 0 -> 18458 bytes
.../__pycache__/reading_time.cpython-311.pyc | Bin 0 -> 10341 bytes
.../__pycache__/shortcodes.cpython-311.pyc | Bin 0 -> 12874 bytes
.../__pycache__/socialmedia.cpython-311.pyc | Bin 0 -> 1347 bytes
.../__pycache__/socialmedia.cpython-38.pyc | Bin 0 -> 893 bytes
.../__pycache__/translations.cpython-311.pyc | Bin 0 -> 6230 bytes
site/overrides/hooks/ai_summary.py | 393 +
site/overrides/hooks/reading_time.py | 255 +
site/overrides/hooks/socialmedia.py | 21 +
site/overrides/partials/announce.html | 5 +
site/overrides/partials/comments.html | 81 +
site/overrides/partials/feedback.html | 79 +
site/overrides/partials/footer.html | 92 +
site/overrides/partials/source-file.html | 172 +
site/search/search_index.json | 1 +
site/sitemap.xml | 203 +
site/sitemap.xml.gz | Bin 0 -> 630 bytes
site/stylesheets/customize.css | 70 +
site/stylesheets/extra.css | 606 ++
site/stylesheets/extra1.css | 40 +
site/stylesheets/link.css | 95 +
site/stylesheets/portfolio.css | 577 ++
site/stylesheets/shubiao.css | 36 +
site/stylesheets/video.css | 40 +
site/stylesheets/ziti.css | 19 +
site/tag/index.html | 3022 ++++++++
164 files changed, 166125 insertions(+), 3 deletions(-)
create mode 100644 docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc
create mode 100644 docs/overrides/hooks/__pycache__/reading_time.cpython-311.pyc
create mode 100644 docs/overrides/hooks/__pycache__/socialmedia.cpython-311.pyc
create mode 100644 docs/overrides/hooks/ai_summary.py
create mode 100644 docs/overrides/hooks/reading_time.py
create mode 100644 site/.ai_cache/13352c45213bc8b828bab035a8bdf5b8.json
create mode 100644 site/.ai_cache/1b4e1af979077c14c74bbed4bef9c267.json
create mode 100644 site/.ai_cache/277b36310e56b2d1abf896f3be1decbe.json
create mode 100644 site/.ai_cache/3d9da43a479c2f295e2ac1fd9b1d4145.json
create mode 100644 site/.ai_cache/41af14f53464f96f48f956e0a80c7fac.json
create mode 100644 site/.ai_cache/5babf7c4c0d88d50ac56ea5a64bece7f.json
create mode 100644 site/.ai_cache/63c53d3efcef0bbfa3517cc57124ea22.json
create mode 100644 site/.ai_cache/676d241d1f71cee7979d1437ab409429.json
create mode 100644 site/.ai_cache/6e3557e004b1983d54297433aa07fe32.json
create mode 100644 site/.ai_cache/7312994b59876da56cecf87e6ce38b89.json
create mode 100644 site/.ai_cache/77612039e8879ec0a34732497e4d927b.json
create mode 100644 site/.ai_cache/78377a142b37e49176adad2a7dc5ea03.json
create mode 100644 site/.ai_cache/88d3fe972a711ac574cdb224f89be6f8.json
create mode 100644 site/.ai_cache/89458e1939eedd5696536b60dff41f99.json
create mode 100644 site/.ai_cache/93960e1d1b82fdcade6022ecf95972c4.json
create mode 100644 site/.ai_cache/ab758b5aa76ff31704c3afef8781f32b.json
create mode 100644 site/.ai_cache/b4fdcb1514d03b4a0bfa36bce929faae.json
create mode 100644 site/.ai_cache/bd5eaaa9ad0f9655b0296602b3e4df7d.json
create mode 100644 site/.ai_cache/c8088321e603b20469a9826a88748350.json
create mode 100644 site/.ai_cache/cb9d4d1856da4475fdde51c070fbc24d.json
create mode 100644 site/.ai_cache/cee9dfb7bfb56fa9e63e493a418499c3.json
create mode 100644 site/.ai_cache/d117ae5382dbad25458d5b090dcb8c42.json
create mode 100644 site/404.html
create mode 100644 site/CNAME
create mode 100644 site/ZH-TW/index.html
create mode 100644 site/about/assets/stylesheets/portfolio.css
create mode 100644 site/about/geren/index.html
create mode 100644 site/about/resume/index.html
create mode 100644 site/about/sty/portfolio.css
create mode 100644 site/about/test/index.html
create mode 100644 site/about/zcw/index.html
create mode 100644 site/about/个人简历.pdf
create mode 100644 site/assets/images/favicon.png
create mode 100644 site/assets/javascripts/bundle.13a4f30d.min.js
create mode 100644 site/assets/javascripts/bundle.13a4f30d.min.js.map
create mode 100644 site/assets/javascripts/lunr/min/lunr.ar.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.da.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.de.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.du.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.el.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.es.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.fi.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.fr.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.he.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.hi.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.hu.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.hy.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.it.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.ja.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.jp.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.kn.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.ko.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.multi.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.nl.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.no.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.pt.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.ro.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.ru.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.sa.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.stemmer.support.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.sv.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.ta.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.te.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.th.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.tr.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.vi.min.js
create mode 100644 site/assets/javascripts/lunr/min/lunr.zh.min.js
create mode 100644 site/assets/javascripts/lunr/tinyseg.js
create mode 100644 site/assets/javascripts/lunr/wordcut.js
create mode 100644 site/assets/javascripts/workers/search.d50fe291.min.js
create mode 100644 site/assets/javascripts/workers/search.d50fe291.min.js.map
create mode 100644 site/assets/stylesheets/main.342714a4.min.css
create mode 100644 site/assets/stylesheets/main.342714a4.min.css.map
create mode 100644 site/assets/stylesheets/palette.06af60db.min.css
create mode 100644 site/assets/stylesheets/palette.06af60db.min.css.map
create mode 100644 site/blog/2021/12/18/博客文章测试/index.html
create mode 100644 site/blog/2022/06/06/2022网站更新记录/index.html
create mode 100644 site/blog/2023/12/21/2023网站更新记录/index.html
create mode 100644 site/blog/2024/01/01/2024网站更新记录/index.html
create mode 100644 site/blog/2025/01/01/2025网站更新记录/index.html
create mode 100644 site/blog/MIT/index.html
create mode 100644 site/blog/Mkdocs/mkdocs1/index.html
create mode 100644 site/blog/Mkdocs/mkdocs2/index.html
create mode 100644 site/blog/Mkdocs/mkdocs3/index.html
create mode 100644 site/blog/Mkdocs/mkdocsblog/index.html
create mode 100644 site/blog/Mkdocs/mkfirst/index.html
create mode 100644 site/blog/archive/2021/index.html
create mode 100644 site/blog/archive/2022/index.html
create mode 100644 site/blog/archive/2023/index.html
create mode 100644 site/blog/archive/2024/index.html
create mode 100644 site/blog/archive/2025/index.html
create mode 100644 site/blog/category/hello-world/index.html
create mode 100644 site/blog/category/网站更新记录/index.html
create mode 100644 site/blog/index.html
create mode 100644 site/blog/websitebeauty/404/index.html
create mode 100644 site/blog/websitebeauty/Relativeaddress/index.html
create mode 100644 site/blog/websitebeauty/accelerate/index.html
create mode 100644 site/blog/websitebeauty/backgroud/index.html
create mode 100644 site/blog/websitebeauty/footer/index.html
create mode 100644 site/blog/websitebeauty/header/index.html
create mode 100644 site/blog/websitebeauty/linktech/index.html
create mode 100644 site/blog/websitebeauty/mkcomments/index.html
create mode 100644 site/blog/websitebeauty/mkdocsfont/index.html
create mode 100644 site/blog/websitebeauty/mkpdf/index.html
create mode 100644 site/blog/websitebeauty/shubiao/index.html
create mode 100644 site/blog/websitebeauty/time/index.html
create mode 100644 site/blog/websitebeauty/webtalknow/index.html
create mode 100644 site/blog/websitebeauty/yuanjiaohua/index.html
create mode 100644 site/develop/Markdown/MWeb/index.html
create mode 100644 site/develop/Markdown/markdown/index.html
create mode 100644 site/develop/designbeauty/db1/index.html
create mode 100644 site/develop/designbeauty/my-to-desihn/index.html
create mode 100644 site/develop/git/index.html
create mode 100644 site/develop/lighthouse/index.html
create mode 100644 site/develop/vercel/index.html
create mode 100644 site/en/index.html
create mode 100644 site/img/apple-line.png
create mode 100644 site/index.html
create mode 100644 site/javascripts/backgroud.js
create mode 100644 site/javascripts/extra.js
create mode 100644 site/javascripts/mathjax-config.js
create mode 100644 site/javascripts/mathjax.js
create mode 100644 site/javascripts/rellax.min.js
create mode 100644 site/javascripts/shortcuts.js
create mode 100644 site/javascripts/shubiao.js
create mode 100644 site/javascripts/view.js
create mode 100644 site/link/index.html
create mode 100644 site/liuyanban/index.html
create mode 100644 site/overrides/404.html
create mode 100644 site/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc
create mode 100644 site/overrides/hooks/__pycache__/reading_time.cpython-311.pyc
create mode 100644 site/overrides/hooks/__pycache__/shortcodes.cpython-311.pyc
create mode 100644 site/overrides/hooks/__pycache__/socialmedia.cpython-311.pyc
create mode 100644 site/overrides/hooks/__pycache__/socialmedia.cpython-38.pyc
create mode 100644 site/overrides/hooks/__pycache__/translations.cpython-311.pyc
create mode 100644 site/overrides/hooks/ai_summary.py
create mode 100644 site/overrides/hooks/reading_time.py
create mode 100644 site/overrides/hooks/socialmedia.py
create mode 100644 site/overrides/partials/announce.html
create mode 100644 site/overrides/partials/comments.html
create mode 100644 site/overrides/partials/feedback.html
create mode 100644 site/overrides/partials/footer.html
create mode 100644 site/overrides/partials/source-file.html
create mode 100644 site/search/search_index.json
create mode 100644 site/sitemap.xml
create mode 100644 site/sitemap.xml.gz
create mode 100644 site/stylesheets/customize.css
create mode 100644 site/stylesheets/extra.css
create mode 100644 site/stylesheets/extra1.css
create mode 100644 site/stylesheets/link.css
create mode 100644 site/stylesheets/portfolio.css
create mode 100644 site/stylesheets/shubiao.css
create mode 100644 site/stylesheets/video.css
create mode 100644 site/stylesheets/ziti.css
create mode 100644 site/tag/index.html
diff --git a/.cache/plugin/git-committers/page-authors.json b/.cache/plugin/git-committers/page-authors.json
index 99cb682..554c7a3 100644
--- a/.cache/plugin/git-committers/page-authors.json
+++ b/.cache/plugin/git-committers/page-authors.json
@@ -1 +1 @@
-{"cache_date": "2024-07-22", "page_authors": {}}
\ No newline at end of file
+{"cache_date": "2025-06-03", "page_authors": {}}
\ No newline at end of file
diff --git a/docs/blog/index.md b/docs/blog/index.md
index 8b7dacf..3675754 100644
--- a/docs/blog/index.md
+++ b/docs/blog/index.md
@@ -6,6 +6,7 @@ hide:
# - feedback
# comments: false
# icon: octicons/home-fill-24
+hide_reading_time: true
---
# MyBlog
diff --git a/docs/blog/posts/update2025.md b/docs/blog/posts/update2025.md
index 1571498..e8fd6e5 100644
--- a/docs/blog/posts/update2025.md
+++ b/docs/blog/posts/update2025.md
@@ -20,7 +20,7 @@ readtime: 2
##
2025-04-10
* 优化网站流畅度(玄学)
-* 优化[友链](../../about/link.md)统计方式,更加准确计数
+* 优化[友链](../../link.md)统计方式,更加准确计数
* 修复评论区重定位的bug,防止他人网站测试评论区导致评论区覆盖到我的网站
##
2025-03-30
diff --git a/docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc b/docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..2c1f60a5f1bf9177562069c832bb3f51b2a425d0
GIT binary patch
literal 18473
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
literal 0
HcmV?d00001
diff --git a/docs/overrides/hooks/ai_summary.py b/docs/overrides/hooks/ai_summary.py
new file mode 100644
index 0000000..d8616fb
--- /dev/null
+++ b/docs/overrides/hooks/ai_summary.py
@@ -0,0 +1,393 @@
+import re
+import json
+import hashlib
+import requests
+from pathlib import Path
+from datetime import datetime
+
+class AISummaryGenerator:
+ def __init__(self):
+ self.cache_dir = Path("site/.ai_cache")
+ self.cache_dir.mkdir(exist_ok=True)
+
+ # DeepSeek API配置
+ self.api_config = {
+ 'url': 'https://api.deepseek.com/v1/chat/completions',
+ 'model': 'deepseek-chat',
+ 'headers': {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer sk-7dbcd6e21fb3417299b50aecff76c7bf'
+ }
+ }
+
+ # 📂 可自定义的文件夹配置
+ self.enabled_folders = [
+ 'blog/', # blog文件夹
+ 'develop/', # develop文件夹
+ # 在这里添加您想要启用AI摘要的文件夹
+ ]
+
+ # 📋 排除的文件和文件夹
+ self.exclude_patterns = [
+ 'liuyanban.md', 'link.md', '404.md', 'tag.md', 'tags.md',
+ '/about/', '/search/', '/sitemap', 'index.md', # 根目录index.md
+ ]
+
+ # 📋 排除的特定文件
+ self.exclude_files = [
+ 'blog/index.md',
+ 'blog/indexblog.md',
+ 'docs/index.md',
+ 'develop/index.md',
+ ]
+
+ def configure_folders(self, folders=None, exclude_patterns=None, exclude_files=None):
+ """
+ 配置启用AI摘要的文件夹
+
+ Args:
+ folders: 启用AI摘要的文件夹列表
+ exclude_patterns: 排除的模式列表
+ exclude_files: 排除的特定文件列表
+ """
+ if folders is not None:
+ self.enabled_folders = folders
+ if exclude_patterns is not None:
+ self.exclude_patterns = exclude_patterns
+ if exclude_files is not None:
+ self.exclude_files = exclude_files
+
+ def get_content_hash(self, content):
+ """生成内容hash用于缓存"""
+ return hashlib.md5(content.encode('utf-8')).hexdigest()
+
+ def get_cached_summary(self, content_hash):
+ """获取缓存的摘要"""
+ cache_file = self.cache_dir / f"{content_hash}.json"
+ if cache_file.exists():
+ try:
+ with open(cache_file, 'r', encoding='utf-8') as f:
+ cache_data = json.load(f)
+ # 检查缓存是否过期(7天)
+ cache_time = datetime.fromisoformat(cache_data.get('timestamp', '1970-01-01'))
+ if (datetime.now() - cache_time).days < 7:
+ return cache_data
+ except:
+ pass
+ return None
+
+ def save_summary_cache(self, content_hash, summary_data):
+ """保存摘要到缓存"""
+ cache_file = self.cache_dir / f"{content_hash}.json"
+ try:
+ summary_data['timestamp'] = datetime.now().isoformat()
+ with open(cache_file, 'w', encoding='utf-8') as f:
+ json.dump(summary_data, f, ensure_ascii=False, indent=2)
+ except Exception as e:
+ print(f"保存摘要缓存失败: {e}")
+
+ def clean_content_for_ai(self, markdown):
+ """清理内容,提取主要文本用于AI处理"""
+ content = markdown
+
+ # 移除YAML front matter
+ content = re.sub(r'^---.*?---\s*', '', content, flags=re.DOTALL)
+
+ # 移除已存在的阅读信息块和AI摘要块
+ content = re.sub(r'!!! info "📖 阅读信息".*?(?=\n\n|\n#|\Z)', '', content, flags=re.DOTALL)
+ content = re.sub(r'!!! info "🤖 AI智能摘要".*?(?=\n\n|\n#|\Z)', '', content, flags=re.DOTALL)
+ content = re.sub(r'!!! tip "📝 自动摘要".*?(?=\n\n|\n#|\Z)', '', content, flags=re.DOTALL)
+
+ # 移除HTML标签
+ content = re.sub(r'<[^>]+>', '', content)
+
+ # 移除图片,保留alt文本作为内容提示
+ content = re.sub(r'!\[([^\]]*)\]\([^)]+\)', r'[图片:\1]', content)
+
+ # 移除链接,保留文本
+ content = re.sub(r'\[([^\]]+)\]\([^)]+\)', r'\1', content)
+
+ # 移除代码块,但保留关键信息
+ content = re.sub(r'```(\w+)?\n(.*?)\n```', r'[代码示例]', content, flags=re.DOTALL)
+
+ # 移除行内代码
+ content = re.sub(r'`[^`]+`', '[代码]', content)
+
+ # 移除表格格式但保留内容
+ content = re.sub(r'\|[^\n]+\|', '', content)
+ content = re.sub(r'^[-|:\s]+$', '', content, flags=re.MULTILINE)
+
+ # 清理格式符号
+ content = re.sub(r'\*\*([^*]+)\*\*', r'\1', content) # 粗体
+ content = re.sub(r'\*([^*]+)\*', r'\1', content) # 斜体
+ content = re.sub(r'^#+\s*', '', content, flags=re.MULTILINE) # 标题符号
+
+ # 移除多余的空行和空格
+ content = re.sub(r'\n\s*\n', '\n\n', content)
+ content = re.sub(r'^[ \t]+', '', content, flags=re.MULTILINE)
+ content = content.strip()
+
+ return content
+
+ def generate_ai_summary(self, content, page_title=""):
+ """使用DeepSeek生成摘要"""
+ # 优化的提示词
+ prompt = f"""请为以下技术文章生成一个高质量的摘要,要求:
+
+1. **长度控制**:严格控制在80-120字以内
+2. **内容要求**:
+ - 准确概括文章的核心主题和关键要点
+ - 突出技术特点、应用场景或解决的问题
+ - 使用专业但易懂的语言
+ - 避免重复文章标题的内容
+3. **格式要求**:
+ - 直接返回摘要内容,无需任何前缀或后缀
+ - 使用简洁的陈述句
+ - 可以适当使用技术术语
+
+文章标题:{page_title}
+
+文章内容:
+{content[:2500]}
+
+请生成摘要:"""
+
+ try:
+ payload = {
+ "model": self.api_config['model'],
+ "messages": [
+ {
+ "role": "system",
+ "content": "你是一个专业的技术文档摘要专家,擅长提取文章核心要点并生成简洁准确的摘要。"
+ },
+ {
+ "role": "user",
+ "content": prompt
+ }
+ ],
+ "max_tokens": 150,
+ "temperature": 0.3, # 降低随机性,提高准确性
+ "top_p": 0.9
+ }
+
+ response = requests.post(
+ self.api_config['url'],
+ headers=self.api_config['headers'],
+ json=payload,
+ timeout=30
+ )
+
+ if response.status_code == 200:
+ result = response.json()
+ summary = result['choices'][0]['message']['content'].strip()
+
+ # 清理可能的格式问题
+ summary = re.sub(r'^["""''`]+|["""''`]+$', '', summary)
+ summary = re.sub(r'^\s*摘要[::]\s*', '', summary)
+ summary = re.sub(r'^\s*总结[::]\s*', '', summary)
+
+ return summary
+ else:
+ print(f"DeepSeek API请求失败: {response.status_code} - {response.text}")
+ return None
+
+ except requests.exceptions.RequestException as e:
+ print(f"DeepSeek API请求异常: {e}")
+ return None
+ except Exception as e:
+ print(f"AI摘要生成异常: {e}")
+ return None
+
+ def generate_fallback_summary(self, content, page_title=""):
+ """生成备用摘要(基于规则的智能摘要)"""
+ # 移除格式符号
+ clean_text = re.sub(r'^#+\s*', '', content, flags=re.MULTILINE)
+ clean_text = re.sub(r'\*\*([^*]+)\*\*', r'\1', clean_text)
+ clean_text = re.sub(r'\*([^*]+)\*', r'\1', clean_text)
+
+ # 分割成句子
+ sentences = re.split(r'[。!?.!?]', clean_text)
+ sentences = [s.strip() for s in sentences if len(s.strip()) > 15]
+
+ # 优先选择包含关键词的句子
+ key_indicators = [
+ '介绍', '讲解', '说明', '分析', '探讨', '研究', '实现', '应用',
+ '方法', '技术', '算法', '原理', '概念', '特点', '优势', '解决',
+ '教程', '指南', '配置', '安装', '部署', '开发', '设计', '构建'
+ ]
+
+ priority_sentences = []
+ normal_sentences = []
+
+ for sentence in sentences[:10]: # 处理前10句
+ if any(keyword in sentence for keyword in key_indicators):
+ priority_sentences.append(sentence)
+ else:
+ normal_sentences.append(sentence)
+
+ # 组合摘要
+ selected_sentences = []
+ total_length = 0
+
+ # 优先使用关键句子
+ for sentence in priority_sentences:
+ if total_length + len(sentence) > 100:
+ break
+ selected_sentences.append(sentence)
+ total_length += len(sentence)
+
+ # 如果还有空间,添加普通句子
+ if total_length < 80:
+ for sentence in normal_sentences:
+ if total_length + len(sentence) > 100:
+ break
+ selected_sentences.append(sentence)
+ total_length += len(sentence)
+
+ if selected_sentences:
+ summary = '。'.join(selected_sentences) + '。'
+ # 简化冗长的摘要
+ if len(summary) > 120:
+ summary = selected_sentences[0] + '。'
+ return summary
+ else:
+ # 根据标题生成通用摘要
+ if any(keyword in page_title for keyword in ['教程', '指南', 'Tutorial']):
+ return '本文提供了详细的教程指南,通过实例演示帮助读者掌握相关技术要点。'
+ elif any(keyword in page_title for keyword in ['配置', '设置', '安装', 'Config']):
+ return '本文介绍了系统配置的方法和步骤,提供实用的设置建议和最佳实践。'
+ elif any(keyword in page_title for keyword in ['开发', '编程', 'Development']):
+ return '本文分享了开发经验和技术实践,提供了实用的代码示例和解决方案。'
+ else:
+ return '本文深入探讨了相关技术内容,提供了实用的方法和解决方案。'
+
+ def process_page(self, markdown, page, config):
+ """处理页面,生成AI摘要"""
+ if not self.should_generate_summary(page, markdown):
+ return markdown
+
+ clean_content = self.clean_content_for_ai(markdown)
+
+ # 内容长度检查
+ if len(clean_content) < 200:
+ print(f"📄 内容太短,跳过摘要生成: {page.file.src_path}")
+ return markdown
+
+ content_hash = self.get_content_hash(clean_content)
+ page_title = getattr(page, 'title', '')
+
+ # 检查缓存
+ cached_summary = self.get_cached_summary(content_hash)
+ if cached_summary:
+ summary = cached_summary.get('summary', '')
+ ai_service = 'cached'
+ print(f"✅ 使用缓存摘要: {page.file.src_path}")
+ else:
+ # 生成新摘要
+ print(f"🤖 正在生成AI摘要: {page.file.src_path}")
+ summary = self.generate_ai_summary(clean_content, page_title)
+
+ if not summary:
+ summary = self.generate_fallback_summary(clean_content, page_title)
+ ai_service = 'fallback'
+ print(f"📝 使用备用摘要: {page.file.src_path}")
+ else:
+ ai_service = 'deepseek'
+ print(f"✅ AI摘要生成成功: {page.file.src_path}")
+
+ # 保存到缓存
+ self.save_summary_cache(content_hash, {
+ 'summary': summary,
+ 'service': ai_service,
+ 'page_title': page_title
+ })
+
+ # 添加摘要到页面最上面
+ summary_html = self.format_summary(summary, ai_service)
+ return summary_html + '\n\n' + markdown
+
+ def should_generate_summary(self, page, markdown):
+ """判断是否应该生成摘要 - 可自定义文件夹"""
+ # 检查页面元数据
+ if hasattr(page, 'meta'):
+ # 明确禁用
+ if page.meta.get('ai_summary') == False:
+ return False
+
+ # 强制启用
+ if page.meta.get('ai_summary') == True:
+ return True
+
+ # 获取文件路径
+ src_path = page.file.src_path.replace('\\', '/') # 统一路径分隔符
+
+ # 检查排除模式
+ if any(pattern in src_path for pattern in self.exclude_patterns):
+ return False
+
+ # 检查排除的特定文件
+ if src_path in self.exclude_files:
+ return False
+
+ # 检查是否在启用的文件夹中
+ for folder in self.enabled_folders:
+ if src_path.startswith(folder) or f'/{folder}' in src_path:
+ folder_name = folder.rstrip('/')
+ print(f"🎯 {folder_name}文件夹文章检测到,启用AI摘要: {src_path}")
+ return True
+
+ # 默认不生成摘要
+ return False
+
+ def format_summary(self, summary, ai_service):
+ """格式化摘要显示"""
+ service_config = {
+ 'deepseek': {
+ 'icon': '🤖',
+ 'name': 'AI智能摘要',
+ 'color': 'info'
+ },
+ 'fallback': {
+ 'icon': '📝',
+ 'name': '自动摘要',
+ 'color': 'tip'
+ },
+ 'cached': {
+ 'icon': '💾',
+ 'name': 'AI智能摘要',
+ 'color': 'info'
+ }
+ }
+
+ config = service_config.get(ai_service, service_config['deepseek'])
+
+ return f'''!!! {config['color']} "{config['icon']} {config['name']}"
+ {summary}
+
+'''
+
+# 创建全局实例
+ai_summary_generator = AISummaryGenerator()
+
+# 🔧 自定义配置函数
+def configure_ai_summary(enabled_folders=None, exclude_patterns=None, exclude_files=None):
+ """
+ 配置AI摘要功能
+
+ Args:
+ enabled_folders: 启用AI摘要的文件夹列表,例如 ['blog/', 'docs/', 'posts/']
+ exclude_patterns: 排除的模式列表,例如 ['404.md', '/admin/']
+ exclude_files: 排除的特定文件列表,例如 ['blog/index.md']
+
+ Example:
+ # 只在blog和docs文件夹启用
+ configure_ai_summary(['blog/', 'docs/'])
+
+ # 在所有文件夹启用,但排除特定文件
+ configure_ai_summary([''], exclude_files=['index.md', 'about.md'])
+ """
+ ai_summary_generator.configure_folders(enabled_folders, exclude_patterns, exclude_files)
+
+def on_page_markdown(markdown, page, config, files):
+ """MkDocs hook入口点"""
+ return ai_summary_generator.process_page(markdown, page, config)
\ No newline at end of file
diff --git a/docs/overrides/hooks/reading_time.py b/docs/overrides/hooks/reading_time.py
new file mode 100644
index 0000000..fbc3731
--- /dev/null
+++ b/docs/overrides/hooks/reading_time.py
@@ -0,0 +1,255 @@
+import re
+from functools import lru_cache
+
+# 预编译正则表达式(保持原有格式)
+EXCLUDE_PATTERNS = [
+ re.compile(r'^index\.md$'),
+ re.compile(r'^about/'),
+ re.compile(r'^trip/index\.md$'),
+ re.compile(r'^relax/index\.md$'),
+ re.compile(r'^blog/indexblog\.md$'),
+ re.compile(r'^blog/posts\.md$'),
+ re.compile(r'^develop/index\.md$'),
+ re.compile(r'waline\.md$'),
+ re.compile(r'link\.md$'),
+ re.compile(r'404\.md$'),
+]
+
+# 优化的字符统计正则表达式
+CHINESE_CHARS_PATTERN = re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf]')
+CODE_BLOCK_PATTERN = re.compile(r'```.*?```', re.DOTALL)
+INLINE_CODE_PATTERN = re.compile(r'`[^`]+`')
+YAML_FRONT_PATTERN = re.compile(r'^---.*?---\s*', re.DOTALL)
+HTML_TAG_PATTERN = re.compile(r'<[^>]+>')
+IMAGE_PATTERN = re.compile(r'!\[.*?\]\([^)]+\)')
+LINK_PATTERN = re.compile(r'\[([^\]]+)\]\([^)]+\)')
+
+# 预定义排除类型
+EXCLUDE_TYPES = frozenset({'landing', 'special', 'widget'})
+
+# 扩展非编程行内代码词汇(更全面的过滤)
+NON_CODE_WORDS = frozenset({
+ 'markdown', 'target', 'blank', 'lg', 'middle', 'small', 'large',
+ 'left', 'right', 'center', 'top', 'bottom', 'primary', 'secondary',
+ 'success', 'warning', 'danger', 'info', 'light', 'dark', 'grid',
+ 'cards', 'octicons', 'bookmark', 'div', 'class', 'img', 'src',
+ 'alt', 'width', 'height', 'style', 'id', 'data', 'href', 'title'
+})
+
+# 支持的编程和标记语言(扩展版本)
+PROGRAMMING_LANGUAGES = frozenset({
+ # 编程语言
+ 'python', 'py', 'javascript', 'js', 'typescript', 'ts', 'java', 'cpp', 'c',
+ 'go', 'rust', 'php', 'ruby', 'swift', 'kotlin', 'csharp', 'cs',
+ # 脚本语言
+ 'bash', 'sh', 'powershell', 'ps1', 'zsh', 'fish', 'bat', 'cmd',
+ # 标记和配置语言
+ 'html', 'css', 'scss', 'sass', 'less', 'yaml', 'yml', 'json', 'xml',
+ 'toml', 'ini', 'conf', 'dockerfile', 'makefile',
+ # 数据库和查询
+ 'sql', 'mysql', 'postgresql', 'sqlite', 'mongodb',
+ # 其他
+ 'r', 'matlab', 'scala', 'perl', 'lua', 'dart', 'tex', 'latex',
+ # 数据格式
+ 'csv', 'properties',
+ # 无标识符(空字符串也算作有效语言)
+ ''
+})
+
+@lru_cache(maxsize=256)
+def clean_markdown_content_for_chinese(content_hash, markdown):
+ """清理Markdown内容,只保留中文文本用于统计(添加缓存)"""
+ content = markdown
+
+ # 使用预编译的正则表达式
+ content = YAML_FRONT_PATTERN.sub('', content)
+ content = HTML_TAG_PATTERN.sub('', content)
+ content = IMAGE_PATTERN.sub('', content)
+ content = LINK_PATTERN.sub(r'\1', content)
+ content = CODE_BLOCK_PATTERN.sub('', content)
+ content = INLINE_CODE_PATTERN.sub('', content)
+
+ return content
+
+def count_code_lines(markdown):
+ """统计代码行数(修复版本 - 正确处理所有代码行)"""
+ code_blocks = CODE_BLOCK_PATTERN.findall(markdown)
+ total_code_lines = 0
+
+ for i, block in enumerate(code_blocks):
+ # 提取语言标识
+ lang_match = re.match(r'^```(\w*)', block)
+ language = lang_match.group(1).lower() if lang_match else ''
+
+ # 移除开头的语言标识和结尾的```
+ code_content = re.sub(r'^```\w*\n?', '', block)
+ code_content = re.sub(r'\n?```$', '', code_content)
+
+ # 过滤空代码块
+ if not code_content.strip():
+ continue
+
+ # 计算有效行数(包含所有非空行,包括注释行)
+ lines = [line for line in code_content.split('\n') if line.strip()]
+ line_count = len(lines)
+
+ # 如果有明确的编程语言标识,直接统计
+ if language and language in PROGRAMMING_LANGUAGES:
+ total_code_lines += line_count
+ continue
+
+ # 增强的检测策略 - 更宽松的判断
+ is_code = False
+
+ # 1. 命令行检测
+ command_indicators = [
+ 'sudo ', 'npm ', 'pip ', 'git ', 'cd ', 'ls ', 'mkdir ', 'rm ', 'cp ', 'mv ',
+ 'chmod ', 'chown ', 'grep ', 'find ', 'ps ', 'kill ', 'top ', 'cat ', 'echo ',
+ 'wget ', 'curl ', 'tar ', 'zip ', 'unzip ', 'ssh ', 'scp ', 'rsync ',
+ 'xattr ', 'codesign ', 'xcode-select ', 'spctl ', 'launchctl ',
+ 'brew ', 'defaults ', 'ditto ', 'hdiutil ', 'diskutil ',
+ 'dir ', 'copy ', 'xcopy ', 'del ', 'rd ', 'md ', 'type ', 'attrib ',
+ '$ ', '# ', '% ', '> ', 'C:\\>', 'PS>',
+ '--', '-r', '-d', '-f', '-v', '-h', '--help', '--version',
+ '--force', '--deep', '--sign', '--master-disable',
+ '/Applications/', '/usr/', '/etc/', '/var/', '/home/', '~/',
+ 'C:\\', 'D:\\', '.app', '.exe', '.pkg', '.dmg', '.zip', '.tar',
+ '#!/',
+ ]
+
+ if any(indicator in code_content for indicator in command_indicators):
+ is_code = True
+
+ # 2. 编程语法检测(增强版)
+ if not is_code:
+ programming_indicators = [
+ # Python语法特征
+ 'def ', 'class ', 'import ', 'from ', 'return ', 'yield ', 'lambda ',
+ 'with ', 'as ', 'try:', 'except:', 'finally:', 'elif ', 'if __name__',
+ 'print(', '.append(', '.extend(', '.remove(', '.sort(', '.reverse(',
+ 'range(', 'len(', 'str(', 'int(', 'float(', 'list(', 'dict(',
+ # JavaScript/TypeScript语法
+ 'function', 'var ', 'let ', 'const ', 'async ', 'await ', '=>',
+ 'console.log', 'document.', 'window.', 'require(',
+ # 通用编程语法
+ 'public ', 'private ', 'protected ', 'static ', 'void ', 'int ',
+ 'string ', 'boolean ', 'float ', 'double ', 'char ',
+ # 操作符和结构
+ '==', '!=', '<=', '>=', '&&', '||', '++', '--', '+=', '-=', '**',
+ # 特殊结构
+ 'while ', 'for ', 'if ', 'else:', 'switch ', 'case ',
+ # HTML/XML语法
+ '',
+ '
+
+
+
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
4
+
0
+
+
+
+