fix(editor): follow local Markdown anchor links (#1328)

Go to Declaration and modifier-click on a fragment-only Markdown or HTML link such as [artist::order](#Artist-order) said there was nothing to go to: the text-reference fallback rejected fragment-only targets, and Markdown fragment lookup checked headings only, never HTML id / name anchors. Fragment-only href targets are now recognized and resolve in the same file (the current buffer, so unsaved anchors count), and Markdown files fall back to id / name anchors after headings.

Co-authored-by: pravdomil <[email protected]>
Цей коміт міститься в:
pravdomil authored and GitHub committed 2026-11-05 01:48:06 +08:00
1 джерело 11932a87af
коміт fd69664ca7
4 files changed
+81 -12

No files matched your search

+15 -5
Переглянути файл
@@ -82,15 +82,12 @@ const local = (over: Partial<Extract<Locals, { status: "local" }>["symbol"]> = {
});
const views: EditorView[] = [];
function editor(doc: string, language = "typescript", anchor = 0) {
function editor(doc: string, language = "typescript", anchor = 0, path = "/p/a.ts") {
const view = new EditorView({
state: EditorState.create({
doc,
selection: { anchor },
extensions: [
lspDoc.of({ doc: 7, path: "/p/a.ts", language, uiMode: null, readOnly: false }),
navigationExtension(),
],
extensions: [lspDoc.of({ doc: 7, path, language, uiMode: null, readOnly: false }), navigationExtension()],
}),
parent: document.body,
});
@@ -670,3 +667,16 @@ describe("modifier-hover navigation recovery", () => {
expect(view.dom.querySelector(".cm-lsp-link")?.textContent).toBe("bar");
});
});
describe("same-document fragment navigation", () => {
it.each(["definition", "declaration"] as const)(
"follows Markdown HTML anchors through %s without a server",
async (kind) => {
const source = '[artist::order](#Artist-order)\n\n<a id="Artist-order"></a>';
const view = editor(source, "markdown", source.indexOf("#Artist"), "/p/notes.md");
await gotoTargets(view, kind);
expect(view.state.selection.main.head).toBe(source.indexOf("id="));
expect(openFile).not.toHaveBeenCalled();
},
);
});