1/**
2 * Simple Levenshtein distance implementation (small N, no perf worries)
3 */
4const levenshtein = (a: string, b: string): number => {
5 const m = a.length
6 const n = b.length
7 const dp: Array<Array<number>> = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0))
8 for (let i = 0; i <= m; i++) dp[i][0] = i
9 for (let j = 0; j <= n; j++) dp[0][j] = j
10 for (let i = 1; i <= m; i++) {
11 for (let j = 1; j <= n; j++) {
12 const cost = a[i - 1] === b[j - 1] ? 0 : 1
13 dp[i][j] = Math.min(
14 dp[i - 1][j] + 1,
15 dp[i][j - 1] + 1,
16 dp[i - 1][j - 1] + cost
17 )
18 }
19 }
20 return dp[m][n]
21}
22
23/**
24 * Return suggestions with minimum distance found, up to distance 2.
25 *
26 * @internal
27 */
28export const suggest = (input: string, candidates: ReadonlyArray<string>): ReadonlyArray<string> => {
29 const distances = candidates
30 .map((c) => [levenshtein(input, c), c] as const)
31 .filter(([d]) => d <= 2) // Stricter threshold
32 .sort(([a], [b]) => a - b)
33
34 if (distances.length === 0) return []
35
36 // Only return suggestions with the minimum distance found
37 const minDistance = distances[0][0]
38 return distances
39 .filter(([d]) => d === minDistance)
40 .map(([, c]) => c)
41}