diff --git a/package.json b/package.json index 068775f..929f52c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@author.io/arg", - "version": "1.3.14", + "version": "1.3.15", "description": "An argument parser for CLI applications.", "main": "src/index.js", "exports": { @@ -12,11 +12,9 @@ "test": "npm run test:node && npm run test:deno && npm run test:browser && npm run report:syntax && npm run report:size", "test:node": "dev test -rt node tests/*.js", "test:node:sanity": "dev test -rt node tests/01-sanity.js", - "test:node:base": "dev test -rt node tests/02-base.js", - "test:node:relationships": "dev test -rt node tests/06-relationships.js", + "test:node:regression": "dev test -rt node tests/09-regression.js", "test:browser": "dev test -rt browser tests/*.js", "test:browser:sanity": "dev test -rt browser tests/01-sanity.js", - "test:browser:base": "dev test -rt browser tests/02-base.js", "test:deno": "dev test -rt deno tests/*.js", "test:deno:sanity": "dev test -rt deno tests/01-sanity.js", "manually": "dev test -rt manual tests/*.js", diff --git a/src/index.js b/src/index.js index 38cd99f..c96ed75 100644 --- a/src/index.js +++ b/src/index.js @@ -1,7 +1,7 @@ import Flag from './flag.js' // const PARSER = /\s*(?:((?:(?:"(?:\\.|[^"])*")|(?:'[^']*')|(?:\\.)|\S)+)\s*)/gi -const PARSER = /((-+(?[^\s\"\']+))(\s+(?([\"\']((\\\"|\\\')|[^\"\'])+[\"\']|[^-][^\s]+)))?|(?[^\s]+))/gi // eslint-disable-line no-useless-escape +const PARSER = /((-+(?[^\s\"\']+))(\s+((?[\"\'](?((\\\"|\\\')|[^\"\'])+)[\"\']|[^-][^\s]+)))?|(([\"\'](?((\\\"|\\\')|[^\"\'])+)[\"\']))|(?[^\s]+))/gi // eslint-disable-line no-useless-escape const BOOLS = new Set(['true', 'false']) class Parser { @@ -176,25 +176,24 @@ class Parser { // Normalize each flag/value pairing Array.from([...input.matchAll(PARSER)]).forEach(parsedArg => { - let { flag, value, arg } = parsedArg.groups + let { flag, value, unquoted_value, quoted_arg, arg } = parsedArg.groups // If the arg attribute is present, add the // value to the arguments placeholder instead // of the flags if (arg) { args.push(arg) + } else if (quoted_arg) { + args.push(quoted_arg) } else { + value = unquoted_value || value // Flags without values are considered boolean "true" value = value !== undefined ? value : true // Remove surrounding quotes in string values // and convert true/false strings to boolean values. - if (typeof value === 'string') { - value = value.replace(/^[\"\']|[\"\']$/gi, '').replace(/\\([\"\'])/gi, '$1') // eslint-disable-line no-useless-escape - - if (BOOLS.has(value.toLowerCase())) { - value = value.toLowerCase() === 'true' - } + if (typeof value === 'string' && BOOLS.has(value.toLowerCase())) { + value = value.toLowerCase() === 'true' } flags.push({ flag, value }) diff --git a/tests/01-sanity.js b/tests/01-sanity.js index b067830..bac3dff 100644 --- a/tests/01-sanity.js +++ b/tests/01-sanity.js @@ -46,6 +46,7 @@ test('Support custom validation methods', t => { let Args = new Parser(input, cfg) t.ok(Args.violations.length === 0, `Expected no violations, recognized ${Args.violations.length}.`) + if (Args.violations.length > 0) { console.log(Args.violations) } cfg.bad = { alias: 'b', @@ -54,6 +55,7 @@ test('Support custom validation methods', t => { Args = new Parser(input, cfg) t.ok(Args.violations.length === 1, `Expected 1 violation, recognized ${Args.violations.length}.`) + if (Args.violations.length > 1) { console.log(Args.violations) } Args = new Parser('test --pass abbbbc', { pass: { @@ -62,6 +64,7 @@ test('Support custom validation methods', t => { }) t.ok(Args.violations.length === 0, `Expected no violations, recognized ${Args.violations.length}.`) + if (Args.violations.length > 0) { console.log(Args.violations) } t.end() }) diff --git a/tests/09-regression.js b/tests/09-regression.js index 22f5d70..21135e8 100644 --- a/tests/09-regression.js +++ b/tests/09-regression.js @@ -90,3 +90,18 @@ test('Multi-value flags', t => { t.expect(2, data.file.length, 'Extract multiple values') t.end() }) + +test('Multi-value quoted and unquoted arguments', t => { + const input = 'me@domain.com "John Doe" empty -name \'Jill Doe\'' + const cfg = { + name: { alias: 'n' } + } + const { data } = new Parser(input, cfg) + + t.expect('Jill Doe', data.name, 'recognized single quoted flag') + t.ok(data['me@domain.com'], 'recognized unquoted string with special characters') + t.ok(data['John Doe'], 'recognized double quoted argument with space in the value') + t.ok(data.empty, 'recognized unquoted argument') + + t.end() +})