#!/usr/bin/env python3 # -*- coding: utf-8 -*- from pathlib import Path from datetime import datetime import hashlib # 可按需增减 INCLUDE_EXTS = { ".js", ".ts", ".html", ".css", ".json", ".md", ".txt", ".yml", ".yaml", } INCLUDE_NAMES = {"manifest.json", "readme.md"} # 无扩展也可加进来 EXCLUDE_DIRS = {".git", ".idea", ".vscode", "node_modules", "dist", "build", "out", "target"} def is_excluded(p: Path, root: Path) -> bool: parts = p.relative_to(root).parts return any(x in EXCLUDE_DIRS for x in parts) def sha256(data: bytes) -> str: return hashlib.sha256(data).hexdigest() def is_binary(data: bytes) -> bool: return b"\x00" in data # 极简判断:有 NUL 基本就是二进制 def main(): root = Path(".").resolve() ts = datetime.now().strftime("%Y%m%d_%H%M%S") out = root / f"frontend_project_code_v{ts}.md" files = [] for p in root.rglob("*"): if not p.is_file(): continue if is_excluded(p, root): continue name = p.name.lower() ext = p.suffix.lower() if ext in INCLUDE_EXTS or name in INCLUDE_NAMES: files.append(p) files.sort(key=lambda x: x.relative_to(root).as_posix().lower()) with out.open("w", encoding="utf-8", newline="\n") as w: w.write("# Code Bundle\n\n") w.write(f"- GeneratedAt: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n") w.write(f"- Root: {root.as_posix()}\n") w.write(f"- FileCount: {len(files)}\n\n") w.write("---\n\n") for p in files: rel = p.relative_to(root).as_posix() data = p.read_bytes() w.write(f"## FILE: {rel}\n") w.write(f"- Size: {len(data)} bytes\n") w.write(f"- SHA256: {sha256(data)}\n\n") if is_binary(data): w.write("*(binary file, content skipped)*\n\n") w.write("---\n\n") continue # 统一用 utf-8 写出,解码失败就用 replace 保底 text = data.decode("utf-8", errors="replace") w.write("```\n") w.write(text.rstrip("\n")) w.write("\n```\n\n") w.write("---\n\n") print(f"[OK] 输出完成:{out}") if __name__ == "__main__": main()