22// This module is browser compatible.
33import { levenshteinDistance } from "./levenshtein_distance.ts" ;
44
5- // NOTE: this metric may change in future versions (e.g. better than levenshteinDistance)
6- const getWordDistance = levenshteinDistance ;
5+ /** Options for {@linkcode closestString}. */
6+ export interface ClosestStringOptions {
7+ /**
8+ * Whether the distance should include case.
9+ *
10+ * @default {false}
11+ */
12+ caseSensitive ?: boolean ;
13+ /**
14+ * A custom comparison function to use for comparing strings.
15+ *
16+ * @param a The first string for comparison.
17+ * @param b The second string for comparison.
18+ * @returns The distance between the two strings.
19+ * @default {levenshteinDistance}
20+ */
21+ compareFn ?: ( a : string , b : string ) => number ;
22+ }
723
824/**
925 * Finds the most similar string from an array of strings.
1026 *
11- * Note: the ordering of words may change with version-updates
12- * E.g. word-distance metric may change (improve)
13- * use a named-distance (e.g. levenshteinDistance) to
14- * guarantee a particular ordering.
27+ * By default, calculates the distance between words using the
28+ * {@link https://en.wikipedia.org/wiki/Levenshtein_distance | Levenshtein distance}.
1529 *
1630 * @example Usage
1731 * ```ts
@@ -26,23 +40,20 @@ const getWordDistance = levenshteinDistance;
2640 *
2741 * @param givenWord The string to measure distance against
2842 * @param possibleWords The string-array to pick the closest string from
29- * @param options An options bag containing a `caseSensitive` flag indicating
30- * whether the distance should include case. Default is false.
43+ * @param options The options for the comparison.
3144 * @returns The closest string
3245 */
3346export function closestString (
3447 givenWord : string ,
3548 possibleWords : ReadonlyArray < string > ,
36- options ?: {
37- caseSensitive ?: boolean ;
38- } ,
49+ options ?: ClosestStringOptions ,
3950) : string {
4051 if ( possibleWords . length === 0 ) {
4152 throw new TypeError (
4253 "When using closestString(), the possibleWords array must contain at least one word" ,
4354 ) ;
4455 }
45- const { caseSensitive } = { ...options } ;
56+ const { caseSensitive, compareFn = levenshteinDistance } = { ...options } ;
4657
4758 if ( ! caseSensitive ) {
4859 givenWord = givenWord . toLowerCase ( ) ;
@@ -52,13 +63,12 @@ export function closestString(
5263 let closestStringDistance = Infinity ;
5364 for ( const each of possibleWords ) {
5465 const distance = caseSensitive
55- ? getWordDistance ( givenWord , each )
56- : getWordDistance ( givenWord , each . toLowerCase ( ) ) ;
66+ ? compareFn ( givenWord , each )
67+ : compareFn ( givenWord , each . toLowerCase ( ) ) ;
5768 if ( distance < closestStringDistance ) {
5869 nearestWord = each ;
5970 closestStringDistance = distance ;
6071 }
6172 }
62- // this distance metric could be swapped/improved in the future
6373 return nearestWord ;
6474}
0 commit comments