Skip to content

Commit ae11f49

Browse files
authored
fix: parser should preserve inner quotes (#407)
1 parent 90f970a commit ae11f49

File tree

2 files changed

+37
-13
lines changed

2 files changed

+37
-13
lines changed

lib/yargs-parser.ts

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export class YargsParser {
5959
// allow a string argument to be passed in rather
6060
// than an argv array.
6161
const args = tokenizeArgString(argsInput)
62+
// tokenizeArgString adds extra quotes to args if argsInput is a string
63+
// only strip those extra quotes in processValue if argsInput is a string
64+
const inputIsString = typeof argsInput === 'string'
6265

6366
// aliases might have transitive relationships, normalize this.
6467
const aliases = combineAliases(Object.assign(Object.create(null), opts.alias))
@@ -243,7 +246,7 @@ export class YargsParser {
243246
// nargs format = '--f=monkey washing cat'
244247
i = eatNargs(i, m[1], args, m[2])
245248
} else {
246-
setArg(m[1], m[2])
249+
setArg(m[1], m[2], true)
247250
}
248251
}
249252
} else if (arg.match(negatedBoolean) && configuration['boolean-negation']) {
@@ -516,15 +519,15 @@ export class YargsParser {
516519
} else {
517520
// value in --option=value is eaten as is
518521
if (!isUndefined(argAfterEqualSign)) {
519-
argsToSet.push(processValue(key, argAfterEqualSign))
522+
argsToSet.push(processValue(key, argAfterEqualSign, true))
520523
}
521524
for (let ii = i + 1; ii < args.length; ii++) {
522525
if ((!configuration['greedy-arrays'] && argsToSet.length > 0) ||
523526
(nargsCount && typeof nargsCount === 'number' && argsToSet.length >= nargsCount)) break
524527
next = args[ii]
525528
if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break
526529
i = ii
527-
argsToSet.push(processValue(key, next))
530+
argsToSet.push(processValue(key, next, inputIsString))
528531
}
529532
}
530533

@@ -540,15 +543,15 @@ export class YargsParser {
540543
return i
541544
}
542545

543-
function setArg (key: string, val: any): void {
546+
function setArg (key: string, val: any, shouldStripQuotes: boolean = inputIsString): void {
544547
if (/-/.test(key) && configuration['camel-case-expansion']) {
545548
const alias = key.split('.').map(function (prop) {
546549
return camelCase(prop)
547550
}).join('.')
548551
addNewAlias(key, alias)
549552
}
550553

551-
const value = processValue(key, val)
554+
const value = processValue(key, val, shouldStripQuotes)
552555
const splitKey = key.split('.')
553556
setKey(argv, splitKey, value)
554557

@@ -605,13 +608,10 @@ export class YargsParser {
605608
}
606609
}
607610

608-
function processValue (key: string, val: any) {
611+
function processValue (key: string, val: any, shouldStripQuotes: boolean) {
609612
// strings may be quoted, clean this up as we assign values.
610-
if (typeof val === 'string' &&
611-
(val[0] === "'" || val[0] === '"') &&
612-
val[val.length - 1] === val[0]
613-
) {
614-
val = val.substring(1, val.length - 1)
613+
if (shouldStripQuotes) {
614+
val = stripQuotes(val)
615615
}
616616

617617
// handle parsing boolean arguments --foo=true --bar false.
@@ -1116,3 +1116,13 @@ function sanitizeKey (key: string): string {
11161116
if (key === '__proto__') return '___proto___'
11171117
return key
11181118
}
1119+
1120+
function stripQuotes (val: string): string {
1121+
return (
1122+
typeof val === 'string' &&
1123+
(val[0] === "'" || val[0] === '"') &&
1124+
val[val.length - 1] === val[0]
1125+
)
1126+
? val.substring(1, val.length - 1)
1127+
: val
1128+
}

test/yargs-parser.cjs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3569,7 +3569,7 @@ describe('yargs-parser', function () {
35693569
args.foo.should.equal('hello world')
35703570
args.bar.should.equal('goodnight\'moon')
35713571
const args2 = parser(['--foo', '"hello world"', '--bar="goodnight\'moon"'])
3572-
args2.foo.should.equal('hello world')
3572+
args2.foo.should.equal('"hello world"')
35733573
args2.bar.should.equal('goodnight\'moon')
35743574
})
35753575

@@ -3578,7 +3578,7 @@ describe('yargs-parser', function () {
35783578
args.foo.should.equal('hello world')
35793579
args.bar.should.equal('goodnight"moon')
35803580
const args2 = parser(['--foo', "'hello world'", "--bar='goodnight\"moon'"])
3581-
args2.foo.should.equal('hello world')
3581+
args2.foo.should.equal("'hello world'")
35823582
args2.bar.should.equal('goodnight"moon')
35833583
})
35843584

@@ -3587,6 +3587,20 @@ describe('yargs-parser', function () {
35873587
args.foo.should.equal('-hello world')
35883588
args.bar.should.equal('--goodnight moon')
35893589
})
3590+
3591+
it('respects inner quotes (string)', function () {
3592+
const args = parser('cmd --foo ""Hello"" --bar ""World"" --baz="":)""')
3593+
args.foo.should.equal('"Hello"')
3594+
args.bar.should.equal('"World"')
3595+
args.baz.should.equal('":)"')
3596+
})
3597+
3598+
it('respects inner quotes (array)', function () {
3599+
const args = parser(['cmd', '--foo', '"Hello"', '--bar', '"World"', '--baz="":)""'])
3600+
args.foo.should.equal('"Hello"')
3601+
args.bar.should.equal('"World"')
3602+
args.baz.should.equal('":)"')
3603+
})
35903604
})
35913605

35923606
// see: https://github.com/yargs/yargs-parser/issues/144

0 commit comments

Comments
 (0)