├── .gitignore
├── .travis.yml
├── LICENSE
├── Makefile
├── README.md
├── docs
├── README.md
├── interfaces
│ ├── _index_d_.isearchparserdictionary.md
│ ├── _index_d_.searchparseroffset.md
│ ├── _index_d_.searchparseroptions.md
│ └── _index_d_.searchparserresult.md
└── modules
│ └── _index_d_.md
├── index.d.ts
├── index.js
├── lib
└── search-query-parser.js
├── package-lock.json
├── package.json
├── test
├── index.html
├── mocha.css
├── mocha.js
└── test.js
├── tsconfig.json
└── tslint.json
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # Compiled binary addons (http://nodejs.org/api/addons.html)
20 | build/Release
21 |
22 | # Dependency directory
23 | # Deployed apps should consider commenting this line out:
24 | # see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
25 | node_modules
26 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "12"
4 | - "13"
5 | - "14"
6 | - "15"
7 | - "16"
8 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 retraceio
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | BINS=./node_modules/.bin
2 |
3 | install:
4 | @npm install .
5 |
6 | test:
7 | @$(BINS)/mocha -R spec
8 |
9 | .PHONY: test
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Search Query Syntax Parser
2 |
3 | > A simple parser for advanced search query syntax.
4 |
5 | [](https://travis-ci.org/nepsilon/search-query-parser)
6 |
7 | It parses a string like this:
8 | ```
9 | from:hi@retrace.io,foo@gmail.com to:me subject:vacations date:1/10/2013-15/04/2014 photos
10 | ```
11 |
12 | And turns it into an object like this:
13 |
14 | ```javascript
15 | {
16 | from: ['hi@retrace.io', 'foo@gmail.com'],
17 | to: 'me',
18 | subject: 'vacations',
19 | date: {
20 | from: '1/10/2013',
21 | to: '15/04/2014'
22 | },
23 | text: 'photos',
24 | offsets:
25 | [ { keyword: 'from', value: 'hi@retrace.io,foo@gmail.com', offsetStart: 0, offsetEnd: 32 },
26 | { keyword: 'to', value: 'me', offsetStart: 33, offsetEnd: 38 },
27 | { keyword: 'subject', value: 'vacations', offsetStart: 39, offsetEnd: 56 },
28 | { keyword: 'date', value: '1/10/2013-15/04/2014', offsetStart: 57, offsetEnd: 82 },
29 | { text: 'photos', offsetStart: 83, offsetEnd: 89 } ]
30 | }
31 | ```
32 |
33 | ## Installation
34 |
35 | ```shell
36 | $ npm install search-query-parser
37 | ```
38 |
39 | ## Usage
40 |
41 | ```javascript
42 | var searchQuery = require('search-query-parser');
43 |
44 | var query = 'from:hi@retrace.io,foo@gmail.com to:me subject:vacations date:1/10/2013-15/04/2014 photos';
45 | var options = {keywords: ['from', 'to', 'subject'], ranges: ['date']}
46 |
47 | var searchQueryObj = searchQuery.parse(query, options);
48 |
49 | // searchQueryObj.from is now ['hi@retrace.io', 'foo@gmail.com']
50 | // searchQueryObj.to is now 'me'
51 | // searchQueryObj.date is now {from: '1/10/2013', to: '15/04/2014'}
52 | // searchQueryObj.text is now 'photos'
53 | ```
54 |
55 | You can configure what keywords and ranges the parser should accept with the options argument.
56 | It accepts 5 values:
57 | * `keywords`, that can be separated by commas (,). Accepts an array of strings.
58 | * `ranges`, that can be separated by a hyphen (-). Accepts an array of strings.
59 | * `tokenize`, that controls the behaviour of text search terms. If set to `true`, non-keyword text terms are returned as an array of strings where each term in the array is a whitespace-separated word, or a multi-word term surrounded by single- or double-quotes.
60 | * `alwaysArray`, a boolean that controls the behaviour of the returned query. If set to `true`, all matched keywords would always be arrays instead of strings. If set to `false` they will be strings if matched a single value. Defaults to `false`.
61 | * `offsets`, a boolean that controls the behaviour of the returned query. If set to `true`, the query will contain the offsets object. If set to `false`, the query will not contain the offsets object. Defaults to `true`.
62 |
63 | If no keywords or ranges are specified, or if none are present in the given search query, then `searchQuery.parse` will return a string if `tokenize` is false, or an array of strings under the key `text` if `tokenize` is true.
64 |
65 | ```javascript
66 | var searchQuery = require('search-query-parser');
67 |
68 | var query = 'a query with "just text"';
69 | var parsedQuery = searchQuery.parse(query);
70 | // parsedQuery is now 'a query with "just text"'
71 |
72 | var options = {keywords: ['unused']};
73 | var parsedQueryWithOptions = searchQuery.parse(query, options);
74 | // parsedQueryWithOptions is now 'a query with "just text"'
75 |
76 | var options2 = {tokenize: true};
77 | var parsedQueryWithTokens = searchQuery.parse(query, options2);
78 | // parsedQueryWithTokens is now: ['a', 'query', 'with', 'just text']
79 | ```
80 |
81 | You can also use exclusion syntax, like `-from:sep@foobar.io name:hello,world`. This also works with non-keyword text terms when `tokenize` is set to `true`.
82 |
83 | ```javascript
84 | {
85 | name: ['hello', 'world'],
86 | exclude: {
87 | from: ['sep@foobar.io']
88 | }
89 | }
90 | ```
91 |
92 | Sometimes checking against whether a keyword holds string or not can be excessive and prone to errors; it's often easier to simply expect everything is an array even if it means doing 1-iteration loops often.
93 |
94 | ```javascript
95 | var searchQuery = require('search-query-parser');
96 |
97 | var query = 'test:helloworld fun:yay,happy';
98 | var options = {keywords: ['test', 'fun']};
99 | var parsedQueryWithOptions = searchQuery.parse(query, options);
100 | // parsedQueryWithOptions is now:
101 | // {
102 | // test: 'helloworld',
103 | // fun: ['yay', 'happy']
104 | // }
105 |
106 | var optionsAlwaysArray = {keywords: ['test', 'fun'], alwaysArray: true};
107 | var parsedQueryWithOptions = searchQuery.parse(query, options);
108 | // parsedQueryWithOptions is now:
109 | // {
110 | // test: ['helloworld'], //No need to check whether test is a string or not!
111 | // fun: ['yay', 'happy']
112 | // }
113 | ```
114 |
115 | The offsets object could become pretty huge with long search queries which could be an unnecessary use of space if no functionality depends on it. It can simply be turned off using the option `offsets: false`.
116 |
117 | Anytime, you can go back and stringify the parsed search query. This could be handy if you would like to manipulate the parsed search query object.
118 |
119 | ```javascript
120 | var searchQuery = require('search-query-parser');
121 |
122 | var query = 'from:hi@retrace.io,foo@gmail.com to:me subject:vacations date:1/10/2013-15/04/2014 photos';
123 | var options = {keywords: ['from', 'to', 'subject'], ranges: ['date']}
124 |
125 | var searchQueryObj = searchQuery.parse(query, options);
126 |
127 | searchQueryObj.to = 'you';
128 | var newQuery = searchQuery.stringify(query, options);
129 |
130 | // newQuery is now: photos from:hi@retrace.io,foo@gmail.com to:you subject:vacations date:1/10/2013-15/04/2014
131 | ```
132 |
133 | ## Typescript
134 |
135 | Typescript types are available for this library in the `docs` directory.
136 | [Browse type documentation here.](docs/README.md)
137 |
138 | Documentation is generated using `node_modules/.bin/typedoc index.d.ts`
139 |
140 | ## Testing
141 |
142 | The 29 tests are written using the BDD testing framework should.js, and run with mocha.
143 |
144 | Run `npm install should` and `npm install -g mocha` to install them both.
145 |
146 | Run tests with `make test`.
147 |
148 | ## License
149 |
150 | The MIT License (MIT)
151 |
152 | Copyright (c) 2014
153 |
154 | Permission is hereby granted, free of charge, to any person obtaining a copy
155 | of this software and associated documentation files (the "Software"), to deal
156 | in the Software without restriction, including without limitation the rights
157 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
158 | copies of the Software, and to permit persons to whom the Software is
159 | furnished to do so, subject to the following conditions:
160 |
161 | The above copyright notice and this permission notice shall be included in all
162 | copies or substantial portions of the Software.
163 |
164 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
165 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
167 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
168 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
169 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
170 | SOFTWARE.
171 |
--------------------------------------------------------------------------------
/docs/README.md:
--------------------------------------------------------------------------------
1 |
2 | # search-query-parser
3 |
4 | ## Index
5 |
6 | ### External modules
7 |
8 | * ["index.d"](modules/_index_d_.md)
9 |
10 | ---
11 |
12 |
--------------------------------------------------------------------------------
/docs/interfaces/_index_d_.isearchparserdictionary.md:
--------------------------------------------------------------------------------
1 | [search-query-parser](../README.md) > ["index.d"](../modules/_index_d_.md) > [ISearchParserDictionary](../interfaces/_index_d_.isearchparserdictionary.md)
2 |
3 | # Interface: ISearchParserDictionary
4 |
5 | ## Hierarchy
6 |
7 | **ISearchParserDictionary**
8 |
9 | ↳ [SearchParserResult](_index_d_.searchparserresult.md)
10 |
11 | ## Indexable
12 |
13 | \[key: `string`\]: `any`
14 | ## Index
15 |
16 | ---
17 |
18 |
--------------------------------------------------------------------------------
/docs/interfaces/_index_d_.searchparseroffset.md:
--------------------------------------------------------------------------------
1 | [search-query-parser](../README.md) > ["index.d"](../modules/_index_d_.md) > [SearchParserOffset](../interfaces/_index_d_.searchparseroffset.md)
2 |
3 | # Interface: SearchParserOffset
4 |
5 | ## Hierarchy
6 |
7 | **SearchParserOffset**
8 |
9 | ## Index
10 |
11 | ### Properties
12 |
13 | * [keyword](_index_d_.searchparseroffset.md#keyword)
14 | * [offsetEnd](_index_d_.searchparseroffset.md#offsetend)
15 | * [offsetStart](_index_d_.searchparseroffset.md#offsetstart)
16 | * [value](_index_d_.searchparseroffset.md#value)
17 |
18 | ---
19 |
20 | ## Properties
21 |
22 |
23 |
24 | ### keyword
25 |
26 | **● keyword**: *`string`*
27 |
28 | *Defined in [index.d.ts:20](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L20)*
29 |
30 | ___
31 |
32 |
33 | ### offsetEnd
34 |
35 | **● offsetEnd**: *`number`*
36 |
37 | *Defined in [index.d.ts:23](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L23)*
38 |
39 | ___
40 |
41 |
42 | ### offsetStart
43 |
44 | **● offsetStart**: *`number`*
45 |
46 | *Defined in [index.d.ts:22](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L22)*
47 |
48 | ___
49 |
50 |
51 | ### `` value
52 |
53 | **● value**: *`string`*
54 |
55 | *Defined in [index.d.ts:21](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L21)*
56 |
57 | ___
58 |
59 |
--------------------------------------------------------------------------------
/docs/interfaces/_index_d_.searchparseroptions.md:
--------------------------------------------------------------------------------
1 | [search-query-parser](../README.md) > ["index.d"](../modules/_index_d_.md) > [SearchParserOptions](../interfaces/_index_d_.searchparseroptions.md)
2 |
3 | # Interface: SearchParserOptions
4 |
5 | ## Hierarchy
6 |
7 | **SearchParserOptions**
8 |
9 | ## Index
10 |
11 | ### Properties
12 |
13 | * [alwaysArray](_index_d_.searchparseroptions.md#alwaysarray)
14 | * [keywords](_index_d_.searchparseroptions.md#keywords)
15 | * [offsets](_index_d_.searchparseroptions.md#offsets)
16 | * [ranges](_index_d_.searchparseroptions.md#ranges)
17 | * [tokenize](_index_d_.searchparseroptions.md#tokenize)
18 |
19 | ---
20 |
21 | ## Properties
22 |
23 |
24 |
25 | ### `` alwaysArray
26 |
27 | **● alwaysArray**: *`boolean`*
28 |
29 | *Defined in [index.d.ts:12](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L12)*
30 |
31 | ___
32 |
33 |
34 | ### `` keywords
35 |
36 | **● keywords**: *`string`[]*
37 |
38 | *Defined in [index.d.ts:10](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L10)*
39 |
40 | ___
41 |
42 |
43 | ### `` offsets
44 |
45 | **● offsets**: *`boolean`*
46 |
47 | *Defined in [index.d.ts:8](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L8)*
48 |
49 | ___
50 |
51 |
52 | ### `` ranges
53 |
54 | **● ranges**: *`string`[]*
55 |
56 | *Defined in [index.d.ts:11](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L11)*
57 |
58 | ___
59 |
60 |
61 | ### `` tokenize
62 |
63 | **● tokenize**: *`boolean`*
64 |
65 | *Defined in [index.d.ts:9](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L9)*
66 |
67 | ___
68 |
69 |
--------------------------------------------------------------------------------
/docs/interfaces/_index_d_.searchparserresult.md:
--------------------------------------------------------------------------------
1 | [search-query-parser](../README.md) > ["index.d"](../modules/_index_d_.md) > [SearchParserResult](../interfaces/_index_d_.searchparserresult.md)
2 |
3 | # Interface: SearchParserResult
4 |
5 | ## Hierarchy
6 |
7 | [ISearchParserDictionary](_index_d_.isearchparserdictionary.md)
8 |
9 | **↳ SearchParserResult**
10 |
11 | ## Indexable
12 |
13 | \[key: `string`\]: `any`
14 | ## Index
15 |
16 | ### Properties
17 |
18 | * [exclude](_index_d_.searchparserresult.md#exclude)
19 | * [offsets](_index_d_.searchparserresult.md#offsets)
20 | * [text](_index_d_.searchparserresult.md#text)
21 |
22 | ---
23 |
24 | ## Properties
25 |
26 |
27 |
28 | ### `` exclude
29 |
30 | **● exclude**: *[ISearchParserDictionary](_index_d_.isearchparserdictionary.md)*
31 |
32 | *Defined in [index.d.ts:29](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L29)*
33 |
34 | ___
35 |
36 |
37 | ### `` offsets
38 |
39 | **● offsets**: *[SearchParserOffset](_index_d_.searchparseroffset.md)[]*
40 |
41 | *Defined in [index.d.ts:28](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L28)*
42 |
43 | ___
44 |
45 |
46 | ### `` text
47 |
48 | **● text**: *`string` \| `string`[]*
49 |
50 | *Defined in [index.d.ts:27](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L27)*
51 |
52 | ___
53 |
54 |
--------------------------------------------------------------------------------
/docs/modules/_index_d_.md:
--------------------------------------------------------------------------------
1 | [search-query-parser](../README.md) > ["index.d"](../modules/_index_d_.md)
2 |
3 | # External module: "index.d"
4 |
5 | ## Index
6 |
7 | ### Interfaces
8 |
9 | * [ISearchParserDictionary](../interfaces/_index_d_.isearchparserdictionary.md)
10 | * [SearchParserOffset](../interfaces/_index_d_.searchparseroffset.md)
11 | * [SearchParserOptions](../interfaces/_index_d_.searchparseroptions.md)
12 | * [SearchParserResult](../interfaces/_index_d_.searchparserresult.md)
13 |
14 | ### Functions
15 |
16 | * [parse](_index_d_.md#parse)
17 |
18 | ---
19 |
20 | ## Functions
21 |
22 |
23 |
24 | ### parse
25 |
26 | ▸ **parse**(string: *`string`*, options?: *[SearchParserOptions](../interfaces/_index_d_.searchparseroptions.md)*): `string` \| [SearchParserResult](../interfaces/_index_d_.searchparserresult.md)
27 |
28 | *Defined in [index.d.ts:32](https://github.com/rtrvrtg/search-query-parser/blob/e4a7ccc/index.d.ts#L32)*
29 |
30 | **Parameters:**
31 |
32 | | Name | Type |
33 | | ------ | ------ |
34 | | string | `string` |
35 | | `Optional` options | [SearchParserOptions](../interfaces/_index_d_.searchparseroptions.md) |
36 |
37 | **Returns:** `string` \| [SearchParserResult](../interfaces/_index_d_.searchparserresult.md)
38 |
39 | ___
40 |
41 |
--------------------------------------------------------------------------------
/index.d.ts:
--------------------------------------------------------------------------------
1 | // @file
2 | // Type definitions for search-query-parser.
3 | // Project: https://github.com/nepsilon/search-query-parser
4 | // Definitions by: Geoffrey Roberts
5 | // Definitions: https://github.com/nepsilon/search-query-parser
6 |
7 | export interface SearchParserOptions {
8 | offsets?: boolean;
9 | tokenize?: boolean;
10 | keywords?: string[];
11 | ranges?: string[];
12 | alwaysArray?: boolean;
13 | }
14 |
15 | export interface ISearchParserDictionary {
16 | [key: string]: any;
17 | }
18 |
19 | export type SearchParserOffset = (SearchParserKeyWordOffset | SearchParserTextOffset) & {
20 | offsetStart: number;
21 | offsetEnd: number;
22 | }
23 |
24 | export type SearchParserKeyWordOffset = {
25 | keyword: string;
26 | value?: string;
27 |
28 | }
29 |
30 | export type SearchParserTextOffset = {
31 | text: string;
32 | }
33 |
34 | export interface SearchParserResult extends ISearchParserDictionary {
35 | text?: string | string[];
36 | offsets?: SearchParserOffset[];
37 | exclude?: ISearchParserDictionary;
38 | }
39 |
40 | export function parse(string: string, options?: SearchParserOptions & {
41 | tokenize: false
42 | }): string;
43 | export function parse(string: string, options?: SearchParserOptions & {
44 | tokenize: true
45 | }): SearchParserResult & {
46 | text?: string[]
47 | };
48 | export function parse(string: string, options?: SearchParserOptions): string | SearchParserResult;
49 |
50 | export function stringify(searchParserResult: string | SearchParserResult, options?: SearchParserOptions): string;
51 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('./lib/search-query-parser');
2 |
--------------------------------------------------------------------------------
/lib/search-query-parser.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * search-query-parser.js
3 | * Copyright(c) 2014-2019
4 | * MIT Licensed
5 | */
6 |
7 | exports.parse = function (string, options) {
8 |
9 | // Set a default options object when none is provided
10 | if (!options) {
11 | options = {offsets: true};
12 | } else {
13 | // If options offsets was't passed, set it to true
14 | options.offsets = (typeof options.offsets === 'undefined' ? true : options.offsets)
15 | }
16 |
17 | if (!string) {
18 | string = '';
19 | }
20 |
21 | // When a simple string, return it
22 | if (-1 === string.indexOf(':') && !options.tokenize) {
23 | return string;
24 | }
25 | // When no keywords or ranges set, treat as a simple string
26 | else if (!options.keywords && !options.ranges && !options.tokenize){
27 | return string;
28 | }
29 | // Otherwise parse the advanced query syntax
30 | else {
31 | // Our object to store the query object
32 | var query = {text: []};
33 | // When offsets is true, create their array
34 | if (options.offsets) {
35 | query.offsets = [];
36 | }
37 | var exclusion = {};
38 | var terms = [];
39 | // Get a list of search terms respecting single and double quotes
40 | var regex = /(\S+:'(?:[^'\\]|\\.)*')|(\S+:"(?:[^"\\]|\\.)*")|(-?"(?:[^"\\]|\\.)*")|(-?'(?:[^'\\]|\\.)*')|\S+|\S+:\S+/g;
41 | var match;
42 | while ((match = regex.exec(string)) !== null) {
43 | var term = match[0];
44 | var sepIndex = term.indexOf(':');
45 | if (sepIndex !== -1) {
46 | var split = term.split(':'),
47 | key = term.slice(0, sepIndex),
48 | val = term.slice(sepIndex + 1);
49 | // Strip surrounding quotes
50 | val = val.replace(/^\"|\"$|^\'|\'$/g, '');
51 | // Strip backslashes respecting escapes
52 | val = (val + '').replace(/\\(.?)/g, function (s, n1) {
53 | switch (n1) {
54 | case '\\':
55 | return '\\';
56 | case '0':
57 | return '\u0000';
58 | case '':
59 | return '';
60 | default:
61 | return n1;
62 | }
63 | });
64 | terms.push({
65 | keyword: key,
66 | value: val,
67 | offsetStart: match.index,
68 | offsetEnd: match.index + term.length
69 | });
70 | } else {
71 | var isExcludedTerm = false;
72 | if (term[0] === '-') {
73 | isExcludedTerm = true;
74 | term = term.slice(1);
75 | }
76 |
77 | // Strip surrounding quotes
78 | term = term.replace(/^\"|\"$|^\'|\'$/g, '');
79 | // Strip backslashes respecting escapes
80 | term = (term + '').replace(/\\(.?)/g, function (s, n1) {
81 | switch (n1) {
82 | case '\\':
83 | return '\\';
84 | case '0':
85 | return '\u0000';
86 | case '':
87 | return '';
88 | default:
89 | return n1;
90 | }
91 | });
92 |
93 | if (isExcludedTerm) {
94 | if (exclusion['text']) {
95 | if (exclusion['text'] instanceof Array) {
96 | exclusion['text'].push(term);
97 | } else {
98 | exclusion['text'] = [exclusion['text']];
99 | exclusion['text'].push(term);
100 | }
101 | } else {
102 | // First time seeing an excluded text term
103 | exclusion['text'] = term;
104 | }
105 | } else {
106 | terms.push({
107 | text: term,
108 | offsetStart: match.index,
109 | offsetEnd: match.index + term.length
110 | });
111 | }
112 | }
113 | }
114 | // Reverse to ensure proper order when pop()'ing.
115 | terms.reverse();
116 | // For each search term
117 | var term;
118 | while (term = terms.pop()) {
119 | // When just a simple term
120 | if (term.text) {
121 | // We add it as pure text
122 | query.text.push(term.text);
123 | // When offsets is true, push a new offset
124 | if (options.offsets) {
125 | query.offsets.push(term);
126 | }
127 | }
128 | // We got an advanced search syntax
129 | else {
130 | var key = term.keyword;
131 | // Check if the key is a registered keyword
132 | options.keywords = options.keywords || [];
133 | var isKeyword = false;
134 | var isExclusion = false;
135 | if (!/^-/.test(key)) {
136 | isKeyword = !(-1 === options.keywords.indexOf(key));
137 | } else if (key[0] === '-') {
138 | var _key = key.slice(1);
139 | isKeyword = !(-1 === options.keywords.indexOf(_key))
140 | if (isKeyword) {
141 | key = _key;
142 | isExclusion = true;
143 | }
144 | }
145 |
146 | // Check if the key is a registered range
147 | options.ranges = options.ranges || [];
148 | var isRange = !(-1 === options.ranges.indexOf(key));
149 | // When the key matches a keyword
150 | if (isKeyword) {
151 | // When offsets is true, push a new offset
152 | if (options.offsets) {
153 | query.offsets.push({
154 | keyword: key,
155 | value: term.value,
156 | offsetStart: isExclusion ? term.offsetStart + 1 : term.offsetStart,
157 | offsetEnd: term.offsetEnd
158 | });
159 | }
160 |
161 | var value = term.value;
162 | // When value is a thing
163 | if (value.length) {
164 | // Get an array of values when several are there
165 | var values = value.split(',');
166 | if (isExclusion) {
167 | if (exclusion[key]) {
168 | // ...many times...
169 | if (exclusion[key] instanceof Array) {
170 | // ...and got several values this time...
171 | if (values.length > 1) {
172 | // ... concatenate both arrays.
173 | exclusion[key] = exclusion[key].concat(values);
174 | }
175 | else {
176 | // ... append the current single value.
177 | exclusion[key].push(value);
178 | }
179 | }
180 | // We saw that keyword only once before
181 | else {
182 | // Put both the current value and the new
183 | // value in an array
184 | exclusion[key] = [exclusion[key]];
185 | exclusion[key].push(value);
186 | }
187 | }
188 | // First time we see that keyword
189 | else {
190 | // ...and got several values this time...
191 | if (values.length > 1) {
192 | // ...add all values seen.
193 | exclusion[key] = values;
194 | }
195 | // Got only a single value this time
196 | else {
197 | // Record its value as a string
198 | if (options.alwaysArray) {
199 | // ...but we always return an array if option alwaysArray is true
200 | exclusion[key] = [value];
201 | } else {
202 | // Record its value as a string
203 | exclusion[key] = value;
204 | }
205 | }
206 | }
207 | } else {
208 | // If we already have seen that keyword...
209 | if (query[key]) {
210 | // ...many times...
211 | if (query[key] instanceof Array) {
212 | // ...and got several values this time...
213 | if (values.length > 1) {
214 | // ... concatenate both arrays.
215 | query[key] = query[key].concat(values);
216 | }
217 | else {
218 | // ... append the current single value.
219 | query[key].push(value);
220 | }
221 | }
222 | // We saw that keyword only once before
223 | else {
224 | // Put both the current value and the new
225 | // value in an array
226 | query[key] = [query[key]];
227 | query[key].push(value);
228 | }
229 | }
230 | // First time we see that keyword
231 | else {
232 | // ...and got several values this time...
233 | if (values.length > 1) {
234 | // ...add all values seen.
235 | query[key] = values;
236 | }
237 | // Got only a single value this time
238 | else {
239 | if (options.alwaysArray) {
240 | // ...but we always return an array if option alwaysArray is true
241 | query[key] = [value];
242 | } else {
243 | // Record its value as a string
244 | query[key] = value;
245 | }
246 | }
247 | }
248 | }
249 | }
250 | }
251 | // The key allows a range
252 | else if (isRange) {
253 | // When offsets is true, push a new offset
254 | if (options.offsets) {
255 | query.offsets.push(term);
256 | }
257 |
258 | var value = term.value;
259 | // Range are separated with a dash
260 | var rangeValues = value.split('-');
261 | // When both end of the range are specified
262 | // keyword:XXXX-YYYY
263 | query[key] = {};
264 | if (2 === rangeValues.length) {
265 | query[key].from = rangeValues[0];
266 | query[key].to = rangeValues[1];
267 | }
268 | // When pairs of ranges are specified
269 | // keyword:XXXX-YYYY,AAAA-BBBB
270 | else if (!rangeValues.length % 2) {
271 | }
272 | // When only getting a single value,
273 | // or an odd number of values
274 | else {
275 | query[key].from = value;
276 | }
277 | }
278 | else {
279 | // We add it as pure text
280 | var text = term.keyword + ':' + term.value;
281 | query.text.push(text);
282 |
283 | // When offsets is true, push a new offset
284 | if (options.offsets) {
285 | query.offsets.push({
286 | text: text,
287 | offsetStart: term.offsetStart,
288 | offsetEnd: term.offsetEnd
289 | });
290 | }
291 | }
292 | }
293 | }
294 |
295 | // Concatenate all text terms if any
296 | if (query.text.length) {
297 | if (!options.tokenize) {
298 | query.text = query.text.join(' ').trim();
299 | }
300 | }
301 | // Just remove the attribute text when it's empty
302 | else {
303 | delete query.text;
304 | }
305 |
306 | // Return forged query object
307 | query.exclude = exclusion;
308 | return query;
309 | }
310 |
311 | };
312 |
313 | exports.stringify = function (queryObject, options, prefix) {
314 |
315 | // Set a default options object when none is provided
316 | if (!options) {
317 | options = {offsets: true};
318 | }
319 |
320 | // If the query object is falsy we can just return an empty string
321 | if (!queryObject) {
322 | return '';
323 | }
324 |
325 | // If the query object is already a string, we can return it immediately
326 | if (typeof queryObject === 'string') {
327 | return queryObject;
328 | }
329 |
330 | // If the query object is an array, we can return it concatenated with a space
331 | if (Array.isArray(queryObject)) {
332 | return queryObject.join(' ');
333 | }
334 |
335 | // If the query object does not have any keys, we can return an empty string
336 | if (!Object.keys(queryObject).length) {
337 | return '';
338 | }
339 |
340 | // If the query object contains only text which is a string, we can return it immediately
341 | if (Object.keys(queryObject).length === 3 && !!queryObject.text && !!queryObject.offsets && !!queryObject.exclude && typeof queryObject.text === 'string') {
342 | return queryObject.text;
343 | }
344 |
345 | // We will use a prefix for the exclude syntax later one
346 | if (!prefix) {
347 | prefix = ''
348 | }
349 |
350 | // Helpers
351 | var addQuotes = function (string) {
352 | return string.indexOf(' ') > - 1 ? JSON.stringify(string) : string;
353 | };
354 | var addPrefix = function (string) {
355 | return prefix + string;
356 | };
357 |
358 | // Keep track of all single parts in this array
359 | var parts = [];
360 |
361 | // Text
362 | if (queryObject.text) {
363 | var value = [];
364 | if (typeof queryObject.text === 'string') {
365 | value.push(queryObject.text);
366 | } else {
367 | value.push.apply(value, queryObject.text);
368 | }
369 |
370 | if (value.length > 0) {
371 | parts.push(value.map(addQuotes).map(addPrefix).join(' '));
372 | }
373 | }
374 |
375 | // Keywords
376 | if (options.keywords) {
377 | options.keywords.forEach(function (keyword) {
378 | if (!queryObject[keyword]) {
379 | return
380 | }
381 |
382 | var value = [];
383 | if (typeof queryObject[keyword] === 'string') {
384 | value.push(queryObject[keyword]);
385 | } else {
386 | value.push.apply(value, queryObject[keyword]);
387 | }
388 |
389 | if (value.length > 0) {
390 | parts.push(addPrefix(keyword + ':' + value.map(addQuotes).join(',')));
391 | }
392 | });
393 | }
394 |
395 | // Ranges
396 | if (options.ranges) {
397 | options.ranges.forEach(function (range) {
398 | if (!queryObject[range]) {
399 | return
400 | }
401 |
402 | var value = queryObject[range].from;
403 | var to = queryObject[range].to;
404 | if (to) {
405 | value = value + '-' + to;
406 | }
407 |
408 | if (value) {
409 | parts.push(addPrefix(range + ':' + value));
410 | }
411 | });
412 | }
413 |
414 | // Exclude
415 | if (queryObject.exclude) {
416 | if (Object.keys(queryObject.exclude).length > 0) {
417 | parts.push(exports.stringify(queryObject.exclude, options, '-'));
418 | }
419 | }
420 |
421 | return parts.join(' ');
422 |
423 | };
424 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "search-query-parser",
3 | "version": "1.6.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "search-query-parser",
9 | "version": "1.6.0",
10 | "license": "MIT",
11 | "devDependencies": {
12 | "mocha": "^10.2.0",
13 | "should": "^13.2.3",
14 | "typescript": "^4.2.2"
15 | }
16 | },
17 | "node_modules/ansi-colors": {
18 | "version": "4.1.1",
19 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
20 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
21 | "dev": true,
22 | "engines": {
23 | "node": ">=6"
24 | }
25 | },
26 | "node_modules/ansi-regex": {
27 | "version": "5.0.1",
28 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
29 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
30 | "dev": true,
31 | "engines": {
32 | "node": ">=8"
33 | }
34 | },
35 | "node_modules/ansi-styles": {
36 | "version": "4.3.0",
37 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
38 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
39 | "dev": true,
40 | "dependencies": {
41 | "color-convert": "^2.0.1"
42 | },
43 | "engines": {
44 | "node": ">=8"
45 | },
46 | "funding": {
47 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
48 | }
49 | },
50 | "node_modules/anymatch": {
51 | "version": "3.1.2",
52 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
53 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
54 | "dev": true,
55 | "dependencies": {
56 | "normalize-path": "^3.0.0",
57 | "picomatch": "^2.0.4"
58 | },
59 | "engines": {
60 | "node": ">= 8"
61 | }
62 | },
63 | "node_modules/argparse": {
64 | "version": "2.0.1",
65 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
66 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
67 | "dev": true
68 | },
69 | "node_modules/balanced-match": {
70 | "version": "1.0.2",
71 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
72 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
73 | "dev": true
74 | },
75 | "node_modules/binary-extensions": {
76 | "version": "2.2.0",
77 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
78 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
79 | "dev": true,
80 | "engines": {
81 | "node": ">=8"
82 | }
83 | },
84 | "node_modules/brace-expansion": {
85 | "version": "1.1.11",
86 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
87 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
88 | "dev": true,
89 | "dependencies": {
90 | "balanced-match": "^1.0.0",
91 | "concat-map": "0.0.1"
92 | }
93 | },
94 | "node_modules/braces": {
95 | "version": "3.0.2",
96 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
97 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
98 | "dev": true,
99 | "dependencies": {
100 | "fill-range": "^7.0.1"
101 | },
102 | "engines": {
103 | "node": ">=8"
104 | }
105 | },
106 | "node_modules/browser-stdout": {
107 | "version": "1.3.1",
108 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
109 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
110 | "dev": true
111 | },
112 | "node_modules/camelcase": {
113 | "version": "6.3.0",
114 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
115 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
116 | "dev": true,
117 | "engines": {
118 | "node": ">=10"
119 | },
120 | "funding": {
121 | "url": "https://github.com/sponsors/sindresorhus"
122 | }
123 | },
124 | "node_modules/chalk": {
125 | "version": "4.1.2",
126 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
127 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
128 | "dev": true,
129 | "dependencies": {
130 | "ansi-styles": "^4.1.0",
131 | "supports-color": "^7.1.0"
132 | },
133 | "engines": {
134 | "node": ">=10"
135 | },
136 | "funding": {
137 | "url": "https://github.com/chalk/chalk?sponsor=1"
138 | }
139 | },
140 | "node_modules/chalk/node_modules/supports-color": {
141 | "version": "7.2.0",
142 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
143 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
144 | "dev": true,
145 | "dependencies": {
146 | "has-flag": "^4.0.0"
147 | },
148 | "engines": {
149 | "node": ">=8"
150 | }
151 | },
152 | "node_modules/chokidar": {
153 | "version": "3.5.3",
154 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
155 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
156 | "dev": true,
157 | "funding": [
158 | {
159 | "type": "individual",
160 | "url": "https://paulmillr.com/funding/"
161 | }
162 | ],
163 | "dependencies": {
164 | "anymatch": "~3.1.2",
165 | "braces": "~3.0.2",
166 | "glob-parent": "~5.1.2",
167 | "is-binary-path": "~2.1.0",
168 | "is-glob": "~4.0.1",
169 | "normalize-path": "~3.0.0",
170 | "readdirp": "~3.6.0"
171 | },
172 | "engines": {
173 | "node": ">= 8.10.0"
174 | },
175 | "optionalDependencies": {
176 | "fsevents": "~2.3.2"
177 | }
178 | },
179 | "node_modules/cliui": {
180 | "version": "7.0.4",
181 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
182 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
183 | "dev": true,
184 | "dependencies": {
185 | "string-width": "^4.2.0",
186 | "strip-ansi": "^6.0.0",
187 | "wrap-ansi": "^7.0.0"
188 | }
189 | },
190 | "node_modules/color-convert": {
191 | "version": "2.0.1",
192 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
193 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
194 | "dev": true,
195 | "dependencies": {
196 | "color-name": "~1.1.4"
197 | },
198 | "engines": {
199 | "node": ">=7.0.0"
200 | }
201 | },
202 | "node_modules/color-name": {
203 | "version": "1.1.4",
204 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
205 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
206 | "dev": true
207 | },
208 | "node_modules/concat-map": {
209 | "version": "0.0.1",
210 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
211 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
212 | "dev": true
213 | },
214 | "node_modules/debug": {
215 | "version": "4.3.4",
216 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
217 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
218 | "dev": true,
219 | "dependencies": {
220 | "ms": "2.1.2"
221 | },
222 | "engines": {
223 | "node": ">=6.0"
224 | },
225 | "peerDependenciesMeta": {
226 | "supports-color": {
227 | "optional": true
228 | }
229 | }
230 | },
231 | "node_modules/debug/node_modules/ms": {
232 | "version": "2.1.2",
233 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
234 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
235 | "dev": true
236 | },
237 | "node_modules/decamelize": {
238 | "version": "4.0.0",
239 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
240 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
241 | "dev": true,
242 | "engines": {
243 | "node": ">=10"
244 | },
245 | "funding": {
246 | "url": "https://github.com/sponsors/sindresorhus"
247 | }
248 | },
249 | "node_modules/diff": {
250 | "version": "5.0.0",
251 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
252 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
253 | "dev": true,
254 | "engines": {
255 | "node": ">=0.3.1"
256 | }
257 | },
258 | "node_modules/emoji-regex": {
259 | "version": "8.0.0",
260 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
261 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
262 | "dev": true
263 | },
264 | "node_modules/escalade": {
265 | "version": "3.1.1",
266 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
267 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
268 | "dev": true,
269 | "engines": {
270 | "node": ">=6"
271 | }
272 | },
273 | "node_modules/escape-string-regexp": {
274 | "version": "4.0.0",
275 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
276 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
277 | "dev": true,
278 | "engines": {
279 | "node": ">=10"
280 | },
281 | "funding": {
282 | "url": "https://github.com/sponsors/sindresorhus"
283 | }
284 | },
285 | "node_modules/fill-range": {
286 | "version": "7.0.1",
287 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
288 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
289 | "dev": true,
290 | "dependencies": {
291 | "to-regex-range": "^5.0.1"
292 | },
293 | "engines": {
294 | "node": ">=8"
295 | }
296 | },
297 | "node_modules/find-up": {
298 | "version": "5.0.0",
299 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
300 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
301 | "dev": true,
302 | "dependencies": {
303 | "locate-path": "^6.0.0",
304 | "path-exists": "^4.0.0"
305 | },
306 | "engines": {
307 | "node": ">=10"
308 | },
309 | "funding": {
310 | "url": "https://github.com/sponsors/sindresorhus"
311 | }
312 | },
313 | "node_modules/flat": {
314 | "version": "5.0.2",
315 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
316 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
317 | "dev": true,
318 | "bin": {
319 | "flat": "cli.js"
320 | }
321 | },
322 | "node_modules/fs.realpath": {
323 | "version": "1.0.0",
324 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
325 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
326 | "dev": true
327 | },
328 | "node_modules/fsevents": {
329 | "version": "2.3.2",
330 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
331 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
332 | "dev": true,
333 | "hasInstallScript": true,
334 | "optional": true,
335 | "os": [
336 | "darwin"
337 | ],
338 | "engines": {
339 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
340 | }
341 | },
342 | "node_modules/get-caller-file": {
343 | "version": "2.0.5",
344 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
345 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
346 | "dev": true,
347 | "engines": {
348 | "node": "6.* || 8.* || >= 10.*"
349 | }
350 | },
351 | "node_modules/glob": {
352 | "version": "7.2.0",
353 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
354 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
355 | "dev": true,
356 | "dependencies": {
357 | "fs.realpath": "^1.0.0",
358 | "inflight": "^1.0.4",
359 | "inherits": "2",
360 | "minimatch": "^3.0.4",
361 | "once": "^1.3.0",
362 | "path-is-absolute": "^1.0.0"
363 | },
364 | "engines": {
365 | "node": "*"
366 | },
367 | "funding": {
368 | "url": "https://github.com/sponsors/isaacs"
369 | }
370 | },
371 | "node_modules/glob-parent": {
372 | "version": "5.1.2",
373 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
374 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
375 | "dev": true,
376 | "dependencies": {
377 | "is-glob": "^4.0.1"
378 | },
379 | "engines": {
380 | "node": ">= 6"
381 | }
382 | },
383 | "node_modules/has-flag": {
384 | "version": "4.0.0",
385 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
386 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
387 | "dev": true,
388 | "engines": {
389 | "node": ">=8"
390 | }
391 | },
392 | "node_modules/he": {
393 | "version": "1.2.0",
394 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
395 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
396 | "dev": true,
397 | "bin": {
398 | "he": "bin/he"
399 | }
400 | },
401 | "node_modules/inflight": {
402 | "version": "1.0.6",
403 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
404 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
405 | "dev": true,
406 | "dependencies": {
407 | "once": "^1.3.0",
408 | "wrappy": "1"
409 | }
410 | },
411 | "node_modules/inherits": {
412 | "version": "2.0.4",
413 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
414 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
415 | "dev": true
416 | },
417 | "node_modules/is-binary-path": {
418 | "version": "2.1.0",
419 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
420 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
421 | "dev": true,
422 | "dependencies": {
423 | "binary-extensions": "^2.0.0"
424 | },
425 | "engines": {
426 | "node": ">=8"
427 | }
428 | },
429 | "node_modules/is-extglob": {
430 | "version": "2.1.1",
431 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
432 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
433 | "dev": true,
434 | "engines": {
435 | "node": ">=0.10.0"
436 | }
437 | },
438 | "node_modules/is-fullwidth-code-point": {
439 | "version": "3.0.0",
440 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
441 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
442 | "dev": true,
443 | "engines": {
444 | "node": ">=8"
445 | }
446 | },
447 | "node_modules/is-glob": {
448 | "version": "4.0.3",
449 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
450 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
451 | "dev": true,
452 | "dependencies": {
453 | "is-extglob": "^2.1.1"
454 | },
455 | "engines": {
456 | "node": ">=0.10.0"
457 | }
458 | },
459 | "node_modules/is-number": {
460 | "version": "7.0.0",
461 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
462 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
463 | "dev": true,
464 | "engines": {
465 | "node": ">=0.12.0"
466 | }
467 | },
468 | "node_modules/is-plain-obj": {
469 | "version": "2.1.0",
470 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
471 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
472 | "dev": true,
473 | "engines": {
474 | "node": ">=8"
475 | }
476 | },
477 | "node_modules/is-unicode-supported": {
478 | "version": "0.1.0",
479 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
480 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
481 | "dev": true,
482 | "engines": {
483 | "node": ">=10"
484 | },
485 | "funding": {
486 | "url": "https://github.com/sponsors/sindresorhus"
487 | }
488 | },
489 | "node_modules/js-yaml": {
490 | "version": "4.1.0",
491 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
492 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
493 | "dev": true,
494 | "dependencies": {
495 | "argparse": "^2.0.1"
496 | },
497 | "bin": {
498 | "js-yaml": "bin/js-yaml.js"
499 | }
500 | },
501 | "node_modules/locate-path": {
502 | "version": "6.0.0",
503 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
504 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
505 | "dev": true,
506 | "dependencies": {
507 | "p-locate": "^5.0.0"
508 | },
509 | "engines": {
510 | "node": ">=10"
511 | },
512 | "funding": {
513 | "url": "https://github.com/sponsors/sindresorhus"
514 | }
515 | },
516 | "node_modules/log-symbols": {
517 | "version": "4.1.0",
518 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
519 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
520 | "dev": true,
521 | "dependencies": {
522 | "chalk": "^4.1.0",
523 | "is-unicode-supported": "^0.1.0"
524 | },
525 | "engines": {
526 | "node": ">=10"
527 | },
528 | "funding": {
529 | "url": "https://github.com/sponsors/sindresorhus"
530 | }
531 | },
532 | "node_modules/minimatch": {
533 | "version": "3.1.2",
534 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
535 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
536 | "dev": true,
537 | "dependencies": {
538 | "brace-expansion": "^1.1.7"
539 | },
540 | "engines": {
541 | "node": "*"
542 | }
543 | },
544 | "node_modules/mocha": {
545 | "version": "10.2.0",
546 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
547 | "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
548 | "dev": true,
549 | "dependencies": {
550 | "ansi-colors": "4.1.1",
551 | "browser-stdout": "1.3.1",
552 | "chokidar": "3.5.3",
553 | "debug": "4.3.4",
554 | "diff": "5.0.0",
555 | "escape-string-regexp": "4.0.0",
556 | "find-up": "5.0.0",
557 | "glob": "7.2.0",
558 | "he": "1.2.0",
559 | "js-yaml": "4.1.0",
560 | "log-symbols": "4.1.0",
561 | "minimatch": "5.0.1",
562 | "ms": "2.1.3",
563 | "nanoid": "3.3.3",
564 | "serialize-javascript": "6.0.0",
565 | "strip-json-comments": "3.1.1",
566 | "supports-color": "8.1.1",
567 | "workerpool": "6.2.1",
568 | "yargs": "16.2.0",
569 | "yargs-parser": "20.2.4",
570 | "yargs-unparser": "2.0.0"
571 | },
572 | "bin": {
573 | "_mocha": "bin/_mocha",
574 | "mocha": "bin/mocha.js"
575 | },
576 | "engines": {
577 | "node": ">= 14.0.0"
578 | },
579 | "funding": {
580 | "type": "opencollective",
581 | "url": "https://opencollective.com/mochajs"
582 | }
583 | },
584 | "node_modules/mocha/node_modules/brace-expansion": {
585 | "version": "2.0.1",
586 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
587 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
588 | "dev": true,
589 | "dependencies": {
590 | "balanced-match": "^1.0.0"
591 | }
592 | },
593 | "node_modules/mocha/node_modules/minimatch": {
594 | "version": "5.0.1",
595 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
596 | "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
597 | "dev": true,
598 | "dependencies": {
599 | "brace-expansion": "^2.0.1"
600 | },
601 | "engines": {
602 | "node": ">=10"
603 | }
604 | },
605 | "node_modules/ms": {
606 | "version": "2.1.3",
607 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
608 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
609 | "dev": true
610 | },
611 | "node_modules/nanoid": {
612 | "version": "3.3.3",
613 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
614 | "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
615 | "dev": true,
616 | "bin": {
617 | "nanoid": "bin/nanoid.cjs"
618 | },
619 | "engines": {
620 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
621 | }
622 | },
623 | "node_modules/normalize-path": {
624 | "version": "3.0.0",
625 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
626 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
627 | "dev": true,
628 | "engines": {
629 | "node": ">=0.10.0"
630 | }
631 | },
632 | "node_modules/once": {
633 | "version": "1.4.0",
634 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
635 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
636 | "dev": true,
637 | "dependencies": {
638 | "wrappy": "1"
639 | }
640 | },
641 | "node_modules/p-limit": {
642 | "version": "3.1.0",
643 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
644 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
645 | "dev": true,
646 | "dependencies": {
647 | "yocto-queue": "^0.1.0"
648 | },
649 | "engines": {
650 | "node": ">=10"
651 | },
652 | "funding": {
653 | "url": "https://github.com/sponsors/sindresorhus"
654 | }
655 | },
656 | "node_modules/p-locate": {
657 | "version": "5.0.0",
658 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
659 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
660 | "dev": true,
661 | "dependencies": {
662 | "p-limit": "^3.0.2"
663 | },
664 | "engines": {
665 | "node": ">=10"
666 | },
667 | "funding": {
668 | "url": "https://github.com/sponsors/sindresorhus"
669 | }
670 | },
671 | "node_modules/path-exists": {
672 | "version": "4.0.0",
673 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
674 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
675 | "dev": true,
676 | "engines": {
677 | "node": ">=8"
678 | }
679 | },
680 | "node_modules/path-is-absolute": {
681 | "version": "1.0.1",
682 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
683 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
684 | "dev": true,
685 | "engines": {
686 | "node": ">=0.10.0"
687 | }
688 | },
689 | "node_modules/picomatch": {
690 | "version": "2.3.1",
691 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
692 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
693 | "dev": true,
694 | "engines": {
695 | "node": ">=8.6"
696 | },
697 | "funding": {
698 | "url": "https://github.com/sponsors/jonschlinkert"
699 | }
700 | },
701 | "node_modules/randombytes": {
702 | "version": "2.1.0",
703 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
704 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
705 | "dev": true,
706 | "dependencies": {
707 | "safe-buffer": "^5.1.0"
708 | }
709 | },
710 | "node_modules/readdirp": {
711 | "version": "3.6.0",
712 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
713 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
714 | "dev": true,
715 | "dependencies": {
716 | "picomatch": "^2.2.1"
717 | },
718 | "engines": {
719 | "node": ">=8.10.0"
720 | }
721 | },
722 | "node_modules/require-directory": {
723 | "version": "2.1.1",
724 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
725 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
726 | "dev": true,
727 | "engines": {
728 | "node": ">=0.10.0"
729 | }
730 | },
731 | "node_modules/safe-buffer": {
732 | "version": "5.2.1",
733 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
734 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
735 | "dev": true,
736 | "funding": [
737 | {
738 | "type": "github",
739 | "url": "https://github.com/sponsors/feross"
740 | },
741 | {
742 | "type": "patreon",
743 | "url": "https://www.patreon.com/feross"
744 | },
745 | {
746 | "type": "consulting",
747 | "url": "https://feross.org/support"
748 | }
749 | ]
750 | },
751 | "node_modules/serialize-javascript": {
752 | "version": "6.0.0",
753 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
754 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
755 | "dev": true,
756 | "dependencies": {
757 | "randombytes": "^2.1.0"
758 | }
759 | },
760 | "node_modules/should": {
761 | "version": "13.2.3",
762 | "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz",
763 | "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==",
764 | "dev": true,
765 | "dependencies": {
766 | "should-equal": "^2.0.0",
767 | "should-format": "^3.0.3",
768 | "should-type": "^1.4.0",
769 | "should-type-adaptors": "^1.0.1",
770 | "should-util": "^1.0.0"
771 | }
772 | },
773 | "node_modules/should-equal": {
774 | "version": "2.0.0",
775 | "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz",
776 | "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==",
777 | "dev": true,
778 | "dependencies": {
779 | "should-type": "^1.4.0"
780 | }
781 | },
782 | "node_modules/should-format": {
783 | "version": "3.0.3",
784 | "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz",
785 | "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=",
786 | "dev": true,
787 | "dependencies": {
788 | "should-type": "^1.3.0",
789 | "should-type-adaptors": "^1.0.1"
790 | }
791 | },
792 | "node_modules/should-type": {
793 | "version": "1.4.0",
794 | "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz",
795 | "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=",
796 | "dev": true
797 | },
798 | "node_modules/should-type-adaptors": {
799 | "version": "1.1.0",
800 | "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz",
801 | "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==",
802 | "dev": true,
803 | "dependencies": {
804 | "should-type": "^1.3.0",
805 | "should-util": "^1.0.0"
806 | }
807 | },
808 | "node_modules/should-util": {
809 | "version": "1.0.1",
810 | "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz",
811 | "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==",
812 | "dev": true
813 | },
814 | "node_modules/string-width": {
815 | "version": "4.2.3",
816 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
817 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
818 | "dev": true,
819 | "dependencies": {
820 | "emoji-regex": "^8.0.0",
821 | "is-fullwidth-code-point": "^3.0.0",
822 | "strip-ansi": "^6.0.1"
823 | },
824 | "engines": {
825 | "node": ">=8"
826 | }
827 | },
828 | "node_modules/strip-ansi": {
829 | "version": "6.0.1",
830 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
831 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
832 | "dev": true,
833 | "dependencies": {
834 | "ansi-regex": "^5.0.1"
835 | },
836 | "engines": {
837 | "node": ">=8"
838 | }
839 | },
840 | "node_modules/strip-json-comments": {
841 | "version": "3.1.1",
842 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
843 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
844 | "dev": true,
845 | "engines": {
846 | "node": ">=8"
847 | },
848 | "funding": {
849 | "url": "https://github.com/sponsors/sindresorhus"
850 | }
851 | },
852 | "node_modules/supports-color": {
853 | "version": "8.1.1",
854 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
855 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
856 | "dev": true,
857 | "dependencies": {
858 | "has-flag": "^4.0.0"
859 | },
860 | "engines": {
861 | "node": ">=10"
862 | },
863 | "funding": {
864 | "url": "https://github.com/chalk/supports-color?sponsor=1"
865 | }
866 | },
867 | "node_modules/to-regex-range": {
868 | "version": "5.0.1",
869 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
870 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
871 | "dev": true,
872 | "dependencies": {
873 | "is-number": "^7.0.0"
874 | },
875 | "engines": {
876 | "node": ">=8.0"
877 | }
878 | },
879 | "node_modules/typescript": {
880 | "version": "4.5.5",
881 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
882 | "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
883 | "dev": true,
884 | "bin": {
885 | "tsc": "bin/tsc",
886 | "tsserver": "bin/tsserver"
887 | },
888 | "engines": {
889 | "node": ">=4.2.0"
890 | }
891 | },
892 | "node_modules/workerpool": {
893 | "version": "6.2.1",
894 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
895 | "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
896 | "dev": true
897 | },
898 | "node_modules/wrap-ansi": {
899 | "version": "7.0.0",
900 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
901 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
902 | "dev": true,
903 | "dependencies": {
904 | "ansi-styles": "^4.0.0",
905 | "string-width": "^4.1.0",
906 | "strip-ansi": "^6.0.0"
907 | },
908 | "engines": {
909 | "node": ">=10"
910 | },
911 | "funding": {
912 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
913 | }
914 | },
915 | "node_modules/wrappy": {
916 | "version": "1.0.2",
917 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
918 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
919 | "dev": true
920 | },
921 | "node_modules/y18n": {
922 | "version": "5.0.8",
923 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
924 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
925 | "dev": true,
926 | "engines": {
927 | "node": ">=10"
928 | }
929 | },
930 | "node_modules/yargs": {
931 | "version": "16.2.0",
932 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
933 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
934 | "dev": true,
935 | "dependencies": {
936 | "cliui": "^7.0.2",
937 | "escalade": "^3.1.1",
938 | "get-caller-file": "^2.0.5",
939 | "require-directory": "^2.1.1",
940 | "string-width": "^4.2.0",
941 | "y18n": "^5.0.5",
942 | "yargs-parser": "^20.2.2"
943 | },
944 | "engines": {
945 | "node": ">=10"
946 | }
947 | },
948 | "node_modules/yargs-parser": {
949 | "version": "20.2.4",
950 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
951 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
952 | "dev": true,
953 | "engines": {
954 | "node": ">=10"
955 | }
956 | },
957 | "node_modules/yargs-unparser": {
958 | "version": "2.0.0",
959 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
960 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
961 | "dev": true,
962 | "dependencies": {
963 | "camelcase": "^6.0.0",
964 | "decamelize": "^4.0.0",
965 | "flat": "^5.0.2",
966 | "is-plain-obj": "^2.1.0"
967 | },
968 | "engines": {
969 | "node": ">=10"
970 | }
971 | },
972 | "node_modules/yocto-queue": {
973 | "version": "0.1.0",
974 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
975 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
976 | "dev": true,
977 | "engines": {
978 | "node": ">=10"
979 | },
980 | "funding": {
981 | "url": "https://github.com/sponsors/sindresorhus"
982 | }
983 | }
984 | },
985 | "dependencies": {
986 | "ansi-colors": {
987 | "version": "4.1.1",
988 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
989 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
990 | "dev": true
991 | },
992 | "ansi-regex": {
993 | "version": "5.0.1",
994 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
995 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
996 | "dev": true
997 | },
998 | "ansi-styles": {
999 | "version": "4.3.0",
1000 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
1001 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
1002 | "dev": true,
1003 | "requires": {
1004 | "color-convert": "^2.0.1"
1005 | }
1006 | },
1007 | "anymatch": {
1008 | "version": "3.1.2",
1009 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
1010 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
1011 | "dev": true,
1012 | "requires": {
1013 | "normalize-path": "^3.0.0",
1014 | "picomatch": "^2.0.4"
1015 | }
1016 | },
1017 | "argparse": {
1018 | "version": "2.0.1",
1019 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
1020 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
1021 | "dev": true
1022 | },
1023 | "balanced-match": {
1024 | "version": "1.0.2",
1025 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
1026 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
1027 | "dev": true
1028 | },
1029 | "binary-extensions": {
1030 | "version": "2.2.0",
1031 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
1032 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
1033 | "dev": true
1034 | },
1035 | "brace-expansion": {
1036 | "version": "1.1.11",
1037 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1038 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1039 | "dev": true,
1040 | "requires": {
1041 | "balanced-match": "^1.0.0",
1042 | "concat-map": "0.0.1"
1043 | }
1044 | },
1045 | "braces": {
1046 | "version": "3.0.2",
1047 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
1048 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
1049 | "dev": true,
1050 | "requires": {
1051 | "fill-range": "^7.0.1"
1052 | }
1053 | },
1054 | "browser-stdout": {
1055 | "version": "1.3.1",
1056 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
1057 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
1058 | "dev": true
1059 | },
1060 | "camelcase": {
1061 | "version": "6.3.0",
1062 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
1063 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
1064 | "dev": true
1065 | },
1066 | "chalk": {
1067 | "version": "4.1.2",
1068 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1069 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1070 | "dev": true,
1071 | "requires": {
1072 | "ansi-styles": "^4.1.0",
1073 | "supports-color": "^7.1.0"
1074 | },
1075 | "dependencies": {
1076 | "supports-color": {
1077 | "version": "7.2.0",
1078 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1079 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1080 | "dev": true,
1081 | "requires": {
1082 | "has-flag": "^4.0.0"
1083 | }
1084 | }
1085 | }
1086 | },
1087 | "chokidar": {
1088 | "version": "3.5.3",
1089 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
1090 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
1091 | "dev": true,
1092 | "requires": {
1093 | "anymatch": "~3.1.2",
1094 | "braces": "~3.0.2",
1095 | "fsevents": "~2.3.2",
1096 | "glob-parent": "~5.1.2",
1097 | "is-binary-path": "~2.1.0",
1098 | "is-glob": "~4.0.1",
1099 | "normalize-path": "~3.0.0",
1100 | "readdirp": "~3.6.0"
1101 | }
1102 | },
1103 | "cliui": {
1104 | "version": "7.0.4",
1105 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
1106 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
1107 | "dev": true,
1108 | "requires": {
1109 | "string-width": "^4.2.0",
1110 | "strip-ansi": "^6.0.0",
1111 | "wrap-ansi": "^7.0.0"
1112 | }
1113 | },
1114 | "color-convert": {
1115 | "version": "2.0.1",
1116 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1117 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1118 | "dev": true,
1119 | "requires": {
1120 | "color-name": "~1.1.4"
1121 | }
1122 | },
1123 | "color-name": {
1124 | "version": "1.1.4",
1125 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1126 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1127 | "dev": true
1128 | },
1129 | "concat-map": {
1130 | "version": "0.0.1",
1131 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1132 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
1133 | "dev": true
1134 | },
1135 | "debug": {
1136 | "version": "4.3.4",
1137 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1138 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1139 | "dev": true,
1140 | "requires": {
1141 | "ms": "2.1.2"
1142 | },
1143 | "dependencies": {
1144 | "ms": {
1145 | "version": "2.1.2",
1146 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1147 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
1148 | "dev": true
1149 | }
1150 | }
1151 | },
1152 | "decamelize": {
1153 | "version": "4.0.0",
1154 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
1155 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
1156 | "dev": true
1157 | },
1158 | "diff": {
1159 | "version": "5.0.0",
1160 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
1161 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
1162 | "dev": true
1163 | },
1164 | "emoji-regex": {
1165 | "version": "8.0.0",
1166 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1167 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1168 | "dev": true
1169 | },
1170 | "escalade": {
1171 | "version": "3.1.1",
1172 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
1173 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
1174 | "dev": true
1175 | },
1176 | "escape-string-regexp": {
1177 | "version": "4.0.0",
1178 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1179 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
1180 | "dev": true
1181 | },
1182 | "fill-range": {
1183 | "version": "7.0.1",
1184 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
1185 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
1186 | "dev": true,
1187 | "requires": {
1188 | "to-regex-range": "^5.0.1"
1189 | }
1190 | },
1191 | "find-up": {
1192 | "version": "5.0.0",
1193 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
1194 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
1195 | "dev": true,
1196 | "requires": {
1197 | "locate-path": "^6.0.0",
1198 | "path-exists": "^4.0.0"
1199 | }
1200 | },
1201 | "flat": {
1202 | "version": "5.0.2",
1203 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
1204 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
1205 | "dev": true
1206 | },
1207 | "fs.realpath": {
1208 | "version": "1.0.0",
1209 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1210 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
1211 | "dev": true
1212 | },
1213 | "fsevents": {
1214 | "version": "2.3.2",
1215 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
1216 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
1217 | "dev": true,
1218 | "optional": true
1219 | },
1220 | "get-caller-file": {
1221 | "version": "2.0.5",
1222 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
1223 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
1224 | "dev": true
1225 | },
1226 | "glob": {
1227 | "version": "7.2.0",
1228 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
1229 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
1230 | "dev": true,
1231 | "requires": {
1232 | "fs.realpath": "^1.0.0",
1233 | "inflight": "^1.0.4",
1234 | "inherits": "2",
1235 | "minimatch": "^3.0.4",
1236 | "once": "^1.3.0",
1237 | "path-is-absolute": "^1.0.0"
1238 | }
1239 | },
1240 | "glob-parent": {
1241 | "version": "5.1.2",
1242 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
1243 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
1244 | "dev": true,
1245 | "requires": {
1246 | "is-glob": "^4.0.1"
1247 | }
1248 | },
1249 | "has-flag": {
1250 | "version": "4.0.0",
1251 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1252 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1253 | "dev": true
1254 | },
1255 | "he": {
1256 | "version": "1.2.0",
1257 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
1258 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
1259 | "dev": true
1260 | },
1261 | "inflight": {
1262 | "version": "1.0.6",
1263 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1264 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
1265 | "dev": true,
1266 | "requires": {
1267 | "once": "^1.3.0",
1268 | "wrappy": "1"
1269 | }
1270 | },
1271 | "inherits": {
1272 | "version": "2.0.4",
1273 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1274 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1275 | "dev": true
1276 | },
1277 | "is-binary-path": {
1278 | "version": "2.1.0",
1279 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
1280 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
1281 | "dev": true,
1282 | "requires": {
1283 | "binary-extensions": "^2.0.0"
1284 | }
1285 | },
1286 | "is-extglob": {
1287 | "version": "2.1.1",
1288 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1289 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
1290 | "dev": true
1291 | },
1292 | "is-fullwidth-code-point": {
1293 | "version": "3.0.0",
1294 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
1295 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
1296 | "dev": true
1297 | },
1298 | "is-glob": {
1299 | "version": "4.0.3",
1300 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1301 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1302 | "dev": true,
1303 | "requires": {
1304 | "is-extglob": "^2.1.1"
1305 | }
1306 | },
1307 | "is-number": {
1308 | "version": "7.0.0",
1309 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1310 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1311 | "dev": true
1312 | },
1313 | "is-plain-obj": {
1314 | "version": "2.1.0",
1315 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
1316 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
1317 | "dev": true
1318 | },
1319 | "is-unicode-supported": {
1320 | "version": "0.1.0",
1321 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
1322 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
1323 | "dev": true
1324 | },
1325 | "js-yaml": {
1326 | "version": "4.1.0",
1327 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1328 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1329 | "dev": true,
1330 | "requires": {
1331 | "argparse": "^2.0.1"
1332 | }
1333 | },
1334 | "locate-path": {
1335 | "version": "6.0.0",
1336 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
1337 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
1338 | "dev": true,
1339 | "requires": {
1340 | "p-locate": "^5.0.0"
1341 | }
1342 | },
1343 | "log-symbols": {
1344 | "version": "4.1.0",
1345 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
1346 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
1347 | "dev": true,
1348 | "requires": {
1349 | "chalk": "^4.1.0",
1350 | "is-unicode-supported": "^0.1.0"
1351 | }
1352 | },
1353 | "minimatch": {
1354 | "version": "3.1.2",
1355 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1356 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1357 | "dev": true,
1358 | "requires": {
1359 | "brace-expansion": "^1.1.7"
1360 | }
1361 | },
1362 | "mocha": {
1363 | "version": "10.2.0",
1364 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.2.0.tgz",
1365 | "integrity": "sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg==",
1366 | "dev": true,
1367 | "requires": {
1368 | "ansi-colors": "4.1.1",
1369 | "browser-stdout": "1.3.1",
1370 | "chokidar": "3.5.3",
1371 | "debug": "4.3.4",
1372 | "diff": "5.0.0",
1373 | "escape-string-regexp": "4.0.0",
1374 | "find-up": "5.0.0",
1375 | "glob": "7.2.0",
1376 | "he": "1.2.0",
1377 | "js-yaml": "4.1.0",
1378 | "log-symbols": "4.1.0",
1379 | "minimatch": "5.0.1",
1380 | "ms": "2.1.3",
1381 | "nanoid": "3.3.3",
1382 | "serialize-javascript": "6.0.0",
1383 | "strip-json-comments": "3.1.1",
1384 | "supports-color": "8.1.1",
1385 | "workerpool": "6.2.1",
1386 | "yargs": "16.2.0",
1387 | "yargs-parser": "20.2.4",
1388 | "yargs-unparser": "2.0.0"
1389 | },
1390 | "dependencies": {
1391 | "brace-expansion": {
1392 | "version": "2.0.1",
1393 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
1394 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
1395 | "dev": true,
1396 | "requires": {
1397 | "balanced-match": "^1.0.0"
1398 | }
1399 | },
1400 | "minimatch": {
1401 | "version": "5.0.1",
1402 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
1403 | "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
1404 | "dev": true,
1405 | "requires": {
1406 | "brace-expansion": "^2.0.1"
1407 | }
1408 | }
1409 | }
1410 | },
1411 | "ms": {
1412 | "version": "2.1.3",
1413 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1414 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1415 | "dev": true
1416 | },
1417 | "nanoid": {
1418 | "version": "3.3.3",
1419 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
1420 | "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
1421 | "dev": true
1422 | },
1423 | "normalize-path": {
1424 | "version": "3.0.0",
1425 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
1426 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
1427 | "dev": true
1428 | },
1429 | "once": {
1430 | "version": "1.4.0",
1431 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1432 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
1433 | "dev": true,
1434 | "requires": {
1435 | "wrappy": "1"
1436 | }
1437 | },
1438 | "p-limit": {
1439 | "version": "3.1.0",
1440 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
1441 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
1442 | "dev": true,
1443 | "requires": {
1444 | "yocto-queue": "^0.1.0"
1445 | }
1446 | },
1447 | "p-locate": {
1448 | "version": "5.0.0",
1449 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
1450 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
1451 | "dev": true,
1452 | "requires": {
1453 | "p-limit": "^3.0.2"
1454 | }
1455 | },
1456 | "path-exists": {
1457 | "version": "4.0.0",
1458 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
1459 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
1460 | "dev": true
1461 | },
1462 | "path-is-absolute": {
1463 | "version": "1.0.1",
1464 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1465 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
1466 | "dev": true
1467 | },
1468 | "picomatch": {
1469 | "version": "2.3.1",
1470 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1471 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1472 | "dev": true
1473 | },
1474 | "randombytes": {
1475 | "version": "2.1.0",
1476 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
1477 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
1478 | "dev": true,
1479 | "requires": {
1480 | "safe-buffer": "^5.1.0"
1481 | }
1482 | },
1483 | "readdirp": {
1484 | "version": "3.6.0",
1485 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1486 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1487 | "dev": true,
1488 | "requires": {
1489 | "picomatch": "^2.2.1"
1490 | }
1491 | },
1492 | "require-directory": {
1493 | "version": "2.1.1",
1494 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
1495 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=",
1496 | "dev": true
1497 | },
1498 | "safe-buffer": {
1499 | "version": "5.2.1",
1500 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1501 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1502 | "dev": true
1503 | },
1504 | "serialize-javascript": {
1505 | "version": "6.0.0",
1506 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
1507 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
1508 | "dev": true,
1509 | "requires": {
1510 | "randombytes": "^2.1.0"
1511 | }
1512 | },
1513 | "should": {
1514 | "version": "13.2.3",
1515 | "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz",
1516 | "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==",
1517 | "dev": true,
1518 | "requires": {
1519 | "should-equal": "^2.0.0",
1520 | "should-format": "^3.0.3",
1521 | "should-type": "^1.4.0",
1522 | "should-type-adaptors": "^1.0.1",
1523 | "should-util": "^1.0.0"
1524 | }
1525 | },
1526 | "should-equal": {
1527 | "version": "2.0.0",
1528 | "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz",
1529 | "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==",
1530 | "dev": true,
1531 | "requires": {
1532 | "should-type": "^1.4.0"
1533 | }
1534 | },
1535 | "should-format": {
1536 | "version": "3.0.3",
1537 | "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz",
1538 | "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=",
1539 | "dev": true,
1540 | "requires": {
1541 | "should-type": "^1.3.0",
1542 | "should-type-adaptors": "^1.0.1"
1543 | }
1544 | },
1545 | "should-type": {
1546 | "version": "1.4.0",
1547 | "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz",
1548 | "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=",
1549 | "dev": true
1550 | },
1551 | "should-type-adaptors": {
1552 | "version": "1.1.0",
1553 | "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz",
1554 | "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==",
1555 | "dev": true,
1556 | "requires": {
1557 | "should-type": "^1.3.0",
1558 | "should-util": "^1.0.0"
1559 | }
1560 | },
1561 | "should-util": {
1562 | "version": "1.0.1",
1563 | "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz",
1564 | "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==",
1565 | "dev": true
1566 | },
1567 | "string-width": {
1568 | "version": "4.2.3",
1569 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1570 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1571 | "dev": true,
1572 | "requires": {
1573 | "emoji-regex": "^8.0.0",
1574 | "is-fullwidth-code-point": "^3.0.0",
1575 | "strip-ansi": "^6.0.1"
1576 | }
1577 | },
1578 | "strip-ansi": {
1579 | "version": "6.0.1",
1580 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1581 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1582 | "dev": true,
1583 | "requires": {
1584 | "ansi-regex": "^5.0.1"
1585 | }
1586 | },
1587 | "strip-json-comments": {
1588 | "version": "3.1.1",
1589 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
1590 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
1591 | "dev": true
1592 | },
1593 | "supports-color": {
1594 | "version": "8.1.1",
1595 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
1596 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
1597 | "dev": true,
1598 | "requires": {
1599 | "has-flag": "^4.0.0"
1600 | }
1601 | },
1602 | "to-regex-range": {
1603 | "version": "5.0.1",
1604 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1605 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1606 | "dev": true,
1607 | "requires": {
1608 | "is-number": "^7.0.0"
1609 | }
1610 | },
1611 | "typescript": {
1612 | "version": "4.5.5",
1613 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz",
1614 | "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==",
1615 | "dev": true
1616 | },
1617 | "workerpool": {
1618 | "version": "6.2.1",
1619 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
1620 | "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
1621 | "dev": true
1622 | },
1623 | "wrap-ansi": {
1624 | "version": "7.0.0",
1625 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1626 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1627 | "dev": true,
1628 | "requires": {
1629 | "ansi-styles": "^4.0.0",
1630 | "string-width": "^4.1.0",
1631 | "strip-ansi": "^6.0.0"
1632 | }
1633 | },
1634 | "wrappy": {
1635 | "version": "1.0.2",
1636 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1637 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
1638 | "dev": true
1639 | },
1640 | "y18n": {
1641 | "version": "5.0.8",
1642 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
1643 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
1644 | "dev": true
1645 | },
1646 | "yargs": {
1647 | "version": "16.2.0",
1648 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
1649 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
1650 | "dev": true,
1651 | "requires": {
1652 | "cliui": "^7.0.2",
1653 | "escalade": "^3.1.1",
1654 | "get-caller-file": "^2.0.5",
1655 | "require-directory": "^2.1.1",
1656 | "string-width": "^4.2.0",
1657 | "y18n": "^5.0.5",
1658 | "yargs-parser": "^20.2.2"
1659 | }
1660 | },
1661 | "yargs-parser": {
1662 | "version": "20.2.4",
1663 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
1664 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
1665 | "dev": true
1666 | },
1667 | "yargs-unparser": {
1668 | "version": "2.0.0",
1669 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
1670 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
1671 | "dev": true,
1672 | "requires": {
1673 | "camelcase": "^6.0.0",
1674 | "decamelize": "^4.0.0",
1675 | "flat": "^5.0.2",
1676 | "is-plain-obj": "^2.1.0"
1677 | }
1678 | },
1679 | "yocto-queue": {
1680 | "version": "0.1.0",
1681 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
1682 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
1683 | "dev": true
1684 | }
1685 | }
1686 | }
1687 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "search-query-parser",
3 | "version": "1.6.0",
4 | "description": "Parser for advanced search query syntax",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "mocha -R spec"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git://github.com/nepsilon/search-query-parser"
12 | },
13 | "keywords": [
14 | "search syntax parser",
15 | "query syntax parser",
16 | "query",
17 | "parser",
18 | "search query",
19 | "search"
20 | ],
21 | "license": "MIT",
22 | "bugs": {
23 | "url": "https://github.com/nepsilon/search-query-parser/issues"
24 | },
25 | "homepage": "https://github.com/nepsilon/search-query-parser",
26 | "devDependencies": {
27 | "mocha": "^10.2.0",
28 | "should": "^13.2.3",
29 | "typescript": "^4.2.2"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Mocha
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/test/mocha.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | body {
4 | margin:0;
5 | }
6 |
7 | #mocha {
8 | font: 20px/1.5 "Helvetica Neue", Helvetica, Arial, sans-serif;
9 | margin: 60px 50px;
10 | }
11 |
12 | #mocha ul,
13 | #mocha li {
14 | margin: 0;
15 | padding: 0;
16 | }
17 |
18 | #mocha ul {
19 | list-style: none;
20 | }
21 |
22 | #mocha h1,
23 | #mocha h2 {
24 | margin: 0;
25 | }
26 |
27 | #mocha h1 {
28 | margin-top: 15px;
29 | font-size: 1em;
30 | font-weight: 200;
31 | }
32 |
33 | #mocha h1 a {
34 | text-decoration: none;
35 | color: inherit;
36 | }
37 |
38 | #mocha h1 a:hover {
39 | text-decoration: underline;
40 | }
41 |
42 | #mocha .suite .suite h1 {
43 | margin-top: 0;
44 | font-size: .8em;
45 | }
46 |
47 | #mocha .hidden {
48 | display: none;
49 | }
50 |
51 | #mocha h2 {
52 | font-size: 12px;
53 | font-weight: normal;
54 | cursor: pointer;
55 | }
56 |
57 | #mocha .suite {
58 | margin-left: 15px;
59 | }
60 |
61 | #mocha .test {
62 | margin-left: 15px;
63 | overflow: hidden;
64 | }
65 |
66 | #mocha .test.pending:hover h2::after {
67 | content: '(pending)';
68 | font-family: arial, sans-serif;
69 | }
70 |
71 | #mocha .test.pass.medium .duration {
72 | background: #c09853;
73 | }
74 |
75 | #mocha .test.pass.slow .duration {
76 | background: #b94a48;
77 | }
78 |
79 | #mocha .test.pass::before {
80 | content: '✓';
81 | font-size: 12px;
82 | display: block;
83 | float: left;
84 | margin-right: 5px;
85 | color: #00d6b2;
86 | }
87 |
88 | #mocha .test.pass .duration {
89 | font-size: 9px;
90 | margin-left: 5px;
91 | padding: 2px 5px;
92 | color: #fff;
93 | -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
94 | -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
95 | box-shadow: inset 0 1px 1px rgba(0,0,0,.2);
96 | -webkit-border-radius: 5px;
97 | -moz-border-radius: 5px;
98 | -ms-border-radius: 5px;
99 | -o-border-radius: 5px;
100 | border-radius: 5px;
101 | }
102 |
103 | #mocha .test.pass.fast .duration {
104 | display: none;
105 | }
106 |
107 | #mocha .test.pending {
108 | color: #0b97c4;
109 | }
110 |
111 | #mocha .test.pending::before {
112 | content: '◦';
113 | color: #0b97c4;
114 | }
115 |
116 | #mocha .test.fail {
117 | color: #c00;
118 | }
119 |
120 | #mocha .test.fail pre {
121 | color: black;
122 | }
123 |
124 | #mocha .test.fail::before {
125 | content: '✖';
126 | font-size: 12px;
127 | display: block;
128 | float: left;
129 | margin-right: 5px;
130 | color: #c00;
131 | }
132 |
133 | #mocha .test pre.error {
134 | color: #c00;
135 | max-height: 300px;
136 | overflow: auto;
137 | }
138 |
139 | /**
140 | * (1): approximate for browsers not supporting calc
141 | * (2): 42 = 2*15 + 2*10 + 2*1 (padding + margin + border)
142 | * ^^ seriously
143 | */
144 | #mocha .test pre {
145 | display: block;
146 | float: left;
147 | clear: left;
148 | font: 12px/1.5 monaco, monospace;
149 | margin: 5px;
150 | padding: 15px;
151 | border: 1px solid #eee;
152 | max-width: 85%; /*(1)*/
153 | max-width: calc(100% - 42px); /*(2)*/
154 | word-wrap: break-word;
155 | border-bottom-color: #ddd;
156 | -webkit-border-radius: 3px;
157 | -webkit-box-shadow: 0 1px 3px #eee;
158 | -moz-border-radius: 3px;
159 | -moz-box-shadow: 0 1px 3px #eee;
160 | border-radius: 3px;
161 | }
162 |
163 | #mocha .test h2 {
164 | position: relative;
165 | }
166 |
167 | #mocha .test a.replay {
168 | position: absolute;
169 | top: 3px;
170 | right: 0;
171 | text-decoration: none;
172 | vertical-align: middle;
173 | display: block;
174 | width: 15px;
175 | height: 15px;
176 | line-height: 15px;
177 | text-align: center;
178 | background: #eee;
179 | font-size: 15px;
180 | -moz-border-radius: 15px;
181 | border-radius: 15px;
182 | -webkit-transition: opacity 200ms;
183 | -moz-transition: opacity 200ms;
184 | transition: opacity 200ms;
185 | opacity: 0.3;
186 | color: #888;
187 | }
188 |
189 | #mocha .test:hover a.replay {
190 | opacity: 1;
191 | }
192 |
193 | #mocha-report.pass .test.fail {
194 | display: none;
195 | }
196 |
197 | #mocha-report.fail .test.pass {
198 | display: none;
199 | }
200 |
201 | #mocha-report.pending .test.pass,
202 | #mocha-report.pending .test.fail {
203 | display: none;
204 | }
205 | #mocha-report.pending .test.pass.pending {
206 | display: block;
207 | }
208 |
209 | #mocha-error {
210 | color: #c00;
211 | font-size: 1.5em;
212 | font-weight: 100;
213 | letter-spacing: 1px;
214 | }
215 |
216 | #mocha-stats {
217 | position: fixed;
218 | top: 15px;
219 | right: 10px;
220 | font-size: 12px;
221 | margin: 0;
222 | color: #888;
223 | z-index: 1;
224 | }
225 |
226 | #mocha-stats .progress {
227 | float: right;
228 | padding-top: 0;
229 | }
230 |
231 | #mocha-stats em {
232 | color: black;
233 | }
234 |
235 | #mocha-stats a {
236 | text-decoration: none;
237 | color: inherit;
238 | }
239 |
240 | #mocha-stats a:hover {
241 | border-bottom: 1px solid #eee;
242 | }
243 |
244 | #mocha-stats li {
245 | display: inline-block;
246 | margin: 0 5px;
247 | list-style: none;
248 | padding-top: 11px;
249 | }
250 |
251 | #mocha-stats canvas {
252 | width: 40px;
253 | height: 40px;
254 | }
255 |
256 | #mocha code .comment { color: #ddd; }
257 | #mocha code .init { color: #2f6fad; }
258 | #mocha code .string { color: #5890ad; }
259 | #mocha code .keyword { color: #8a6343; }
260 | #mocha code .number { color: #2f6fad; }
261 |
262 | @media screen and (max-device-width: 480px) {
263 | #mocha {
264 | margin: 60px 0px;
265 | }
266 |
267 | #mocha #stats {
268 | position: absolute;
269 | }
270 | }
271 |
--------------------------------------------------------------------------------
/test/test.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert')
2 | , should = require('should')
3 | , searchquery = require('../');
4 |
5 |
6 | describe('Search query syntax parser', function () {
7 |
8 |
9 | it('should return a simple string when zero keyword present', function () {
10 | var searchQuery = "fancy pyjama wear";
11 | var parsedSearchQuery = searchquery.parse(searchQuery);
12 |
13 | parsedSearchQuery.should.be.a.string;
14 | parsedSearchQuery.should.equal(searchQuery);
15 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery));
16 | parsedAfterStringifySearchQuery.should.be.equal(parsedSearchQuery);
17 | });
18 |
19 | it('should return a tokenized string when option is set', function () {
20 | var searchQuery = "fancy pyjama wear";
21 | var options = { tokenize: true };
22 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
23 |
24 | parsedSearchQuery.should.be.an.Object;
25 | parsedSearchQuery.should.have.property('text', ['fancy', 'pyjama', 'wear']);
26 |
27 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
28 | parsedAfterStringifySearchQuery.offsets = undefined;
29 | parsedSearchQuery.offsets = undefined;
30 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
31 | });
32 |
33 | it('should return a tokenized string when option is set, respecting double-quotes and escapes', function () {
34 | var searchQuery = 'fancy "py\\"j\\"am\'a w\'ear"';
35 | var options = { tokenize: true };
36 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
37 |
38 | parsedSearchQuery.should.be.an.Object;
39 | parsedSearchQuery.should.have.property('text', ['fancy', 'py"j"am\'a w\'ear']);
40 |
41 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
42 | parsedAfterStringifySearchQuery.offsets = undefined;
43 | parsedSearchQuery.offsets = undefined;
44 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
45 | });
46 |
47 | it('should return a tokenized string when option is set, respecting single-quotes and escapes', function () {
48 | var searchQuery = "fancy 'py\\'j\\'am\"a w\"ear'";
49 | var options = { tokenize: true };
50 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
51 |
52 | parsedSearchQuery.should.be.an.Object;
53 | parsedSearchQuery.should.have.property('text', ['fancy', "py'j'am\"a w\"ear"]);
54 |
55 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
56 | parsedAfterStringifySearchQuery.offsets = undefined;
57 | parsedSearchQuery.offsets = undefined;
58 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
59 | });
60 |
61 | it('should return a tokenized string with negation of unquoted terms', function () {
62 | var searchQuery = "fancy -pyjama -wear";
63 | var options = { tokenize: true };
64 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
65 |
66 | parsedSearchQuery.should.be.an.Object;
67 | parsedSearchQuery.should.have.property('text', ['fancy']);
68 | parsedSearchQuery.should.have.property('exclude', {text: ['pyjama', 'wear']});
69 |
70 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
71 | parsedAfterStringifySearchQuery.offsets = undefined;
72 | parsedSearchQuery.offsets = undefined;
73 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
74 | });
75 |
76 | it('should return a tokenized string with negation of single-quoted terms', function () {
77 | var searchQuery = "fancy -'pyjama -wear'";
78 | var options = { tokenize: true };
79 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
80 |
81 | parsedSearchQuery.should.be.an.Object;
82 | parsedSearchQuery.should.have.property('text', ['fancy']);
83 | parsedSearchQuery.should.have.property('exclude', {text: 'pyjama -wear'});
84 |
85 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
86 | parsedAfterStringifySearchQuery.offsets = undefined;
87 | parsedSearchQuery.offsets = undefined;
88 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
89 | });
90 |
91 | it('should return a tokenized string with negation of double-quoted terms', function () {
92 | var searchQuery = 'fancy -"pyjama -wear"';
93 | var options = { tokenize: true };
94 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
95 |
96 | parsedSearchQuery.should.be.an.Object;
97 | parsedSearchQuery.should.have.property('text', ['fancy']);
98 | parsedSearchQuery.should.have.property('exclude', {text: 'pyjama -wear'});
99 |
100 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
101 | parsedAfterStringifySearchQuery.offsets = undefined;
102 | parsedSearchQuery.offsets = undefined;
103 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
104 | });
105 |
106 | it('should parse a single keyword with no text', function () {
107 | var searchQuery = 'from:jul@foo.com';
108 | var options = {keywords: ['from']};
109 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
110 |
111 | parsedSearchQuery.should.be.an.Object;
112 | parsedSearchQuery.should.have.property('from', 'jul@foo.com');
113 | parsedSearchQuery.should.not.have.property('text');
114 | parsedSearchQuery.should.have.property('offsets', [{
115 | keyword: 'from',
116 | value: 'jul@foo.com',
117 | offsetStart: 0,
118 | offsetEnd: 16
119 | }]);
120 |
121 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
122 | parsedAfterStringifySearchQuery.offsets = undefined;
123 | parsedSearchQuery.offsets = undefined;
124 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
125 | });
126 |
127 |
128 | it('should parse a single keyword with free text after it', function () {
129 | var searchQuery = 'from:jul@foo.com hey buddy!';
130 | var options = {keywords: ['from']};
131 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
132 |
133 | parsedSearchQuery.should.be.an.Object;
134 | parsedSearchQuery.should.have.property('from', 'jul@foo.com');
135 | parsedSearchQuery.should.have.property('text', 'hey buddy!');
136 | parsedSearchQuery.should.have.property('offsets', [{
137 | keyword: 'from',
138 | value: 'jul@foo.com',
139 | offsetStart: 0,
140 | offsetEnd: 16
141 | }, {
142 | text: 'hey',
143 | offsetStart: 17,
144 | offsetEnd: 20
145 | }, {
146 | text: 'buddy!',
147 | offsetStart: 21,
148 | offsetEnd: 27
149 | }]);
150 |
151 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
152 | parsedAfterStringifySearchQuery.offsets = undefined;
153 | parsedSearchQuery.offsets = undefined;
154 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
155 | });
156 |
157 |
158 | it('should ignore keywords that are not specified', function() {
159 | var searchQuery = 'test another other:jul@foo.com';
160 | var options = {
161 | keywords: ['from']
162 | };
163 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
164 |
165 | parsedSearchQuery.should.be.an.Object;
166 | parsedSearchQuery.should.have.not.have.property('other');
167 | parsedSearchQuery.should.have.property('text', 'test another other:jul@foo.com');
168 | parsedSearchQuery.should.have.property('offsets', [{
169 | text: 'test',
170 | offsetStart: 0,
171 | offsetEnd: 4
172 | }, {
173 | text: 'another',
174 | offsetStart: 5,
175 | offsetEnd: 12
176 | }, {
177 | text: 'other:jul@foo.com',
178 | offsetStart: 13,
179 | offsetEnd: 30
180 | }]);
181 |
182 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
183 | parsedAfterStringifySearchQuery.offsets = undefined;
184 | parsedSearchQuery.offsets = undefined;
185 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
186 | });
187 |
188 |
189 | it('should parse a single keyword with free text before it', function() {
190 | var searchQuery = 'hey you! from:jul@foo.com';
191 | var options = {keywords: ['from']};
192 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
193 |
194 | parsedSearchQuery.should.be.an.Object;
195 | parsedSearchQuery.should.have.property('from', 'jul@foo.com');
196 | parsedSearchQuery.should.have.property('text', 'hey you!');
197 | parsedSearchQuery.should.have.property('offsets', [{
198 | text: 'hey',
199 | offsetStart: 0,
200 | offsetEnd: 3
201 | }, {
202 | text: 'you!',
203 | offsetStart: 4,
204 | offsetEnd: 8
205 | }, {
206 | keyword: 'from',
207 | value: 'jul@foo.com',
208 | offsetStart: 9,
209 | offsetEnd: 25
210 | }]);
211 |
212 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
213 | parsedAfterStringifySearchQuery.offsets = undefined;
214 | parsedSearchQuery.offsets = undefined;
215 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
216 | });
217 |
218 |
219 | it('should parse a single keyword with free text around it', function () {
220 | var searchQuery = 'hey you! from:jul@foo.com pouet';
221 | var options = {keywords: ['from']};
222 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
223 |
224 | parsedSearchQuery.should.be.an.Object;
225 | parsedSearchQuery.should.have.property('from', 'jul@foo.com');
226 | parsedSearchQuery.should.have.property('text', 'hey you! pouet');
227 | parsedSearchQuery.should.have.property('offsets', [{
228 | text: 'hey',
229 | offsetStart: 0,
230 | offsetEnd: 3
231 | }, {
232 | text: 'you!',
233 | offsetStart: 4,
234 | offsetEnd: 8
235 | }, {
236 | keyword: 'from',
237 | value: 'jul@foo.com',
238 | offsetStart: 9,
239 | offsetEnd: 25
240 | }, {
241 | text: 'pouet',
242 | offsetStart: 26,
243 | offsetEnd: 31
244 | }]);
245 |
246 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
247 | parsedAfterStringifySearchQuery.offsets = undefined;
248 | parsedSearchQuery.offsets = undefined;
249 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
250 | });
251 |
252 |
253 | it('should strip any white space at any position', function () {
254 | // We have tabs and regular spaces in the string below
255 | var searchQuery = ' hey you! from:jul@foo.com pouet ';
256 | var options = {keywords: ['from']};
257 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
258 |
259 | parsedSearchQuery.should.be.an.Object;
260 | parsedSearchQuery.should.have.property('from', 'jul@foo.com');
261 | parsedSearchQuery.should.have.property('text', 'hey you! pouet');
262 | parsedSearchQuery.should.have.property('offsets', [{
263 | text: 'hey',
264 | offsetStart: 3,
265 | offsetEnd: 6
266 | }, {
267 | text: 'you!',
268 | offsetStart: 11,
269 | offsetEnd: 15
270 | }, {
271 | keyword: 'from',
272 | value: 'jul@foo.com',
273 | offsetStart: 16,
274 | offsetEnd: 32
275 | }, {
276 | text: 'pouet',
277 | offsetStart: 35,
278 | offsetEnd: 40
279 | }]);
280 |
281 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
282 | parsedAfterStringifySearchQuery.offsets = undefined;
283 | parsedSearchQuery.offsets = undefined;
284 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
285 | });
286 |
287 |
288 | it('should parse 2 different keywords with free text', function () {
289 | var searchQuery = 'hey, from:jul@foo.com to:bar@hey.ya so what\'s up gents';
290 | var options = {keywords: ['from', 'to']};
291 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
292 |
293 | parsedSearchQuery.should.be.an.Object;
294 | parsedSearchQuery.should.have.property('from', 'jul@foo.com');
295 | parsedSearchQuery.should.have.property('to', 'bar@hey.ya');
296 | parsedSearchQuery.should.have.property('text', 'hey, so what\'s up gents');
297 | parsedSearchQuery.should.have.property('offsets', [{
298 | text: 'hey,',
299 | offsetStart: 0,
300 | offsetEnd: 4
301 | }, {
302 | keyword: 'from',
303 | value: 'jul@foo.com',
304 | offsetStart: 5,
305 | offsetEnd: 21
306 | }, {
307 | keyword: 'to',
308 | value: 'bar@hey.ya',
309 | offsetStart: 22,
310 | offsetEnd: 35
311 | }, {
312 | text: 'so',
313 | offsetStart: 36,
314 | offsetEnd: 38
315 | }, {
316 | text: 'what\'s',
317 | offsetStart: 39,
318 | offsetEnd: 45
319 | }, {
320 | text: 'up',
321 | offsetStart: 46,
322 | offsetEnd: 48
323 | }, {
324 | text: 'gents',
325 | offsetStart: 49,
326 | offsetEnd: 54
327 | }]);
328 |
329 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
330 | parsedAfterStringifySearchQuery.offsets = undefined;
331 | parsedSearchQuery.offsets = undefined;
332 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
333 | });
334 |
335 |
336 | it('should concatenate 2 identical keywords value and keep free text', function () {
337 | var searchQuery = 'from:jul@foo.com from:bar@hey.ya vaccationessss';
338 | var options = {keywords: ['from']};
339 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
340 |
341 | parsedSearchQuery.should.be.an.Object;
342 | parsedSearchQuery.should.have.property('from');
343 | parsedSearchQuery.should.have.property('text', 'vaccationessss');
344 | parsedSearchQuery.from.should.be.an.Array;
345 | parsedSearchQuery.from.length.should.equal(2);
346 | parsedSearchQuery.from.should.containEql('jul@foo.com');
347 | parsedSearchQuery.from.should.containEql('bar@hey.ya');
348 | parsedSearchQuery.should.have.property('offsets', [{
349 | keyword: 'from',
350 | value: 'jul@foo.com',
351 | offsetStart: 0,
352 | offsetEnd: 16
353 | }, {
354 | keyword: 'from',
355 | value: 'bar@hey.ya',
356 | offsetStart: 17,
357 | offsetEnd: 32
358 | }, {
359 | text: 'vaccationessss',
360 | offsetStart: 33,
361 | offsetEnd: 47
362 | }]);
363 |
364 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
365 | parsedAfterStringifySearchQuery.offsets = undefined;
366 | parsedSearchQuery.offsets = undefined;
367 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
368 | });
369 |
370 |
371 | it('should concatenate a keyword multiple values', function () {
372 | var searchQuery = 'from:jul@foo.com,bar@hey.ya';
373 | var options = {keywords: ['from']};
374 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
375 |
376 | parsedSearchQuery.should.be.an.Object;
377 | parsedSearchQuery.should.have.property('from');
378 | parsedSearchQuery.from.should.be.an.Array;
379 | parsedSearchQuery.from.length.should.equal(2);
380 | parsedSearchQuery.from.should.containEql('jul@foo.com');
381 | parsedSearchQuery.from.should.containEql('bar@hey.ya');
382 | parsedSearchQuery.should.have.property('offsets', [{
383 | keyword: 'from',
384 | value: 'jul@foo.com,bar@hey.ya',
385 | offsetStart: 0,
386 | offsetEnd: 27
387 | }]);
388 |
389 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
390 | parsedAfterStringifySearchQuery.offsets = undefined;
391 | parsedSearchQuery.offsets = undefined;
392 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
393 | });
394 |
395 |
396 | it('should concatenate values from 2 identical keyword multiple values and keep free text', function () {
397 | var searchQuery = 'from:jul@foo.com,bar@hey.ya from:a@b.c,d@e.f ouch!#';
398 | var options = {keywords: ['from']};
399 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
400 |
401 | parsedSearchQuery.should.be.an.Object;
402 | parsedSearchQuery.should.have.property('text', 'ouch!#');
403 | parsedSearchQuery.should.have.property('from');
404 | parsedSearchQuery.from.should.be.an.Array;
405 | parsedSearchQuery.from.length.should.equal(4);
406 | parsedSearchQuery.from.should.containEql('jul@foo.com');
407 | parsedSearchQuery.from.should.containEql('bar@hey.ya');
408 | parsedSearchQuery.from.should.containEql('a@b.c');
409 | parsedSearchQuery.from.should.containEql('d@e.f');
410 | parsedSearchQuery.should.have.property('offsets', [{
411 | keyword: 'from',
412 | value: 'jul@foo.com,bar@hey.ya',
413 | offsetStart: 0,
414 | offsetEnd: 27
415 | }, {
416 | keyword: 'from',
417 | value: 'a@b.c,d@e.f',
418 | offsetStart: 28,
419 | offsetEnd: 44
420 | }, {
421 | text: 'ouch!#',
422 | offsetStart: 45,
423 | offsetEnd: 51
424 | }]);
425 |
426 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
427 | parsedAfterStringifySearchQuery.offsets = undefined;
428 | parsedSearchQuery.offsets = undefined;
429 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
430 | });
431 |
432 | it('should always return an array if alwaysArray is set to true', function () {
433 | var searchQuery = 'from:jul@foo.com to:a@b.c -cc:you@foo.com ouch!#';
434 |
435 | var options = {keywords: ['from', 'to', 'cc'], alwaysArray: true};
436 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
437 |
438 | parsedSearchQuery.should.be.an.Object;
439 | parsedSearchQuery.should.have.property('text', 'ouch!#');
440 | parsedSearchQuery.should.have.property('from');
441 | parsedSearchQuery.should.have.property('to');
442 | parsedSearchQuery.from.should.be.an.Array;
443 | parsedSearchQuery.to.should.be.an.Array;
444 | parsedSearchQuery.exclude.cc.should.be.an.Array;
445 | parsedSearchQuery.from.length.should.equal(1);
446 | parsedSearchQuery.to.length.should.equal(1);
447 | parsedSearchQuery.exclude.cc.length.should.equal(1);
448 | parsedSearchQuery.from.should.containEql('jul@foo.com');
449 | parsedSearchQuery.to.should.containEql('a@b.c');
450 | parsedSearchQuery.exclude.cc.should.containEql('you@foo.com');
451 | parsedSearchQuery.should.have.property('offsets', [{
452 | keyword: 'from',
453 | value: 'jul@foo.com',
454 | offsetStart: 0,
455 | offsetEnd: 16
456 | }, {
457 | keyword: 'to',
458 | value: 'a@b.c',
459 | offsetStart: 17,
460 | offsetEnd: 25
461 | }, {
462 | keyword: 'cc',
463 | value: 'you@foo.com',
464 | offsetStart: 27,
465 | offsetEnd: 41
466 | }, {
467 | text: 'ouch!#',
468 | offsetStart: 42,
469 | offsetEnd: 48
470 | }]);
471 |
472 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
473 | parsedAfterStringifySearchQuery.offsets = undefined;
474 | parsedSearchQuery.offsets = undefined;
475 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
476 | });
477 |
478 | it('should parse range with only 1 end and free text', function () {
479 | var searchQuery = 'date:12/12/2012 ahaha';
480 | var options = {ranges: ['date']};
481 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
482 |
483 | parsedSearchQuery.should.be.an.Object;
484 | parsedSearchQuery.should.have.property('text', 'ahaha');
485 | parsedSearchQuery.should.have.property('date');
486 | parsedSearchQuery.date.should.be.an.Object;
487 | parsedSearchQuery.date.from.should.containEql('12/12/2012');
488 | parsedSearchQuery.should.have.property('offsets', [{
489 | keyword: 'date',
490 | value: '12/12/2012',
491 | offsetStart: 0,
492 | offsetEnd: 15
493 | }, {
494 | text: 'ahaha',
495 | offsetStart: 16,
496 | offsetEnd: 21
497 | }]);
498 |
499 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
500 | parsedAfterStringifySearchQuery.offsets = undefined;
501 | parsedSearchQuery.offsets = undefined;
502 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
503 | });
504 |
505 | it('should parse range with 2 ends and free text', function () {
506 | var searchQuery = 'date:12/12/2012-01/01/2014 ahaha';
507 | var options = {ranges: ['date']};
508 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
509 |
510 | parsedSearchQuery.should.be.an.Object;
511 | parsedSearchQuery.should.have.property('text', 'ahaha');
512 | parsedSearchQuery.should.have.property('date');
513 | parsedSearchQuery.date.should.be.an.Object;
514 | parsedSearchQuery.date.from.should.containEql('12/12/2012');
515 | parsedSearchQuery.date.to.should.containEql('01/01/2014');
516 | parsedSearchQuery.should.have.property('offsets', [{
517 | keyword: 'date',
518 | value: '12/12/2012-01/01/2014',
519 | offsetStart: 0,
520 | offsetEnd: 26
521 | }, {
522 | text: 'ahaha',
523 | offsetStart: 27,
524 | offsetEnd: 32
525 | }]);
526 |
527 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
528 | parsedAfterStringifySearchQuery.offsets = undefined;
529 | parsedSearchQuery.offsets = undefined;
530 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
531 | });
532 |
533 |
534 | it('should be able to parse unicode', function () {
535 | var searchQuery = '✓ about 这个事儿';
536 | var parsedSearchQuery = searchquery.parse(searchQuery);
537 |
538 | parsedSearchQuery.should.be.a.string;
539 | parsedSearchQuery.should.be.equal('✓ about 这个事儿');
540 |
541 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery));
542 | parsedAfterStringifySearchQuery.offsets = undefined;
543 | parsedSearchQuery.offsets = undefined;
544 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
545 | });
546 |
547 |
548 | it('should be able to parse unicode with keywords and funny spacing', function () {
549 | var searchQuery = ' ✓ about 这个事儿 from:dr@who.co.uk ';
550 | var options = {keywords: ['from']};
551 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
552 |
553 | parsedSearchQuery.should.be.an.Object;
554 | parsedSearchQuery.should.have.property('text', '✓ about 这个事儿');
555 | parsedSearchQuery.should.have.property('from', 'dr@who.co.uk');
556 |
557 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
558 | parsedAfterStringifySearchQuery.offsets = undefined;
559 | parsedSearchQuery.offsets = undefined;
560 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
561 | });
562 |
563 |
564 | it('should handle absurdly complex and long query', function () {
565 | var searchQuery = ' date:12/12/2012-01/01/2014 ahaha from:jul@foo.com,bar@hey.ya from:a@b.c,d@e.f ouch!# to:me@me.com to:toto@hey.co about that';
566 | var options = {ranges: ['date'], keywords: ['from', 'to']};
567 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
568 |
569 | parsedSearchQuery.should.be.an.Object;
570 | parsedSearchQuery.should.have.property('text', 'ahaha ouch!# about that');
571 | parsedSearchQuery.should.have.property('date');
572 | parsedSearchQuery.date.should.be.an.Object;
573 | parsedSearchQuery.date.from.should.containEql('12/12/2012');
574 | parsedSearchQuery.date.to.should.containEql('01/01/2014');
575 | parsedSearchQuery.should.have.property('from');
576 | parsedSearchQuery.from.should.be.an.Array;
577 | parsedSearchQuery.from.length.should.equal(4);
578 | parsedSearchQuery.from.should.containEql('jul@foo.com');
579 | parsedSearchQuery.from.should.containEql('bar@hey.ya');
580 | parsedSearchQuery.from.should.containEql('a@b.c');
581 | parsedSearchQuery.from.should.containEql('d@e.f');
582 | parsedSearchQuery.should.have.property('to');
583 | parsedSearchQuery.to.should.be.an.Array;
584 | parsedSearchQuery.to.length.should.equal(2);
585 | parsedSearchQuery.to.should.containEql('me@me.com');
586 | parsedSearchQuery.to.should.containEql('toto@hey.co');
587 | parsedSearchQuery.should.have.property('offsets', [{
588 | keyword: 'date',
589 | value: '12/12/2012-01/01/2014',
590 | offsetStart: 3,
591 | offsetEnd: 29
592 | }, {
593 | text: 'ahaha',
594 | offsetStart: 30,
595 | offsetEnd: 35
596 | }, {
597 | keyword: 'from',
598 | value: 'jul@foo.com,bar@hey.ya',
599 | offsetStart: 36,
600 | offsetEnd: 63
601 | }, {
602 | keyword: 'from',
603 | value: 'a@b.c,d@e.f',
604 | offsetStart: 64,
605 | offsetEnd: 80
606 | }, {
607 | text: 'ouch!#',
608 | offsetStart: 81,
609 | offsetEnd: 87
610 | }, {
611 | keyword: 'to',
612 | value: 'me@me.com',
613 | offsetStart: 90,
614 | offsetEnd: 102
615 | }, {
616 | keyword: 'to',
617 | value: 'toto@hey.co',
618 | offsetStart: 103,
619 | offsetEnd: 117
620 | }, {
621 | text: 'about',
622 | offsetStart: 118,
623 | offsetEnd: 123
624 | }, {
625 | text: 'that',
626 | offsetStart: 124,
627 | offsetEnd: 128
628 | }]);
629 |
630 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
631 | parsedAfterStringifySearchQuery.offsets = undefined;
632 | parsedSearchQuery.offsets = undefined;
633 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
634 | });
635 |
636 |
637 | it('should not split on spaces inside single and double quotes', function () {
638 | var searchQuery = 'name:"Bob Saget" description:\'Banana Sandwiche\'';
639 | var options = {keywords: ['name', 'description']};
640 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
641 |
642 | parsedSearchQuery.should.be.an.Object;
643 | parsedSearchQuery.should.have.property('name', 'Bob Saget');
644 | parsedSearchQuery.should.have.property('description', 'Banana Sandwiche');
645 | parsedSearchQuery.should.have.property('offsets', [{
646 | keyword: 'name',
647 | value: 'Bob Saget',
648 | offsetStart: 0,
649 | offsetEnd: 16
650 | }, {
651 | keyword: 'description',
652 | value: 'Banana Sandwiche',
653 | offsetStart: 17,
654 | offsetEnd: 47
655 | }]);
656 |
657 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
658 | parsedAfterStringifySearchQuery.offsets = undefined;
659 | parsedSearchQuery.offsets = undefined;
660 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
661 | });
662 |
663 |
664 | it('should correctly handle escaped single and double quotes', function () {
665 | var searchQuery = 'case1:"This \\"is\\" \'a\' test" case2:\'This "is" \\\'a\\\' test\'';
666 | var options = {keywords: ['case1', 'case2']};
667 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
668 |
669 | parsedSearchQuery.should.be.an.Object;
670 | parsedSearchQuery.should.have.property('case1', 'This "is" \'a\' test');
671 | parsedSearchQuery.should.have.property('case2', 'This "is" \'a\' test');
672 | parsedSearchQuery.should.have.property('offsets', [{
673 | keyword: 'case1',
674 | value: 'This "is" \'a\' test',
675 | offsetStart: 0,
676 | offsetEnd: 28
677 | }, {
678 | keyword: 'case2',
679 | value: 'This "is" \'a\' test',
680 | offsetStart: 29,
681 | offsetEnd: 57
682 | }]);
683 |
684 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
685 | parsedAfterStringifySearchQuery.offsets = undefined;
686 | parsedSearchQuery.offsets = undefined;
687 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
688 | });
689 |
690 |
691 | it('should parse a single keyword query in exclusion syntax', function() {
692 | var searchQuery = '-from:jul@foo.com';
693 | var options = {keywords: ['from']};
694 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
695 |
696 | parsedSearchQuery.should.be.an.Object;
697 | parsedSearchQuery.exclude.should.be.an.Object;
698 | parsedSearchQuery.exclude.should.have.property('from', 'jul@foo.com');
699 | parsedSearchQuery.should.not.have.property('text');
700 | parsedSearchQuery.should.have.property('offsets', [{
701 | keyword: 'from',
702 | value: 'jul@foo.com',
703 | offsetStart: 1,
704 | offsetEnd: 17
705 | }]);
706 |
707 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
708 | parsedAfterStringifySearchQuery.offsets = undefined;
709 | parsedSearchQuery.offsets = undefined;
710 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
711 | });
712 |
713 | it('should concatenate a keyword multiple values in exclusion syntax', function() {
714 | var searchQuery = '-from:jul@foo.com,mar@foo.com';
715 | var options = {keywords: ['from']};
716 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
717 |
718 | parsedSearchQuery.should.be.an.Object;
719 | parsedSearchQuery.exclude.should.be.an.Object;
720 | parsedSearchQuery.exclude.from.should.containEql('jul@foo.com');
721 | parsedSearchQuery.exclude.from.should.containEql('mar@foo.com');
722 | parsedSearchQuery.should.not.have.property('text');
723 | parsedSearchQuery.should.have.property('offsets', [{
724 | keyword: 'from',
725 | value: 'jul@foo.com,mar@foo.com',
726 | offsetStart: 1,
727 | offsetEnd: 29
728 | }]);
729 |
730 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
731 | parsedAfterStringifySearchQuery.offsets = undefined;
732 | parsedSearchQuery.offsets = undefined;
733 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
734 | });
735 |
736 | it('should support keywords which appear multiple times with exclusion syntax', function() {
737 | var searchQuery = '-from:jul@foo.com,mar@foo.com -from:jan@foo.com';
738 | var options = {
739 | keywords: ['from']
740 | };
741 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
742 |
743 | parsedSearchQuery.should.be.an.Object;
744 | parsedSearchQuery.exclude.should.be.an.Object;
745 | parsedSearchQuery.exclude.from.should.containEql('jul@foo.com');
746 | parsedSearchQuery.exclude.from.should.containEql('mar@foo.com');
747 | parsedSearchQuery.exclude.from.should.containEql('jan@foo.com');
748 | parsedSearchQuery.should.not.have.property('text');
749 | parsedSearchQuery.should.have.property('offsets', [{
750 | keyword: 'from',
751 | value: 'jul@foo.com,mar@foo.com',
752 | offsetStart: 1,
753 | offsetEnd: 29
754 | }, {
755 | keyword: 'from',
756 | value: 'jan@foo.com',
757 | offsetStart: 31,
758 | offsetEnd: 47
759 | }]);
760 |
761 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
762 | parsedAfterStringifySearchQuery.offsets = undefined;
763 | parsedSearchQuery.offsets = undefined;
764 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
765 | });
766 |
767 | it('should not return offset when offsets option is set to false', function() {
768 | var searchQuery = '-from:jul@foo.com,mar@foo.com to:bar@hey.ya about date:12/12/2012';
769 | var options = {
770 | keywords: ['from', 'to'],
771 | ranges: ['date'],
772 | offsets: false
773 | };
774 | var parsedSearchQuery = searchquery.parse(searchQuery, options);
775 |
776 | parsedSearchQuery.should.be.an.Object;
777 | parsedSearchQuery.exclude.should.be.an.Object;
778 | parsedSearchQuery.exclude.from.should.containEql('jul@foo.com');
779 | parsedSearchQuery.exclude.from.should.containEql('mar@foo.com');
780 | parsedSearchQuery.to.should.containEql('bar@hey.ya');
781 | parsedSearchQuery.should.have.property('text', 'about');
782 | parsedSearchQuery.should.have.property('date');
783 | parsedSearchQuery.date.from.should.containEql('12/12/2012');
784 | parsedSearchQuery.should.not.have.property('offsets');
785 |
786 | var parsedAfterStringifySearchQuery = searchquery.parse(searchquery.stringify(parsedSearchQuery, options), options);
787 | parsedAfterStringifySearchQuery.offsets = undefined;
788 | parsedSearchQuery.offsets = undefined;
789 | parsedAfterStringifySearchQuery.should.be.eql(parsedSearchQuery);
790 | });
791 | });
792 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "module": "commonjs",
4 | "target": "es5",
5 | "composite": true,
6 | "sourceMap": true,
7 | "declaration": true,
8 | "declarationMap": true
9 | },
10 | "include": [
11 | "./lib/**/*"
12 | ],
13 | "exclude": [],
14 | "typedocOptions": {
15 | "mode": "modules",
16 | "out": "docs",
17 | "include": "./lib",
18 | "exclude": ["./node_modules/**/*"],
19 | "module": "commonjs",
20 | "target": "es5",
21 | "includeDeclarations": true,
22 | "theme": "markdown",
23 | "readme": "none"
24 | }
25 | }
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "dtslint/dt.json"
3 | }
--------------------------------------------------------------------------------