Add link autocompletion (limited)

This commit is contained in:
Clément Pons
2025-11-03 11:20:56 +01:00
parent 6db6a4b19d
commit 62c1ccf0b4
5 changed files with 118 additions and 9 deletions

View File

@@ -1,5 +1,25 @@
import type { CompletionContext, CompletionResult } from '@codemirror/autocomplete';
import type { Element, MarkdownConfig } from '@lezer/markdown';
import { styleTags, tags } from '@lezer/highlight';
import { Content } from '../content.util';
function fuzzyMatch(text: string, search: string): number {
const textLower = text.toLowerCase().normalize('NFC');
const searchLower = search.toLowerCase().normalize('NFC');
let searchIndex = 0;
let score = 0;
for (let i = 0; i < textLower.length && searchIndex < searchLower.length; i++) {
if (textLower[i] === searchLower[searchIndex]) {
score += 1;
if (i === searchIndex) score += 2; // Bonus for sequential match
searchIndex++;
}
}
return searchIndex === searchLower.length ? score : 0;
}
export const wikilink: MarkdownConfig = {
defineNodes: [
@@ -69,3 +89,32 @@ export const wikilink: MarkdownConfig = {
})
]
};
export const autocompletion = (context: CompletionContext): CompletionResult | null => {
const word = context.matchBefore(/\[\[[\w\s-]*/);
if (!word || (word.from === word.to && !context.explicit))
return null;
const searchTerm = word.text.slice(2).toLowerCase();
const options = Object.values(Content.files).filter(e => e.type !== 'folder').map(e => ({ ...e, score: fuzzyMatch(e.title, searchTerm) })).filter(e => e.score > 0).sort((a, b) => b.score - a.score).slice(0, 50);
return {
from: word.from + 2,
options: options.map(e => ({
label: e.title,
detail: e.path,
apply: (view, completion, from, to) => {
view.dispatch({
changes: {
from: word.from,
to: word.to,
insert: `[[${e.path}]]`
},
selection: { anchor: word.from + e.path.length + 2 }
});
},
type: 'text'
})),
validFor: /^[\[\w\s-]*$/,
}
};