Skip to content

Commit

Permalink
fix: parser should preserve inner quotes (#407)
Browse files Browse the repository at this point in the history
  • Loading branch information
jly36963 committed Nov 15, 2021
1 parent 90f970a commit ae11f49
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 13 deletions.
32 changes: 21 additions & 11 deletions lib/yargs-parser.ts
Expand Up @@ -59,6 +59,9 @@ export class YargsParser {
// allow a string argument to be passed in rather
// than an argv array.
const args = tokenizeArgString(argsInput)
// tokenizeArgString adds extra quotes to args if argsInput is a string
// only strip those extra quotes in processValue if argsInput is a string
const inputIsString = typeof argsInput === 'string'

// aliases might have transitive relationships, normalize this.
const aliases = combineAliases(Object.assign(Object.create(null), opts.alias))
Expand Down Expand Up @@ -243,7 +246,7 @@ export class YargsParser {
// nargs format = '--f=monkey washing cat'
i = eatNargs(i, m[1], args, m[2])
} else {
setArg(m[1], m[2])
setArg(m[1], m[2], true)
}
}
} else if (arg.match(negatedBoolean) && configuration['boolean-negation']) {
Expand Down Expand Up @@ -516,15 +519,15 @@ export class YargsParser {
} else {
// value in --option=value is eaten as is
if (!isUndefined(argAfterEqualSign)) {
argsToSet.push(processValue(key, argAfterEqualSign))
argsToSet.push(processValue(key, argAfterEqualSign, true))
}
for (let ii = i + 1; ii < args.length; ii++) {
if ((!configuration['greedy-arrays'] && argsToSet.length > 0) ||
(nargsCount && typeof nargsCount === 'number' && argsToSet.length >= nargsCount)) break
next = args[ii]
if (/^-/.test(next) && !negative.test(next) && !isUnknownOptionAsArg(next)) break
i = ii
argsToSet.push(processValue(key, next))
argsToSet.push(processValue(key, next, inputIsString))
}
}

Expand All @@ -540,15 +543,15 @@ export class YargsParser {
return i
}

function setArg (key: string, val: any): void {
function setArg (key: string, val: any, shouldStripQuotes: boolean = inputIsString): void {
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 value = processValue(key, val, shouldStripQuotes)
const splitKey = key.split('.')
setKey(argv, splitKey, value)

Expand Down Expand Up @@ -605,13 +608,10 @@ export class YargsParser {
}
}

function processValue (key: string, val: any) {
function processValue (key: string, val: any, shouldStripQuotes: boolean) {
// 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)
if (shouldStripQuotes) {
val = stripQuotes(val)
}

// handle parsing boolean arguments --foo=true --bar false.
Expand Down Expand Up @@ -1116,3 +1116,13 @@ function sanitizeKey (key: string): string {
if (key === '__proto__') return '___proto___'
return key
}

function stripQuotes (val: string): string {
return (
typeof val === 'string' &&
(val[0] === "'" || val[0] === '"') &&
val[val.length - 1] === val[0]
)
? val.substring(1, val.length - 1)
: val
}
18 changes: 16 additions & 2 deletions test/yargs-parser.cjs
Expand Up @@ -3569,7 +3569,7 @@ describe('yargs-parser', function () {
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.foo.should.equal('"hello world"')
args2.bar.should.equal('goodnight\'moon')
})

Expand All @@ -3578,7 +3578,7 @@ describe('yargs-parser', function () {
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.foo.should.equal("'hello world'")
args2.bar.should.equal('goodnight"moon')
})

Expand All @@ -3587,6 +3587,20 @@ describe('yargs-parser', function () {
args.foo.should.equal('-hello world')
args.bar.should.equal('--goodnight moon')
})

it('respects inner quotes (string)', function () {
const args = parser('cmd --foo ""Hello"" --bar ""World"" --baz="":)""')
args.foo.should.equal('"Hello"')
args.bar.should.equal('"World"')
args.baz.should.equal('":)"')
})

it('respects inner quotes (array)', function () {
const args = parser(['cmd', '--foo', '"Hello"', '--bar', '"World"', '--baz="":)""'])
args.foo.should.equal('"Hello"')
args.bar.should.equal('"World"')
args.baz.should.equal('":)"')
})
})

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

0 comments on commit ae11f49

Please sign in to comment.