diff --git a/tools/test_validate_docs.py b/tools/test_validate_docs.py index 960c0b4..a26a678 100644 --- a/tools/test_validate_docs.py +++ b/tools/test_validate_docs.py @@ -229,6 +229,52 @@ def test_plain_markdown_image_and_archbee_directive_both_found(self) -> None: self.assertEqual(urls, ["/files/pics/a.png", "/files/pics/b.png"]) +class RawHtmlParsingTest(unittest.TestCase): + def test_extracts_src_from_html_img_in_table_cell(self) -> None: + # Real shape from docs/general/Controls.md, whose controls reference + # is an Archbee HTML table -- every icon on that page is referenced + # this way and never as Markdown. + line = '
'
+ refs = extract_link_refs(Path("docs/x.md"), [(1, line)])
+ self.assertEqual(len(refs), 1)
+ self.assertEqual(refs[0].raw_url, "/files/pics/flipctl-in-terminal.png")
+
+ def test_extracts_href_from_html_link(self) -> None:
+ # Real shape from docs/resources/docs/Markup-reference.md.
+ line = ''
+ refs = extract_link_refs(Path("docs/x.md"), [(1, line)])
+ self.assertEqual(len(refs), 1)
+ self.assertEqual(refs[0].raw_url, "Markup-reference.md")
+ self.assertFalse(refs[0].is_image)
+
+ def test_single_quoted_attributes_are_extracted(self) -> None:
+ line = "
x"
+ refs = extract_link_refs(Path("docs/x.md"), [(1, line)])
+ self.assertEqual(
+ sorted(r.raw_url for r in refs),
+ ["/files/pics/a.png", "/general/Controls.md"],
+ )
+
+ def test_several_html_images_on_one_line(self) -> None:
+ line = '
'
+ refs = extract_link_refs(Path("docs/x.md"), [(1, line)])
+ self.assertEqual(
+ sorted(r.raw_url for r in refs), ["/files/pics/a.png", "/files/pics/b.png"]
+ )
+
+ def test_other_html_attributes_are_not_mistaken_for_a_reference(self) -> None:
+ line = 'Task
\n'
+ "```\n"
+ ),
+ },
+ )
+ md_files = sorted(docs_root.rglob("*.md"))
+ findings = check_links(md_files, docs_root, docs_root.parent)
+ self.assertEqual(findings, [])
+
def test_external_url_is_never_checked(self) -> None:
with tempfile.TemporaryDirectory() as tmp_str:
docs_root = self._write_docs(
diff --git a/tools/validate_docs.py b/tools/validate_docs.py
index 92941b8..d28515d 100644
--- a/tools/validate_docs.py
+++ b/tools/validate_docs.py
@@ -12,8 +12,9 @@
target page and confirm the fragment matches a GitHub-style slug of one
of its headings.
2. Path check: for every internal link and image reference -- plain
- Markdown and Archbee's `::Image[]{src="..."}` / `:inlineImage[]{src="..."}`
- directives -- confirm the target file actually exists. Image references
+ Markdown, Archbee's `::Image[]{src="..."}` / `:inlineImage[]{src="..."}`
+ directives, and raw HTML `[\"'])(?P.*?)(?P=q)", re.IGNORECASE +) +_HTML_LINK_RE = re.compile( + r"]*?\shref=(?P [\"'])(?P.*?)(?P=q)", re.IGNORECASE +) # Used to strip Markdown/Archbee markup out of a heading before slugifying, # so the anchor is computed from the *rendered* text, same as GitHub does. @@ -205,6 +217,10 @@ def extract_link_refs(source: Path, lines: list[tuple[int, str]]) -> list[LinkRe ) for match in _ARCHBEE_IMAGE_RE.finditer(line): refs.append(LinkRef(source, lineno, match.group("src"), is_image=True)) + for match in _HTML_IMAGE_RE.finditer(line): + refs.append(LinkRef(source, lineno, match.group("src"), is_image=True)) + for match in _HTML_LINK_RE.finditer(line): + refs.append(LinkRef(source, lineno, match.group("href"), is_image=False)) return refs