diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml index c415be7..cf900ef 100644 --- a/.github/workflows/validate.yml +++ b/.github/workflows/validate.yml @@ -14,4 +14,4 @@ jobs: steps: - uses: actions/checkout@v4 - name: Validate note files - run: python -c "from pathlib import Path; notes=list(Path('.').rglob('*.md')); assert len(notes)>=2 and all(p.read_text(encoding='utf-8').strip() for p in notes)" + run: python scripts/validate_notes.py diff --git "a/01-basics/01-\345\217\230\351\207\217\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" "b/01-basics/01-\345\217\230\351\207\217\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" index b883ea4..f8d38ca 100644 --- "a/01-basics/01-\345\217\230\351\207\217\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" +++ "b/01-basics/01-\345\217\230\351\207\217\345\222\214\346\225\260\346\215\256\347\261\273\345\236\213.md" @@ -209,8 +209,9 @@ print("很高兴认识你!") # 获取出生年份 birth_year = int(input("请输入你的出生年份:")) -# 计算年龄 -current_year = 2026 +# 使用当前年份计算年龄,避免示例过期 +from datetime import date +current_year = date.today().year age = current_year - birth_year # 输出 diff --git a/README.md b/README.md index 8c55cb0..24c6349 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,14 @@ python-notes/ - **GitHub:** [@DorianChn](https://github.com/DorianChn) - **Email:** 3671276527@qq.com +## ✅ 本地验证 + +```bash +python scripts/validate_notes.py +``` + +该检查不需要第三方依赖,会验证笔记非空并检查仓库内的相对链接。 + ---
diff --git a/scripts/validate_notes.py b/scripts/validate_notes.py new file mode 100644 index 0000000..6b0a1bd --- /dev/null +++ b/scripts/validate_notes.py @@ -0,0 +1,45 @@ +"""Validate the learning-note collection without third-party dependencies.""" + +from __future__ import annotations + +import re +import sys +from pathlib import Path +from urllib.parse import unquote + + +ROOT = Path(__file__).resolve().parents[1] +LINK = re.compile(r"\[[^\]]+\]\(([^)]+)\)") + + +def fail(message: str) -> None: + print(f"validation error: {message}", file=sys.stderr) + raise SystemExit(1) + + +def main() -> None: + notes = sorted(ROOT.rglob("*.md")) + if len(notes) < 2: + fail(f"expected at least 2 Markdown files, found {len(notes)}") + + for note in notes: + text = note.read_text(encoding="utf-8") + if not text.strip(): + fail(f"empty note: {note.relative_to(ROOT)}") + for match in LINK.finditer(text): + target = unquote(match.group(1).split("#", 1)[0].strip()) + if not target or target.startswith(("http://", "https://", "mailto:")): + continue + candidate = (note.parent / target).resolve() + try: + candidate.relative_to(ROOT) + except ValueError: + fail(f"link escapes repository: {note.relative_to(ROOT)} -> {target}") + if not candidate.exists(): + fail(f"missing link: {note.relative_to(ROOT)} -> {target}") + + print(f"validated {len(notes)} Markdown files and all relative links") + + +if __name__ == "__main__": + main()