"""README.md relative links must stay inside the repo and point to existing files.""" import re import unittest from pathlib import Path ROOT = Path(__file__).resolve().parent.parent LINK = re.compile(r'!?\[[^\]]*\]\(([^)\s]+)(?:\s+"[^"]*")?\)') def bad_links(text, root=ROOT): bad = [] for target in LINK.findall(text): if re.match(r'^([a-zA-Z][a-zA-Z0-9+.-]*:|#|//)', target): continue path = target.split('#')[0].split('?')[0] if not path: continue p = (root / path).resolve() if root.resolve() not in (p, *p.parents): bad.append((target, 'escapes repo')) elif not p.exists(): bad.append((target, 'missing')) return bad class ReadmeLinks(unittest.TestCase): def test_current_readme(self): self.assertEqual(bad_links((ROOT / 'README.md').read_text()), []) def test_detects_escape(self): self.assertEqual(bad_links('[v](../worldmap-viewer)'), [('../worldmap-viewer', 'escapes repo')]) def test_detects_missing(self): self.assertEqual(bad_links('![i](nope/none.png)'), [('nope/none.png', 'missing')]) if __name__ == '__main__': unittest.main()