{"version":3,"file":"fuzzy.mjs","sources":["../../../src/utils/fuzzy.ts"],"sourcesContent":["import { last } from 'lodash';\n\nimport { HighlightPart } from '../types';\n\ntype FuzzyMatch = {\n  /**\n   * Total number of unmatched letters between matched letters\n   */\n  distance: number;\n  ranges: HighlightPart[];\n  found: boolean;\n};\n\n/**\n * Attempts to do a partial input search, e.g. allowing to search for a text (needle)\n * in another text (stack) by skipping some letters in-between. All letters from\n * the needle must exist in the stack in the same order to find a match.\n *\n * The search is case sensitive. Convert stack and needle to lower case\n * to make it case insensitive.\n *\n * @param stack - main text to be searched\n * @param needle - partial text to find in the stack\n *\n * @internal\n */\nexport function fuzzyMatch(stack: string, needle: string): FuzzyMatch {\n  let distance = 0,\n    searchIndex = stack.indexOf(needle);\n  // Remove whitespace from needle as a temporary solution to treat separate string\n  // queries as 'AND'\n  needle = needle.replace(/\\s/g, '');\n\n  const ranges: HighlightPart[] = [];\n\n  if (searchIndex !== -1) {\n    return {\n      distance: 0,\n      found: true,\n      ranges: [{ start: searchIndex, end: searchIndex + needle.length - 1 }],\n    };\n  }\n\n  for (const letter of needle) {\n    const letterIndex = stack.indexOf(letter, searchIndex);\n\n    if (letterIndex === -1) {\n      return { distance: Infinity, ranges: [], found: false };\n    }\n    // do not cumulate the distance if it's the first letter\n    if (searchIndex !== -1) {\n      distance += letterIndex - searchIndex;\n    }\n    searchIndex = letterIndex + 1;\n\n    if (ranges.length === 0) {\n      ranges.push({ start: letterIndex, end: letterIndex });\n    } else {\n      const lastRange = last(ranges)!;\n      if (letterIndex === lastRange.end + 1) {\n        lastRange.end++;\n      } else {\n        ranges.push({ start: letterIndex, end: letterIndex });\n      }\n    }\n  }\n\n  return {\n    distance: distance,\n    ranges,\n    found: true,\n  };\n}\n"],"names":[],"mappings":";;AA0BgB,SAAA,UAAA,CAAW,OAAe,MAA4B,EAAA;AACpE,EAAA,IAAI,QAAW,GAAA,CAAA,EACb,WAAc,GAAA,KAAA,CAAM,QAAQ,MAAM,CAAA;AAGpC,EAAS,MAAA,GAAA,MAAA,CAAO,OAAQ,CAAA,KAAA,EAAO,EAAE,CAAA;AAEjC,EAAA,MAAM,SAA0B,EAAC;AAEjC,EAAA,IAAI,gBAAgB,CAAI,CAAA,EAAA;AACtB,IAAO,OAAA;AAAA,MACL,QAAU,EAAA,CAAA;AAAA,MACV,KAAO,EAAA,IAAA;AAAA,MACP,MAAA,EAAQ,CAAC,EAAE,KAAO,EAAA,WAAA,EAAa,KAAK,WAAc,GAAA,MAAA,CAAO,MAAS,GAAA,CAAA,EAAG;AAAA,KACvE;AAAA;AAGF,EAAA,KAAA,MAAW,UAAU,MAAQ,EAAA;AAC3B,IAAA,MAAM,WAAc,GAAA,KAAA,CAAM,OAAQ,CAAA,MAAA,EAAQ,WAAW,CAAA;AAErD,IAAA,IAAI,gBAAgB,CAAI,CAAA,EAAA;AACtB,MAAA,OAAO,EAAE,QAAU,EAAA,QAAA,EAAU,QAAQ,EAAC,EAAG,OAAO,KAAM,EAAA;AAAA;AAGxD,IAAA,IAAI,gBAAgB,CAAI,CAAA,EAAA;AACtB,MAAA,QAAA,IAAY,WAAc,GAAA,WAAA;AAAA;AAE5B,IAAA,WAAA,GAAc,WAAc,GAAA,CAAA;AAE5B,IAAI,IAAA,MAAA,CAAO,WAAW,CAAG,EAAA;AACvB,MAAA,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,WAAa,EAAA,GAAA,EAAK,aAAa,CAAA;AAAA,KAC/C,MAAA;AACL,MAAM,MAAA,SAAA,GAAY,KAAK,MAAM,CAAA;AAC7B,MAAI,IAAA,WAAA,KAAgB,SAAU,CAAA,GAAA,GAAM,CAAG,EAAA;AACrC,QAAU,SAAA,CAAA,GAAA,EAAA;AAAA,OACL,MAAA;AACL,QAAA,MAAA,CAAO,KAAK,EAAE,KAAA,EAAO,WAAa,EAAA,GAAA,EAAK,aAAa,CAAA;AAAA;AACtD;AACF;AAGF,EAAO,OAAA;AAAA,IACL,QAAA;AAAA,IACA,MAAA;AAAA,IACA,KAAO,EAAA;AAAA,GACT;AACF;;;;"}