search-query-parser
Advanced tools
Comparing version 1.0.0 to 1.1.0
@@ -34,2 +34,3 @@ /*! | ||
var query = {text: []}; | ||
var exclusion = {}; | ||
// Get a list of search terms respecting single and double quotes | ||
@@ -78,3 +79,14 @@ var terms = string.match(/(\S+:'(?:[^'\\]|\\.)*')|(\S+:"(?:[^"\\]|\\.)*")|\S+|\S+:\S+/g); | ||
options.keywords = options.keywords || []; | ||
var isKeyword = !(-1 === options.keywords.indexOf(key)); | ||
var isKeyword = false; | ||
var isExclusion = false; | ||
if (!/^-/.test(key)) { | ||
isKeyword = !(-1 === options.keywords.indexOf(key)); | ||
} else if (key[0] === '-') { | ||
var _key = key.slice(1); | ||
isKeyword = !(-1 === options.keywords.indexOf(_key)) | ||
if (isKeyword) { | ||
key = _key; | ||
isExclusion = true; | ||
} | ||
} | ||
// Check if the key is a registered range | ||
@@ -90,38 +102,75 @@ options.ranges = options.ranges || []; | ||
var values = value.split(','); | ||
// If we already have seen that keyword... | ||
if (query[key]) { | ||
// ...many times... | ||
if (query[key] instanceof Array) { | ||
if (isExclusion) { | ||
if (exclusion[key]) { | ||
// ...many times... | ||
if (exclusion[key] instanceof Array) { | ||
// ...and got several values this time... | ||
if (values.length > 1) { | ||
// ... concatenate both arrays. | ||
exclusion[key] = exclusion[key].concat(values); | ||
} | ||
else { | ||
// ... append the current single value. | ||
exclusion[key].push(value); | ||
} | ||
} | ||
// We saw that keyword only once before | ||
else { | ||
// Put both the current value and the new | ||
// value in an array | ||
exclusion[key] = [exclusion[key]]; | ||
exclusion[key].push(value); | ||
} | ||
} | ||
// First time we see that keyword | ||
else { | ||
// ...and got several values this time... | ||
if (values.length > 1) { | ||
// ... concatenate both arrays. | ||
query[key] = query[key].concat(values); | ||
// ...add all values seen. | ||
exclusion[key] = values; | ||
} | ||
// Got only a single value this time | ||
else { | ||
// ... append the current single value. | ||
// Record its value as a string | ||
exclusion[key] = value; | ||
} | ||
} | ||
} else { | ||
// If we already have seen that keyword... | ||
if (query[key]) { | ||
// ...many times... | ||
if (query[key] instanceof Array) { | ||
// ...and got several values this time... | ||
if (values.length > 1) { | ||
// ... concatenate both arrays. | ||
query[key] = query[key].concat(values); | ||
} | ||
else { | ||
// ... append the current single value. | ||
query[key].push(value); | ||
} | ||
} | ||
// We saw that keyword only once before | ||
else { | ||
// Put both the current value and the new | ||
// value in an array | ||
query[key] = [query[key]]; | ||
query[key].push(value); | ||
} | ||
} | ||
// We saw that keyword only once before | ||
// First time we see that keyword | ||
else { | ||
// Put both the current value and the new | ||
// value in an array | ||
query[key] = [query[key]]; | ||
query[key].push(value); | ||
// ...and got several values this time... | ||
if (values.length > 1) { | ||
// ...add all values seen. | ||
query[key] = values; | ||
} | ||
// Got only a single value this time | ||
else { | ||
// Record its value as a string | ||
query[key] = value; | ||
} | ||
} | ||
} | ||
// First time we see that keyword | ||
else { | ||
// ...and got several values this time... | ||
if (values.length > 1) { | ||
// ...add all values seen. | ||
query[key] = values; | ||
} | ||
// Got only a single value this time | ||
else { | ||
// Record its value as a string | ||
query[key] = value; | ||
} | ||
} | ||
} | ||
} | ||
} | ||
@@ -167,6 +216,6 @@ // The key allows a range | ||
// Return forged query object | ||
query.exclude = exclusion; | ||
return query; | ||
} | ||
}; |
{ | ||
"name": "search-query-parser", | ||
"version": "1.0.0", | ||
"version": "1.1.0", | ||
"description": "Parser for advanced search query syntax", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -51,4 +51,4 @@ # Search Query Syntax Parser | ||
It accepts 2 values: | ||
* `keywords`, that can be separated by commas (,) | ||
* `ranges`, that can be separated by a hyphen (-) | ||
* `keywords`, that can be separated by commas (,) | ||
* `ranges`, that can be separated by a hyphen (-) | ||
@@ -71,5 +71,16 @@ Both values take an array of strings, as in the example just above. | ||
You can also use exclusion syntax, like `-from:sep@foobar.io name:hello,world` . And it will return : | ||
```javascript | ||
{ | ||
name: ['hello', 'world'], | ||
exclusion: { | ||
from: ['sep@foobar.io'] | ||
} | ||
} | ||
``` | ||
## Testing | ||
The 17 tests are written using the BDD testing framework should.js, and run with mocha. | ||
The 20 tests are written using the BDD testing framework should.js, and run with mocha. | ||
@@ -76,0 +87,0 @@ Run `npm install should` and `npm install -g mocha` to install them both. |
@@ -226,2 +226,37 @@ var assert = require('assert') | ||
it('should parse a single keyword query in exclusion syntax', function() { | ||
var searchQuery = '-from:jul@foo.com'; | ||
var options = {keywords: ['from']}; | ||
var parsedSearchQuery = searchquery.parse(searchQuery, options); | ||
parsedSearchQuery.should.be.an.Object; | ||
parsedSearchQuery.exclude.should.be.an.Object; | ||
parsedSearchQuery.exclude.should.have.property('from', 'jul@foo.com'); | ||
parsedSearchQuery.should.not.have.property('text'); | ||
}); | ||
it('should concatenate a keyword multiple values in exclusion syntax', function() { | ||
var searchQuery = '-from:jul@foo.com,mar@foo.com'; | ||
var options = {keywords: ['from']}; | ||
var parsedSearchQuery = searchquery.parse(searchQuery, options); | ||
parsedSearchQuery.should.be.an.Object; | ||
parsedSearchQuery.exclude.should.be.an.Object; | ||
parsedSearchQuery.exclude.from.should.containEql('jul@foo.com'); | ||
parsedSearchQuery.exclude.from.should.containEql('mar@foo.com'); | ||
parsedSearchQuery.should.not.have.property('text'); | ||
}); | ||
it('should support keywords which appear multiple times with exclusion syntax', function() { | ||
var searchQuery = '-from:jul@foo.com,mar@foo.com -from:jan@foo.com'; | ||
var options = {keywords: ['from']}; | ||
var parsedSearchQuery = searchquery.parse(searchQuery, options); | ||
parsedSearchQuery.should.be.an.Object; | ||
parsedSearchQuery.exclude.should.be.an.Object; | ||
parsedSearchQuery.exclude.from.should.containEql('jul@foo.com'); | ||
parsedSearchQuery.exclude.from.should.containEql('mar@foo.com'); | ||
parsedSearchQuery.exclude.from.should.containEql('jan@foo.com'); | ||
parsedSearchQuery.should.not.have.property('text'); | ||
}); | ||
}); |
153296
5460
112