diff --git a/.ai_cache/service_config.json b/.ai_cache/service_config.json index b0a4a59..7915dfa 100644 --- a/.ai_cache/service_config.json +++ b/.ai_cache/service_config.json @@ -6,5 +6,5 @@ "gemini" ], "summary_language": "zh", - "check_time": "2025-06-04T11:03:04.808361" + "check_time": "2025-06-06T19:19:56.275939" } \ No newline at end of file diff --git a/.cache/plugin/git-committers/page-authors.json b/.cache/plugin/git-committers/page-authors.json index d6004e2..363e1af 100644 --- a/.cache/plugin/git-committers/page-authors.json +++ b/.cache/plugin/git-committers/page-authors.json @@ -1 +1 @@ -{"cache_date": "2025-06-04", "page_authors": {}} \ No newline at end of file +{"cache_date": "2025-06-06", "page_authors": {}} \ No newline at end of file diff --git a/docs/about/test.md b/docs/about/test.md index e9f7197..a60f133 100644 --- a/docs/about/test.md +++ b/docs/about/test.md @@ -1,6 +1,15 @@ +--- +title: 测试小组件 +# status: new +--- + +# 测试小组件 + !!!info 测试中的小组件,可看源代码自行取用 + +
“循此苦旅 以达星辰”
diff --git a/docs/blog/websitebeauty/MkDocs-AI-Hooks.md b/docs/blog/websitebeauty/Mkdocs-AI-Summary.md similarity index 98% rename from docs/blog/websitebeauty/MkDocs-AI-Hooks.md rename to docs/blog/websitebeauty/Mkdocs-AI-Summary.md index 0a3421b..c30e2af 100644 --- a/docs/blog/websitebeauty/MkDocs-AI-Hooks.md +++ b/docs/blog/websitebeauty/Mkdocs-AI-Summary.md @@ -7,8 +7,10 @@ status: new # MkDocs AI Hooks -仓库地址:https://github.com/Wcowin/mkdocs-ai-hooks -在线预览:https://wcowin.work/mkdocs-ai-hooks/ +![logo 2](https://s1.imagehub.cc/images/2025/06/06/ee327dc2912fd2f31d38ee8a16a1e1ff.png){.img1} + +仓库地址:[https://github.com/Wcowin/Mkdocs-AI-Summary](https://github.com/Wcowin/Mkdocs-AI-Summary) +🌐 **在线演示**:[https://wcowin.work/Mkdocs-AI-Summary/](https://wcowin.work/Mkdocs-AI-Summary/)

MkDocs Hooks @@ -26,7 +28,6 @@ status: new ![预览图1](https://s1.imagehub.cc/images/2025/06/03/d1563500263b22cfd0ffc3679993aa83.jpg) ![预览图2](https://s1.imagehub.cc/images/2025/06/03/526b59b6a2e478f2ffa1629320e3e2ce.png) -🌐 **在线演示**: https://wcowin.work/mkdocs-ai-hooks/ --- diff --git a/docs/blog/websitebeauty/reading_time.md b/docs/blog/websitebeauty/reading_time.md new file mode 100644 index 0000000..4a23047 --- /dev/null +++ b/docs/blog/websitebeauty/reading_time.md @@ -0,0 +1,374 @@ +--- +title: Mkdocs 阅读时间插件 +tags: + - Mkdocs +status: new +--- + +## 1. 基础配置 + +### **步骤1** + +创建reading_time.py + +??? note "reading_time.py" + ```python + import re + import threading + import time + from functools import lru_cache + from collections import OrderedDict + import hashlib + + # 预编译正则表达式(性能优化版本) + EXCLUDE_PATTERNS = [ + re.compile(r'^index\.md$'), + 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语法 + '', + '', + # SQL语法 + 'SELECT ', 'FROM ', 'WHERE ', 'INSERT ', 'UPDATE ', 'DELETE ', + 'CREATE ', 'ALTER ', 'DROP ', 'INDEX ', 'TABLE ', + # 数学公式和LaTeX + '\\', '$', '$$', '\\begin', '\\end', '\\frac', '\\sum', + ] + + if any(indicator in code_content for indicator in programming_indicators): + is_code = True + + # 3. 结构化检测 + if not is_code: + # 缩进结构检测 + if len(lines) > 1 and any(line.startswith(' ') or line.startswith('\t') for line in lines): + is_code = True + + # HTML标签结构 + elif '<' in code_content and '>' in code_content: + is_code = True + + # 包含特殊字符组合 + elif any(char in code_content for char in ['{', '}', '(', ')', '[', ']']) and ('=' in code_content or ':' in code_content): + is_code = True + + # 4. 模式匹配检测(宽松策略) + if not is_code and len(lines) >= 1: + special_patterns = [ + r'\w+\(\)', r'\w+\[\]', r'\w+\{\}', r'\w+=\w+', r'\w+:\w+', + r'<\w+>', r'\$\w+', r'#\w+', r'@\w+', r'\w+\.\w+\(\)', + r'\d+\.\d+\.\d+', r'http[s]?://', r'ftp://', r'localhost', + r'def\s+\w+', r'class\s+\w+', r'import\s+\w+', r'from\s+\w+', + r'if\s+\w+', r'while\s+\w+', r'for\s+\w+', r'return\s+\w*', + r'\w+\s*=\s*\w+', r'\w+\.\w+', r'#.*输出', r'#.*结果' + ] + + if any(re.search(pattern, code_content) for pattern in special_patterns): + is_code = True + + # 如果判断为代码,则统计行数 + if is_code: + total_code_lines += line_count + + return total_code_lines + + def calculate_reading_stats(markdown): + """计算中文字符数和代码行数""" + # 生成内容哈希用于缓存 + content_hash = hash(markdown) + + # 使用缓存的清理函数 + clean_content = clean_markdown_content_for_chinese(content_hash, markdown) + chinese_chars = len(CHINESE_CHARS_PATTERN.findall(clean_content)) + + # 统计代码行数 + code_lines = count_code_lines(markdown) + + # 计算阅读时间(中文:400字/分钟) + reading_time = max(1, round(chinese_chars / 400)) + + return reading_time, chinese_chars, code_lines + + def on_page_markdown(markdown, **kwargs): + page = kwargs['page'] + + # 快速排除检查 + if page.meta.get('hide_reading_time', False): + return markdown + + # 保持原有的EXCLUDE_PATTERNS循环检查方式 + src_path = page.file.src_path + for pattern in EXCLUDE_PATTERNS: + if pattern.match(src_path): + return markdown + + # 优化类型检查 + page_type = page.meta.get('type', '') + if page_type in EXCLUDE_TYPES: + return markdown + + # 快速预检查 + if len(markdown) < 300: + return markdown + + # 计算统计信息 + reading_time, chinese_chars, code_lines = calculate_reading_stats(markdown) + + # 过滤太短的内容 + if chinese_chars < 50: + return markdown + + # 生成阅读信息 + if code_lines > 0: + reading_info = f"""!!! info "📖 阅读信息" + 阅读时间:**{reading_time}** 分钟 | 中文字符:**{chinese_chars}** | 有效代码行数:**{code_lines}** + + """ + else: + reading_info = f"""!!! info "📖 阅读信息" + 阅读时间:**{reading_time}** 分钟 | 中文字符:**{chinese_chars}** + + """ + + return reading_info + markdown + ``` + + + +### **步骤2** + +把reading_time.py放到docs/overrides/hooks目录下,然后在mkdocs.yml中添加: + +```yaml +# 在 mkdocs.yml 中添加 +hooks: + - docs/overrides/hooks/reading_time.py # 阅读时间统计 +``` + +### **步骤3** +配置MkDocs主题以及覆写路径custom_dir +```yaml +# 在 mkdocs.yml 中添加 +theme: + name: material + custom_dir: docs/overrides # 必需配置!!! + features: + - content.code.copy + - content.code.select +``` + +到这里检查下目录树状图: +``` +$ tree -a +文件名 +├── .github +│ ├── .DS_Store +│ └── workflows +│ └── ci.yml +├── docs +│ └── index.md +| └── overrides +│ └── hooks +│ └── reading_time.py +│ └── ... +└── mkdocs.yml +``` + +### **步骤4** + +```bash +mkdocs serve # 本地预览 +``` + + +## 2. 效果展示 + +![image](https://s1.imagehub.cc/images/2025/06/06/a4584dbad4da3f87eb5c2f1e7ed14a74.png) + + +## 3.高级配置 + +### 3.1 排除特定页面 +如果有一些页面不想统计阅读时间,可以在页面的元数据中添加 `hide_reading_time: true`。例如: + +```markdown +--- +title: 不统计阅读时间的页面 +hide_reading_time: true +--- +``` + +或者直接在reading_time.py中添加: +```python +# 你想排除的页面路径 +EXCLUDE_PATTERNS = [ + re.compile(r'^index\.md$'), + 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$'), +] +``` + +### 3.2 自定义统计信息 +如果需要自定义统计信息的格式,可以修改reading_time.py中的calculate_reading_stats函数。例如: +```python +def calculate_reading_stats(markdown): + # 计算统计信息 + reading_time, chinese_chars, code_lines = calculate_reading_stats(markdown) + # 自定义统计信息格式 + if code_lines > 0: + reading_info = f"""!!! info "📖 阅读信息" + 阅读时间:**{reading_time}** 分钟 | 中文字符:**{chinese_chars}** | 有效代码行数:**{code_lines}** + """ + else: + reading_info = f"""!!! info "📖 阅读信息" + 阅读时间:**{reading_time}** 分钟 | 中文字符:**{chinese_chars}** + """ + return reading_info + markdown +``` + diff --git a/docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc b/docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc index 576fc3c..0087df8 100644 Binary files a/docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc and b/docs/overrides/hooks/__pycache__/ai_summary.cpython-311.pyc differ diff --git a/docs/overrides/hooks/reading_time.py b/docs/overrides/hooks/reading_time.py index fbc3731..cbf4ff7 100644 --- a/docs/overrides/hooks/reading_time.py +++ b/docs/overrides/hooks/reading_time.py @@ -237,7 +237,7 @@ def on_page_markdown(markdown, **kwargs): reading_time, chinese_chars, code_lines = calculate_reading_stats(markdown) # 过滤太短的内容 - if chinese_chars < 50: + if chinese_chars < 30: return markdown # 生成阅读信息 diff --git a/mkdocs.yml b/mkdocs.yml index 8b248e1..c54c386 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -75,7 +75,8 @@ nav: - 2.Mkdocs配置说明(mkdocs.yml): blog/Mkdocs/mkdocs2.md - 3.解决Github Pages部署mkdocs自定义域名失效的问题: blog/Mkdocs/mkdocs3.md - Mkdocs美化/补充: - - MkDocs文档AI摘要: blog/websitebeauty/MkDocs-AI-Hooks.md + - MkDocs文档AI摘要: blog/websitebeauty/Mkdocs-AI-Summary.md + - 添加阅读信息统计: blog/websitebeauty/reading_time.md - 添加Mkdocs博客: blog/Mkdocs/mkdocsblog.md - 网页圆角化设计: blog/websitebeauty/yuanjiaohua.md - 添加评论系统(giscus为例): blog/websitebeauty/mkcomments.md @@ -313,5 +314,5 @@ extra_css: hooks: - docs/overrides/hooks/socialmedia.py - # - docs/overrides/hooks/reading_time.py + - docs/overrides/hooks/reading_time.py - docs/overrides/hooks/ai_summary.py \ No newline at end of file