UNPKG

ss-search

Version:

The most basic, yet powerful text search.

97 lines (94 loc) 4.19 kB
"use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); 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/index.ts var index_exports = {}; __export(index_exports, { convertToSearchableStrings: () => convertToSearchableStrings, getScore: () => getScore, indexDocuments: () => indexDocuments, normalize: () => normalize, search: () => search, tokenize: () => tokenize }); module.exports = __toCommonJS(index_exports); // src/lib/ss-search.ts var import_lodash_es = require("lodash-es"); var normalize = /* @__PURE__ */ __name((text) => (0, import_lodash_es.deburr)(text).replace(/[\u0300-\u036f]/g, "").toLocaleLowerCase().trim(), "normalize"); var tokenize = /* @__PURE__ */ __name((searchText) => normalize((0, import_lodash_es.escapeRegExp)(searchText)).match(/[\p{L}\d]+/gimu) || [], "tokenize"); var convertToSearchableStrings = (0, import_lodash_es.memoize)((elements, searchableKeys, _cacheKey) => { if (!elements || elements.length === 0 || !searchableKeys || searchableKeys.length === 0) { return []; } const arraySelectorRegex = /\[(.*)]/; return elements.map((element) => searchableKeys.map((key) => { const value = (0, import_lodash_es.get)(element, key.replace(arraySelectorRegex, "")); if (value === null || value === void 0 || typeof value === "function") { return ""; } const arraySelector = (0, import_lodash_es.get)(arraySelectorRegex.exec(key), "1"); if (arraySelector) { return value.map((x) => (0, import_lodash_es.get)(x, arraySelector)); } if (Array.isArray(value) || typeof value === "object") { return JSON.stringify(value); } return value; }).reduce((a, b) => a + b, "")).map((x) => normalize(x)); }, (elements, _, cacheKey) => cacheKey ?? elements); var indexDocuments = convertToSearchableStrings; var getScore = /* @__PURE__ */ __name((matchesAllSearchWords, searchWords, searchableDataString) => { if (!matchesAllSearchWords) { return 0; } const searchableDataStringWithoutNonWordCharacters = searchableDataString.replace(/[^\p{L}\d]+/gimu, ""); const remainingTextAfterRemovingSearchWords = searchWords.sort((a, b) => b.length - a.length).reduce((remainingText, searchWord) => remainingText.replace(new RegExp(searchWord, "gm"), ""), searchableDataStringWithoutNonWordCharacters); return (0, import_lodash_es.round)(1 - remainingTextAfterRemovingSearchWords.length / searchableDataStringWithoutNonWordCharacters.length, 4); }, "getScore"); function search(elements, searchableKeys, searchText, options) { const searchWords = tokenize(searchText); const searchableDataStrings = convertToSearchableStrings(elements, searchableKeys, options?.cacheKey); const results = []; for (let i = 0; i < searchableDataStrings.length; i++) { const x = searchableDataStrings[i]; const matchesAllSearchWords = searchWords.every((searchWord) => x.includes(searchWord)); if (options?.withScore) { const score = getScore(matchesAllSearchWords, searchWords, x); results.push({ element: elements[i], score }); continue; } if (matchesAllSearchWords) { results.push(elements[i]); } } return results; } __name(search, "search"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { convertToSearchableStrings, getScore, indexDocuments, normalize, search, tokenize });