UNPKG

search-fuzzy

Version:

A simple fuzzy search algorithm that uses the Levenshtein distance algorithm to find the closest match to a given string.

225 lines (217 loc) 7.64 kB
/* eslint-disable */ /** * search-fuzzy.js v 1.1.1 - Fuzzy search for Angular () * * Copyright (c) 2024 Jaswanth Darapaneni (https://github.com/jaswanthdarapaneni) * All Rights Reserved. Apache Software License 2.0 * * git: https://github.com/JaswanthDarapaneni/search-fuzzy.git */ "use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/fuzzy.ts var fuzzy_exports = {}; __export(fuzzy_exports, { Credentials: () => Credentials, fuzzySearch: () => fuzzySearch }); module.exports = __toCommonJS(fuzzy_exports); // src/utils/search/levenshtein.search.ts function levenshtein(a, b) { const alen = a.length; const blen = b.length; if (alen === 0) return blen; if (blen === 0) return alen; const dist = Array(blen + 1).fill(0).map((_, i) => i); for (let i = 0; i < alen; i++) { let prevDist = i; for (let j = 0; j < blen; j++) { const cost = a[i] === b[j] ? 0 : 1; const currentDist = Math.min( dist[j] + 1, // Deletion Math.min( prevDist + 1, // Insertion dist[j + 1] + cost ) // Substitution ); dist[j] = prevDist; prevDist = currentDist; } dist[blen] = prevDist; } return dist[blen]; } function computeLevenshtein(a, b) { return levenshtein(a, b); } var levenshtein_search_default = computeLevenshtein; // src/utils/filter/filter.data.ts function filterData(data, query, fields, limit = 10) { const queryParts = query.toLowerCase().split(" "); return data.map((item) => { let totalScore = 0; if (fields.length === 0 || fields.length === 1) { const itemString = JSON.stringify(item).toLowerCase(); queryParts.forEach((queryPart) => { const exactMatchScore = itemString.includes(queryPart) ? 0 : Number.MAX_VALUE; const levDistance = levenshtein_search_default(queryPart, itemString); const score = Math.min(exactMatchScore, levDistance); totalScore += score; }); } else { fields.forEach((field) => { if (item[field] !== void 0 && item[field] !== null) { const fieldValue = item[field].toString().toLowerCase(); queryParts.forEach((queryPart) => { const exactMatchScore = fieldValue.includes(queryPart) ? 0 : Number.MAX_VALUE; const levDistance = levenshtein_search_default(queryPart, fieldValue); const score = Math.min(exactMatchScore, levDistance); totalScore += score; }); } }); } return { item, score: totalScore }; }).sort((a, b) => a.score - b.score).slice(0, limit); } var filter_data_default = filterData; // src/utils/textUtils.ts var defaultOptions = { threshold: 0.5, maxResults: 10, ignoreCase: false, ignoreDiacritics: false, ignorePunctuation: false, ignoreWhitespace: false, ignoreNumbers: false, ignoreSymbols: false, ignoreAccents: false, ignoreCaseSensitive: false, ignoreDiacriticSensitive: false, ignorePunctuationSensitive: false, ignoreWhitespaceSensitive: false, ignoreNumbersSensitive: false, ignoreSymbolsSensitive: false, ignoreAccentsSensitive: false, ignoreCaseSensitiveSensitive: false, ignoreDiacriticSensitiveSensitive: false, ignorePunctuationSensitiveSensitive: false, ignoreWhitespaceSensitiveSensitive: false, ignoreNumbersSensitiveSensitive: false, ignoreSymbolsSensitiveSensitive: false, ignoreAccentsSensitiveSensitive: false, ignoreCaseSensitiveSensitiveSensitive: false, ignoreDiacriticSensitiveSensitiveSensitive: false }; function mergeOptions(userOptions) { return { ...defaultOptions, ...userOptions }; } function preprocessText(text, inputOptions) { if (!text) return ""; const options = mergeOptions(inputOptions); let processedText = text; if (options.ignoreCase || options.ignoreCaseSensitive) { processedText = processedText.toLowerCase(); } if (options.ignoreDiacritics || options.ignoreDiacriticSensitive) { processedText = processedText.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); } if (options.ignorePunctuation || options.ignorePunctuationSensitive) { processedText = processedText.replace(/[.,/#!$%^&*;:{}=\-_`~()]/g, ""); } if (options.ignoreWhitespace || options.ignoreWhitespaceSensitive) { processedText = processedText.replace(/\s+/g, " ").trim(); } if (options.ignoreNumbers || options.ignoreNumbersSensitive) { processedText = processedText.replace(/\d+/g, ""); } if (options.ignoreSymbols || options.ignoreSymbolsSensitive) { processedText = processedText.replace(/[\W_]+/g, ""); } if (options.ignoreAccents || options.ignoreAccentsSensitive) { processedText = processedText.normalize("NFD").replace(/[\u0300-\u036f]/g, ""); } return processedText; } var textUtils_default = preprocessText; // src/funtions.ts async function fuzzySearch(data, fields, query, apiConfig, options) { let dataToSearch = data; let searchFields = fields; const text = textUtils_default(query.query, options); if (apiConfig?.useApi) { try { const url = new URL(apiConfig.url); if (apiConfig.params) { Object.keys(apiConfig.params || {}).forEach( (key) => url.searchParams.append(key, apiConfig.params?.[key] || "") ); } const response = await fetch(url.toString(), { method: "GET", body: apiConfig.body ? JSON.stringify(apiConfig.body) : void 0, credentials: apiConfig.credentials || void 0, headers: apiConfig.headers, keepalive: apiConfig.keepalive || false }); if (!response.ok) { throw new Error(`HTTP error! Status: ${response.status}`); } const apiData = await response.json(); dataToSearch = apiData; if (!searchFields && Array.isArray(apiData) && apiData.length > 0) { searchFields = Object.keys(apiData[0]); } } catch (error) { console.error("Error fetching data from API:", error); return []; } if (!searchFields && Array.isArray(dataToSearch) && dataToSearch.length > 0) { searchFields = Object.keys(dataToSearch[0]); } const filteredData = filter_data_default( dataToSearch, text, searchFields, options?.maxResults ); return filteredData.map((item) => item.item); } else { if (data.length === 0) { throw new Error("Data is empty"); } const filteredData = filter_data_default(data, text, fields, options?.maxResults); return filteredData.map((item) => item.item); } } // src/types.ts var Credentials = /* @__PURE__ */ ((Credentials2) => { Credentials2["Omit"] = "omit"; Credentials2["SameOrigin"] = "same-origin"; Credentials2["Include"] = "include"; return Credentials2; })(Credentials || {}); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Credentials, fuzzySearch });