@nexucis/fuzzy
Advanced tools
| "use strict"; | ||
| // MIT License | ||
| // | ||
| // Copyright (c) 2020 Augustin Husson | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to deal | ||
| // in the Software without restriction, including without limitation the rights | ||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| // copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in all | ||
| // copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| // SOFTWARE. | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.render = exports.match = exports.filter = exports.Fuzzy = exports.score = void 0; | ||
| function escapeHTML(text) { | ||
| return text.replace(/[&<>"']/g, (m) => { | ||
| switch (m) { | ||
| case '&': | ||
| return '&'; | ||
| case '<': | ||
| return '<'; | ||
| case '>': | ||
| return '>'; | ||
| case '"': | ||
| return '"'; | ||
| default: | ||
| return '''; | ||
| } | ||
| }); | ||
| } | ||
| function intervalSize(interval) { | ||
| return interval.to - interval.from + 1; | ||
| } | ||
| function calculatePreviousNotMatchingInterval(intervals, idx) { | ||
| const currentInterval = intervals[idx]; | ||
| let previousNotMatchingInterval = null; | ||
| if (idx === 0 && currentInterval.from !== 0) { | ||
| previousNotMatchingInterval = { from: 0, to: currentInterval.from - 1 }; | ||
| } | ||
| if (idx > 0) { | ||
| previousNotMatchingInterval = { from: intervals[idx - 1].to + 1, to: currentInterval.from - 1 }; | ||
| } | ||
| return previousNotMatchingInterval; | ||
| } | ||
| // score should be used to calculate the score based on the intervals created during the matching step. | ||
| // Here is how the score is determinated: | ||
| // 1. Consecutive characters should increase the score more than linearly | ||
| // 2. More there is a distance between the characters, higher it reduces the score | ||
| // For example, for the pattern 'abc', the following string are sorted by the highest score | ||
| // abcdef > defabc > abec > defabec | ||
| // Note: this function is exported only for testing purpose. | ||
| function score(intervals, strLength) { | ||
| let result = 0; | ||
| for (let i = 0; i < intervals.length; i++) { | ||
| const currentInterval = intervals[i]; | ||
| const previousNotMatchingInterval = calculatePreviousNotMatchingInterval(intervals, i); | ||
| if (previousNotMatchingInterval !== null) { | ||
| result = result - intervalSize(previousNotMatchingInterval) / strLength; | ||
| } | ||
| result = result + intervalSize(currentInterval) ** 2; | ||
| } | ||
| return result; | ||
| } | ||
| exports.score = score; | ||
| // generateMatchingInterval will iterate other the given text to find the different char that matched the given pattern | ||
| function generateMatchingInterval(pattern, text, idxText) { | ||
| let patternIdx = 0; | ||
| const intervals = []; | ||
| for (let i = idxText; i < text.length && patternIdx < pattern.length;) { | ||
| if (text[i] === pattern[patternIdx]) { | ||
| const interval = { from: i, to: i }; | ||
| patternIdx++; | ||
| i++; | ||
| for (let j = i; j < text.length && patternIdx < pattern.length && text[j] === pattern[patternIdx]; j++) { | ||
| interval.to = j; | ||
| patternIdx++; | ||
| i = j; | ||
| } | ||
| intervals.push(interval); | ||
| } | ||
| i++; | ||
| } | ||
| if (intervals.length === 0 || patternIdx !== pattern.length) { | ||
| return null; | ||
| } | ||
| return { score: score(intervals, text.length), intervals: intervals }; | ||
| } | ||
| class Fuzzy { | ||
| constructor(conf) { | ||
| this.conf = { | ||
| caseSensitive: (conf === null || conf === void 0 ? void 0 : conf.caseSensitive) === undefined ? false : conf.caseSensitive, | ||
| includeMatches: (conf === null || conf === void 0 ? void 0 : conf.includeMatches) === undefined ? false : conf.includeMatches, | ||
| shouldSort: (conf === null || conf === void 0 ? void 0 : conf.shouldSort) === undefined ? false : conf.shouldSort, | ||
| escapeHTML: (conf === null || conf === void 0 ? void 0 : conf.escapeHTML) === undefined ? false : conf.escapeHTML, | ||
| pre: (conf === null || conf === void 0 ? void 0 : conf.pre) === undefined ? '' : conf.pre, | ||
| post: (conf === null || conf === void 0 ? void 0 : conf.post) === undefined ? '' : conf.post, | ||
| }; | ||
| } | ||
| // filter is the method to use to filter a string list | ||
| // list of result return can be sort if parameter `shouldSort` is set. | ||
| filter(pattern, list, conf) { | ||
| const shouldSort = (conf === null || conf === void 0 ? void 0 : conf.shouldSort) !== undefined ? conf.shouldSort : this.conf.shouldSort; | ||
| let result = []; | ||
| for (let i = 0; i < list.length; i++) { | ||
| const matchedText = this.match(pattern, list[i], conf); | ||
| if (matchedText !== null) { | ||
| matchedText.index = i; | ||
| result.push(matchedText); | ||
| } | ||
| } | ||
| if (shouldSort) { | ||
| result = result.sort((a, b) => { | ||
| return b.score - a.score; | ||
| }); | ||
| } | ||
| return result; | ||
| } | ||
| // match will return a result if `pattern` is matching `text`, | ||
| match(pattern, text, conf) { | ||
| let localPattern = pattern; | ||
| let localText = text; | ||
| const caseSensitive = (conf === null || conf === void 0 ? void 0 : conf.caseSensitive) !== undefined ? conf.caseSensitive : this.conf.caseSensitive; | ||
| const includeMatches = (conf === null || conf === void 0 ? void 0 : conf.includeMatches) !== undefined ? conf.includeMatches : this.conf.includeMatches; | ||
| if (!caseSensitive) { | ||
| localPattern = localPattern.toLowerCase(); | ||
| localText = localText.toLowerCase(); | ||
| } | ||
| // in case it's a perfect match, no need to loop to find which char is matching | ||
| if (localPattern === localText) { | ||
| const intervals = [{ from: 0, to: pattern.length - 1 }]; | ||
| const result = { | ||
| original: text, | ||
| rendered: this.render(text, intervals, conf), | ||
| score: Infinity, | ||
| }; | ||
| if (includeMatches) { | ||
| result.intervals = intervals; | ||
| } | ||
| return result; | ||
| } | ||
| // otherwise let's calculate the different indices that will then be used to calculate the score | ||
| let intervals = []; | ||
| let score = 0; | ||
| for (let i = 0; i < localText.length - localPattern.length + 1; i++) { | ||
| // Each time a char is matching the first char of the pattern | ||
| // loop other the rest of the text to generate the different matching interval. | ||
| // Like that we will be able to find the best matching possibility. | ||
| // For example: given the pattern `bac` and the text `babac` | ||
| // instead of matching `<ba>ba<c>, it will match ba<bac> which has a better score than the previous one. | ||
| if (localText[i] === localPattern[0]) { | ||
| const matchingResult = generateMatchingInterval(localPattern, localText, i); | ||
| if (matchingResult === null) { | ||
| break; | ||
| } | ||
| if (matchingResult.score > score) { | ||
| score = matchingResult.score; | ||
| intervals = matchingResult.intervals; | ||
| } | ||
| } | ||
| } | ||
| if (intervals.length === 0) { | ||
| return null; | ||
| } | ||
| const result = { | ||
| original: text, | ||
| rendered: this.render(text, intervals, conf), | ||
| score: score, | ||
| }; | ||
| if (includeMatches) { | ||
| result.intervals = intervals; | ||
| } | ||
| return result; | ||
| } | ||
| // render will modify the text according to the different parameter set in the conf. | ||
| // If nothing is set, then it will return the text not modified. | ||
| render(text, intervals, conf) { | ||
| let rendered = ''; | ||
| const pre = (conf === null || conf === void 0 ? void 0 : conf.pre) ? conf.pre : this.conf.pre; | ||
| const post = (conf === null || conf === void 0 ? void 0 : conf.post) ? conf.post : this.conf.post; | ||
| for (let i = 0; i < intervals.length; i++) { | ||
| const currentInterval = intervals[i]; | ||
| const previousNotMatchingInterval = calculatePreviousNotMatchingInterval(intervals, i); | ||
| let previousStr = ''; | ||
| if (previousNotMatchingInterval !== null) { | ||
| previousStr = this.extractSubString(text, previousNotMatchingInterval, conf); | ||
| } | ||
| const currentStr = this.extractSubString(text, currentInterval, conf); | ||
| rendered = `${rendered}${previousStr}${pre}${currentStr}${post}`; | ||
| } | ||
| // check if the last interval contains the end of the string. Otherwise add it | ||
| const lastInterval = intervals[intervals.length - 1]; | ||
| if (lastInterval.to < text.length - 1) { | ||
| rendered = rendered + this.extractSubString(text, { from: lastInterval.to + 1, to: text.length }, conf); | ||
| } | ||
| return rendered; | ||
| } | ||
| extractSubString(text, interval, conf) { | ||
| const shouldEscape = (conf === null || conf === void 0 ? void 0 : conf.escapeHTML) !== undefined ? conf.escapeHTML : this.conf.escapeHTML; | ||
| let str = text.substr(interval.from, intervalSize(interval)); | ||
| if (shouldEscape) { | ||
| str = escapeHTML(str); | ||
| } | ||
| return str; | ||
| } | ||
| } | ||
| exports.Fuzzy = Fuzzy; | ||
| const fuz = new Fuzzy(); | ||
| function filter(pattern, list, conf) { | ||
| return fuz.filter(pattern, list, conf); | ||
| } | ||
| exports.filter = filter; | ||
| function match(pattern, text, conf) { | ||
| return fuz.match(pattern, text, conf); | ||
| } | ||
| exports.match = match; | ||
| function render(text, intervals, conf) { | ||
| return fuz.render(text, intervals, conf); | ||
| } | ||
| exports.render = render; |
| export declare function score(intervals: FuzzyMatchingInterval[], strLength: number): number; | ||
| export interface FuzzyConfiguration { | ||
| caseSensitive?: boolean; | ||
| includeMatches?: boolean; | ||
| shouldSort?: boolean; | ||
| escapeHTML?: boolean; | ||
| pre?: string; | ||
| post?: string; | ||
| } | ||
| export interface FuzzyMatchingInterval { | ||
| from: number; | ||
| to: number; | ||
| } | ||
| export interface FuzzyResult { | ||
| rendered: string; | ||
| original: string; | ||
| index: number; | ||
| score: number; | ||
| intervals?: FuzzyMatchingInterval[]; | ||
| } | ||
| export declare class Fuzzy { | ||
| private readonly conf; | ||
| constructor(conf?: FuzzyConfiguration); | ||
| filter(pattern: string, list: string[], conf?: FuzzyConfiguration): FuzzyResult[]; | ||
| match(pattern: string, text: string, conf?: FuzzyConfiguration): FuzzyResult | null; | ||
| render(text: string, intervals: FuzzyMatchingInterval[], conf?: FuzzyConfiguration): string; | ||
| private extractSubString; | ||
| } | ||
| export declare function filter(pattern: string, list: string[], conf?: FuzzyConfiguration): FuzzyResult[]; | ||
| export declare function match(pattern: string, text: string, conf?: FuzzyConfiguration): FuzzyResult | null; | ||
| export declare function render(text: string, intervals: FuzzyMatchingInterval[], conf?: FuzzyConfiguration): string; |
+221
| // MIT License | ||
| // | ||
| // Copyright (c) 2020 Augustin Husson | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to deal | ||
| // in the Software without restriction, including without limitation the rights | ||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| // copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in all | ||
| // copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| // SOFTWARE. | ||
| function escapeHTML(text) { | ||
| return text.replace(/[&<>"']/g, (m) => { | ||
| switch (m) { | ||
| case '&': | ||
| return '&'; | ||
| case '<': | ||
| return '<'; | ||
| case '>': | ||
| return '>'; | ||
| case '"': | ||
| return '"'; | ||
| default: | ||
| return '''; | ||
| } | ||
| }); | ||
| } | ||
| function intervalSize(interval) { | ||
| return interval.to - interval.from + 1; | ||
| } | ||
| function calculatePreviousNotMatchingInterval(intervals, idx) { | ||
| const currentInterval = intervals[idx]; | ||
| let previousNotMatchingInterval = null; | ||
| if (idx === 0 && currentInterval.from !== 0) { | ||
| previousNotMatchingInterval = { from: 0, to: currentInterval.from - 1 }; | ||
| } | ||
| if (idx > 0) { | ||
| previousNotMatchingInterval = { from: intervals[idx - 1].to + 1, to: currentInterval.from - 1 }; | ||
| } | ||
| return previousNotMatchingInterval; | ||
| } | ||
| // score should be used to calculate the score based on the intervals created during the matching step. | ||
| // Here is how the score is determinated: | ||
| // 1. Consecutive characters should increase the score more than linearly | ||
| // 2. More there is a distance between the characters, higher it reduces the score | ||
| // For example, for the pattern 'abc', the following string are sorted by the highest score | ||
| // abcdef > defabc > abec > defabec | ||
| // Note: this function is exported only for testing purpose. | ||
| export function score(intervals, strLength) { | ||
| let result = 0; | ||
| for (let i = 0; i < intervals.length; i++) { | ||
| const currentInterval = intervals[i]; | ||
| const previousNotMatchingInterval = calculatePreviousNotMatchingInterval(intervals, i); | ||
| if (previousNotMatchingInterval !== null) { | ||
| result = result - intervalSize(previousNotMatchingInterval) / strLength; | ||
| } | ||
| result = result + intervalSize(currentInterval) ** 2; | ||
| } | ||
| return result; | ||
| } | ||
| // generateMatchingInterval will iterate other the given text to find the different char that matched the given pattern | ||
| function generateMatchingInterval(pattern, text, idxText) { | ||
| let patternIdx = 0; | ||
| const intervals = []; | ||
| for (let i = idxText; i < text.length && patternIdx < pattern.length;) { | ||
| if (text[i] === pattern[patternIdx]) { | ||
| const interval = { from: i, to: i }; | ||
| patternIdx++; | ||
| i++; | ||
| for (let j = i; j < text.length && patternIdx < pattern.length && text[j] === pattern[patternIdx]; j++) { | ||
| interval.to = j; | ||
| patternIdx++; | ||
| i = j; | ||
| } | ||
| intervals.push(interval); | ||
| } | ||
| i++; | ||
| } | ||
| if (intervals.length === 0 || patternIdx !== pattern.length) { | ||
| return null; | ||
| } | ||
| return { score: score(intervals, text.length), intervals: intervals }; | ||
| } | ||
| export class Fuzzy { | ||
| constructor(conf) { | ||
| this.conf = { | ||
| caseSensitive: (conf === null || conf === void 0 ? void 0 : conf.caseSensitive) === undefined ? false : conf.caseSensitive, | ||
| includeMatches: (conf === null || conf === void 0 ? void 0 : conf.includeMatches) === undefined ? false : conf.includeMatches, | ||
| shouldSort: (conf === null || conf === void 0 ? void 0 : conf.shouldSort) === undefined ? false : conf.shouldSort, | ||
| escapeHTML: (conf === null || conf === void 0 ? void 0 : conf.escapeHTML) === undefined ? false : conf.escapeHTML, | ||
| pre: (conf === null || conf === void 0 ? void 0 : conf.pre) === undefined ? '' : conf.pre, | ||
| post: (conf === null || conf === void 0 ? void 0 : conf.post) === undefined ? '' : conf.post, | ||
| }; | ||
| } | ||
| // filter is the method to use to filter a string list | ||
| // list of result return can be sort if parameter `shouldSort` is set. | ||
| filter(pattern, list, conf) { | ||
| const shouldSort = (conf === null || conf === void 0 ? void 0 : conf.shouldSort) !== undefined ? conf.shouldSort : this.conf.shouldSort; | ||
| let result = []; | ||
| for (let i = 0; i < list.length; i++) { | ||
| const matchedText = this.match(pattern, list[i], conf); | ||
| if (matchedText !== null) { | ||
| matchedText.index = i; | ||
| result.push(matchedText); | ||
| } | ||
| } | ||
| if (shouldSort) { | ||
| result = result.sort((a, b) => { | ||
| return b.score - a.score; | ||
| }); | ||
| } | ||
| return result; | ||
| } | ||
| // match will return a result if `pattern` is matching `text`, | ||
| match(pattern, text, conf) { | ||
| let localPattern = pattern; | ||
| let localText = text; | ||
| const caseSensitive = (conf === null || conf === void 0 ? void 0 : conf.caseSensitive) !== undefined ? conf.caseSensitive : this.conf.caseSensitive; | ||
| const includeMatches = (conf === null || conf === void 0 ? void 0 : conf.includeMatches) !== undefined ? conf.includeMatches : this.conf.includeMatches; | ||
| if (!caseSensitive) { | ||
| localPattern = localPattern.toLowerCase(); | ||
| localText = localText.toLowerCase(); | ||
| } | ||
| // in case it's a perfect match, no need to loop to find which char is matching | ||
| if (localPattern === localText) { | ||
| const intervals = [{ from: 0, to: pattern.length - 1 }]; | ||
| const result = { | ||
| original: text, | ||
| rendered: this.render(text, intervals, conf), | ||
| score: Infinity, | ||
| }; | ||
| if (includeMatches) { | ||
| result.intervals = intervals; | ||
| } | ||
| return result; | ||
| } | ||
| // otherwise let's calculate the different indices that will then be used to calculate the score | ||
| let intervals = []; | ||
| let score = 0; | ||
| for (let i = 0; i < localText.length - localPattern.length + 1; i++) { | ||
| // Each time a char is matching the first char of the pattern | ||
| // loop other the rest of the text to generate the different matching interval. | ||
| // Like that we will be able to find the best matching possibility. | ||
| // For example: given the pattern `bac` and the text `babac` | ||
| // instead of matching `<ba>ba<c>, it will match ba<bac> which has a better score than the previous one. | ||
| if (localText[i] === localPattern[0]) { | ||
| const matchingResult = generateMatchingInterval(localPattern, localText, i); | ||
| if (matchingResult === null) { | ||
| break; | ||
| } | ||
| if (matchingResult.score > score) { | ||
| score = matchingResult.score; | ||
| intervals = matchingResult.intervals; | ||
| } | ||
| } | ||
| } | ||
| if (intervals.length === 0) { | ||
| return null; | ||
| } | ||
| const result = { | ||
| original: text, | ||
| rendered: this.render(text, intervals, conf), | ||
| score: score, | ||
| }; | ||
| if (includeMatches) { | ||
| result.intervals = intervals; | ||
| } | ||
| return result; | ||
| } | ||
| // render will modify the text according to the different parameter set in the conf. | ||
| // If nothing is set, then it will return the text not modified. | ||
| render(text, intervals, conf) { | ||
| let rendered = ''; | ||
| const pre = (conf === null || conf === void 0 ? void 0 : conf.pre) ? conf.pre : this.conf.pre; | ||
| const post = (conf === null || conf === void 0 ? void 0 : conf.post) ? conf.post : this.conf.post; | ||
| for (let i = 0; i < intervals.length; i++) { | ||
| const currentInterval = intervals[i]; | ||
| const previousNotMatchingInterval = calculatePreviousNotMatchingInterval(intervals, i); | ||
| let previousStr = ''; | ||
| if (previousNotMatchingInterval !== null) { | ||
| previousStr = this.extractSubString(text, previousNotMatchingInterval, conf); | ||
| } | ||
| const currentStr = this.extractSubString(text, currentInterval, conf); | ||
| rendered = `${rendered}${previousStr}${pre}${currentStr}${post}`; | ||
| } | ||
| // check if the last interval contains the end of the string. Otherwise add it | ||
| const lastInterval = intervals[intervals.length - 1]; | ||
| if (lastInterval.to < text.length - 1) { | ||
| rendered = rendered + this.extractSubString(text, { from: lastInterval.to + 1, to: text.length }, conf); | ||
| } | ||
| return rendered; | ||
| } | ||
| extractSubString(text, interval, conf) { | ||
| const shouldEscape = (conf === null || conf === void 0 ? void 0 : conf.escapeHTML) !== undefined ? conf.escapeHTML : this.conf.escapeHTML; | ||
| let str = text.substr(interval.from, intervalSize(interval)); | ||
| if (shouldEscape) { | ||
| str = escapeHTML(str); | ||
| } | ||
| return str; | ||
| } | ||
| } | ||
| const fuz = new Fuzzy(); | ||
| export function filter(pattern, list, conf) { | ||
| return fuz.filter(pattern, list, conf); | ||
| } | ||
| export function match(pattern, text, conf) { | ||
| return fuz.match(pattern, text, conf); | ||
| } | ||
| export function render(text, intervals, conf) { | ||
| return fuz.render(text, intervals, conf); | ||
| } |
+21
| MIT License | ||
| Copyright (c) 2020 Augustin Husson | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
+20
-16
| { | ||
| "name": "@nexucis/fuzzy", | ||
| "version": "0.3.0", | ||
| "version": "0.4.0", | ||
| "description": "small, standalone fuzzy search / fuzzy filter. browser or node", | ||
| "main": "index.js", | ||
| "module": "dist/index.js", | ||
| "main": "dist/cjs/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "scripts": { | ||
| "build": "tsc", | ||
| "test": "mocha -r ts-node/register src/**/*.test.ts", | ||
| "test-coverage": "nyc mocha -r ts-node/register src/**/*.test.ts", | ||
| "build:cjs": "tsc --project ./tsconfig.cjs.json", | ||
| "test": "ts-mocha -n loader=ts-node/esm -p tsconfig.cjs.json src/**/*.test.ts", | ||
| "test-coverage": "nyc ts-mocha -n loader=ts-node/esm -p tsconfig.cjs.json src/**/*.test.ts", | ||
| "codecov": "nyc report --reporter=text-lcov > coverage.lcov && codecov", | ||
@@ -30,16 +33,17 @@ "lint": "eslint src/ --ext .ts", | ||
| "devDependencies": { | ||
| "@types/chai": "^4.2.12", | ||
| "@types/mocha": "^8.0.2", | ||
| "@typescript-eslint/eslint-plugin": "^2.22.0", | ||
| "@typescript-eslint/parser": "^2.22.0", | ||
| "chai": "^4.2.0", | ||
| "codecov": "^3.7.2", | ||
| "eslint": "^6.0.0", | ||
| "eslint-plugin-flowtype": "^5.2.0", | ||
| "eslint-plugin-import": "^2.22.0", | ||
| "mocha": "^8.1.1", | ||
| "@types/chai": "^4.3.1", | ||
| "@types/mocha": "^9.1.1", | ||
| "@typescript-eslint/eslint-plugin": "^5.25.0", | ||
| "@typescript-eslint/parser": "^5.25.0", | ||
| "chai": "^4.3.6", | ||
| "codecov": "^3.8.3", | ||
| "eslint": "^8.15.0", | ||
| "eslint-plugin-flowtype": "^8.0.3", | ||
| "eslint-plugin-import": "^2.26.0", | ||
| "mocha": "^9.2.2", | ||
| "nyc": "^15.1.0", | ||
| "ts-node": "^8.10.2", | ||
| "typescript": "^3.9.7" | ||
| "ts-mocha": "^9.0.2", | ||
| "ts-node": "^10.7.0", | ||
| "typescript": "^4.6.4" | ||
| } | ||
| } |
-31
| export declare function score(intervals: FuzzyMatchingInterval[], strLength: number): number; | ||
| export interface FuzzyConfiguration { | ||
| caseSensitive?: boolean; | ||
| includeMatches?: boolean; | ||
| shouldSort?: boolean; | ||
| escapeHTML?: boolean; | ||
| pre?: string; | ||
| post?: string; | ||
| } | ||
| export interface FuzzyMatchingInterval { | ||
| from: number; | ||
| to: number; | ||
| } | ||
| export interface FuzzyResult { | ||
| rendered: string; | ||
| original: string; | ||
| index: number; | ||
| score: number; | ||
| intervals?: FuzzyMatchingInterval[]; | ||
| } | ||
| export declare class Fuzzy { | ||
| private readonly conf; | ||
| constructor(conf?: FuzzyConfiguration); | ||
| filter(pattern: string, list: string[], conf?: FuzzyConfiguration): FuzzyResult[]; | ||
| match(pattern: string, text: string, conf?: FuzzyConfiguration): FuzzyResult | null; | ||
| render(text: string, intervals: FuzzyMatchingInterval[], conf?: FuzzyConfiguration): string; | ||
| private extractSubString; | ||
| } | ||
| export declare function filter(pattern: string, list: string[], conf?: FuzzyConfiguration): FuzzyResult[]; | ||
| export declare function match(pattern: string, text: string, conf?: FuzzyConfiguration): FuzzyResult | null; | ||
| export declare function render(text: string, intervals: FuzzyMatchingInterval[], conf?: FuzzyConfiguration): string; |
-230
| "use strict"; | ||
| // MIT License | ||
| // | ||
| // Copyright (c) 2020 Augustin Husson | ||
| // | ||
| // Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| // of this software and associated documentation files (the "Software"), to deal | ||
| // in the Software without restriction, including without limitation the rights | ||
| // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| // copies of the Software, and to permit persons to whom the Software is | ||
| // furnished to do so, subject to the following conditions: | ||
| // | ||
| // The above copyright notice and this permission notice shall be included in all | ||
| // copies or substantial portions of the Software. | ||
| // | ||
| // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| // SOFTWARE. | ||
| Object.defineProperty(exports, "__esModule", { value: true }); | ||
| exports.render = exports.match = exports.filter = exports.Fuzzy = exports.score = void 0; | ||
| function escapeHTML(text) { | ||
| return text.replace(/[&<>"']/g, (m) => { | ||
| switch (m) { | ||
| case '&': | ||
| return '&'; | ||
| case '<': | ||
| return '<'; | ||
| case '>': | ||
| return '>'; | ||
| case '"': | ||
| return '"'; | ||
| default: | ||
| return '''; | ||
| } | ||
| }); | ||
| } | ||
| function intervalSize(interval) { | ||
| return interval.to - interval.from + 1; | ||
| } | ||
| function calculatePreviousNotMatchingInterval(intervals, idx) { | ||
| const currentInterval = intervals[idx]; | ||
| let previousNotMatchingInterval = null; | ||
| if (idx === 0 && currentInterval.from !== 0) { | ||
| previousNotMatchingInterval = { from: 0, to: currentInterval.from - 1 }; | ||
| } | ||
| if (idx > 0) { | ||
| previousNotMatchingInterval = { from: intervals[idx - 1].to + 1, to: currentInterval.from - 1 }; | ||
| } | ||
| return previousNotMatchingInterval; | ||
| } | ||
| // score should be used to calculate the score based on the intervals created during the matching step. | ||
| // Here is how the score is determinated: | ||
| // 1. Consecutive characters should increase the score more than linearly | ||
| // 2. More there is a distance between the characters, higher it reduces the score | ||
| // For example, for the pattern 'abc', the following string are sorted by the highest score | ||
| // abcdef > defabc > abec > defabec | ||
| // Note: this function is exported only for testing purpose. | ||
| function score(intervals, strLength) { | ||
| let result = 0; | ||
| for (let i = 0; i < intervals.length; i++) { | ||
| const currentInterval = intervals[i]; | ||
| const previousNotMatchingInterval = calculatePreviousNotMatchingInterval(intervals, i); | ||
| if (previousNotMatchingInterval !== null) { | ||
| result = result - intervalSize(previousNotMatchingInterval) / strLength; | ||
| } | ||
| result = result + Math.pow(intervalSize(currentInterval), 2); | ||
| } | ||
| return result; | ||
| } | ||
| exports.score = score; | ||
| // generateMatchingInterval will iterate other the given text to find the different char that matched the given pattern | ||
| function generateMatchingInterval(pattern, text, idxText) { | ||
| let patternIdx = 0; | ||
| const intervals = []; | ||
| for (let i = idxText; i < text.length && patternIdx < pattern.length;) { | ||
| if (text[i] === pattern[patternIdx]) { | ||
| const interval = { from: i, to: i }; | ||
| patternIdx++; | ||
| i++; | ||
| for (let j = i; j < text.length && patternIdx < pattern.length && text[j] === pattern[patternIdx]; j++) { | ||
| interval.to = j; | ||
| patternIdx++; | ||
| i = j; | ||
| } | ||
| intervals.push(interval); | ||
| } | ||
| i++; | ||
| } | ||
| if (intervals.length === 0 || patternIdx !== pattern.length) { | ||
| return null; | ||
| } | ||
| return { score: score(intervals, text.length), intervals: intervals }; | ||
| } | ||
| class Fuzzy { | ||
| constructor(conf) { | ||
| this.conf = { | ||
| caseSensitive: (conf === null || conf === void 0 ? void 0 : conf.caseSensitive) === undefined ? false : conf.caseSensitive, | ||
| includeMatches: (conf === null || conf === void 0 ? void 0 : conf.includeMatches) === undefined ? false : conf.includeMatches, | ||
| shouldSort: (conf === null || conf === void 0 ? void 0 : conf.shouldSort) === undefined ? false : conf.shouldSort, | ||
| escapeHTML: (conf === null || conf === void 0 ? void 0 : conf.escapeHTML) === undefined ? false : conf.escapeHTML, | ||
| pre: (conf === null || conf === void 0 ? void 0 : conf.pre) === undefined ? '' : conf.pre, | ||
| post: (conf === null || conf === void 0 ? void 0 : conf.post) === undefined ? '' : conf.post, | ||
| }; | ||
| } | ||
| // filter is the method to use to filter a string list | ||
| // list of result return can be sort if parameter `shouldSort` is set. | ||
| filter(pattern, list, conf) { | ||
| const shouldSort = (conf === null || conf === void 0 ? void 0 : conf.shouldSort) !== undefined ? conf.shouldSort : this.conf.shouldSort; | ||
| let result = []; | ||
| for (let i = 0; i < list.length; i++) { | ||
| const matchedText = this.match(pattern, list[i], conf); | ||
| if (matchedText !== null) { | ||
| matchedText.index = i; | ||
| result.push(matchedText); | ||
| } | ||
| } | ||
| if (shouldSort) { | ||
| result = result.sort((a, b) => { | ||
| return b.score - a.score; | ||
| }); | ||
| } | ||
| return result; | ||
| } | ||
| // match will return a result if `pattern` is matching `text`, | ||
| match(pattern, text, conf) { | ||
| let localPattern = pattern; | ||
| let localText = text; | ||
| const caseSensitive = (conf === null || conf === void 0 ? void 0 : conf.caseSensitive) !== undefined ? conf.caseSensitive : this.conf.caseSensitive; | ||
| const includeMatches = (conf === null || conf === void 0 ? void 0 : conf.includeMatches) !== undefined ? conf.includeMatches : this.conf.includeMatches; | ||
| if (!caseSensitive) { | ||
| localPattern = localPattern.toLowerCase(); | ||
| localText = localText.toLowerCase(); | ||
| } | ||
| // in case it's a perfect match, no need to loop to find which char is matching | ||
| if (localPattern === localText) { | ||
| const intervals = [{ from: 0, to: pattern.length - 1 }]; | ||
| const result = { | ||
| original: text, | ||
| rendered: this.render(text, intervals, conf), | ||
| score: Infinity, | ||
| }; | ||
| if (includeMatches) { | ||
| result.intervals = intervals; | ||
| } | ||
| return result; | ||
| } | ||
| // otherwise let's calculate the different indices that will then be used to calculate the score | ||
| let intervals = []; | ||
| let score = 0; | ||
| for (let i = 0; i < localText.length - localPattern.length + 1; i++) { | ||
| // Each time a char is matching the first char of the pattern | ||
| // loop other the rest of the text to generate the different matching interval. | ||
| // Like that we will be able to find the best matching possibility. | ||
| // For example: given the pattern `bac` and the text `babac` | ||
| // instead of matching `<ba>ba<c>, it will match ba<bac> which has a better score than the previous one. | ||
| if (localText[i] === localPattern[0]) { | ||
| const matchingResult = generateMatchingInterval(localPattern, localText, i); | ||
| if (matchingResult === null) { | ||
| break; | ||
| } | ||
| if (matchingResult.score > score) { | ||
| score = matchingResult.score; | ||
| intervals = matchingResult.intervals; | ||
| } | ||
| } | ||
| } | ||
| if (intervals.length === 0) { | ||
| return null; | ||
| } | ||
| const result = { | ||
| original: text, | ||
| rendered: this.render(text, intervals, conf), | ||
| score: score, | ||
| }; | ||
| if (includeMatches) { | ||
| result.intervals = intervals; | ||
| } | ||
| return result; | ||
| } | ||
| // render will modify the text according to the different parameter set in the conf. | ||
| // If nothing is set, then it will return the text not modified. | ||
| render(text, intervals, conf) { | ||
| let rendered = ''; | ||
| const pre = (conf === null || conf === void 0 ? void 0 : conf.pre) ? conf.pre : this.conf.pre; | ||
| const post = (conf === null || conf === void 0 ? void 0 : conf.post) ? conf.post : this.conf.post; | ||
| for (let i = 0; i < intervals.length; i++) { | ||
| const currentInterval = intervals[i]; | ||
| const previousNotMatchingInterval = calculatePreviousNotMatchingInterval(intervals, i); | ||
| let previousStr = ''; | ||
| if (previousNotMatchingInterval !== null) { | ||
| previousStr = this.extractSubString(text, previousNotMatchingInterval, conf); | ||
| } | ||
| const currentStr = this.extractSubString(text, currentInterval, conf); | ||
| rendered = `${rendered}${previousStr}${pre}${currentStr}${post}`; | ||
| } | ||
| // check if the last interval contains the end of the string. Otherwise add it | ||
| const lastInterval = intervals[intervals.length - 1]; | ||
| if (lastInterval.to < text.length - 1) { | ||
| rendered = rendered + this.extractSubString(text, { from: lastInterval.to + 1, to: text.length }, conf); | ||
| } | ||
| return rendered; | ||
| } | ||
| extractSubString(text, interval, conf) { | ||
| const shouldEscape = (conf === null || conf === void 0 ? void 0 : conf.escapeHTML) !== undefined ? conf.escapeHTML : this.conf.escapeHTML; | ||
| let str = text.substr(interval.from, intervalSize(interval)); | ||
| if (shouldEscape) { | ||
| str = escapeHTML(str); | ||
| } | ||
| return str; | ||
| } | ||
| } | ||
| exports.Fuzzy = Fuzzy; | ||
| const fuz = new Fuzzy(); | ||
| function filter(pattern, list, conf) { | ||
| return fuz.filter(pattern, list, conf); | ||
| } | ||
| exports.filter = filter; | ||
| function match(pattern, text, conf) { | ||
| return fuz.match(pattern, text, conf); | ||
| } | ||
| exports.match = match; | ||
| function render(text, intervals, conf) { | ||
| return fuz.render(text, intervals, conf); | ||
| } | ||
| exports.render = render; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
27717
13.71%6
20%481
85%14
7.69%8
100%1
Infinity%