├── LICENSE.md
├── README.md
├── lib
└── characterset.js
├── package-lock.json
├── package.json
└── test
├── characterset-test.js
└── index.html
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2013, Bram Stein
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | 1. Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 | 2. Redistributions in binary form must reproduce the above copyright
11 | notice, this list of conditions and the following disclaimer in the
12 | documentation and/or other materials provided with the distribution.
13 | 3. The name of the author may not be used to endorse or promote products
14 | derived from this software without specific prior written permission.
15 |
16 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
17 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 | EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
20 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21 | BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
23 | OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
24 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
25 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## CharacterSet
2 |
3 | CharacterSet is a library for creating and manipulating Unicode character sets in JavaScript. Its main purpose is to help in building regular expressions for validation and matching. It fully supports all Unicode characters and correctly handles surrogate pairs in JavaScript strings and regular expressions.
4 |
5 | ## Installation
6 |
7 | If you are using Node.js you can install it using npm:
8 |
9 | ```sh
10 | npm install characterset
11 | ```
12 |
13 | If you want to use CharacterSet in the browser, use the global `CharacterSet` constructor or include CharacterSet as an ES6 module.
14 |
15 | ## API
16 |
17 | The constructor takes a single input value, which can either be a number, a string or a range. A range is an array of numbers or number pairs.
18 |
19 | ```js
20 | import CharacterSet from 'characterset';
21 |
22 | // Creates a character set with a single code point for [97]
23 | var cs = new CharacterSet(97);
24 |
25 | // Creates a character set for the code points [97, 98, 99]
26 | var cs = new CharacterSet('abc');
27 |
28 | // Creates a character set for the code points [97, 98, 99]
29 | var cs = new CharacterSet([97, 98, 99]);
30 |
31 | // Creates a character set for the code points [97, 98, 99] using a range
32 | var cs = new CharacterSet([[97, 99]]);
33 |
34 | // Combines pairs and numbers in ranges for [0, 97, 98, 99]
35 | var cs = new CharacterSet([48, [97, 99]]);
36 | ```
37 |
38 | Or you can use the `parseUnicodeRange` method to return a CharacterSet instance from a comma-delimited unicode range string.
39 |
40 | ```js
41 | import CharacterSet from 'characterset';
42 |
43 | // Creates a character set for the code points [34, 35]
44 | var cs = CharacterSet.parseUnicodeRange('u+23,u+22');
45 |
46 | // Creates a character set for the code points [34, 35, 36, 37]
47 | var cs = CharacterSet.parseUnicodeRange('u+22-25');
48 | ```
49 |
50 | Once you have an instance of `CharacterSet` you can use the following methods on it:
51 |
52 |
53 | getSize()
54 | Returns the number of code points in this set.
55 |
56 | toArray()
57 | Returns all code points in this set as a sorted array.
58 |
59 | toRange()
60 | Returns all code points in this set as a range (i.e. compressed.)
61 |
62 | isEmpty()
63 | Returns true if this set is empty.
64 |
65 | add(codePoint, ...)
66 | Adds the given code point(s) to this set.
67 |
68 | remove(codePoint, ...)
69 | Removes the given code point(s) from this set.
70 |
71 | contains(codePoint)
72 | Returns true if the given code point is in this set.
73 |
74 | equals(other)
75 | Returns true if the `other` set is equal to this set.
76 |
77 | union(other)
78 | Returns a new character set from the combined code points from `other` and this character set.
79 |
80 | intersect(other)
81 | Returns a new character set containing only the code points `other` and this character set have in common.
82 |
83 | difference(other)
84 | Returns a new character set containing only the code points from this that are not in `other`.
85 |
86 | subset(other)
87 | Returns true if this character set is a subset of `other`.
88 |
89 | toRegExp()
90 | Returns a RegExp matching the code points in this character set
91 |
92 | toString()
93 | Returns a string representation of this character set.
94 |
95 | toHexString()
96 | Returns a hex string representation of this character set.
97 |
98 | toHexRangeString()
99 | Returns a hex string representation with ranges of this character set.
100 |
101 |
102 | ## License
103 |
104 | CharacterSet is licensed under the three clause BSD license (see [BSD.txt](BSD.txt).)
105 |
--------------------------------------------------------------------------------
/lib/characterset.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @constructor
3 | * @struct
4 | * @param {number|string|CharacterSet.Range} input
5 | */
6 | function CharacterSet(input) {
7 | /**
8 | * @type {Object.}
9 | */
10 | this.data = {};
11 |
12 | /**
13 | * @type {number}
14 | */
15 | this.size = 0;
16 |
17 | if (typeof input === 'string') {
18 | for (var i = 0; i < input.length; i += 1) {
19 | var codePoint = input.charCodeAt(i);
20 |
21 | if ((codePoint & 0xF800) === 0xD800 && i < input.length) {
22 | var nextCodePoint = input.charCodeAt(i + 1);
23 | if ((nextCodePoint & 0xFC00) === 0xDC00) {
24 | this.add(((codePoint & 0x3FF) << 10) + (nextCodePoint & 0x3FF) + 0x10000);
25 | } else {
26 | this.add(codePoint);
27 | }
28 | i += 1;
29 | } else {
30 | this.add(codePoint);
31 | }
32 | }
33 | } else if (typeof input === 'number') {
34 | this.add(input);
35 | } else if (Array.isArray(input)) {
36 | input = this.expandRange(input);
37 |
38 | for (var i = 0; i < input.length; i += 1) {
39 | this.add(input[i]);
40 | }
41 | }
42 | }
43 |
44 | /**
45 | * @typedef {Array.>}
46 | */
47 | CharacterSet.Range;
48 |
49 | /**
50 | * @return {number}
51 | */
52 | CharacterSet.prototype.getSize = function () {
53 | return this.size;
54 | };
55 |
56 | /**
57 | * @private
58 | * @param {CharacterSet.Range} range
59 | * @return {Array.}
60 | */
61 | CharacterSet.prototype.expandRange = function (range) {
62 | var result = [];
63 |
64 | for (var i = 0; i < range.length; i += 1) {
65 | if (Array.isArray(range[i])) {
66 | for (var j = range[i][0]; j < range[i][1] + 1; j += 1) {
67 | result.push(j);
68 | }
69 | } else {
70 | result.push(range[i]);
71 | }
72 | }
73 |
74 | return result;
75 | };
76 |
77 | /**
78 | * @private
79 | * @param {Array.} codePoints
80 | * @return {CharacterSet.Range}
81 | */
82 | CharacterSet.prototype.compressRange = function (codePoints) {
83 | var result = [];
84 |
85 | for (var i = 0; i < codePoints.length; i += 1) {
86 | var previous = (i > 0) ? codePoints[i - 1] : null,
87 | next = (i < codePoints.length - 1) ? codePoints[i + 1] : null,
88 | current = codePoints[i];
89 |
90 | if ((current - 1 !== previous || previous === null) &&
91 | (current + 1 !== next || next === null)) {
92 | result.push(current);
93 | } else if ((current - 1 !== previous || previous === null) &&
94 | (current + 1 === next || next === null)) {
95 | result.push(current);
96 | } else if ((current - 1 === previous || previous === null) &&
97 | (current + 1 !== next || next === null)) {
98 |
99 | // Don't bother collapsing the range if the range only consists of two adjacent code points
100 | if (current - result[result.length - 1] > 1) {
101 | result[result.length - 1] = [result[result.length - 1], current];
102 | } else {
103 | result.push(current);
104 | }
105 | }
106 | }
107 |
108 | return result;
109 | };
110 |
111 | /**
112 | * @return {Array.} Returns the code points in this set as an array.
113 | */
114 | CharacterSet.prototype.toArray = function () {
115 | var result = [];
116 |
117 | for (var codePoint in this.data) {
118 | if (this.data.hasOwnProperty(codePoint) && this.data[codePoint] === true) {
119 | result.push(parseInt(codePoint, 10));
120 | }
121 | }
122 |
123 | result.sort(function (a, b) {
124 | return a - b;
125 | });
126 |
127 | return result;
128 | };
129 |
130 | /**
131 | * @return {CharacterSet.Range}
132 | */
133 | CharacterSet.prototype.toRange = function () {
134 | return this.compressRange(this.toArray());
135 | };
136 |
137 | /**
138 | * @return {boolean} True if this set is empty.
139 | */
140 | CharacterSet.prototype.isEmpty = function () {
141 | return this.size === 0;
142 | };
143 |
144 | /**
145 | * @param {...number} var_args The code point to add to this set.
146 | */
147 | CharacterSet.prototype.add = function (var_args) {
148 | for (var i = 0; i < arguments.length; i += 1) {
149 | var codePoint = arguments[i];
150 |
151 | if (this.data[codePoint] !== true) {
152 | this.data[codePoint] = true;
153 | this.size += 1;
154 | }
155 | }
156 | };
157 |
158 | /**
159 | * @param {...number} var_args The code point to remove from this set.
160 | */
161 | CharacterSet.prototype.remove = function (var_args) {
162 | for (var i = 0; i < arguments.length; i += 1) {
163 | var codePoint = arguments[i];
164 |
165 | if (this.data[codePoint] === true) {
166 | this.data[codePoint] = false;
167 | this.size -= 1;
168 | }
169 | }
170 | };
171 |
172 | /**
173 | * @param {number} codePoint
174 | * @return {boolean} True if the code point is in this set.
175 | */
176 | CharacterSet.prototype.contains = function (codePoint) {
177 | return this.data[codePoint] === true;
178 | };
179 |
180 | /**
181 | * @param {CharacterSet} other
182 | * @return {boolean} True if this character set matches other.
183 | */
184 | CharacterSet.prototype.equals = function (other) {
185 | var codePoints = this.toArray();
186 |
187 | if (this.getSize() === other.getSize()) {
188 | for (var i = 0; i < codePoints.length; i += 1) {
189 | if (!other.contains(codePoints[i])) {
190 | return false;
191 | }
192 | }
193 | return true;
194 | } else {
195 | return false;
196 | }
197 | };
198 |
199 | /**
200 | * @param {CharacterSet} other
201 | * @return {CharacterSet} The combined code points of both character sets.
202 | */
203 | CharacterSet.prototype.union = function (other) {
204 | return new CharacterSet(this.toArray().concat(other.toArray()));
205 | };
206 |
207 | /**
208 | * @param {CharacerSet} other
209 | * @return {CharacterSet} A set containing only those code points both sets have in common.
210 | */
211 | CharacterSet.prototype.intersect = function (other) {
212 | var result = new CharacterSet(),
213 | codePoints = this.toArray();
214 |
215 | for (var i = 0; i < codePoints.length; i += 1) {
216 | if (other.contains(codePoints[i])) {
217 | result.add(codePoints[i]);
218 | }
219 | }
220 |
221 | return result;
222 | };
223 |
224 | /**
225 | * @param {CharacterSet} other
226 | * @return {CharacterSet} A set containing only those code points that are not in `other`.
227 | */
228 | CharacterSet.prototype.difference = function (other) {
229 | var result = new CharacterSet(),
230 | codePoints = this.toArray();
231 |
232 | for (var i = 0; i < codePoints.length; i += 1) {
233 | if (!other.contains(codePoints[i])) {
234 | result.add(codePoints[i]);
235 | }
236 | }
237 |
238 | return result;
239 | };
240 |
241 | /**
242 | * @param {CharacterSet} other
243 | * @return true if this is a subset of `other`
244 | */
245 | CharacterSet.prototype.subset = function (other) {
246 | var codePoints = this.toArray();
247 |
248 | for (var i = 0; i < codePoints.length; i += 1) {
249 | if (!other.contains(codePoints[i])) {
250 | return false;
251 | }
252 | }
253 | return true;
254 | };
255 |
256 | /**
257 | * @private
258 | * @param {number} codePoint
259 | * @return {number} The high surrogate for this code point.
260 | */
261 | CharacterSet.prototype.extractHighSurrogate = function (codePoint) {
262 | return Math.floor((codePoint - 0x10000) / 0x400) + 0xD800;
263 | };
264 |
265 | /**
266 | * @private
267 | * @param {number} codePoint
268 | * @return {number} The low surrogate for this code point.
269 | */
270 | CharacterSet.prototype.extractLowSurrogate = function (codePoint) {
271 | return (codePoint - 0x10000) % 0x400 + 0xDC00;
272 | };
273 |
274 | /**
275 | * @private
276 | * @param {number} codePoint The code point to encode
277 | * @return {string}
278 | */
279 | CharacterSet.prototype.encodeCodePoint = function (codePoint) {
280 | if ((codePoint >= 0x41 && codePoint <= 0x5A) || // A-Z
281 | (codePoint >= 0x61 && codePoint <= 0x7A) || // a-z
282 | (codePoint >= 0x30 && codePoint <= 0x39)) { // 0-9
283 | return String.fromCharCode(codePoint);
284 | } else if (codePoint <= 0xFFFF) {
285 | return '\\u' + (codePoint + 0x10000).toString(16).substr(-4).toUpperCase();
286 | } else {
287 | return this.encodeCodePoint(this.extractHighSurrogate(codePoint)) +
288 | this.encodeCodePoint(this.extractLowSurrogate(codePoint));
289 | }
290 | };
291 |
292 | /**
293 | * @return {string} A regular expression that can be used to match or test
294 | * this character set. The regular expression is returned as a string so
295 | * that the user can set flags and add capturing groups.
296 | *
297 | * Thanks to: http://inimino.org/~inimino/blog/javascript_cset for the
298 | * inspiration for this function.
299 | */
300 | CharacterSet.prototype.toRegExp = function () {
301 | var codePoints = this.toArray(),
302 | bmp = new CharacterSet(),
303 | surrogates = new CharacterSet(),
304 | highSurrogates = {},
305 | lowSurrogates = {},
306 | result = [];
307 |
308 | // Go through all the code points and split them into BMP code points,
309 | // code points in the surrogate range, and surrogate pairs.
310 | for (var i = 0; i < codePoints.length; i += 1) {
311 | if (codePoints[i] >= 0xD8000 && codePoints[i] <= 0xDBFF) {
312 | surrogates.add(codePoints[i]);
313 | } else if (codePoints[i] <= 0xFFFF) {
314 | bmp.add(codePoints[i]);
315 | } else {
316 | // We calculate the high and low surrogate code point for
317 | // each code point outside the BMP.
318 | var highSurrogate = this.extractHighSurrogate(codePoints[i]),
319 | lowSurrogate = this.extractLowSurrogate(codePoints[i]);
320 |
321 | if (!highSurrogates.hasOwnProperty(highSurrogate)) {
322 | highSurrogates[highSurrogate] = new CharacterSet();
323 | }
324 | // Store all low surrogate code points for each high code point.
325 | // This creates a mapping from high code points to matching low
326 | // code points.
327 | //
328 | // {
329 | // 103849: [104499, 189548, 103478],
330 | // 103478: [102819],
331 | // 120928: [104499, 189548, 103478]
332 | // ...
333 | // }
334 | highSurrogates[highSurrogate].add(lowSurrogate);
335 | }
336 | }
337 |
338 | for (var highSurrogate in highSurrogates) {
339 | var lowSurrogateSet = highSurrogates[highSurrogate],
340 | lowSurrogateKey = lowSurrogateSet.toRangeString();
341 |
342 | // Make a unique set of low surrogates and their matching
343 | // high surrogate points
344 | // {
345 | // '[103478,104499,189548]': [103849, 120928],
346 | // '[102819]': [103478],
347 | // ...
348 | // }
349 | if (!lowSurrogates.hasOwnProperty(lowSurrogateKey)) {
350 | lowSurrogates[lowSurrogateKey] = new CharacterSet();
351 | }
352 |
353 | lowSurrogates[lowSurrogateKey].add(parseInt(highSurrogate, 10));
354 | }
355 |
356 | if (!bmp.isEmpty()) {
357 | result.push(bmp.toRangeString());
358 | }
359 |
360 | for (var lowSurrogateRange in lowSurrogates) {
361 | // Combine the low and high surrogate sets into
362 | // a single group.
363 | //
364 | // [103849,120928][103478,104499,189548]
365 | // 103478[102819]
366 | var highSurrogateSet = lowSurrogates[lowSurrogateRange];
367 | result.push(highSurrogateSet.toRangeString() + lowSurrogateRange);
368 | }
369 |
370 | if (!surrogates.isEmpty()) {
371 | result.push(surrogates.toRangeString());
372 | }
373 |
374 | return result.join('|');
375 | };
376 |
377 | /**
378 | * Returns the set as a compressed code point string.
379 | * NOTE: this method handles code points outside
380 | * the BMP as if they are code points inside the BMP.
381 | * For a range outside the BMP it will thus return
382 | * four code points separated by a dash. It is up to
383 | * the consumer to correctly handle this case.
384 | *
385 | * @private
386 | * @return {string}
387 | */
388 | CharacterSet.prototype.toRangeString = function () {
389 | var containsRange = false,
390 | result = this.toRange().map(function (value) {
391 | if (Array.isArray(value)) {
392 | containsRange = true;
393 | return this.encodeCodePoint(value[0]) + '-' + this.encodeCodePoint(value[1]);
394 | } else {
395 | return this.encodeCodePoint(value);
396 | }
397 | }, this);
398 |
399 | if (result.length === 0) {
400 | return '';
401 | } else if (result.length === 1 && !containsRange) {
402 | return result[0];
403 | } else {
404 | return '[' + result.join('') + ']';
405 | }
406 | };
407 |
408 | /**
409 | * Returns the set as a list of comma separated hex
410 | * codepoints as seen in the CSS unicode-range syntax.
411 | *
412 | * @return {string}
413 | */
414 | CharacterSet.prototype.toHexString = function () {
415 | return this.toArray().map(function (codePoint) {
416 | return 'U+' + codePoint.toString(16).toUpperCase();
417 | }).join(',');
418 | };
419 |
420 | /**
421 | * Returns the set as a list of comma separated hex
422 | * ranges as seen in the CSS unicode-range syntax.
423 | *
424 | * @return {string}
425 | */
426 | CharacterSet.prototype.toHexRangeString = function () {
427 | return this.toRange().map(function (value) {
428 | if (Array.isArray(value)) {
429 | return 'U+' + value[0].toString(16).toUpperCase() + '-' + value[1].toString(16).toUpperCase();
430 | } else {
431 | return 'U+' + value.toString(16).toUpperCase();
432 | }
433 | }).join(',');
434 | };
435 |
436 | /**
437 | * @return {string}
438 | */
439 | CharacterSet.prototype.toString = function () {
440 | return this.toArray().map(this.encodeCodePoint.bind(this)).join('');
441 | };
442 |
443 | /**
444 | * @param {string} input
445 | *
446 | * @return {CharacterSet}
447 | */
448 | CharacterSet.parseUnicodeRange = function (input) {
449 | var ranges = input.split(/\s*,\s*/);
450 | var result = new CharacterSet();
451 |
452 | for (var i = 0; i < ranges.length; i++) {
453 | var match = /^(u\+([0-9a-f?]{1,6})(?:-([0-9a-f]{1,6}))?)$/i.exec(ranges[i]),
454 | start = null,
455 | end = null;
456 |
457 | if (match) {
458 | if (match[2].indexOf('?') !== -1) {
459 | start = parseInt(match[2].replace('?', '0'), 16);
460 | end = parseInt(match[2].replace('?', 'f'), 16);
461 | } else {
462 | start = parseInt(match[2], 16);
463 |
464 | if (match[3]) {
465 | end = parseInt(match[3], 16);
466 | } else {
467 | end = start;
468 | }
469 | }
470 |
471 | if (start !== end) {
472 | for (var codePoint = start; codePoint <= end; codePoint++) {
473 | result.add(codePoint);
474 | }
475 | } else {
476 | result.add(start);
477 | }
478 | }
479 | }
480 |
481 | return result;
482 | };
483 |
484 | export default CharacterSet;
485 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "characterset",
3 | "version": "2.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "name": "characterset",
9 | "version": "2.0.0",
10 | "devDependencies": {
11 | "expect.js": "0.2.0",
12 | "mocha": "^10.0.0"
13 | }
14 | },
15 | "node_modules/@ungap/promise-all-settled": {
16 | "version": "1.1.2",
17 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
18 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
19 | "dev": true
20 | },
21 | "node_modules/ansi-colors": {
22 | "version": "4.1.1",
23 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
24 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
25 | "dev": true,
26 | "engines": {
27 | "node": ">=6"
28 | }
29 | },
30 | "node_modules/ansi-regex": {
31 | "version": "5.0.1",
32 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
33 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
34 | "dev": true,
35 | "engines": {
36 | "node": ">=8"
37 | }
38 | },
39 | "node_modules/ansi-styles": {
40 | "version": "4.3.0",
41 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
42 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
43 | "dev": true,
44 | "dependencies": {
45 | "color-convert": "^2.0.1"
46 | },
47 | "engines": {
48 | "node": ">=8"
49 | },
50 | "funding": {
51 | "url": "https://github.com/chalk/ansi-styles?sponsor=1"
52 | }
53 | },
54 | "node_modules/anymatch": {
55 | "version": "3.1.2",
56 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
57 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
58 | "dev": true,
59 | "dependencies": {
60 | "normalize-path": "^3.0.0",
61 | "picomatch": "^2.0.4"
62 | },
63 | "engines": {
64 | "node": ">= 8"
65 | }
66 | },
67 | "node_modules/argparse": {
68 | "version": "2.0.1",
69 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
70 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
71 | "dev": true
72 | },
73 | "node_modules/balanced-match": {
74 | "version": "1.0.2",
75 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
76 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
77 | "dev": true
78 | },
79 | "node_modules/binary-extensions": {
80 | "version": "2.2.0",
81 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
82 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
83 | "dev": true,
84 | "engines": {
85 | "node": ">=8"
86 | }
87 | },
88 | "node_modules/brace-expansion": {
89 | "version": "2.0.1",
90 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
91 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
92 | "dev": true,
93 | "dependencies": {
94 | "balanced-match": "^1.0.0"
95 | }
96 | },
97 | "node_modules/braces": {
98 | "version": "3.0.2",
99 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
100 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
101 | "dev": true,
102 | "dependencies": {
103 | "fill-range": "^7.0.1"
104 | },
105 | "engines": {
106 | "node": ">=8"
107 | }
108 | },
109 | "node_modules/browser-stdout": {
110 | "version": "1.3.1",
111 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
112 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
113 | "dev": true
114 | },
115 | "node_modules/camelcase": {
116 | "version": "6.3.0",
117 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
118 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
119 | "dev": true,
120 | "engines": {
121 | "node": ">=10"
122 | },
123 | "funding": {
124 | "url": "https://github.com/sponsors/sindresorhus"
125 | }
126 | },
127 | "node_modules/chalk": {
128 | "version": "4.1.2",
129 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
130 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
131 | "dev": true,
132 | "dependencies": {
133 | "ansi-styles": "^4.1.0",
134 | "supports-color": "^7.1.0"
135 | },
136 | "engines": {
137 | "node": ">=10"
138 | },
139 | "funding": {
140 | "url": "https://github.com/chalk/chalk?sponsor=1"
141 | }
142 | },
143 | "node_modules/chalk/node_modules/supports-color": {
144 | "version": "7.2.0",
145 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
146 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
147 | "dev": true,
148 | "dependencies": {
149 | "has-flag": "^4.0.0"
150 | },
151 | "engines": {
152 | "node": ">=8"
153 | }
154 | },
155 | "node_modules/chokidar": {
156 | "version": "3.5.3",
157 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
158 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
159 | "dev": true,
160 | "funding": [
161 | {
162 | "type": "individual",
163 | "url": "https://paulmillr.com/funding/"
164 | }
165 | ],
166 | "dependencies": {
167 | "anymatch": "~3.1.2",
168 | "braces": "~3.0.2",
169 | "glob-parent": "~5.1.2",
170 | "is-binary-path": "~2.1.0",
171 | "is-glob": "~4.0.1",
172 | "normalize-path": "~3.0.0",
173 | "readdirp": "~3.6.0"
174 | },
175 | "engines": {
176 | "node": ">= 8.10.0"
177 | },
178 | "optionalDependencies": {
179 | "fsevents": "~2.3.2"
180 | }
181 | },
182 | "node_modules/cliui": {
183 | "version": "7.0.4",
184 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
185 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
186 | "dev": true,
187 | "dependencies": {
188 | "string-width": "^4.2.0",
189 | "strip-ansi": "^6.0.0",
190 | "wrap-ansi": "^7.0.0"
191 | }
192 | },
193 | "node_modules/color-convert": {
194 | "version": "2.0.1",
195 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
196 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
197 | "dev": true,
198 | "dependencies": {
199 | "color-name": "~1.1.4"
200 | },
201 | "engines": {
202 | "node": ">=7.0.0"
203 | }
204 | },
205 | "node_modules/color-name": {
206 | "version": "1.1.4",
207 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
208 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
209 | "dev": true
210 | },
211 | "node_modules/concat-map": {
212 | "version": "0.0.1",
213 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
214 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
215 | "dev": true
216 | },
217 | "node_modules/debug": {
218 | "version": "4.3.4",
219 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
220 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
221 | "dev": true,
222 | "dependencies": {
223 | "ms": "2.1.2"
224 | },
225 | "engines": {
226 | "node": ">=6.0"
227 | },
228 | "peerDependenciesMeta": {
229 | "supports-color": {
230 | "optional": true
231 | }
232 | }
233 | },
234 | "node_modules/debug/node_modules/ms": {
235 | "version": "2.1.2",
236 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
237 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
238 | "dev": true
239 | },
240 | "node_modules/decamelize": {
241 | "version": "4.0.0",
242 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
243 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
244 | "dev": true,
245 | "engines": {
246 | "node": ">=10"
247 | },
248 | "funding": {
249 | "url": "https://github.com/sponsors/sindresorhus"
250 | }
251 | },
252 | "node_modules/diff": {
253 | "version": "5.0.0",
254 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
255 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
256 | "dev": true,
257 | "engines": {
258 | "node": ">=0.3.1"
259 | }
260 | },
261 | "node_modules/emoji-regex": {
262 | "version": "8.0.0",
263 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
264 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
265 | "dev": true
266 | },
267 | "node_modules/escalade": {
268 | "version": "3.1.1",
269 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
270 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
271 | "dev": true,
272 | "engines": {
273 | "node": ">=6"
274 | }
275 | },
276 | "node_modules/escape-string-regexp": {
277 | "version": "4.0.0",
278 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
279 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
280 | "dev": true,
281 | "engines": {
282 | "node": ">=10"
283 | },
284 | "funding": {
285 | "url": "https://github.com/sponsors/sindresorhus"
286 | }
287 | },
288 | "node_modules/expect.js": {
289 | "version": "0.2.0",
290 | "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.2.0.tgz",
291 | "integrity": "sha512-Si9lyFUkFCY9nTSKocf/Im/knEJNHUgbEWCNpRqiM5J2w+0YPxalJo0aomfh4WxlQiZ6kG97cZlN2UhAVxPAsA==",
292 | "dev": true
293 | },
294 | "node_modules/fill-range": {
295 | "version": "7.0.1",
296 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
297 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
298 | "dev": true,
299 | "dependencies": {
300 | "to-regex-range": "^5.0.1"
301 | },
302 | "engines": {
303 | "node": ">=8"
304 | }
305 | },
306 | "node_modules/find-up": {
307 | "version": "5.0.0",
308 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
309 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
310 | "dev": true,
311 | "dependencies": {
312 | "locate-path": "^6.0.0",
313 | "path-exists": "^4.0.0"
314 | },
315 | "engines": {
316 | "node": ">=10"
317 | },
318 | "funding": {
319 | "url": "https://github.com/sponsors/sindresorhus"
320 | }
321 | },
322 | "node_modules/flat": {
323 | "version": "5.0.2",
324 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
325 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
326 | "dev": true,
327 | "bin": {
328 | "flat": "cli.js"
329 | }
330 | },
331 | "node_modules/fs.realpath": {
332 | "version": "1.0.0",
333 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
334 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
335 | "dev": true
336 | },
337 | "node_modules/fsevents": {
338 | "version": "2.3.2",
339 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
340 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
341 | "dev": true,
342 | "hasInstallScript": true,
343 | "optional": true,
344 | "os": [
345 | "darwin"
346 | ],
347 | "engines": {
348 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
349 | }
350 | },
351 | "node_modules/get-caller-file": {
352 | "version": "2.0.5",
353 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
354 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
355 | "dev": true,
356 | "engines": {
357 | "node": "6.* || 8.* || >= 10.*"
358 | }
359 | },
360 | "node_modules/glob": {
361 | "version": "7.2.0",
362 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
363 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
364 | "dev": true,
365 | "dependencies": {
366 | "fs.realpath": "^1.0.0",
367 | "inflight": "^1.0.4",
368 | "inherits": "2",
369 | "minimatch": "^3.0.4",
370 | "once": "^1.3.0",
371 | "path-is-absolute": "^1.0.0"
372 | },
373 | "engines": {
374 | "node": "*"
375 | },
376 | "funding": {
377 | "url": "https://github.com/sponsors/isaacs"
378 | }
379 | },
380 | "node_modules/glob-parent": {
381 | "version": "5.1.2",
382 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
383 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
384 | "dev": true,
385 | "dependencies": {
386 | "is-glob": "^4.0.1"
387 | },
388 | "engines": {
389 | "node": ">= 6"
390 | }
391 | },
392 | "node_modules/glob/node_modules/brace-expansion": {
393 | "version": "1.1.11",
394 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
395 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
396 | "dev": true,
397 | "dependencies": {
398 | "balanced-match": "^1.0.0",
399 | "concat-map": "0.0.1"
400 | }
401 | },
402 | "node_modules/glob/node_modules/minimatch": {
403 | "version": "3.1.2",
404 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
405 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
406 | "dev": true,
407 | "dependencies": {
408 | "brace-expansion": "^1.1.7"
409 | },
410 | "engines": {
411 | "node": "*"
412 | }
413 | },
414 | "node_modules/has-flag": {
415 | "version": "4.0.0",
416 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
417 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
418 | "dev": true,
419 | "engines": {
420 | "node": ">=8"
421 | }
422 | },
423 | "node_modules/he": {
424 | "version": "1.2.0",
425 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
426 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
427 | "dev": true,
428 | "bin": {
429 | "he": "bin/he"
430 | }
431 | },
432 | "node_modules/inflight": {
433 | "version": "1.0.6",
434 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
435 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
436 | "dev": true,
437 | "dependencies": {
438 | "once": "^1.3.0",
439 | "wrappy": "1"
440 | }
441 | },
442 | "node_modules/inherits": {
443 | "version": "2.0.4",
444 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
445 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
446 | "dev": true
447 | },
448 | "node_modules/is-binary-path": {
449 | "version": "2.1.0",
450 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
451 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
452 | "dev": true,
453 | "dependencies": {
454 | "binary-extensions": "^2.0.0"
455 | },
456 | "engines": {
457 | "node": ">=8"
458 | }
459 | },
460 | "node_modules/is-extglob": {
461 | "version": "2.1.1",
462 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
463 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
464 | "dev": true,
465 | "engines": {
466 | "node": ">=0.10.0"
467 | }
468 | },
469 | "node_modules/is-fullwidth-code-point": {
470 | "version": "3.0.0",
471 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
472 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
473 | "dev": true,
474 | "engines": {
475 | "node": ">=8"
476 | }
477 | },
478 | "node_modules/is-glob": {
479 | "version": "4.0.3",
480 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
481 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
482 | "dev": true,
483 | "dependencies": {
484 | "is-extglob": "^2.1.1"
485 | },
486 | "engines": {
487 | "node": ">=0.10.0"
488 | }
489 | },
490 | "node_modules/is-number": {
491 | "version": "7.0.0",
492 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
493 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
494 | "dev": true,
495 | "engines": {
496 | "node": ">=0.12.0"
497 | }
498 | },
499 | "node_modules/is-plain-obj": {
500 | "version": "2.1.0",
501 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
502 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
503 | "dev": true,
504 | "engines": {
505 | "node": ">=8"
506 | }
507 | },
508 | "node_modules/is-unicode-supported": {
509 | "version": "0.1.0",
510 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
511 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
512 | "dev": true,
513 | "engines": {
514 | "node": ">=10"
515 | },
516 | "funding": {
517 | "url": "https://github.com/sponsors/sindresorhus"
518 | }
519 | },
520 | "node_modules/js-yaml": {
521 | "version": "4.1.0",
522 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
523 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
524 | "dev": true,
525 | "dependencies": {
526 | "argparse": "^2.0.1"
527 | },
528 | "bin": {
529 | "js-yaml": "bin/js-yaml.js"
530 | }
531 | },
532 | "node_modules/locate-path": {
533 | "version": "6.0.0",
534 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
535 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
536 | "dev": true,
537 | "dependencies": {
538 | "p-locate": "^5.0.0"
539 | },
540 | "engines": {
541 | "node": ">=10"
542 | },
543 | "funding": {
544 | "url": "https://github.com/sponsors/sindresorhus"
545 | }
546 | },
547 | "node_modules/log-symbols": {
548 | "version": "4.1.0",
549 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
550 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
551 | "dev": true,
552 | "dependencies": {
553 | "chalk": "^4.1.0",
554 | "is-unicode-supported": "^0.1.0"
555 | },
556 | "engines": {
557 | "node": ">=10"
558 | },
559 | "funding": {
560 | "url": "https://github.com/sponsors/sindresorhus"
561 | }
562 | },
563 | "node_modules/minimatch": {
564 | "version": "5.0.1",
565 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
566 | "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
567 | "dev": true,
568 | "dependencies": {
569 | "brace-expansion": "^2.0.1"
570 | },
571 | "engines": {
572 | "node": ">=10"
573 | }
574 | },
575 | "node_modules/mocha": {
576 | "version": "10.0.0",
577 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz",
578 | "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==",
579 | "dev": true,
580 | "dependencies": {
581 | "@ungap/promise-all-settled": "1.1.2",
582 | "ansi-colors": "4.1.1",
583 | "browser-stdout": "1.3.1",
584 | "chokidar": "3.5.3",
585 | "debug": "4.3.4",
586 | "diff": "5.0.0",
587 | "escape-string-regexp": "4.0.0",
588 | "find-up": "5.0.0",
589 | "glob": "7.2.0",
590 | "he": "1.2.0",
591 | "js-yaml": "4.1.0",
592 | "log-symbols": "4.1.0",
593 | "minimatch": "5.0.1",
594 | "ms": "2.1.3",
595 | "nanoid": "3.3.3",
596 | "serialize-javascript": "6.0.0",
597 | "strip-json-comments": "3.1.1",
598 | "supports-color": "8.1.1",
599 | "workerpool": "6.2.1",
600 | "yargs": "16.2.0",
601 | "yargs-parser": "20.2.4",
602 | "yargs-unparser": "2.0.0"
603 | },
604 | "bin": {
605 | "_mocha": "bin/_mocha",
606 | "mocha": "bin/mocha.js"
607 | },
608 | "engines": {
609 | "node": ">= 14.0.0"
610 | },
611 | "funding": {
612 | "type": "opencollective",
613 | "url": "https://opencollective.com/mochajs"
614 | }
615 | },
616 | "node_modules/ms": {
617 | "version": "2.1.3",
618 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
619 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
620 | "dev": true
621 | },
622 | "node_modules/nanoid": {
623 | "version": "3.3.3",
624 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
625 | "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
626 | "dev": true,
627 | "bin": {
628 | "nanoid": "bin/nanoid.cjs"
629 | },
630 | "engines": {
631 | "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
632 | }
633 | },
634 | "node_modules/normalize-path": {
635 | "version": "3.0.0",
636 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
637 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
638 | "dev": true,
639 | "engines": {
640 | "node": ">=0.10.0"
641 | }
642 | },
643 | "node_modules/once": {
644 | "version": "1.4.0",
645 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
646 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
647 | "dev": true,
648 | "dependencies": {
649 | "wrappy": "1"
650 | }
651 | },
652 | "node_modules/p-limit": {
653 | "version": "3.1.0",
654 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
655 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
656 | "dev": true,
657 | "dependencies": {
658 | "yocto-queue": "^0.1.0"
659 | },
660 | "engines": {
661 | "node": ">=10"
662 | },
663 | "funding": {
664 | "url": "https://github.com/sponsors/sindresorhus"
665 | }
666 | },
667 | "node_modules/p-locate": {
668 | "version": "5.0.0",
669 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
670 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
671 | "dev": true,
672 | "dependencies": {
673 | "p-limit": "^3.0.2"
674 | },
675 | "engines": {
676 | "node": ">=10"
677 | },
678 | "funding": {
679 | "url": "https://github.com/sponsors/sindresorhus"
680 | }
681 | },
682 | "node_modules/path-exists": {
683 | "version": "4.0.0",
684 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
685 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
686 | "dev": true,
687 | "engines": {
688 | "node": ">=8"
689 | }
690 | },
691 | "node_modules/path-is-absolute": {
692 | "version": "1.0.1",
693 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
694 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
695 | "dev": true,
696 | "engines": {
697 | "node": ">=0.10.0"
698 | }
699 | },
700 | "node_modules/picomatch": {
701 | "version": "2.3.1",
702 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
703 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
704 | "dev": true,
705 | "engines": {
706 | "node": ">=8.6"
707 | },
708 | "funding": {
709 | "url": "https://github.com/sponsors/jonschlinkert"
710 | }
711 | },
712 | "node_modules/randombytes": {
713 | "version": "2.1.0",
714 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
715 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
716 | "dev": true,
717 | "dependencies": {
718 | "safe-buffer": "^5.1.0"
719 | }
720 | },
721 | "node_modules/readdirp": {
722 | "version": "3.6.0",
723 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
724 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
725 | "dev": true,
726 | "dependencies": {
727 | "picomatch": "^2.2.1"
728 | },
729 | "engines": {
730 | "node": ">=8.10.0"
731 | }
732 | },
733 | "node_modules/require-directory": {
734 | "version": "2.1.1",
735 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
736 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
737 | "dev": true,
738 | "engines": {
739 | "node": ">=0.10.0"
740 | }
741 | },
742 | "node_modules/safe-buffer": {
743 | "version": "5.2.1",
744 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
745 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
746 | "dev": true,
747 | "funding": [
748 | {
749 | "type": "github",
750 | "url": "https://github.com/sponsors/feross"
751 | },
752 | {
753 | "type": "patreon",
754 | "url": "https://www.patreon.com/feross"
755 | },
756 | {
757 | "type": "consulting",
758 | "url": "https://feross.org/support"
759 | }
760 | ]
761 | },
762 | "node_modules/serialize-javascript": {
763 | "version": "6.0.0",
764 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
765 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
766 | "dev": true,
767 | "dependencies": {
768 | "randombytes": "^2.1.0"
769 | }
770 | },
771 | "node_modules/string-width": {
772 | "version": "4.2.3",
773 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
774 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
775 | "dev": true,
776 | "dependencies": {
777 | "emoji-regex": "^8.0.0",
778 | "is-fullwidth-code-point": "^3.0.0",
779 | "strip-ansi": "^6.0.1"
780 | },
781 | "engines": {
782 | "node": ">=8"
783 | }
784 | },
785 | "node_modules/strip-ansi": {
786 | "version": "6.0.1",
787 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
788 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
789 | "dev": true,
790 | "dependencies": {
791 | "ansi-regex": "^5.0.1"
792 | },
793 | "engines": {
794 | "node": ">=8"
795 | }
796 | },
797 | "node_modules/strip-json-comments": {
798 | "version": "3.1.1",
799 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
800 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
801 | "dev": true,
802 | "engines": {
803 | "node": ">=8"
804 | },
805 | "funding": {
806 | "url": "https://github.com/sponsors/sindresorhus"
807 | }
808 | },
809 | "node_modules/supports-color": {
810 | "version": "8.1.1",
811 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
812 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
813 | "dev": true,
814 | "dependencies": {
815 | "has-flag": "^4.0.0"
816 | },
817 | "engines": {
818 | "node": ">=10"
819 | },
820 | "funding": {
821 | "url": "https://github.com/chalk/supports-color?sponsor=1"
822 | }
823 | },
824 | "node_modules/to-regex-range": {
825 | "version": "5.0.1",
826 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
827 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
828 | "dev": true,
829 | "dependencies": {
830 | "is-number": "^7.0.0"
831 | },
832 | "engines": {
833 | "node": ">=8.0"
834 | }
835 | },
836 | "node_modules/workerpool": {
837 | "version": "6.2.1",
838 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
839 | "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
840 | "dev": true
841 | },
842 | "node_modules/wrap-ansi": {
843 | "version": "7.0.0",
844 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
845 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
846 | "dev": true,
847 | "dependencies": {
848 | "ansi-styles": "^4.0.0",
849 | "string-width": "^4.1.0",
850 | "strip-ansi": "^6.0.0"
851 | },
852 | "engines": {
853 | "node": ">=10"
854 | },
855 | "funding": {
856 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
857 | }
858 | },
859 | "node_modules/wrappy": {
860 | "version": "1.0.2",
861 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
862 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
863 | "dev": true
864 | },
865 | "node_modules/y18n": {
866 | "version": "5.0.8",
867 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
868 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
869 | "dev": true,
870 | "engines": {
871 | "node": ">=10"
872 | }
873 | },
874 | "node_modules/yargs": {
875 | "version": "16.2.0",
876 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
877 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
878 | "dev": true,
879 | "dependencies": {
880 | "cliui": "^7.0.2",
881 | "escalade": "^3.1.1",
882 | "get-caller-file": "^2.0.5",
883 | "require-directory": "^2.1.1",
884 | "string-width": "^4.2.0",
885 | "y18n": "^5.0.5",
886 | "yargs-parser": "^20.2.2"
887 | },
888 | "engines": {
889 | "node": ">=10"
890 | }
891 | },
892 | "node_modules/yargs-parser": {
893 | "version": "20.2.4",
894 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
895 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
896 | "dev": true,
897 | "engines": {
898 | "node": ">=10"
899 | }
900 | },
901 | "node_modules/yargs-unparser": {
902 | "version": "2.0.0",
903 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
904 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
905 | "dev": true,
906 | "dependencies": {
907 | "camelcase": "^6.0.0",
908 | "decamelize": "^4.0.0",
909 | "flat": "^5.0.2",
910 | "is-plain-obj": "^2.1.0"
911 | },
912 | "engines": {
913 | "node": ">=10"
914 | }
915 | },
916 | "node_modules/yocto-queue": {
917 | "version": "0.1.0",
918 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
919 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
920 | "dev": true,
921 | "engines": {
922 | "node": ">=10"
923 | },
924 | "funding": {
925 | "url": "https://github.com/sponsors/sindresorhus"
926 | }
927 | }
928 | },
929 | "dependencies": {
930 | "@ungap/promise-all-settled": {
931 | "version": "1.1.2",
932 | "resolved": "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz",
933 | "integrity": "sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q==",
934 | "dev": true
935 | },
936 | "ansi-colors": {
937 | "version": "4.1.1",
938 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz",
939 | "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==",
940 | "dev": true
941 | },
942 | "ansi-regex": {
943 | "version": "5.0.1",
944 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
945 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
946 | "dev": true
947 | },
948 | "ansi-styles": {
949 | "version": "4.3.0",
950 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
951 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
952 | "dev": true,
953 | "requires": {
954 | "color-convert": "^2.0.1"
955 | }
956 | },
957 | "anymatch": {
958 | "version": "3.1.2",
959 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
960 | "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
961 | "dev": true,
962 | "requires": {
963 | "normalize-path": "^3.0.0",
964 | "picomatch": "^2.0.4"
965 | }
966 | },
967 | "argparse": {
968 | "version": "2.0.1",
969 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
970 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
971 | "dev": true
972 | },
973 | "balanced-match": {
974 | "version": "1.0.2",
975 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
976 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
977 | "dev": true
978 | },
979 | "binary-extensions": {
980 | "version": "2.2.0",
981 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
982 | "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
983 | "dev": true
984 | },
985 | "brace-expansion": {
986 | "version": "2.0.1",
987 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
988 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
989 | "dev": true,
990 | "requires": {
991 | "balanced-match": "^1.0.0"
992 | }
993 | },
994 | "braces": {
995 | "version": "3.0.2",
996 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
997 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
998 | "dev": true,
999 | "requires": {
1000 | "fill-range": "^7.0.1"
1001 | }
1002 | },
1003 | "browser-stdout": {
1004 | "version": "1.3.1",
1005 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
1006 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
1007 | "dev": true
1008 | },
1009 | "camelcase": {
1010 | "version": "6.3.0",
1011 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
1012 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
1013 | "dev": true
1014 | },
1015 | "chalk": {
1016 | "version": "4.1.2",
1017 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
1018 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
1019 | "dev": true,
1020 | "requires": {
1021 | "ansi-styles": "^4.1.0",
1022 | "supports-color": "^7.1.0"
1023 | },
1024 | "dependencies": {
1025 | "supports-color": {
1026 | "version": "7.2.0",
1027 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
1028 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
1029 | "dev": true,
1030 | "requires": {
1031 | "has-flag": "^4.0.0"
1032 | }
1033 | }
1034 | }
1035 | },
1036 | "chokidar": {
1037 | "version": "3.5.3",
1038 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
1039 | "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
1040 | "dev": true,
1041 | "requires": {
1042 | "anymatch": "~3.1.2",
1043 | "braces": "~3.0.2",
1044 | "fsevents": "~2.3.2",
1045 | "glob-parent": "~5.1.2",
1046 | "is-binary-path": "~2.1.0",
1047 | "is-glob": "~4.0.1",
1048 | "normalize-path": "~3.0.0",
1049 | "readdirp": "~3.6.0"
1050 | }
1051 | },
1052 | "cliui": {
1053 | "version": "7.0.4",
1054 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
1055 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
1056 | "dev": true,
1057 | "requires": {
1058 | "string-width": "^4.2.0",
1059 | "strip-ansi": "^6.0.0",
1060 | "wrap-ansi": "^7.0.0"
1061 | }
1062 | },
1063 | "color-convert": {
1064 | "version": "2.0.1",
1065 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
1066 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
1067 | "dev": true,
1068 | "requires": {
1069 | "color-name": "~1.1.4"
1070 | }
1071 | },
1072 | "color-name": {
1073 | "version": "1.1.4",
1074 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
1075 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
1076 | "dev": true
1077 | },
1078 | "concat-map": {
1079 | "version": "0.0.1",
1080 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
1081 | "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
1082 | "dev": true
1083 | },
1084 | "debug": {
1085 | "version": "4.3.4",
1086 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
1087 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
1088 | "dev": true,
1089 | "requires": {
1090 | "ms": "2.1.2"
1091 | },
1092 | "dependencies": {
1093 | "ms": {
1094 | "version": "2.1.2",
1095 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
1096 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
1097 | "dev": true
1098 | }
1099 | }
1100 | },
1101 | "decamelize": {
1102 | "version": "4.0.0",
1103 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
1104 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
1105 | "dev": true
1106 | },
1107 | "diff": {
1108 | "version": "5.0.0",
1109 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz",
1110 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==",
1111 | "dev": true
1112 | },
1113 | "emoji-regex": {
1114 | "version": "8.0.0",
1115 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
1116 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
1117 | "dev": true
1118 | },
1119 | "escalade": {
1120 | "version": "3.1.1",
1121 | "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
1122 | "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
1123 | "dev": true
1124 | },
1125 | "escape-string-regexp": {
1126 | "version": "4.0.0",
1127 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
1128 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
1129 | "dev": true
1130 | },
1131 | "expect.js": {
1132 | "version": "0.2.0",
1133 | "resolved": "https://registry.npmjs.org/expect.js/-/expect.js-0.2.0.tgz",
1134 | "integrity": "sha512-Si9lyFUkFCY9nTSKocf/Im/knEJNHUgbEWCNpRqiM5J2w+0YPxalJo0aomfh4WxlQiZ6kG97cZlN2UhAVxPAsA==",
1135 | "dev": true
1136 | },
1137 | "fill-range": {
1138 | "version": "7.0.1",
1139 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
1140 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
1141 | "dev": true,
1142 | "requires": {
1143 | "to-regex-range": "^5.0.1"
1144 | }
1145 | },
1146 | "find-up": {
1147 | "version": "5.0.0",
1148 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
1149 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
1150 | "dev": true,
1151 | "requires": {
1152 | "locate-path": "^6.0.0",
1153 | "path-exists": "^4.0.0"
1154 | }
1155 | },
1156 | "flat": {
1157 | "version": "5.0.2",
1158 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
1159 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
1160 | "dev": true
1161 | },
1162 | "fs.realpath": {
1163 | "version": "1.0.0",
1164 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
1165 | "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
1166 | "dev": true
1167 | },
1168 | "fsevents": {
1169 | "version": "2.3.2",
1170 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
1171 | "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
1172 | "dev": true,
1173 | "optional": true
1174 | },
1175 | "get-caller-file": {
1176 | "version": "2.0.5",
1177 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
1178 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
1179 | "dev": true
1180 | },
1181 | "glob": {
1182 | "version": "7.2.0",
1183 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
1184 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
1185 | "dev": true,
1186 | "requires": {
1187 | "fs.realpath": "^1.0.0",
1188 | "inflight": "^1.0.4",
1189 | "inherits": "2",
1190 | "minimatch": "^3.0.4",
1191 | "once": "^1.3.0",
1192 | "path-is-absolute": "^1.0.0"
1193 | },
1194 | "dependencies": {
1195 | "brace-expansion": {
1196 | "version": "1.1.11",
1197 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
1198 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
1199 | "dev": true,
1200 | "requires": {
1201 | "balanced-match": "^1.0.0",
1202 | "concat-map": "0.0.1"
1203 | }
1204 | },
1205 | "minimatch": {
1206 | "version": "3.1.2",
1207 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
1208 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
1209 | "dev": true,
1210 | "requires": {
1211 | "brace-expansion": "^1.1.7"
1212 | }
1213 | }
1214 | }
1215 | },
1216 | "glob-parent": {
1217 | "version": "5.1.2",
1218 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
1219 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
1220 | "dev": true,
1221 | "requires": {
1222 | "is-glob": "^4.0.1"
1223 | }
1224 | },
1225 | "has-flag": {
1226 | "version": "4.0.0",
1227 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
1228 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
1229 | "dev": true
1230 | },
1231 | "he": {
1232 | "version": "1.2.0",
1233 | "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
1234 | "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
1235 | "dev": true
1236 | },
1237 | "inflight": {
1238 | "version": "1.0.6",
1239 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
1240 | "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
1241 | "dev": true,
1242 | "requires": {
1243 | "once": "^1.3.0",
1244 | "wrappy": "1"
1245 | }
1246 | },
1247 | "inherits": {
1248 | "version": "2.0.4",
1249 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
1250 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
1251 | "dev": true
1252 | },
1253 | "is-binary-path": {
1254 | "version": "2.1.0",
1255 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
1256 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
1257 | "dev": true,
1258 | "requires": {
1259 | "binary-extensions": "^2.0.0"
1260 | }
1261 | },
1262 | "is-extglob": {
1263 | "version": "2.1.1",
1264 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
1265 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
1266 | "dev": true
1267 | },
1268 | "is-fullwidth-code-point": {
1269 | "version": "3.0.0",
1270 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
1271 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
1272 | "dev": true
1273 | },
1274 | "is-glob": {
1275 | "version": "4.0.3",
1276 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
1277 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
1278 | "dev": true,
1279 | "requires": {
1280 | "is-extglob": "^2.1.1"
1281 | }
1282 | },
1283 | "is-number": {
1284 | "version": "7.0.0",
1285 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
1286 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
1287 | "dev": true
1288 | },
1289 | "is-plain-obj": {
1290 | "version": "2.1.0",
1291 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
1292 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
1293 | "dev": true
1294 | },
1295 | "is-unicode-supported": {
1296 | "version": "0.1.0",
1297 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
1298 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
1299 | "dev": true
1300 | },
1301 | "js-yaml": {
1302 | "version": "4.1.0",
1303 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
1304 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
1305 | "dev": true,
1306 | "requires": {
1307 | "argparse": "^2.0.1"
1308 | }
1309 | },
1310 | "locate-path": {
1311 | "version": "6.0.0",
1312 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
1313 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
1314 | "dev": true,
1315 | "requires": {
1316 | "p-locate": "^5.0.0"
1317 | }
1318 | },
1319 | "log-symbols": {
1320 | "version": "4.1.0",
1321 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
1322 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
1323 | "dev": true,
1324 | "requires": {
1325 | "chalk": "^4.1.0",
1326 | "is-unicode-supported": "^0.1.0"
1327 | }
1328 | },
1329 | "minimatch": {
1330 | "version": "5.0.1",
1331 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz",
1332 | "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==",
1333 | "dev": true,
1334 | "requires": {
1335 | "brace-expansion": "^2.0.1"
1336 | }
1337 | },
1338 | "mocha": {
1339 | "version": "10.0.0",
1340 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.0.0.tgz",
1341 | "integrity": "sha512-0Wl+elVUD43Y0BqPZBzZt8Tnkw9CMUdNYnUsTfOM1vuhJVZL+kiesFYsqwBkEEuEixaiPe5ZQdqDgX2jddhmoA==",
1342 | "dev": true,
1343 | "requires": {
1344 | "@ungap/promise-all-settled": "1.1.2",
1345 | "ansi-colors": "4.1.1",
1346 | "browser-stdout": "1.3.1",
1347 | "chokidar": "3.5.3",
1348 | "debug": "4.3.4",
1349 | "diff": "5.0.0",
1350 | "escape-string-regexp": "4.0.0",
1351 | "find-up": "5.0.0",
1352 | "glob": "7.2.0",
1353 | "he": "1.2.0",
1354 | "js-yaml": "4.1.0",
1355 | "log-symbols": "4.1.0",
1356 | "minimatch": "5.0.1",
1357 | "ms": "2.1.3",
1358 | "nanoid": "3.3.3",
1359 | "serialize-javascript": "6.0.0",
1360 | "strip-json-comments": "3.1.1",
1361 | "supports-color": "8.1.1",
1362 | "workerpool": "6.2.1",
1363 | "yargs": "16.2.0",
1364 | "yargs-parser": "20.2.4",
1365 | "yargs-unparser": "2.0.0"
1366 | }
1367 | },
1368 | "ms": {
1369 | "version": "2.1.3",
1370 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
1371 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
1372 | "dev": true
1373 | },
1374 | "nanoid": {
1375 | "version": "3.3.3",
1376 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz",
1377 | "integrity": "sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==",
1378 | "dev": true
1379 | },
1380 | "normalize-path": {
1381 | "version": "3.0.0",
1382 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
1383 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
1384 | "dev": true
1385 | },
1386 | "once": {
1387 | "version": "1.4.0",
1388 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
1389 | "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
1390 | "dev": true,
1391 | "requires": {
1392 | "wrappy": "1"
1393 | }
1394 | },
1395 | "p-limit": {
1396 | "version": "3.1.0",
1397 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
1398 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
1399 | "dev": true,
1400 | "requires": {
1401 | "yocto-queue": "^0.1.0"
1402 | }
1403 | },
1404 | "p-locate": {
1405 | "version": "5.0.0",
1406 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
1407 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
1408 | "dev": true,
1409 | "requires": {
1410 | "p-limit": "^3.0.2"
1411 | }
1412 | },
1413 | "path-exists": {
1414 | "version": "4.0.0",
1415 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
1416 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
1417 | "dev": true
1418 | },
1419 | "path-is-absolute": {
1420 | "version": "1.0.1",
1421 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
1422 | "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
1423 | "dev": true
1424 | },
1425 | "picomatch": {
1426 | "version": "2.3.1",
1427 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
1428 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
1429 | "dev": true
1430 | },
1431 | "randombytes": {
1432 | "version": "2.1.0",
1433 | "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
1434 | "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
1435 | "dev": true,
1436 | "requires": {
1437 | "safe-buffer": "^5.1.0"
1438 | }
1439 | },
1440 | "readdirp": {
1441 | "version": "3.6.0",
1442 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
1443 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
1444 | "dev": true,
1445 | "requires": {
1446 | "picomatch": "^2.2.1"
1447 | }
1448 | },
1449 | "require-directory": {
1450 | "version": "2.1.1",
1451 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
1452 | "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
1453 | "dev": true
1454 | },
1455 | "safe-buffer": {
1456 | "version": "5.2.1",
1457 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
1458 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
1459 | "dev": true
1460 | },
1461 | "serialize-javascript": {
1462 | "version": "6.0.0",
1463 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz",
1464 | "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==",
1465 | "dev": true,
1466 | "requires": {
1467 | "randombytes": "^2.1.0"
1468 | }
1469 | },
1470 | "string-width": {
1471 | "version": "4.2.3",
1472 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
1473 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
1474 | "dev": true,
1475 | "requires": {
1476 | "emoji-regex": "^8.0.0",
1477 | "is-fullwidth-code-point": "^3.0.0",
1478 | "strip-ansi": "^6.0.1"
1479 | }
1480 | },
1481 | "strip-ansi": {
1482 | "version": "6.0.1",
1483 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
1484 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
1485 | "dev": true,
1486 | "requires": {
1487 | "ansi-regex": "^5.0.1"
1488 | }
1489 | },
1490 | "strip-json-comments": {
1491 | "version": "3.1.1",
1492 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
1493 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
1494 | "dev": true
1495 | },
1496 | "supports-color": {
1497 | "version": "8.1.1",
1498 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
1499 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
1500 | "dev": true,
1501 | "requires": {
1502 | "has-flag": "^4.0.0"
1503 | }
1504 | },
1505 | "to-regex-range": {
1506 | "version": "5.0.1",
1507 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
1508 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
1509 | "dev": true,
1510 | "requires": {
1511 | "is-number": "^7.0.0"
1512 | }
1513 | },
1514 | "workerpool": {
1515 | "version": "6.2.1",
1516 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz",
1517 | "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==",
1518 | "dev": true
1519 | },
1520 | "wrap-ansi": {
1521 | "version": "7.0.0",
1522 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
1523 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
1524 | "dev": true,
1525 | "requires": {
1526 | "ansi-styles": "^4.0.0",
1527 | "string-width": "^4.1.0",
1528 | "strip-ansi": "^6.0.0"
1529 | }
1530 | },
1531 | "wrappy": {
1532 | "version": "1.0.2",
1533 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
1534 | "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
1535 | "dev": true
1536 | },
1537 | "y18n": {
1538 | "version": "5.0.8",
1539 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
1540 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
1541 | "dev": true
1542 | },
1543 | "yargs": {
1544 | "version": "16.2.0",
1545 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
1546 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
1547 | "dev": true,
1548 | "requires": {
1549 | "cliui": "^7.0.2",
1550 | "escalade": "^3.1.1",
1551 | "get-caller-file": "^2.0.5",
1552 | "require-directory": "^2.1.1",
1553 | "string-width": "^4.2.0",
1554 | "y18n": "^5.0.5",
1555 | "yargs-parser": "^20.2.2"
1556 | }
1557 | },
1558 | "yargs-parser": {
1559 | "version": "20.2.4",
1560 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.4.tgz",
1561 | "integrity": "sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA==",
1562 | "dev": true
1563 | },
1564 | "yargs-unparser": {
1565 | "version": "2.0.0",
1566 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
1567 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
1568 | "dev": true,
1569 | "requires": {
1570 | "camelcase": "^6.0.0",
1571 | "decamelize": "^4.0.0",
1572 | "flat": "^5.0.2",
1573 | "is-plain-obj": "^2.1.0"
1574 | }
1575 | },
1576 | "yocto-queue": {
1577 | "version": "0.1.0",
1578 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
1579 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
1580 | "dev": true
1581 | }
1582 | }
1583 | }
1584 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "author": "Bram Stein (http://www.bramstein.com/)",
3 | "name": "characterset",
4 | "description": "A library for working with Unicode character sets",
5 | "keywords": [
6 | "unicode",
7 | "utf16",
8 | "characterset",
9 | "character set",
10 | "surrogate pair"
11 | ],
12 | "type": "module",
13 | "version": "2.0.0",
14 | "repository": {
15 | "url": "https://github.com/bramstein/characterset.git"
16 | },
17 | "scripts": {
18 | "test": "mocha --reporter spec"
19 | },
20 | "main": "./lib/characterset.js",
21 | "devDependencies": {
22 | "expect.js": "0.2.0",
23 | "mocha": "^10.0.0"
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/test/characterset-test.js:
--------------------------------------------------------------------------------
1 | import CharacterSet from '../lib/characterset.js';
2 | import expect from 'expect.js';
3 |
4 | describe('CharacterSet', function () {
5 | describe('#constructor', function () {
6 | it('should create a CharacterSet instance that is empty', function () {
7 | var cs = new CharacterSet();
8 |
9 | expect(cs).not.to.be(null);
10 | expect(cs.data).to.be.empty();
11 | });
12 |
13 | it('should create a CharacterSet instance with a single code point', function () {
14 | var cs = new CharacterSet(1);
15 |
16 | expect(cs).not.to.be(null);
17 | expect(cs.data).to.eql({1: true});
18 | });
19 |
20 | it('should create a CharacterSet instance from an ASCII string', function () {
21 | var cs = new CharacterSet('abc');
22 |
23 | expect(cs).not.to.be(null);
24 | expect(cs.data).to.eql({
25 | 97: true,
26 | 98: true,
27 | 99: true
28 | });
29 | });
30 |
31 | it('should create a CharacterSet instance from a BMP string', function () {
32 | var cs = new CharacterSet('中国');
33 |
34 | expect(cs).not.to.be(null);
35 | expect(cs.data).to.eql({
36 | 20013: true,
37 | 22269: true
38 | });
39 | });
40 |
41 | it('should create a CharacterSet instance from a string containing surrogate pairs', function () {
42 | var cs = new CharacterSet('a\uD834\uDF06bc');
43 |
44 | expect(cs).not.to.be(null);
45 | expect(cs.data).to.eql({
46 | 97: true,
47 | 98: true,
48 | 99: true,
49 | 119558: true
50 | });
51 | });
52 |
53 | it('should create a CharacterSet from a range', function () {
54 | var cs = new CharacterSet([1, 2]);
55 |
56 | expect(cs).not.to.be(null);
57 | expect(cs.data).to.eql({
58 | 1: true,
59 | 2: true
60 | });
61 | });
62 |
63 | it('should create a CharacterSet from a compressed range', function () {
64 | var cs = new CharacterSet([1, [3, 5], 6]);
65 |
66 | expect(cs).not.to.be(null);
67 | expect(cs.data).to.eql({
68 | 1: true,
69 | 3: true,
70 | 4: true,
71 | 5: true,
72 | 6: true
73 | });
74 | });
75 | });
76 |
77 | describe('#getSize', function () {
78 | it('should return zero on an empty character set', function () {
79 | var cs = new CharacterSet();
80 |
81 | expect(cs.getSize()).to.eql(0);
82 | });
83 |
84 | it('should return the correct size with single code points', function () {
85 | var cs = new CharacterSet([1, 2]);
86 |
87 | expect(cs.getSize()).to.eql(2);
88 | });
89 |
90 | it('should return the correct size with ranges', function () {
91 | var cs = new CharacterSet([[1, 5]]);
92 |
93 | expect(cs.getSize()).to.eql(5);
94 | });
95 |
96 | it('should return the correct size for a string', function () {
97 | var cs = new CharacterSet('hello world');
98 |
99 | expect(cs.getSize()).to.eql(8);
100 | });
101 |
102 | it('should return the correct size with surrogate pairs', function () {
103 | var cs = new CharacterSet('\uD834\uDF06');
104 |
105 | expect(cs.getSize()).to.eql(1);
106 | });
107 |
108 | it('should maintain the correct size when removing code points', function () {
109 | var cs = new CharacterSet([1, 2, 3]);
110 |
111 | expect(cs.getSize()).to.eql(3);
112 |
113 | cs.remove(3);
114 | expect(cs.getSize()).to.eql(2);
115 | });
116 |
117 | it('should maintain the correct size when adding code points', function () {
118 | var cs = new CharacterSet();
119 |
120 | expect(cs.getSize()).to.eql(0);
121 |
122 | cs.add(1);
123 | expect(cs.getSize()).to.eql(1);
124 | });
125 | });
126 |
127 | describe('#equals', function () {
128 | it('should consider two empty character sets equal', function () {
129 | var a = new CharacterSet(),
130 | b = new CharacterSet();
131 |
132 | expect(a.equals(b)).to.be(true);
133 | expect(b.equals(a)).to.be(true);
134 | });
135 |
136 | it('should consider two identical non-empty character sets equal', function () {
137 | var a = new CharacterSet(200),
138 | b = new CharacterSet(200);
139 |
140 | expect(a.equals(b)).to.be(true);
141 | expect(b.equals(a)).to.be(true);
142 | });
143 |
144 | it('should consider two different character sets to be unequal', function () {
145 | var a = new CharacterSet(200),
146 | b = new CharacterSet(404);
147 |
148 | expect(a.equals(b)).to.be(false);
149 | expect(b.equals(a)).to.be(false);
150 | });
151 | });
152 |
153 | describe('#expandRange', function () {
154 | it('should not expand non ranges', function () {
155 | var cs = new CharacterSet();
156 |
157 | expect(cs.expandRange([1, 2, 3])).to.eql([1, 2, 3]);
158 | });
159 |
160 | it('should expand a single range', function () {
161 | var cs = new CharacterSet();
162 |
163 | expect(cs.expandRange([[1, 4]])).to.eql([1, 2, 3, 4]);
164 | });
165 |
166 | it('should expand multiple ranges', function () {
167 | var cs = new CharacterSet();
168 |
169 | expect(cs.expandRange([[1, 4], [5, 8]])).to.eql([1, 2, 3, 4, 5, 6, 7, 8]);
170 | });
171 |
172 | it('should expand ranges and non ranges', function () {
173 | var cs = new CharacterSet();
174 |
175 | expect(cs.expandRange([[1, 2], 3, 4, [5, 8]])).to.eql([1, 2, 3, 4, 5, 6, 7, 8]);
176 | });
177 | });
178 |
179 | describe('#compressRange', function () {
180 | it('should not compress non continuous code points', function () {
181 | var cs = new CharacterSet();
182 |
183 | expect(cs.compressRange([1, 3, 5])).to.eql([1, 3, 5]);
184 | });
185 |
186 | it('should compress a single range', function () {
187 | var cs = new CharacterSet();
188 |
189 | expect(cs.compressRange([1, 2, 3])).to.eql([[1,3]]);
190 | });
191 |
192 | it('should not compress a range only consisting of two code points', function () {
193 | var cs = new CharacterSet();
194 |
195 | expect(cs.compressRange([1, 2])).to.eql([1, 2]);
196 | });
197 |
198 | it('should compress multiple ranges', function () {
199 | var cs = new CharacterSet();
200 |
201 | expect(cs.compressRange([1, 2, 3, 5, 6, 7])).to.eql([[1, 3], [5, 7]]);
202 | });
203 |
204 | it('should compress multiple ranges and single code points', function () {
205 | var cs = new CharacterSet();
206 |
207 | expect(cs.compressRange([1, 2, 3, 5, 7, 8, 9, 11])).to.eql([[1, 3], 5, [7, 9], 11]);
208 | });
209 | });
210 |
211 | describe('#toArray', function () {
212 | it('should return the correct code points', function () {
213 | var cs = new CharacterSet([1, 2]);
214 |
215 | expect(cs.toArray()).to.eql([1, 2]);
216 | });
217 |
218 | it('should return the correct code points in sorted order', function () {
219 | var cs = new CharacterSet([2, 1, 3, 0]);
220 |
221 | expect(cs.toArray()).to.eql([0, 1, 2, 3]);
222 | });
223 |
224 | it('should sort numerically instead of lexicographical', function () {
225 | var cs = new CharacterSet([7, 40, 300]);
226 |
227 | expect(cs.toArray()).to.eql([7, 40, 300]);
228 | });
229 | });
230 |
231 | describe('#toRange', function () {
232 | it('should return a range', function () {
233 | var cs = new CharacterSet([1, [2, 4], 5]);
234 |
235 | expect(cs.toRange()).to.eql([[1,5]]);
236 | });
237 | });
238 |
239 | describe('#isEmpty', function () {
240 | it('should return true when empty', function () {
241 | var cs = new CharacterSet();
242 |
243 | expect(cs.isEmpty()).to.be(true);
244 | });
245 |
246 | it('should return false when not empty', function () {
247 | var cs = new CharacterSet(119558);
248 |
249 | expect(cs.isEmpty()).to.be(false);
250 | });
251 | });
252 |
253 | describe('#add', function () {
254 | var cs = null;
255 |
256 | beforeEach(function () {
257 | cs = new CharacterSet();
258 | });
259 |
260 | it('should add a single code point', function () {
261 | cs.add(1);
262 |
263 | expect(cs.size).to.eql(1);
264 | expect(cs.data).to.eql({
265 | 1: true
266 | });
267 | });
268 |
269 | it('should add another code point', function () {
270 | cs.add(1);
271 | cs.add(2);
272 |
273 | expect(cs.size).to.eql(2);
274 | expect(cs.data).to.eql({
275 | 1: true,
276 | 2: true
277 | });
278 | });
279 |
280 | it('should not add the same code point twice', function () {
281 | cs.add(1);
282 | cs.add(2);
283 | cs.add(1);
284 |
285 | expect(cs.size).to.eql(2);
286 | expect(cs.data).to.eql({
287 | 1: true,
288 | 2: true
289 | });
290 | });
291 |
292 | it('should add multiple code points at the same time', function () {
293 | cs.add(1, 2);
294 |
295 | expect(cs.size).to.eql(2);
296 | expect(cs.data).to.eql({
297 | 1: true,
298 | 2: true
299 | });
300 | });
301 |
302 | it('should only add a single code point if they are the same', function () {
303 | cs.add(1, 1);
304 |
305 | expect(cs.size).to.eql(1);
306 | expect(cs.data).to.eql({
307 | 1: true
308 | });
309 | });
310 | });
311 |
312 | describe('#remove', function () {
313 | var cs = null;
314 |
315 | beforeEach(function () {
316 | cs = new CharacterSet([1, 2, 3, 4]);
317 | });
318 |
319 | it('should remove a single code point', function () {
320 | cs.remove(1);
321 |
322 | expect(cs.size).to.eql(3);
323 | expect(cs.data).to.eql({
324 | 1: false,
325 | 2: true,
326 | 3: true,
327 | 4: true
328 | });
329 | });
330 |
331 | it('should remove another code point', function () {
332 | cs.remove(1);
333 | cs.remove(2);
334 |
335 | expect(cs.size).to.eql(2);
336 | expect(cs.data).to.eql({
337 | 1: false,
338 | 2: false,
339 | 3: true,
340 | 4: true
341 | });
342 | });
343 |
344 | it('should not remove the same code point twice', function () {
345 | cs.remove(1);
346 | cs.remove(2);
347 |
348 | expect(cs.size).to.eql(2);
349 | expect(cs.data).to.eql({
350 | 1: false,
351 | 2: false,
352 | 3: true,
353 | 4: true
354 | });
355 | });
356 |
357 | it('should remove two code points at the same time', function () {
358 | cs.remove(1, 2);
359 |
360 | expect(cs.size).to.eql(2);
361 | expect(cs.data).to.eql({
362 | 1: false,
363 | 2: false,
364 | 3: true,
365 | 4: true
366 | });
367 | });
368 | });
369 |
370 | describe('encodeCodePoint', function () {
371 | var characterSet = null;
372 |
373 | beforeEach(function () {
374 | characterSet = new CharacterSet();
375 | });
376 |
377 | it('should encode ASCII safe characters as themselves', function () {
378 | expect(characterSet.encodeCodePoint(65)).to.eql('A');
379 | expect(characterSet.encodeCodePoint(57)).to.eql('9');
380 | expect(characterSet.encodeCodePoint(97)).to.eql('a');
381 | });
382 |
383 | it('should encode ASCII unsafe code points encoded', function () {
384 | expect(characterSet.encodeCodePoint(0)).to.eql('\\u0000');
385 | expect(characterSet.encodeCodePoint(36)).to.eql('\\u0024');
386 | expect(characterSet.encodeCodePoint(62)).to.eql('\\u003E');
387 | expect(characterSet.encodeCodePoint(127)).to.eql('\\u007F');
388 | });
389 |
390 | it('should always encode code points in the BMP that are not safe characters', function () {
391 | expect(characterSet.encodeCodePoint(20013)).to.eql('\\u4E2D');
392 | expect(characterSet.encodeCodePoint(22269)).to.eql('\\u56FD');
393 | });
394 |
395 | it('should encode code points outside the BMP as surrogate pairs', function () {
396 | expect(characterSet.encodeCodePoint(119558)).to.eql('\\uD834\\uDF06');
397 | });
398 | });
399 |
400 | describe('#toString', function () {
401 | it('should return ASCII as ASCII', function () {
402 | var cs = new CharacterSet('abc');
403 |
404 | expect(cs.toString()).to.eql('abc');
405 | });
406 |
407 | it('should not contain duplicates', function () {
408 | var cs = new CharacterSet('abcabc');
409 |
410 | expect(cs.toString()).to.eql('abc');
411 | });
412 |
413 | it('should encode characters inside the BMP as using hex escapes', function () {
414 | var cs = new CharacterSet([20013, 22269]);
415 |
416 | expect(cs.toString()).to.eql('\\u4E2D\\u56FD');
417 | });
418 |
419 | it('should encode characters outside the BMP as surrogate pairs', function () {
420 | var cs = new CharacterSet(119558);
421 |
422 | expect(cs.toString()).to.eql('\\uD834\\uDF06');
423 | });
424 | });
425 |
426 | describe('#toHexString', function () {
427 | it('should return hex', function () {
428 | var cs = new CharacterSet('abc');
429 |
430 | expect(cs.toHexString()).to.eql('U+61,U+62,U+63');
431 | });
432 |
433 | it('should not contain duplicates', function () {
434 | var cs = new CharacterSet('abcabc');
435 |
436 | expect(cs.toHexString()).to.eql('U+61,U+62,U+63');
437 | });
438 |
439 | it('should encode characters inside the BMP', function () {
440 | var cs = new CharacterSet([20013, 22269]);
441 |
442 | expect(cs.toHexString()).to.eql('U+4E2D,U+56FD');
443 | });
444 |
445 | it('should encode characters outside the BMP as a single codepoint', function () {
446 | var cs = new CharacterSet(119558);
447 |
448 | expect(cs.toHexString()).to.eql('U+1D306');
449 | });
450 | });
451 |
452 | describe('#toHexRangeString', function () {
453 | it('should return return hex', function () {
454 | var cs = new CharacterSet('ac');
455 |
456 | expect(cs.toHexRangeString()).to.eql('U+61,U+63');
457 | });
458 |
459 | it('should return a hex range', function () {
460 | var cs = new CharacterSet('abc');
461 |
462 | expect(cs.toHexRangeString()).to.eql('U+61-63');
463 | });
464 |
465 | it('should return a hex range and individual code points', function () {
466 | var cs = new CharacterSet('abch');
467 |
468 | expect(cs.toHexRangeString()).to.eql('U+61-63,U+68');
469 | });
470 |
471 | it('should return encoded ranges', function () {
472 | var cs = new CharacterSet([[127, 255]]);
473 |
474 | expect(cs.toHexRangeString()).to.eql('U+7F-FF');
475 | });
476 |
477 | it('should return encoded ranges outside the BMP', function () {
478 | var cs = new CharacterSet([[0x10000,0x10FFF]]);
479 |
480 | expect(cs.toHexRangeString()).to.eql('U+10000-10FFF');
481 | });
482 |
483 | it('should return range and single points', function () {
484 | var cs = new CharacterSet([1, [4, 7]]);
485 |
486 | expect(cs.toHexRangeString()).to.eql('U+1,U+4-7');
487 | });
488 | });
489 |
490 | describe('#toRangeString', function () {
491 | it('should return return ASCII as ASCII', function () {
492 | var cs = new CharacterSet('ac');
493 |
494 | expect(cs.toRangeString()).to.eql('[ac]');
495 | });
496 |
497 | it('should return ASCII ranges', function () {
498 | var cs = new CharacterSet('abc');
499 |
500 | expect(cs.toRangeString()).to.eql('[a-c]');
501 | });
502 |
503 | it('should return ASCII range and points', function () {
504 | var cs = new CharacterSet('abch');
505 |
506 | expect(cs.toRangeString()).to.eql('[a-ch]');
507 | });
508 |
509 | it('should return combined ASCII and encoded ranges', function () {
510 | var cs = new CharacterSet([[67, 127]]);
511 |
512 | expect(cs.toRangeString()).to.eql('[C-\\u007F]');
513 | });
514 |
515 | it('should return encoded ranges', function () {
516 | var cs = new CharacterSet([[127, 255]]);
517 |
518 | expect(cs.toRangeString()).to.eql('[\\u007F-\\u00FF]');
519 | });
520 |
521 | it('should return encoded ranges outside the BMP', function () {
522 | var cs = new CharacterSet([[0x10000,0x10FFF]]);
523 |
524 | expect(cs.toRangeString()).to.eql('[\\uD800\\uDC00-\\uD803\\uDFFF]');
525 | });
526 |
527 | it('should return range and single points', function () {
528 | var cs = new CharacterSet([1, [4, 7]]);
529 |
530 | expect(cs.toRangeString()).to.eql('[\\u0001\\u0004-\\u0007]');
531 | });
532 | });
533 |
534 | describe('#union', function () {
535 | it('should union two distinct character sets', function () {
536 | var a = new CharacterSet([1, 2]),
537 | b = new CharacterSet([3, 4]);
538 |
539 | expect(a.union(b).data).to.eql({
540 | 1: true,
541 | 2: true,
542 | 3: true,
543 | 4: true
544 | });
545 | });
546 |
547 | it('should union two overlapping character sets', function () {
548 | var a = new CharacterSet([1, 2, 3]),
549 | b = new CharacterSet([2, 3, 4]);
550 |
551 | expect(a.union(b).data).to.eql({
552 | 1: true,
553 | 2: true,
554 | 3: true,
555 | 4: true
556 | });
557 | });
558 | });
559 |
560 | describe('#intersection', function () {
561 | it('should not find any code points in common', function () {
562 | var a = new CharacterSet([1, 2]),
563 | b = new CharacterSet([3, 4]);
564 |
565 | expect(a.intersect(b).data).to.eql({});
566 | });
567 |
568 | it('should find code points in common', function () {
569 | var a = new CharacterSet([1, 2, 3]),
570 | b = new CharacterSet([2, 3, 4]);
571 |
572 | expect(a.intersect(b).data).to.eql({
573 | 2: true,
574 | 3: true
575 | });
576 | });
577 | });
578 |
579 | describe('#difference', function () {
580 | it('should return the same set if there are now common code points', function () {
581 | var a = new CharacterSet([1, 2]),
582 | b = new CharacterSet([3, 4]);
583 |
584 | expect(a.difference(b).data).to.eql({
585 | 1: true,
586 | 2: true
587 | });
588 | expect(b.difference(a).data).to.eql({
589 | 3: true,
590 | 4: true
591 | });
592 | expect(a.difference(a).data).to.eql({});
593 | });
594 |
595 | it('should only return those code points that are not in common', function () {
596 | var a = new CharacterSet([1, 2, 3]),
597 | b = new CharacterSet([2, 3, 4]);
598 |
599 | expect(a.difference(b).data).to.eql({
600 | 1: true
601 | });
602 | expect(b.difference(a).data).to.eql({
603 | 4: true
604 | });
605 | });
606 | });
607 |
608 | describe('#subset', function () {
609 | it('should consider an empty character set as a subset of any character set', function () {
610 | var a = new CharacterSet(),
611 | b = new CharacterSet([1, 2]);
612 |
613 | expect(a.subset(b)).to.be(true);
614 | expect(b.subset(a)).to.be(false);
615 | });
616 |
617 | it('should consider a character set a subset only if all its codepoints are present in another character set', function () {
618 | var a = new CharacterSet([1, 2]),
619 | b = new CharacterSet([1, 2, 3]);
620 |
621 | expect(a.subset(b)).to.be(true);
622 | expect(b.subset(a)).to.be(false);
623 | });
624 |
625 | it('should consider a character set a subset of itself', function () {
626 | var a = new CharacterSet([1, 2]);
627 |
628 | expect(a.subset(a)).to.be(true);
629 | });
630 | });
631 |
632 | describe('#toRegExp', function () {
633 | it('should build a regex for safe ASCII', function () {
634 | var cs = new CharacterSet(67);
635 |
636 | expect(cs.toRegExp()).to.eql('C');
637 | });
638 |
639 | it('should build a regex for a safe ASCII range', function () {
640 | var cs = new CharacterSet([[67,70]]);
641 |
642 | expect(cs.toRegExp()).to.eql('[C-F]');
643 | });
644 |
645 | it('should build a regex for ranges and points', function () {
646 | var cs = new CharacterSet([1, 3, [67, 70]]);
647 |
648 | expect(cs.toRegExp()).to.eql('[\\u0001\\u0003C-F]');
649 | });
650 |
651 | it('should build a regex for a range that crosses the BMP', function () {
652 | var cs = new CharacterSet([[65534, 65537]]);
653 |
654 | expect(cs.toRegExp()).to.eql('[\\uFFFE\\uFFFF]|\\uD800[\\uDC00\\uDC01]');
655 | });
656 |
657 | it('should build a regex for a code point outside the BMP', function () {
658 | var cs = new CharacterSet(119558);
659 |
660 | expect(cs.toRegExp()).to.eql('\\uD834\\uDF06');
661 | });
662 |
663 | it('should build a regex for a code point range outside the BMP', function () {
664 | var cs = new CharacterSet([[119558, 119638]]);
665 |
666 | expect(cs.toRegExp()).to.eql('\\uD834[\\uDF06-\\uDF56]');
667 | });
668 |
669 | it('should build a regex for a code point range and point outside the BMP', function () {
670 | var cs = new CharacterSet([119555, [119558, 119638]]);
671 | expect(cs.toRegExp()).to.eql('\\uD834[\\uDF03\\uDF06-\\uDF56]');
672 | });
673 |
674 | it('should build a regex for a code point range outside the BMP that spans multiple high surrogates', function () {
675 | var cs = new CharacterSet([[119558, 126980]]);
676 |
677 | expect(cs.toRegExp()).to.eql('\\uD834[\\uDF06-\\uDFFF]|[\\uD835-\\uD83B][\\uDC00-\\uDFFF]|\\uD83C[\\uDC00-\\uDC04]');
678 | });
679 | });
680 |
681 | describe('parseUnicodeRange', function () {
682 | it('parses an empty string', function () {
683 | var cs = CharacterSet.parseUnicodeRange('');
684 |
685 | expect(cs.size).to.eql(0);
686 | expect(cs.data).to.eql({});
687 | });
688 |
689 | it('parses a single value', function () {
690 | var cs = CharacterSet.parseUnicodeRange('u+23,U+23');
691 |
692 | expect(cs.size).to.eql(1);
693 | expect(cs.data).to.eql({
694 | 35: true
695 | });
696 | });
697 |
698 | it('parses multiple values', function () {
699 | var cs = CharacterSet.parseUnicodeRange('u+23, u+22');
700 |
701 | expect(cs.size).to.eql(2);
702 | expect(cs.data).to.eql({
703 | 34: true,
704 | 35: true
705 | });
706 | });
707 |
708 | it('parses ranges', function () {
709 | var cs = CharacterSet.parseUnicodeRange('u+22-25');
710 |
711 | expect(cs.size).to.eql(4);
712 | expect(cs.data).to.eql({
713 | 34: true,
714 | 35: true,
715 | 36: true,
716 | 37: true
717 | });
718 | });
719 |
720 | it('parses multiple ranges', function () {
721 | var cs = CharacterSet.parseUnicodeRange('u+22-24, u+25-28');
722 |
723 | expect(cs.data).to.eql({
724 | 34: true,
725 | 35: true,
726 | 36: true,
727 | 37: true,
728 | 38: true,
729 | 39: true,
730 | 40: true
731 | });
732 | });
733 |
734 | it('parses wildcards', function () {
735 | var cs = CharacterSet.parseUnicodeRange('u+1?');
736 |
737 | expect(cs.data).to.eql({
738 | 16: true,
739 | 17: true,
740 | 18: true,
741 | 19: true,
742 | 20: true,
743 | 21: true,
744 | 22: true,
745 | 23: true,
746 | 24: true,
747 | 25: true,
748 | 26: true,
749 | 27: true,
750 | 28: true,
751 | 29: true,
752 | 30: true,
753 | 31: true
754 | });
755 | });
756 | });
757 | });
758 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CharacterSet tests
6 |
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
20 |
21 |
24 |
25 |
26 |
--------------------------------------------------------------------------------