用Kimi写一个python脚本,自动生成nav配置
自动生成 MkDocs 的 Nav 树形结构¶
需求提示词:¶
用python封装一个mkdocs插件,要能正确用pip安装调用,有setup.py。在编译前修改mkdocs.yml文件,生成nav配置,具体需求如下:
1. **扫描文件夹和文件**:
- 忽略docs下的blog文件夹
- 递归扫描 `docs` 文件夹及其所有子文件夹。
- 只包含 `.md` 文件,忽略 `index.md` 文件。
- 如果一个文件夹中除了 `index.md` 没有其他 `.md` 文件,并且其所有子文件夹中也没有其他 `.md` 文件,则跳过该文件夹。
- 如果文件夹中有其他 `.md` 文件,或其子文件夹中有 `.md` 文件,则正常扫描并包含在树形结构中。
2. **生成树形结构**:
- 树形结构以文件夹和文件名作为键,相对路径作为值。
- 文件名不包含文件扩展名(`.md`)
- 如果 .md 文件中定义了 meta 数据,并且指定了 urlname,则在生成路径时,将文件名替换为 urlname.md,并去掉 .html 后缀。
- 相对路径以 `docs` 文件夹为基准,但路径中不显示 `docs/` 前缀。
- 路径风格统一为 Unix 风格(`/`),即使在 Windows 系统上也使用 `/`。
3. **更新 `mkdocs.yml` 文件**:
- 将生成的树形结构写入 `mkdocs.yml` 文件的 `nav` 部分,覆盖原有内容。
- 确保生成的 YAML 格式正确,路径和文件名正确无误。
4. **代码实现要求**:
- 使用 `pathlib` 模块进行路径操作。
- 使用 `yaml` 模块读取和写入 `mkdocs.yml` 文件。
- 使用正则表达式或解析工具读取 .md 文件的 meta 数据。
- 确保代码简洁、易读,支持多层级文件夹结构。
---
结果¶
上面提示词生成的结果,貌似每次都有点不太一样,我一点点问,然后慢慢修正它的,最后生成的脚本完全满足我自己的需求,当然不是问一次就能成功,只是觉得现在AI强的有点离谱,记录一下自己曾经用过的提示词。
from pathlib import Path, PurePosixPath
import yaml
import re
def extract_meta(file_path):
"""
提取 Markdown 文件中的 meta 数据
"""
meta = {}
with open(file_path, "r", encoding="utf-8") as f:
content = f.read()
# 匹配 YAML frontmatter
match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)
if match:
meta_content = match.group(1)
# 解析 meta 数据
meta = yaml.safe_load(meta_content)
return meta
def scan_files_and_folders(root_folder, base_path=None):
"""
使用 pathlib 递归扫描文件夹并生成树形结构
- 只包含 .md 文件,忽略 index.md 文件
- 如果当前文件夹中没有其他 .md 文件,并且所有子文件夹也没有其他 .md 文件,则跳过该文件夹
- 否则,正常扫描子文件夹
- 相对路径以 docs 为基准,但不显示 docs/ 前缀,路径风格统一为 /
- 如果 .md 文件中定义了 urlname,则在路径中替换文件名部分为 urlname.md
"""
tree = {}
root_path = Path(root_folder)
# 如果未指定 base_path,则默认为 docs 文件夹
if base_path is None:
base_path = root_path
# 获取当前文件夹中的 .md 文件(忽略 index.md)
md_files = [item for item in root_path.glob("*.md") if item.name != "index.md"]
# 检查子文件夹中是否有其他 .md 文件
has_md_in_subfolders = False
for item in root_path.iterdir():
if item.is_dir():
sub_tree = scan_files_and_folders(item, base_path=base_path)
if sub_tree: # 如果子文件夹中有有效内容
tree[item.name] = sub_tree
has_md_in_subfolders = True
# 如果当前文件夹中没有其他 .md 文件,并且子文件夹中也没有其他 .md 文件,则跳过
if not md_files and not has_md_in_subfolders:
return None
# 如果当前文件夹中有其他 .md 文件,则将它们添加到树形结构中
if md_files:
for item in md_files:
meta = extract_meta(item)
urlname = meta.get("urlname", "").replace(".html", "")
name = item.stem
relative_path = PurePosixPath(item.relative_to(base_path))
# 如果定义了 urlname,则替换路径中的文件名部分
if urlname:
relative_path = relative_path.with_name(f"{urlname}.md")
tree[name] = str(relative_path)
return tree
def update_mkdocs_nav(tree, mkdocs_yml_path):
"""
更新 mkdocs.yml 的 nav 部分
"""
# 加载 mkdocs.yml 文件
with open(mkdocs_yml_path, "r", encoding="utf-8") as f:
mkdocs_config = yaml.safe_load(f)
# 将树形结构转换为带有 - 的 YAML 格式
def format_nav(tree):
nav = []
for key, value in tree.items():
if isinstance(value, dict):
nav.append({key: format_nav(value)})
else:
nav.append({key: value})
return nav
# 更新 nav 部分
mkdocs_config["nav"] = format_nav(tree)
# 将更新后的配置写回 mkdocs.yml
with open(mkdocs_yml_path, "w", encoding="utf-8") as f:
yaml.dump(mkdocs_config, f, allow_unicode=True, sort_keys=False)
def updateYaml(root_folder, mkdocs_yml_path):
# 生成树形结构
tree = scan_files_and_folders(root_folder)
# 如果根目录下没有任何有效内容,则直接退出
if not tree:
print("docs 文件夹中没有任何有效的 .md 文件,无需更新 mkdocs.yml。")
return
# 更新 mkdocs.yml 的 nav 部分
update_mkdocs_nav(tree, mkdocs_yml_path)
print("mkdocs.yml 的 nav 部分已更新完成。")
if __name__ == "__main__":
current_dir = Path.cwd()
root_folder = current_dir / "docs"
mkdocs_yml_path = current_dir / "mkdocs.yml"
updateYaml(root_folder,mkdocs_yml_path)