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
JavaScript
/* 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
*/
;
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
});