Files
mkdocs/add_docs_to_mkdocs.py
renjianbo 9474bbca66 测试
2026-01-12 11:35:01 +08:00

210 lines
6.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
自动将docs目录下的文件添加到mkdocs.yml导航配置中
"""
import os
import sys
import re
import yaml
from pathlib import Path
def load_mkdocs_nav(mkdocs_path='mkdocs.yml'):
"""加载mkdocs.yml中的导航配置"""
try:
with open(mkdocs_path, 'r', encoding='utf-8') as f:
content = f.read()
# 使用正则表达式提取nav部分
nav_match = re.search(r'nav:\s*\n(.*?)(?=\n\w+:|$)', content, re.DOTALL)
if not nav_match:
print("错误: 找不到nav配置")
sys.exit(1)
nav_content = nav_match.group(1)
# 解析YAML格式的nav内容
# 为nav内容添加适当的缩进
nav_yaml = "nav:\n" + nav_content
config = yaml.safe_load(nav_yaml)
return config.get('nav', [])
except FileNotFoundError:
print(f"错误: 找不到文件 {mkdocs_path}")
sys.exit(1)
except Exception as e:
print(f"错误: 解析文件失败: {e}")
sys.exit(1)
def save_mkdocs_nav(nav, mkdocs_path='mkdocs.yml'):
"""保存导航配置到mkdocs.yml"""
try:
with open(mkdocs_path, 'r', encoding='utf-8') as f:
content = f.read()
# 生成新的nav内容
nav_yaml = yaml.dump({'nav': nav}, allow_unicode=True, default_flow_style=False, sort_keys=False)
# 移除第一行的"nav:"
nav_lines = nav_yaml.split('\n')
new_nav_content = '\n'.join(nav_lines[1:]) # 跳过第一行
# 替换原有的nav部分使用re.escape避免特殊字符问题
nav_pattern = r'(nav:\s*\n)(.*?)(?=\n\w+:|$)'
# 对new_nav_content进行转义处理
escaped_content = re.escape(new_nav_content)
# 但我们需要保留实际的换行符等,所以使用更简单的方法
new_content = re.sub(nav_pattern, r'\1' + new_nav_content, content, flags=re.DOTALL)
with open(mkdocs_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f"✓ 已更新 {mkdocs_path}")
except Exception as e:
print(f"错误: 保存文件失败: {e}")
sys.exit(1)
def get_all_md_files(docs_dir='docs'):
"""获取docs目录下的所有.md文件"""
md_files = []
for root, dirs, files in os.walk(docs_dir):
for file in files:
if file.endswith('.md'):
rel_path = os.path.relpath(os.path.join(root, file), docs_dir)
# 将Windows路径分隔符转换为Unix风格/
rel_path = rel_path.replace('\\', '/')
md_files.append(rel_path)
return sorted(md_files)
def get_nav_files(nav):
"""从导航配置中提取所有文件路径"""
nav_files = []
def extract_files(item):
if isinstance(item, dict):
for key, value in item.items():
if isinstance(value, list):
for subitem in value:
extract_files(subitem)
elif isinstance(value, str):
nav_files.append(value)
elif isinstance(item, str):
nav_files.append(item)
for item in nav:
extract_files(item)
return nav_files
def categorize_file(file_path):
"""根据文件路径分类文件"""
path_parts = file_path.split('/')
# 如果文件在根目录
if len(path_parts) == 1:
return "其他"
# 根据目录名分类
category_map = {
'技术文档': '技术文档',
'开发指南': '开发指南',
'学习笔记': '学习笔记',
'DevOps平台': 'DevOps平台',
'cursor': 'Cursor工具',
'Obsidian': 'Obsidian笔记'
}
first_dir = path_parts[0]
# 如果目录名在映射中,使用映射的名称,否则使用目录名
return category_map.get(first_dir, first_dir)
def add_files_to_nav(nav, missing_files):
"""将缺失的文件添加到导航配置中"""
# 创建分类字典
categories = {}
for file_path in missing_files:
category = categorize_file(file_path)
if category not in categories:
categories[category] = []
categories[category].append(file_path)
# 将文件添加到现有分类或创建新分类
for category, files in categories.items():
category_found = False
# 查找是否已存在该分类
for i, item in enumerate(nav):
if isinstance(item, dict) and category in item:
# 添加到现有分类
existing_files = set(item[category])
for file_path in files:
if file_path not in existing_files:
item[category].append(file_path)
category_found = True
print(f"✓ 已将 {len(files)} 个文件添加到 '{category}' 分类")
break
# 如果分类不存在,创建新分类
if not category_found:
nav.append({category: sorted(files)})
print(f"✓ 已创建新分类 '{category}' 并添加 {len(files)} 个文件")
return nav
def main():
print("开始自动将docs目录下的文件添加到mkdocs.yml中...")
print("=" * 60)
# 1. 加载当前导航配置
print("1. 加载mkdocs.yml导航配置...")
nav = load_mkdocs_nav()
# 2. 获取所有.md文件
print("2. 扫描docs目录下的所有.md文件...")
all_md_files = get_all_md_files()
print(f" 找到 {len(all_md_files)} 个.md文件")
# 3. 获取导航中的文件
print("3. 分析当前导航配置...")
nav_files = get_nav_files(nav)
print(f" 导航中已有 {len(nav_files)} 个文件")
# 4. 找出缺失的文件
missing_files = []
for md_file in all_md_files:
# 将路径统一为Unix风格进行比较
if md_file not in nav_files and md_file != 'index.md':
missing_files.append(md_file)
if not missing_files:
print("✓ 所有文件已在导航中,无需更新")
return
print(f"4. 发现 {len(missing_files)} 个文件不在导航中:")
for i, file_path in enumerate(missing_files, 1):
print(f" {i:2d}. {file_path}")
# 5. 确认是否继续
print("\n5. 是否继续添加这些文件到mkdocs.yml")
response = input(" 输入 'y' 继续,其他键取消: ")
if response.lower() != 'y':
print("操作已取消")
return
# 6. 添加文件到导航
print("\n6. 正在更新mkdocs.yml...")
updated_nav = add_files_to_nav(nav, missing_files)
# 7. 保存配置
save_mkdocs_nav(updated_nav)
print("\n" + "=" * 60)
print("完成mkdocs.yml已更新")
print(f"总计添加了 {len(missing_files)} 个文件到导航中")
if __name__ == '__main__':
main()