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:
@@ -1386,7 +1386,7 @@ fn heading_range_in(idx: &WorkspaceIndex, uri: &Url, anchor: &str, _utf8: bool)
|
||||
let page = idx.page(uri)?;
|
||||
// Headings win over tags when both match — same precedence as
|
||||
// vimwiki: heading anchors are the "canonical" target shape.
|
||||
if let Some(h) = page.headings.iter().find(|h| h.anchor == anchor) {
|
||||
if let Some(h) = page.find_heading_by_anchor(anchor) {
|
||||
return Some(span_to_lsp_range_no_text(&h.span));
|
||||
}
|
||||
// Phase 12: tags-as-anchors. `[[Page#tag-name]]` lands on the
|
||||
@@ -1434,7 +1434,7 @@ fn preview_for(page: &IndexedPage, anchor: Option<&str>) -> String {
|
||||
buf.push_str(title);
|
||||
buf.push_str("**\n\n");
|
||||
if let Some(anchor) = anchor {
|
||||
if let Some(h) = page.headings.iter().find(|h| h.anchor == anchor) {
|
||||
if let Some(h) = page.find_heading_by_anchor(anchor) {
|
||||
buf.push_str(&format!("§ {}\n", h.title));
|
||||
} else {
|
||||
buf.push_str(&format!("(anchor `{anchor}` not found)\n"));
|
||||
|
||||
Reference in New Issue
Block a user