跳转至

用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)

评论