From 7e6460a909055c6bebaa91bda85bbf1d1525cf59 Mon Sep 17 00:00:00 2001 From: Danny Wolf Date: Mon, 16 May 2016 15:51:32 -0400 Subject: [PATCH 1/3] Add option to allow for returning match information though an array of 'match info' objects --- lib/fuzzy.js | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/lib/fuzzy.js b/lib/fuzzy.js index 9914065..50e4d53 100644 --- a/lib/fuzzy.js +++ b/lib/fuzzy.js @@ -34,6 +34,10 @@ fuzzy.test = function(pattern, string) { // If `pattern` matches `string`, wrap each matching character // in `opts.pre` and `opts.post`. If no match, return null +// If `opts.returnMatchInfo` is true, return an array of objects +// with boolean match info. +// `opts.pre` and `opts.post` can be used with `opts.returnMatchInfo` +// if necessary. fuzzy.match = function(pattern, string, opts) { opts = opts || {}; var patternIdx = 0 @@ -45,18 +49,21 @@ fuzzy.match = function(pattern, string, opts) { , pre = opts.pre || '' // suffix , post = opts.post || '' + , returnMatchInfo = opts.returnMatchInfo || false // String to compare against. This might be a lowercase version of the // raw string , compareString = opts.caseSensitive && string || string.toLowerCase() - , ch, compareChar; + , ch, compareChar, chMatch; pattern = opts.caseSensitive && pattern || pattern.toLowerCase(); // For each character in the string, either add it to the result // or wrap in template if it's the next string in the pattern for(var idx = 0; idx < len; idx++) { + chMatch = false; ch = string[idx]; if(compareString[idx] === pattern[patternIdx]) { + chMatch = true; ch = pre + ch + post; patternIdx += 1; @@ -66,12 +73,22 @@ fuzzy.match = function(pattern, string, opts) { currScore = 0; } totalScore += currScore; - result[result.length] = ch; + + // assemble match info object if requested + if(returnMatchInfo) { + result[result.length] = {match: chMatch, char: ch}; + } else { + result[result.length] = ch; + } } - // return rendered string if we have a match for every char + // return rendered string/array if we have a match for every char if(patternIdx === pattern.length) { - return {rendered: result.join(''), score: totalScore}; + // join if not returning match info object + if(!returnMatchInfo) { + result = result.join(''); + } + return {rendered: result, score: totalScore}; } return null; From 627eb67ea879da155f725455efcd30dabbe2585c Mon Sep 17 00:00:00 2001 From: Danny Wolf Date: Mon, 16 May 2016 16:11:29 -0400 Subject: [PATCH 2/3] Add tests for object returning --- test/fuzzy.test.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/fuzzy.test.js b/test/fuzzy.test.js index d1bc253..9f23e40 100644 --- a/test/fuzzy.test.js +++ b/test/fuzzy.test.js @@ -105,6 +105,24 @@ describe('fuzzy', function(){ })[0].string; expect(rendered).to.eql('ccc'); }); + it('should optionally return an object surrounding each character', function(){ + var fuzzyMatched = fuzzy.filter('a', ['a'], { + returnMatchInfo: true + })[0].string; + expect(fuzzyMatched).to.eql([{match: true, char: 'a'}]); + + fuzzyMatched = fuzzy.filter('a', ['ab'], { + returnMatchInfo: true + })[0].string; + expect(fuzzyMatched).to.eql([{match: true, char: 'a'}, {match: false, char: 'b'}]); + + fuzzyMatched = fuzzy.filter('a', ['ab'], { + returnMatchInfo: true + , pre: "tah" + , post: "zah!" + })[0].string; + expect(fuzzyMatched).to.eql([{match: true, char: 'tahazah!'}, {match: false, char: 'b'}]); + }) it('should use optional func to get string out of array entry', function() { var arr = [{arg: 'hizzahpooslahp'}, {arg: 'arppg'}]; expect(fuzzy.filter('poop', arr, { From 66a412ee1241b9a3ce2157f6e27c39d203e055b0 Mon Sep 17 00:00:00 2001 From: Danny Wolf Date: Mon, 16 May 2016 16:28:34 -0400 Subject: [PATCH 3/3] Add returnMatchInfo to README.md --- README.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/README.md b/README.md index d6f97b2..60fc97c 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,37 @@ console.log(matches); // [ 'aoing', 'a mighty ear aoe' ] ``` +Chewbacca: sometimes you don't want to get unsafely wrapped html structures, +and you'd rather do it yourself later. Prepending and appending strings is +cool until you use React and don't want XSS. You can tell fuzzy.js to return +small 'match info' objects to suit your needs better. + +```javascript +var list = ['rey', 'kylo ren', 'finn']; +var options = { returnMatchInfo: true }; +var results = fuzzy.filter('ren', list, options); +console.log(results); +// [ { string: +// [ {match: true, char: 'r'}, +// {match: true, char: 'e'}, +// {match: false, char: 'y'} ], +// score: 4, +// index: 0, +// original: 'rey' }, +// { string: +// [ {match: false, char: 'k'}, +// {match: false, char: 'y'}, +// {match: false, char: 'l'}, +// {match: false, char: 'o'}, +// {match: false, char: ' '}, +// {match: true, char: 'r'}, +// {match: true, char: 'e'}, +// {match: false, char: 'n'} ], +// score: 4, +// index: 1, +// original: 'kylo ren' } ] +``` + ## Examples Check out the html files in the [examples](https://github.com/mattyork/fuzzy/tree/master/examples) directory.