{"version":3,"sources":["../src/filters.ts"],"names":["simpleFilter","options","query","normalizedQuery","option","labelMatch","keywordMatch","k","startsWithFilter","fuzzyFilter","queryChars","text","score","lastIndex","consecutiveMatches","char","index","item","a","b","createRegexFilter","pattern","flags","regex"],"mappings":"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","file":"filters.mjs","sourcesContent":["import type { CommandOption, FilterFunction } from \"./core\";\n\n/**\n * Case-insensitive contains match across label and keywords.\n */\nexport const simpleFilter: FilterFunction = (options, query) => {\n  if (!query) return options;\n\n  const normalizedQuery = query.toLowerCase();\n\n  return options.filter((option) => {\n    if (option.disabled) return false;\n\n    const labelMatch = option.label.toLowerCase().includes(normalizedQuery);\n    const keywordMatch = option.keywords?.some((k) =>\n      k.toLowerCase().includes(normalizedQuery)\n    );\n\n    return labelMatch || keywordMatch;\n  });\n};\n\n/**\n * Case-insensitive starts-with match across label and keywords.\n */\nexport const startsWithFilter: FilterFunction = (options, query) => {\n  if (!query) return options;\n\n  const normalizedQuery = query.toLowerCase();\n\n  return options.filter((option) => {\n    if (option.disabled) return false;\n\n    const labelMatch = option.label.toLowerCase().startsWith(normalizedQuery);\n    const keywordMatch = option.keywords?.some((k) =>\n      k.toLowerCase().startsWith(normalizedQuery)\n    );\n\n    return labelMatch || keywordMatch;\n  });\n};\n\n/**\n * Simple fuzzy matcher that rewards consecutive and word-boundary matches.\n */\nexport const fuzzyFilter: FilterFunction = (options, query) => {\n  if (!query) return options;\n\n  const normalizedQuery = query.toLowerCase();\n  const queryChars = normalizedQuery.split(\"\");\n\n  const scored = options\n    .filter((option) => !option.disabled)\n    .map((option) => {\n      const text =\n        `${option.label} ${option.keywords?.join(\" \") || \"\"}`.toLowerCase();\n      let score = 0;\n      let lastIndex = -1;\n      let consecutiveMatches = 0;\n\n      for (const char of queryChars) {\n        const index = text.indexOf(char, lastIndex + 1);\n        if (index === -1) {\n          return null;\n        }\n\n        if (index === lastIndex + 1) {\n          consecutiveMatches++;\n          score += 10 * consecutiveMatches;\n        } else {\n          consecutiveMatches = 0;\n          score += 1;\n        }\n\n        if (index === 0 || text[index - 1] === \" \") {\n          score += 5;\n        }\n\n        lastIndex = index;\n      }\n\n      score -= text.length * 0.1;\n\n      return { option, score };\n    })\n    .filter(\n      (item): item is { option: CommandOption; score: number } => item !== null\n    )\n    .sort((a, b) => b.score - a.score)\n    .map((item) => item.option);\n\n  return scored;\n};\n\n/**\n * Build a filter using a regex pattern where `{{query}}` is replaced\n * by the user's query at evaluation time.\n */\nexport function createRegexFilter(\n  pattern: string,\n  flags?: string\n): FilterFunction {\n  return (options, query) => {\n    if (!query) return options;\n\n    try {\n      const regex = new RegExp(pattern.replace(\"{{query}}\", query), flags);\n\n      return options.filter((option) => {\n        if (option.disabled) return false;\n\n        const text = `${option.label} ${option.keywords?.join(\" \") || \"\"}`;\n        return regex.test(text);\n      });\n    } catch {\n      return [];\n    }\n  };\n}\n"]}