diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..4039ff11 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,12 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +trim_trailing_whitespace = false diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 00000000..ac6ca880 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,21 @@ +{ + "overrides": [ + { + "files": "*.ts", + "parser": "@typescript-eslint/parser", + "rules": { + "no-unused-vars": "off", + "no-useless-constructor": "off", + "@typescript-eslint/no-unused-vars": "error", + "@typescript-eslint/no-useless-constructor": "error" + } + } + ], + "parserOptions": { + "ecmaVersion": 2018, + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint/eslint-plugin" + ] +} diff --git a/.gitignore b/.gitignore index a7502d1d..791cb484 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .idea +build/ .nyc_output node_modules .DS_Store diff --git a/.mocharc.json b/.mocharc.json new file mode 100644 index 00000000..ef1c3645 --- /dev/null +++ b/.mocharc.json @@ -0,0 +1,6 @@ +{ + "spec": [ + "build/test", + "test" + ] +} diff --git a/.nycrc b/.nycrc new file mode 100644 index 00000000..89f6c3a0 --- /dev/null +++ b/.nycrc @@ -0,0 +1,13 @@ +{ + "exclude": [ + "build/test/**", + "test/**" + ], + "reporter": [ + "html", + "text" + ], + "lines": 100, + "branches": "97", + "statements": "100" +} diff --git a/index.js b/index.js index 24962d66..4522fcc1 100644 --- a/index.js +++ b/index.js @@ -1,7 +1,7 @@ const camelCase = require('camelcase') const decamelize = require('decamelize') const path = require('path') -const tokenizeArgString = require('./lib/tokenize-arg-string') +const { tokenizeArgString } = require('./build/lib/tokenize-arg-string') const util = require('util') // See https://github.com/yargs/yargs-parser#supported-nodejs-versions for our diff --git a/lib/tokenize-arg-string.js b/lib/tokenize-arg-string.ts similarity index 78% rename from lib/tokenize-arg-string.js rename to lib/tokenize-arg-string.ts index 260c67c1..52827080 100644 --- a/lib/tokenize-arg-string.js +++ b/lib/tokenize-arg-string.ts @@ -1,5 +1,5 @@ // take an un-split argv string and tokenize it. -module.exports = function (argString) { +export function tokenizeArgString (argString: string | any[]): string[] { if (Array.isArray(argString)) { return argString.map(e => typeof e !== 'string' ? e + '' : e) } @@ -7,10 +7,10 @@ module.exports = function (argString) { argString = argString.trim() let i = 0 - let prevC = null - let c = null - let opening = null - const args = [] + let prevC: string | null = null + let c: string | null = null + let opening: string | null = null + const args: string[] = [] for (let ii = 0; ii < argString.length; ii++) { prevC = c diff --git a/package.json b/package.json index 2f3a8068..1b44cd1b 100644 --- a/package.json +++ b/package.json @@ -4,10 +4,14 @@ "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" + "fix": "standardx --fix && standardx --fix **/*.ts", + "pretest": "npm run compile -- -p tsconfig.test.json", + "test": "c8 --reporter=text --reporter=html mocha test/*.js", + "posttest": "npm run check", + "coverage": "c8 report --check-coverage", + "check": "standardx && standardx **/*.ts", + "compile": "rimraf build && tsc", + "prepare": "npm run compile" }, "repository": { "type": "git", @@ -27,20 +31,38 @@ "author": "Ben Coe ", "license": "ISC", "devDependencies": { + "@types/chai": "^4.2.11", + "@types/mocha": "^7.0.2", + "@types/node": "^10.0.3", + "@typescript-eslint/eslint-plugin": "^2.25.0", + "@typescript-eslint/parser": "^2.25.0", "c8": "^7.1.2", "chai": "^4.2.0", + "eslint": "^7.0.0", + "eslint-plugin-import": "^2.20.1", + "eslint-plugin-node": "^11.0.0", + "gts": "^2.0.0-alpha.4", "mocha": "^7.2.0", - "standard": "^14.3.4" + "rimraf": "^3.0.2", + "standardx": "^5.0.0", + "typescript": "^3.7.0" }, "dependencies": { "camelcase": "^6.0.0", "decamelize": "^4.0.0" }, "files": [ - "lib", - "index.js" + "index.js", + "build", + "lib/**/*.js" ], "engines": { "node": ">=10" + }, + "standardx": { + "ignore": [ + "build", + "example.js" + ] } } diff --git a/test/tokenize-arg-string.js b/test/tokenize-arg-string.js deleted file mode 100644 index 2f35895c..00000000 --- a/test/tokenize-arg-string.js +++ /dev/null @@ -1,70 +0,0 @@ -/* 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"') - }) -}) diff --git a/test/tokenize-arg-string.ts b/test/tokenize-arg-string.ts new file mode 100644 index 00000000..7621d45c --- /dev/null +++ b/test/tokenize-arg-string.ts @@ -0,0 +1,133 @@ +/* global describe, it */ +import { expect, should } from 'chai' +import { tokenizeArgString } from '../lib/tokenize-arg-string' + +should() + +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"') + }) + + it('handles boolean options', function () { + const args = tokenizeArgString('--foo -bar') + expect(args[0]).to.equal(('--foo')) + expect(args[1]).to.equal(('-bar')) + }) + + it('handles empty string', function () { + const args = tokenizeArgString('') + expect(args.length).to.equal(0) + }) + + it('handles array with unquoted string', function () { + const args = tokenizeArgString(['--foo', '99']) + args[0].should.equal('--foo') + args[1].should.equal('99') + }) + + it('handles array with quoted string with no spaces', function () { + const args = tokenizeArgString(['--foo', "'hello'"]) + args[0].should.equal('--foo') + args[1].should.equal("'hello'") + }) + + it('handles array with 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 array with 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 array with 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 array with 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 array with 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"\'') + }) + + it('handles array with boolean options', function () { + const args = tokenizeArgString(['--foo', '-bar']) + expect(args[0]).to.equal('--foo') + expect(args[1]).to.equal('-bar') + }) +}) diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..c28e1966 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "extends": "./node_modules/gts/tsconfig-google.json", + "compilerOptions": { + "outDir": "build", + "rootDir": ".", + "sourceMap": false + }, + "include": [ + "lib/**/*.ts" + ] +} diff --git a/tsconfig.test.json b/tsconfig.test.json new file mode 100644 index 00000000..75a19fe0 --- /dev/null +++ b/tsconfig.test.json @@ -0,0 +1,10 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "sourceMap": true + }, + "include": [ + "lib/**/*.ts", + "test/**/*.ts" + ] +}