├── 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 | --------------------------------------------------------------------------------