From b5043f621648585e42fd636ffbc841e7ecacc6de Mon Sep 17 00:00:00 2001 From: tukuaiai Date: Sun, 3 May 2026 21:22:10 +0800 Subject: [PATCH] docs: add anchor gate and folded references toc --- .github/workflows/ci.yml | 2 +- Makefile | 4 +- README.md | 8 +-- docs/README.md | 12 ++-- docs/getting-started/README.md | 8 +-- docs/references/README.md | 38 ++++++++++- scripts/README.md | 2 +- scripts/check-local-links.py | 114 +++++++++++++++++++++++++++----- tools/prompts-library/README.md | 6 +- 9 files changed, 156 insertions(+), 38 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 20eeaf7..2e546d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: run: npm install -g markdownlint-cli - name: Run markdownlint run: markdownlint --config .github/lint_config.json --ignore .history --ignore tools/external '**/*.md' - - name: Check local markdown links + - name: Check local markdown links and anchors run: python3 scripts/check-local-links.py link-checker: diff --git a/Makefile b/Makefile index 82509bd..65b7893 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ help: @echo "Available commands:" @echo " help - Show this help message" @echo " lint - Lint all markdown files" - @echo " check-links - Check local markdown links" + @echo " check-links - Check local markdown links and anchors" @echo " build - Verify knowledge base has no build step" @echo " test - Run repository quality gates" @echo " clean - Remove ignored generated caches" @@ -20,7 +20,7 @@ lint: @markdownlint --config .github/lint_config.json --ignore .history --ignore tools/external '**/*.md' check-links: - @echo "Checking local markdown links..." + @echo "Checking local markdown links and anchors..." @python3 scripts/check-local-links.py build: diff --git a/README.md b/README.md index 785c20b..61e5d00 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,7 @@ 问题求解 思维模型 哲学与方法论 - 工程实践 + 工程实践 语言层要素 skills技能大全 提示词在线表格 @@ -178,7 +178,7 @@ 1. [Vibe Coding 经验](docs/getting-started/README.md#1-vibe-coding-经验) - 通用语言能力、人机分工、机器门禁和入门铁律 2. [问题求解](docs/concepts/README.md#concept-problem-solving) - “目标-现状-差距-标准”与“目标-约束-对象-路径”的极简框架 3. [拼好码](docs/concepts/README.md#concept-glue-coding) - 优先复用成熟能力,用胶水代码连接、编排、适配业务流程 -4. [工程实践](docs/references/README.md#reference-engineering-practice-4-ai-编程质量门禁与常见坑) - 用项目架构、代码组织、开发经验和硬门禁约束 AI 输出 +4. [工程实践](docs/references/README.md#quality-gates) - 用项目架构、代码组织、开发经验和硬门禁约束 AI 输出 @@ -407,8 +407,8 @@ pip install -r tools/prompts-library/scripts/requirements.txt * [**Chat Vault**](./tools/chat-vault/): AI 聊天记录保存工具,支持 Codex/Kiro/Gemini/Claude CLI。 * [**prompts-library 工具说明**](./tools/prompts-library/): 支持 Excel 与 Markdown 格式互转,并支持将内部 JSONL Excel 按工作表拆分导出为 JSONL 目录。 * [**编程提示词集合**](https://docs.google.com/spreadsheets/d/1Ifk_dLF25ULSxcfGem1hXzJsi7_RBUNAki8SBCuvkJA/edit?gid=1254297203#gid=1254297203): 适用于 Vibe Coding 流程的专用提示词(云端表格)。 -* [**工程实践**](docs/references/README.md#reference-engineering-practice-4-ai-编程质量门禁与常见坑): 项目架构、代码组织、开发经验、AI 编程质量门禁与常见坑的统一入口。 -* [**技术栈**](docs/references/README.md#reference-technology-stack-十四如何选择技术栈): 常见软件系统技术栈、选型维度、组合案例与初学者学习路径。 +* [**工程实践**](docs/references/README.md#quality-gates): 项目架构、代码组织、开发经验、AI 编程质量门禁与常见坑的统一入口。 +* [**技术栈**](docs/references/README.md#tech-stack-selection): 常见软件系统技术栈、选型维度、组合案例与初学者学习路径。 * [**系统提示词集合**](https://docs.google.com/spreadsheets/d/1Ifk_dLF25ULSxcfGem1hXzJsi7_RBUNAki8SBCuvkJA/edit?gid=1254297203#gid=1254297203): AI 开发的系统提示词,含多版本开发规范(云端表格)。 * [**外部资源(在线表格)**](./assets/README.md): 外部资源的唯一真相源(按类型分表),本地 Markdown 保留为历史参考。 diff --git a/docs/README.md b/docs/README.md index 75cd59d..ab4ec19 100644 --- a/docs/README.md +++ b/docs/README.md @@ -20,14 +20,14 @@ 2. [Vibe Coding 经验](./getting-started/README.md#1-vibe-coding-经验) 3. [问题求解](concepts/README.md#concept-problem-solving) 4. [拼好码](concepts/README.md#concept-glue-coding) -5. [工程实践](references/README.md#reference-engineering-practice-顶部导航) +5. [工程实践](references/README.md#reference-engineering-practice) ### 开发者路径 1. [拼好码](concepts/README.md#concept-glue-coding) 2. [系统构建方法](concepts/README.md#concept-system-building) -3. [技术栈](references/README.md#reference-technology-stack-顶部导航) -4. [工程实践](references/README.md#reference-engineering-practice-顶部导航) +3. [技术栈](references/README.md#reference-technology-stack) +4. [工程实践](references/README.md#reference-engineering-practice) ### 思维模型路径 @@ -42,7 +42,7 @@ 2. [docs 目录 AGENTS](./AGENTS.md) 3. [从零开始完整入门](./getting-started/README.md#1-学习地图) 4. [Vibe Coding 经验](./getting-started/README.md#1-vibe-coding-经验) -5. [工程实践](references/README.md#reference-engineering-practice-顶部导航) +5. [工程实践](references/README.md#reference-engineering-practice) 6. [AI 引用语料](../assets/ai-citation/README.md) ## 全部文档索引 @@ -76,8 +76,8 @@ - [README](./references/README.md) - 参考资料索引。 - [AGENTS](./references/AGENTS.md) - 参考资料目录操作规则。 -- [工程实践](references/README.md#reference-engineering-practice-顶部导航) - 项目架构、代码组织、开发经验、质量门禁与常见坑。 -- [技术栈](references/README.md#reference-technology-stack-顶部导航) - 技术栈选型、组合案例与初学者学习路径。 +- [工程实践](references/README.md#reference-engineering-practice) - 项目架构、代码组织、开发经验、质量门禁与常见坑。 +- [技术栈](references/README.md#reference-technology-stack) - 技术栈选型、组合案例与初学者学习路径。 ### research diff --git a/docs/getting-started/README.md b/docs/getting-started/README.md index d0d55f6..c278d40 100644 --- a/docs/getting-started/README.md +++ b/docs/getting-started/README.md @@ -163,7 +163,7 @@ AI 能安装依赖、执行命令、修复报错、提交 Git;你负责确认 | 开发者路线 | 已会写代码 | 建立 AI 结对编程工作流 | [Vibe Coding 经验](#1-vibe-coding-经验) | | Prompt 路线 | 想提升提问质量 | 把需求表达成可执行指令 | [提示词库](../../../prompts/README.md) | | Skill 路线 | 想沉淀复用能力 | 把高频任务做成可重复调用的技能 | [Skills 技能大全](../../../skills/README.md) | -| 质量门禁路线 | 担心 AI 乱写代码 | 用测试、CI、schema、清单约束 AI 输出 | [工程实践](../references/README.md#reference-engineering-practice-顶部导航) | +| 质量门禁路线 | 担心 AI 乱写代码 | 用测试、CI、schema、清单约束 AI 输出 | [工程实践](../references/README.md#reference-engineering-practice) | | GEO/SEO 路线 | 想提升仓库被引用概率 | 建设 AI 可理解、可引用、可验证的内容资产 | [GEO / SEO 检查清单](../../assets/ai-citation/geo-seo-checklist.md) | ### 路线一:零基础路线 @@ -197,7 +197,7 @@ AI 能安装依赖、执行命令、修复报错、提交 Git;你负责确认 先建立人机分工和质量意识。 2. [拼好码](../concepts/README.md#concept-glue-coding) 优先复用成熟能力,把自研代码限制在连接、编排、适配和业务逻辑。 -3. [工程实践](../references/README.md#reference-engineering-practice-顶部导航) +3. [工程实践](../references/README.md#reference-engineering-practice) 在任务开始前写清楚目标、边界、禁止项、验收标准和门禁,并用底层程序逻辑检查项约束实现质量。 完成标准: @@ -212,7 +212,7 @@ AI 能安装依赖、执行命令、修复报错、提交 Git;你负责确认 目标:把自然语言需求写成可执行、可检查、可复用的指令。 1. [提示词库入口](../../../prompts/README.md) -2. [工程实践](../references/README.md#reference-engineering-practice-顶部导航) +2. [工程实践](../references/README.md#reference-engineering-practice) 3. [语言层要素](../concepts/README.md#concept-language-layers) 4. [问题求解](../concepts/README.md#concept-problem-solving) @@ -244,7 +244,7 @@ AI 能安装依赖、执行命令、修复报错、提交 Git;你负责确认 优先阅读: 1. [AGENTS.md](../../../../AGENTS.md) -2. [工程实践](../references/README.md#reference-engineering-practice-顶部导航) +2. [工程实践](../references/README.md#reference-engineering-practice) 3. [GEO / SEO 检查清单](../../assets/ai-citation/geo-seo-checklist.md) 团队约束: diff --git a/docs/references/README.md b/docs/references/README.md index 6568c87..230b595 100644 --- a/docs/references/README.md +++ b/docs/references/README.md @@ -11,12 +11,44 @@ - 它承载稳定、可执行、可检查、可复用的工程参考资料。 - 每个原独立文档都已并入本 README,并通过稳定锚点提供细粒度跳转。 +## 常用入口 + +| 目标 | 直接跳转 | +|:---|:---| +| 新项目结构怎么搭 | [项目架构模板](#reference-engineering-practice-1-项目架构模板) | +| AI 代码质量怎么卡住 | [AI 编程质量门禁与常见坑](#quality-gates) | +| 系统提示词怎么写 | [系统提示词构建原则](#reference-engineering-practice-1-系统提示词构建原则) | +| 强前置条件怎么约束 | [强前置条件约束](#reference-engineering-practice-2-强前置条件约束) | +| 常见坑怎么排查 | [常见坑汇总](#reference-engineering-practice-3-常见坑汇总) | +| 底层程序逻辑怎么审 | [底层程序逻辑设计与工程优化项](#reference-engineering-practice-5-底层程序逻辑设计与工程优化项) | +| 技术栈怎么选 | [如何选择技术栈](#tech-stack-selection) | +| 初学者先学什么 | [初学者应该学什么技术栈](#reference-technology-stack-十五初学者应该学什么技术栈) | + ## 总目录 1. [工程实践](#reference-engineering-practice) - 项目架构、代码组织、开发经验、质量门禁与常见坑。 2. [技术栈](#reference-technology-stack) - 技术栈选型、组合案例与学习路径。 -## 细粒度目录 +## 折叠块语法 + +长目录统一使用 `details + summary`,常用入口放在折叠块外,完整细粒度目录放在折叠块内。 + +```md +
+完整细粒度目录(默认收起) + +### 细粒度目录 + +- [章节](#stable-anchor) + - [子章节](#stable-child-anchor) + +
+``` + +
+完整细粒度目录(默认收起) + +### 细粒度目录 - [1. 工程实践](#reference-engineering-practice) - [核心摘要](#reference-engineering-practice-核心摘要) @@ -215,6 +247,8 @@ - [二十、面试中如何介绍自己的技术栈](#reference-technology-stack-二十面试中如何介绍自己的技术栈) - [二十一、总结](#reference-technology-stack-二十一总结) +
+ ## 和其他目录的边界 - 检查清单、模板、质量门禁和经验类内容优先收敛到本 README 的工程实践部分。 @@ -1244,6 +1278,7 @@ Redis 的作用: * 异步任务处理 * 提高系统稳定性与吞吐 + ### 4. AI 编程质量门禁与常见坑 @@ -4897,6 +4932,7 @@ Web 游戏: --- + ### 十四、如何选择技术栈 diff --git a/scripts/README.md b/scripts/README.md index 2f4f6ec..00b4372 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -4,4 +4,4 @@ 当前已有: -- `check-local-links.py`:仓库内 Markdown 相对链接检查脚本。 +- `check-local-links.py`:仓库内 Markdown 相对链接与锚点检查脚本。 diff --git a/scripts/check-local-links.py b/scripts/check-local-links.py index 71d6bbc..76c9e2c 100644 --- a/scripts/check-local-links.py +++ b/scripts/check-local-links.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Check local Markdown links that should resolve inside this repository.""" +"""Check local Markdown links and anchors that should resolve in this repository.""" from __future__ import annotations @@ -21,7 +21,6 @@ LINK_PATTERNS = [ re.compile(r"\b(?:href|src)=[\"']([^\"']+)[\"']"), ] EXTERNAL_PREFIXES = ( - "#", "http://", "https://", "wss://", @@ -32,6 +31,72 @@ EXTERNAL_PREFIXES = ( ) +def github_slug(title: str) -> str: + """Approximate GitHub Markdown heading anchors for local validation.""" + title = re.sub(r"<[^>]+>", "", title.strip().lower()) + title = re.sub(r"[`*_~]", "", title) + title = re.sub(r"[^\w\u4e00-\u9fff\- ]+", "", title) + title = re.sub(r"\s+", "-", title).strip("-") + return title + + +def strip_fenced_code(text: str) -> str: + """Remove fenced code blocks before scanning inline links.""" + lines: list[str] = [] + in_fence = False + fence_marker = "" + + for line in text.splitlines(): + stripped = line.lstrip() + if stripped.startswith(("```", "~~~")): + marker = stripped[:3] + if not in_fence: + in_fence = True + fence_marker = marker + elif marker == fence_marker: + in_fence = False + fence_marker = "" + lines.append("") + continue + lines.append("" if in_fence else line) + + return "\n".join(lines) + + +def markdown_anchors(path: Path) -> set[str]: + text = path.read_text(encoding="utf-8", errors="ignore") + anchors = set(re.findall(r" bool: rel = path.relative_to(ROOT) if any(part in SKIP_PARTS for part in rel.parts): @@ -39,17 +104,23 @@ def should_skip(path: Path) -> bool: return any(rel == prefix or prefix in rel.parents for prefix in SKIP_PREFIXES) -def normalize_target(raw: str) -> str: +def normalize_target(raw: str) -> tuple[str, str]: raw = raw.strip() if not raw or raw.startswith(EXTERNAL_PREFIXES): - return "" + return "", "" target = raw.split()[0] if " " in raw and not raw.startswith("<") else raw - target = target.strip("<>").split("#", 1)[0] - return urllib.parse.unquote(target) + target = target.strip("<>") + if "#" in target: + path_part, anchor = target.split("#", 1) + else: + path_part, anchor = target, "" + return urllib.parse.unquote(path_part), urllib.parse.unquote(anchor) def main() -> int: - missing: list[tuple[Path, str, Path]] = [] + missing_links: list[tuple[Path, str, Path]] = [] + missing_anchors: list[tuple[Path, str, Path, str]] = [] + anchor_cache: dict[Path, set[str]] = {} checked_files = 0 for markdown_file in sorted(ROOT.rglob("*.md")): @@ -57,31 +128,42 @@ def main() -> int: continue checked_files += 1 text = markdown_file.read_text(encoding="utf-8", errors="ignore") + scan_text = strip_fenced_code(text) for pattern in LINK_PATTERNS: - for match in pattern.finditer(text): + for match in pattern.finditer(scan_text): raw = match.group(1) - target = normalize_target(raw) - if not target or target.startswith(("/", "\\")): + target, anchor = normalize_target(raw) + if target.startswith(("/", "\\")): continue - destination = (markdown_file.parent / target).resolve() + destination = (markdown_file.parent / target).resolve() if target else markdown_file.resolve() try: destination.relative_to(ROOT) except ValueError: continue if not destination.exists(): - missing.append((markdown_file.relative_to(ROOT), raw, markdown_file.parent / target)) + missing_links.append((markdown_file.relative_to(ROOT), raw, markdown_file.parent / target)) + continue + if anchor and destination.suffix.lower() == ".md": + if destination not in anchor_cache: + anchor_cache[destination] = markdown_anchors(destination) + if anchor not in anchor_cache[destination]: + missing_anchors.append((markdown_file.relative_to(ROOT), raw, destination.relative_to(ROOT), anchor)) - if missing: + if missing_links or missing_anchors: print("MISSING_LINKS") - for source, raw, resolved in missing: + for source, raw, resolved in missing_links: print(f"{source} -> {raw} => {resolved.relative_to(ROOT)}") - print(f"TOTAL={len(missing)}") + print("MISSING_ANCHORS") + for source, raw, destination, anchor in missing_anchors: + print(f"{source} -> {raw} => {destination}#{anchor}") + print(f"TOTAL_LINKS={len(missing_links)}") + print(f"TOTAL_ANCHORS={len(missing_anchors)}") return 1 - print(f"OK local links checked: {checked_files} files") + print(f"OK local links and anchors checked: {checked_files} files") return 0 diff --git a/tools/prompts-library/README.md b/tools/prompts-library/README.md index 11d38fb..6175931 100644 --- a/tools/prompts-library/README.md +++ b/tools/prompts-library/README.md @@ -30,10 +30,10 @@ 代码大小

-[✨ 功能特性](#-功能特性) • -[🚀 快速开始](#-快速开始) • +[✨ 功能特性](#功能特性) • +[🚀 快速开始](#快速开始) • [⚙️ 架构与工作流程](#architecture-workflow) • -[🤝 参与贡献](#-参与贡献) • +[🤝 参与贡献](#参与贡献) • [🗺️ 路线图](#roadmap)