├── .gitignore ├── .travis.yml ├── CODE_OF_CONDUCT.md ├── docs ├── api-reference.md └── tutorial.md ├── main.mjs ├── package-lock.json ├── package.json ├── readme.md ├── src ├── context-with-holes.mjs ├── context.mjs ├── lang.mjs ├── outcome.mjs ├── parser.mjs └── state-context.mjs └── test ├── snapshots ├── test-lexer.js.md └── test-lexer.js.snap ├── test-context-with-holes.js ├── test-lang.js ├── test-lexer.js └── test-parser.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '10' 4 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies within all project spaces, and it also applies when 49 | an individual is representing the project or its community in public spaces. 50 | Examples of representing a project or community include using an official 51 | project e-mail address, posting via an official social media account, or acting 52 | as an appointed representative at an online or offline event. Representation of 53 | a project may be further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at tim@disnet.me. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | 78 | -------------------------------------------------------------------------------- /docs/api-reference.md: -------------------------------------------------------------------------------- 1 | # API Reference 2 | 3 | - [Parser](#Parser) 4 | - [new Parser()](#constructor) 5 | - [Parser#parse](#parse) 6 | - [Parser#tryParse](#tryParse) 7 | - [Parser.of](#par-of) 8 | - [Parser.zero](#zero) 9 | - [Parser.failure](#failure) 10 | - [Parser#map](#map) 11 | - [Parser#ap](#ap) 12 | - [Parser#chain](#chain) 13 | - [Parser#or](#or) 14 | - [Parser#alt](#alt) 15 | - [Parser#then](#then) 16 | - [Parser#skip](#skip) 17 | - [Parser#result](#result) 18 | - [Parser#many](#many) 19 | - [Parser#atLeast](#atLeast) 20 | - [Parser#atMost](#atMost) 21 | - [Parser#times](#times) 22 | - [Parser#tie](#tie) 23 | - [Operators](#Operators) 24 | - [succeed](#succeed) 25 | - [empty](#empty) 26 | - [item](#item) 27 | - [satisfy](#satisfy) 28 | - [char](#char) 29 | - [string](#string) 30 | - [regex](#regex) 31 | - [sequence](#sequence) 32 | - [alternatives](#alternatives) 33 | - [Types](#Types) 34 | - [Outcome](#Outcome) 35 | - [Outcome.of](#outcome-of) 36 | - [Outcome#map](#outcome-map) 37 | - [Outcome#chain](#outcome-chain) 38 | - [Outcome#forEach](#forEach) 39 | - [Context](#context) 40 | - [ParseResult](#ParseResult) 41 | 42 | ## Parser 43 | 44 | ```js 45 | import Parser from 'parser-lang'; 46 | ``` 47 | 48 | The `Parser` is the primary class in ParserLang. A `Parser` is a wrapper around a function that does the parsing along with a variety of methods for combining the `Parser` instance with other `Parser`s. 49 | 50 | ### `constructor` 51 | 52 | ``` 53 | Parser(action: Context => Outcome>) 54 | ``` 55 | 56 | A `Parser` is constructed by giving it a function that takes a `Context` to consume and returns an `Outcome` of a `ParseResult`. 57 | 58 | An `Outcome` represents a `Success` or a `Failure` (for those coming from a functional background this is the `Either` type just with more clear names). 59 | 60 | A `ParseResult` is an object of shape `{ value, ctx }` that holds the resulting value along with the new `Context`. 61 | 62 | ```js 63 | import { Outcome } from 'parser-lang'; 64 | 65 | let p = new Parser(ctx => { 66 | return Outcome.of({ 67 | value: true, 68 | ctx, 69 | }); 70 | }); 71 | ``` 72 | 73 | ### `parse` 74 | 75 | ``` 76 | Parser#parse( 77 | ctx: string | Array | Iterable | Context 78 | ): Outcome> 79 | ``` 80 | 81 | Runs the wrapped `action` by first converting `ctx` to a `Context`. 82 | 83 | ### `tryParse` 84 | 85 | ``` 86 | Parser#tryParse( 87 | ctx: string | Array | Iterable | Context 88 | ): A 89 | ``` 90 | 91 | Runs the wrapped `action` by first converting `ctx` to a `Context` and then return its value (unwrapping the value from the `Outcome` and `ParseResult`). If the `action` returns a `Failure` outcome throws an `Error`. 92 | 93 | ```js 94 | Parser.failure('fail').tryParse(''); 95 | // throws Error('fail') 96 | ``` 97 | 98 | ### `of` 99 | 100 | ``` 101 | Parser.of(value: A): Parser 102 | ``` 103 | 104 | Returns a parser that consumes nothing from the context and succeeds with `value`. 105 | 106 | ```js 107 | Parser.of(42).tryParse('123'); 108 | // 42 109 | ``` 110 | 111 | ### `zero` 112 | 113 | ``` 114 | Parser.zero(): Parser<> 115 | ``` 116 | 117 | Returns a parser that always results in a `Failure` outcome. 118 | 119 | ```js 120 | Parser.zero().tryParse(''); 121 | // throws Error 122 | ``` 123 | 124 | ### `failure` 125 | 126 | ``` 127 | Parser.failure(msg: string): Parser<> 128 | ``` 129 | 130 | Returns a parser that always results in a `Failure` outcome with `msg` as the failure message. 131 | 132 | ```js 133 | Parser.failure('a message').tryParse(''); 134 | // throws Error('a message') 135 | ``` 136 | 137 | ### `map` 138 | 139 | ``` 140 | Parser#map(f: A => B): Parser 141 | ``` 142 | 143 | Returns a parser that runs the first parser and then applies `f` to the resulting value. 144 | 145 | ```js 146 | Parser.of(2) 147 | .map(n => n * 10) 148 | .tryParse(''); 149 | // 20 150 | ``` 151 | 152 | ### `ap` 153 | 154 | ``` 155 | Parser#ap( 156 | parser: Parser B> 157 | ): Parser 158 | ``` 159 | 160 | Returns a parser that runs the first parser and then runs `parser` to get the function `A => B` to apply to the result of the first parser. 161 | 162 | ### `chain` 163 | 164 | ``` 165 | Parser#chain( 166 | f: A => Parser 167 | ): Parser 168 | ``` 169 | 170 | Returns a parser that runs the first parser and then applies the value to `f` and returns the resulting parser. 171 | 172 | ### `or` 173 | 174 | ``` 175 | Parser#or( 176 | other: Parser 177 | ): Parser 178 | ``` 179 | 180 | Returns a parser that runs the first parser and if it results in a failure runs `other`. 181 | 182 | ```js 183 | Parser.zero() 184 | .or(Parser.of(1)) 185 | .tryParse(''); 186 | // 1 187 | ``` 188 | 189 | ### `alt` 190 | 191 | Alias for `or`. 192 | 193 | ### `then` 194 | 195 | ``` 196 | Parser#then( 197 | other: Parser 198 | ): Parser 199 | ``` 200 | 201 | Returns a parser that runs the first parser and then the second parser and returns the result of the second parser. 202 | 203 | ```js 204 | Parser.of(1) 205 | .then(Parser.of(2)) 206 | .tryParse(''); 207 | // 2 208 | ``` 209 | 210 | ### `skip` 211 | 212 | ``` 213 | Parser#skip( 214 | other: Parser 215 | ): Parser 216 | ``` 217 | 218 | Returns a parser that runs the first parser and then the second parser and returns the result of the first parser. 219 | 220 | ```js 221 | Parser.of(1) 222 | .skip(Parser.of(2)) 223 | .tryParse(''); 224 | // 1 225 | ``` 226 | 227 | ### `result` 228 | 229 | ``` 230 | Parser#result( 231 | value: B 232 | ): Parser 233 | ``` 234 | 235 | Returns a parser that runs the first parser and then uses `value` as the result. 236 | 237 | ```js 238 | Parser.of(1) 239 | .result('a') 240 | .tryParse(''); 241 | // 'a' 242 | ``` 243 | 244 | ### `many` 245 | 246 | ``` 247 | Parser#many(): Parser 248 | ``` 249 | 250 | Returns a parser that matches this parser zero or more times and records the matched values in an array. 251 | 252 | ```js 253 | import { char } from 'parser-lang'; 254 | 255 | char('a') 256 | .many() 257 | .tryParse('aaa'); 258 | // ['a', 'a', 'a' ] 259 | char('a') 260 | .many() 261 | .tryParse('bbb'); 262 | // [] 263 | ``` 264 | 265 | ### `atLeast` 266 | 267 | ``` 268 | Parser#atLeast(n: number): Parser 269 | ``` 270 | 271 | Returns a parser that matches this parser at least `n` times and records the matched values in an array. 272 | 273 | ```js 274 | import { char } from 'parser-lang'; 275 | 276 | char('a') 277 | .atLeast(1) 278 | .tryParse('aaa'); 279 | // ['a', 'a', 'a' ] 280 | char('a') 281 | .atLeast(1) 282 | .tryParse('bbb'); 283 | // throw Error 284 | ``` 285 | 286 | ### `atMost` 287 | 288 | ``` 289 | Parser#atMost(n: number): Parser 290 | ``` 291 | 292 | Returns a parser that matches this parser at most `n` times and records the matched values in an array. 293 | 294 | ```js 295 | import { char } from 'parser-lang'; 296 | 297 | char('a') 298 | .atMost(5) 299 | .tryParse('aaa'); 300 | // ['a', 'a', 'a' ] 301 | char('a') 302 | .atMost(1) 303 | .tryParse('bbb'); 304 | // [] 305 | char('a') 306 | .atMost(1) 307 | .tryParse('aaa'); 308 | // throw Error 309 | ``` 310 | 311 | ### `times` 312 | 313 | ``` 314 | Parser#times(n: number, max: number = n): Parser 315 | ``` 316 | 317 | Returns a parser that matches this parser at least `n` but no more than `max` times and records the matched values in an array. 318 | 319 | ```js 320 | import { char } from 'parser-lang'; 321 | 322 | char('a') 323 | .times(3) 324 | .tryParse('aaa'); 325 | // ['a', 'a', 'a' ] 326 | char('a') 327 | .times(1, 3) 328 | .tryParse('aa'); 329 | // ['a', 'a'] 330 | char('a') 331 | .times(1) 332 | .tryParse('bbb'); 333 | // throw Error 334 | ``` 335 | 336 | ### `tie` 337 | 338 | ``` 339 | Parser#tie( 340 | sep: string = '' 341 | ): Parser 342 | ``` 343 | 344 | Returns a parser that runs the first parser and then joins the resulting array by `sep`. 345 | 346 | ```js 347 | Parser.of(['a', 'b', 'c']) 348 | .tie() 349 | .tryParse(''); 350 | // 'abc' 351 | ``` 352 | 353 | ## Operators 354 | 355 | ### `succeed` 356 | 357 | ``` 358 | succeed(value: A): Parser 359 | ``` 360 | 361 | Returns a parser that always succeeds with `value`. 362 | 363 | ```js 364 | import { succeed } from 'parser-lang'; 365 | 366 | succeed('a').tryParse(''); 367 | // 'a' 368 | ``` 369 | 370 | ### `empty` 371 | 372 | ``` 373 | empty(): Parser 374 | ``` 375 | 376 | Returns a parser that succeeds when the context is empty. 377 | 378 | ```js 379 | import { empty } from 'parser-lang'; 380 | 381 | empty().tryParse([]); 382 | // undefined 383 | empty().tryParse(['a']); 384 | // throw Error 385 | ``` 386 | 387 | ### `item` 388 | 389 | ``` 390 | item(): Parser 391 | ``` 392 | 393 | Returns a parser that consumes the next item in the context. 394 | 395 | ```js 396 | import { item } from 'parser-lang'; 397 | 398 | item().tryParse('abc'); 399 | // 'a' 400 | item().tryParse(''); 401 | // throw Error 402 | ``` 403 | 404 | ### `satisfy` 405 | 406 | ``` 407 | satisfy( 408 | f: A => boolean, 409 | msg?: A => string 410 | ): Parser 411 | ``` 412 | 413 | Returns a parser that consumes the next item from the context and applies the predicate `f` on the result. The parser fails if the predicate fails and invokes `msg` with the item result to get the failure message. 414 | 415 | ```js 416 | import { satisfy } from 'parser-lang'; 417 | 418 | satisfy(n => n > 2).tryParse([10]); 419 | // 10 420 | satisfy(n => n > 2).tryParse([1, 10]); 421 | // throw Error 422 | satisfy(n => n > 2, n => `${n} is not big enough`).tryParse([1, 10]); 423 | // throw Error('1 is not big enough') 424 | ``` 425 | 426 | ### `char` 427 | 428 | ``` 429 | char(ch: string): Parser 430 | ``` 431 | 432 | Returns a parser that matches the character `ch`. 433 | 434 | ```js 435 | import { char } from 'parser-lang'; 436 | 437 | char('a').tryParse('abc'); 438 | // 'a' 439 | char('b').tryParse('abc'); 440 | // throw Error 441 | ``` 442 | 443 | ### `string` 444 | 445 | ``` 446 | string(s: string | Iterable): Parser 447 | ``` 448 | 449 | Returns a parser that matches the string or iterable `s`. 450 | 451 | ```js 452 | import { string } from 'parser-lang'; 453 | 454 | string('foo').tryParse('foobar'); 455 | // 'foo' 456 | string('foo').tryParse(['f', 'o', 'o', 'b', 'a', 'r']); 457 | // 'foo' 458 | string('foo').tryParse('bar'); 459 | // throw Error 460 | ``` 461 | 462 | ### `regex` 463 | 464 | ``` 465 | regex(re: RegExp): Parser 466 | ``` 467 | 468 | Returns a parser that matches the regular expression `re`. 469 | 470 | ```js 471 | import { regex } from 'parser-lang'; 472 | 473 | regex(/foo/).tryParse('foobar'); 474 | // 'foo' 475 | regex(/foo/).tryParse('barfoo'); 476 | // throw Error 477 | ``` 478 | 479 | ### `sequence` 480 | 481 | ``` 482 | sequence( 483 | ...parsers: Parser 484 | ): Parser 485 | ``` 486 | 487 | Returns a parser that matches a sequence of `parsers` and collects their results in an array. 488 | 489 | ```js 490 | import { sequence } from 'parser-lang'; 491 | 492 | sequence(char('a'), char('b')).tryParse('abcd'); 493 | // ['a', 'b'] 494 | sequence(char('a'), char('b')).tryParse('afg'); 495 | // throw Error 496 | ``` 497 | 498 | ### `alternatives` 499 | 500 | ``` 501 | alternatives( 502 | ...parsers: Parser 503 | ): Parser 504 | ``` 505 | 506 | Returns a parser that tries each parser from `parsers` and returns the first one that succeeds. 507 | 508 | ```js 509 | import { alternatives } from 'parser-lang'; 510 | 511 | alternatives(char('a'), char('b')).tryParse('a'); 512 | // 'a' 513 | alternatives(char('a'), char('b')).tryParse('b'); 514 | // 'b' 515 | alternatives(char('a'), char('b')).tryParse('c'); 516 | // throw Error 517 | ``` 518 | 519 | ## Types 520 | 521 | ### `Outcome` 522 | 523 | An `Outcome` is an abstract class with two implementations, a `Success` or a `Failure`. An `Outcome` is the same as the `Either` type from haskell and similar languages. 524 | 525 | #### `of` 526 | 527 | ``` 528 | Outcome.of(value: A): Outcome 529 | ``` 530 | 531 | Returns a `Success` of `value`. 532 | 533 | #### `map` 534 | 535 | ``` 536 | Outcome#map(f: A => B): Outcome 537 | ``` 538 | 539 | Return a new outcome with the result of applying `f` to the value in this outcome. 540 | 541 | ```js 542 | Outcome.of(1).map(x => x + 1); 543 | // Success { value: 2 } 544 | ``` 545 | 546 | #### `chain` 547 | 548 | ``` 549 | Outcome#chain( 550 | f: A => Outcome 551 | ): Outcome 552 | ``` 553 | 554 | Return the result of applying `f` to the value in this outcome. 555 | 556 | #### `forEach` 557 | 558 | ``` 559 | Outcome#forEach( 560 | f: A => void 561 | ): Outcome 562 | ``` 563 | 564 | Return the original outcome after applying `f` to the value for its effects. 565 | 566 | ### Context 567 | 568 | ```js 569 | import { Context } from 'parser-lang`; 570 | ``` 571 | 572 | The **context** protocol defines a standard way for mutable iterable objects to be used in an "immutable" way by allowing consumers to make clones before performing mutations. 573 | 574 | An object is a context object when: 575 | 576 | - it follows the [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols#The_iterator_protocol) protocol 577 | - it has a method accessible on the symbol property `[Context.clone]` with behavior described below 578 | - it optionally has a method accessible on the symbol property `[Context.regex]` with behavior described below 579 | 580 | The `[Context.clone]` method is a zero argument function that must return a fresh clone of the context object. Any subsequent mutations on the original object (e.g. calls to `next`) must not effect the clone. 581 | 582 | The optional `[Context.regex]` method is a function that takes a single regular expression argument and returns an object with the following properties: 583 | 584 | - `done` - a `boolean` indicating if the regular expression matched. The match must start from the current location in the iterator 585 | - `value` - the string matched by the regular expression. Only present if `done` is `true` 586 | 587 | Note the similarities to the `next` method of an iterator. 588 | 589 | ### `ParseResult` 590 | 591 | ```js 592 | type ParseResult = { 593 | value: A, 594 | ctx: Context, 595 | }; 596 | ``` 597 | 598 | `ParseResult` is the type returned from a parse. It represents the `value` that was parsed along with a new `Context` the resulted in consuming the previous `Context`. 599 | -------------------------------------------------------------------------------- /docs/tutorial.md: -------------------------------------------------------------------------------- 1 | # Tutorial 2 | 3 | ## Getting Started 4 | 5 | Install from npm: 6 | 7 | ```sh 8 | npm install parser-lang 9 | ``` 10 | 11 | ## Parsing 12 | 13 | What even is a parser? 14 | 15 | Some possible answers: 16 | 17 | - the software component that analyzes source code 18 | - the other frontend (ie, the frontend to the compiler, not UI development) 19 | - the thing that makes abstract syntax trees 20 | 21 | For our purposes a nice abstract definition is something like "a parser is a function from some input context to a result value paired with a potentially modified context (or a failure)". 22 | 23 | More concretely, a `Parser` is the default export of ParserLang: 24 | 25 | ```js 26 | import Parser from 'parser-lang'; 27 | ``` 28 | 29 | A `Parser` is a class that you can construct: 30 | 31 | ```js 32 | new Parser(ctx => { 33 | // ignore for now 34 | }); 35 | ``` 36 | 37 | Usually when working with ParserLang you combine already existing `Parser`s with other already existing `Parser`s (thus, parser combinator) so we can ignore the primitive constructor for now. 38 | 39 | What you use most of the time are operators that return `Parser`s. For example, the `char` operator makes a parser that matches a single character: 40 | 41 | ```js 42 | import { char } from 'parser-lang'; 43 | 44 | char('a').tryParse('ab'); 45 | // 'a' 46 | ``` 47 | 48 | The method `tryParse` is defined on `Parser` instances and takes an input context, the string `'ab'`, and returns the result of running the parser on the input. The `char('a')` parser consumes the input by a single character if consumed character equals `'a'`. If the character is not `'a'` the parser fails and `tryParse` throws an error: 49 | 50 | ```js 51 | char('a').tryParse('ba'); 52 | // throw Error 53 | ``` 54 | 55 | If you want to create your own parser that consumes a single item if it matches some predicate you can use the `satisfy` function: 56 | 57 | ```js 58 | import { satisfy } from 'parser-lang'; 59 | 60 | let digit = satisfy(ch => ch >= '0' && ch <= '9'); 61 | digit().tryParse('5'); 62 | // '5' 63 | ``` 64 | 65 | The `Parser` class defines a bunch of methods that let you combine parsers together. For example, if you want to match either one parser or another, use the `or` method: 66 | 67 | ```js 68 | let aOrB = char('a').or(char('b')); 69 | 70 | aOrB.tryParse('ba'); 71 | // 'b' 72 | aOrB.tryParse('ab'); 73 | // 'a' 74 | ``` 75 | 76 | Matching one parser after another can be done with the `sequence` combinator: 77 | 78 | ```js 79 | import { sequence } from 'parser-lang'; 80 | 81 | sequence(char('a'), char('b')).tryParse('ab'); 82 | // ['a', 'b'] 83 | ``` 84 | 85 | Note that the result in the parser returned from `sequence` is an array of the results of its sub-parsers. This might not be the type that we want but it is easy to transform the result by using the `map` method: 86 | 87 | ```js 88 | sequence(char('a'), char('b')) 89 | .map(([aResult, bResult]) => aResult + bResult) 90 | .tryParse('ab'); 91 | // 'ab' 92 | ``` 93 | 94 | Since joining arrays of strings is such a common operation, ParserLang defines the `tie` method: 95 | 96 | ```js 97 | sequence(char('a'), char('b')) 98 | .tie() 99 | .tryParse('ab'); 100 | // 'ab' 101 | ``` 102 | 103 | ## lang 104 | 105 | One downside of defining parser combinators using JavaScript functions and methods is that it can become difficult to read as the parsers grow in complexity. The way ParserLang approaches handling this problem is by allowing you to define your parsers using a declarative language in template literals: 106 | 107 | ```js 108 | import { lang } from 'parser-lang'; 109 | 110 | let { a } = lang` 111 | a = 'a'; 112 | `; 113 | a.tryParse('a'); 114 | // 'a' 115 | ``` 116 | 117 | The above is equivalent to `let a = char('a')` in JavaScript. 118 | 119 | The `lang` template literal tag parses the template literal for a sequence of rules where the syntax for each rule is `[name] = [parser] ;`. Each rule `[parser]` is converted to a `Parser` and bound to the property `[name]` in the return object (e.g. the `a` parser is bound to the `a` property in the above example). 120 | 121 | The possible syntax for `[parser]` are: 122 | 123 | (Note that square brackets and `...` are meta-syntax) 124 | 125 | - `'string'` a parser that matches the string `'string'` 126 | - `/re/` a parser that matches the regular expression `re` 127 | - `[name]` a parser defined in `[name]` rule 128 | - `([parser])` group parser (to handle precedence) 129 | - `!${pred}` a parser that satisfies the predicate `pred` 130 | - `@${parser}` a parser that satisfies the parser `parser` 131 | - `[parser_1] | ... | [parser_n]` a parser that tries each `[parser_i]` and matches the first one that succeeds 132 | - `[parser_1] [parser_2] ...` a parser that matches each `[parser_i]` in sequence 133 | - `[parser]*` a parser that matches `[parser]` zero or more times 134 | - `[parser]+` a parser that matches `[parser]` one or more times 135 | - `[parser] > ${f}` a parser that matches `[parser]` and then `map`s the result with `f` 136 | - `[parser] >> ${f}` a parser that matches `[parser]` and then `chain`s the result with `f` 137 | 138 | For example, 139 | 140 | ```js 141 | let { aOrB } = lang` 142 | a = 'a' > ${ch => ch.toUpperCase()}; 143 | b = 'b' > ${ch => ch.toUpperCase()}; 144 | 145 | aOrB = (a | b)* > ${resultArray => resultArray.join('')}; 146 | `; 147 | aOrB.tryParse('aaabbb'); 148 | // 'AAABBB' 149 | ``` 150 | -------------------------------------------------------------------------------- /main.mjs: -------------------------------------------------------------------------------- 1 | export { default } from './src/parser.mjs'; 2 | export * from './src/parser.mjs'; 3 | export { default as Context } from './src/context.mjs'; 4 | export { default as lang } from './src/lang.mjs'; 5 | export * from './src/outcome.mjs'; 6 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parser-lang", 3 | "version": "0.4.0", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "@babel/code-frame": { 8 | "version": "7.8.3", 9 | "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", 10 | "integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==", 11 | "dev": true, 12 | "requires": { 13 | "@babel/highlight": "^7.8.3" 14 | } 15 | }, 16 | "@babel/helper-validator-identifier": { 17 | "version": "7.9.5", 18 | "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz", 19 | "integrity": "sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g==", 20 | "dev": true 21 | }, 22 | "@babel/highlight": { 23 | "version": "7.9.0", 24 | "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz", 25 | "integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==", 26 | "dev": true, 27 | "requires": { 28 | "@babel/helper-validator-identifier": "^7.9.0", 29 | "chalk": "^2.0.0", 30 | "js-tokens": "^4.0.0" 31 | }, 32 | "dependencies": { 33 | "ansi-styles": { 34 | "version": "3.2.1", 35 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 36 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 37 | "dev": true, 38 | "requires": { 39 | "color-convert": "^1.9.0" 40 | } 41 | }, 42 | "chalk": { 43 | "version": "2.4.2", 44 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 45 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 46 | "dev": true, 47 | "requires": { 48 | "ansi-styles": "^3.2.1", 49 | "escape-string-regexp": "^1.0.5", 50 | "supports-color": "^5.3.0" 51 | } 52 | }, 53 | "color-convert": { 54 | "version": "1.9.3", 55 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 56 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 57 | "dev": true, 58 | "requires": { 59 | "color-name": "1.1.3" 60 | } 61 | }, 62 | "color-name": { 63 | "version": "1.1.3", 64 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 65 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 66 | "dev": true 67 | }, 68 | "has-flag": { 69 | "version": "3.0.0", 70 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 71 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 72 | "dev": true 73 | }, 74 | "supports-color": { 75 | "version": "5.5.0", 76 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 77 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 78 | "dev": true, 79 | "requires": { 80 | "has-flag": "^3.0.0" 81 | } 82 | } 83 | } 84 | }, 85 | "@concordance/react": { 86 | "version": "2.0.0", 87 | "resolved": "https://registry.npmjs.org/@concordance/react/-/react-2.0.0.tgz", 88 | "integrity": "sha512-huLSkUuM2/P+U0uy2WwlKuixMsTODD8p4JVQBI4VKeopkiN0C7M3N9XYVawb4M+4spN5RrO/eLhk7KoQX6nsfA==", 89 | "dev": true, 90 | "requires": { 91 | "arrify": "^1.0.1" 92 | }, 93 | "dependencies": { 94 | "arrify": { 95 | "version": "1.0.1", 96 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 97 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 98 | "dev": true 99 | } 100 | } 101 | }, 102 | "@nodelib/fs.scandir": { 103 | "version": "2.1.3", 104 | "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz", 105 | "integrity": "sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw==", 106 | "dev": true, 107 | "requires": { 108 | "@nodelib/fs.stat": "2.0.3", 109 | "run-parallel": "^1.1.9" 110 | } 111 | }, 112 | "@nodelib/fs.stat": { 113 | "version": "2.0.3", 114 | "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz", 115 | "integrity": "sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA==", 116 | "dev": true 117 | }, 118 | "@nodelib/fs.walk": { 119 | "version": "1.2.4", 120 | "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz", 121 | "integrity": "sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ==", 122 | "dev": true, 123 | "requires": { 124 | "@nodelib/fs.scandir": "2.1.3", 125 | "fastq": "^1.6.0" 126 | } 127 | }, 128 | "@sindresorhus/is": { 129 | "version": "0.14.0", 130 | "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", 131 | "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", 132 | "dev": true 133 | }, 134 | "@szmarczak/http-timer": { 135 | "version": "1.1.2", 136 | "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", 137 | "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", 138 | "dev": true, 139 | "requires": { 140 | "defer-to-connect": "^1.0.1" 141 | } 142 | }, 143 | "@types/color-name": { 144 | "version": "1.1.1", 145 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 146 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", 147 | "dev": true 148 | }, 149 | "@types/events": { 150 | "version": "3.0.0", 151 | "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz", 152 | "integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g==", 153 | "dev": true 154 | }, 155 | "@types/glob": { 156 | "version": "7.1.1", 157 | "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.1.tgz", 158 | "integrity": "sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==", 159 | "dev": true, 160 | "requires": { 161 | "@types/events": "*", 162 | "@types/minimatch": "*", 163 | "@types/node": "*" 164 | } 165 | }, 166 | "@types/minimatch": { 167 | "version": "3.0.3", 168 | "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", 169 | "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", 170 | "dev": true 171 | }, 172 | "@types/node": { 173 | "version": "13.13.4", 174 | "resolved": "https://registry.npmjs.org/@types/node/-/node-13.13.4.tgz", 175 | "integrity": "sha512-x26ur3dSXgv5AwKS0lNfbjpCakGIduWU1DU91Zz58ONRWrIKGunmZBNv4P7N+e27sJkiGDsw/3fT4AtsqQBrBA==", 176 | "dev": true 177 | }, 178 | "@types/normalize-package-data": { 179 | "version": "2.4.0", 180 | "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz", 181 | "integrity": "sha512-f5j5b/Gf71L+dbqxIpQ4Z2WlmI/mPJ0fOkGGmFgtb6sAu97EPczzbS3/tJKxmcYDj55OX6ssqwDAWOHIYDRDGA==", 182 | "dev": true 183 | }, 184 | "acorn": { 185 | "version": "7.1.1", 186 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.1.tgz", 187 | "integrity": "sha512-add7dgA5ppRPxCFJoAGfMDi7PIBXq1RtGo7BhbLaxwrXPOmw8gq48Y9ozT01hUKy9byMjlR20EJhu5zlkErEkg==", 188 | "dev": true 189 | }, 190 | "acorn-walk": { 191 | "version": "7.1.1", 192 | "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.1.1.tgz", 193 | "integrity": "sha512-wdlPY2tm/9XBr7QkKlq0WQVgiuGTX6YWPyRyBviSoScBuLfTVQhvwg6wJ369GJ/1nPfTLMfnrFIfjqVg6d+jQQ==", 194 | "dev": true 195 | }, 196 | "aggregate-error": { 197 | "version": "3.0.1", 198 | "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.0.1.tgz", 199 | "integrity": "sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA==", 200 | "dev": true, 201 | "requires": { 202 | "clean-stack": "^2.0.0", 203 | "indent-string": "^4.0.0" 204 | } 205 | }, 206 | "ansi-align": { 207 | "version": "3.0.0", 208 | "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", 209 | "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", 210 | "dev": true, 211 | "requires": { 212 | "string-width": "^3.0.0" 213 | }, 214 | "dependencies": { 215 | "ansi-regex": { 216 | "version": "4.1.0", 217 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", 218 | "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", 219 | "dev": true 220 | }, 221 | "emoji-regex": { 222 | "version": "7.0.3", 223 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", 224 | "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", 225 | "dev": true 226 | }, 227 | "is-fullwidth-code-point": { 228 | "version": "2.0.0", 229 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 230 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 231 | "dev": true 232 | }, 233 | "string-width": { 234 | "version": "3.1.0", 235 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", 236 | "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", 237 | "dev": true, 238 | "requires": { 239 | "emoji-regex": "^7.0.1", 240 | "is-fullwidth-code-point": "^2.0.0", 241 | "strip-ansi": "^5.1.0" 242 | } 243 | }, 244 | "strip-ansi": { 245 | "version": "5.2.0", 246 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", 247 | "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", 248 | "dev": true, 249 | "requires": { 250 | "ansi-regex": "^4.1.0" 251 | } 252 | } 253 | } 254 | }, 255 | "ansi-regex": { 256 | "version": "5.0.0", 257 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", 258 | "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", 259 | "dev": true 260 | }, 261 | "ansi-styles": { 262 | "version": "4.2.1", 263 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 264 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 265 | "dev": true, 266 | "requires": { 267 | "@types/color-name": "^1.1.1", 268 | "color-convert": "^2.0.1" 269 | } 270 | }, 271 | "anymatch": { 272 | "version": "3.1.1", 273 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", 274 | "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", 275 | "dev": true, 276 | "requires": { 277 | "normalize-path": "^3.0.0", 278 | "picomatch": "^2.0.4" 279 | } 280 | }, 281 | "argparse": { 282 | "version": "1.0.10", 283 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 284 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 285 | "dev": true, 286 | "requires": { 287 | "sprintf-js": "~1.0.2" 288 | } 289 | }, 290 | "array-find-index": { 291 | "version": "1.0.2", 292 | "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", 293 | "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", 294 | "dev": true 295 | }, 296 | "array-union": { 297 | "version": "2.1.0", 298 | "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", 299 | "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", 300 | "dev": true 301 | }, 302 | "arrgv": { 303 | "version": "1.0.2", 304 | "resolved": "https://registry.npmjs.org/arrgv/-/arrgv-1.0.2.tgz", 305 | "integrity": "sha512-a4eg4yhp7mmruZDQFqVMlxNRFGi/i1r87pt8SDHy0/I8PqSXoUTlWZRdAZo0VXgvEARcujbtTk8kiZRi1uDGRw==", 306 | "dev": true 307 | }, 308 | "arrify": { 309 | "version": "2.0.1", 310 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", 311 | "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", 312 | "dev": true 313 | }, 314 | "astral-regex": { 315 | "version": "2.0.0", 316 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 317 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 318 | "dev": true 319 | }, 320 | "ava": { 321 | "version": "3.8.1", 322 | "resolved": "https://registry.npmjs.org/ava/-/ava-3.8.1.tgz", 323 | "integrity": "sha512-OPWrTxcf1EbtAaGGFQPLbx4AaVqPrFMumKOKn2SzIRo+RTKb33lF2aoVnWqBeZaJ68uSc9R6jqIE7qkG6O33uQ==", 324 | "dev": true, 325 | "requires": { 326 | "@concordance/react": "^2.0.0", 327 | "acorn": "^7.1.1", 328 | "acorn-walk": "^7.1.1", 329 | "ansi-styles": "^4.2.1", 330 | "arrgv": "^1.0.2", 331 | "arrify": "^2.0.1", 332 | "callsites": "^3.1.0", 333 | "chalk": "^4.0.0", 334 | "chokidar": "^3.4.0", 335 | "chunkd": "^2.0.1", 336 | "ci-info": "^2.0.0", 337 | "ci-parallel-vars": "^1.0.0", 338 | "clean-yaml-object": "^0.1.0", 339 | "cli-cursor": "^3.1.0", 340 | "cli-truncate": "^2.1.0", 341 | "code-excerpt": "^2.1.1", 342 | "common-path-prefix": "^3.0.0", 343 | "concordance": "^4.0.0", 344 | "convert-source-map": "^1.7.0", 345 | "currently-unhandled": "^0.4.1", 346 | "debug": "^4.1.1", 347 | "del": "^5.1.0", 348 | "emittery": "^0.6.0", 349 | "equal-length": "^1.0.0", 350 | "figures": "^3.2.0", 351 | "globby": "^11.0.0", 352 | "ignore-by-default": "^1.0.0", 353 | "import-local": "^3.0.2", 354 | "indent-string": "^4.0.0", 355 | "is-error": "^2.2.2", 356 | "is-plain-object": "^3.0.0", 357 | "is-promise": "^3.0.0", 358 | "lodash": "^4.17.15", 359 | "matcher": "^3.0.0", 360 | "md5-hex": "^3.0.1", 361 | "mem": "^6.1.0", 362 | "ms": "^2.1.2", 363 | "ora": "^4.0.4", 364 | "p-map": "^4.0.0", 365 | "picomatch": "^2.2.2", 366 | "pkg-conf": "^3.1.0", 367 | "plur": "^4.0.0", 368 | "pretty-ms": "^6.0.1", 369 | "read-pkg": "^5.2.0", 370 | "resolve-cwd": "^3.0.0", 371 | "slash": "^3.0.0", 372 | "source-map-support": "^0.5.19", 373 | "stack-utils": "^2.0.1", 374 | "strip-ansi": "^6.0.0", 375 | "supertap": "^1.0.0", 376 | "temp-dir": "^2.0.0", 377 | "trim-off-newlines": "^1.0.1", 378 | "update-notifier": "^4.1.0", 379 | "write-file-atomic": "^3.0.3", 380 | "yargs": "^15.3.1" 381 | } 382 | }, 383 | "balanced-match": { 384 | "version": "1.0.0", 385 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 386 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 387 | "dev": true 388 | }, 389 | "binary-extensions": { 390 | "version": "2.0.0", 391 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", 392 | "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==", 393 | "dev": true 394 | }, 395 | "blueimp-md5": { 396 | "version": "2.13.0", 397 | "resolved": "https://registry.npmjs.org/blueimp-md5/-/blueimp-md5-2.13.0.tgz", 398 | "integrity": "sha512-lmp0m647R5e77ORduxLW5mISIDcvgJZa52vMBv5uVI3UmSWTQjkJsZVBfaFqQPw/QFogJwvY6e3Gl9nP+Loe+Q==", 399 | "dev": true 400 | }, 401 | "boxen": { 402 | "version": "4.2.0", 403 | "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", 404 | "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", 405 | "dev": true, 406 | "requires": { 407 | "ansi-align": "^3.0.0", 408 | "camelcase": "^5.3.1", 409 | "chalk": "^3.0.0", 410 | "cli-boxes": "^2.2.0", 411 | "string-width": "^4.1.0", 412 | "term-size": "^2.1.0", 413 | "type-fest": "^0.8.1", 414 | "widest-line": "^3.1.0" 415 | }, 416 | "dependencies": { 417 | "chalk": { 418 | "version": "3.0.0", 419 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", 420 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", 421 | "dev": true, 422 | "requires": { 423 | "ansi-styles": "^4.1.0", 424 | "supports-color": "^7.1.0" 425 | } 426 | }, 427 | "type-fest": { 428 | "version": "0.8.1", 429 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", 430 | "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", 431 | "dev": true 432 | } 433 | } 434 | }, 435 | "brace-expansion": { 436 | "version": "1.1.11", 437 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 438 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 439 | "dev": true, 440 | "requires": { 441 | "balanced-match": "^1.0.0", 442 | "concat-map": "0.0.1" 443 | } 444 | }, 445 | "braces": { 446 | "version": "3.0.2", 447 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", 448 | "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", 449 | "dev": true, 450 | "requires": { 451 | "fill-range": "^7.0.1" 452 | } 453 | }, 454 | "buffer-from": { 455 | "version": "1.1.1", 456 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 457 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 458 | "dev": true 459 | }, 460 | "cacheable-request": { 461 | "version": "6.1.0", 462 | "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", 463 | "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", 464 | "dev": true, 465 | "requires": { 466 | "clone-response": "^1.0.2", 467 | "get-stream": "^5.1.0", 468 | "http-cache-semantics": "^4.0.0", 469 | "keyv": "^3.0.0", 470 | "lowercase-keys": "^2.0.0", 471 | "normalize-url": "^4.1.0", 472 | "responselike": "^1.0.2" 473 | }, 474 | "dependencies": { 475 | "get-stream": { 476 | "version": "5.1.0", 477 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", 478 | "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", 479 | "dev": true, 480 | "requires": { 481 | "pump": "^3.0.0" 482 | } 483 | }, 484 | "lowercase-keys": { 485 | "version": "2.0.0", 486 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", 487 | "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", 488 | "dev": true 489 | } 490 | } 491 | }, 492 | "callsites": { 493 | "version": "3.1.0", 494 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", 495 | "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", 496 | "dev": true 497 | }, 498 | "camelcase": { 499 | "version": "5.3.1", 500 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", 501 | "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", 502 | "dev": true 503 | }, 504 | "chalk": { 505 | "version": "4.0.0", 506 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.0.0.tgz", 507 | "integrity": "sha512-N9oWFcegS0sFr9oh1oz2d7Npos6vNoWW9HvtCg5N1KRFpUhaAhvTv5Y58g880fZaEYSNm3qDz8SU1UrGvp+n7A==", 508 | "dev": true, 509 | "requires": { 510 | "ansi-styles": "^4.1.0", 511 | "supports-color": "^7.1.0" 512 | } 513 | }, 514 | "chokidar": { 515 | "version": "3.4.0", 516 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", 517 | "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", 518 | "dev": true, 519 | "requires": { 520 | "anymatch": "~3.1.1", 521 | "braces": "~3.0.2", 522 | "fsevents": "~2.1.2", 523 | "glob-parent": "~5.1.0", 524 | "is-binary-path": "~2.1.0", 525 | "is-glob": "~4.0.1", 526 | "normalize-path": "~3.0.0", 527 | "readdirp": "~3.4.0" 528 | } 529 | }, 530 | "chunkd": { 531 | "version": "2.0.1", 532 | "resolved": "https://registry.npmjs.org/chunkd/-/chunkd-2.0.1.tgz", 533 | "integrity": "sha512-7d58XsFmOq0j6el67Ug9mHf9ELUXsQXYJBkyxhH/k+6Ke0qXRnv0kbemx+Twc6fRJ07C49lcbdgm9FL1Ei/6SQ==", 534 | "dev": true 535 | }, 536 | "ci-info": { 537 | "version": "2.0.0", 538 | "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", 539 | "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", 540 | "dev": true 541 | }, 542 | "ci-parallel-vars": { 543 | "version": "1.0.0", 544 | "resolved": "https://registry.npmjs.org/ci-parallel-vars/-/ci-parallel-vars-1.0.0.tgz", 545 | "integrity": "sha512-u6dx20FBXm+apMi+5x7UVm6EH7BL1gc4XrcnQewjcB7HWRcor/V5qWc3RG2HwpgDJ26gIi2DSEu3B7sXynAw/g==", 546 | "dev": true 547 | }, 548 | "clean-stack": { 549 | "version": "2.2.0", 550 | "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", 551 | "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", 552 | "dev": true 553 | }, 554 | "clean-yaml-object": { 555 | "version": "0.1.0", 556 | "resolved": "https://registry.npmjs.org/clean-yaml-object/-/clean-yaml-object-0.1.0.tgz", 557 | "integrity": "sha1-Y/sRDcLOGoTcIfbZM0h20BCui2g=", 558 | "dev": true 559 | }, 560 | "cli-boxes": { 561 | "version": "2.2.0", 562 | "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", 563 | "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==", 564 | "dev": true 565 | }, 566 | "cli-cursor": { 567 | "version": "3.1.0", 568 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 569 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 570 | "dev": true, 571 | "requires": { 572 | "restore-cursor": "^3.1.0" 573 | } 574 | }, 575 | "cli-spinners": { 576 | "version": "2.3.0", 577 | "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.3.0.tgz", 578 | "integrity": "sha512-Xs2Hf2nzrvJMFKimOR7YR0QwZ8fc0u98kdtwN1eNAZzNQgH3vK2pXzff6GJtKh7S5hoJ87ECiAiZFS2fb5Ii2w==", 579 | "dev": true 580 | }, 581 | "cli-truncate": { 582 | "version": "2.1.0", 583 | "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", 584 | "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", 585 | "dev": true, 586 | "requires": { 587 | "slice-ansi": "^3.0.0", 588 | "string-width": "^4.2.0" 589 | } 590 | }, 591 | "cliui": { 592 | "version": "6.0.0", 593 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", 594 | "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", 595 | "dev": true, 596 | "requires": { 597 | "string-width": "^4.2.0", 598 | "strip-ansi": "^6.0.0", 599 | "wrap-ansi": "^6.2.0" 600 | } 601 | }, 602 | "clone": { 603 | "version": "1.0.4", 604 | "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", 605 | "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", 606 | "dev": true 607 | }, 608 | "clone-response": { 609 | "version": "1.0.2", 610 | "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", 611 | "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", 612 | "dev": true, 613 | "requires": { 614 | "mimic-response": "^1.0.0" 615 | } 616 | }, 617 | "code-excerpt": { 618 | "version": "2.1.1", 619 | "resolved": "https://registry.npmjs.org/code-excerpt/-/code-excerpt-2.1.1.tgz", 620 | "integrity": "sha512-tJLhH3EpFm/1x7heIW0hemXJTUU5EWl2V0EIX558jp05Mt1U6DVryCgkp3l37cxqs+DNbNgxG43SkwJXpQ14Jw==", 621 | "dev": true, 622 | "requires": { 623 | "convert-to-spaces": "^1.0.1" 624 | } 625 | }, 626 | "color-convert": { 627 | "version": "2.0.1", 628 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 629 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 630 | "dev": true, 631 | "requires": { 632 | "color-name": "~1.1.4" 633 | } 634 | }, 635 | "color-name": { 636 | "version": "1.1.4", 637 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 638 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 639 | "dev": true 640 | }, 641 | "common-path-prefix": { 642 | "version": "3.0.0", 643 | "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", 644 | "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", 645 | "dev": true 646 | }, 647 | "concat-map": { 648 | "version": "0.0.1", 649 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 650 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 651 | "dev": true 652 | }, 653 | "concordance": { 654 | "version": "4.0.0", 655 | "resolved": "https://registry.npmjs.org/concordance/-/concordance-4.0.0.tgz", 656 | "integrity": "sha512-l0RFuB8RLfCS0Pt2Id39/oCPykE01pyxgAFypWTlaGRgvLkZrtczZ8atEHpTeEIW+zYWXTBuA9cCSeEOScxReQ==", 657 | "dev": true, 658 | "requires": { 659 | "date-time": "^2.1.0", 660 | "esutils": "^2.0.2", 661 | "fast-diff": "^1.1.2", 662 | "js-string-escape": "^1.0.1", 663 | "lodash.clonedeep": "^4.5.0", 664 | "lodash.flattendeep": "^4.4.0", 665 | "lodash.islength": "^4.0.1", 666 | "lodash.merge": "^4.6.1", 667 | "md5-hex": "^2.0.0", 668 | "semver": "^5.5.1", 669 | "well-known-symbols": "^2.0.0" 670 | }, 671 | "dependencies": { 672 | "md5-hex": { 673 | "version": "2.0.0", 674 | "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-2.0.0.tgz", 675 | "integrity": "sha1-0FiOnxx0lUSS7NJKwKxs6ZfZLjM=", 676 | "dev": true, 677 | "requires": { 678 | "md5-o-matic": "^0.1.1" 679 | } 680 | } 681 | } 682 | }, 683 | "configstore": { 684 | "version": "5.0.1", 685 | "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", 686 | "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", 687 | "dev": true, 688 | "requires": { 689 | "dot-prop": "^5.2.0", 690 | "graceful-fs": "^4.1.2", 691 | "make-dir": "^3.0.0", 692 | "unique-string": "^2.0.0", 693 | "write-file-atomic": "^3.0.0", 694 | "xdg-basedir": "^4.0.0" 695 | } 696 | }, 697 | "convert-source-map": { 698 | "version": "1.7.0", 699 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", 700 | "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", 701 | "dev": true, 702 | "requires": { 703 | "safe-buffer": "~5.1.1" 704 | } 705 | }, 706 | "convert-to-spaces": { 707 | "version": "1.0.2", 708 | "resolved": "https://registry.npmjs.org/convert-to-spaces/-/convert-to-spaces-1.0.2.tgz", 709 | "integrity": "sha1-fj5Iu+bZl7FBfdyihoIEtNPYVxU=", 710 | "dev": true 711 | }, 712 | "crypto-random-string": { 713 | "version": "2.0.0", 714 | "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", 715 | "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", 716 | "dev": true 717 | }, 718 | "currently-unhandled": { 719 | "version": "0.4.1", 720 | "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", 721 | "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", 722 | "dev": true, 723 | "requires": { 724 | "array-find-index": "^1.0.1" 725 | } 726 | }, 727 | "date-time": { 728 | "version": "2.1.0", 729 | "resolved": "https://registry.npmjs.org/date-time/-/date-time-2.1.0.tgz", 730 | "integrity": "sha512-/9+C44X7lot0IeiyfgJmETtRMhBidBYM2QFFIkGa0U1k+hSyY87Nw7PY3eDqpvCBm7I3WCSfPeZskW/YYq6m4g==", 731 | "dev": true, 732 | "requires": { 733 | "time-zone": "^1.0.0" 734 | } 735 | }, 736 | "debug": { 737 | "version": "4.1.1", 738 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", 739 | "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", 740 | "dev": true, 741 | "requires": { 742 | "ms": "^2.1.1" 743 | } 744 | }, 745 | "decamelize": { 746 | "version": "1.2.0", 747 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", 748 | "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", 749 | "dev": true 750 | }, 751 | "decompress-response": { 752 | "version": "3.3.0", 753 | "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", 754 | "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", 755 | "dev": true, 756 | "requires": { 757 | "mimic-response": "^1.0.0" 758 | } 759 | }, 760 | "deep-extend": { 761 | "version": "0.6.0", 762 | "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", 763 | "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", 764 | "dev": true 765 | }, 766 | "defaults": { 767 | "version": "1.0.3", 768 | "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", 769 | "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", 770 | "dev": true, 771 | "requires": { 772 | "clone": "^1.0.2" 773 | } 774 | }, 775 | "defer-to-connect": { 776 | "version": "1.1.3", 777 | "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", 778 | "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", 779 | "dev": true 780 | }, 781 | "del": { 782 | "version": "5.1.0", 783 | "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", 784 | "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", 785 | "dev": true, 786 | "requires": { 787 | "globby": "^10.0.1", 788 | "graceful-fs": "^4.2.2", 789 | "is-glob": "^4.0.1", 790 | "is-path-cwd": "^2.2.0", 791 | "is-path-inside": "^3.0.1", 792 | "p-map": "^3.0.0", 793 | "rimraf": "^3.0.0", 794 | "slash": "^3.0.0" 795 | }, 796 | "dependencies": { 797 | "globby": { 798 | "version": "10.0.2", 799 | "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", 800 | "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", 801 | "dev": true, 802 | "requires": { 803 | "@types/glob": "^7.1.1", 804 | "array-union": "^2.1.0", 805 | "dir-glob": "^3.0.1", 806 | "fast-glob": "^3.0.3", 807 | "glob": "^7.1.3", 808 | "ignore": "^5.1.1", 809 | "merge2": "^1.2.3", 810 | "slash": "^3.0.0" 811 | } 812 | }, 813 | "p-map": { 814 | "version": "3.0.0", 815 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", 816 | "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", 817 | "dev": true, 818 | "requires": { 819 | "aggregate-error": "^3.0.0" 820 | } 821 | } 822 | } 823 | }, 824 | "dir-glob": { 825 | "version": "3.0.1", 826 | "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", 827 | "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", 828 | "dev": true, 829 | "requires": { 830 | "path-type": "^4.0.0" 831 | } 832 | }, 833 | "dot-prop": { 834 | "version": "5.2.0", 835 | "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", 836 | "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", 837 | "dev": true, 838 | "requires": { 839 | "is-obj": "^2.0.0" 840 | } 841 | }, 842 | "duplexer3": { 843 | "version": "0.1.4", 844 | "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", 845 | "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", 846 | "dev": true 847 | }, 848 | "emittery": { 849 | "version": "0.6.0", 850 | "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.6.0.tgz", 851 | "integrity": "sha512-6EMRGr9KzYWp8DzHFZsKVZBsMO6QhAeHMeHND8rhyBNCHKMLpgW9tZv40bwN3rAIKRS5CxcK8oLRKUJSB9h7yQ==", 852 | "dev": true 853 | }, 854 | "emoji-regex": { 855 | "version": "8.0.0", 856 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 857 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 858 | "dev": true 859 | }, 860 | "end-of-stream": { 861 | "version": "1.4.4", 862 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 863 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 864 | "dev": true, 865 | "requires": { 866 | "once": "^1.4.0" 867 | } 868 | }, 869 | "equal-length": { 870 | "version": "1.0.1", 871 | "resolved": "https://registry.npmjs.org/equal-length/-/equal-length-1.0.1.tgz", 872 | "integrity": "sha1-IcoRLUirJLTh5//A5TOdMf38J0w=", 873 | "dev": true 874 | }, 875 | "error-ex": { 876 | "version": "1.3.2", 877 | "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", 878 | "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", 879 | "dev": true, 880 | "requires": { 881 | "is-arrayish": "^0.2.1" 882 | } 883 | }, 884 | "escape-goat": { 885 | "version": "2.1.1", 886 | "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", 887 | "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", 888 | "dev": true 889 | }, 890 | "escape-string-regexp": { 891 | "version": "1.0.5", 892 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 893 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 894 | "dev": true 895 | }, 896 | "esprima": { 897 | "version": "4.0.1", 898 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 899 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 900 | "dev": true 901 | }, 902 | "esutils": { 903 | "version": "2.0.3", 904 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 905 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 906 | "dev": true 907 | }, 908 | "fast-diff": { 909 | "version": "1.2.0", 910 | "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", 911 | "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", 912 | "dev": true 913 | }, 914 | "fast-glob": { 915 | "version": "3.2.2", 916 | "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.2.tgz", 917 | "integrity": "sha512-UDV82o4uQyljznxwMxyVRJgZZt3O5wENYojjzbaGEGZgeOxkLFf+V4cnUD+krzb2F72E18RhamkMZ7AdeggF7A==", 918 | "dev": true, 919 | "requires": { 920 | "@nodelib/fs.stat": "^2.0.2", 921 | "@nodelib/fs.walk": "^1.2.3", 922 | "glob-parent": "^5.1.0", 923 | "merge2": "^1.3.0", 924 | "micromatch": "^4.0.2", 925 | "picomatch": "^2.2.1" 926 | } 927 | }, 928 | "fastq": { 929 | "version": "1.7.0", 930 | "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.7.0.tgz", 931 | "integrity": "sha512-YOadQRnHd5q6PogvAR/x62BGituF2ufiEA6s8aavQANw5YKHERI4AREboX6KotzP8oX2klxYF2wcV/7bn1clfQ==", 932 | "dev": true, 933 | "requires": { 934 | "reusify": "^1.0.4" 935 | } 936 | }, 937 | "figures": { 938 | "version": "3.2.0", 939 | "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", 940 | "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", 941 | "dev": true, 942 | "requires": { 943 | "escape-string-regexp": "^1.0.5" 944 | } 945 | }, 946 | "fill-range": { 947 | "version": "7.0.1", 948 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", 949 | "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", 950 | "dev": true, 951 | "requires": { 952 | "to-regex-range": "^5.0.1" 953 | } 954 | }, 955 | "find-up": { 956 | "version": "4.1.0", 957 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 958 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 959 | "dev": true, 960 | "requires": { 961 | "locate-path": "^5.0.0", 962 | "path-exists": "^4.0.0" 963 | } 964 | }, 965 | "fs.realpath": { 966 | "version": "1.0.0", 967 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 968 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 969 | "dev": true 970 | }, 971 | "fsevents": { 972 | "version": "2.1.3", 973 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", 974 | "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", 975 | "dev": true, 976 | "optional": true 977 | }, 978 | "get-caller-file": { 979 | "version": "2.0.5", 980 | "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", 981 | "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", 982 | "dev": true 983 | }, 984 | "get-stream": { 985 | "version": "4.1.0", 986 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", 987 | "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", 988 | "dev": true, 989 | "requires": { 990 | "pump": "^3.0.0" 991 | } 992 | }, 993 | "glob": { 994 | "version": "7.1.6", 995 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 996 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 997 | "dev": true, 998 | "requires": { 999 | "fs.realpath": "^1.0.0", 1000 | "inflight": "^1.0.4", 1001 | "inherits": "2", 1002 | "minimatch": "^3.0.4", 1003 | "once": "^1.3.0", 1004 | "path-is-absolute": "^1.0.0" 1005 | } 1006 | }, 1007 | "glob-parent": { 1008 | "version": "5.1.1", 1009 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", 1010 | "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", 1011 | "dev": true, 1012 | "requires": { 1013 | "is-glob": "^4.0.1" 1014 | } 1015 | }, 1016 | "global-dirs": { 1017 | "version": "2.0.1", 1018 | "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", 1019 | "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", 1020 | "dev": true, 1021 | "requires": { 1022 | "ini": "^1.3.5" 1023 | } 1024 | }, 1025 | "globby": { 1026 | "version": "11.0.0", 1027 | "resolved": "https://registry.npmjs.org/globby/-/globby-11.0.0.tgz", 1028 | "integrity": "sha512-iuehFnR3xu5wBBtm4xi0dMe92Ob87ufyu/dHwpDYfbcpYpIbrO5OnS8M1vWvrBhSGEJ3/Ecj7gnX76P8YxpPEg==", 1029 | "dev": true, 1030 | "requires": { 1031 | "array-union": "^2.1.0", 1032 | "dir-glob": "^3.0.1", 1033 | "fast-glob": "^3.1.1", 1034 | "ignore": "^5.1.4", 1035 | "merge2": "^1.3.0", 1036 | "slash": "^3.0.0" 1037 | } 1038 | }, 1039 | "got": { 1040 | "version": "9.6.0", 1041 | "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", 1042 | "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", 1043 | "dev": true, 1044 | "requires": { 1045 | "@sindresorhus/is": "^0.14.0", 1046 | "@szmarczak/http-timer": "^1.1.2", 1047 | "cacheable-request": "^6.0.0", 1048 | "decompress-response": "^3.3.0", 1049 | "duplexer3": "^0.1.4", 1050 | "get-stream": "^4.1.0", 1051 | "lowercase-keys": "^1.0.1", 1052 | "mimic-response": "^1.0.1", 1053 | "p-cancelable": "^1.0.0", 1054 | "to-readable-stream": "^1.0.0", 1055 | "url-parse-lax": "^3.0.0" 1056 | } 1057 | }, 1058 | "graceful-fs": { 1059 | "version": "4.2.4", 1060 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", 1061 | "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", 1062 | "dev": true 1063 | }, 1064 | "has-flag": { 1065 | "version": "4.0.0", 1066 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1067 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1068 | "dev": true 1069 | }, 1070 | "has-yarn": { 1071 | "version": "2.1.0", 1072 | "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", 1073 | "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", 1074 | "dev": true 1075 | }, 1076 | "hosted-git-info": { 1077 | "version": "2.8.8", 1078 | "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz", 1079 | "integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==", 1080 | "dev": true 1081 | }, 1082 | "http-cache-semantics": { 1083 | "version": "4.1.0", 1084 | "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", 1085 | "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", 1086 | "dev": true 1087 | }, 1088 | "ignore": { 1089 | "version": "5.1.4", 1090 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.4.tgz", 1091 | "integrity": "sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A==", 1092 | "dev": true 1093 | }, 1094 | "ignore-by-default": { 1095 | "version": "1.0.1", 1096 | "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", 1097 | "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", 1098 | "dev": true 1099 | }, 1100 | "import-lazy": { 1101 | "version": "2.1.0", 1102 | "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", 1103 | "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", 1104 | "dev": true 1105 | }, 1106 | "import-local": { 1107 | "version": "3.0.2", 1108 | "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.0.2.tgz", 1109 | "integrity": "sha512-vjL3+w0oulAVZ0hBHnxa/Nm5TAurf9YLQJDhqRZyqb+VKGOB6LU8t9H1Nr5CIo16vh9XfJTOoHwU0B71S557gA==", 1110 | "dev": true, 1111 | "requires": { 1112 | "pkg-dir": "^4.2.0", 1113 | "resolve-cwd": "^3.0.0" 1114 | } 1115 | }, 1116 | "imurmurhash": { 1117 | "version": "0.1.4", 1118 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1119 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1120 | "dev": true 1121 | }, 1122 | "indent-string": { 1123 | "version": "4.0.0", 1124 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", 1125 | "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", 1126 | "dev": true 1127 | }, 1128 | "inflight": { 1129 | "version": "1.0.6", 1130 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1131 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1132 | "dev": true, 1133 | "requires": { 1134 | "once": "^1.3.0", 1135 | "wrappy": "1" 1136 | } 1137 | }, 1138 | "inherits": { 1139 | "version": "2.0.4", 1140 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1141 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", 1142 | "dev": true 1143 | }, 1144 | "ini": { 1145 | "version": "1.3.5", 1146 | "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", 1147 | "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", 1148 | "dev": true 1149 | }, 1150 | "irregular-plurals": { 1151 | "version": "3.2.0", 1152 | "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-3.2.0.tgz", 1153 | "integrity": "sha512-YqTdPLfwP7YFN0SsD3QUVCkm9ZG2VzOXv3DOrw5G5mkMbVwptTwVcFv7/C0vOpBmgTxAeTG19XpUs1E522LW9Q==", 1154 | "dev": true 1155 | }, 1156 | "is-arrayish": { 1157 | "version": "0.2.1", 1158 | "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", 1159 | "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", 1160 | "dev": true 1161 | }, 1162 | "is-binary-path": { 1163 | "version": "2.1.0", 1164 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1165 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1166 | "dev": true, 1167 | "requires": { 1168 | "binary-extensions": "^2.0.0" 1169 | } 1170 | }, 1171 | "is-ci": { 1172 | "version": "2.0.0", 1173 | "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", 1174 | "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", 1175 | "dev": true, 1176 | "requires": { 1177 | "ci-info": "^2.0.0" 1178 | } 1179 | }, 1180 | "is-error": { 1181 | "version": "2.2.2", 1182 | "resolved": "https://registry.npmjs.org/is-error/-/is-error-2.2.2.tgz", 1183 | "integrity": "sha512-IOQqts/aHWbiisY5DuPJQ0gcbvaLFCa7fBa9xoLfxBZvQ+ZI/Zh9xoI7Gk+G64N0FdK4AbibytHht2tWgpJWLg==", 1184 | "dev": true 1185 | }, 1186 | "is-extglob": { 1187 | "version": "2.1.1", 1188 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1189 | "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", 1190 | "dev": true 1191 | }, 1192 | "is-fullwidth-code-point": { 1193 | "version": "3.0.0", 1194 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1195 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1196 | "dev": true 1197 | }, 1198 | "is-glob": { 1199 | "version": "4.0.1", 1200 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", 1201 | "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", 1202 | "dev": true, 1203 | "requires": { 1204 | "is-extglob": "^2.1.1" 1205 | } 1206 | }, 1207 | "is-installed-globally": { 1208 | "version": "0.3.2", 1209 | "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", 1210 | "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", 1211 | "dev": true, 1212 | "requires": { 1213 | "global-dirs": "^2.0.1", 1214 | "is-path-inside": "^3.0.1" 1215 | } 1216 | }, 1217 | "is-interactive": { 1218 | "version": "1.0.0", 1219 | "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", 1220 | "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", 1221 | "dev": true 1222 | }, 1223 | "is-npm": { 1224 | "version": "4.0.0", 1225 | "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", 1226 | "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", 1227 | "dev": true 1228 | }, 1229 | "is-number": { 1230 | "version": "7.0.0", 1231 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1232 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1233 | "dev": true 1234 | }, 1235 | "is-obj": { 1236 | "version": "2.0.0", 1237 | "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", 1238 | "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", 1239 | "dev": true 1240 | }, 1241 | "is-path-cwd": { 1242 | "version": "2.2.0", 1243 | "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", 1244 | "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", 1245 | "dev": true 1246 | }, 1247 | "is-path-inside": { 1248 | "version": "3.0.2", 1249 | "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", 1250 | "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==", 1251 | "dev": true 1252 | }, 1253 | "is-plain-object": { 1254 | "version": "3.0.0", 1255 | "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.0.tgz", 1256 | "integrity": "sha512-tZIpofR+P05k8Aocp7UI/2UTa9lTJSebCXpFFoR9aibpokDj/uXBsJ8luUu0tTVYKkMU6URDUuOfJZ7koewXvg==", 1257 | "dev": true, 1258 | "requires": { 1259 | "isobject": "^4.0.0" 1260 | } 1261 | }, 1262 | "is-promise": { 1263 | "version": "3.0.0", 1264 | "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-3.0.0.tgz", 1265 | "integrity": "sha512-aTHJ4BvETyySzLhguH+7sL4b8765eecqq7ZrHVuhZr3FjCL/IV+LsvisEeH+9d0AkChYny3ad1KEL+mKy4ot7A==", 1266 | "dev": true 1267 | }, 1268 | "is-typedarray": { 1269 | "version": "1.0.0", 1270 | "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", 1271 | "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", 1272 | "dev": true 1273 | }, 1274 | "is-yarn-global": { 1275 | "version": "0.3.0", 1276 | "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", 1277 | "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", 1278 | "dev": true 1279 | }, 1280 | "isobject": { 1281 | "version": "4.0.0", 1282 | "resolved": "https://registry.npmjs.org/isobject/-/isobject-4.0.0.tgz", 1283 | "integrity": "sha512-S/2fF5wH8SJA/kmwr6HYhK/RI/OkhD84k8ntalo0iJjZikgq1XFvR5M8NPT1x5F7fBwCG3qHfnzeP/Vh/ZxCUA==", 1284 | "dev": true 1285 | }, 1286 | "js-string-escape": { 1287 | "version": "1.0.1", 1288 | "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", 1289 | "integrity": "sha1-4mJbrbwNZ8dTPp7cEGjFh65BN+8=", 1290 | "dev": true 1291 | }, 1292 | "js-tokens": { 1293 | "version": "4.0.0", 1294 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", 1295 | "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", 1296 | "dev": true 1297 | }, 1298 | "js-yaml": { 1299 | "version": "3.13.1", 1300 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1301 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1302 | "dev": true, 1303 | "requires": { 1304 | "argparse": "^1.0.7", 1305 | "esprima": "^4.0.0" 1306 | } 1307 | }, 1308 | "json-buffer": { 1309 | "version": "3.0.0", 1310 | "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", 1311 | "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", 1312 | "dev": true 1313 | }, 1314 | "json-parse-better-errors": { 1315 | "version": "1.0.2", 1316 | "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", 1317 | "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", 1318 | "dev": true 1319 | }, 1320 | "keyv": { 1321 | "version": "3.1.0", 1322 | "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", 1323 | "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", 1324 | "dev": true, 1325 | "requires": { 1326 | "json-buffer": "3.0.0" 1327 | } 1328 | }, 1329 | "latest-version": { 1330 | "version": "5.1.0", 1331 | "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", 1332 | "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", 1333 | "dev": true, 1334 | "requires": { 1335 | "package-json": "^6.3.0" 1336 | } 1337 | }, 1338 | "lines-and-columns": { 1339 | "version": "1.1.6", 1340 | "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", 1341 | "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", 1342 | "dev": true 1343 | }, 1344 | "load-json-file": { 1345 | "version": "5.3.0", 1346 | "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-5.3.0.tgz", 1347 | "integrity": "sha512-cJGP40Jc/VXUsp8/OrnyKyTZ1y6v/dphm3bioS+RrKXjK2BB6wHUd6JptZEFDGgGahMT+InnZO5i1Ei9mpC8Bw==", 1348 | "dev": true, 1349 | "requires": { 1350 | "graceful-fs": "^4.1.15", 1351 | "parse-json": "^4.0.0", 1352 | "pify": "^4.0.1", 1353 | "strip-bom": "^3.0.0", 1354 | "type-fest": "^0.3.0" 1355 | } 1356 | }, 1357 | "locate-path": { 1358 | "version": "5.0.0", 1359 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1360 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1361 | "dev": true, 1362 | "requires": { 1363 | "p-locate": "^4.1.0" 1364 | } 1365 | }, 1366 | "lodash": { 1367 | "version": "4.17.15", 1368 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1369 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 1370 | "dev": true 1371 | }, 1372 | "lodash.clonedeep": { 1373 | "version": "4.5.0", 1374 | "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", 1375 | "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", 1376 | "dev": true 1377 | }, 1378 | "lodash.flattendeep": { 1379 | "version": "4.4.0", 1380 | "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", 1381 | "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", 1382 | "dev": true 1383 | }, 1384 | "lodash.islength": { 1385 | "version": "4.0.1", 1386 | "resolved": "https://registry.npmjs.org/lodash.islength/-/lodash.islength-4.0.1.tgz", 1387 | "integrity": "sha1-Tpho1FJXXXUK/9NYyXlUPcIO1Xc=", 1388 | "dev": true 1389 | }, 1390 | "lodash.merge": { 1391 | "version": "4.6.2", 1392 | "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", 1393 | "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", 1394 | "dev": true 1395 | }, 1396 | "log-symbols": { 1397 | "version": "3.0.0", 1398 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", 1399 | "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", 1400 | "dev": true, 1401 | "requires": { 1402 | "chalk": "^2.4.2" 1403 | }, 1404 | "dependencies": { 1405 | "ansi-styles": { 1406 | "version": "3.2.1", 1407 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", 1408 | "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", 1409 | "dev": true, 1410 | "requires": { 1411 | "color-convert": "^1.9.0" 1412 | } 1413 | }, 1414 | "chalk": { 1415 | "version": "2.4.2", 1416 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", 1417 | "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", 1418 | "dev": true, 1419 | "requires": { 1420 | "ansi-styles": "^3.2.1", 1421 | "escape-string-regexp": "^1.0.5", 1422 | "supports-color": "^5.3.0" 1423 | } 1424 | }, 1425 | "color-convert": { 1426 | "version": "1.9.3", 1427 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", 1428 | "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", 1429 | "dev": true, 1430 | "requires": { 1431 | "color-name": "1.1.3" 1432 | } 1433 | }, 1434 | "color-name": { 1435 | "version": "1.1.3", 1436 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", 1437 | "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", 1438 | "dev": true 1439 | }, 1440 | "has-flag": { 1441 | "version": "3.0.0", 1442 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", 1443 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", 1444 | "dev": true 1445 | }, 1446 | "supports-color": { 1447 | "version": "5.5.0", 1448 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", 1449 | "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", 1450 | "dev": true, 1451 | "requires": { 1452 | "has-flag": "^3.0.0" 1453 | } 1454 | } 1455 | } 1456 | }, 1457 | "lowercase-keys": { 1458 | "version": "1.0.1", 1459 | "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", 1460 | "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", 1461 | "dev": true 1462 | }, 1463 | "make-dir": { 1464 | "version": "3.1.0", 1465 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", 1466 | "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", 1467 | "dev": true, 1468 | "requires": { 1469 | "semver": "^6.0.0" 1470 | }, 1471 | "dependencies": { 1472 | "semver": { 1473 | "version": "6.3.0", 1474 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1475 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1476 | "dev": true 1477 | } 1478 | } 1479 | }, 1480 | "map-age-cleaner": { 1481 | "version": "0.1.3", 1482 | "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", 1483 | "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", 1484 | "dev": true, 1485 | "requires": { 1486 | "p-defer": "^1.0.0" 1487 | } 1488 | }, 1489 | "matcher": { 1490 | "version": "3.0.0", 1491 | "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", 1492 | "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", 1493 | "dev": true, 1494 | "requires": { 1495 | "escape-string-regexp": "^4.0.0" 1496 | }, 1497 | "dependencies": { 1498 | "escape-string-regexp": { 1499 | "version": "4.0.0", 1500 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1501 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1502 | "dev": true 1503 | } 1504 | } 1505 | }, 1506 | "md5-hex": { 1507 | "version": "3.0.1", 1508 | "resolved": "https://registry.npmjs.org/md5-hex/-/md5-hex-3.0.1.tgz", 1509 | "integrity": "sha512-BUiRtTtV39LIJwinWBjqVsU9xhdnz7/i889V859IBFpuqGAj6LuOvHv5XLbgZ2R7ptJoJaEcxkv88/h25T7Ciw==", 1510 | "dev": true, 1511 | "requires": { 1512 | "blueimp-md5": "^2.10.0" 1513 | } 1514 | }, 1515 | "md5-o-matic": { 1516 | "version": "0.1.1", 1517 | "resolved": "https://registry.npmjs.org/md5-o-matic/-/md5-o-matic-0.1.1.tgz", 1518 | "integrity": "sha1-givM1l4RfFFPqxdrJZRdVBAKA8M=", 1519 | "dev": true 1520 | }, 1521 | "mem": { 1522 | "version": "6.1.0", 1523 | "resolved": "https://registry.npmjs.org/mem/-/mem-6.1.0.tgz", 1524 | "integrity": "sha512-RlbnLQgRHk5lwqTtpEkBTQ2ll/CG/iB+J4Hy2Wh97PjgZgXgWJWrFF+XXujh3UUVLvR4OOTgZzcWMMwnehlEUg==", 1525 | "dev": true, 1526 | "requires": { 1527 | "map-age-cleaner": "^0.1.3", 1528 | "mimic-fn": "^3.0.0" 1529 | }, 1530 | "dependencies": { 1531 | "mimic-fn": { 1532 | "version": "3.0.0", 1533 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.0.0.tgz", 1534 | "integrity": "sha512-PiVO95TKvhiwgSwg1IdLYlCTdul38yZxZMIcnDSFIBUm4BNZha2qpQ4GpJ++15bHoKDtrW2D69lMfFwdFYtNZQ==", 1535 | "dev": true 1536 | } 1537 | } 1538 | }, 1539 | "merge2": { 1540 | "version": "1.3.0", 1541 | "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.3.0.tgz", 1542 | "integrity": "sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw==", 1543 | "dev": true 1544 | }, 1545 | "micromatch": { 1546 | "version": "4.0.2", 1547 | "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz", 1548 | "integrity": "sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==", 1549 | "dev": true, 1550 | "requires": { 1551 | "braces": "^3.0.1", 1552 | "picomatch": "^2.0.5" 1553 | } 1554 | }, 1555 | "mimic-fn": { 1556 | "version": "2.1.0", 1557 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 1558 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 1559 | "dev": true 1560 | }, 1561 | "mimic-response": { 1562 | "version": "1.0.1", 1563 | "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", 1564 | "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", 1565 | "dev": true 1566 | }, 1567 | "minimatch": { 1568 | "version": "3.0.4", 1569 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1570 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1571 | "dev": true, 1572 | "requires": { 1573 | "brace-expansion": "^1.1.7" 1574 | } 1575 | }, 1576 | "minimist": { 1577 | "version": "1.2.5", 1578 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", 1579 | "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", 1580 | "dev": true 1581 | }, 1582 | "ms": { 1583 | "version": "2.1.2", 1584 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1585 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 1586 | "dev": true 1587 | }, 1588 | "mute-stream": { 1589 | "version": "0.0.8", 1590 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", 1591 | "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", 1592 | "dev": true 1593 | }, 1594 | "normalize-package-data": { 1595 | "version": "2.5.0", 1596 | "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", 1597 | "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", 1598 | "dev": true, 1599 | "requires": { 1600 | "hosted-git-info": "^2.1.4", 1601 | "resolve": "^1.10.0", 1602 | "semver": "2 || 3 || 4 || 5", 1603 | "validate-npm-package-license": "^3.0.1" 1604 | } 1605 | }, 1606 | "normalize-path": { 1607 | "version": "3.0.0", 1608 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1609 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1610 | "dev": true 1611 | }, 1612 | "normalize-url": { 1613 | "version": "4.5.0", 1614 | "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", 1615 | "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==", 1616 | "dev": true 1617 | }, 1618 | "once": { 1619 | "version": "1.4.0", 1620 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1621 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1622 | "dev": true, 1623 | "requires": { 1624 | "wrappy": "1" 1625 | } 1626 | }, 1627 | "onetime": { 1628 | "version": "5.1.0", 1629 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", 1630 | "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", 1631 | "dev": true, 1632 | "requires": { 1633 | "mimic-fn": "^2.1.0" 1634 | } 1635 | }, 1636 | "ora": { 1637 | "version": "4.0.4", 1638 | "resolved": "https://registry.npmjs.org/ora/-/ora-4.0.4.tgz", 1639 | "integrity": "sha512-77iGeVU1cIdRhgFzCK8aw1fbtT1B/iZAvWjS+l/o1x0RShMgxHUZaD2yDpWsNCPwXg9z1ZA78Kbdvr8kBmG/Ww==", 1640 | "dev": true, 1641 | "requires": { 1642 | "chalk": "^3.0.0", 1643 | "cli-cursor": "^3.1.0", 1644 | "cli-spinners": "^2.2.0", 1645 | "is-interactive": "^1.0.0", 1646 | "log-symbols": "^3.0.0", 1647 | "mute-stream": "0.0.8", 1648 | "strip-ansi": "^6.0.0", 1649 | "wcwidth": "^1.0.1" 1650 | }, 1651 | "dependencies": { 1652 | "chalk": { 1653 | "version": "3.0.0", 1654 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", 1655 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", 1656 | "dev": true, 1657 | "requires": { 1658 | "ansi-styles": "^4.1.0", 1659 | "supports-color": "^7.1.0" 1660 | } 1661 | } 1662 | } 1663 | }, 1664 | "p-cancelable": { 1665 | "version": "1.1.0", 1666 | "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", 1667 | "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", 1668 | "dev": true 1669 | }, 1670 | "p-defer": { 1671 | "version": "1.0.0", 1672 | "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", 1673 | "integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=", 1674 | "dev": true 1675 | }, 1676 | "p-limit": { 1677 | "version": "2.3.0", 1678 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1679 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1680 | "dev": true, 1681 | "requires": { 1682 | "p-try": "^2.0.0" 1683 | } 1684 | }, 1685 | "p-locate": { 1686 | "version": "4.1.0", 1687 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1688 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1689 | "dev": true, 1690 | "requires": { 1691 | "p-limit": "^2.2.0" 1692 | } 1693 | }, 1694 | "p-map": { 1695 | "version": "4.0.0", 1696 | "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", 1697 | "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", 1698 | "dev": true, 1699 | "requires": { 1700 | "aggregate-error": "^3.0.0" 1701 | } 1702 | }, 1703 | "p-try": { 1704 | "version": "2.2.0", 1705 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1706 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 1707 | "dev": true 1708 | }, 1709 | "package-json": { 1710 | "version": "6.5.0", 1711 | "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", 1712 | "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", 1713 | "dev": true, 1714 | "requires": { 1715 | "got": "^9.6.0", 1716 | "registry-auth-token": "^4.0.0", 1717 | "registry-url": "^5.0.0", 1718 | "semver": "^6.2.0" 1719 | }, 1720 | "dependencies": { 1721 | "semver": { 1722 | "version": "6.3.0", 1723 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 1724 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 1725 | "dev": true 1726 | } 1727 | } 1728 | }, 1729 | "parse-json": { 1730 | "version": "4.0.0", 1731 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", 1732 | "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", 1733 | "dev": true, 1734 | "requires": { 1735 | "error-ex": "^1.3.1", 1736 | "json-parse-better-errors": "^1.0.1" 1737 | } 1738 | }, 1739 | "parse-ms": { 1740 | "version": "2.1.0", 1741 | "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", 1742 | "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", 1743 | "dev": true 1744 | }, 1745 | "path-exists": { 1746 | "version": "4.0.0", 1747 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1748 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1749 | "dev": true 1750 | }, 1751 | "path-is-absolute": { 1752 | "version": "1.0.1", 1753 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1754 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1755 | "dev": true 1756 | }, 1757 | "path-parse": { 1758 | "version": "1.0.6", 1759 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1760 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 1761 | "dev": true 1762 | }, 1763 | "path-type": { 1764 | "version": "4.0.0", 1765 | "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", 1766 | "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", 1767 | "dev": true 1768 | }, 1769 | "picomatch": { 1770 | "version": "2.2.2", 1771 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", 1772 | "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", 1773 | "dev": true 1774 | }, 1775 | "pify": { 1776 | "version": "4.0.1", 1777 | "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", 1778 | "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", 1779 | "dev": true 1780 | }, 1781 | "pkg-conf": { 1782 | "version": "3.1.0", 1783 | "resolved": "https://registry.npmjs.org/pkg-conf/-/pkg-conf-3.1.0.tgz", 1784 | "integrity": "sha512-m0OTbR/5VPNPqO1ph6Fqbj7Hv6QU7gR/tQW40ZqrL1rjgCU85W6C1bJn0BItuJqnR98PWzw7Z8hHeChD1WrgdQ==", 1785 | "dev": true, 1786 | "requires": { 1787 | "find-up": "^3.0.0", 1788 | "load-json-file": "^5.2.0" 1789 | }, 1790 | "dependencies": { 1791 | "find-up": { 1792 | "version": "3.0.0", 1793 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", 1794 | "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", 1795 | "dev": true, 1796 | "requires": { 1797 | "locate-path": "^3.0.0" 1798 | } 1799 | }, 1800 | "locate-path": { 1801 | "version": "3.0.0", 1802 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", 1803 | "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", 1804 | "dev": true, 1805 | "requires": { 1806 | "p-locate": "^3.0.0", 1807 | "path-exists": "^3.0.0" 1808 | } 1809 | }, 1810 | "p-locate": { 1811 | "version": "3.0.0", 1812 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", 1813 | "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", 1814 | "dev": true, 1815 | "requires": { 1816 | "p-limit": "^2.0.0" 1817 | } 1818 | }, 1819 | "path-exists": { 1820 | "version": "3.0.0", 1821 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1822 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1823 | "dev": true 1824 | } 1825 | } 1826 | }, 1827 | "pkg-dir": { 1828 | "version": "4.2.0", 1829 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 1830 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 1831 | "dev": true, 1832 | "requires": { 1833 | "find-up": "^4.0.0" 1834 | } 1835 | }, 1836 | "plur": { 1837 | "version": "4.0.0", 1838 | "resolved": "https://registry.npmjs.org/plur/-/plur-4.0.0.tgz", 1839 | "integrity": "sha512-4UGewrYgqDFw9vV6zNV+ADmPAUAfJPKtGvb/VdpQAx25X5f3xXdGdyOEVFwkl8Hl/tl7+xbeHqSEM+D5/TirUg==", 1840 | "dev": true, 1841 | "requires": { 1842 | "irregular-plurals": "^3.2.0" 1843 | } 1844 | }, 1845 | "prepend-http": { 1846 | "version": "2.0.0", 1847 | "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", 1848 | "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", 1849 | "dev": true 1850 | }, 1851 | "pretty-ms": { 1852 | "version": "6.0.1", 1853 | "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-6.0.1.tgz", 1854 | "integrity": "sha512-ke4njoVmlotekHlHyCZ3wI/c5AMT8peuHs8rKJqekj/oR5G8lND2dVpicFlUz5cbZgE290vvkMuDwfj/OcW1kw==", 1855 | "dev": true, 1856 | "requires": { 1857 | "parse-ms": "^2.1.0" 1858 | } 1859 | }, 1860 | "pump": { 1861 | "version": "3.0.0", 1862 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1863 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1864 | "dev": true, 1865 | "requires": { 1866 | "end-of-stream": "^1.1.0", 1867 | "once": "^1.3.1" 1868 | } 1869 | }, 1870 | "pupa": { 1871 | "version": "2.0.1", 1872 | "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", 1873 | "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", 1874 | "dev": true, 1875 | "requires": { 1876 | "escape-goat": "^2.0.0" 1877 | } 1878 | }, 1879 | "rc": { 1880 | "version": "1.2.8", 1881 | "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", 1882 | "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", 1883 | "dev": true, 1884 | "requires": { 1885 | "deep-extend": "^0.6.0", 1886 | "ini": "~1.3.0", 1887 | "minimist": "^1.2.0", 1888 | "strip-json-comments": "~2.0.1" 1889 | } 1890 | }, 1891 | "read-pkg": { 1892 | "version": "5.2.0", 1893 | "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", 1894 | "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", 1895 | "dev": true, 1896 | "requires": { 1897 | "@types/normalize-package-data": "^2.4.0", 1898 | "normalize-package-data": "^2.5.0", 1899 | "parse-json": "^5.0.0", 1900 | "type-fest": "^0.6.0" 1901 | }, 1902 | "dependencies": { 1903 | "parse-json": { 1904 | "version": "5.0.0", 1905 | "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", 1906 | "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", 1907 | "dev": true, 1908 | "requires": { 1909 | "@babel/code-frame": "^7.0.0", 1910 | "error-ex": "^1.3.1", 1911 | "json-parse-better-errors": "^1.0.1", 1912 | "lines-and-columns": "^1.1.6" 1913 | } 1914 | }, 1915 | "type-fest": { 1916 | "version": "0.6.0", 1917 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", 1918 | "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", 1919 | "dev": true 1920 | } 1921 | } 1922 | }, 1923 | "readdirp": { 1924 | "version": "3.4.0", 1925 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", 1926 | "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", 1927 | "dev": true, 1928 | "requires": { 1929 | "picomatch": "^2.2.1" 1930 | } 1931 | }, 1932 | "registry-auth-token": { 1933 | "version": "4.1.1", 1934 | "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", 1935 | "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", 1936 | "dev": true, 1937 | "requires": { 1938 | "rc": "^1.2.8" 1939 | } 1940 | }, 1941 | "registry-url": { 1942 | "version": "5.1.0", 1943 | "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", 1944 | "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", 1945 | "dev": true, 1946 | "requires": { 1947 | "rc": "^1.2.8" 1948 | } 1949 | }, 1950 | "require-directory": { 1951 | "version": "2.1.1", 1952 | "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", 1953 | "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", 1954 | "dev": true 1955 | }, 1956 | "require-main-filename": { 1957 | "version": "2.0.0", 1958 | "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", 1959 | "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", 1960 | "dev": true 1961 | }, 1962 | "resolve": { 1963 | "version": "1.17.0", 1964 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", 1965 | "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", 1966 | "dev": true, 1967 | "requires": { 1968 | "path-parse": "^1.0.6" 1969 | } 1970 | }, 1971 | "resolve-cwd": { 1972 | "version": "3.0.0", 1973 | "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", 1974 | "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", 1975 | "dev": true, 1976 | "requires": { 1977 | "resolve-from": "^5.0.0" 1978 | } 1979 | }, 1980 | "resolve-from": { 1981 | "version": "5.0.0", 1982 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", 1983 | "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", 1984 | "dev": true 1985 | }, 1986 | "responselike": { 1987 | "version": "1.0.2", 1988 | "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", 1989 | "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", 1990 | "dev": true, 1991 | "requires": { 1992 | "lowercase-keys": "^1.0.0" 1993 | } 1994 | }, 1995 | "restore-cursor": { 1996 | "version": "3.1.0", 1997 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 1998 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 1999 | "dev": true, 2000 | "requires": { 2001 | "onetime": "^5.1.0", 2002 | "signal-exit": "^3.0.2" 2003 | } 2004 | }, 2005 | "reusify": { 2006 | "version": "1.0.4", 2007 | "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", 2008 | "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", 2009 | "dev": true 2010 | }, 2011 | "rimraf": { 2012 | "version": "3.0.2", 2013 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 2014 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 2015 | "dev": true, 2016 | "requires": { 2017 | "glob": "^7.1.3" 2018 | } 2019 | }, 2020 | "run-parallel": { 2021 | "version": "1.1.9", 2022 | "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.1.9.tgz", 2023 | "integrity": "sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q==", 2024 | "dev": true 2025 | }, 2026 | "safe-buffer": { 2027 | "version": "5.1.2", 2028 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 2029 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", 2030 | "dev": true 2031 | }, 2032 | "semver": { 2033 | "version": "5.7.1", 2034 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 2035 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", 2036 | "dev": true 2037 | }, 2038 | "semver-diff": { 2039 | "version": "3.1.1", 2040 | "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", 2041 | "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", 2042 | "dev": true, 2043 | "requires": { 2044 | "semver": "^6.3.0" 2045 | }, 2046 | "dependencies": { 2047 | "semver": { 2048 | "version": "6.3.0", 2049 | "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", 2050 | "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", 2051 | "dev": true 2052 | } 2053 | } 2054 | }, 2055 | "serialize-error": { 2056 | "version": "2.1.0", 2057 | "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", 2058 | "integrity": "sha1-ULZ51WNc34Rme9yOWa9OW4HV9go=", 2059 | "dev": true 2060 | }, 2061 | "set-blocking": { 2062 | "version": "2.0.0", 2063 | "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", 2064 | "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", 2065 | "dev": true 2066 | }, 2067 | "signal-exit": { 2068 | "version": "3.0.3", 2069 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", 2070 | "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", 2071 | "dev": true 2072 | }, 2073 | "slash": { 2074 | "version": "3.0.0", 2075 | "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", 2076 | "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", 2077 | "dev": true 2078 | }, 2079 | "slice-ansi": { 2080 | "version": "3.0.0", 2081 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", 2082 | "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", 2083 | "dev": true, 2084 | "requires": { 2085 | "ansi-styles": "^4.0.0", 2086 | "astral-regex": "^2.0.0", 2087 | "is-fullwidth-code-point": "^3.0.0" 2088 | } 2089 | }, 2090 | "source-map": { 2091 | "version": "0.6.1", 2092 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2093 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2094 | "dev": true 2095 | }, 2096 | "source-map-support": { 2097 | "version": "0.5.19", 2098 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", 2099 | "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", 2100 | "dev": true, 2101 | "requires": { 2102 | "buffer-from": "^1.0.0", 2103 | "source-map": "^0.6.0" 2104 | } 2105 | }, 2106 | "spdx-correct": { 2107 | "version": "3.1.0", 2108 | "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.0.tgz", 2109 | "integrity": "sha512-lr2EZCctC2BNR7j7WzJ2FpDznxky1sjfxvvYEyzxNyb6lZXHODmEoJeFu4JupYlkfha1KZpJyoqiJ7pgA1qq8Q==", 2110 | "dev": true, 2111 | "requires": { 2112 | "spdx-expression-parse": "^3.0.0", 2113 | "spdx-license-ids": "^3.0.0" 2114 | } 2115 | }, 2116 | "spdx-exceptions": { 2117 | "version": "2.3.0", 2118 | "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", 2119 | "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", 2120 | "dev": true 2121 | }, 2122 | "spdx-expression-parse": { 2123 | "version": "3.0.0", 2124 | "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", 2125 | "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", 2126 | "dev": true, 2127 | "requires": { 2128 | "spdx-exceptions": "^2.1.0", 2129 | "spdx-license-ids": "^3.0.0" 2130 | } 2131 | }, 2132 | "spdx-license-ids": { 2133 | "version": "3.0.5", 2134 | "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.5.tgz", 2135 | "integrity": "sha512-J+FWzZoynJEXGphVIS+XEh3kFSjZX/1i9gFBaWQcB+/tmpe2qUsSBABpcxqxnAxFdiUFEgAX1bjYGQvIZmoz9Q==", 2136 | "dev": true 2137 | }, 2138 | "sprintf-js": { 2139 | "version": "1.0.3", 2140 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 2141 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 2142 | "dev": true 2143 | }, 2144 | "stack-utils": { 2145 | "version": "2.0.2", 2146 | "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.2.tgz", 2147 | "integrity": "sha512-0H7QK2ECz3fyZMzQ8rH0j2ykpfbnd20BFtfg/SqVC2+sCTtcw0aDTGB7dk+de4U4uUeuz6nOtJcrkFFLG1B0Rg==", 2148 | "dev": true, 2149 | "requires": { 2150 | "escape-string-regexp": "^2.0.0" 2151 | }, 2152 | "dependencies": { 2153 | "escape-string-regexp": { 2154 | "version": "2.0.0", 2155 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", 2156 | "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", 2157 | "dev": true 2158 | } 2159 | } 2160 | }, 2161 | "string-width": { 2162 | "version": "4.2.0", 2163 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 2164 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 2165 | "dev": true, 2166 | "requires": { 2167 | "emoji-regex": "^8.0.0", 2168 | "is-fullwidth-code-point": "^3.0.0", 2169 | "strip-ansi": "^6.0.0" 2170 | } 2171 | }, 2172 | "strip-ansi": { 2173 | "version": "6.0.0", 2174 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 2175 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 2176 | "dev": true, 2177 | "requires": { 2178 | "ansi-regex": "^5.0.0" 2179 | } 2180 | }, 2181 | "strip-bom": { 2182 | "version": "3.0.0", 2183 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 2184 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 2185 | "dev": true 2186 | }, 2187 | "strip-json-comments": { 2188 | "version": "2.0.1", 2189 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 2190 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 2191 | "dev": true 2192 | }, 2193 | "supertap": { 2194 | "version": "1.0.0", 2195 | "resolved": "https://registry.npmjs.org/supertap/-/supertap-1.0.0.tgz", 2196 | "integrity": "sha512-HZJ3geIMPgVwKk2VsmO5YHqnnJYl6bV5A9JW2uzqV43WmpgliNEYbuvukfor7URpaqpxuw3CfZ3ONdVbZjCgIA==", 2197 | "dev": true, 2198 | "requires": { 2199 | "arrify": "^1.0.1", 2200 | "indent-string": "^3.2.0", 2201 | "js-yaml": "^3.10.0", 2202 | "serialize-error": "^2.1.0", 2203 | "strip-ansi": "^4.0.0" 2204 | }, 2205 | "dependencies": { 2206 | "ansi-regex": { 2207 | "version": "3.0.0", 2208 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 2209 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 2210 | "dev": true 2211 | }, 2212 | "arrify": { 2213 | "version": "1.0.1", 2214 | "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", 2215 | "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", 2216 | "dev": true 2217 | }, 2218 | "indent-string": { 2219 | "version": "3.2.0", 2220 | "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz", 2221 | "integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok=", 2222 | "dev": true 2223 | }, 2224 | "strip-ansi": { 2225 | "version": "4.0.0", 2226 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2227 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2228 | "dev": true, 2229 | "requires": { 2230 | "ansi-regex": "^3.0.0" 2231 | } 2232 | } 2233 | } 2234 | }, 2235 | "supports-color": { 2236 | "version": "7.1.0", 2237 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", 2238 | "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", 2239 | "dev": true, 2240 | "requires": { 2241 | "has-flag": "^4.0.0" 2242 | } 2243 | }, 2244 | "temp-dir": { 2245 | "version": "2.0.0", 2246 | "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", 2247 | "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", 2248 | "dev": true 2249 | }, 2250 | "term-size": { 2251 | "version": "2.2.0", 2252 | "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", 2253 | "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==", 2254 | "dev": true 2255 | }, 2256 | "time-zone": { 2257 | "version": "1.0.0", 2258 | "resolved": "https://registry.npmjs.org/time-zone/-/time-zone-1.0.0.tgz", 2259 | "integrity": "sha1-mcW/VZWJZq9tBtg73zgA3IL67F0=", 2260 | "dev": true 2261 | }, 2262 | "to-readable-stream": { 2263 | "version": "1.0.0", 2264 | "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", 2265 | "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", 2266 | "dev": true 2267 | }, 2268 | "to-regex-range": { 2269 | "version": "5.0.1", 2270 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2271 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2272 | "dev": true, 2273 | "requires": { 2274 | "is-number": "^7.0.0" 2275 | } 2276 | }, 2277 | "trim-off-newlines": { 2278 | "version": "1.0.1", 2279 | "resolved": "https://registry.npmjs.org/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz", 2280 | "integrity": "sha1-n5up2e+odkw4dpi8v+sshI8RrbM=", 2281 | "dev": true 2282 | }, 2283 | "type-fest": { 2284 | "version": "0.3.1", 2285 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.3.1.tgz", 2286 | "integrity": "sha512-cUGJnCdr4STbePCgqNFbpVNCepa+kAVohJs1sLhxzdH+gnEoOd8VhbYa7pD3zZYGiURWM2xzEII3fQcRizDkYQ==", 2287 | "dev": true 2288 | }, 2289 | "typedarray-to-buffer": { 2290 | "version": "3.1.5", 2291 | "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", 2292 | "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", 2293 | "dev": true, 2294 | "requires": { 2295 | "is-typedarray": "^1.0.0" 2296 | } 2297 | }, 2298 | "unique-string": { 2299 | "version": "2.0.0", 2300 | "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", 2301 | "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", 2302 | "dev": true, 2303 | "requires": { 2304 | "crypto-random-string": "^2.0.0" 2305 | } 2306 | }, 2307 | "update-notifier": { 2308 | "version": "4.1.0", 2309 | "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", 2310 | "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", 2311 | "dev": true, 2312 | "requires": { 2313 | "boxen": "^4.2.0", 2314 | "chalk": "^3.0.0", 2315 | "configstore": "^5.0.1", 2316 | "has-yarn": "^2.1.0", 2317 | "import-lazy": "^2.1.0", 2318 | "is-ci": "^2.0.0", 2319 | "is-installed-globally": "^0.3.1", 2320 | "is-npm": "^4.0.0", 2321 | "is-yarn-global": "^0.3.0", 2322 | "latest-version": "^5.0.0", 2323 | "pupa": "^2.0.1", 2324 | "semver-diff": "^3.1.1", 2325 | "xdg-basedir": "^4.0.0" 2326 | }, 2327 | "dependencies": { 2328 | "chalk": { 2329 | "version": "3.0.0", 2330 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", 2331 | "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", 2332 | "dev": true, 2333 | "requires": { 2334 | "ansi-styles": "^4.1.0", 2335 | "supports-color": "^7.1.0" 2336 | } 2337 | } 2338 | } 2339 | }, 2340 | "url-parse-lax": { 2341 | "version": "3.0.0", 2342 | "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", 2343 | "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", 2344 | "dev": true, 2345 | "requires": { 2346 | "prepend-http": "^2.0.0" 2347 | } 2348 | }, 2349 | "validate-npm-package-license": { 2350 | "version": "3.0.4", 2351 | "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", 2352 | "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", 2353 | "dev": true, 2354 | "requires": { 2355 | "spdx-correct": "^3.0.0", 2356 | "spdx-expression-parse": "^3.0.0" 2357 | } 2358 | }, 2359 | "wcwidth": { 2360 | "version": "1.0.1", 2361 | "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", 2362 | "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", 2363 | "dev": true, 2364 | "requires": { 2365 | "defaults": "^1.0.3" 2366 | } 2367 | }, 2368 | "well-known-symbols": { 2369 | "version": "2.0.0", 2370 | "resolved": "https://registry.npmjs.org/well-known-symbols/-/well-known-symbols-2.0.0.tgz", 2371 | "integrity": "sha512-ZMjC3ho+KXo0BfJb7JgtQ5IBuvnShdlACNkKkdsqBmYw3bPAaJfPeYUo6tLUaT5tG/Gkh7xkpBhKRQ9e7pyg9Q==", 2372 | "dev": true 2373 | }, 2374 | "which-module": { 2375 | "version": "2.0.0", 2376 | "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", 2377 | "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", 2378 | "dev": true 2379 | }, 2380 | "widest-line": { 2381 | "version": "3.1.0", 2382 | "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", 2383 | "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", 2384 | "dev": true, 2385 | "requires": { 2386 | "string-width": "^4.0.0" 2387 | } 2388 | }, 2389 | "wrap-ansi": { 2390 | "version": "6.2.0", 2391 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 2392 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 2393 | "dev": true, 2394 | "requires": { 2395 | "ansi-styles": "^4.0.0", 2396 | "string-width": "^4.1.0", 2397 | "strip-ansi": "^6.0.0" 2398 | } 2399 | }, 2400 | "wrappy": { 2401 | "version": "1.0.2", 2402 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2403 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2404 | "dev": true 2405 | }, 2406 | "write-file-atomic": { 2407 | "version": "3.0.3", 2408 | "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", 2409 | "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", 2410 | "dev": true, 2411 | "requires": { 2412 | "imurmurhash": "^0.1.4", 2413 | "is-typedarray": "^1.0.0", 2414 | "signal-exit": "^3.0.2", 2415 | "typedarray-to-buffer": "^3.1.5" 2416 | } 2417 | }, 2418 | "xdg-basedir": { 2419 | "version": "4.0.0", 2420 | "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", 2421 | "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", 2422 | "dev": true 2423 | }, 2424 | "y18n": { 2425 | "version": "4.0.0", 2426 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", 2427 | "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", 2428 | "dev": true 2429 | }, 2430 | "yargs": { 2431 | "version": "15.3.1", 2432 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", 2433 | "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", 2434 | "dev": true, 2435 | "requires": { 2436 | "cliui": "^6.0.0", 2437 | "decamelize": "^1.2.0", 2438 | "find-up": "^4.1.0", 2439 | "get-caller-file": "^2.0.1", 2440 | "require-directory": "^2.1.1", 2441 | "require-main-filename": "^2.0.0", 2442 | "set-blocking": "^2.0.0", 2443 | "string-width": "^4.2.0", 2444 | "which-module": "^2.0.0", 2445 | "y18n": "^4.0.0", 2446 | "yargs-parser": "^18.1.1" 2447 | } 2448 | }, 2449 | "yargs-parser": { 2450 | "version": "18.1.3", 2451 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", 2452 | "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", 2453 | "dev": true, 2454 | "requires": { 2455 | "camelcase": "^5.0.0", 2456 | "decamelize": "^1.2.0" 2457 | } 2458 | } 2459 | } 2460 | } 2461 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "parser-lang", 3 | "version": "0.4.0", 4 | "description": "A parser combinator library for JavaScript with declarative superpowers", 5 | "type": "module", 6 | "main": "main.mjs", 7 | "keywords": [ 8 | "parsing", 9 | "parse", 10 | "parser combinators", 11 | "template literals" 12 | ], 13 | "scripts": { 14 | "test": "ava" 15 | }, 16 | "author": "Tim Disney", 17 | "license": "MIT", 18 | "repository": { 19 | "type": "git", 20 | "url": "https://github.com/disnet/parser-lang.git" 21 | }, 22 | "prettier": { 23 | "singleQuote": true, 24 | "trailingComma": "es5" 25 | }, 26 | "devDependencies": { 27 | "ava": "^3.8.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | [![npm version](https://badge.fury.io/js/parser-lang.svg)](https://badge.fury.io/js/parser-lang) [![Build Status](https://travis-ci.org/disnet/parser-lang.svg?branch=master)](https://travis-ci.org/disnet/parser-lang) [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-v1.4%20adopted-ff69b4.svg)](code-of-conduct.md) 2 | 3 | # ParserLang 4 | 5 | ParserLang is parser combinator library. It lets you make parsers by combining other parsers. 6 | 7 | Its primary superpower is the ability to define parsers declaratively with template literals: 8 | 9 | ```js 10 | import { lang } from 'parser-lang'; 11 | 12 | let { calc } = lang` 13 | num = /[0-9]+/ > ${ch => parseInt(ch, 10)}; 14 | 15 | addExpr = num '+' multExpr > ${([left, op, right]) => left + right} 16 | | num ; 17 | 18 | multExpr = addExpr '*' multExpr > ${([left, op, right]) => left * right} 19 | | addExpr ; 20 | 21 | calc = multExpr ; 22 | `; 23 | 24 | calc.tryParse('1+1*2'); 25 | // 3 26 | ``` 27 | 28 | It's monadic and stuff but don't get too hung up on that. It tries to be very friendly. 29 | 30 | ## Installing 31 | 32 | ```sh 33 | npm install parser-lang 34 | ``` 35 | 36 | ## Documentation 37 | 38 | - [Tutorial](./docs/tutorial.md) 39 | - [API Reference](./docs/api-reference.md) 40 | 41 | ## Related Projects/Papers 42 | 43 | - [Parsimmon](https://github.com/jneen/parsimmon) - a JavaScript parser combinator library. ParserLang is heavily inspired by Parsimmon. Parsimmon is more coupled to parsing strings (ParserLang uses the [Context protocol](./docs/api-reference.md#context) to support a variety of input types) but also supports a wider variety of JavaScript runtimes. 44 | - [Parsec](http://hackage.haskell.org/package/parsec) - a Haskell parser combinator library 45 | - [Monadic Parser Combinators](http://www.cs.nott.ac.uk/~pszgmh/monparsing.pdf) - one of the seminal papers describing parser combinators 46 | -------------------------------------------------------------------------------- /src/context-with-holes.mjs: -------------------------------------------------------------------------------- 1 | import Context from './context.mjs'; 2 | 3 | const holeSymbol = Symbol('ContextWithHoles.hole'); 4 | export default class ContextWithHoles { 5 | constructor(parts, holes, index = 0, currentPart = 0, currentHole = 0) { 6 | this.parts = parts; 7 | this.holes = holes; 8 | this.index = index; 9 | this.currentPart = currentPart; 10 | this.currentHole = currentHole; 11 | if (this.holes.length !== this.parts.length - 1) { 12 | throw new Error( 13 | `The number of parts (${ 14 | this.parts.length 15 | }) must be one more than the number of holes (${this.holes.length})` 16 | ); 17 | } 18 | } 19 | 20 | [Context.regex](re) { 21 | let array = this.parts[this.currentPart]; 22 | if (typeof array !== 'string') { 23 | throw new Error('Matching by regex only supported for string contexts'); 24 | } 25 | if (array.length > 0 && this.index < array.length) { 26 | let match = re.exec(array.slice(this.index)); 27 | if (match && match.index === 0) { 28 | let result = match[0]; 29 | this.index += result.length; 30 | return { 31 | done: false, 32 | value: match[0], 33 | }; 34 | } 35 | } 36 | return { 37 | done: true, 38 | }; 39 | } 40 | 41 | [Context.next]() { 42 | if (this.currentPart < this.parts.length) { 43 | let array = this.parts[this.currentPart]; 44 | if (this.index < array.length) { 45 | return { 46 | done: false, 47 | value: array[this.index++], 48 | }; 49 | } else if (this.currentHole < this.holes.length) { 50 | this.currentPart++; 51 | let hole = this.holes[this.currentHole++]; 52 | this.index = 0; 53 | return { 54 | done: false, 55 | value: { 56 | [holeSymbol]: hole, 57 | }, 58 | }; 59 | } 60 | } 61 | return { 62 | done: true, 63 | }; 64 | } 65 | 66 | next() { 67 | return this[Context.next](); 68 | } 69 | 70 | [Context.clone]() { 71 | return new ContextWithHoles( 72 | this.parts, 73 | this.holes, 74 | this.index, 75 | this.currentPart, 76 | this.currentHole 77 | ); 78 | } 79 | 80 | [Symbol.iterator]() { 81 | return this; 82 | } 83 | } 84 | 85 | ContextWithHoles.hole = holeSymbol; 86 | -------------------------------------------------------------------------------- /src/context.mjs: -------------------------------------------------------------------------------- 1 | const cloneSymbol = Symbol('Context.clone'); 2 | const regexSymbol = Symbol('Context.regex'); 3 | 4 | export default class Context { 5 | constructor(array, index = 0) { 6 | this.array = array; 7 | this.index = index; 8 | } 9 | 10 | static of(...values) { 11 | return new Context(values); 12 | } 13 | 14 | static from(arrayLike) { 15 | if (typeof arrayLike[Context.clone] === 'function') { 16 | return arrayLike; 17 | } else if (typeof arrayLike === 'string') { 18 | return new Context(arrayLike); 19 | } 20 | return new Context(Array.from(arrayLike)); 21 | } 22 | 23 | static empty() { 24 | return new Context([]); 25 | } 26 | 27 | next() { 28 | if (this.array.length > 0 && this.index < this.array.length) { 29 | return { 30 | done: false, 31 | value: this.array[this.index++], 32 | }; 33 | } 34 | return { 35 | done: true, 36 | }; 37 | } 38 | 39 | [regexSymbol](re) { 40 | if (typeof this.array !== 'string') { 41 | throw new Error('Matching by regex only supported for string contexts'); 42 | } 43 | if (this.array.length > 0 && this.index < this.array.length) { 44 | let match = re.exec(this.array.slice(this.index)); 45 | if (match && match.index === 0) { 46 | let result = match[0]; 47 | this.index += result.length; 48 | return { 49 | done: false, 50 | value: match[0], 51 | }; 52 | } 53 | } 54 | return { 55 | done: true, 56 | }; 57 | } 58 | 59 | // the point of Context.clone is to give immutable clones 60 | [cloneSymbol]() { 61 | return new Context(this.array, this.index); 62 | } 63 | 64 | [Symbol.iterator]() { 65 | return this; 66 | } 67 | } 68 | 69 | Context.clone = cloneSymbol; 70 | Context.regex = regexSymbol; 71 | -------------------------------------------------------------------------------- /src/lang.mjs: -------------------------------------------------------------------------------- 1 | import Parser, { 2 | sequence, 3 | alternatives, 4 | char, 5 | satisfy, 6 | regex, 7 | empty, 8 | lazy, 9 | succeed, 10 | string, 11 | item, 12 | } from './parser.mjs'; 13 | import StateContext from './state-context.mjs'; 14 | import ContextWithHoles from './context-with-holes.mjs'; 15 | import { Outcome, Failure } from './outcome.mjs'; 16 | 17 | const snd = ([, x]) => x; 18 | 19 | class Token { 20 | constructor(type, value) { 21 | this.type = type; 22 | this.value = value; 23 | } 24 | toString() { 25 | return `Token { type = ${this.type}, value = ${this.value} }`; 26 | } 27 | } 28 | const emptySigal = {}; 29 | function isToken(type, value = emptySigal) { 30 | return satisfy( 31 | x => { 32 | if (x != null && x.type === type) { 33 | return value === emptySigal || value === x.value; 34 | } 35 | return false; 36 | }, 37 | c => 38 | `${c} is not a token with type ${type}${ 39 | value === empty ? '' : ` or value ${value}` 40 | }` 41 | ); 42 | } 43 | class Rule { 44 | constructor(name, definition) { 45 | this.name = name; 46 | this.definition = definition; 47 | } 48 | } 49 | 50 | const hole = satisfy(o => { 51 | return o != null && typeof o === 'object' && ContextWithHoles.hole in o; 52 | }); 53 | 54 | const whitespace = regex(/[ \t\n]+/); 55 | const optWhitespace = whitespace.or(succeed('')); 56 | 57 | const identStart = regex(/[a-zA-Z]/); 58 | const identRest = regex(/[a-zA-Z0-9]*/).or(succeed('')); 59 | const ident = sequence(identStart, identRest).tie(); 60 | 61 | const isLineTerminator = ch => 62 | ch === 0x0a || ch === 0x0d || ch === 0x2028 || ch === 0x2029; 63 | 64 | const nonEscapedStringCharacter = satisfy( 65 | ch => ch !== "'" && ch !== '\\' && ch !== '\n' 66 | ); 67 | 68 | const hexDigit = alternatives( 69 | satisfy(ch => ch >= '0' && ch <= '9').map(ch => ch.charCodeAt(0) - 48), 70 | satisfy(ch => ch >= 'a' && ch <= 'f').map(ch => ch.charCodeAt(0) - 87), 71 | satisfy(ch => ch >= 'A' && ch <= 'F').map(ch => ch.charCodeAt(0) - 55) 72 | ); 73 | const hexDigits = hexDigit 74 | .atLeast(1) 75 | .map(hexCodes => hexCodes.reduce((acc, hex) => (acc << 4) | hex, 0)) 76 | .map(unescaped => String.fromCodePoint(unescaped)); 77 | 78 | const escapedStringCharacter = char('\\').then( 79 | alternatives( 80 | char('n').result('\n'), 81 | char('r').result('\r'), 82 | char('t').result('\t'), 83 | char('b').result('\b'), 84 | char('f').result('\f'), 85 | char('v').result('\v'), 86 | char('u').then( 87 | alternatives(sequence(char('{'), hexDigits, char('}')).map(snd)) 88 | ), 89 | item() 90 | ) 91 | ); 92 | 93 | const stringLiteral = sequence( 94 | char("'"), 95 | alternatives(nonEscapedStringCharacter, escapedStringCharacter) 96 | .many() 97 | .tie(), 98 | char("'") 99 | ).map(snd); 100 | 101 | const slash = char('/'); 102 | const reFlags = regex(/[gimuy]+/).or(succeed('')); 103 | const looseRegexPattern = alternatives( 104 | sequence(regex(/\\\\/).map(s => '\\'), char('/')).tie(), 105 | regex(/[^\n\/]+/) 106 | ) 107 | .many() 108 | .tie(); 109 | 110 | const punctuator = alternatives( 111 | char('='), 112 | char('|'), 113 | char('('), 114 | char(')'), 115 | char('*'), 116 | char('+'), 117 | char(';'), 118 | char('!'), 119 | string('>>'), 120 | char('>'), 121 | char('@') 122 | ); 123 | 124 | export const lex = sequence( 125 | optWhitespace, 126 | alternatives( 127 | sequence(slash, looseRegexPattern, slash, reFlags, optWhitespace).map( 128 | ([, body, , flags]) => new Token('regex', { body, flags }) 129 | ), 130 | sequence(ident, optWhitespace).map(([value]) => new Token('ident', value)), 131 | sequence(hole, optWhitespace).map( 132 | ([value]) => new Token('hole', value[ContextWithHoles.hole]) 133 | ), 134 | sequence(stringLiteral, optWhitespace).map( 135 | ([value]) => new Token('string', value) 136 | ), 137 | sequence(punctuator, optWhitespace).map( 138 | ([value]) => new Token('punctuator', value) 139 | ) 140 | ).many() 141 | ).map(snd); 142 | 143 | const isPunctuatorToken = value => isToken('punctuator', value); 144 | 145 | const identToken = isToken('ident'); 146 | const stringToken = isToken('string'); 147 | const holeToken = isToken('hole'); 148 | const regexToken = isToken('regex'); 149 | 150 | const eqToken = isPunctuatorToken('='); 151 | const pipeToken = isPunctuatorToken('|'); 152 | const starToken = isPunctuatorToken('*'); 153 | const plusToken = isPunctuatorToken('+'); 154 | const openParenToken = isPunctuatorToken('('); 155 | const closeParenToken = isPunctuatorToken(')'); 156 | const semicolonToken = isPunctuatorToken(';'); 157 | const bangToken = isPunctuatorToken('!'); 158 | const rarrowToken = isPunctuatorToken('>'); 159 | const chainToken = isPunctuatorToken('>>'); 160 | const atToken = isPunctuatorToken('@'); 161 | 162 | function getState(f) { 163 | return new Parser(ctx => { 164 | if (typeof ctx[StateContext.state] !== 'function') { 165 | return new Failure('State does not exist on the context'); 166 | } 167 | let state = ctx[StateContext.state](); 168 | 169 | return Outcome.of({ 170 | value: succeed().chain(() => { 171 | return f(state); 172 | }), 173 | ctx, 174 | }); 175 | }); 176 | } 177 | 178 | const identDefinition = identToken.chain(({ value: name }) => 179 | getState(state => state[name]) 180 | ); 181 | 182 | const stringLiteralDefinition = stringToken.map(({ value }) => string(value)); 183 | 184 | const satisfiesDefinition = bangToken 185 | .then(holeToken) 186 | .map(({ value: satFunc }) => satisfy(satFunc)); 187 | 188 | const parserHoleDefinition = atToken 189 | .then(holeToken) 190 | .map(({ value: parser }) => parser); 191 | 192 | const regexDefinition = regexToken.map(({ value: { body, flags } }) => 193 | regex(new RegExp(body, flags)) 194 | ); 195 | 196 | const primDefinition = lazy(() => 197 | alternatives( 198 | stringLiteralDefinition, 199 | identDefinition, 200 | regexDefinition, 201 | satisfiesDefinition, 202 | parserHoleDefinition, 203 | sequence(openParenToken, definition, closeParenToken).map(snd) 204 | ) 205 | ); 206 | 207 | const baseDefinition = alternatives( 208 | sequence(primDefinition, starToken).map(([p]) => p.many()), 209 | sequence(primDefinition, plusToken).map(([p]) => p.atLeast(1)), 210 | primDefinition 211 | ); 212 | 213 | const isMapToken = t => t != null && t.type === 'punctuator' && t.value === '>'; 214 | 215 | const mapDefinition = sequence( 216 | alternatives( 217 | baseDefinition.atLeast(2).map(defs => sequence(...defs)), 218 | baseDefinition 219 | ), 220 | sequence(alternatives(rarrowToken, chainToken), holeToken).many() 221 | ).map(([base, maps]) => maps.reduce((acc, [t, { value: f }]) => isMapToken(t) ? acc.map(f) : acc.chain(f), base)); 222 | 223 | const sequenceDefinition = mapDefinition 224 | .many() 225 | .map(rest => (rest.length === 1 ? rest[0] : sequence(...rest))); 226 | 227 | const alternativeDefinition = sequence( 228 | sequenceDefinition, 229 | sequence(pipeToken, sequenceDefinition).many() 230 | ).map(([first, rest]) => 231 | alternatives(...[first].concat(rest.map(([, p]) => p))) 232 | ); 233 | 234 | const definition = alternativeDefinition; 235 | 236 | const rule = sequence(identToken, eqToken, definition, semicolonToken).map( 237 | ([name, , definition]) => new Rule(name.value, definition) 238 | ); 239 | 240 | const rules = rule.many(); 241 | 242 | export default function lang({ raw: strings }, ...args) { 243 | let lexemes = lex.tryParse(new ContextWithHoles(strings, args)); 244 | let state = {}; 245 | let parseValue = rules.tryParse(StateContext.from(lexemes, state)); 246 | 247 | parseValue.forEach(({ name, definition }) => { 248 | state[name] = definition; 249 | }); 250 | return state; 251 | } 252 | -------------------------------------------------------------------------------- /src/outcome.mjs: -------------------------------------------------------------------------------- 1 | export class Outcome { 2 | static of(result) { 3 | return new Success(result); 4 | } 5 | map(f) { 6 | mustImplement(); 7 | } 8 | forEach(f) { 9 | mustImplement(); 10 | } 11 | chain(f) { 12 | mustImplement(); 13 | } 14 | } 15 | export class Success extends Outcome { 16 | constructor(result) { 17 | super(); 18 | this.success = true; 19 | this.result = result; 20 | } 21 | 22 | // f: A => B 23 | // ret: Outcome 24 | map(f) { 25 | return new Success(f(this.result)); 26 | } 27 | 28 | // f: A => void 29 | // ret: Outcome 30 | forEach(f) { 31 | f(this.result); 32 | return this; 33 | } 34 | 35 | // f: A => Outcome 36 | // ret: Outcome 37 | chain(f) { 38 | return f(this.result); 39 | } 40 | } 41 | 42 | export class Failure extends Outcome { 43 | constructor(error, subErrors) { 44 | super(); 45 | this.success = false; 46 | this.result = error; 47 | this.subErrors = subErrors; 48 | } 49 | 50 | toString() { 51 | return `Failure { result: ${this.result}, subErrors: ${this.subErrors} }`; 52 | } 53 | 54 | // f: A => B 55 | // ret: Outcome 56 | map(f) { 57 | return this; 58 | } 59 | 60 | // f: A => void 61 | // ret: Outcome 62 | forEach(f) { 63 | return this; 64 | } 65 | 66 | // f: A => Outcome 67 | // ret: Outcome 68 | chain(f) { 69 | return this; 70 | } 71 | } 72 | 73 | function mustImplement() { 74 | throw new Error('Must implement'); 75 | } 76 | -------------------------------------------------------------------------------- /src/parser.mjs: -------------------------------------------------------------------------------- 1 | import { Outcome, Failure } from './outcome.mjs'; 2 | import Context from './context.mjs'; 3 | 4 | export default class Parser { 5 | // action: Context => Outcome 6 | constructor(action) { 7 | this.action = action; 8 | } 9 | 10 | // ctx: Context 11 | // ret: Outcome 12 | parse(ctx) { 13 | return this.action(Context.from(ctx)); 14 | } 15 | 16 | tryParse(ctx) { 17 | let outcome = this.parse(ctx); 18 | if (!outcome.success) throw new Error(outcome); 19 | return outcome.result.value; 20 | } 21 | 22 | static of(value) { 23 | return new Parser(ctx => 24 | Outcome.of({ 25 | value, 26 | ctx, 27 | }) 28 | ); 29 | } 30 | 31 | static failure(msg) { 32 | return new Parser(_ => new Failure(msg)); 33 | } 34 | 35 | // ret: Parser 36 | static zero() { 37 | return Parser.failure(''); 38 | } 39 | 40 | // f: A => B 41 | // ret: Parser 42 | map(f) { 43 | return new Parser(ctx => 44 | this.parse(ctx).chain(({ value, ctx }) => 45 | Outcome.of({ 46 | value: f(value), 47 | ctx, 48 | }) 49 | ) 50 | ); 51 | } 52 | 53 | debug(f = console.log) { 54 | return new Parser(ctx => 55 | this.parse(ctx).chain(({ value, ctx }) => { 56 | f(value); 57 | return Outcome.of({ 58 | value, 59 | ctx, 60 | }); 61 | }) 62 | ); 63 | } 64 | 65 | // parser: Parser B, Context> 66 | // ret: Parser 67 | ap(parser) { 68 | return new Parser(ctx => 69 | this.parse(ctx).chain(({ value: a, ctx }) => 70 | parser.parse(ctx).chain(({ value: f, ctx }) => 71 | Outcome.of({ 72 | value: f(a), 73 | ctx, 74 | }) 75 | ) 76 | ) 77 | ); 78 | } 79 | 80 | // other: Parser 81 | // ret: Parser 82 | alt(other) { 83 | return new Parser(ctx => { 84 | let outcome = this.parse(ctx); 85 | if (!outcome.success) { 86 | return other.parse(ctx); 87 | } 88 | return outcome; 89 | }); 90 | } 91 | 92 | // other: Parser 93 | // ret: Parser 94 | or(other) { 95 | return this.alt(other); 96 | } 97 | 98 | then(other) { 99 | return sequence(this, other).map(([fst, snd]) => snd); 100 | } 101 | 102 | skip(other) { 103 | return sequence(this, other).map(([fst, snd]) => fst); 104 | } 105 | 106 | // f: A => Parser 107 | // ret: Parser 108 | chain(f) { 109 | return new Parser(ctx => 110 | this.parse(ctx).chain(({ value, ctx }) => f(value).parse(ctx)) 111 | ); 112 | } 113 | 114 | // ret: Parser, Context> 115 | many() { 116 | return this.between(); 117 | } 118 | 119 | // n: number >= 0 120 | // max?: number >= 0 121 | // ret: Parser, Context> 122 | times(n, max = n) { 123 | return this.between(n, max); 124 | } 125 | 126 | // n: number >= 0 127 | // ret: Parser, Context> 128 | atMost(n) { 129 | return this.between(0, n); 130 | } 131 | 132 | // n: number >= 0 133 | // ret: Parser, Context> 134 | atLeast(n) { 135 | return this.between(n); 136 | } 137 | 138 | between(requiredLowerBound = 0, requiredUpperBound = Infinity) { 139 | return new Parser(ctx => { 140 | let matches = 0, 141 | values = [], 142 | nextCtx = ctx, 143 | lastCtx = ctx, 144 | value, 145 | success; 146 | do { 147 | ({ 148 | success, 149 | result: { value, ctx: nextCtx }, 150 | } = this.parse(nextCtx)); 151 | if (success) { 152 | ++matches; 153 | values.push(value); 154 | lastCtx = nextCtx; 155 | if (matches > requiredUpperBound) { 156 | return new Failure( 157 | `Expected an upper bound of ${requiredUpperBound} but matched ${matches} times` 158 | ); 159 | } 160 | } 161 | } while (success); 162 | if (matches >= requiredLowerBound) { 163 | return Outcome.of({ 164 | value: values, 165 | ctx: lastCtx, 166 | }); 167 | } 168 | return new Failure( 169 | `Expected a lower bound of ${requiredLowerBound} but matched ${matches} times` 170 | ); 171 | }); 172 | } 173 | 174 | // sep: Parser 175 | // ret: Parser, Context> 176 | sepBy1(sep) { 177 | return this.chain(x => 178 | sep 179 | .chain(() => this.chain(y => Parser.of(y))) 180 | .atLeast(1) 181 | .chain(xs => Parser.of(xs.concat(x))) 182 | ); 183 | } 184 | 185 | // sep: Parser 186 | // ret: Parser, Context> 187 | sepBy(sep) { 188 | return this.sepBy1(sep).alt(Parser.of([])); 189 | } 190 | 191 | result(value) { 192 | return this.map(() => value); 193 | } 194 | 195 | tie(sep = '') { 196 | return this.map(a => a.join(sep)); 197 | } 198 | 199 | // ops: Array<{ 200 | // type: 'left' | 'right' | 'prefix' 201 | // prec: number, 202 | // action: A => B | (A, A) => B 203 | // }> 204 | // ret: Parser 205 | operators(ops) { 206 | let infixOps = alternatives( 207 | ...ops 208 | .filter(op => op.type === 'left' || op.type === 'right') 209 | .reduce( 210 | (acc, op) => 211 | acc.concat( 212 | op.parser.result({ 213 | assoc: op.type, 214 | prec: op.prec, 215 | action: op.action, 216 | }) 217 | ), 218 | [] 219 | ) 220 | ); 221 | let prefixOps = alternatives( 222 | ...ops 223 | .filter(op => op.type === 'prefix') 224 | .reduce( 225 | (acc, op) => 226 | acc.concat( 227 | op.parser.result({ 228 | assoc: op.type, 229 | prec: op.prec, 230 | action: op.action, 231 | }) 232 | ), 233 | [] 234 | ) 235 | ); 236 | 237 | return new Parser(ctx => { 238 | let stack = []; 239 | let prec = 0; 240 | let assoc = 'left'; 241 | let action = x => x; 242 | let nextCtx = ctx; 243 | while (true) { 244 | let outcome = this.parse(nextCtx); 245 | if (!outcome.success) { 246 | if (prefixOps != null) { 247 | let opOutcome = prefixOps.parse(nextCtx); 248 | if ( 249 | opOutcome.success && 250 | opOutcome.result.value.assoc === 'prefix' 251 | ) { 252 | stack.push({ 253 | prec, 254 | assoc, 255 | action, 256 | }); 257 | assoc = opOutcome.result.value.assoc; 258 | prec = opOutcome.result.value.prec; 259 | action = opOutcome.result.value.action; 260 | nextCtx = opOutcome.result.ctx; 261 | continue; 262 | } 263 | } 264 | return new Failure('Did not match item in operator'); 265 | } else { 266 | nextCtx = outcome.result.ctx; 267 | } 268 | 269 | let opOutcome = infixOps.parse(nextCtx); 270 | if (opOutcome.success) { 271 | if (ltAssoc(assoc, prec, opOutcome.result.value.prec)) { 272 | stack.push({ 273 | prec, 274 | assoc, 275 | action, 276 | }); 277 | prec = opOutcome.result.value.prec; 278 | assoc = opOutcome.result.value.assoc; 279 | action = opOutcome.result.value.action.bind( 280 | null, 281 | outcome.result.value 282 | ); 283 | } else { 284 | let left = action(outcome.result.value); 285 | prec = opOutcome.result.value.prec; 286 | assoc = opOutcome.result.value.assoc; 287 | action = opOutcome.result.value.action.bind(null, left); 288 | } 289 | nextCtx = opOutcome.result.ctx; 290 | } else { 291 | let value = action(outcome.result.value); 292 | while (stack.length > 0) { 293 | ({ action } = stack.pop()); 294 | value = action(value); 295 | } 296 | return Outcome.of({ 297 | value, 298 | ctx: nextCtx, 299 | }); 300 | } 301 | } 302 | }); 303 | } 304 | } 305 | 306 | function ltAssoc(assoc, l, r) { 307 | switch (assoc) { 308 | case 'left': 309 | return l < r; 310 | case 'right': 311 | return r <= l; 312 | case 'prefix': 313 | return r <= l; 314 | default: 315 | throw new Error(`Unimplemented association ${assoc}`); 316 | } 317 | } 318 | 319 | export function lazy(f) { 320 | return succeed().chain(() => f()); 321 | } 322 | 323 | export function succeed(value) { 324 | return new Parser(ctx => { 325 | return Outcome.of({ value, ctx }); 326 | }); 327 | } 328 | 329 | export function empty() { 330 | return new Parser(ctx => { 331 | let nextCtx = ctx[Context.clone]()[Symbol.iterator](); 332 | let result = nextCtx.next(); 333 | if (result.done) { 334 | return Outcome.of({ 335 | value: void 0, 336 | ctx: nextCtx, 337 | }); 338 | } 339 | return new Failure('list not empty'); 340 | }); 341 | } 342 | 343 | // ret: Parser 344 | export function item() { 345 | return new Parser(ctx => { 346 | let nextCtx = ctx[Context.clone]()[Symbol.iterator](); 347 | let result = nextCtx.next(); 348 | if (result.done) { 349 | return new Failure('list is empty'); 350 | } 351 | return Outcome.of({ 352 | value: result.value, 353 | ctx: nextCtx, 354 | }); 355 | }); 356 | } 357 | 358 | export function string(s) { 359 | return new Parser(ctx => { 360 | let nextCtx = ctx[Context.clone]()[Symbol.iterator](); 361 | for (let toMatch of s) { 362 | let x = nextCtx.next(); 363 | if (x.done || x.value !== toMatch) 364 | return new Failure(`The prefix ${s} did not match`); 365 | } 366 | return Outcome.of({ 367 | value: s, 368 | ctx: nextCtx, 369 | }); 370 | }); 371 | } 372 | 373 | // f: A => boolean 374 | // ret: Parser 375 | export function satisfy(f, failMsg = c => `${c} did not satisfy predicate`) { 376 | return item().chain(item => 377 | f(item) ? Parser.of(item) : Parser.failure(failMsg(item)) 378 | ); 379 | } 380 | 381 | // f: (A, B) => C 382 | // ret: (Parser, Parser) => Parser 383 | export function lift2(f) { 384 | return (a, b) => a.chain(va => b.chain(vb => Parser.of(f(va, vb)))); 385 | } 386 | 387 | // ...parser: Parser 388 | // ret: Parser, Context> 389 | export function sequence(...parsers) { 390 | return new Parser(ctx => { 391 | let result = []; 392 | let nextCtx = ctx; 393 | for (let p of parsers) { 394 | let outcome = p.parse(nextCtx); 395 | if (!outcome.success) { 396 | return new Failure(`Sequence failed`, outcome); 397 | } 398 | result.push(outcome.result.value); 399 | nextCtx = outcome.result.ctx; 400 | } 401 | return Outcome.of({ 402 | value: result, 403 | ctx: nextCtx, 404 | }); 405 | }); 406 | } 407 | 408 | // ...parser: Parser 409 | // ret: Parser 410 | export function alternatives(...parser) { 411 | return new Parser(ctx => { 412 | let failures = []; 413 | for (let p of parser) { 414 | let outcome = p.parse(ctx); 415 | if (outcome.success) return outcome; 416 | failures.push(outcome); 417 | } 418 | return new Failure('No alternatives matched', failures); 419 | }); 420 | } 421 | 422 | export function char(ch) { 423 | return satisfy(c => c === ch); 424 | } 425 | 426 | function anchorRegexAtStart(re) { 427 | return new RegExp(`^${re.source}`, re.flags); 428 | } 429 | 430 | export function regex(rawRegex) { 431 | let re = anchorRegexAtStart(rawRegex); 432 | return new Parser(ctx => { 433 | let nextCtx = ctx[Context.clone](); 434 | let result = nextCtx[Context.regex](re); 435 | if (result.done) return new Failure(`Did not match regex ${rawRegex}`); 436 | return Outcome.of({ 437 | value: result.value, 438 | ctx: nextCtx, 439 | }); 440 | }); 441 | } 442 | -------------------------------------------------------------------------------- /src/state-context.mjs: -------------------------------------------------------------------------------- 1 | import Context from './context.mjs'; 2 | 3 | const stateSymbol = Symbol('StateContext.state'); 4 | export default class StateContext { 5 | constructor(context, state = {}) { 6 | this.context = context; 7 | this.state = state; 8 | } 9 | 10 | static from(arrayLike, state = {}) { 11 | return new StateContext(Context.from(arrayLike), state); 12 | } 13 | 14 | [stateSymbol]() { 15 | return this.state; 16 | } 17 | 18 | next() { 19 | return this.context.next(); 20 | } 21 | 22 | [Context.regex](re) { 23 | return this.context[Context.regex](re); 24 | } 25 | 26 | [Context.clone]() { 27 | return new StateContext(this.context[Context.clone](), this.state); 28 | } 29 | 30 | [Symbol.iterator]() { 31 | return this; 32 | } 33 | } 34 | StateContext.state = stateSymbol; 35 | -------------------------------------------------------------------------------- /test/snapshots/test-lexer.js.md: -------------------------------------------------------------------------------- 1 | # Snapshot report for `test/test-lexer.js` 2 | 3 | The actual snapshot is saved in `test-lexer.js.snap`. 4 | 5 | Generated by [AVA](https://ava.li). 6 | 7 | ## can lex a hole 8 | 9 | > Snapshot 1 10 | 11 | [ 12 | Token { 13 | type: 'ident', 14 | value: 'a', 15 | }, 16 | Token { 17 | type: 'punctuator', 18 | value: '=', 19 | }, 20 | Token { 21 | type: 'hole', 22 | value: 'b', 23 | }, 24 | Token { 25 | type: 'punctuator', 26 | value: ';', 27 | }, 28 | ] 29 | -------------------------------------------------------------------------------- /test/snapshots/test-lexer.js.snap: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/disnet/parser-lang/896696d552ae850fabe8ae504a7e6a28294e43fd/test/snapshots/test-lexer.js.snap -------------------------------------------------------------------------------- /test/test-context-with-holes.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import ContextWithHoles from '../src/context-with-holes.mjs'; 3 | import Context from '../src/context.mjs'; 4 | 5 | test('no holes', t => { 6 | let c = new ContextWithHoles(['abc'], []); 7 | 8 | t.is(c.next().value, 'a'); 9 | t.is(c.next().value, 'b'); 10 | t.is(c.next().value, 'c'); 11 | t.true(c.next().done); 12 | }); 13 | 14 | test('unmatched number of parts and holes', t => { 15 | t.throws(() => new ContextWithHoles([], [])); 16 | t.throws(() => new ContextWithHoles(['abc'], [() => null])); 17 | t.throws(() => new ContextWithHoles([], [() => null])); 18 | }); 19 | 20 | test('empty strings with a single hole', t => { 21 | let c = new ContextWithHoles(['', ''], [() => 'b']); 22 | 23 | t.is(c.next().value[ContextWithHoles.hole](), 'b'); 24 | t.true(c.next().done); 25 | }); 26 | 27 | test('single strings with a single hole', t => { 28 | let c = new ContextWithHoles(['a', 'c'], [() => 'b']); 29 | 30 | t.is(c.next().value, 'a'); 31 | t.is(c.next().value[ContextWithHoles.hole](), 'b'); 32 | t.is(c.next().value, 'c'); 33 | t.true(c.next().done); 34 | }); 35 | 36 | test('regex matching in the middle of a part', t => { 37 | let c = new ContextWithHoles(['abc', 'c'], [() => 'b']); 38 | 39 | t.is(c.next().value, 'a'); 40 | t.is(c[Context.regex](/b/).value, 'b'); 41 | t.is(c.next().value, 'c'); 42 | t.is(c.next().value[ContextWithHoles.hole](), 'b'); 43 | t.is(c.next().value, 'c'); 44 | t.true(c.next().done); 45 | }); 46 | 47 | test('regex matching to the end of a part', t => { 48 | let c = new ContextWithHoles(['abc', 'c'], [() => 'b']); 49 | 50 | t.is(c.next().value, 'a'); 51 | t.is(c[Context.regex](/bc/).value, 'bc'); 52 | t.is(c.next().value[ContextWithHoles.hole](), 'b'); 53 | t.is(c.next().value, 'c'); 54 | t.true(c.next().done); 55 | }); 56 | -------------------------------------------------------------------------------- /test/test-lang.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import lang from '../src/lang.mjs'; 3 | import { empty, succeed } from '../src/parser.mjs'; 4 | 5 | test('lang with a single token literal rule', t => { 6 | let { a } = lang` 7 | a = 'a'; 8 | `; 9 | 10 | t.deepEqual(a.tryParse('a'), 'a'); 11 | t.throws(() => a.tryParse('b')); 12 | t.throws(() => a.tryParse('')); 13 | }); 14 | 15 | test('lang with a multi char single token literal rule', t => { 16 | let { a } = lang` 17 | a = 'foo'; 18 | `; 19 | 20 | t.deepEqual(a.tryParse('foo'), 'foo'); 21 | t.throws(() => a.tryParse('f')); 22 | t.throws(() => a.tryParse('')); 23 | }); 24 | 25 | test('lang with a string with escape sequences', t => { 26 | let { a, b, c, d, e } = lang` 27 | a = '\n'; 28 | b = '\t'; 29 | c = '\u{ffff}'; 30 | d = '\\'; 31 | e = '\z'; 32 | `; 33 | 34 | t.deepEqual(a.tryParse('\n'), '\n'); 35 | t.deepEqual(b.tryParse('\t'), '\t'); 36 | t.deepEqual(c.tryParse('\u{ffff}'), '\u{ffff}'); 37 | t.deepEqual(d.tryParse('\\'), '\\'); 38 | t.deepEqual(e.tryParse('z'), 'z'); 39 | t.throws(() => a.tryParse('f')); 40 | t.throws(() => a.tryParse('')); 41 | }); 42 | 43 | test('lang with regex rule', t => { 44 | let { a } = lang` 45 | a = /foo/i; 46 | `; 47 | 48 | t.deepEqual(a.tryParse('Foo'), 'Foo'); 49 | t.deepEqual(a.tryParse('foo'), 'foo'); 50 | t.throws(() => a.tryParse('f')); 51 | t.throws(() => a.tryParse('')); 52 | }); 53 | 54 | test('lang with regex rule with escaped slash', t => { 55 | let { a } = lang` 56 | a = /\\//i; 57 | `; 58 | 59 | t.deepEqual(a.tryParse('/'), '/'); 60 | t.throws(() => a.tryParse('f')); 61 | t.throws(() => a.tryParse('')); 62 | }); 63 | 64 | test('lang with regex rule with escaped paren', t => { 65 | let { a } = lang` 66 | a = /\(/i; 67 | `; 68 | 69 | t.deepEqual(a.tryParse('('), '('); 70 | t.throws(() => a.tryParse('f')); 71 | t.throws(() => a.tryParse('')); 72 | }); 73 | 74 | test('lang with a single token literal rule with star', t => { 75 | let { a } = lang` 76 | a = 'a'*; 77 | `; 78 | 79 | t.deepEqual(a.tryParse(''), []); 80 | t.deepEqual(a.tryParse('a'), ['a']); 81 | t.deepEqual(a.tryParse('aaa'), ['a', 'a', 'a']); 82 | }); 83 | 84 | test('lang with a single token literal rule with plus', t => { 85 | let { a } = lang` 86 | a = 'a'+; 87 | `; 88 | 89 | t.throws(() => a.tryParse('')); 90 | t.deepEqual(a.tryParse('a'), ['a']); 91 | t.deepEqual(a.tryParse('aaa'), ['a', 'a', 'a']); 92 | }); 93 | 94 | test('lang with a sequence of token literals', t => { 95 | let { a } = lang` 96 | a = 'a' 'b'; 97 | `; 98 | 99 | t.deepEqual(a.tryParse('ab'), ['a', 'b']); 100 | t.throws(() => a.tryParse('')); 101 | t.throws(() => a.tryParse('a')); 102 | t.throws(() => a.tryParse('ba')); 103 | }); 104 | 105 | test('lang with alternation of token literals', t => { 106 | let { a } = lang` 107 | a = 'a' | 'b'; 108 | `; 109 | 110 | t.deepEqual(a.tryParse('a'), 'a'); 111 | t.deepEqual(a.tryParse('b'), 'b'); 112 | t.deepEqual(a.tryParse('bc'), 'b'); 113 | t.deepEqual(a.tryParse('ba'), 'b'); 114 | t.deepEqual(a.tryParse('bb'), 'b'); 115 | t.throws(() => a.tryParse('')); 116 | t.throws(() => a.tryParse('c')); 117 | }); 118 | 119 | test('lang with sequence of an alternative', t => { 120 | let { a } = lang` 121 | a = 'a' | 'b' 'c'; 122 | `; 123 | 124 | t.deepEqual(a.tryParse('a'), 'a'); 125 | t.deepEqual(a.tryParse('abc'), 'a'); 126 | t.deepEqual(a.tryParse('bc'), ['b', 'c']); 127 | t.throws(() => a.tryParse('')); 128 | t.throws(() => a.tryParse('b')); 129 | t.throws(() => a.tryParse('c')); 130 | }); 131 | 132 | test('lang with either "a" or many "b"', t => { 133 | let { a } = lang` 134 | a = 'a' | 'b'*; 135 | `; 136 | 137 | t.deepEqual(a.tryParse(''), []); 138 | t.deepEqual(a.tryParse('a'), 'a'); 139 | t.deepEqual(a.tryParse('b'), ['b']); 140 | t.deepEqual(a.tryParse('bb'), ['b', 'b']); 141 | }); 142 | 143 | test('lang with sequence of either "a" or "b"', t => { 144 | let { a } = lang` 145 | a = ('a' | 'b')*; 146 | `; 147 | 148 | t.deepEqual(a.tryParse(''), []); 149 | t.deepEqual(a.tryParse('a'), ['a']); 150 | t.deepEqual(a.tryParse('b'), ['b']); 151 | t.deepEqual(a.tryParse('abba'), ['a', 'b', 'b', 'a']); 152 | }); 153 | 154 | test('lang with two rules', t => { 155 | let { a, b } = lang` 156 | a = 'a'; 157 | b = 'b'; 158 | `; 159 | 160 | t.deepEqual(a.tryParse('a'), 'a'); 161 | t.throws(() => a.tryParse('b')); 162 | t.deepEqual(b.tryParse('b'), 'b'); 163 | t.throws(() => b.tryParse('a')); 164 | }); 165 | 166 | test('lang with two rules where b depends on a', t => { 167 | let { a, b } = lang` 168 | a = 'a'; 169 | b = a; 170 | `; 171 | 172 | t.throws(() => a.tryParse('')); 173 | t.throws(() => a.tryParse('b')); 174 | t.deepEqual(a.tryParse('a'), 'a'); 175 | 176 | t.throws(() => b.tryParse('')); 177 | t.throws(() => b.tryParse('b')); 178 | t.deepEqual(b.tryParse('a'), 'a'); 179 | }); 180 | 181 | test('lang with a sequence with two rules', t => { 182 | let { c } = lang` 183 | a = 'a'; 184 | b = 'b'; 185 | c = a b; 186 | `; 187 | t.throws(() => c.tryParse('')); 188 | t.throws(() => c.tryParse('a')); 189 | t.throws(() => c.tryParse('b')); 190 | t.deepEqual(c.tryParse('ab'), ['a', 'b']); 191 | }); 192 | 193 | test('lang with a satisfies hole', t => { 194 | let { a } = lang` 195 | a = !${ch => ch === 'a'}; 196 | `; 197 | 198 | t.deepEqual(a.tryParse('a'), 'a'); 199 | t.throws(() => a.tryParse('b')); 200 | t.throws(() => a.tryParse('')); 201 | }); 202 | 203 | test('lang with a parser hole', t => { 204 | let { a } = lang` 205 | a = @${empty()}; 206 | `; 207 | 208 | t.deepEqual(a.tryParse(''), void 0); 209 | t.throws(() => a.tryParse('b')); 210 | }); 211 | 212 | test('lang with a satisfies hole and a sequence', t => { 213 | let { a } = lang` 214 | a = !${ch => ch === 'a'} 'b'; 215 | `; 216 | 217 | t.throws(() => a.tryParse('b')); 218 | t.throws(() => a.tryParse('')); 219 | t.deepEqual(a.tryParse('ab'), ['a', 'b']); 220 | }); 221 | 222 | test('lang with a map', t => { 223 | let { a } = lang` 224 | a = 'a' > ${value => ({ value })} ; 225 | `; 226 | 227 | t.deepEqual(a.tryParse('a'), { value: 'a' }); 228 | }); 229 | 230 | test('map is under sequence', t => { 231 | let { a } = lang` 232 | a = 'a' 'b' > ${value => ({ value })} ; 233 | `; 234 | 235 | t.deepEqual(a.tryParse('ab'), { value: ['a', 'b'] }); 236 | }); 237 | 238 | test('map to the left of a sequence', t => { 239 | let { a } = lang` 240 | a = 'a' > ${value => ({ value })} 'b'; 241 | `; 242 | 243 | t.deepEqual(a.tryParse('ab'), [{ value: 'a' }, 'b']); 244 | }); 245 | 246 | test('map is under alternation', t => { 247 | let { a } = lang` 248 | a = 'a' | 'b' > ${value => ({ value })} ; 249 | `; 250 | 251 | t.deepEqual(a.tryParse('a'), 'a'); 252 | t.deepEqual(a.tryParse('b'), { value: 'b' }); 253 | }); 254 | 255 | test('lang with multiple maps that associate to the left', t => { 256 | let { a } = lang` 257 | a = 'a' > ${value => ({ value })} > ${o => o.value + 'b'} ; 258 | `; 259 | 260 | t.deepEqual(a.tryParse('a'), 'ab'); 261 | }); 262 | 263 | test('lang with a chain', t => { 264 | let { a } = lang` 265 | a = 'a' >> ${value => succeed({ value })} ; 266 | `; 267 | 268 | t.deepEqual(a.tryParse('a'), { value: 'a' }); 269 | }); 270 | 271 | test('calc language', t => { 272 | const { multExpr } = lang` 273 | num = /[0-9]+/ > ${ch => parseInt(ch, 10)}; 274 | 275 | addExpr = num '+' multExpr > ${([left, op, right]) => left + right} 276 | | num ; 277 | 278 | multExpr = addExpr '*' multExpr > ${([left, op, right]) => left * right} 279 | | addExpr ; 280 | `; 281 | 282 | t.deepEqual(multExpr.tryParse('1'), 1); 283 | t.deepEqual(multExpr.tryParse('12'), 12); 284 | t.deepEqual(multExpr.tryParse('1+1'), 2); 285 | t.deepEqual(multExpr.tryParse('1+1*2'), 3); 286 | t.deepEqual(multExpr.tryParse('1*1+2'), 3); 287 | }); 288 | -------------------------------------------------------------------------------- /test/test-lexer.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import ContextWithHoles from '../src/context-with-holes.mjs'; 3 | import { lex } from '../src/lang.mjs'; 4 | 5 | test('can lex a hole', t => { 6 | t.snapshot(lex.tryParse(new ContextWithHoles(['a = ', ';'], ['b']))); 7 | }); 8 | -------------------------------------------------------------------------------- /test/test-parser.js: -------------------------------------------------------------------------------- 1 | import test from 'ava'; 2 | import Parser, { 3 | item, 4 | empty, 5 | satisfy, 6 | lift2, 7 | sequence, 8 | alternatives, 9 | char, 10 | string, 11 | } from '../src/parser.mjs'; 12 | 13 | test('item() from array-likes', t => { 14 | t.true(item().parse('123').success); 15 | t.true(item().parse([1, 2, 3]).success); 16 | t.true( 17 | item().parse({ 18 | 0: 1, 19 | length: 1, 20 | }).success 21 | ); 22 | 23 | t.false(item().parse('').success); 24 | t.false(item().parse([]).success); 25 | t.false( 26 | item().parse({ 27 | length: 0, 28 | }).success 29 | ); 30 | }); 31 | 32 | test('empty() from array-likes', t => { 33 | t.true(empty().parse('').success); 34 | t.true(empty().parse([]).success); 35 | t.true( 36 | empty().parse({ 37 | length: 0, 38 | }).success 39 | ); 40 | 41 | t.false(empty().parse('123').success); 42 | t.false(empty().parse([1, 2, 3]).success); 43 | t.false( 44 | empty().parse({ 45 | 0: 1, 46 | length: 1, 47 | }).success 48 | ); 49 | }); 50 | 51 | test('satisfy() from array-likes', t => { 52 | t.true(satisfy(x => x === 1).parse([1]).success); 53 | t.true(satisfy(x => x === '1').parse('1').success); 54 | t.true( 55 | satisfy(x => x === 1).parse({ 56 | 0: 1, 57 | length: 1, 58 | }).success 59 | ); 60 | 61 | t.false(satisfy(x => x === 1).parse([2]).success); 62 | t.false(satisfy(x => x === '1').parse('2').success); 63 | t.false( 64 | satisfy(x => x === 1).parse({ 65 | 0: 2, 66 | length: 1, 67 | }).success 68 | ); 69 | }); 70 | 71 | test('string works', t => { 72 | t.throws(() => string('foo').tryParse('')); 73 | t.throws(() => string('foo').tryParse('f')); 74 | t.throws(() => string('foo').tryParse('fo')); 75 | t.throws(() => string('foo').tryParse('boo')); 76 | t.throws(() => string('foo').tryParse('xfoo')); 77 | 78 | t.is(string('foo').tryParse('foo'), 'foo'); 79 | t.is(string('foo').tryParse('foobar'), 'foo'); 80 | t.is(string('').tryParse('foobar'), ''); 81 | t.is(string('').tryParse(''), ''); 82 | }); 83 | 84 | test('Parser#map', t => { 85 | t.is( 86 | Parser.of(1) 87 | .map(x => x + 1) 88 | .parse([]).result.value, 89 | 2 90 | ); 91 | }); 92 | 93 | test('Parser#chain', t => { 94 | t.false( 95 | Parser.of(1) 96 | .chain(x => Parser.zero()) 97 | .parse([]).success 98 | ); 99 | 100 | t.is( 101 | Parser.of(1) 102 | .chain(x => Parser.of(x + 1)) 103 | .parse([]).result.value, 104 | 2 105 | ); 106 | }); 107 | 108 | test('Parser#ap', t => { 109 | t.is( 110 | Parser.of(1) 111 | .ap(Parser.of(x => x + 1)) 112 | .parse([]).result.value, 113 | 2 114 | ); 115 | }); 116 | 117 | test('Parser#alt', t => { 118 | let one = satisfy(x => x === 1); 119 | let two = satisfy(x => x === 2); 120 | 121 | t.true(one.alt(two).parse([1]).success); 122 | t.true(one.alt(two).parse([2]).success); 123 | t.false(one.alt(two).parse([3]).success); 124 | t.false(two.alt(one).parse([3]).success); 125 | }); 126 | 127 | test('Parser#many', t => { 128 | let one = satisfy(x => x === 1).map(x => '' + x); 129 | 130 | t.true(one.many().parse([2]).success); 131 | t.deepEqual(one.many().parse([2]).result.value, []); 132 | 133 | t.deepEqual(one.many().parse([1, 2]).result.value, ['1']); 134 | 135 | t.deepEqual(one.many().parse([1, 1, 2]).result.value, ['1', '1']); 136 | }); 137 | 138 | test('times', t => { 139 | let one = satisfy(x => x === 1); 140 | 141 | t.false(one.times(1).parse([]).success); 142 | t.false(one.times(1).parse([1, 1]).success); 143 | 144 | t.true(one.times(1).parse([1]).success); 145 | 146 | t.false(one.times(1, 3).parse([]).success); 147 | t.false(one.times(1, 3).parse([1, 1, 1, 1]).success); 148 | 149 | t.true(one.times(1, 3).parse([1]).success); 150 | t.true(one.times(1, 3).parse([1, 1]).success); 151 | t.true(one.times(1, 3).parse([1, 1, 1]).success); 152 | }); 153 | 154 | test('atMost', t => { 155 | let one = satisfy(x => x === 1); 156 | 157 | t.false(one.atMost(2).parse([1, 1, 1]).success); 158 | 159 | t.true(one.atMost(2).parse([1, 1]).success); 160 | t.true(one.atMost(2).parse([1]).success); 161 | t.true(one.atMost(2).parse([]).success); 162 | }); 163 | 164 | test('atLeast', t => { 165 | let one = satisfy(x => x === 1); 166 | 167 | t.false(one.atLeast(2).parse([]).success); 168 | t.false(one.atLeast(2).parse([1]).success); 169 | 170 | t.true(one.atLeast(2).parse([1, 1]).success); 171 | t.true(one.atLeast(2).parse([1, 1, 1]).success); 172 | }); 173 | 174 | test('sepBy1', t => { 175 | let one = satisfy(x => x === 1).map(x => '' + x); 176 | let comma = satisfy(x => x === ','); 177 | 178 | t.false(one.sepBy1(comma).parse([]).success); 179 | t.false(one.sepBy1(comma).parse([1]).success); 180 | t.false(one.sepBy1(comma).parse([1, 1]).success); 181 | 182 | t.true(one.sepBy1(comma).parse([1, ',', 1]).success); 183 | t.deepEqual(one.sepBy1(comma).parse([1, ',', 1]).result.value, ['1', '1']); 184 | t.deepEqual(one.sepBy1(comma).parse([1, ',', 1, ',']).result.value, [ 185 | '1', 186 | '1', 187 | ]); 188 | t.deepEqual(one.sepBy1(comma).parse([1, ',', 1, ',', 1]).result.value, [ 189 | '1', 190 | '1', 191 | '1', 192 | ]); 193 | }); 194 | 195 | test('sepBy', t => { 196 | let one = satisfy(x => x === 1).map(x => '' + x); 197 | let comma = satisfy(x => x === ','); 198 | 199 | t.true(one.sepBy(comma).parse([]).success); 200 | t.deepEqual(one.sepBy(comma).parse([]).result.value, []); 201 | t.true(one.sepBy(comma).parse([1]).success); 202 | t.deepEqual(one.sepBy(comma).parse([1]).result.value, []); 203 | t.true(one.sepBy(comma).parse([1, 1]).success); 204 | t.deepEqual(one.sepBy(comma).parse([1, 1]).result.value, []); 205 | 206 | t.true(one.sepBy(comma).parse([1, ',', 1]).success); 207 | t.deepEqual(one.sepBy(comma).parse([1, ',', 1]).result.value, ['1', '1']); 208 | t.deepEqual(one.sepBy(comma).parse([1, ',', 1, ',']).result.value, [ 209 | '1', 210 | '1', 211 | ]); 212 | t.deepEqual(one.sepBy(comma).parse([1, ',', 1, ',', 1]).result.value, [ 213 | '1', 214 | '1', 215 | '1', 216 | ]); 217 | }); 218 | 219 | test('lift2', t => { 220 | let f = lift2((x, y) => x + y); 221 | 222 | t.true(f(Parser.of(1), Parser.of(2)).parse([]).success); 223 | t.deepEqual(f(Parser.of(1), Parser.of(2)).parse([]).result.value, 3); 224 | }); 225 | 226 | test('sequence', t => { 227 | let one = satisfy(x => x === 1).map(x => '' + x); 228 | let two = satisfy(x => x === 2).map(x => '' + x); 229 | 230 | t.false(sequence(one, two).parse([]).success); 231 | t.false(sequence(one, two).parse([1]).success); 232 | 233 | t.true(sequence(one, two).parse([1, 2]).success); 234 | t.deepEqual(sequence(one, two).parse([1, 2]).result.value, ['1', '2']); 235 | t.true(sequence(one, two).parse([1, 2, 3]).success); 236 | t.deepEqual(sequence(one, two).parse([1, 2, 3]).result.value, ['1', '2']); 237 | }); 238 | 239 | test('alternatives', t => { 240 | let one = satisfy(x => x === 1).map(x => '' + x); 241 | let two = satisfy(x => x === 2).map(x => '' + x); 242 | 243 | t.false(alternatives(one, two).parse([]).success); 244 | t.false(alternatives(one, two).parse([3]).success); 245 | t.false(alternatives(one, two).parse([3, 1]).success); 246 | 247 | t.true(alternatives(one, two).parse([1]).success); 248 | t.deepEqual(alternatives(one, two).parse([1]).result.value, '1'); 249 | t.deepEqual(alternatives(one, two).parse([2]).result.value, '2'); 250 | t.deepEqual(alternatives(one, two).parse([2, 1]).result.value, '2'); 251 | }); 252 | 253 | test('operator', t => { 254 | let number = satisfy(x => typeof x === 'number'); 255 | let basicOperators = [ 256 | { 257 | type: 'left', 258 | prec: 2, 259 | parser: char('+'), 260 | action(left, right) { 261 | return left + right; 262 | }, 263 | }, 264 | { 265 | type: 'left', 266 | prec: 3, 267 | parser: char('*'), 268 | action(left, right) { 269 | return left * right; 270 | }, 271 | }, 272 | { 273 | type: 'prefix', 274 | prec: 1, 275 | parser: char('-'), 276 | action(operand) { 277 | return -operand; 278 | }, 279 | }, 280 | { 281 | type: 'right', 282 | prec: 3, 283 | parser: char('/'), 284 | action(left, right) { 285 | return left / right; 286 | }, 287 | }, 288 | ]; 289 | 290 | t.false(number.operators(basicOperators).parse([]).success); 291 | t.false(number.operators(basicOperators).parse(['1']).success); 292 | 293 | t.true(number.operators(basicOperators).parse([1]).success); 294 | t.is(number.operators(basicOperators).parse([1, '+', 2]).result.value, 3); 295 | t.is( 296 | number.operators(basicOperators).parse([1, '+', 2, '*', 3]).result.value, 297 | 7 298 | ); 299 | t.is( 300 | number.operators(basicOperators).parse([2, '*', 3, '+', 1]).result.value, 301 | 7 302 | ); 303 | t.is( 304 | number.operators(basicOperators).parse([10, '/', 5, '/', 2]).result.value, 305 | 4 306 | ); 307 | t.is( 308 | number.operators(basicOperators).parse([1, '+', '-', 2]).result.value, 309 | -1 310 | ); 311 | t.is( 312 | number.operators(basicOperators).parse(['-', 2, '+', 1]).result.value, 313 | -1 314 | ); 315 | t.is( 316 | number 317 | .operators([ 318 | { 319 | type: 'left', 320 | prec: 2, 321 | parser: char('+'), 322 | action(left, right) { 323 | return left + right; 324 | }, 325 | }, 326 | { 327 | type: 'prefix', 328 | prec: 3, // bigger than plus prec 329 | parser: char('-'), 330 | action(operand) { 331 | return -operand; 332 | }, 333 | }, 334 | ]) 335 | .parse(['-', 2, '+', 1]).result.value, 336 | -3 337 | ); 338 | }); 339 | 340 | test('CSV parser', t => { 341 | let comma = char(','); 342 | let dquote = char('"'); 343 | let textdata = satisfy(c => 344 | /[\u{20}-\u{21}]|[\u{23}-\u{2B}]|[\u{2D}-\u{7E}]/u.test(c) 345 | ); 346 | let nonescaped = textdata.many().map(chars => chars.join('')); 347 | 348 | let escaped = sequence( 349 | dquote, 350 | alternatives(dquote.then(dquote), textdata, comma) 351 | .many() 352 | .map(chars => chars.join('')), 353 | dquote 354 | ).map(([q1, f, q2]) => f); 355 | 356 | let field = escaped.or(nonescaped); 357 | 358 | let record = sequence( 359 | field, 360 | sequence(comma, field) 361 | .map(([c, f]) => f) 362 | .many() 363 | ).map(([f, rest]) => [f].concat(rest)); 364 | 365 | t.deepEqual(record.parse('foo,bar').result.value, ['foo', 'bar']); 366 | 367 | t.deepEqual(record.parse('"foo","bar"').result.value, ['foo', 'bar']); 368 | 369 | t.deepEqual(record.parse('"foo","bar,baz"').result.value, ['foo', 'bar,baz']); 370 | 371 | t.deepEqual(record.parse('""""').result.value, ['"']); 372 | 373 | t.deepEqual(record.parse('"foo","bar,baz"""').result.value, [ 374 | 'foo', 375 | 'bar,baz"', 376 | ]); 377 | }); 378 | --------------------------------------------------------------------------------