pax_global_header 0000666 0000000 0000000 00000000064 13633624025 0014516 g ustar 00root root 0000000 0000000 52 comment=b96b989680be8259ed530876c1e6cb69608e19ef
yargs-parser-18.1.1/ 0000775 0000000 0000000 00000000000 13633624025 0014225 5 ustar 00root root 0000000 0000000 yargs-parser-18.1.1/.github/ 0000775 0000000 0000000 00000000000 13633624025 0015565 5 ustar 00root root 0000000 0000000 yargs-parser-18.1.1/.github/publish.yml 0000664 0000000 0000000 00000000057 13633624025 0017760 0 ustar 00root root 0000000 0000000 project: oss-automation
secretId: node-tooling
yargs-parser-18.1.1/.github/release-please.yml 0000664 0000000 0000000 00000000050 13633624025 0021172 0 ustar 00root root 0000000 0000000 releaseType: node
handleGHRelease: true
yargs-parser-18.1.1/.github/workflows/ 0000775 0000000 0000000 00000000000 13633624025 0017622 5 ustar 00root root 0000000 0000000 yargs-parser-18.1.1/.github/workflows/ci.yaml 0000664 0000000 0000000 00000001470 13633624025 0021103 0 ustar 00root root 0000000 0000000 on:
push:
branches:
- master
pull_request:
name: ci
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node: [8, 10, 12, 13]
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: ${{ matrix.node }}
- run: node --version
- run: npm install
- run: npm test
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 12
- run: npm install
- run: npm test
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- uses: actions/setup-node@v1
with:
node-version: 13
- run: npm install
- run: npm test
- run: npm run coverage
yargs-parser-18.1.1/.gitignore 0000664 0000000 0000000 00000000141 13633624025 0016211 0 ustar 00root root 0000000 0000000 .idea
.nyc_output
node_modules
.DS_Store
package-lock.json
./test/fixtures/package.json
coverage
yargs-parser-18.1.1/CHANGELOG.md 0000664 0000000 0000000 00000057150 13633624025 0016046 0 ustar 00root root 0000000 0000000 # Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [18.1.1](https://www.github.com/yargs/yargs-parser/compare/v18.1.0...v18.1.1) (2020-03-16)
### Bug Fixes
* \_\_proto\_\_ will now be replaced with \_\_\_proto\_\_\_ in parse ([#258](https://www.github.com/yargs/yargs-parser/issues/258)), patching a potential
prototype pollution vulnerability. This was reported by the Snyk Security Research Team.([63810ca](https://www.github.com/yargs/yargs-parser/commit/63810ca1ae1a24b08293a4d971e70e058c7a41e2))
## [18.1.0](https://www.github.com/yargs/yargs-parser/compare/v18.0.0...v18.1.0) (2020-03-07)
### Features
* introduce single-digit boolean aliases ([#255](https://www.github.com/yargs/yargs-parser/issues/255)) ([9c60265](https://www.github.com/yargs/yargs-parser/commit/9c60265fd7a03cb98e6df3e32c8c5e7508d9f56f))
## [18.0.0](https://www.github.com/yargs/yargs-parser/compare/v17.1.0...v18.0.0) (2020-03-02)
### ⚠ BREAKING CHANGES
* the narg count is now enforced when parsing arrays.
### Features
* NaN can now be provided as a value for nargs, indicating "at least" one value is expected for array ([#251](https://www.github.com/yargs/yargs-parser/issues/251)) ([9db4be8](https://www.github.com/yargs/yargs-parser/commit/9db4be81417a2c7097128db34d86fe70ef4af70c))
## [17.1.0](https://www.github.com/yargs/yargs-parser/compare/v17.0.1...v17.1.0) (2020-03-01)
### Features
* introduce greedy-arrays config, for specifying whether arrays consume multiple positionals ([#249](https://www.github.com/yargs/yargs-parser/issues/249)) ([60e880a](https://www.github.com/yargs/yargs-parser/commit/60e880a837046314d89fa4725f923837fd33a9eb))
### [17.0.1](https://www.github.com/yargs/yargs-parser/compare/v17.0.0...v17.0.1) (2020-02-29)
### Bug Fixes
* normalized keys were not enumerable ([#247](https://www.github.com/yargs/yargs-parser/issues/247)) ([57119f9](https://www.github.com/yargs/yargs-parser/commit/57119f9f17cf27499bd95e61c2f72d18314f11ba))
## [17.0.0](https://www.github.com/yargs/yargs-parser/compare/v16.1.0...v17.0.0) (2020-02-10)
### ⚠ BREAKING CHANGES
* this reverts parsing behavior of booleans to that of yargs@14
* objects used during parsing are now created with a null
prototype. There may be some scenarios where this change in behavior
leaks externally.
### Features
* boolean arguments will not be collected into an implicit array ([#236](https://www.github.com/yargs/yargs-parser/issues/236)) ([34c4e19](https://www.github.com/yargs/yargs-parser/commit/34c4e19bae4e7af63e3cb6fa654a97ed476e5eb5))
* introduce nargs-eats-options config option ([#246](https://www.github.com/yargs/yargs-parser/issues/246)) ([d50822a](https://www.github.com/yargs/yargs-parser/commit/d50822ac10e1b05f2e9643671ca131ac251b6732))
### Bug Fixes
* address bugs with "uknown-options-as-args" ([bc023e3](https://www.github.com/yargs/yargs-parser/commit/bc023e3b13e20a118353f9507d1c999bf388a346))
* array should take precedence over nargs, but enforce nargs ([#243](https://www.github.com/yargs/yargs-parser/issues/243)) ([4cbc188](https://www.github.com/yargs/yargs-parser/commit/4cbc188b7abb2249529a19c090338debdad2fe6c))
* support keys that collide with object prototypes ([#234](https://www.github.com/yargs/yargs-parser/issues/234)) ([1587b6d](https://www.github.com/yargs/yargs-parser/commit/1587b6d91db853a9109f1be6b209077993fee4de))
* unknown options terminated with digits now handled by unknown-options-as-args ([#238](https://www.github.com/yargs/yargs-parser/issues/238)) ([d36cdfa](https://www.github.com/yargs/yargs-parser/commit/d36cdfa854254d7c7e0fe1d583818332ac46c2a5))
## [16.1.0](https://www.github.com/yargs/yargs-parser/compare/v16.0.0...v16.1.0) (2019-11-01)
### ⚠ BREAKING CHANGES
* populate error if incompatible narg/count or array/count options are used (#191)
### Features
* options that have had their default value used are now tracked ([#211](https://www.github.com/yargs/yargs-parser/issues/211)) ([a525234](https://www.github.com/yargs/yargs-parser/commit/a525234558c847deedd73f8792e0a3b77b26e2c0))
* populate error if incompatible narg/count or array/count options are used ([#191](https://www.github.com/yargs/yargs-parser/issues/191)) ([84a401f](https://www.github.com/yargs/yargs-parser/commit/84a401f0fa3095e0a19661670d1570d0c3b9d3c9))
### Reverts
* revert 16.0.0 CHANGELOG entry ([920320a](https://www.github.com/yargs/yargs-parser/commit/920320ad9861bbfd58eda39221ae211540fc1daf))
## [15.0.0](https://github.com/yargs/yargs-parser/compare/v14.0.0...v15.0.0) (2019-10-07)
### Features
* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality ([ef771ca](https://github.com/yargs/yargs-parser/commit/ef771ca))
### BREAKING CHANGES
* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality
## [14.0.0](https://github.com/yargs/yargs-parser/compare/v13.1.1...v14.0.0) (2019-09-06)
### Bug Fixes
* boolean arrays with default values ([#185](https://github.com/yargs/yargs-parser/issues/185)) ([7d42572](https://github.com/yargs/yargs-parser/commit/7d42572))
* boolean now behaves the same as other array types ([#184](https://github.com/yargs/yargs-parser/issues/184)) ([17ca3bd](https://github.com/yargs/yargs-parser/commit/17ca3bd))
* eatNargs() for 'opt.narg === 0' and boolean typed options ([#188](https://github.com/yargs/yargs-parser/issues/188)) ([c5a1db0](https://github.com/yargs/yargs-parser/commit/c5a1db0))
* maybeCoerceNumber now takes precedence over coerce return value ([#182](https://github.com/yargs/yargs-parser/issues/182)) ([2f26436](https://github.com/yargs/yargs-parser/commit/2f26436))
* take into account aliases when appending arrays from config object ([#199](https://github.com/yargs/yargs-parser/issues/199)) ([f8a2d3f](https://github.com/yargs/yargs-parser/commit/f8a2d3f))
### Features
* add configuration option to "collect-unknown-options" ([#181](https://github.com/yargs/yargs-parser/issues/181)) ([7909cc4](https://github.com/yargs/yargs-parser/commit/7909cc4))
* maybeCoerceNumber() now takes into account arrays ([#187](https://github.com/yargs/yargs-parser/issues/187)) ([31c204b](https://github.com/yargs/yargs-parser/commit/31c204b))
### BREAKING CHANGES
* unless "parse-numbers" is set to "false", arrays of numeric strings are now parsed as numbers, rather than strings.
* we have dropped the broken "defaulted" functionality; we would like to revisit adding this in the future.
* maybeCoerceNumber now takes precedence over coerce return value (#182)
### [13.1.1](https://www.github.com/yargs/yargs-parser/compare/v13.1.0...v13.1.1) (2019-06-10)
### Bug Fixes
* convert values to strings when tokenizing ([#167](https://www.github.com/yargs/yargs-parser/issues/167)) ([57b7883](https://www.github.com/yargs/yargs-parser/commit/57b7883))
* nargs should allow duplicates when duplicate-arguments-array=false ([#164](https://www.github.com/yargs/yargs-parser/issues/164)) ([47ccb0b](https://www.github.com/yargs/yargs-parser/commit/47ccb0b))
* should populate "_" when given config with "short-option-groups" false ([#179](https://www.github.com/yargs/yargs-parser/issues/179)) ([6055974](https://www.github.com/yargs/yargs-parser/commit/6055974))
## [13.1.0](https://github.com/yargs/yargs-parser/compare/v13.0.0...v13.1.0) (2019-05-05)
### Features
* add `strip-aliased` and `strip-dashed` configuration options. ([#172](https://github.com/yargs/yargs-parser/issues/172)) ([a3936aa](https://github.com/yargs/yargs-parser/commit/a3936aa))
* support boolean which do not consume next argument. ([#171](https://github.com/yargs/yargs-parser/issues/171)) ([0ae7fcb](https://github.com/yargs/yargs-parser/commit/0ae7fcb))
# [13.0.0](https://github.com/yargs/yargs-parser/compare/v12.0.0...v13.0.0) (2019-02-02)
### Features
* don't coerce number from string with leading '0' or '+' ([#158](https://github.com/yargs/yargs-parser/issues/158)) ([18d0fd5](https://github.com/yargs/yargs-parser/commit/18d0fd5))
### BREAKING CHANGES
* options with leading '+' or '0' now parse as strings
# [12.0.0](https://github.com/yargs/yargs-parser/compare/v11.1.1...v12.0.0) (2019-01-29)
### Bug Fixes
* better handling of quoted strings ([#153](https://github.com/yargs/yargs-parser/issues/153)) ([2fb71b2](https://github.com/yargs/yargs-parser/commit/2fb71b2))
### Features
* default value is now used if no right-hand value provided for numbers/strings ([#156](https://github.com/yargs/yargs-parser/issues/156)) ([5a7c46a](https://github.com/yargs/yargs-parser/commit/5a7c46a))
### BREAKING CHANGES
* a flag with no right-hand value no longer populates defaulted options with `undefined`.
* quotes at beginning and endings of strings are not removed during parsing.
## [11.1.1](https://github.com/yargs/yargs-parser/compare/v11.1.0...v11.1.1) (2018-11-19)
### Bug Fixes
* ensure empty string is added into argv._ ([#140](https://github.com/yargs/yargs-parser/issues/140)) ([79cda98](https://github.com/yargs/yargs-parser/commit/79cda98))
### Reverts
* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([f4a3063](https://github.com/yargs/yargs-parser/commit/f4a3063))
# [11.1.0](https://github.com/yargs/yargs-parser/compare/v11.0.0...v11.1.0) (2018-11-10)
### Bug Fixes
* handling of one char alias ([#139](https://github.com/yargs/yargs-parser/issues/139)) ([ee56e31](https://github.com/yargs/yargs-parser/commit/ee56e31))
### Features
* add halt-at-non-option configuration option ([#130](https://github.com/yargs/yargs-parser/issues/130)) ([a849fce](https://github.com/yargs/yargs-parser/commit/a849fce))
# [11.0.0](https://github.com/yargs/yargs-parser/compare/v10.1.0...v11.0.0) (2018-10-06)
### Bug Fixes
* flatten-duplicate-arrays:false for more than 2 arrays ([#128](https://github.com/yargs/yargs-parser/issues/128)) ([2bc395f](https://github.com/yargs/yargs-parser/commit/2bc395f))
* hyphenated flags combined with dot notation broke parsing ([#131](https://github.com/yargs/yargs-parser/issues/131)) ([dc788da](https://github.com/yargs/yargs-parser/commit/dc788da))
* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([77ae1d4](https://github.com/yargs/yargs-parser/commit/77ae1d4))
### Chores
* update dependencies ([6dc42a1](https://github.com/yargs/yargs-parser/commit/6dc42a1))
### Features
* also add camelCase array options ([#125](https://github.com/yargs/yargs-parser/issues/125)) ([08c0117](https://github.com/yargs/yargs-parser/commit/08c0117))
* array.type can now be provided, supporting coercion ([#132](https://github.com/yargs/yargs-parser/issues/132)) ([4b8cfce](https://github.com/yargs/yargs-parser/commit/4b8cfce))
### BREAKING CHANGES
* drops Node 4 support
* the argv object is now populated differently (correctly) when hyphens and dot notation are used in conjunction.
# [10.1.0](https://github.com/yargs/yargs-parser/compare/v10.0.0...v10.1.0) (2018-06-29)
### Features
* add `set-placeholder-key` configuration ([#123](https://github.com/yargs/yargs-parser/issues/123)) ([19386ee](https://github.com/yargs/yargs-parser/commit/19386ee))
# [10.0.0](https://github.com/yargs/yargs-parser/compare/v9.0.2...v10.0.0) (2018-04-04)
### Bug Fixes
* do not set boolean flags if not defined in `argv` ([#119](https://github.com/yargs/yargs-parser/issues/119)) ([f6e6599](https://github.com/yargs/yargs-parser/commit/f6e6599))
### BREAKING CHANGES
* `boolean` flags defined without a `default` value will now behave like other option type and won't be set in the parsed results when the user doesn't set the corresponding CLI arg.
Previous behavior:
```js
var parse = require('yargs-parser');
parse('--flag', {boolean: ['flag']});
// => { _: [], flag: true }
parse('--no-flag', {boolean: ['flag']});
// => { _: [], flag: false }
parse('', {boolean: ['flag']});
// => { _: [], flag: false }
```
New behavior:
```js
var parse = require('yargs-parser');
parse('--flag', {boolean: ['flag']});
// => { _: [], flag: true }
parse('--no-flag', {boolean: ['flag']});
// => { _: [], flag: false }
parse('', {boolean: ['flag']});
// => { _: [] } => flag not set similarly to other option type
```
## [9.0.2](https://github.com/yargs/yargs-parser/compare/v9.0.1...v9.0.2) (2018-01-20)
### Bug Fixes
* nargs was still aggressively consuming too many arguments ([9b28aad](https://github.com/yargs/yargs-parser/commit/9b28aad))
## [9.0.1](https://github.com/yargs/yargs-parser/compare/v9.0.0...v9.0.1) (2018-01-20)
### Bug Fixes
* nargs was consuming too many arguments ([4fef206](https://github.com/yargs/yargs-parser/commit/4fef206))
# [9.0.0](https://github.com/yargs/yargs-parser/compare/v8.1.0...v9.0.0) (2018-01-20)
### Features
* narg arguments no longer consume flag arguments ([#114](https://github.com/yargs/yargs-parser/issues/114)) ([60bb9b3](https://github.com/yargs/yargs-parser/commit/60bb9b3))
### BREAKING CHANGES
* arguments of form --foo, -abc, will no longer be consumed by nargs
# [8.1.0](https://github.com/yargs/yargs-parser/compare/v8.0.0...v8.1.0) (2017-12-20)
### Bug Fixes
* allow null config values ([#108](https://github.com/yargs/yargs-parser/issues/108)) ([d8b14f9](https://github.com/yargs/yargs-parser/commit/d8b14f9))
* ensure consistent parsing of dot-notation arguments ([#102](https://github.com/yargs/yargs-parser/issues/102)) ([c9bd79c](https://github.com/yargs/yargs-parser/commit/c9bd79c))
* implement [@antoniom](https://github.com/antoniom)'s fix for camel-case expansion ([3087e1d](https://github.com/yargs/yargs-parser/commit/3087e1d))
* only run coercion functions once, despite aliases. ([#76](https://github.com/yargs/yargs-parser/issues/76)) ([#103](https://github.com/yargs/yargs-parser/issues/103)) ([507aaef](https://github.com/yargs/yargs-parser/commit/507aaef))
* scientific notation circumvented bounds check ([#110](https://github.com/yargs/yargs-parser/issues/110)) ([3571f57](https://github.com/yargs/yargs-parser/commit/3571f57))
* tokenizer should ignore spaces at the beginning of the argString ([#106](https://github.com/yargs/yargs-parser/issues/106)) ([f34ead9](https://github.com/yargs/yargs-parser/commit/f34ead9))
### Features
* make combining arrays a configurable option ([#111](https://github.com/yargs/yargs-parser/issues/111)) ([c8bf536](https://github.com/yargs/yargs-parser/commit/c8bf536))
* merge array from arguments with array from config ([#83](https://github.com/yargs/yargs-parser/issues/83)) ([806ddd6](https://github.com/yargs/yargs-parser/commit/806ddd6))
# [8.0.0](https://github.com/yargs/yargs-parser/compare/v7.0.0...v8.0.0) (2017-10-05)
### Bug Fixes
* Ignore multiple spaces between arguments. ([#100](https://github.com/yargs/yargs-parser/issues/100)) ([d137227](https://github.com/yargs/yargs-parser/commit/d137227))
### Features
* allow configuration of prefix for boolean negation ([#94](https://github.com/yargs/yargs-parser/issues/94)) ([00bde7d](https://github.com/yargs/yargs-parser/commit/00bde7d))
* reworking how numbers are parsed ([#104](https://github.com/yargs/yargs-parser/issues/104)) ([fba00eb](https://github.com/yargs/yargs-parser/commit/fba00eb))
### BREAKING CHANGES
* strings that fail `Number.isSafeInteger()` are no longer coerced into numbers.
# [7.0.0](https://github.com/yargs/yargs-parser/compare/v6.0.1...v7.0.0) (2017-05-02)
### Chores
* revert populate-- logic ([#91](https://github.com/yargs/yargs-parser/issues/91)) ([6003e6d](https://github.com/yargs/yargs-parser/commit/6003e6d))
### BREAKING CHANGES
* populate-- now defaults to false.
## [6.0.1](https://github.com/yargs/yargs-parser/compare/v6.0.0...v6.0.1) (2017-05-01)
### Bug Fixes
* default '--' to undefined when not provided; this is closer to the array API ([#90](https://github.com/yargs/yargs-parser/issues/90)) ([4e739cc](https://github.com/yargs/yargs-parser/commit/4e739cc))
# [6.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v6.0.0) (2017-05-01)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
* parsing hints should apply for dot notation keys ([#86](https://github.com/yargs/yargs-parser/issues/86)) ([3e47d62](https://github.com/yargs/yargs-parser/commit/3e47d62))
### Chores
* upgrade to newest version of camelcase ([#87](https://github.com/yargs/yargs-parser/issues/87)) ([f1903aa](https://github.com/yargs/yargs-parser/commit/f1903aa))
### Features
* add -- option which allows arguments after the -- flag to be returned separated from positional arguments ([#84](https://github.com/yargs/yargs-parser/issues/84)) ([2572ca8](https://github.com/yargs/yargs-parser/commit/2572ca8))
* when parsing stops, we now populate "--" by default ([#88](https://github.com/yargs/yargs-parser/issues/88)) ([cd666db](https://github.com/yargs/yargs-parser/commit/cd666db))
### BREAKING CHANGES
* rather than placing arguments in "_", when parsing is stopped via "--"; we now populate an array called "--" by default.
* camelcase now requires Node 4+.
* environment variables will now override config files (args, env, config-file, config-object)
# [5.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v5.0.0) (2017-02-18)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
### BREAKING CHANGES
* environment variables will now override config files (args, env, config-file, config-object)
## [4.2.1](https://github.com/yargs/yargs-parser/compare/v4.2.0...v4.2.1) (2017-01-02)
### Bug Fixes
* flatten/duplicate regression ([#75](https://github.com/yargs/yargs-parser/issues/75)) ([68d68a0](https://github.com/yargs/yargs-parser/commit/68d68a0))
# [4.2.0](https://github.com/yargs/yargs-parser/compare/v4.1.0...v4.2.0) (2016-12-01)
### Bug Fixes
* inner objects in configs had their keys appended to top-level key when dot-notation was disabled ([#72](https://github.com/yargs/yargs-parser/issues/72)) ([0b1b5f9](https://github.com/yargs/yargs-parser/commit/0b1b5f9))
### Features
* allow multiple arrays to be provided, rather than always combining ([#71](https://github.com/yargs/yargs-parser/issues/71)) ([0f0fb2d](https://github.com/yargs/yargs-parser/commit/0f0fb2d))
# [4.1.0](https://github.com/yargs/yargs-parser/compare/v4.0.2...v4.1.0) (2016-11-07)
### Features
* apply coercions to default options ([#65](https://github.com/yargs/yargs-parser/issues/65)) ([c79052b](https://github.com/yargs/yargs-parser/commit/c79052b))
* handle dot notation boolean options ([#63](https://github.com/yargs/yargs-parser/issues/63)) ([02c3545](https://github.com/yargs/yargs-parser/commit/02c3545))
## [4.0.2](https://github.com/yargs/yargs-parser/compare/v4.0.1...v4.0.2) (2016-09-30)
### Bug Fixes
* whoops, let's make the assign not change the Object key order ([29d069a](https://github.com/yargs/yargs-parser/commit/29d069a))
## [4.0.1](https://github.com/yargs/yargs-parser/compare/v4.0.0...v4.0.1) (2016-09-30)
### Bug Fixes
* lodash.assign was deprecated ([#59](https://github.com/yargs/yargs-parser/issues/59)) ([5e7eb11](https://github.com/yargs/yargs-parser/commit/5e7eb11))
# [4.0.0](https://github.com/yargs/yargs-parser/compare/v3.2.0...v4.0.0) (2016-09-26)
### Bug Fixes
* coerce should be applied to the final objects and arrays created ([#57](https://github.com/yargs/yargs-parser/issues/57)) ([4ca69da](https://github.com/yargs/yargs-parser/commit/4ca69da))
### BREAKING CHANGES
* coerce is no longer applied to individual arguments in an implicit array.
# [3.2.0](https://github.com/yargs/yargs-parser/compare/v3.1.0...v3.2.0) (2016-08-13)
### Features
* coerce full array instead of each element ([#51](https://github.com/yargs/yargs-parser/issues/51)) ([cc4dc56](https://github.com/yargs/yargs-parser/commit/cc4dc56))
# [3.1.0](https://github.com/yargs/yargs-parser/compare/v3.0.0...v3.1.0) (2016-08-09)
### Bug Fixes
* address pkgConf parsing bug outlined in [#37](https://github.com/yargs/yargs-parser/issues/37) ([#45](https://github.com/yargs/yargs-parser/issues/45)) ([be76ee6](https://github.com/yargs/yargs-parser/commit/be76ee6))
* better parsing of negative values ([#44](https://github.com/yargs/yargs-parser/issues/44)) ([2e43692](https://github.com/yargs/yargs-parser/commit/2e43692))
* check aliases when guessing defaults for arguments fixes [#41](https://github.com/yargs/yargs-parser/issues/41) ([#43](https://github.com/yargs/yargs-parser/issues/43)) ([f3e4616](https://github.com/yargs/yargs-parser/commit/f3e4616))
### Features
* added coerce option, for providing specialized argument parsing ([#42](https://github.com/yargs/yargs-parser/issues/42)) ([7b49cd2](https://github.com/yargs/yargs-parser/commit/7b49cd2))
# [3.0.0](https://github.com/yargs/yargs-parser/compare/v2.4.1...v3.0.0) (2016-08-07)
### Bug Fixes
* parsing issue with numeric character in group of options ([#19](https://github.com/yargs/yargs-parser/issues/19)) ([f743236](https://github.com/yargs/yargs-parser/commit/f743236))
* upgraded lodash.assign ([5d7fdf4](https://github.com/yargs/yargs-parser/commit/5d7fdf4))
### BREAKING CHANGES
* subtle change to how values are parsed in a group of single-character arguments.
* _first released in 3.1.0, better handling of negative values should be considered a breaking change._
## [2.4.1](https://github.com/yargs/yargs-parser/compare/v2.4.0...v2.4.1) (2016-07-16)
### Bug Fixes
* **count:** do not increment a default value ([#39](https://github.com/yargs/yargs-parser/issues/39)) ([b04a189](https://github.com/yargs/yargs-parser/commit/b04a189))
# [2.4.0](https://github.com/yargs/yargs-parser/compare/v2.3.0...v2.4.0) (2016-04-11)
### Features
* **environment:** Support nested options in environment variables ([#26](https://github.com/yargs/yargs-parser/issues/26)) thanks [@elas7](https://github.com/elas7) \o/ ([020778b](https://github.com/yargs/yargs-parser/commit/020778b))
# [2.3.0](https://github.com/yargs/yargs-parser/compare/v2.2.0...v2.3.0) (2016-04-09)
### Bug Fixes
* **boolean:** fix for boolean options with non boolean defaults (#20) ([2dbe86b](https://github.com/yargs/yargs-parser/commit/2dbe86b)), closes [(#20](https://github.com/(/issues/20)
* **package:** remove tests from tarball ([0353c0d](https://github.com/yargs/yargs-parser/commit/0353c0d))
* **parsing:** handle calling short option with an empty string as the next value. ([a867165](https://github.com/yargs/yargs-parser/commit/a867165))
* boolean flag when next value contains the strings 'true' or 'false'. ([69941a6](https://github.com/yargs/yargs-parser/commit/69941a6))
* update dependencies; add standard-version bin for next release (#24) ([822d9d5](https://github.com/yargs/yargs-parser/commit/822d9d5))
### Features
* **configuration:** Allow to pass configuration objects to yargs-parser ([0780900](https://github.com/yargs/yargs-parser/commit/0780900))
* **normalize:** allow normalize to work with arrays ([e0eaa1a](https://github.com/yargs/yargs-parser/commit/e0eaa1a))
yargs-parser-18.1.1/LICENSE.txt 0000664 0000000 0000000 00000001333 13633624025 0016050 0 ustar 00root root 0000000 0000000 Copyright (c) 2016, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
yargs-parser-18.1.1/README.md 0000664 0000000 0000000 00000024104 13633624025 0015505 0 ustar 00root root 0000000 0000000 # yargs-parser
[](https://travis-ci.org/yargs/yargs-parser)
[](https://www.npmjs.com/package/yargs-parser)
[](https://github.com/conventional-changelog/standard-version)
The mighty option parser used by [yargs](https://github.com/yargs/yargs).
visit the [yargs website](http://yargs.js.org/) for more examples, and thorough usage instructions.
## Example
```sh
npm i yargs-parser --save
```
```js
var argv = require('yargs-parser')(process.argv.slice(2))
console.log(argv)
```
```sh
node example.js --foo=33 --bar hello
{ _: [], foo: 33, bar: 'hello' }
```
_or parse a string!_
```js
var argv = require('yargs-parser')('--foo=99 --bar=33')
console.log(argv)
```
```sh
{ _: [], foo: 99, bar: 33 }
```
Convert an array of mixed types before passing to `yargs-parser`:
```js
var parse = require('yargs-parser')
parse(['-f', 11, '--zoom', 55].join(' ')) // <-- array to string
parse(['-f', 11, '--zoom', 55].map(String)) // <-- array of strings
```
## API
### require('yargs-parser')(args, opts={})
Parses command line arguments returning a simple mapping of keys and values.
**expects:**
* `args`: a string or array of strings representing the options to parse.
* `opts`: provide a set of hints indicating how `args` should be parsed:
* `opts.alias`: an object representing the set of aliases for a key: `{alias: {foo: ['f']}}`.
* `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.
Indicate that keys should be parsed as an array and coerced to booleans / numbers:
`{array: [{ key: 'foo', boolean: true }, {key: 'bar', number: true}]}`.
* `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`.
* `opts.coerce`: provide a custom synchronous function that returns a coerced value from the argument provided
(or throws an error). For arrays the function is called only once for the entire array:
`{coerce: {foo: function (arg) {return modifiedArg}}}`.
* `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed).
* `opts.configObjects`: configuration objects to parse, their properties will be set as arguments:
`{configObjects: [{'x': 5, 'y': 33}, {'z': 44}]}`.
* `opts.configuration`: provide configuration options to the yargs-parser (see: [configuration](#configuration)).
* `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`.
* `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`.
* `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed.
* `opts.narg`: specify that a key requires `n` arguments: `{narg: {x: 2}}`.
* `opts.normalize`: `path.normalize()` will be applied to values set to this key.
* `opts.number`: keys should be treated as numbers.
* `opts.string`: keys should be treated as strings (even if they resemble a number `-x 33`).
**returns:**
* `obj`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* [optional] `--`: an array with arguments after the end-of-options flag `--`.
### require('yargs-parser').detailed(args, opts={})
Parses a command line string, returning detailed information required by the
yargs engine.
**expects:**
* `args`: a string or array of strings representing options to parse.
* `opts`: provide a set of hints indicating how `args`, inputs are identical to `require('yargs-parser')(args, opts={})`.
**returns:**
* `argv`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* [optional] `--`: an array with arguments after the end-of-options flag `--`.
* `error`: populated with an error object if an exception occurred during parsing.
* `aliases`: the inferred list of aliases built by combining lists in `opts.alias`.
* `newAliases`: any new aliases added via camel-case expansion:
* `boolean`: `{ fooBar: true }`
* `defaulted`: any new argument created by `opts.default`, no aliases included.
* `boolean`: `{ foo: true }`
* `configuration`: given by default settings and `opts.configuration`.
### Configuration
The yargs-parser applies several automated transformations on the keys provided
in `args`. These features can be turned on and off using the `configuration` field
of `opts`.
```js
var parsed = parser(['--no-dice'], {
configuration: {
'boolean-negation': false
}
})
```
### short option groups
* default: `true`.
* key: `short-option-groups`.
Should a group of short-options be treated as boolean flags?
```sh
node example.js -abc
{ _: [], a: true, b: true, c: true }
```
_if disabled:_
```sh
node example.js -abc
{ _: [], abc: true }
```
### camel-case expansion
* default: `true`.
* key: `camel-case-expansion`.
Should hyphenated arguments be expanded into camel-case aliases?
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true, fooBar: true }
```
_if disabled:_
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true }
```
### dot-notation
* default: `true`
* key: `dot-notation`
Should keys that contain `.` be treated as objects?
```sh
node example.js --foo.bar
{ _: [], foo: { bar: true } }
```
_if disabled:_
```sh
node example.js --foo.bar
{ _: [], "foo.bar": true }
```
### parse numbers
* default: `true`
* key: `parse-numbers`
Should keys that look like numbers be treated as such?
```sh
node example.js --foo=99.3
{ _: [], foo: 99.3 }
```
_if disabled:_
```sh
node example.js --foo=99.3
{ _: [], foo: "99.3" }
```
### boolean negation
* default: `true`
* key: `boolean-negation`
Should variables prefixed with `--no` be treated as negations?
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if disabled:_
```sh
node example.js --no-foo
{ _: [], "no-foo": true }
```
### combine arrays
* default: `false`
* key: `combine-arrays`
Should arrays be combined when provided by both command line arguments and
a configuration file.
### duplicate arguments array
* default: `true`
* key: `duplicate-arguments-array`
Should arguments be coerced into an array when duplicated:
```sh
node example.js -x 1 -x 2
{ _: [], x: [1, 2] }
```
_if disabled:_
```sh
node example.js -x 1 -x 2
{ _: [], x: 2 }
```
### flatten duplicate arrays
* default: `true`
* key: `flatten-duplicate-arrays`
Should array arguments be coerced into a single array when duplicated:
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [1, 2, 3, 4] }
```
_if disabled:_
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [[1, 2], [3, 4]] }
```
### greedy arrays
* default: `true`
* key: `greedy-arrays`
Should arrays consume more than one positional argument following their flag.
```sh
node example --arr 1 2
{ _[], arr: [1, 2] }
```
_if disabled:_
```sh
node example --arr 1 2
{ _[2], arr: [1] }
```
**Note: in `v18.0.0` we are considering defaulting greedy arrays to `false`.**
### nargs eats options
* default: `false`
* key: `nargs-eats-options`
Should nargs consume dash options as well as positional arguments.
### negation prefix
* default: `no-`
* key: `negation-prefix`
The prefix to use for negated boolean variables.
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if set to `quux`:_
```sh
node example.js --quuxfoo
{ _: [], foo: false }
```
### populate --
* default: `false`.
* key: `populate--`
Should unparsed flags be stored in `--` or `_`.
_If disabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a', 'x', 'y' ], b: true }
```
_If enabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a' ], '--': [ 'x', 'y' ], b: true }
```
### set placeholder key
* default: `false`.
* key: `set-placeholder-key`.
Should a placeholder be added for keys not set via the corresponding CLI argument?
_If disabled:_
```sh
node example.js -a 1 -c 2
{ _: [], a: 1, c: 2 }
```
_If enabled:_
```sh
node example.js -a 1 -c 2
{ _: [], a: 1, b: undefined, c: 2 }
```
### halt at non-option
* default: `false`.
* key: `halt-at-non-option`.
Should parsing stop at the first positional argument? This is similar to how e.g. `ssh` parses its command line.
_If disabled:_
```sh
node example.js -a run b -x y
{ _: [ 'b' ], a: 'run', x: 'y' }
```
_If enabled:_
```sh
node example.js -a run b -x y
{ _: [ 'b', '-x', 'y' ], a: 'run' }
```
### strip aliased
* default: `false`
* key: `strip-aliased`
Should aliases be removed before returning results?
_If disabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1, 'test-alias': 1, testAlias: 1 }
```
_If enabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1 }
```
### strip dashed
* default: `false`
* key: `strip-dashed`
Should dashed keys be removed before returning results? This option has no effect if
`camel-case-expansion` is disabled.
_If disabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1 }
```
_If enabled:_
```sh
node example.js --test-field 1
{ _: [], testField: 1 }
```
### unknown options as args
* default: `false`
* key: `unknown-options-as-args`
Should unknown options be treated like regular arguments? An unknown option is one that is not
configured in `opts`.
_If disabled_
```sh
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: [], unknownOption: true, knownOption: 2, stringOption: '', unknownOption2: true }
```
_If enabled_
```sh
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: ['--unknown-option'], knownOption: 2, stringOption: '--unknown-option2' }
```
## Special Thanks
The yargs project evolves from optimist and minimist. It owes its
existence to a lot of James Halliday's hard work. Thanks [substack](https://github.com/substack) **beep** **boop** \o/
## License
ISC
yargs-parser-18.1.1/example.js 0000775 0000000 0000000 00000000121 13633624025 0016213 0 ustar 00root root 0000000 0000000 var parser = require('./')
var parse = parser('--foo "-bar"')
console.log(parse)
yargs-parser-18.1.1/index.js 0000664 0000000 0000000 00000100506 13633624025 0015674 0 ustar 00root root 0000000 0000000 const camelCase = require('camelcase')
const decamelize = require('decamelize')
const path = require('path')
const tokenizeArgString = require('./lib/tokenize-arg-string')
const util = require('util')
function parse (args, opts) {
opts = Object.assign(Object.create(null), opts)
// allow a string argument to be passed in rather
// than an argv array.
args = tokenizeArgString(args)
// aliases might have transitive relationships, normalize this.
const aliases = combineAliases(Object.assign(Object.create(null), opts.alias))
const configuration = Object.assign({
'boolean-negation': true,
'camel-case-expansion': true,
'combine-arrays': false,
'dot-notation': true,
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true,
'greedy-arrays': true,
'halt-at-non-option': false,
'nargs-eats-options': false,
'negation-prefix': 'no-',
'parse-numbers': true,
'populate--': false,
'set-placeholder-key': false,
'short-option-groups': true,
'strip-aliased': false,
'strip-dashed': false,
'unknown-options-as-args': false
}, opts.configuration)
const defaults = Object.assign(Object.create(null), opts.default)
const configObjects = opts.configObjects || []
const envPrefix = opts.envPrefix
const notFlagsOption = configuration['populate--']
const notFlagsArgv = notFlagsOption ? '--' : '_'
const newAliases = Object.create(null)
const defaulted = Object.create(null)
// allow a i18n handler to be passed in, default to a fake one (util.format).
const __ = opts.__ || util.format
const flags = {
aliases: Object.create(null),
arrays: Object.create(null),
bools: Object.create(null),
strings: Object.create(null),
numbers: Object.create(null),
counts: Object.create(null),
normalize: Object.create(null),
configs: Object.create(null),
nargs: Object.create(null),
coercions: Object.create(null),
keys: []
}
const negative = /^-([0-9]+(\.[0-9]+)?|\.[0-9]+)$/
const negatedBoolean = new RegExp('^--' + configuration['negation-prefix'] + '(.+)')
;[].concat(opts.array).filter(Boolean).forEach(function (opt) {
const key = opt.key || opt
// assign to flags[bools|strings|numbers]
const assignment = Object.keys(opt).map(function (key) {
return ({
boolean: 'bools',
string: 'strings',
number: 'numbers'
})[key]
}).filter(Boolean).pop()
// assign key to be coerced
if (assignment) {
flags[assignment][key] = true
}
flags.arrays[key] = true
flags.keys.push(key)
})
;[].concat(opts.boolean).filter(Boolean).forEach(function (key) {
flags.bools[key] = true
flags.keys.push(key)
})
;[].concat(opts.string).filter(Boolean).forEach(function (key) {
flags.strings[key] = true
flags.keys.push(key)
})
;[].concat(opts.number).filter(Boolean).forEach(function (key) {
flags.numbers[key] = true
flags.keys.push(key)
})
;[].concat(opts.count).filter(Boolean).forEach(function (key) {
flags.counts[key] = true
flags.keys.push(key)
})
;[].concat(opts.normalize).filter(Boolean).forEach(function (key) {
flags.normalize[key] = true
flags.keys.push(key)
})
Object.keys(opts.narg || {}).forEach(function (k) {
flags.nargs[k] = opts.narg[k]
flags.keys.push(k)
})
Object.keys(opts.coerce || {}).forEach(function (k) {
flags.coercions[k] = opts.coerce[k]
flags.keys.push(k)
})
if (Array.isArray(opts.config) || typeof opts.config === 'string') {
;[].concat(opts.config).filter(Boolean).forEach(function (key) {
flags.configs[key] = true
})
} else {
Object.keys(opts.config || {}).forEach(function (k) {
flags.configs[k] = opts.config[k]
})
}
// create a lookup table that takes into account all
// combinations of aliases: {f: ['foo'], foo: ['f']}
extendAliases(opts.key, aliases, opts.default, flags.arrays)
// apply default values to all aliases.
Object.keys(defaults).forEach(function (key) {
(flags.aliases[key] || []).forEach(function (alias) {
defaults[alias] = defaults[key]
})
})
let error = null
checkConfiguration()
let notFlags = []
const argv = Object.assign(Object.create(null), { _: [] })
// TODO(bcoe): for the first pass at removing object prototype we didn't
// remove all prototypes from objects returned by this API, we might want
// to gradually move towards doing so.
const argvReturn = {}
for (let i = 0; i < args.length; i++) {
const arg = args[i]
let broken
let key
let letters
let m
let next
let value
// any unknown option (except for end-of-options, "--")
if (arg !== '--' && isUnknownOptionAsArg(arg)) {
argv._.push(arg)
// -- separated by =
} else if (arg.match(/^--.+=/) || (
!configuration['short-option-groups'] && arg.match(/^-.+=/)
)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
m = arg.match(/^--?([^=]+)=([\s\S]*)$/)
// arrays format = '--f=a b c'
if (checkAllAliases(m[1], flags.arrays)) {
args.splice(i + 1, 0, m[2])
i = eatArray(i, m[1], args)
} else if (checkAllAliases(m[1], flags.nargs)) {
// nargs format = '--f=monkey washing cat'
args.splice(i + 1, 0, m[2])
i = eatNargs(i, m[1], args)
} else {
setArg(m[1], m[2])
}
} else if (arg.match(negatedBoolean) && configuration['boolean-negation']) {
key = arg.match(negatedBoolean)[1]
setArg(key, checkAllAliases(key, flags.arrays) ? [false] : false)
// -- separated by space.
} else if (arg.match(/^--.+/) || (
!configuration['short-option-groups'] && arg.match(/^-[^-]+/)
)) {
key = arg.match(/^--?(.+)/)[1]
if (checkAllAliases(key, flags.arrays)) {
// array format = '--foo a b c'
i = eatArray(i, key, args)
} else if (checkAllAliases(key, flags.nargs) !== false) {
// nargs format = '--foo a b c'
// should be truthy even if: flags.nargs[key] === 0
i = eatNargs(i, key, args)
} else {
next = args[i + 1]
if (next !== undefined && (!next.match(/^-/) ||
next.match(negative)) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else if (/^(true|false)$/.test(next)) {
setArg(key, next)
i++
} else {
setArg(key, defaultValue(key))
}
}
// dot-notation flag separated by '='.
} else if (arg.match(/^-.\..+=/)) {
m = arg.match(/^-([^=]+)=([\s\S]*)$/)
setArg(m[1], m[2])
// dot-notation flag separated by space.
} else if (arg.match(/^-.\..+/) && !arg.match(negative)) {
next = args[i + 1]
key = arg.match(/^-(.\..+)/)[1]
if (next !== undefined && !next.match(/^-/) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else {
setArg(key, defaultValue(key))
}
} else if (arg.match(/^-[^-]+/) && !arg.match(negative)) {
letters = arg.slice(1, -1).split('')
broken = false
for (let j = 0; j < letters.length; j++) {
next = arg.slice(j + 2)
if (letters[j + 1] && letters[j + 1] === '=') {
value = arg.slice(j + 3)
key = letters[j]
if (checkAllAliases(key, flags.arrays)) {
// array format = '-f=a b c'
args.splice(i + 1, 0, value)
i = eatArray(i, key, args)
} else if (checkAllAliases(key, flags.nargs)) {
// nargs format = '-f=monkey washing cat'
args.splice(i + 1, 0, value)
i = eatNargs(i, key, args)
} else {
setArg(key, value)
}
broken = true
break
}
if (next === '-') {
setArg(letters[j], next)
continue
}
// current letter is an alphabetic character and next value is a number
if (/[A-Za-z]/.test(letters[j]) &&
/^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
setArg(letters[j], next)
broken = true
break
}
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
setArg(letters[j], next)
broken = true
break
} else {
setArg(letters[j], defaultValue(letters[j]))
}
}
key = arg.slice(-1)[0]
if (!broken && key !== '-') {
if (checkAllAliases(key, flags.arrays)) {
// array format = '-f a b c'
i = eatArray(i, key, args)
} else if (checkAllAliases(key, flags.nargs) !== false) {
// nargs format = '-f a b c'
// should be truthy even if: flags.nargs[key] === 0
i = eatNargs(i, key, args)
} else {
next = args[i + 1]
if (next !== undefined && (!/^(-|--)[^-]/.test(next) ||
next.match(negative)) &&
!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts)) {
setArg(key, next)
i++
} else if (/^(true|false)$/.test(next)) {
setArg(key, next)
i++
} else {
setArg(key, defaultValue(key))
}
}
}
} else if (arg.match(/^-[0-9]$/) &&
arg.match(negative) &&
checkAllAliases(arg.slice(1), flags.bools)) {
// single-digit boolean alias, e.g: xargs -0
key = arg.slice(1)
setArg(key, defaultValue(key))
} else if (arg === '--') {
notFlags = args.slice(i + 1)
break
} else if (configuration['halt-at-non-option']) {
notFlags = args.slice(i)
break
} else {
argv._.push(maybeCoerceNumber('_', arg))
}
}
// order of precedence:
// 1. command line arg
// 2. value from env var
// 3. value from config file
// 4. value from config objects
// 5. configured default value
applyEnvVars(argv, true) // special case: check env vars that point to config file
applyEnvVars(argv, false)
setConfig(argv)
setConfigObjects()
applyDefaultsAndAliases(argv, flags.aliases, defaults, true)
applyCoercions(argv)
if (configuration['set-placeholder-key']) setPlaceholderKeys(argv)
// for any counts either not in args or without an explicit default, set to 0
Object.keys(flags.counts).forEach(function (key) {
if (!hasKey(argv, key.split('.'))) setArg(key, 0)
})
// '--' defaults to undefined.
if (notFlagsOption && notFlags.length) argv[notFlagsArgv] = []
notFlags.forEach(function (key) {
argv[notFlagsArgv].push(key)
})
if (configuration['camel-case-expansion'] && configuration['strip-dashed']) {
Object.keys(argv).filter(key => key !== '--' && key.includes('-')).forEach(key => {
delete argv[key]
})
}
if (configuration['strip-aliased']) {
;[].concat(...Object.keys(aliases).map(k => aliases[k])).forEach(alias => {
if (configuration['camel-case-expansion']) {
delete argv[alias.split('.').map(prop => camelCase(prop)).join('.')]
}
delete argv[alias]
})
}
// how many arguments should we consume, based
// on the nargs option?
function eatNargs (i, key, args) {
let ii
let toEat = checkAllAliases(key, flags.nargs)
// NaN has a special meaning for the array type, indicating that one or
// more values are expected.
toEat = isNaN(toEat) ? 1 : toEat
if (toEat === 0) {
setArg(key, defaultValue(key))
return i
}
let available = 0
if (configuration['nargs-eats-options']) {
// classic behavior, yargs eats positional and dash arguments.
if (args.length - (i + 1) < toEat) error = Error(__('Not enough arguments following: %s', key))
available = toEat
} else {
// nargs will not consume flag arguments, e.g., -abc, --foo,
// and terminates when one is observed.
for (ii = i + 1; ii < args.length; ii++) {
if (!args[ii].match(/^-[^0-9]/) || args[ii].match(negative) || isUnknownOptionAsArg(args[ii])) available++
else break
}
if (available < toEat) error = Error(__('Not enough arguments following: %s', key))
}
const consumed = Math.min(available, toEat)
for (ii = i + 1; ii < (consumed + i + 1); ii++) {
setArg(key, args[ii])
}
return (i + consumed)
}
// if an option is an array, eat all non-hyphenated arguments
// following it... YUM!
// e.g., --foo apple banana cat becomes ["apple", "banana", "cat"]
function eatArray (i, key, args) {
let argsToSet = []
let next = args[i + 1]
// If both array and nargs are configured, enforce the nargs count:
const nargsCount = checkAllAliases(key, flags.nargs)
if (checkAllAliases(key, flags.bools) && !(/^(true|false)$/.test(next))) {
argsToSet.push(true)
} else if (isUndefined(next) || (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next))) {
// for keys without value ==> argsToSet remains an empty []
// set user default value, if available
if (defaults[key] !== undefined) {
const defVal = defaults[key]
argsToSet = Array.isArray(defVal) ? defVal : [defVal]
}
} else {
for (let ii = i + 1; ii < args.length; ii++) {
next = args[ii]
if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break
i = ii
argsToSet.push(processValue(key, next))
if (!configuration['greedy-arrays'] ||
(nargsCount && argsToSet.length >= nargsCount)) break
}
}
// If both array and nargs are configured, create an error if less than
// nargs positionals were found. NaN has special meaning, indicating
// that at least one value is required (more are okay).
if ((nargsCount && argsToSet.length < nargsCount) ||
(isNaN(nargsCount) && argsToSet.length === 0)) {
error = Error(__('Not enough arguments following: %s', key))
}
setArg(key, argsToSet)
return i
}
function setArg (key, val) {
if (/-/.test(key) && configuration['camel-case-expansion']) {
const alias = key.split('.').map(function (prop) {
return camelCase(prop)
}).join('.')
addNewAlias(key, alias)
}
const value = processValue(key, val)
const splitKey = key.split('.')
setKey(argv, splitKey, value)
// handle populating aliases of the full key
if (flags.aliases[key]) {
flags.aliases[key].forEach(function (x) {
x = x.split('.')
setKey(argv, x, value)
})
}
// handle populating aliases of the first element of the dot-notation key
if (splitKey.length > 1 && configuration['dot-notation']) {
;(flags.aliases[splitKey[0]] || []).forEach(function (x) {
x = x.split('.')
// expand alias with nested objects in key
const a = [].concat(splitKey)
a.shift() // nuke the old key.
x = x.concat(a)
setKey(argv, x, value)
})
}
// Set normalize getter and setter when key is in 'normalize' but isn't an array
if (checkAllAliases(key, flags.normalize) && !checkAllAliases(key, flags.arrays)) {
const keys = [key].concat(flags.aliases[key] || [])
keys.forEach(function (key) {
Object.defineProperty(argvReturn, key, {
enumerable: true,
get () {
return val
},
set (value) {
val = typeof value === 'string' ? path.normalize(value) : value
}
})
})
}
}
function addNewAlias (key, alias) {
if (!(flags.aliases[key] && flags.aliases[key].length)) {
flags.aliases[key] = [alias]
newAliases[alias] = true
}
if (!(flags.aliases[alias] && flags.aliases[alias].length)) {
addNewAlias(alias, key)
}
}
function processValue (key, val) {
// strings may be quoted, clean this up as we assign values.
if (typeof val === 'string' &&
(val[0] === "'" || val[0] === '"') &&
val[val.length - 1] === val[0]
) {
val = val.substring(1, val.length - 1)
}
// handle parsing boolean arguments --foo=true --bar false.
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) {
if (typeof val === 'string') val = val === 'true'
}
let value = Array.isArray(val)
? val.map(function (v) { return maybeCoerceNumber(key, v) })
: maybeCoerceNumber(key, val)
// increment a count given as arg (either no value or value parsed as boolean)
if (checkAllAliases(key, flags.counts) && (isUndefined(value) || typeof value === 'boolean')) {
value = increment
}
// Set normalized value when key is in 'normalize' and in 'arrays'
if (checkAllAliases(key, flags.normalize) && checkAllAliases(key, flags.arrays)) {
if (Array.isArray(val)) value = val.map(path.normalize)
else value = path.normalize(val)
}
return value
}
function maybeCoerceNumber (key, value) {
if (!checkAllAliases(key, flags.strings) && !checkAllAliases(key, flags.bools) && !Array.isArray(value)) {
const shouldCoerceNumber = isNumber(value) && configuration['parse-numbers'] && (
Number.isSafeInteger(Math.floor(value))
)
if (shouldCoerceNumber || (!isUndefined(value) && checkAllAliases(key, flags.numbers))) value = Number(value)
}
return value
}
// set args from config.json file, this should be
// applied last so that defaults can be applied.
function setConfig (argv) {
const configLookup = Object.create(null)
// expand defaults/aliases, in-case any happen to reference
// the config.json file.
applyDefaultsAndAliases(configLookup, flags.aliases, defaults)
Object.keys(flags.configs).forEach(function (configKey) {
const configPath = argv[configKey] || configLookup[configKey]
if (configPath) {
try {
let config = null
const resolvedConfigPath = path.resolve(process.cwd(), configPath)
if (typeof flags.configs[configKey] === 'function') {
try {
config = flags.configs[configKey](resolvedConfigPath)
} catch (e) {
config = e
}
if (config instanceof Error) {
error = config
return
}
} else {
config = require(resolvedConfigPath)
}
setConfigObject(config)
} catch (ex) {
if (argv[configKey]) error = Error(__('Invalid JSON config file: %s', configPath))
}
}
})
}
// set args from config object.
// it recursively checks nested objects.
function setConfigObject (config, prev) {
Object.keys(config).forEach(function (key) {
const value = config[key]
const fullKey = prev ? prev + '.' + key : key
// if the value is an inner object and we have dot-notation
// enabled, treat inner objects in config the same as
// heavily nested dot notations (foo.bar.apple).
if (typeof value === 'object' && value !== null && !Array.isArray(value) && configuration['dot-notation']) {
// if the value is an object but not an array, check nested object
setConfigObject(value, fullKey)
} else {
// setting arguments via CLI takes precedence over
// values within the config file.
if (!hasKey(argv, fullKey.split('.')) || (checkAllAliases(fullKey, flags.arrays) && configuration['combine-arrays'])) {
setArg(fullKey, value)
}
}
})
}
// set all config objects passed in opts
function setConfigObjects () {
if (typeof configObjects === 'undefined') return
configObjects.forEach(function (configObject) {
setConfigObject(configObject)
})
}
function applyEnvVars (argv, configOnly) {
if (typeof envPrefix === 'undefined') return
const prefix = typeof envPrefix === 'string' ? envPrefix : ''
Object.keys(process.env).forEach(function (envVar) {
if (prefix === '' || envVar.lastIndexOf(prefix, 0) === 0) {
// get array of nested keys and convert them to camel case
const keys = envVar.split('__').map(function (key, i) {
if (i === 0) {
key = key.substring(prefix.length)
}
return camelCase(key)
})
if (((configOnly && flags.configs[keys.join('.')]) || !configOnly) && !hasKey(argv, keys)) {
setArg(keys.join('.'), process.env[envVar])
}
}
})
}
function applyCoercions (argv) {
let coerce
const applied = new Set()
Object.keys(argv).forEach(function (key) {
if (!applied.has(key)) { // If we haven't already coerced this option via one of its aliases
coerce = checkAllAliases(key, flags.coercions)
if (typeof coerce === 'function') {
try {
const value = maybeCoerceNumber(key, coerce(argv[key]))
;([].concat(flags.aliases[key] || [], key)).forEach(ali => {
applied.add(ali)
argv[ali] = value
})
} catch (err) {
error = err
}
}
}
})
}
function setPlaceholderKeys (argv) {
flags.keys.forEach((key) => {
// don't set placeholder keys for dot notation options 'foo.bar'.
if (~key.indexOf('.')) return
if (typeof argv[key] === 'undefined') argv[key] = undefined
})
return argv
}
function applyDefaultsAndAliases (obj, aliases, defaults, canLog = false) {
Object.keys(defaults).forEach(function (key) {
if (!hasKey(obj, key.split('.'))) {
setKey(obj, key.split('.'), defaults[key])
if (canLog) defaulted[key] = true
;(aliases[key] || []).forEach(function (x) {
if (hasKey(obj, x.split('.'))) return
setKey(obj, x.split('.'), defaults[key])
})
}
})
}
function hasKey (obj, keys) {
let o = obj
if (!configuration['dot-notation']) keys = [keys.join('.')]
keys.slice(0, -1).forEach(function (key) {
o = (o[key] || {})
})
const key = keys[keys.length - 1]
if (typeof o !== 'object') return false
else return key in o
}
function setKey (obj, keys, value) {
let o = obj
if (!configuration['dot-notation']) keys = [keys.join('.')]
keys.slice(0, -1).forEach(function (key, index) {
// TODO(bcoe): in the next major version of yargs, switch to
// Object.create(null) for dot notation:
key = sanitizeKey(key)
if (typeof o === 'object' && o[key] === undefined) {
o[key] = {}
}
if (typeof o[key] !== 'object' || Array.isArray(o[key])) {
// ensure that o[key] is an array, and that the last item is an empty object.
if (Array.isArray(o[key])) {
o[key].push({})
} else {
o[key] = [o[key], {}]
}
// we want to update the empty object at the end of the o[key] array, so set o to that object
o = o[key][o[key].length - 1]
} else {
o = o[key]
}
})
// TODO(bcoe): in the next major version of yargs, switch to
// Object.create(null) for dot notation:
const key = sanitizeKey(keys[keys.length - 1])
const isTypeArray = checkAllAliases(keys.join('.'), flags.arrays)
const isValueArray = Array.isArray(value)
let duplicate = configuration['duplicate-arguments-array']
// nargs has higher priority than duplicate
if (!duplicate && checkAllAliases(key, flags.nargs)) {
duplicate = true
if ((!isUndefined(o[key]) && flags.nargs[key] === 1) || (Array.isArray(o[key]) && o[key].length === flags.nargs[key])) {
o[key] = undefined
}
}
if (value === increment) {
o[key] = increment(o[key])
} else if (Array.isArray(o[key])) {
if (duplicate && isTypeArray && isValueArray) {
o[key] = configuration['flatten-duplicate-arrays'] ? o[key].concat(value) : (Array.isArray(o[key][0]) ? o[key] : [o[key]]).concat([value])
} else if (!duplicate && Boolean(isTypeArray) === Boolean(isValueArray)) {
o[key] = value
} else {
o[key] = o[key].concat([value])
}
} else if (o[key] === undefined && isTypeArray) {
o[key] = isValueArray ? value : [value]
} else if (duplicate && !(
o[key] === undefined ||
checkAllAliases(key, flags.counts) ||
checkAllAliases(key, flags.bools)
)) {
o[key] = [o[key], value]
} else {
o[key] = value
}
}
// extend the aliases list with inferred aliases.
function extendAliases (...args) {
args.forEach(function (obj) {
Object.keys(obj || {}).forEach(function (key) {
// short-circuit if we've already added a key
// to the aliases array, for example it might
// exist in both 'opts.default' and 'opts.key'.
if (flags.aliases[key]) return
flags.aliases[key] = [].concat(aliases[key] || [])
// For "--option-name", also set argv.optionName
flags.aliases[key].concat(key).forEach(function (x) {
if (/-/.test(x) && configuration['camel-case-expansion']) {
const c = camelCase(x)
if (c !== key && flags.aliases[key].indexOf(c) === -1) {
flags.aliases[key].push(c)
newAliases[c] = true
}
}
})
// For "--optionName", also set argv['option-name']
flags.aliases[key].concat(key).forEach(function (x) {
if (x.length > 1 && /[A-Z]/.test(x) && configuration['camel-case-expansion']) {
const c = decamelize(x, '-')
if (c !== key && flags.aliases[key].indexOf(c) === -1) {
flags.aliases[key].push(c)
newAliases[c] = true
}
}
})
flags.aliases[key].forEach(function (x) {
flags.aliases[x] = [key].concat(flags.aliases[key].filter(function (y) {
return x !== y
}))
})
})
})
}
// return the 1st set flag for any of a key's aliases (or false if no flag set)
function checkAllAliases (key, flag) {
const toCheck = [].concat(flags.aliases[key] || [], key)
const keys = Object.keys(flag)
const setAlias = toCheck.find(key => keys.includes(key))
return setAlias ? flag[setAlias] : false
}
function hasAnyFlag (key) {
const toCheck = [].concat(Object.keys(flags).map(k => flags[k]))
return toCheck.some(function (flag) {
return Array.isArray(flag) ? flag.includes(key) : flag[key]
})
}
function hasFlagsMatching (arg, ...patterns) {
const toCheck = [].concat(...patterns)
return toCheck.some(function (pattern) {
const match = arg.match(pattern)
return match && hasAnyFlag(match[1])
})
}
// based on a simplified version of the short flag group parsing logic
function hasAllShortFlags (arg) {
// if this is a negative number, or doesn't start with a single hyphen, it's not a short flag group
if (arg.match(negative) || !arg.match(/^-[^-]+/)) { return false }
let hasAllFlags = true
let next
const letters = arg.slice(1).split('')
for (let j = 0; j < letters.length; j++) {
next = arg.slice(j + 2)
if (!hasAnyFlag(letters[j])) {
hasAllFlags = false
break
}
if ((letters[j + 1] && letters[j + 1] === '=') ||
next === '-' ||
(/[A-Za-z]/.test(letters[j]) && /^-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) ||
(letters[j + 1] && letters[j + 1].match(/\W/))) {
break
}
}
return hasAllFlags
}
function isUnknownOptionAsArg (arg) {
return configuration['unknown-options-as-args'] && isUnknownOption(arg)
}
function isUnknownOption (arg) {
// ignore negative numbers
if (arg.match(negative)) { return false }
// if this is a short option group and all of them are configured, it isn't unknown
if (hasAllShortFlags(arg)) { return false }
// e.g. '--count=2'
const flagWithEquals = /^-+([^=]+?)=[\s\S]*$/
// e.g. '-a' or '--arg'
const normalFlag = /^-+([^=]+?)$/
// e.g. '-a-'
const flagEndingInHyphen = /^-+([^=]+?)-$/
// e.g. '-abc123'
const flagEndingInDigits = /^-+([^=]+?\d+)$/
// e.g. '-a/usr/local'
const flagEndingInNonWordCharacters = /^-+([^=]+?)\W+.*$/
// check the different types of flag styles, including negatedBoolean, a pattern defined near the start of the parse method
return !hasFlagsMatching(arg, flagWithEquals, negatedBoolean, normalFlag, flagEndingInHyphen, flagEndingInDigits, flagEndingInNonWordCharacters)
}
// make a best effor to pick a default value
// for an option based on name and type.
function defaultValue (key) {
if (!checkAllAliases(key, flags.bools) &&
!checkAllAliases(key, flags.counts) &&
`${key}` in defaults) {
return defaults[key]
} else {
return defaultForType(guessType(key))
}
}
// return a default value, given the type of a flag.,
// e.g., key of type 'string' will default to '', rather than 'true'.
function defaultForType (type) {
const def = {
boolean: true,
string: '',
number: undefined,
array: []
}
return def[type]
}
// given a flag, enforce a default type.
function guessType (key) {
let type = 'boolean'
if (checkAllAliases(key, flags.strings)) type = 'string'
else if (checkAllAliases(key, flags.numbers)) type = 'number'
else if (checkAllAliases(key, flags.bools)) type = 'boolean'
else if (checkAllAliases(key, flags.arrays)) type = 'array'
return type
}
function isNumber (x) {
if (x === null || x === undefined) return false
// if loaded from config, may already be a number.
if (typeof x === 'number') return true
// hexadecimal.
if (/^0x[0-9a-f]+$/i.test(x)) return true
// don't treat 0123 as a number; as it drops the leading '0'.
if (x.length > 1 && x[0] === '0') return false
return /^[-]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x)
}
function isUndefined (num) {
return num === undefined
}
// check user configuration settings for inconsistencies
function checkConfiguration () {
// count keys should not be set as array/narg
Object.keys(flags.counts).find(key => {
if (checkAllAliases(key, flags.arrays)) {
error = Error(__('Invalid configuration: %s, opts.count excludes opts.array.', key))
return true
} else if (checkAllAliases(key, flags.nargs)) {
error = Error(__('Invalid configuration: %s, opts.count excludes opts.narg.', key))
return true
}
})
}
return {
argv: Object.assign(argvReturn, argv),
error: error,
aliases: Object.assign({}, flags.aliases),
newAliases: Object.assign({}, newAliases),
defaulted: Object.assign({}, defaulted),
configuration: configuration
}
}
// if any aliases reference each other, we should
// merge them together.
function combineAliases (aliases) {
const aliasArrays = []
const combined = Object.create(null)
let change = true
// turn alias lookup hash {key: ['alias1', 'alias2']} into
// a simple array ['key', 'alias1', 'alias2']
Object.keys(aliases).forEach(function (key) {
aliasArrays.push(
[].concat(aliases[key], key)
)
})
// combine arrays until zero changes are
// made in an iteration.
while (change) {
change = false
for (let i = 0; i < aliasArrays.length; i++) {
for (let ii = i + 1; ii < aliasArrays.length; ii++) {
const intersect = aliasArrays[i].filter(function (v) {
return aliasArrays[ii].indexOf(v) !== -1
})
if (intersect.length) {
aliasArrays[i] = aliasArrays[i].concat(aliasArrays[ii])
aliasArrays.splice(ii, 1)
change = true
break
}
}
}
}
// map arrays back to the hash-lookup (de-dupe while
// we're at it).
aliasArrays.forEach(function (aliasArray) {
aliasArray = aliasArray.filter(function (v, i, self) {
return self.indexOf(v) === i
})
combined[aliasArray.pop()] = aliasArray
})
return combined
}
// this function should only be called when a count is given as an arg
// it is NOT called to set a default value
// thus we can start the count at 1 instead of 0
function increment (orig) {
return orig !== undefined ? orig + 1 : 1
}
function Parser (args, opts) {
const result = parse(args.slice(), opts)
return result.argv
}
// parse arguments and return detailed
// meta information, aliases, etc.
Parser.detailed = function (args, opts) {
return parse(args.slice(), opts)
}
// TODO(bcoe): in the next major version of yargs, switch to
// Object.create(null) for dot notation:
function sanitizeKey (key) {
if (key === '__proto__') return '___proto___'
return key
}
module.exports = Parser
yargs-parser-18.1.1/lib/ 0000775 0000000 0000000 00000000000 13633624025 0014773 5 ustar 00root root 0000000 0000000 yargs-parser-18.1.1/lib/tokenize-arg-string.js 0000664 0000000 0000000 00000001530 13633624025 0021233 0 ustar 00root root 0000000 0000000 // take an un-split argv string and tokenize it.
module.exports = function (argString) {
if (Array.isArray(argString)) {
return argString.map(e => typeof e !== 'string' ? e + '' : e)
}
argString = argString.trim()
let i = 0
let prevC = null
let c = null
let opening = null
const args = []
for (let ii = 0; ii < argString.length; ii++) {
prevC = c
c = argString.charAt(ii)
// split on spaces unless we're in quotes.
if (c === ' ' && !opening) {
if (!(prevC === ' ')) {
i++
}
continue
}
// don't split the string if we're in matching
// opening or closing single and double quotes.
if (c === opening) {
opening = null
} else if ((c === "'" || c === '"') && !opening) {
opening = c
}
if (!args[i]) args[i] = ''
args[i] += c
}
return args
}
yargs-parser-18.1.1/package.json 0000664 0000000 0000000 00000001702 13633624025 0016513 0 ustar 00root root 0000000 0000000 {
"name": "yargs-parser",
"version": "18.1.1",
"description": "the mighty option parser used by yargs",
"main": "index.js",
"scripts": {
"fix": "standard --fix",
"test": "c8 --reporter=text --reporter=html mocha test/*.js",
"posttest": "standard",
"coverage": "c8 report --check-coverage check-coverage --lines=100 --branches=97 --statements=100"
},
"repository": {
"type": "git",
"url": "https://github.com/yargs/yargs-parser.git"
},
"keywords": [
"argument",
"parser",
"yargs",
"command",
"cli",
"parsing",
"option",
"args",
"argument"
],
"author": "Ben Coe ",
"license": "ISC",
"devDependencies": {
"c8": "^7.0.1",
"chai": "^4.2.0",
"mocha": "^7.0.0",
"standard": "^14.3.1"
},
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"files": [
"lib",
"index.js"
],
"engines": {
"node": ">=6"
}
}
yargs-parser-18.1.1/renovate.json 0000664 0000000 0000000 00000000220 13633624025 0016735 0 ustar 00root root 0000000 0000000 {
"extends": [
"config:base"
],
"pinVersions": false,
"rebaseStalePrs": true,
"gitAuthor": null,
"ignoreDeps": ["decamelize"]
}
yargs-parser-18.1.1/test/ 0000775 0000000 0000000 00000000000 13633624025 0015204 5 ustar 00root root 0000000 0000000 yargs-parser-18.1.1/test/fixtures/ 0000775 0000000 0000000 00000000000 13633624025 0017055 5 ustar 00root root 0000000 0000000 yargs-parser-18.1.1/test/fixtures/config.json 0000664 0000000 0000000 00000000357 13633624025 0021222 0 ustar 00root root 0000000 0000000 {
"herp": "derp",
"z": 55,
"foo": "baz",
"version": "1.0.2",
"truthy": true,
"toString": "method name",
"__proto__": {
"aaa": 99
},
"bar": {
"__proto__": {
"bbb": 100
}
}
}
yargs-parser-18.1.1/test/fixtures/config.txt 0000664 0000000 0000000 00000000035 13633624025 0021061 0 ustar 00root root 0000000 0000000 AWESOME=banana
BATMAN=grumpy
yargs-parser-18.1.1/test/fixtures/nested_config.json 0000664 0000000 0000000 00000000120 13633624025 0022550 0 ustar 00root root 0000000 0000000 {
"a": "a",
"nested": {
"foo": "baz",
"bar": "bar"
},
"b": "b"
} yargs-parser-18.1.1/test/fixtures/settings.js 0000664 0000000 0000000 00000000127 13633624025 0021253 0 ustar 00root root 0000000 0000000 module.exports = {
calculate: function (a) {
return a + 55
},
herp: 'derp'
}
yargs-parser-18.1.1/test/tokenize-arg-string.js 0000664 0000000 0000000 00000004366 13633624025 0021456 0 ustar 00root root 0000000 0000000 /* global describe, it */
const tokenizeArgString = require('../lib/tokenize-arg-string')
require('chai').should()
const expect = require('chai').expect
describe('TokenizeArgString', function () {
it('handles unquoted string', function () {
const args = tokenizeArgString('--foo 99')
args[0].should.equal('--foo')
args[1].should.equal('99')
})
it('handles unquoted numbers', function () {
const args = tokenizeArgString(['--foo', 9])
args[0].should.equal('--foo')
args[1].should.equal('9')
})
it('handles quoted string with no spaces', function () {
const args = tokenizeArgString("--foo 'hello'")
args[0].should.equal('--foo')
args[1].should.equal("'hello'")
})
it('handles single quoted string with spaces', function () {
const args = tokenizeArgString("--foo 'hello world' --bar='foo bar'")
args[0].should.equal('--foo')
args[1].should.equal("'hello world'")
args[2].should.equal("--bar='foo bar'")
})
it('handles double quoted string with spaces', function () {
const args = tokenizeArgString('--foo "hello world" --bar="foo bar"')
args[0].should.equal('--foo')
args[1].should.equal('"hello world"')
args[2].should.equal('--bar="foo bar"')
})
it('handles single quoted empty string', function () {
const args = tokenizeArgString('--foo \'\' --bar=\'\'')
args[0].should.equal('--foo')
args[1].should.equal("''")
args[2].should.equal("--bar=''")
})
it('handles double quoted empty string', function () {
const args = tokenizeArgString('--foo "" --bar=""')
args[0].should.equal('--foo')
args[1].should.equal('""')
args[2].should.equal('--bar=""')
})
it('handles quoted string with embedded quotes', function () {
var args = tokenizeArgString('--foo "hello \'world\'" --bar=\'foo "bar"\'')
args[0].should.equal('--foo')
args[1].should.equal('"hello \'world\'"')
args[2].should.equal('--bar=\'foo "bar"\'')
})
// https://github.com/yargs/yargs-parser/pull/100
// https://github.com/yargs/yargs-parser/pull/106
it('ignores unneeded spaces', function () {
const args = tokenizeArgString(' foo bar "foo bar" ')
args[0].should.equal('foo')
expect(args[1]).equal('bar')
expect(args[2]).equal('"foo bar"')
})
})
yargs-parser-18.1.1/test/yargs-parser.js 0000664 0000000 0000000 00000342131 13633624025 0020165 0 ustar 00root root 0000000 0000000 /* global beforeEach, describe, it */
require('chai').should()
const { expect } = require('chai')
const fs = require('fs')
const parser = require('../')
const path = require('path')
describe('yargs-parser', function () {
it('should parse a "short boolean"', function () {
var parse = parser(['-b'])
parse.should.not.have.property('--')
parse.should.have.property('b').to.be.ok.and.be.a('boolean')
parse.should.have.property('_').with.length(0)
})
it('should parse a "long boolean"', function () {
var parse = parser('--bool')
parse.should.not.have.property('--')
parse.should.have.property('bool', true)
parse.should.have.property('_').with.length(0)
})
it('should place bare options in the _ array', function () {
var parse = parser('foo bar baz')
parse.should.have.property('_').and.deep.equal(['foo', 'bar', 'baz'])
})
it('should set the value of the final option in a group to the next supplied value', function () {
var parse = parser(['-cats', 'meow'])
parse.should.have.property('c', true)
parse.should.have.property('a', true)
parse.should.have.property('t', true)
parse.should.have.property('s', 'meow')
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single long option to the next supplied value', function () {
var parse = parser(['--pow', 'xixxle'])
parse.should.have.property('pow', 'xixxle')
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single long option to the next supplied value, even if the value is empty', function () {
var parse = parser(['--pow', ''])
parse.should.have.property('pow', '')
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single long option if an = was used', function () {
var parse = parser(['--pow=xixxle'])
parse.should.have.property('pow', 'xixxle')
parse.should.have.property('_').with.length(0)
})
it('should set the value of multiple long options to the next supplied values relative to each', function () {
var parse = parser(['--host', 'localhost', '--port', '555'])
parse.should.have.property('host', 'localhost')
parse.should.have.property('port', 555)
parse.should.have.property('_').with.length(0)
})
it('should set the value of multiple long options if = signs were used', function () {
var parse = parser(['--host=localhost', '--port=555'])
parse.should.have.property('host', 'localhost')
parse.should.have.property('port', 555)
parse.should.have.property('_').with.length(0)
})
it('should still set values appropriately if a mix of short, long, and grouped short options are specified', function () {
var parse = parser(['-h', 'localhost', '-fp', '555', 'script.js'])
parse.should.have.property('f', true)
parse.should.have.property('p', 555)
parse.should.have.property('h', 'localhost')
parse.should.have.property('_').and.deep.equal(['script.js'])
})
it('should still set values appropriately if a mix of short and long options are specified', function () {
var parse = parser(['-h', 'localhost', '--port', '555'])
parse.should.have.property('h', 'localhost')
parse.should.have.property('port', 555)
parse.should.have.property('_').with.length(0)
})
it('should explicitly set a boolean option to false if preceded by "--no-"', function () {
var parse = parser(['--no-moo'])
parse.should.have.property('moo', false)
parse.should.have.property('_').with.length(0)
})
it('should still set values appropriately if we supply a comprehensive list of various types of options', function () {
var parse = parser([
'--name=meowmers', 'bare', '-cats', 'woo',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', '-', '-h', '-multi', '--', 'eek'
], {
configuration: {
'populate--': false
}
})
parse.should.have.property('c', true)
parse.should.have.property('a', true)
parse.should.have.property('t', true)
parse.should.have.property('s', 'woo')
parse.should.have.property('h', 'awesome')
parse.should.have.property('b', true)
parse.should.have.property('bool', true)
parse.should.have.property('key', 'value')
parse.should.have.property('multi').and.deep.equal(['quux', 'baz'])
parse.should.have.property('meep', false)
parse.should.have.property('name', 'meowmers')
parse.should.have.property('_').and.deep.equal(['bare', '--not-a-flag', '-', '-h', '-multi', '--', 'eek'])
})
it('should parse numbers appropriately', function () {
var argv = parser([
'-x', '1234',
'-y', '5.67',
'-z', '1e7',
'-w', '10f',
'--hex', '0xdeadbeef',
'789'
])
argv.should.have.property('x', 1234).and.be.a('number')
argv.should.have.property('y', 5.67).and.be.a('number')
argv.should.have.property('z', 1e7).and.be.a('number')
argv.should.have.property('w', '10f').and.be.a('string')
argv.should.have.property('hex', 0xdeadbeef).and.be.a('number')
argv.should.have.property('_').and.deep.equal([789])
argv._[0].should.be.a('number')
})
// addresses: https://github.com/yargs/yargs-parser/issues/33
it('should handle parsing negative #s', function () {
var argv = parser([
'-33', '-177', '33',
'--n1', '-33',
'-n', '-44',
'--n2=-55',
'--foo.bar', '-33',
'-o=-55',
'--bounds', '-180', '99', '-180', '90',
'--other', '-99', '-220'
], {
array: 'bounds',
narg: { other: 2 }
})
argv._.should.deep.equal([-33, -177, 33])
argv.n1.should.equal(-33)
argv.n.should.equal(-44)
argv.n2.should.equal(-55)
argv.foo.bar.should.equal(-33)
argv.o.should.equal(-55)
argv.bounds.should.deep.equal([-180, 99, -180, 90])
argv.other.should.deep.equal([-99, -220])
})
it('should handle negative (and positive) numbers with decimal places, with or without a leading 0', function () {
var argv = parser([
'-0.1', '-1.1', '-.5', '-.1', '.1', '.5',
'--bounds', '-5.1', '-.1', '.1',
'--other', '.9', '-.5'
], {
array: 'bounds',
narg: { other: 2 }
})
argv._.should.deep.equal([-0.1, -1.1, -0.5, -0.1, 0.1, 0.5])
argv.bounds.should.deep.equal([-5.1, -0.1, 0.1])
argv.other.should.deep.equal([0.9, -0.5])
})
it('should set the value of a single short option to the next supplied value, even if the value is empty', function () {
var parse = parser(['-p', ''])
parse.should.have.property('p', '')
parse.should.have.property('_').with.length(0)
})
it('should not set the next value as the value of a short option if that option is explicitly defined as a boolean', function () {
var parse = parser(['-t', 'moo'], {
boolean: 't'
})
parse.should.have.property('t', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['moo'])
})
it('should set boolean options values if the next value is "true" or "false"', function () {
var parse = parser(['--verbose', 'false', 'moo', '-t', 'true'], {
boolean: ['t', 'verbose'],
default: {
verbose: true
}
})
parse.should.have.property('verbose', false).and.be.a('boolean')
parse.should.have.property('t', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['moo'])
})
it('should not set boolean options values if the next value only contains the words "true" or "false"', function () {
var parse = parser(['--verbose', 'aaatrueaaa', 'moo', '-t', 'aaafalseaaa'], {
boolean: ['t', 'verbose']
})
parse.should.have.property('verbose', true).and.be.a('boolean')
parse.should.have.property('t', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['aaatrueaaa', 'moo', 'aaafalseaaa'])
})
it('should not use next value for boolean/number/string configured with zero narg', function () {
var parse = parser(['--bool', 'false', '--nr', '7', '--str', 'foo'], {
boolean: ['bool'],
number: ['nr'],
string: ['str'],
narg: { bool: 0, nr: 0, str: 0 }
})
parse.should.have.property('bool', true).and.be.a('boolean')
parse.should.have.property('nr', undefined).and.be.a('undefined')
parse.should.have.property('str', '').and.be.a('string')
parse.should.have.property('_').and.deep.equal(['false', 7, 'foo'])
})
it('should allow defining options as boolean in groups', function () {
var parse = parser(['-x', '-z', 'one', 'two', 'three'], {
boolean: ['x', 'y', 'z']
})
parse.should.have.property('x', true).and.be.a('boolean')
parse.should.not.have.property('y')
parse.should.have.property('z', true).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['one', 'two', 'three'])
})
it('should correctly parse dot-notation boolean flags', function () {
var parse = parser(['--nested', '--n.v', '--n.y', 'foo'], {
boolean: ['nested', 'n.v']
})
parse.should.have.property('nested', true).and.be.a('boolean')
parse.should.have.property('n').and.deep.equal({
v: true,
y: 'foo'
})
})
it('should preserve newlines in option values', function () {
var args = parser(['-s', 'X\nX'])
args.should.have.property('_').with.length(0)
args.should.have.property('s', 'X\nX')
// reproduce in bash:
// VALUE="new
// line"
// node program.js --s="$VALUE"
args = parser(['--s=X\nX'])
args.should.have.property('_').with.length(0)
args.should.have.property('s', 'X\nX')
})
it('should not convert numbers to type number if explicitly defined as strings', function () {
var s = parser(['-s', '0001234'], {
string: 's'
}).s
s.should.be.a('string').and.equal('0001234')
var x = parser(['-x', '56'], {
string: ['x']
}).x
x.should.be.a('string').and.equal('56')
})
it('should default numbers to undefined', function () {
var n = parser(['-n'], {
number: ['n']
}).n
expect(n).to.equal(undefined)
})
it('should default number to NaN if value is not a valid number', function () {
var n = parser(['-n', 'string'], {
number: ['n']
}).n
expect(n).to.deep.equal(NaN)
})
// Fixes: https://github.com/bcoe/yargs/issues/68
it('should parse flag arguments with no right-hand value as strings, if defined as strings', function () {
var s = parser(['-s'], {
string: ['s']
}).s
s.should.be.a('string').and.equal('')
s = parser(['-sf'], {
string: ['s']
}).s
s.should.be.a('string').and.equal('')
s = parser(['--string'], {
string: ['string']
}).string
s.should.be.a('string').and.equal('')
})
it('should leave all non-hyphenated values as strings if _ is defined as a string', function () {
var s = parser([' ', ' '], {
string: ['_']
})._
s.should.have.length(2)
s[0].should.be.a('string').and.equal(' ')
s[1].should.be.a('string').and.equal(' ')
})
describe('normalize', function () {
it('should normalize redundant paths', function () {
var a = parser(['-s', ['', 'tmp', '..', ''].join(path.sep)], {
alias: {
s: ['save']
},
normalize: 's'
})
a.should.have.property('s', path.sep)
a.should.have.property('save', path.sep)
})
it('should normalize redundant paths when a value is later assigned', function () {
var a = parser(['-s'], {
normalize: ['s']
})
a.should.have.property('s', true)
a.s = ['', 'path', 'to', 'new', 'dir', '..', '..', ''].join(path.sep)
a.s.should.equal(['', 'path', 'to', ''].join(path.sep))
})
it('should normalize when key is also an array', function () {
var a = parser(['-s', ['', 'tmp', '..', ''].join(path.sep), ['', 'path', 'to', 'new', 'dir', '..', '..', ''].join(path.sep)], {
alias: {
s: ['save']
},
normalize: 's',
array: 's'
})
var expected = [path.sep, ['', 'path', 'to', ''].join(path.sep)]
a.should.have.property('s').and.deep.equal(expected)
a.should.have.property('save').and.deep.equal(expected)
})
it('should allow normalized keys to be enumerated', () => {
var a = parser(['-s', ['', 'tmp', '..', ''].join(path.sep)], {
alias: {
s: ['save']
},
normalize: 's'
})
Object.keys(a).should.include('s')
})
})
describe('alias', function () {
it('should set alias value to the same value as the full option', function () {
var argv = parser(['-f', '11', '--zoom', '55'], {
alias: {
z: ['zoom']
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('z', 55)
argv.should.have.property('f', 11)
})
it('should allow multiple aliases to be specified', function () {
var argv = parser(['-f', '11', '--zoom', '55'], {
alias: {
z: ['zm', 'zoom']
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('z', 55)
argv.should.have.property('zm', 55)
argv.should.have.property('f', 11)
})
// regression, see https://github.com/chevex/yargs/issues/63
it('should not add the same key to argv multiple times, when creating camel-case aliases', function () {
var argv = parser(['--health-check=banana', '--second-key', 'apple', '-t=blarg'], {
alias: {
h: ['health-check'],
'second-key': ['s'],
'third-key': ['t']
},
default: {
h: 'apple',
'second-key': 'banana',
'third-key': 'third'
}
})
// before this fix, yargs failed parsing
// one but not all forms of an arg.
argv.secondKey.should.eql('apple')
argv.s.should.eql('apple')
argv['second-key'].should.eql('apple')
argv.healthCheck.should.eql('banana')
argv.h.should.eql('banana')
argv['health-check'].should.eql('banana')
argv.thirdKey.should.eql('blarg')
argv.t.should.eql('blarg')
argv['third-key'].should.eql('blarg')
})
it('should allow transitive aliases to be specified', function () {
var argv = parser(['-f', '11', '--zoom', '55'], {
alias: {
z: 'zm',
zm: 'zoom'
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('z', 55)
argv.should.have.property('zm', 55)
argv.should.have.property('f', 11)
})
it('should merge two lists of aliases if they collide', function () {
var argv = parser(['-f', '11', '--zoom', '55'], {
alias: {
z: 'zm',
zoom: 'zoop',
zm: 'zoom'
}
})
argv.should.have.property('zoom', 55)
argv.should.have.property('zoop', 55)
argv.should.have.property('z', 55)
argv.should.have.property('zm', 55)
argv.should.have.property('f', 11)
})
it('should set single-digit boolean alias', function () {
var argv = parser(['-f', '11', '-0'], {
alias: {
0: 'print0'
},
boolean: [
'print0'
]
})
argv.should.have.property('print0', true)
argv.should.have.property('f', 11)
})
it('should not set single-digit alias if no alias defined', function () {
var argv = parser(['-f', '11', '-0', '-1'])
argv.should.have.property('f', 11)
argv._.should.deep.equal([-0, -1])
})
it('should not set single-digit boolean alias if no boolean defined', function () {
var argv = parser(['-f', '11', '-9'], {
alias: {
0: 'print0'
}
})
argv.should.have.property('f', 11)
argv._.should.deep.equal([-9])
})
it('should be able to negate set single-digit boolean alias', function () {
var argv = parser(['--no-9'], {
alias: {
9: 'max'
},
boolean: [
'max'
]
})
argv.should.have.property('max', false)
})
})
it('should assign data after forward slash to the option before the slash', function () {
var parse = parser(['-I/foo/bar/baz'])
parse.should.have.property('_').with.length(0)
parse.should.have.property('I', '/foo/bar/baz')
parse = parser(['-xyz/foo/bar/baz'])
parse.should.have.property('x', true)
parse.should.have.property('y', true)
parse.should.have.property('z', '/foo/bar/baz')
parse.should.have.property('_').with.length(0)
})
const jsonPath = path.resolve(__dirname, './fixtures/config.json')
describe('config', function () {
// See: https://github.com/chevex/yargs/issues/12
it('should load options and values from default config if specified', function () {
var argv = parser(['--foo', 'bar'], {
alias: {
z: 'zoom'
},
default: {
settings: jsonPath
},
config: 'settings'
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('bar')
})
it('should use value from config file, if argv value is using default value', function () {
var argv = parser([], {
alias: {
z: 'zoom'
},
config: ['settings'],
default: {
settings: jsonPath,
foo: 'banana'
}
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('baz')
})
it('should combine values from config file and argv, if argv value is an array', function () {
var argv = parser(['--foo', 'bar'], {
config: ['settings'],
array: ['foo'],
default: {
settings: jsonPath
},
configuration: {
'combine-arrays': true
}
})
argv.should.have.property('foo').and.deep.equal(['bar', 'baz'])
})
it('should use value from config file, if argv key is a boolean', function () {
var argv = parser([], {
config: ['settings'],
default: {
settings: jsonPath
},
boolean: ['truthy']
})
argv.should.have.property('truthy', true)
})
it('should use value from cli, if cli overrides boolean argv key', function () {
var argv = parser(['--no-truthy'], {
config: ['settings'],
default: {
settings: jsonPath
},
boolean: ['truthy']
})
argv.should.have.property('truthy', false)
})
it('should use cli value, if cli value is set and both cli and default value match', function () {
var argv = parser(['--foo', 'banana'], {
alias: {
z: 'zoom'
},
config: ['settings'],
default: {
settings: jsonPath,
foo: 'banana'
}
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('banana')
})
it("should allow config to be set as flag in 'option'", function () {
var argv = parser(['--settings', jsonPath, '--foo', 'bar'], {
alias: {
z: 'zoom'
},
config: ['settings']
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('bar')
})
it('should load options and values from a JS file when config has .js extention', function () {
var jsPath = path.resolve(__dirname, './fixtures/settings.js')
var argv = parser(['--settings', jsPath, '--foo', 'bar'], {
config: ['settings']
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('foo', 'bar')
argv.should.have.property('calculate').and.be.a('function')
})
it('should raise an appropriate error if JSON file is not found', function () {
var argv = parser.detailed(['--settings', 'fake.json', '--foo', 'bar'], {
alias: {
z: 'zoom'
},
config: ['settings']
})
argv.error.message.should.equal('Invalid JSON config file: fake.json')
})
// see: https://github.com/bcoe/yargs/issues/172
it('should not raise an exception if config file is set as default argument value', function () {
var argv = parser.detailed([], {
default: {
config: 'foo.json'
},
config: ['config']
})
expect(argv.error).to.equal(null)
})
it('should load nested options from config file', function () {
var jsonPath = path.resolve(__dirname, './fixtures/nested_config.json')
var argv = parser(['--settings', jsonPath, '--nested.foo', 'bar'], {
config: ['settings']
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'bar',
bar: 'bar'
})
})
it('should use nested value from config file, if argv value is using default value', function () {
var jsonPath = path.resolve(__dirname, './fixtures/nested_config.json')
var argv = parser(['--settings', jsonPath], {
config: ['settings'],
default: {
'nested.foo': 'banana'
}
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'baz',
bar: 'bar'
})
})
it('allows a custom parsing function to be provided', function () {
var jsPath = path.resolve(__dirname, './fixtures/config.txt')
var argv = parser(['--settings', jsPath, '--foo', 'bar'], {
config: {
settings: function (configPath) {
// as an example, parse an environment
// variable style config:
// FOO=99
// BATMAN=grumpy
var config = {}
var txt = fs.readFileSync(configPath, 'utf-8')
txt.split(/\r?\n/).forEach(function (l) {
var kv = l.split('=')
config[kv[0].toLowerCase()] = kv[1]
})
return config
}
}
})
argv.batman.should.equal('grumpy')
argv.awesome.should.equal('banana')
argv.foo.should.equal('bar')
})
it('allows a custom parsing function to be provided as an alias', function () {
var jsPath = path.resolve(__dirname, './fixtures/config.json')
var argv = parser(['--settings', jsPath, '--foo', 'bar'], {
config: {
s: function (configPath) {
return JSON.parse(fs.readFileSync(configPath, 'utf-8'))
}
},
alias: {
s: ['settings']
}
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('foo', 'bar')
})
it('outputs an error returned by the parsing function', function () {
var argv = parser.detailed(['--settings=./package.json'], {
config: {
settings: function (configPath) {
return Error('someone set us up the bomb')
}
}
})
argv.error.message.should.equal('someone set us up the bomb')
})
it('outputs an error if thrown by the parsing function', function () {
var argv = parser.detailed(['--settings=./package.json'], {
config: {
settings: function (configPath) {
throw Error('someone set us up the bomb')
}
}
})
argv.error.message.should.equal('someone set us up the bomb')
})
it('should not pollute the prototype', function () {
const argv = parser(['--foo', 'bar'], {
alias: {
z: 'zoom'
},
default: {
settings: jsonPath
},
config: 'settings'
})
argv.should.have.property('herp', 'derp')
argv.should.have.property('zoom', 55)
argv.should.have.property('foo').and.deep.equal('bar')
expect({}.bbb).to.equal(undefined)
expect({}.aaa).to.equal(undefined)
})
})
describe('config objects', function () {
it('should load options from config object', function () {
var argv = parser(['--foo', 'bar'], {
configObjects: [{
apple: 'apple',
banana: 42,
foo: 'baz',
gotcha: null
}]
})
argv.should.have.property('apple', 'apple')
argv.should.have.property('banana', 42)
argv.should.have.property('foo', 'bar')
argv.should.have.property('gotcha', null)
})
it('should use value from config object, if argv value is using default value', function () {
var argv = parser([], {
configObjects: [{
apple: 'apple',
banana: 42,
foo: 'baz'
}],
default: {
foo: 'banana'
}
})
argv.should.have.property('apple', 'apple')
argv.should.have.property('banana', 42)
argv.should.have.property('foo', 'baz')
})
it('should use value from config object to all aliases', function () {
var argv = parser([], {
configObjects: [{
apple: 'apple',
banana: 42,
foo: 'baz'
}],
alias: {
a: ['apple'],
banana: ['b']
}
})
argv.should.have.property('apple', 'apple')
argv.should.have.property('a', 'apple')
argv.should.have.property('banana', 42)
argv.should.have.property('b', 42)
argv.should.have.property('foo', 'baz')
})
it('should load nested options from config object', function () {
var argv = parser(['--nested.foo', 'bar'], {
configObjects: [{
a: 'a',
nested: {
foo: 'baz',
bar: 'bar'
},
b: 'b'
}]
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'bar',
bar: 'bar'
})
})
it('should use nested value from config object, if argv value is using default value', function () {
var argv = parser([], {
configObjects: [{
a: 'a',
nested: {
foo: 'baz',
bar: 'bar'
},
b: 'b'
}],
default: {
'nested.foo': 'banana'
}
})
argv.should.have.property('a', 'a')
argv.should.have.property('b', 'b')
argv.should.have.property('nested').and.deep.equal({
foo: 'baz',
bar: 'bar'
})
})
it('should load objects with first object having greatest priority', function () {
var argv = parser(['--foo', 'bar'], {
configObjects: [{
bar: 'baz'
}, {
bar: 'quux',
foo: 'spam'
}]
})
argv.should.have.property('foo', 'bar')
argv.should.have.property('bar', 'baz')
})
it('should combine array typed options with alias and camel-case', function () {
var argv = parser(['--camEl', 'foo', '--camEl', 'bar', '-a', 'red'], {
array: ['cam-el', 'apple'],
alias: { apple: 'a' },
configObjects: [{ camEl: 'baz' }, { a: 'sweet' }],
configuration: {
'combine-arrays': true,
'camel-case-expansion': true
}
})
argv['cam-el'].should.deep.equal(['foo', 'bar', 'baz'])
argv.apple.should.deep.equal(['red', 'sweet'])
})
})
describe('dot notation', function () {
it('should allow object graph traversal via dot notation', function () {
var argv = parser([
'--foo.bar', '3', '--foo.baz', '4',
'--foo.quux.quibble', '5', '--foo.quux.o_O',
'--beep.boop'
])
argv.should.have.property('foo').and.deep.equal({
bar: 3,
baz: 4,
quux: {
quibble: 5,
o_O: true
}
})
argv.should.have.property('beep').and.deep.equal({ boop: true })
})
it('should apply defaults to dot notation arguments', function () {
var argv = parser([], {
default: {
'foo.bar': 99
}
})
argv.foo.bar.should.eql(99)
})
// see #279
it('should allow default to be overridden when an alias is provided', function () {
var argv = parser(['--foo.bar', '200'], {
default: {
'foo.bar': 99
}
})
argv.foo.bar.should.eql(200)
})
// see #279
it('should also override alias', function () {
var argv = parser(['--foo.bar', '200'], {
alias: {
'foo.bar': ['f']
},
default: {
'foo.bar': 99
}
})
argv.f.should.eql(200)
})
// see #279
it('should not set an undefined dot notation key', function () {
var argv = parser(['--foo.bar', '200'], {
default: {
'foo.bar': 99
},
alias: {
'foo.bar': ['f']
}
})
; ('foo.bar' in argv).should.equal(false)
})
it('should respect .string() for dot notation arguments', function () {
var argv = parser(['--foo.bar', '99', '--bar.foo=99'], {
string: ['foo.bar']
})
argv.foo.bar.should.eql('99')
argv.bar.foo.should.eql(99)
})
it('should populate aliases when dot notation is used', function () {
var argv = parser(['--foo.bar', '99'], {
alias: {
foo: ['f']
}
})
argv.f.bar.should.eql(99)
})
it('should populate aliases when nested dot notation is used', function () {
var argv = parser(['--foo.bar.snuh', '99', '--foo.apple', '33', '--foo.bar.cool', '11'], {
alias: {
foo: ['f']
}
})
argv.f.bar.snuh.should.eql(99)
argv.foo.bar.snuh.should.eql(99)
argv.f.apple.should.eql(33)
argv.foo.apple.should.eql(33)
argv.f.bar.cool.should.eql(11)
argv.foo.bar.cool.should.eql(11)
})
it("should allow flags to use dot notation, when separated by '='", function () {
var argv = parser(['-f.foo=99'])
argv.f.foo.should.eql(99)
})
it("should allow flags to use dot notation, when separated by ' '", function () {
var argv = parser(['-f.foo', '99'])
argv.f.foo.should.eql(99)
})
it('should allow flags to use dot notation when no right-hand-side is given', function () {
var argv = parser(['-f.foo', '99', '-f.bar'])
argv.f.foo.should.eql(99)
argv.f.bar.should.eql(true)
})
it('should not pollute the prototype', function () {
parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
Object.keys({}.__proto__).length.should.equal(0) // eslint-disable-line
expect({}.foo).to.equal(undefined)
expect({}.bar).to.equal(undefined)
})
})
it('should set boolean and alias using explicit true', function () {
var aliased = ['-h', 'true']
var aliasedArgv = parser(aliased, {
boolean: ['h'],
alias: {
h: ['herp']
}
})
aliasedArgv.should.have.property('herp', true)
aliasedArgv.should.have.property('h', true)
aliasedArgv.should.have.property('_').with.length(0)
})
// regression, see https://github.com/substack/node-optimist/issues/71
it('should set boolean and --x=true', function () {
var parsed = parser(['--boool', '--other=true'], {
boolean: ['boool']
})
parsed.should.have.property('boool', true)
parsed.should.have.property('other', 'true')
parsed = parser(['--boool', '--other=false'], {
boolean: ['boool']
})
parsed.should.have.property('boool', true)
parsed.should.have.property('other', 'false')
})
// regression, see https://github.com/chevex/yargs/issues/66
it('should set boolean options values if next value is "true" or "false" with = as separator', function () {
var argv = parser(['--bool=false'], {
boolean: ['b'],
alias: {
b: ['bool']
},
default: {
b: true
}
})
argv.bool.should.eql(false)
})
describe('short options', function () {
it('should set the value of multiple single short options to the next supplied values relative to each', function () {
var parse = parser(['-h', 'localhost', '-p', '555'])
parse.should.have.property('h', 'localhost')
parse.should.have.property('p', 555)
parse.should.have.property('_').with.length(0)
})
it('should set the value of a single short option to the next supplied value', function () {
var parse = parser(['-h', 'localhost'])
parse.should.have.property('h', 'localhost')
parse.should.have.property('_').with.length(0)
})
it('should expand grouped short options to a hash with a key for each', function () {
var parse = parser(['-cats'])
parse.should.have.property('c', true)
parse.should.have.property('a', true)
parse.should.have.property('t', true)
parse.should.have.property('s', true)
parse.should.have.property('_').with.length(0)
})
it('should set n to the numeric value 123', function () {
var argv = parser(['-n123'])
argv.should.have.property('n', 123)
})
it('should set n to the numeric value 123, with n at the end of a group', function () {
var argv = parser(['-ab5n123'])
argv.should.have.property('a', true)
argv.should.have.property('b', true)
argv.should.have.property('5', true)
argv.should.have.property('n', 123)
argv.should.have.property('_').with.length(0)
})
it('should set n to the numeric value 123, with = as separator', function () {
var argv = parser(['-n=123'])
argv.should.have.property('n', 123)
})
it('should set n to the numeric value 123, with n at the end of a group and = as separator', function () {
var argv = parser(['-ab5n=123'])
argv.should.have.property('a', true)
argv.should.have.property('b', true)
argv.should.have.property('5', true)
argv.should.have.property('n', 123)
argv.should.have.property('_').with.length(0)
})
})
describe('whitespace', function () {
it('should be whitespace', function () {
var argv = parser(['-x', '\t'])
argv.should.have.property('x', '\t')
})
})
describe('boolean modifier function', function () {
it('should prevent yargs from sucking in the next option as the value of the first option', function () {
// Arrange & Act
var result = parser(['-b', '123'], {
boolean: ['b']
})
// Assert
result.should.have.property('b').that.is.a('boolean').and.is.true // eslint-disable-line
result.should.have.property('_').and.deep.equal([123])
})
})
describe('defaults', function () {
function checkNoArgs (opts, hasAlias) {
it('should set defaults if no args', function () {
var result = parser([], opts)
result.should.have.property('flag', true)
if (hasAlias) {
result.should.have.property('f', true)
}
})
}
function checkExtraArg (opts, hasAlias) {
it('should set defaults if one extra arg', function () {
var result = parser(['extra'], opts)
result.should.have.property('flag', true)
result.should.have.property('_').and.deep.equal(['extra'])
if (hasAlias) {
result.should.have.property('f', true)
}
})
}
function checkStringArg (opts, hasAlias) {
it('should set defaults even if arg looks like a string', function () {
var result = parser(['--flag', 'extra'], opts)
result.should.have.property('flag', true)
result.should.have.property('_').and.deep.equal(['extra'])
if (hasAlias) {
result.should.have.property('f', true)
}
})
}
describe('for options with aliases', function () {
var opts = {
alias: {
flag: ['f']
},
default: {
flag: true
}
}
checkNoArgs(opts, true)
checkExtraArg(opts, true)
})
describe('for typed options without aliases', function () {
var opts = {
boolean: ['flag'],
default: {
flag: true
}
}
checkNoArgs(opts)
checkExtraArg(opts)
checkStringArg(opts)
})
describe('for typed options with aliases', function () {
var opts = {
alias: {
flag: ['f']
},
boolean: ['flag'],
default: {
flag: true
}
}
checkNoArgs(opts, true)
checkExtraArg(opts, true)
checkStringArg(opts, true)
})
describe('for boolean options', function () {
[true, false, undefined, null].forEach(function (def) {
describe('with explicit ' + def + ' default', function () {
var opts = {
default: {
flag: def
},
boolean: ['flag']
}
it('should set true if --flag in arg', function () {
parser(['--flag'], opts).flag.should.be.true // eslint-disable-line
})
it('should set false if --no-flag in arg', function () {
parser(['--no-flag'], opts).flag.should.be.false // eslint-disable-line
})
it('should set ' + def + ' if no flag in arg', function () {
expect(parser([], opts).flag).to.equal(def)
})
})
})
describe('without any default value', function () {
var opts = null
beforeEach(function () {
opts = {
boolean: ['flag']
}
})
it('should set true if --flag in arg', function () {
parser(['--flag'], opts).flag.should.be.true // eslint-disable-line
})
it('should set false if --no-flag in arg', function () {
parser(['--no-flag'], opts).flag.should.be.false // eslint-disable-line
})
it('should not add property if no flag in arg', function () {
parser([''], opts).should.not.have.property('flag')
})
})
// Fixes: https://github.com/bcoe/yargs/issues/341
it('should apply defaults to camel-case form of argument', function () {
var argv = parser([], {
default: {
'foo-bar': 99
}
})
argv.fooBar.should.equal(99)
})
// Fixes: https://github.com/yargs/yargs-parser/issues/77
it('should combine dot-notation and camel-case expansion', function () {
var argv = parser(['--dot-notation.foo.bar'])
argv.should.satisfy(function (args) {
return args.dotNotation.foo.bar
})
})
})
it('should define option as boolean and set default to true', function () {
var argv = parser([], {
boolean: ['sometrue'],
default: {
sometrue: true
}
})
argv.should.have.property('sometrue', true)
})
it('should define option as boolean and set default to false', function () {
var argv = parser([], {
default: {
somefalse: false
},
boolean: ['somefalse']
})
argv.should.have.property('somefalse', false)
})
it('should set boolean options to false by default', function () {
var parse = parser(['moo'], {
boolean: ['t', 'verbose'],
default: {
verbose: false,
t: false
}
})
parse.should.have.property('verbose', false).and.be.a('boolean')
parse.should.have.property('t', false).and.be.a('boolean')
parse.should.have.property('_').and.deep.equal(['moo'])
})
describe('track defaulted', function () {
it('should log defaulted options - not specified by user', function () {
var parsed = parser.detailed('', {
default: { foo: 'abc', 'bar.prop': 33, baz: 'x' },
configObjects: [{ baz: 'xyz' }]
})
expect(parsed.argv).to.eql({ _: [], baz: 'xyz', foo: 'abc', bar: { prop: 33 } })
parsed.defaulted.should.deep.equal({ foo: true, 'bar.prop': true })
})
it('should not log defaulted options - specified without value', function () {
var parsed = parser.detailed('--foo --bar.prop', {
default: { foo: 'abc', 'bar.prop': 33 }
})
parsed.argv.should.deep.equal({ _: [], foo: 'abc', bar: { prop: 33 } })
parsed.defaulted.should.deep.equal({})
})
it('should log defaulted options - no aliases included', function () {
var parsed = parser.detailed('', {
default: { kaa: 'abc' },
alias: { foo: 'kaa' }
})
parsed.argv.should.deep.equal({ _: [], kaa: 'abc', foo: 'abc' })
parsed.defaulted.should.deep.equal({ kaa: true })
})
it('setting an alias excludes associated key from defaulted', function () {
var parsed = parser.detailed('--foo abc', {
default: { kaa: 'abc' },
alias: { foo: 'kaa' }
})
parsed.argv.should.deep.equal({ _: [], kaa: 'abc', foo: 'abc' })
parsed.defaulted.should.deep.equal({})
})
})
})
describe('camelCase', function () {
function runTests (strict) {
if (!strict) {
// Skip this test in strict mode because this option is not specified
it('should provide options with dashes as camelCase properties', function () {
var result = parser(['--some-option'])
result.should.have.property('some-option').that.is.a('boolean').and.is.true // eslint-disable-line
result.should.have.property('someOption').that.is.a('boolean').and.is.true // eslint-disable-line
})
}
it('should provide count options with dashes as camelCase properties', function () {
var result = parser(['--some-option', '--some-option', '--some-option'], {
count: ['some-option']
})
result.should.have.property('some-option', 3)
result.should.have.property('someOption', 3)
})
it('should provide options with dashes and aliases as camelCase properties', function () {
var result = parser(['--some-option'], {
alias: {
'some-horse': 'o'
}
})
result.should.have.property('some-option').that.is.a('boolean').and.is.true // eslint-disable-line
result.should.have.property('someOption').that.is.a('boolean').and.is.true // eslint-disable-line
})
it('should provide defaults of options with dashes as camelCase properties', function () {
var result = parser([], {
default: {
'some-option': 'asdf'
}
})
result.should.have.property('some-option', 'asdf')
result.should.have.property('someOption', 'asdf')
})
it('should provide aliases of options with dashes as camelCase properties', function () {
var result = parser([], {
default: {
'some-option': 'asdf'
},
alias: {
'some-option': ['o']
}
})
result.should.have.property('o', 'asdf')
result.should.have.property('some-option', 'asdf')
result.should.have.property('someOption', 'asdf')
})
it('should not apply camel-case logic to 1-character options', function () {
var result = parser(['-p', 'hello'], {
alias: {
p: 'parallel',
P: 'parallel-series'
}
})
result.should.not.have.property('P', 'hello')
result.should.not.have.property('parallel-series', 'hello')
result.should.not.have.property('parallelSeries', 'hello')
result.should.have.property('parallel', 'hello')
result.should.have.property('p', 'hello')
})
it('should provide aliases of options with dashes as camelCase properties', function () {
var result = parser([], {
alias: {
o: ['some-option']
},
default: {
o: 'asdf'
}
})
result.should.have.property('o', 'asdf')
result.should.have.property('some-option', 'asdf')
result.should.have.property('someOption', 'asdf')
})
it('should provide aliases with dashes as camelCase properties', function () {
var result = parser(['--some-option', 'val'], {
alias: {
o: 'some-option'
}
})
result.should.have.property('o').that.is.a('string').and.equals('val')
result.should.have.property('some-option').that.is.a('string').and.equals('val')
result.should.have.property('someOption').that.is.a('string').and.equals('val')
})
// https://github.com/yargs/yargs-parser/issues/95
it('should not duplicate option values when equivalent dashed aliases are provided', function () {
var result = parser(['--someOption', 'val'], {
alias: {
someOption: 'some-option'
}
})
result.should.have.property('some-option').that.is.a('string').and.equals('val')
result.should.have.property('someOption').that.is.a('string').and.equals('val')
})
}
describe('dashes and camelCase', function () {
runTests()
})
describe('dashes and camelCase (strict)', function () {
runTests(true)
})
})
describe('-', function () {
it('should set - as value of n', function () {
var argv = parser(['-n', '-'])
argv.should.have.property('n', '-')
argv.should.have.property('_').with.length(0)
})
it('should set - as a non-hyphenated value', function () {
var argv = parser(['-'])
argv.should.have.property('_').and.deep.equal(['-'])
})
it('should set - as a value of f', function () {
var argv = parser(['-f-'])
argv.should.have.property('f', '-')
argv.should.have.property('_').with.length(0)
})
it('should set b to true and set - as a non-hyphenated value when b is set as a boolean', function () {
var argv = parser(['-b', '-'], {
boolean: ['b']
})
argv.should.have.property('b', true)
argv.should.have.property('_').and.deep.equal(['-'])
})
it('should set - as the value of s when s is set as a string', function () {
var argv = parser(['-s', '-'], {
string: ['s']
})
argv.should.have.property('s', '-')
argv.should.have.property('_').with.length(0)
})
})
describe('count', function () {
it('should count the number of times a boolean is present', function () {
var parsed
parsed = parser(['-x'], {
count: ['verbose']
})
parsed.verbose.should.equal(0)
parsed = parser(['--verbose'], {
count: ['verbose']
})
parsed.verbose.should.equal(1)
parsed = parser(['--verbose', '--verbose'], {
count: ['verbose']
})
parsed.verbose.should.equal(2)
parsed = parser(['-vvv'], {
alias: {
v: ['verbose']
},
count: ['verbose']
})
parsed.verbose.should.equal(3)
parsed = parser(['--verbose', '--verbose', '-v', '--verbose'], {
count: ['verbose'],
alias: {
v: ['verbose']
}
})
parsed.verbose.should.equal(4)
parsed = parser(['--verbose', '--verbose', '-v', '-vv'], {
count: ['verbose'],
alias: {
v: ['verbose']
}
})
parsed.verbose.should.equal(5)
})
it('should not consume the next argument', function () {
var parsed = parser(['-v', 'moo'], {
count: 'v'
})
parsed.v.should.equal(1)
parsed.should.have.property('_').and.deep.equal(['moo'])
parsed = parser(['--verbose', 'moomoo', '--verbose'], {
count: 'verbose'
})
parsed.verbose.should.equal(2)
parsed.should.have.property('_').and.deep.equal(['moomoo'])
})
it('should use a default value as is when no arg given', function () {
var parsed = parser([], {
count: 'v',
default: { v: 3 }
})
parsed.v.should.equal(3)
parsed = parser([], {
count: 'v',
default: { v: undefined }
})
expect(parsed.v).to.be.undefined // eslint-disable-line
parsed = parser([], {
count: 'v',
default: { v: null }
})
expect(parsed.v).to.be.null // eslint-disable-line
parsed = parser([], {
count: 'v',
default: { v: false }
})
parsed.v.should.equal(false)
parsed = parser([], {
count: 'v',
default: { v: 'hello' }
})
parsed.v.should.equal('hello')
})
it('should ignore a default value when arg given', function () {
var parsed = parser(['-vv', '-v', '-v'], {
count: 'v',
default: { v: 1 }
})
parsed.v.should.equal(4)
})
it('should increment regardless of arg value', function () {
var parsed = parser([
'-v',
'-v=true',
'-v', 'true',
'-v=false',
'-v', 'false',
'--no-v',
'-v=999',
'-v=foobar'
], { count: 'v' })
parsed.v.should.equal(8)
})
it('should add an error if counter is also set as array', function () {
var argv = parser.detailed(['--counter', '--counter', '--counter'], {
count: ['counter'],
array: ['counter']
})
argv.error.message.should.equal('Invalid configuration: counter, opts.count excludes opts.array.')
})
it('should add an error if counter is also set as narg', function () {
var argv = parser.detailed(['--counter', 'foo', 'bar'], {
count: ['counter'],
narg: { counter: 2 }
})
argv.error.message.should.equal('Invalid configuration: counter, opts.count excludes opts.narg.')
})
})
describe('array', function () {
it('should group values into an array if the same option is specified multiple times (duplicate-arguments-array=true)', function () {
var parse = parser(['-v', 'a', '-v', 'b', '-v', 'c'], { configuration: { 'duplicate-arguments-array': true } })
parse.should.have.property('v').and.deep.equal(['a', 'b', 'c'])
parse.should.have.property('_').with.length(0)
})
it('should keep only the last value if the same option is specified multiple times (duplicate-arguments-false)', function () {
var parse = parser(['-v', 'a', '-v', 'b', '-v', 'c'], { configuration: { 'duplicate-arguments-array': false } })
parse.should.have.property('v').and.equal('c')
parse.should.have.property('_').with.length(0)
})
it('should default an array to an empty array if passed as first option followed by another', function () {
var result = parser(['-a', '-b'], {
array: 'a'
})
result.should.have.property('a').and.deep.equal([])
})
it('should not attempt to default array if an element has already been populated', function () {
var result = parser(['-a', 'foo', 'bar', '-b'], {
array: 'a'
})
result.should.have.property('a').and.deep.equal(['foo', 'bar'])
})
it('should default argument to empty array if no value given', function () {
var result = parser(['-b', '--tag'], {
array: ['b', 'tag'],
default: { tag: [] }
})
result.b.should.deep.equal([])
result.tag.should.deep.equal([])
})
it('should place default of argument in array, when default provided', function () {
var result = parser(['-b', '--tag'], {
array: ['b', 'tag'],
default: { b: 33, tag: ['foo'] }
})
result.b.should.deep.equal([33])
result.tag.should.deep.equal(['foo'])
})
it('should place value of argument in array, when one argument provided', function () {
var result = parser(['-b', '33'], {
array: ['b']
})
Array.isArray(result.b).should.equal(true)
result.b[0].should.equal(33)
})
it('should add multiple argument values to the array', function () {
var result = parser(['-b', '33', '-b', 'hello'], {
array: 'b'
})
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
result.b.should.include('hello')
})
it('should allow array: true, to be set inside an option block', function () {
var result = parser(['-b', '33'], {
array: 'b'
})
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
})
// issue #103
it('should default camel-case alias to array type', function () {
var result = parser(['--ca-path', 'http://www.example.com'], {
array: ['ca-path']
})
Array.isArray(result['ca-path']).should.equal(true)
Array.isArray(result.caPath).should.equal(true)
})
it('should default alias to array type', function () {
var result = parser(['--ca-path', 'http://www.example.com'], {
array: 'ca-path',
alias: {
'ca-path': 'c'
}
})
Array.isArray(result['ca-path']).should.equal(true)
Array.isArray(result.caPath).should.equal(true)
Array.isArray(result.c).should.equal(true)
})
// see: https://github.com/bcoe/yargs/issues/162
it('should eat non-hyphenated arguments until hyphenated option is hit', function () {
var result = parser(['-a=hello', 'world', '-b',
'33', '22', '--foo', 'red', 'green',
'--bar=cat', 'dog'], {
array: ['a', 'b', 'foo', 'bar']
})
Array.isArray(result.a).should.equal(true)
result.a.should.include('hello')
result.a.should.include('world')
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
result.b.should.include(22)
Array.isArray(result.foo).should.equal(true)
result.foo.should.include('red')
result.foo.should.include('green')
Array.isArray(result.bar).should.equal(true)
result.bar.should.include('cat')
result.bar.should.include('dog')
})
// see: https://github.com/yargs/yargs-parser/pull/13
it('should support array for --foo= format when the key is a number', function () {
var result = parser(['--1=a', 'b'], {
array: ['1']
})
Array.isArray(result['1']).should.equal(true)
result['1'][0].should.equal('a')
result['1'][1].should.equal('b')
})
it('should create an array when passing an argument twice with same value', function () {
var result = parser(['-x', 'val1', '-x', 'val1'])
result.should.have.property('x').that.is.an('array').and.to.deep.equal(['val1', 'val1'])
})
it('should eat camelCase switch with camelCase array option', function () {
var result = parser(['--someOption', '1', '2'], {
array: ['someOption']
})
Array.isArray(result.someOption).should.equal(true)
result.someOption.should.deep.equal([1, 2])
})
it('should eat hyphenated switch with hyphenated array option', function () {
var result = parser(['--some-option', '1', '2'], {
array: ['some-option']
})
Array.isArray(result['some-option']).should.equal(true)
result['some-option'].should.deep.equal([1, 2])
})
it('should eat camelCase switch with hyphenated array option', function () {
var result = parser(['--someOption', '1', '2'], {
array: ['some-option']
})
Array.isArray(result['some-option']).should.equal(true)
result['some-option'].should.deep.equal([1, 2])
})
it('should eat hyphenated switch with camelCase array option', function () {
var result = parser(['--some-option', '1', '2'], {
array: ['someOption']
})
Array.isArray(result.someOption).should.equal(true)
result.someOption.should.deep.equal([1, 2])
})
// see https://github.com/yargs/yargs-parser/issues/6
it('should respect the type `boolean` option for arrays', function () {
var result = parser(['-x=true', 'false'], {
array: [{ key: 'x', boolean: true }]
})
result.should.have.property('x').that.is.an('array').and.to.deep.equal([true, false])
})
it('should respect type `boolean` without value for arrays', function () {
var result = parser(['-x', '-x'], {
array: [{ key: 'x', boolean: true }],
configuration: { 'flatten-duplicate-arrays': false }
})
result.x.should.deep.equal([[true], [true]])
})
it('should respect `boolean negation` for arrays', function () {
var result = parser(['--no-bool', '--no-bool'], {
array: [{ key: 'bool', boolean: true }],
configuration: { 'flatten-duplicate-arrays': false }
})
result.bool.should.deep.equal([[false], [false]])
})
it('should respect the type `number` option for arrays', function () {
var result = parser(['-x=5', '2'], {
array: [{ key: 'x', number: true }]
})
result.should.have.property('x').that.is.an('array').and.to.deep.equal([5, 2])
})
it('should respect the type `string` option for arrays', function () {
var result = parser(['-x=5', '2'], {
configuration: {
'parse-numbers': true
},
array: [{ key: 'x', string: true }]
})
result.should.have.property('x').that.is.an('array').and.to.deep.equal(['5', '2'])
})
it('should eat non-hyphenated arguments until hyphenated option is hit - combined with coercion', function () {
var result = parser([
'-a=hello', 'world',
'-b', '33', '22',
'--foo', 'true', 'false',
'--bar=cat', 'dog'
], {
array: [
'a',
{ key: 'b', integer: true },
{ key: 'foo', boolean: true },
'bar'
]
})
Array.isArray(result.a).should.equal(true)
result.a.should.include('hello')
result.a.should.include('world')
Array.isArray(result.b).should.equal(true)
result.b.should.include(33)
result.b.should.include(22)
Array.isArray(result.foo).should.equal(true)
result.foo.should.include(true)
result.foo.should.include(false)
Array.isArray(result.bar).should.equal(true)
result.bar.should.include('cat')
result.bar.should.include('dog')
})
})
describe('nargs', function () {
it('should allow the number of arguments following a key to be specified', function () {
var result = parser(['--foo', 'apple', 'bar'], {
narg: {
foo: 2
}
})
Array.isArray(result.foo).should.equal(true)
result.foo[0].should.equal('apple')
result.foo[1].should.equal('bar')
})
it('should raise an exception if there are not enough arguments following key', function () {
var argv = parser.detailed('--foo apple', {
narg: {
foo: 2
}
})
argv.error.message.should.equal('Not enough arguments following: foo')
})
it('nargs is applied to aliases', function () {
var result = parser(['--bar', 'apple', 'bar'], {
narg: {
foo: 2
},
alias: {
foo: 'bar'
}
})
Array.isArray(result.foo).should.equal(true)
result.foo[0].should.equal('apple')
result.foo[1].should.equal('bar')
})
it('should apply nargs to flag arguments', function () {
var result = parser(['-f', 'apple', 'bar', 'blerg'], {
narg: {
f: 2
}
})
result.f[0].should.equal('apple')
result.f[1].should.equal('bar')
result._[0].should.equal('blerg')
})
it('should support nargs for -f= and --bar= format arguments', function () {
var result = parser(['-f=apple', 'bar', 'blerg', '--bar=monkey', 'washing', 'cat'], {
narg: {
f: 2,
bar: 2
}
})
result.f[0].should.equal('apple')
result.f[1].should.equal('bar')
result._[0].should.equal('blerg')
result.bar[0].should.equal('monkey')
result.bar[1].should.equal('washing')
result._[1].should.equal('cat')
})
it('should not modify the input args if an = was used', function () {
var expected = ['-f=apple', 'bar', 'blerg', '--bar=monkey', 'washing', 'cat']
var args = expected.slice()
parser(args, {
narg: {
f: 2,
bar: 2
}
})
args.should.deep.equal(expected)
parser.detailed(args, {
narg: {
f: 2,
bar: 2
}
})
args.should.deep.equal(expected)
})
it('allows multiple nargs to be set at the same time', function () {
var result = parser(['--foo', 'apple', 'bar', '--bar', 'banana', '-f'], {
narg: {
foo: 2,
bar: 1
}
})
Array.isArray(result.foo).should.equal(true)
result.foo[0].should.equal('apple')
result.foo[1].should.equal('bar')
result.bar.should.equal('banana')
result.f.should.equal(true)
})
// see: https://github.com/yargs/yargs-parser/pull/13
it('should support nargs for --foo= format when the key is a number', function () {
var result = parser(['--1=a', 'b'], {
narg: {
1: 2
}
})
Array.isArray(result['1']).should.equal(true)
result['1'][0].should.equal('a')
result['1'][1].should.equal('b')
})
it('should not treat flag arguments as satisfying narg requirements', function () {
var result = parser.detailed(['--foo', '--bar', '99'], {
narg: {
foo: 1
}
})
result.argv.bar.should.equal(99)
result.error.message.should.equal('Not enough arguments following: foo')
})
// See: https://github.com/yargs/yargs-parser/issues/232
it('should treat flag arguments as satisfying narg requirements, if nargs-eats-options=true', function () {
var result = parser.detailed(['--foo', '--bar', '99', '--batman', 'robin'], {
narg: {
foo: 2
},
configuration: {
'nargs-eats-options': true
}
})
result.argv.foo.should.eql(['--bar', 99])
result.argv.batman.should.eql('robin')
})
it('should not consume more than configured nargs', function () {
var result = parser(['--foo', 'a', 'b'], {
narg: {
foo: 1
}
})
result.foo.should.eql('a')
})
})
describe('env vars', function () {
it('should apply all env vars if prefix is empty', function () {
process.env.ONE_FISH = 'twofish'
process.env.RED_FISH = 'bluefish'
var result = parser([], {
envPrefix: ''
})
result.oneFish.should.equal('twofish')
result.redFish.should.equal('bluefish')
})
it('should apply only env vars matching prefix if prefix is valid string', function () {
process.env.ONE_FISH = 'twofish'
process.env.RED_FISH = 'bluefish'
process.env.GREEN_EGGS = 'sam'
process.env.GREEN_HAM = 'iam'
var result = parser([], {
envPrefix: 'GREEN'
})
result.eggs.should.equal('sam')
result.ham.should.equal('iam')
expect(result.oneFish).to.be.undefined // eslint-disable-line
expect(result.redFish).to.be.undefined // eslint-disable-line
})
it('should set aliases for options defined by env var', function () {
process.env.AIRFORCE_ONE = 'two'
var result = parser([], {
envPrefix: 'AIRFORCE',
alias: {
1: ['one', 'uno']
}
})
result['1'].should.equal('two')
result.one.should.equal('two')
result.uno.should.equal('two')
})
it('should prefer command line value over env var', function () {
process.env.FOO_BAR = 'ignore'
var result = parser(['--foo-bar', 'baz'], {
envPrefix: ''
})
result.fooBar.should.equal('baz')
})
it('should respect type for args defined by env var', function () {
process.env.MY_TEST_STRING = '1'
process.env.MY_TEST_NUMBER = '2'
var result = parser([], {
string: 'string',
envPrefix: 'MY_TEST_'
})
result.string.should.equal('1')
result.number.should.equal(2)
})
it('should set option from aliased env var', function () {
process.env.SPACE_X = 'awesome'
var result = parser([], {
alias: {
xactly: 'x'
},
envPrefix: 'SPACE'
})
result.xactly.should.equal('awesome')
})
it('should prefer env var value over configured default', function () {
process.env.FOO_BALL = 'wut'
process.env.FOO_BOOL = 'true'
var result = parser([], {
envPrefix: 'FOO',
default: {
ball: 'baz',
bool: false
},
boolean: 'bool',
string: 'ball'
})
result.ball.should.equal('wut')
result.bool.should.equal(true)
})
var jsonPath = path.resolve(__dirname, './fixtures/config.json')
it('should prefer environment variables over config file', function () {
process.env.CFG_HERP = 'zerp'
var result = parser(['--cfg', jsonPath], {
envPrefix: 'CFG',
config: 'cfg',
string: 'herp',
default: {
herp: 'nerp'
}
})
result.herp.should.equal('zerp')
})
it('should support an env var value as config file option', function () {
process.env.TUX_CFG = jsonPath
var result = parser([], {
envPrefix: 'TUX',
config: ['cfg'],
default: {
z: 44
}
})
result.should.have.property('herp')
result.should.have.property('foo')
result.should.have.property('version')
result.should.have.property('truthy')
result.z.should.equal(55)
})
it('should prefer cli config file option over env var config file option', function () {
process.env.MUX_CFG = path.resolve(__dirname, '../package.json')
var result = parser(['--cfg', jsonPath], {
envPrefix: 'MUX',
config: 'cfg'
})
result.should.have.property('herp')
result.should.have.property('foo')
result.should.have.property('version')
result.should.have.property('truthy')
result.z.should.equal(55)
})
it('should apply all nested env vars', function () {
process.env.TEST_A = 'a'
process.env.TEST_NESTED_OPTION__FOO = 'baz'
process.env.TEST_NESTED_OPTION__BAR = 'bar'
var result = parser(['--nestedOption.foo', 'bar'], {
envPrefix: 'TEST'
})
result.should.have.property('a', 'a')
result.should.have.property('nestedOption').and.deep.equal({
foo: 'bar',
bar: 'bar'
})
})
it('should apply nested env var if argv value is using default value', function () {
process.env.TEST_A = 'a'
process.env.TEST_NESTED_OPTION__FOO = 'baz'
process.env.TEST_NESTED_OPTION__BAR = 'bar'
var result = parser([], {
envPrefix: 'TEST',
default: {
'nestedOption.foo': 'banana'
}
})
result.should.have.property('a', 'a')
result.should.have.property('nestedOption').and.deep.equal({
foo: 'baz',
bar: 'bar'
})
})
})
describe('configuration', function () {
describe('short option groups', function () {
it('allows short-option-groups to be disabled', function () {
var parse = parser(['-cats=meow'], {
configuration: {
'short-option-groups': false
}
})
parse.cats.should.equal('meow')
parse = parser(['-cats', 'meow'], {
configuration: {
'short-option-groups': false
}
})
parse.cats.should.equal('meow')
})
})
describe('camel-case expansion', function () {
it('does not expand camel-case aliases', function () {
var parsed = parser.detailed([], {
alias: {
'foo-bar': ['x']
},
configuration: {
'camel-case-expansion': false
}
})
expect(parsed.newAliases.fooBar).to.equal(undefined)
expect(parsed.aliases.fooBar).to.equal(undefined)
})
it('does not expand camel-case keys', function () {
var parsed = parser.detailed(['--foo-bar=apple'], {
configuration: {
'camel-case-expansion': false
}
})
expect(parsed.argv.fooBar).to.equal(undefined)
expect(parsed.argv['foo-bar']).to.equal('apple')
})
})
describe('dot notation', function () {
it('does not expand dot notation defaults', function () {
var parsed = parser([], {
default: {
'foo.bar': 'x'
},
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('x')
})
it('does not expand dot notation arguments', function () {
var parsed = parser(['--foo.bar', 'banana'], {
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('banana')
parsed = parser(['--foo.bar=banana'], {
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('banana')
})
it('should use value from cli, if cli overrides dot notation default', function () {
var parsed = parser(['--foo.bar', 'abc'], {
default: {
'foo.bar': 'default'
},
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('abc')
})
it('should also override dot notation alias', function () {
var parsed = parser(['--foo.bar', 'abc'], {
alias: {
'foo.bar': ['alias.bar']
},
default: {
'foo.bar': 'default'
},
configuration: {
'dot-notation': false
}
})
expect(parsed['alias.bar']).to.equal('abc')
})
it('does not expand alias of first element of dot notation arguments', function () {
var parsed = parser(['--foo.bar', 'banana'], {
alias: {
foo: ['f']
},
configuration: {
'dot-notation': false
}
})
expect(parsed['foo.bar']).to.equal('banana')
expect(parsed).not.to.include.keys('f.bar')
})
// addresses https://github.com/yargs/yargs/issues/716
it('does not append nested-object keys from config to top-level key', function () {
var parsed = parser([], {
alias: {
foo: ['f']
},
configuration: {
'dot-notation': false
},
configObjects: [
{
'website.com': {
a: 'b',
b: 'c'
}
}
]
})
parsed['website.com'].should.deep.equal({
a: 'b',
b: 'c'
})
})
})
describe('parse numbers', function () {
it('does not coerce defaults into numbers', function () {
var parsed = parser([], {
default: {
foo: '5'
},
configuration: {
'parse-numbers': false
}
})
expect(parsed.foo).to.equal('5')
})
it('does not coerce arguments into numbers', function () {
var parsed = parser(['--foo', '5'], {
configuration: {
'parse-numbers': false
}
})
expect(parsed.foo).to.equal('5')
})
it('does not coerce positional arguments into numbers', function () {
var parsed = parser(['5'], {
configuration: {
'parse-numbers': false
}
})
expect(parsed._[0]).to.equal('5')
})
it('parses number if option explicitly set to number type', function () {
var parsed = parser(['--foo', '5', '--bar', '6', '--baz', '7'], {
number: ['bar', 'baz'],
coerce: {
baz: val => val
},
configuration: {
'parse-numbers': false
}
})
expect(parsed.foo).to.equal('5')
expect(parsed.bar).to.equal(6)
expect(parsed.baz).to.equal(7)
})
it('should coerce elements of number typed arrays to numbers', function () {
var parsed = parser(['--foo', '4', '--foo', '5', '2'], {
array: ['foo'],
configObjects: [{ foo: ['1', '2', '3'] }],
configuration: {
'combine-arrays': true,
'flatten-duplicate-arrays': false
}
})
expect(parsed.foo).to.deep.equal([[4], [5, 2], [1, 2, 3]])
})
})
describe('boolean negation', function () {
it('does not negate arguments prefixed with --no-', function () {
var parsed = parser(['--no-dice'], {
configuration: {
'boolean-negation': false
}
})
parsed['no-dice'].should.equal(true)
expect(parsed.dice).to.equal(undefined)
})
it('negates boolean arguments with correct prefix', function () {
var parsed = parser(['--foodice'], {
configuration: {
'negation-prefix': 'foo'
}
})
expect(parsed.dice).to.equal(false)
})
})
describe('duplicate arguments array', function () {
it('adds duplicate argument to array', function () {
var parsed = parser('-x a -x b', {
configuration: {
'duplicate-arguments-array': true
}
})
parsed.x.should.deep.equal(['a', 'b'])
})
it('keeps only last argument', function () {
var parsed = parser('-x a -x b', {
configuration: {
'duplicate-arguments-array': false
}
})
parsed.x.should.equal('b')
})
it('does not interfere with nargs', function () {
var parsed = parser('-x a b c -x o p q', {
narg: { x: 3 },
configuration: {
'duplicate-arguments-array': false
}
})
parsed.x.should.deep.equal(['o', 'p', 'q'])
})
})
describe('flatten duplicate arrays', function () {
it('flattens duplicate array type', function () {
var parsed = parser('-x a b -x c d', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal(['a', 'b', 'c', 'd'])
})
it('nests duplicate array types', function () {
var parsed = parser('-x a b -x c d', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([['a', 'b'], ['c', 'd']])
})
it('nests duplicate array types of more than 2', function () {
var parsed = parser('-x a b -x c d -x e f -x g h', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']])
})
it('doesn\'t nests single arrays', function () {
var parsed = parser('-x a b', {
array: ['x'],
configuration: {
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal(['a', 'b'])
})
it('flattens duplicate array type, when argument uses dot notation', function () {
var parsed = parser('-x.foo a -x.foo b', {
array: ['x.foo'],
configuration: {
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal({ foo: ['a', 'b'] })
})
})
describe('duplicate-arguments-array VS flatten-duplicate-arrays', function () {
/*
duplicate=false, flatten=false
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [2, 3, 4]
type=string/number/etc
[-x 1 -x 2 -x 3] => 3
duplicate=false, flatten=true
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [2, 3, 4]
type=string/number/etc
[-x 1 -x 2 -x 3] => 3
duplicate=true, flatten=true
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [1, 2, 3, 2, 3, 4]
type=string/number/etc
[-x 1 -x 2 -x 3] => [1, 2, 3]
duplicate=true, flatten=false
type=array
[-x 1 2 3] => [1, 2, 3]
[-x 1 2 3 -x 2 3 4] => [[1, 2, 3], [2, 3, 4]]
type=string/number/etc
[-x 1 -x 2 -x 3] => [1, 2, 3]
*/
describe('duplicate=false, flatten=false,', function () {
describe('type=array', function () {
it('[-x 1 2 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 2 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [2, 3, 4]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([2, 3, 4])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => 3', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal(3)
})
})
describe('type=boolean', function () {
it('[-x true -x true -x false] => false', function () {
var parsed = parser('-x true -x true -x false', {
boolean: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal(false)
})
})
})
describe('duplicate=false, flatten=true,', function () {
describe('type=array', function () {
it('[-x 1 2 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 2 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [2, 3, 4]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal([2, 3, 4])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => 3', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal(3)
})
})
describe('type=boolean', function () {
it('[-x true -x true -x false] => false', function () {
var parsed = parser('-x true -x true -x false', {
boolean: ['x'],
configuration: {
'duplicate-arguments-array': false,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal(false)
})
})
})
describe('duplicate=true, flatten=true,', function () {
describe('type=array', function () {
it('[-x 1 2 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 2 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal([1, 2, 3])
})
it('[-x 1 2 3 -x 2 3 4] => [1, 2, 3, 2, 3, 4]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal([1, 2, 3, 2, 3, 4])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal([1, 2, 3])
})
})
describe('type=boolean', function () {
// in the casse of boolean arguments, only the last argument is used:
it('[-x true -x true -x false] => false', function () {
var parsed = parser('-x true -x true -x false', {
boolean: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': true
}
})
parsed.x.should.deep.equal(false)
})
})
})
describe('duplicate=true, flatten=false,', function () {
describe('type=array', function () {
it('[-x 1 -x 2 -x 3] => [[1], [2], [3]]', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([[1], [2], [3]])
})
it('[-x 1 2 3 -x 2 3 4] => [[1, 2, 3], [ 2, 3, 4]]', function () {
var parsed = parser('-x 1 2 3 -x 2 3 4', {
array: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([[1, 2, 3], [2, 3, 4]])
})
})
describe('type=number', function () {
it('[-x 1 -x 2 -x 3] => [1, 2, 3]', function () {
var parsed = parser('-x 1 -x 2 -x 3', {
number: 'x',
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal([1, 2, 3])
})
})
describe('type=boolean', function () {
it('[-x true -x true -x false] => false', function () {
var parsed = parser('-x true -x true -x false', {
boolean: ['x'],
configuration: {
'duplicate-arguments-array': true,
'flatten-duplicate-arrays': false
}
})
parsed.x.should.deep.equal(false)
})
})
})
})
describe('populate--', function () {
it('should populate "_" by default', function () {
var result = parser([
'bare',
'--', '-h', 'eek', '--'
])
result.should.have.property('_').and.deep.equal(['bare', '-h', 'eek', '--'])
result.should.not.have.property('--')
})
it('should populate "_" when given config with "short-option-groups" false', function () {
var result = parser.detailed([
'--', 'foo'
], {
configuration: {
'short-option-groups': false
}
})
result.argv.should.deep.equal({ _: ['foo'] })
result.argv.should.not.have.property('--')
result.newAliases.should.deep.equal({})
})
it('should populate the "--" if populate-- is "true"', function () {
var result = parser([
'--name=meowmers', 'bare', '-cats', 'woo', 'moxy',
'-h', 'awesome', '--multi=quux',
'--key', 'value',
'-b', '--bool', '--no-meep', '--multi=baz',
'--', '--not-a-flag', '-', '-h', '-multi', '--', 'eek'
], {
configuration: {
'populate--': true
}
})
result.should.have.property('c', true)
result.should.have.property('a', true)
result.should.have.property('t', true)
result.should.have.property('s', 'woo')
result.should.have.property('h', 'awesome')
result.should.have.property('b', true)
result.should.have.property('bool', true)
result.should.have.property('key', 'value')
result.should.have.property('multi').and.deep.equal(['quux', 'baz'])
result.should.have.property('meep', false)
result.should.have.property('name', 'meowmers')
result.should.have.property('_').and.deep.equal(['bare', 'moxy'])
result.should.have.property('--').and.deep.equal(['--not-a-flag', '-', '-h', '-multi', '--', 'eek'])
})
})
describe('set-placeholder-key', function () {
it('should not set placeholder key by default', function () {
var parsed = parser([], {
string: ['a']
})
parsed.should.not.have.property('a')
})
it('should set placeholder key to "undefined"', function () {
var parsed = parser([], {
array: ['a'],
boolean: ['b'],
string: ['c'],
number: ['d'],
count: ['e'],
normalize: ['f'],
narg: { g: 2 },
coerce: {
h: function (arg) {
return arg
}
},
configuration: { 'set-placeholder-key': true }
})
parsed.should.have.property('a')
expect(parsed.a).to.be.equal(undefined)
parsed.should.have.property('b')
expect(parsed.b).to.be.equal(undefined)
parsed.should.have.property('c')
expect(parsed.c).to.be.equal(undefined)
parsed.should.have.property('d')
expect(parsed.d).to.be.equal(undefined)
parsed.should.have.property('e')
expect(parsed.f).to.be.equal(undefined)
parsed.should.have.property('g')
expect(parsed.g).to.be.equal(undefined)
parsed.should.have.property('h')
expect(parsed.h).to.be.equal(undefined)
})
it('should not set placeholder for key with a default value', function () {
var parsed = parser([], {
string: ['a'],
default: { a: 'hello' },
configuration: { 'set-placeholder-key': true }
})
parsed.a.should.equal('hello')
})
it('should not set placeholder key with dot notation', function () {
var parsed = parser([], {
string: ['a.b']
})
parsed.should.not.have.property('a')
parsed.should.not.have.property('b')
parsed.should.not.have.property('a.b')
})
})
describe('halt-at-non-option', function () {
it('gets the entire rest of line', function () {
var parse = parser(['--foo', './file.js', '--foo', '--bar'], {
configuration: { 'halt-at-non-option': true },
boolean: ['foo', 'bar']
})
parse.should.deep.equal({ foo: true, _: ['./file.js', '--foo', '--bar'] })
})
it('is not influenced by --', function () {
var parse = parser(
['--foo', './file.js', '--foo', '--', 'barbar', '--bar'],
{ configuration: { 'halt-at-non-option': true }, boolean: ['foo', 'bar'] }
)
parse.should.deep.equal({
foo: true,
_: ['./file.js', '--foo', '--', 'barbar', '--bar']
})
})
it('is not influenced by unknown options', function () {
var parse = parser(
['-v', '--long', 'arg', './file.js', '--foo', '--', 'barbar'],
{ configuration: { 'halt-at-non-option': true }, boolean: ['foo'] }
)
parse.should.deep.equal({
v: true,
long: 'arg',
_: ['./file.js', '--foo', '--', 'barbar']
})
})
})
describe('unknown-options-as-args = true', function () {
it('should ignore unknown options in long format separated by =', function () {
const argv = parser('--known-arg=1 --unknown-arg=2', {
number: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['--unknown-arg=2'],
'known-arg': 1,
knownArg: 1
})
})
it('should ignore unknown options in boolean negations', function () {
const argv = parser('--no-known-arg --no-unknown-arg', {
boolean: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['--no-unknown-arg'],
'known-arg': false,
knownArg: false
})
})
it('should ignore unknown options in long format separated by space', function () {
const argv = parser('--known-arg a --unknown-arg b', {
string: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['--unknown-arg', 'b'],
'known-arg': 'a',
knownArg: 'a'
})
})
it('should ignore unknown options in short dot format separated by equals', function () {
const argv = parser('-k.arg=a -u.arg=b', {
string: ['k.arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u.arg=b'],
k: {
arg: 'a'
}
})
})
it('should ignore unknown options in short dot format separated by space', function () {
const argv = parser('-k.arg 1 -u.arg 2', {
number: ['k.arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u.arg', '2'],
k: {
arg: 1
}
})
})
it('should ignore unknown options in short format separated by equals', function () {
const argv = parser('-k=a -u=b', {
string: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u=b'],
k: 'a'
})
})
it('should ignore unknown options in short format followed by hyphen', function () {
const argv = parser('-k- -u-', {
string: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u-'],
k: '-'
})
})
it('should ignore unknown options in short format separated by space', function () {
const argv = parser('-k 1 -u 2', {
number: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u', '2'],
k: 1
})
})
it('should allow an unknown arg to be used as the value of another flag in short form', function () {
const argv = parser('-k -u', {
string: ['k'],
narg: { k: 1 },
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
k: '-u'
})
})
it('should allow an unknown arg to be used as the value of another flag in long form', function () {
const argv = parser('--known-arg --unknown-arg', {
string: ['known-arg'],
narg: { 'known-arg': 1 },
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
knownArg: '--unknown-arg',
'known-arg': '--unknown-arg'
})
})
it('should allow an unknown arg to be used as the value of another flag in array form', function () {
const argv = parser('--known-arg --unknown-arg1 --unknown-arg2', {
array: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
knownArg: ['--unknown-arg1', '--unknown-arg2'],
'known-arg': ['--unknown-arg1', '--unknown-arg2']
})
})
it('should ignore unknown options in short format followed by a number', function () {
const argv = parser('-k1 -u2', {
number: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u2'],
k: 1
})
})
it('should ignore unknown options in short format followed by a non-word character', function () {
const argv = parser('-k/1/ -u/2/', {
string: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-u/2/'],
k: '/1/'
})
})
it('should ignore unknown options in short format with multiple flags in one argument where an unknown flag is before the end', function () {
const argv = parser('-kuv', {
boolean: ['k', 'v'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-kuv']
})
})
it('should parse known options in short format with multiple flags in one argument where no unknown flag is in the argument', function () {
const argv = parser('-kv', {
boolean: ['k', 'v'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [],
k: true,
v: true
})
})
it('should parse negative numbers', function () {
const argv = parser('-k -33', {
boolean: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: [-33],
k: true
})
})
it('should not identify "--" as an unknown option', function () {
const argv = parser('-a -k one -1 -- -b -k two -2', {
boolean: ['k'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['-a', 'one', -1, '-b', '-k', 'two', '-2'],
k: true
})
})
it('should not identify "--" as an unknown option when "populate--" is true', function () {
const argv = parser('-a -k one -1 -- -b -k two -2', {
boolean: ['k'],
configuration: {
'populate--': true,
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
// populate argv._ with everything before the --
_: ['-a', 'one', -1],
// and argv['--'] with everything after the --
'--': ['-b', '-k', 'two', '-2'],
k: true
})
})
// see: https://github.com/yargs/yargs/issues/1489
it('should identify "hasOwnProperty" as unknown option', () => {
const argv = parser('--known-arg=1 --hasOwnProperty=33', {
number: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['--hasOwnProperty=33'],
'known-arg': 1,
knownArg: 1
})
})
})
// See: https://github.com/yargs/yargs-parser/issues/231
it('should collect unknown options terminated with digit', function () {
const argv = parser('--known-arg=1 --num2', {
alias: { num: ['n'] },
number: ['known-arg'],
configuration: {
'unknown-options-as-args': true
}
})
argv.should.deep.equal({
_: ['--num2'],
'known-arg': 1,
knownArg: 1
})
})
})
// addresses: https://github.com/yargs/yargs-parser/issues/41
it('defaults to empty array if array option is provided no values', function () {
var parsed = parser(['-f'], {
alias: {
f: 'files'
},
array: ['files']
})
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
parsed = parser(['--files'], {
alias: {
f: 'files'
},
array: ['files']
})
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
parsed = parser(['-f', '-y'], {
alias: {
f: 'files'
},
array: ['files']
})
parsed.f.should.deep.equal([])
parsed.files.should.deep.equal([])
})
describe('coerce', function () {
it('applies coercion function to simple arguments', function () {
var parsed = parser(['--foo', '99'], {
coerce: {
foo: function (arg) {
return arg * -1
}
}
})
parsed.foo.should.equal(-99)
})
it('applies coercion function to aliases', function () {
var parsed = parser(['--foo', '99'], {
coerce: {
f: function (arg) {
return arg * -1
}
},
alias: {
f: ['foo']
}
})
parsed.foo.should.equal(-99)
parsed.f.should.equal(-99)
})
it('applies coercion function to all dot options', function () {
var parsed = parser(['--foo.bar', 'nananana'], {
coerce: {
foo: function (val) {
val.bar += ', batman!'
return val
}
}
})
parsed.foo.bar.should.equal('nananana, batman!')
})
it('applies coercion to defaults', function () {
var parsed = parser([], {
default: { foo: 'bar' },
coerce: {
foo: function (val) {
return val.toUpperCase()
}
}
})
parsed.foo.should.equal('BAR')
})
it('applies coercion function to an implicit array', function () {
var parsed = parser(['--foo', '99', '-f', '33'], {
coerce: {
f: function (arg) {
return arg.map(function (a) {
return a * -1
})
}
},
alias: {
f: ['foo']
}
})
parsed.f.should.deep.equal([-99, -33])
parsed.foo.should.deep.equal([-99, -33])
})
it('applies coercion function to an explicit array', function () {
var parsed = parser(['--foo', '99', '-f', '33'], {
coerce: {
f: function (arg) {
return arg.map(function (a) {
return a * -1
})
}
},
array: ['foo'],
alias: {
f: ['foo']
}
})
parsed.f.should.deep.equal([-99, -33])
parsed.foo.should.deep.equal([-99, -33])
})
it('applies coercion function to _', function () {
var parsed = parser(['99', '33'], {
coerce: {
_: function (arg) {
return arg.map(function (a) {
return a * -1
})
}
}
})
parsed._.should.deep.equal([-99, -33])
})
// see: https://github.com/yargs/yargs/issues/550
it('coercion function can be used to parse large #s', function () {
var fancyNumberParser = function (arg) {
if (arg.length > 10) return arg
else return parseInt(arg)
}
var parsed = parser(['--foo', '88888889999990000998989898989898', '--bar', '998'], {
coerce: {
foo: fancyNumberParser,
bar: fancyNumberParser
}
})
; (typeof parsed.foo).should.equal('string')
parsed.foo.should.equal('88888889999990000998989898989898')
; (typeof parsed.bar).should.equal('number')
parsed.bar.should.equal(998)
})
it('populates argv.error, if an error is thrown', function () {
var parsed = parser.detailed(['--foo', '99'], {
coerce: {
foo: function (arg) {
throw Error('banana')
}
}
})
parsed.error.message.should.equal('banana')
})
it('populates argv.error, if an error is thrown for an explicit array', function () {
var parsed = parser.detailed(['--foo', '99'], {
array: ['foo'],
coerce: {
foo: function (arg) {
throw Error('foo is array: ' + Array.isArray(arg))
}
}
})
parsed.error.message.should.equal('foo is array: true')
})
// see: https://github.com/yargs/yargs-parser/issues/76
it('only runs coercion functions once, even with aliases', function () {
var runcount = 0
var func = (arg) => {
runcount++
return undefined
}
parser(['--foo', 'bar'], {
alias: {
foo: ['f', 'foo-bar', 'bar'],
b: ['bar']
},
coerce: {
bar: func
}
})
runcount.should.equal(1)
})
})
// see: https://github.com/yargs/yargs-parser/issues/37
it('normalizes all paths in array when provided via config object', function () {
var argv = parser(['--foo', 'bar'], {
array: ['a'],
normalize: ['a'],
configObjects: [{ a: ['bin/../a.txt', 'bin/../b.txt'] }]
})
argv.a.should.deep.equal(['a.txt', 'b.txt'])
})
// see: https://github.com/yargs/yargs/issues/963
it('does not magically convert numeric strings larger than Number.MAX_SAFE_INTEGER', () => {
const argv = parser(['--foo', '93940495950949399948393'])
argv.foo.should.equal('93940495950949399948393')
})
it('does not magically convert scientific notation larger than Number.MAX_SAFE_INTEGER', () => {
const argv = parser(['--foo', '33e99999'])
argv.foo.should.equal('33e99999')
})
it('converts numeric options larger than Number.MAX_SAFE_INTEGER to number', () => {
const argv = parser(['--foo', '93940495950949399948393'], {
number: ['foo']
})
argv.foo.should.equal(9.39404959509494e+22)
})
// see: https://github.com/yargs/yargs/issues/1099
it('does not magically convert options with leading + to number', () => {
const argv = parser(['--foo', '+5550100', '--bar', '+5550100'], {
number: 'bar'
})
argv.foo.should.equal('+5550100')
argv.bar.should.equal(5550100)
})
// see: https://github.com/yargs/yargs/issues/1099
it('does not magically convert options with leading 0 to number', () => {
const argv = parser(['--foo', '000000', '--bar', '000000'], {
number: 'bar'
})
argv.foo.should.equal('000000')
argv.bar.should.equal(0)
})
// see: https://github.com/yargs/yargs-parser/issues/101
describe('dot-notation array arguments combined with string arguments', function () {
it('parses correctly when dot-notation argument is first', function () {
var argv = parser(['--foo.bar', 'baz', '--foo', 'bux'])
Array.isArray(argv.foo).should.equal(true)
argv.foo[0].bar.should.equal('baz')
argv.foo[1].should.equal('bux')
})
it('parses correctly when dot-notation argument is last', function () {
var argv = parser(['--foo', 'bux', '--foo.bar', 'baz'])
Array.isArray(argv.foo).should.equal(true)
argv.foo[0].should.equal('bux')
argv.foo[1].bar.should.equal('baz')
})
it('parses correctly when there are multiple dot-notation arguments', function () {
var argv = parser(['--foo.first', 'firstvalue', '--foo', 'bux', '--foo.bar', 'baz', '--foo.bla', 'banana'])
Array.isArray(argv.foo).should.equal(true)
argv.foo.length.should.equal(4)
argv.foo[0].first.should.equal('firstvalue')
argv.foo[1].should.equal('bux')
argv.foo[2].bar.should.equal('baz')
argv.foo[3].bla.should.equal('banana')
})
})
// see: https://github.com/yargs/yargs-parser/issues/145
describe('strings with quotes and dashes', () => {
it('handles double quoted strings', function () {
const args = parser('--foo "hello world" --bar="goodnight\'moon"')
args.foo.should.equal('hello world')
args.bar.should.equal('goodnight\'moon')
const args2 = parser(['--foo', '"hello world"', '--bar="goodnight\'moon"'])
args2.foo.should.equal('hello world')
args2.bar.should.equal('goodnight\'moon')
})
it('handles single quoted strings', function () {
const args = parser("--foo 'hello world' --bar='goodnight\"moon'")
args.foo.should.equal('hello world')
args.bar.should.equal('goodnight"moon')
const args2 = parser(['--foo', "'hello world'", "--bar='goodnight\"moon'"])
args2.foo.should.equal('hello world')
args2.bar.should.equal('goodnight"moon')
})
it('handles strings with dashes', function () {
const args = parser('--foo "-hello world" --bar="--goodnight moon"')
args.foo.should.equal('-hello world')
args.bar.should.equal('--goodnight moon')
})
})
// see: https://github.com/yargs/yargs-parser/issues/144
it('number/string types should use default when no right-hand value', () => {
let argv = parser(['--foo'], {
number: ['foo'],
default: {
foo: 99
}
})
argv.foo.should.equal(99)
argv = parser(['-b'], {
alias: {
bar: 'b'
},
string: ['bar'],
default: {
bar: 'hello'
}
})
argv.bar.should.equal('hello')
})
describe('stripping', function () {
it('strip-dashed removes expected fields from argv', function () {
const argv = parser(['--test-value', '1'], {
number: ['test-value'],
alias: {
'test-value': ['alt-test']
},
configuration: {
'strip-dashed': true
}
})
argv.should.deep.equal({
_: [],
testValue: 1,
altTest: 1
})
})
it('strip-aliased removes expected fields from argv', function () {
const argv = parser(['--test-value', '1'], {
number: ['test-value'],
alias: {
'test-value': ['alt-test']
},
configuration: {
'strip-aliased': true
}
})
argv.should.deep.equal({
_: [],
'test-value': 1,
testValue: 1
})
})
it('strip-aliased and strip-dashed combined removes expected fields from argv', function () {
const argv = parser(['--test-value', '1'], {
number: ['test-value'],
alias: {
'test-value': ['alt-test']
},
configuration: {
'strip-aliased': true,
'strip-dashed': true
}
})
argv.should.deep.equal({
_: [],
testValue: 1
})
})
it('ignores strip-dashed if camel-case-expansion is disabled', function () {
const argv = parser(['--test-value', '1'], {
number: ['test-value'],
configuration: {
'camel-case-expansion': false,
'strip-dashed': true
}
})
argv.should.deep.equal({
_: [],
'test-value': 1
})
})
})
describe('prototype collisions', () => {
it('parses unknown argument colliding with prototype', () => {
var parse = parser(['--toString'])
parse.toString.should.equal(true)
})
it('parses unknown argument colliding with prototype, when unknown options as args', () => {
var parse = parser(['--toString'], {
configuration: {
'unknown-options-as-args': true
}
})
parse._.should.include('--toString')
})
it('handles "alias" colliding with prototype', () => {
var parse = parser(['-t', '99'], {
alias: {
toString: ['t']
}
})
parse.toString.should.equal(99)
parse.t.should.equal(99)
parse['to-string'].should.equal(99)
})
it('handles multiple args colliding with alias', () => {
var parse = parser(['--toString', '88', '--toString', '99'])
parse.toString.should.eql([88, 99])
})
it('handle dot notation colliding with alias', () => {
var parse = parser(['--toString.cool', 'apple'])
parse.toString.cool.should.equal('apple')
})
it('handles "arrays" colliding with prototype', () => {
var parse = parser(['--toString', '99', '100'], {
array: ['toString']
})
parse.toString.should.eql([99, 100])
})
it('handles "arrays" colliding with prototype', () => {
var parse = parser(['--toString', '99', '100'], {
array: ['toString']
})
parse.toString.should.eql([99, 100])
})
it('handles "strings" colliding with prototype', () => {
var parse = parser(['--toString', '99'], {
string: ['toString']
})
parse.toString.should.eql('99')
})
it('handles "numbers" colliding with prototype', () => {
var parse = parser(['--toString', '99'], {
number: ['toString'],
configuration: {
'parse-numbers': false
}
})
parse.toString.should.eql(99)
})
it('handles "counts" colliding with prototype', () => {
var parse = parser(['--toString', '--toString', '--toString'], {
count: ['toString']
})
parse.toString.should.eql(3)
})
it('handles "normalize" colliding with prototype', () => {
var parse = parser(['--toString', './node_modules/chai'], {
normalize: ['toString']
})
parse.toString.should.include('node_modules')
})
it('handles "normalize" colliding with prototype', () => {
var parse = parser(['--toString', './node_modules/chai'], {
normalize: ['toString']
})
parse.toString.should.include('node_modules')
})
it('handles key in configuration file that collides with prototype', function () {
var argv = parser(['--foo', 'bar'], {
alias: {
z: 'zoom'
},
default: {
settings: jsonPath
},
config: 'settings'
})
argv.toString.should.equal('method name')
})
it('handles "nargs" colliding with prototype', () => {
var parse = parser(['--toString', 'apple', 'banana', 'batman', 'robin'], {
narg: {
toString: 3
}
})
parse.toString.should.eql(['apple', 'banana', 'batman'])
parse._.should.eql(['robin'])
})
it('handles "coercions" colliding with prototype', () => {
var parse = parser(['--toString', '33'], {
coerce: {
toString: (val) => {
return val * 2
}
}
})
parse.toString.should.equal(66)
})
})
// See: https://github.com/facebook/jest/issues/9517
it('does not collect arguments configured as booleans into implicit array', () => {
var parse = parser(['--infinite', 'true', '--infinite', 'true', '--no-infinite'], {
boolean: 'infinite'
})
parse.infinite.should.equal(false)
})
// See: https://github.com/yargs/yargs/issues/1098,
// https://github.com/yargs/yargs/issues/1570
describe('array with nargs', () => {
it('allows array and nargs to be configured in conjunction, enforcing the nargs value', () => {
var parse = parser.detailed(['-a', 'apple', 'banana'], {
array: 'a',
narg: {
a: 1
}
})
expect(parse.error).to.be.null // eslint-disable-line
parse.argv.a.should.eql(['apple'])
parse.argv._.should.eql(['banana'])
})
// see; https://github.com/yargs/yargs/issues/1098
it('allows special NaN count to be provided to narg, to indicate one or more array values', () => {
var parse = parser.detailed(['-a', 'apple', 'banana'], {
array: 'a',
narg: {
a: NaN
}
})
expect(parse.error).to.be.null // eslint-disable-line
parse.argv.a.should.eql(['apple', 'banana'])
})
it('throws error if at least one value not provided for NaN', () => {
var parse = parser.detailed(['-a'], {
array: 'a',
narg: {
a: NaN
}
})
parse.error.message.should.match(/Not enough arguments/)
})
it('returns an error if not enough positionals were provided for nargs', () => {
var parse = parser.detailed(['-a', '33'], {
array: 'a',
narg: {
a: 2
}
})
parse.argv.a.should.eql([33])
parse.error.message.should.equal('Not enough arguments following: a')
})
it('does not raise error if no arguments are provided for boolean option', () => {
var parse = parser.detailed(['-a'], {
array: 'a',
boolean: 'a',
narg: {
a: NaN
}
})
expect(parse.error).to.be.null // eslint-disable-line
parse.argv.a.should.eql([true])
})
})
describe('greedy-arrays=false', () => {
it('does not consume more than one argument after array option', () => {
const argv = parser(['--arr', 'foo', 'bar'], {
array: 'arr',
configuration: {
'greedy-arrays': false
}
})
argv.arr.should.eql(['foo'])
argv._.should.eql(['bar'])
})
it('places argument into array when specified multiple times', () => {
const argv = parser(['--arr', 99, 'foo', '--arr', 'hello', 'bar'], {
array: 'arr',
configuration: {
'greedy-arrays': false
}
})
argv.arr.should.eql([99, 'hello'])
argv._.should.eql(['foo', 'bar'])
})
it('places boolean arguments into array when specified multiple times', () => {
const argv = parser(['--arr', 101, '--arr', 102, '--arr', 'false'], {
array: 'arr',
boolean: 'arr',
configuration: {
'greedy-arrays': false
}
})
argv.arr.should.eql([true, true, false])
argv._.should.eql([101, 102])
})
})
it('should replace the key __proto__ with the key ___proto___', function () {
const argv = parser(['-f.__proto__.foo', '99', '-x.y.__proto__.bar', '100', '--__proto__', '200'])
argv.should.eql({
_: [],
___proto___: 200,
f: {
___proto___: {
foo: 99
}
},
x: {
y: {
___proto___: {
bar: 100
}
}
}
})
})
})
yargs-parser-18.1.1/yargs-logo.png 0000664 0000000 0000000 00000041431 13633624025 0017021 0 ustar 00root root 0000000 0000000 PNG
IHDR X bKGD pHYs gR tIME9_ iTXtComment Created with GIMPd.e IDATxwXoT]cM$^5$^@(U{K$ؖ;
b⦆b5Q).efy>ffϜo! :A&