New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

fuzzyjs

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

fuzzyjs - npm Package Compare versions

Comparing version 1.0.4 to 2.0.0

200

build/fuzzy.js

@@ -7,61 +7,171 @@ 'use strict';

// Improved from Bulat Bochkariov's version (http://www.quora.com/Algorithms/How-is-the-fuzzy-search-algorithm-in-Sublime-Text-designed)
var fuzzy = function fuzzy(searchSet, query, opts_) {
var opts = _extends({
caseSensitive: false,
before: '',
after: ''
}, opts_);
var isArray = function isArray(arr) {
return Object.prototype.toString.call(arr) === '[object Array]';
};
if (!query) {
return searchSet;
}
var fuzzy = {
/**
* Tests if a string matches a pattern
* @param {String} q The pattern
* @param {String} str The string
* @param {Boolean} caseSensitive True if case sensitive should count
* @return {Boolean} True if the string matches, false otherwise
*/
var tokens = opts.caseSensitive ? query.split('') : query.toLowerCase().split('');
var matches = [];
var l = searchSet.length;
var i = 0;
test: function test(q, str) {
var caseSensitive = arguments.length <= 2 || arguments[2] === undefined ? false : arguments[2];
for (i; i < l; ++i) {
// tokenIndex : query letter index
// stringIndex : current possible result letter index
// matchWithHighlights : string containing result
// stringLC : lower-case search, or not
if (typeof q !== 'string' || typeof str !== 'string') {
return -1;
}
var tokenIndex = 0;
var stringIndex = 0;
var matchWithHighlights = '';
var matchedPositions = [];
var stringLC = opts.caseSensitive ? searchSet[i] : searchSet[i].toLowerCase();
if (!str) {
return -1;
}
while (stringIndex < searchSet[i].length) {
// [Still] same letter
if (stringLC[stringIndex] === tokens[tokenIndex]) {
matchWithHighlights += opts.before + searchSet[i][stringIndex] + opts.after;
matchedPositions.push(stringIndex);
++tokenIndex;
if (!q) {
return true;
}
if (tokenIndex >= tokens.length) {
matches.push(matchWithHighlights + searchSet[i].slice(stringIndex + 1));
break;
}
if (!caseSensitive) {
q = q.toLowerCase();
str = str.toLowerCase();
}
var pos = 0;
var i = 0;
while (i < str.length) {
if (str[i] === q[pos]) {
pos += 1;
}
++i;
}
return pos === q.length;
},
/**
* Tests if a string matches a pattern and return a score
* @param {String} q The pattern
* @param {String} str The string
* @param {Object} opts Options containing `caseSensitive` `before` and `after`
* @return {Object} Object containing score and surrounded (or intact) result
*/
match: function match(q, str, opts) {
if (typeof q !== 'string' || typeof str !== 'string') {
return { score: 0, result: str };
}
if (!str) {
return { score: 0, result: str };
}
if (!q) {
return { score: 1, result: str };
}
opts = _extends({
caseSensitive: false,
before: '',
after: ''
}, opts);
if (!opts.caseSensitive) {
q = q.toLowerCase();
str = str.toLowerCase();
}
// String with surrounded results
var result = '';
// Number of spaces between matches
var steps = 0;
// Actual pattern position
var pos = 0;
// Last match position
var lastI = 0;
var i = 0;
while (i < str.length) {
var c = str[i];
if (c === q[pos]) {
result += opts.before + c + opts.after;
// Move to the next pattern character
pos += 1;
// Add spaces between the last match to steps
steps += i - lastI;
// Reset counter to the actual position in string
lastI = i;
} else {
matchWithHighlights += searchSet[i][stringIndex];
result += c;
}
++stringIndex;
++i;
}
}
// Order by number of occurrences (requires surrounding)
if (opts.before.length > 0) {
matches = matches.sort(function (a, b) {
var scoreA = a.split(opts.before).length - 1;
var scoreB = b.split(opts.before).length - 1;
if (pos === q.length) {
// Score between 0 and 1 calculated by the number of spaces
// between letters and the string length.
// The biggest the score is the better
var score = q.length / (steps + 1);
return scoreA - scoreB;
return { score: score, result: result };
}
return { score: 0, result: str };
},
/**
* Filters an array based on the pattern
* @param {String} q The pattern
* @param {Array<String>} set An array of queries
* @param {Object} opts Options containing `caseSensitive` `before` and `after`
* @return {Array<String>} A sorted array of results
*/
filter: function filter(q, set, opts) {
if (!isArray(set)) {
return [];
}
if (typeof q !== 'string' || !q) {
return set;
}
opts = _extends({
caseSensitive: false,
before: '',
after: ''
}, opts);
var results = [];
var i = 0;
while (i < set.length) {
var str = set[i];
var result = fuzzy.match(q, str, opts);
if (result.score > 0) {
results.push(result);
}
++i;
}
return results.sort(function (a, b) {
return b.score - a.score;
}).map(function (elem) {
return elem.result;
});
}
return matches;
};

@@ -68,0 +178,0 @@

@@ -1,2 +0,2 @@

"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol?"symbol":typeof obj};var _extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key]}}}return target};var fuzzy=function fuzzy(searchSet,query,opts_){var opts=_extends({caseSensitive:false,before:"",after:""},opts_);if(!query){return searchSet}var tokens=opts.caseSensitive?query.split(""):query.toLowerCase().split("");var matches=[];var l=searchSet.length;var i=0;for(i;i<l;++i){var tokenIndex=0;var stringIndex=0;var matchWithHighlights="";var matchedPositions=[];var stringLC=opts.caseSensitive?searchSet[i]:searchSet[i].toLowerCase();while(stringIndex<searchSet[i].length){if(stringLC[stringIndex]===tokens[tokenIndex]){matchWithHighlights+=opts.before+searchSet[i][stringIndex]+opts.after;matchedPositions.push(stringIndex);++tokenIndex;if(tokenIndex>=tokens.length){matches.push(matchWithHighlights+searchSet[i].slice(stringIndex+1));break}}else{matchWithHighlights+=searchSet[i][stringIndex]}++stringIndex}}if(opts.before.length>0){matches=matches.sort(function(a,b){var scoreA=a.split(opts.before).length-1;var scoreB=b.split(opts.before).length-1;return scoreA-scoreB})}return matches};(function(root,factory){if(typeof define==="function"&&define.amd){define([],factory)}else if((typeof module==="undefined"?"undefined":_typeof(module))==="object"&&module.exports){module.exports=factory()}else{root.returnExports=factory()}})(undefined,function(){return fuzzy});
"use strict";var _typeof=typeof Symbol==="function"&&typeof Symbol.iterator==="symbol"?function(obj){return typeof obj}:function(obj){return obj&&typeof Symbol==="function"&&obj.constructor===Symbol?"symbol":typeof obj};var _extends=Object.assign||function(target){for(var i=1;i<arguments.length;i++){var source=arguments[i];for(var key in source){if(Object.prototype.hasOwnProperty.call(source,key)){target[key]=source[key]}}}return target};var isArray=function isArray(arr){return Object.prototype.toString.call(arr)==="[object Array]"};var fuzzy={test:function test(q,str){var caseSensitive=arguments.length<=2||arguments[2]===undefined?false:arguments[2];if(typeof q!=="string"||typeof str!=="string"){return-1}if(!str){return-1}if(!q){return true}if(!caseSensitive){q=q.toLowerCase();str=str.toLowerCase()}var pos=0;var i=0;while(i<str.length){if(str[i]===q[pos]){pos+=1}++i}return pos===q.length},match:function match(q,str,opts){if(typeof q!=="string"||typeof str!=="string"){return{score:0,result:str}}if(!str){return{score:0,result:str}}if(!q){return{score:1,result:str}}opts=_extends({caseSensitive:false,before:"",after:""},opts);if(!opts.caseSensitive){q=q.toLowerCase();str=str.toLowerCase()}var result="";var steps=0;var pos=0;var lastI=0;var i=0;while(i<str.length){var c=str[i];if(c===q[pos]){result+=opts.before+c+opts.after;pos+=1;steps+=i-lastI;lastI=i}else{result+=c}++i}if(pos===q.length){var score=q.length/(steps+1);return{score:score,result:result}}return{score:0,result:str}},filter:function filter(q,set,opts){if(!isArray(set)){return[]}if(typeof q!=="string"||!q){return set}opts=_extends({caseSensitive:false,before:"",after:""},opts);var results=[];var i=0;while(i<set.length){var str=set[i];var result=fuzzy.match(q,str,opts);if(result.score>0){results.push(result)}++i}return results.sort(function(a,b){return b.score-a.score}).map(function(elem){return elem.result})}};(function(root,factory){if(typeof define==="function"&&define.amd){define([],factory)}else if((typeof module==="undefined"?"undefined":_typeof(module))==="object"&&module.exports){module.exports=factory()}else{root.returnExports=factory()}})(undefined,function(){return fuzzy});
//# sourceMappingURL=build/fuzzy.min.js.map
{
"name": "fuzzyjs",
"version": "1.0.4",
"version": "2.0.0",
"description": "Fuzzy.js is a fuzzy search algorithm in javascript",

@@ -5,0 +5,0 @@ "main": "build/fuzzy.js",

@@ -14,8 +14,11 @@ # fuzzyjs #

```js
const arr = ['A sentence composed of multiple words', 'Set syntax Javscript'];
fuzzy(arr, 'scmw');
// Basic true/false test
fuzzy.test('li', 'lorem ipsum'); // true
fuzzy.test('li', 'Lorem ipsum', true); // false
['A sentence composed of multiple words']
// Advanced match with surrounding and score
fuzzy.match('li', 'lorem ipsum');
// { score: 0.2857, result: 'lorem ipsum' }
fuzzy(arr, 'w', {
fuzzy.match('Li', 'Lorem ipsum', {
caseSensitive: true,

@@ -25,4 +28,13 @@ before: '<span>',

});
// { score: 0.2857, result: '<span>L</span>orem <span>i</span>psum' }
['A sentence composed of multiple <span>w</span>ords']
// Filter an array using match (array is sorted based on score)
const arr = ['lorem ipsum', 'foo', 'the li element'];
fuzzy.filter('li', arr, { caseSensitive: true, before: '<span>', after: '</span>' });
/*
[
'the <span>l</span><span>i</span> element',
'<span>l</span>orem <span>i</span>psum'
]
*/
```
import assert from 'assert';
import fuzzy from '../src/fuzzy';
const testSet = [
'A sentence composed of multiple Words',
'a sentence composed of multiple words',
'Set syntax Javascript'
];
describe('fuzzyjs', () => {
describe('default search', () => {
it('finds the right string and surrounds it with a span tag', () => {
const expected = [
'A sentence composed of multiple Words',
'a sentence composed of multiple words'
];
describe('test', () => {
it('should return -1 if no query', () => {
const str = 'foo';
const q = null;
const expected = -1;
const result = fuzzy(testSet, 'scmw');
const result = fuzzy.test(q, str);
assert.deepEqual(result, expected);
assert.equal(expected, result);
});
it('should return the full set without query', () => {
const expected = testSet;
it('should return -1 if no string to test', () => {
const str = null;
const q = 'foo';
const expected = -1;
const result = fuzzy(testSet);
const result = fuzzy.test(q, str);
assert.deepEqual(result, expected);
assert.equal(expected, result);
});
it('should return -1 if string is empty', () => {
const str = '';
const q = 'foo';
const expected = -1;
const result = fuzzy.test(q, str);
assert.equal(expected, result);
});
it('should return true if query is empty', () => {
const str = 'foo';
const q = '';
const expected = true;
const result = fuzzy.test(q, str);
assert.equal(expected, result);
});
it('should match when the pattern matches', () => {
const str = 'lorem ipsum';
const q = 'li';
const expected = true;
const result = fuzzy.test(q, str);
assert.equal(expected, result);
});
it('should not match when the pattern does not match', () => {
const str = 'lorem ipsum';
const q = 'foo';
const expected = false;
const result = fuzzy.test(q, str);
assert.equal(expected, result);
});
it('should match with caseSensitive set to true and pattern matching', () => {
const str = 'Lorem ipsum';
const q = 'Li';
const expected = true;
const result = fuzzy.test(q, str, true);
assert.equal(expected, result);
});
it('should not match with caseSensitive set to true and pattern not matching', () => {
const str = 'Lorem ipsum';
const q = 'li';
const expected = false;
const result = fuzzy.test(q, str, true);
assert.equal(expected, result);
});
});
describe('custom surrounding tag', () => {
it('finds the right string and surrounds it with a span tag', () => {
const expected = [
'A <strong>s</strong>enten<strong>c</strong>e co<strong>m</strong>posed of multiple <strong>W</strong>ords',
'a <strong>s</strong>enten<strong>c</strong>e co<strong>m</strong>posed of multiple <strong>w</strong>ords'
];
describe('match', () => {
it('should return { score: 0, result: str } if no query', () => {
const str = 'foo';
const q = null;
const result = fuzzy(testSet, 'scmw', {
caseSensitive: false,
before : '<strong>',
after : '</strong>'
});
const expectedScore = 0;
const expectedResult = 'foo';
assert.deepEqual(result, expected);
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should return { score: 0, result: str } if no string to match', () => {
const str = null;
const q = 'foo';
const expectedScore = 0;
const expectedResult = null;
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should return { score: 0, result: str } if string is empty', () => {
const str = '';
const q = 'foo';
const expectedScore = 0;
const expectedResult = '';
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should return { score: 1, result: str } if query is empty', () => {
const str = 'foo';
const q = '';
const expectedScore = 1;
const expectedResult = 'foo';
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should match when the pattern matches', () => {
const str = 'lorem ipsum';
const q = 'li';
const expectedScore = 'li'.length / (6 + 1);
const expectedResult = 'lorem ipsum';
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should scores 1 when the pattern is equal to the string', () => {
const str = 'lorem ipsum';
const q = 'lorem ipsum';
const expectedScore = 1;
const expectedResult = 'lorem ipsum';
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should not match when the pattern does not match', () => {
const str = 'lorem ipsum';
const q = 'foo';
const expectedScore = 0;
const expectedResult = 'lorem ipsum';
const result = fuzzy.match(q, str);
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should match with caseSensitive set to true and pattern matching', () => {
const str = 'Lorem ipsum';
const q = 'Li';
const expectedScore = 'li'.length / (6 + 1);
const expectedResult = 'Lorem ipsum';
const result = fuzzy.match(q, str, { caseSensitive: true });
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should not match with caseSensitive set to true and pattern not matching', () => {
const str = 'Lorem ipsum';
const q = 'li';
const expectedScore = 0;
const expectedResult = 'Lorem ipsum';
const result = fuzzy.match(q, str, { caseSensitive: true });
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
it('should surround with options', () => {
const str = 'lorem ipsum';
const q = 'li';
const expectedScore = 'li'.length / (6 + 1);
const expectedResult = '<span>l</span>orem <span>i</span>psum';
const result = fuzzy.match(q, str, { before: '<span>', after: '</span>' });
assert.equal(expectedScore, result.score);
assert.equal(expectedResult, result.result);
});
});
describe('case sensitive search', () => {
it('finds only the lower case letter', () => {
const expected = [
'a sentence composed of multiple words'
];
describe('filter', () => {
it('should return the original set if no query', () => {
const arr = ['lorem ipsum', 'foo', 'the li element'];
const q = '';
const result = fuzzy(testSet, 'w', {
caseSensitive: true
});
const expected = ['lorem ipsum', 'foo', 'the li element'];
assert.deepEqual(result, expected);
const result = fuzzy.filter(q, arr);
assert.deepEqual(expected, result);
});
it('finds only the upper case letter', () => {
const expected = [
'A sentence composed of multiple Words'
];
it('should return the original set if invalid query', () => {
const arr = ['lorem ipsum', 'foo', 'the li element'];
const q = null;
const result = fuzzy(testSet, 'W', {
caseSensitive: true
});
const expected = ['lorem ipsum', 'foo', 'the li element'];
assert.deepEqual(result, expected);
const result = fuzzy.filter(q, arr);
assert.deepEqual(expected, result);
});
it('should return an empty array if invalid set', () => {
const arr = null;
const q = '';
const expected = [];
const result = fuzzy.filter(q, arr);
assert.deepEqual(expected, result);
});
it('should filter an array based on pattern', () => {
const arr = ['lorem ipsum', 'foo', 'the li element'];
const q = 'li';
const expected = ['the li element', 'lorem ipsum'];
const result = fuzzy.filter(q, arr);
assert.deepEqual(expected, result);
});
});
});

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc