fix(markdown): resolve wikilinks that start with the scan root's own folders (#4559)

Obsidian writes wikilink paths from the vault root, so scanning a folder
below it meets links like [[Corp/wiki/Fox]] from inside Corp/. The
vault-wide fallback matched them as suffixes of root-relative paths,
which never succeeds, and the references edge was dropped. When nothing
matches, drop the longest leading run of the scan root's own folders
and match the rest exactly from the root.
This commit is contained in:
berce authored and safishamsi committed 2026-10-20 11:28:04 +01:00
1 parent 5f4cccf0e7
commit ffaf5c820d
2 files changed
+40

No files matched your search

+11
View File
@@ -211,6 +211,17 @@ def _vault_lookup(target: str, root: Path) -> "Path | None":
c for c in candidates
if c[1] == suffix or c[1].endswith("/" + suffix)
]
if not matches:
# Obsidian writes vault-relative paths, so scanning a folder below the
# vault root meets links that start with that folder's own path
# ([[Corp/wiki/Fox]] from inside Corp/, #4559). Drop the longest such
# leading run and match the rest from the scan root.
root_parts = [_nfc(p) for p in Path(root).parts]
for k in range(len(parts) - 1, 0, -1):
if parts[:k] == root_parts[-k:]:
rest = "/".join(parts[k:])
matches = [c for c in candidates if c[1] == rest]
break
if not matches:
return None
return min(matches)[2]
+29
View File
@@ -3772,6 +3772,35 @@ def test_markdown_wikilink_fallback_path_qualified(tmp_path):
for e in refs), f"path-qualified vault link lost: {refs}"
def test_markdown_wikilink_vault_relative_to_a_scan_root_below_the_vault(tmp_path):
"""Obsidian writes vault-relative paths, so scanning a folder below the
vault meets links that start with that folder's own path (#4559)."""
corp = tmp_path / "Vault" / "Projects" / "Corp"
(corp / "wiki").mkdir(parents=True)
for name in ("Charlie", "Delta", "Fox"):
(corp / "wiki" / f"{name}.md").write_text(f"# {name}\n")
(corp / "Alpha.md").write_text(
"[[wiki/Charlie]] [[Corp/wiki/Delta|alias]] [[Projects/Corp/wiki/Fox]]\n")
pages = [corp / "Alpha.md", *(corp / "wiki").iterdir()]
_, refs, page_id = _vault_extract(corp, pages)
alpha = page_id(corp / "Alpha.md")
assert {e["target"] for e in refs if e["source"] == alpha} == {
page_id(corp / "wiki" / f"{name}.md") for name in ("Charlie", "Delta", "Fox")}
def test_markdown_wikilink_scan_root_prefix_still_needs_the_exact_path(tmp_path):
"""Once the scan root's folder is dropped the rest is a path from the
root, not a suffix: [[Corp/Fox]] does not reach Corp/wiki/Fox.md."""
corp = tmp_path / "Corp"
(corp / "wiki").mkdir(parents=True)
(corp / "wiki" / "Fox.md").write_text("# Fox\n")
(corp / "Alpha.md").write_text("[[Corp/Fox]]\n")
_, refs, page_id = _vault_extract(corp, [corp / "Alpha.md", corp / "wiki" / "Fox.md"])
alpha = page_id(corp / "Alpha.md")
fox = page_id(corp / "wiki" / "Fox.md")
assert fox not in {e["target"] for e in refs if e["source"] == alpha}
def test_markdown_wikilink_fallback_root_wins(tmp_path):
"""On a bare-name collision the shallowest match wins — Obsidian resolves
a bare wikilink to the root-level file over a same-named subfolder file."""