#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 将所有包含 'status: hidden' 的文章标记为草稿 (draft: true),并清理冲突的设置。 原 PowerShell 版本:scripts/add_draft_to_hidden.ps1 改写原因:Gitea 自建 runner 镜像不含 pwsh,改用 Python 3(GitHub/Gitea 均自带)。 对每篇 content/posts 下的 .md: 1. 若 frontmatter 含 status: hidden a. draft: false -> draft: true b. 注释掉冲突的 status: public c. 若无 draft: true 则在 status: hidden 行后补一行 2. 安全检查:新内容非空、且长度不低于原内容的 90%,否则跳过保存 3. 以 UTF-8(无 BOM)写回 """ import os import re import sys POSTS_PATH = "content/posts" # 与原脚本保持一致的正则(多行模式) RE_STATUS_HIDDEN = re.compile(r'^status:\s*("hidden"|hidden)', re.M) RE_DRAFT_FALSE = re.compile(r'^draft:\s*false', re.M) RE_STATUS_PUBLIC = re.compile(r'^status:\s*("public"|public)', re.M) RE_DRAFT_TRUE = re.compile(r'^draft:\s*true', re.M) RE_STATUS_HIDDEN_LINE = re.compile(r'^(status:\s*("hidden"|hidden).*$)', re.M) def main() -> int: if not os.path.isdir(POSTS_PATH): print(f"Path not found: {POSTS_PATH}", file=sys.stderr) return 1 md_files = [] for root, _dirs, files in os.walk(POSTS_PATH): for name in files: if name.endswith(".md"): md_files.append(os.path.join(root, name)) md_files.sort() count = 0 print("Starting scan for hidden posts cleanup...") for path in md_files: with open(path, "r", encoding="utf-8") as f: content = f.read() if not content: print(f" Skipping empty file: {path}") continue # 仅处理含 status: hidden 的文件(与原脚本一致,仅匹配 frontmatter 行首) if not RE_STATUS_HIDDEN.search(content): continue modified = False new_content = content # 1. draft: false -> draft: true if RE_DRAFT_FALSE.search(new_content): new_content = RE_DRAFT_FALSE.sub("draft: true", new_content) modified = True print(f" Fixed 'draft: false' in {path}") # 2. 注释掉 status: public if RE_STATUS_PUBLIC.search(new_content): new_content = RE_STATUS_PUBLIC.sub( r"# \g<0> # Auto-hidden by script", new_content ) modified = True print(f" Commented out 'status: public' in {path}") # 3. 确保存在 draft: true if not RE_DRAFT_TRUE.search(new_content): new_content = RE_STATUS_HIDDEN_LINE.sub( lambda m: f"{m.group(1)}\ndraft: true", new_content ) modified = True print(f" Added 'draft: true' to {path}") if modified: # 安全检查 1:新内容非空 if not new_content: print( f"CRITICAL: New content is empty for {path}. Skipping save.", file=sys.stderr, ) continue # 安全检查 2:长度不应异常缩小(>10%) if len(new_content) < len(content) * 0.9: print( f"CRITICAL: Suspicious size drop for {path}. Skipping save.", file=sys.stderr, ) continue with open(path, "w", encoding="utf-8", newline="") as f: f.write(new_content) print(f" -> Saved changes to {path}") count += 1 print(f"Completed. Updated {count} files.") return 0 if __name__ == "__main__": sys.exit(main())