fix(lsp): match wikilink anchors against raw heading text
`[[Page#Heading text]]` parsed the anchor as the literal string after `#`, but the index stored each heading's anchor as `slugify(title)`. The two never compared equal, so every TOC-style anchor link (`[[#1. Topologia atual]]`, etc.) was reported as a broken anchor and goto-definition couldn't jump to the right heading either. Slugify the request before comparing — `slugify` is idempotent on valid-slug input, so the same code path now accepts both `[[Page#some-heading]]` (slug form) and `[[Page#Some Heading]]` (raw text). Applied to diagnostics, navigation, and hover preview so all three agree on what "an anchor matches a heading" means. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -466,6 +466,60 @@ fn collect_wiki_links_finds_nested() {
|
||||
}
|
||||
}
|
||||
|
||||
// ===== Anchor matching against raw heading text =====
|
||||
|
||||
#[test]
|
||||
fn anchor_matches_raw_heading_text() {
|
||||
// Users write `[[Page#Some Heading]]` (raw text), the index keys by
|
||||
// slugify form. Slugifying the request before comparison makes both
|
||||
// shapes work.
|
||||
let root = "/tmp/anchor1";
|
||||
let idx = build_index(
|
||||
root,
|
||||
&[
|
||||
("Home", "[[Target#Some Heading]]\n"),
|
||||
("Target", "= Target =\n== Some Heading ==\n"),
|
||||
],
|
||||
);
|
||||
let src = "[[Target#Some Heading]]\n";
|
||||
let ast = parse(src);
|
||||
let diags = diagnostics::link_health(
|
||||
&ast,
|
||||
src,
|
||||
Some(&home_uri(root)),
|
||||
&idx,
|
||||
"Home",
|
||||
LinkSeverity::Warning,
|
||||
true,
|
||||
);
|
||||
assert!(diags.is_empty(), "got: {:?}", diags);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn anchor_matches_unicode_heading() {
|
||||
// Real-world content: heading with em dash and accented chars.
|
||||
let root = "/tmp/anchor2";
|
||||
let idx = build_index(
|
||||
root,
|
||||
&[
|
||||
("Home", "[[Target#Homelab — VLANs]]\n"),
|
||||
("Target", "= Target =\n== Homelab — VLANs ==\n"),
|
||||
],
|
||||
);
|
||||
let src = "[[Target#Homelab — VLANs]]\n";
|
||||
let ast = parse(src);
|
||||
let diags = diagnostics::link_health(
|
||||
&ast,
|
||||
src,
|
||||
Some(&home_uri(root)),
|
||||
&idx,
|
||||
"Home",
|
||||
LinkSeverity::Warning,
|
||||
true,
|
||||
);
|
||||
assert!(diags.is_empty(), "got: {:?}", diags);
|
||||
}
|
||||
|
||||
// ===== COMMANDS completeness =====
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user