diff --git a/README.md b/README.md index 510e6b9f..81fb3b79 100644 --- a/README.md +++ b/README.md @@ -50,28 +50,29 @@ npm install -g qrcode Usage: qrcode [options] QR Code options: - -v, --qversion QR Code symbol version (1 - 40) [number] - -e, --error Error correction level [choices: "L", "M", "Q", "H"] - -m, --mask Mask pattern (0 - 7) [number] + -v, --qversion QR Code symbol version (1 - 40) + -e, --error Error correction level (choices: "L", "M", "Q", "H") + -m, --mask Mask pattern (0 - 7) Renderer options: - -t, --type Output type [choices: "png", "svg", "utf8"] - -w, --width Image width (px) [number] - -s, --scale Scale factor [number] - -q, --qzone Quiet zone size [number] - -l, --lightcolor Light RGBA hex color - -d, --darkcolor Dark RGBA hex color - --small Output smaller QR code to terminal [boolean] + -t, --type Output type (choices: "png", "svg", "utf8") + -i, --inverse Invert colors + -w, --width Image width (px) + -s, --scale Scale factor + -q, --qzone Quiet zone size + -l, --lightcolor Light RGBA hex color + -d, --darkcolor Dark RGBA hex color + --small Output smaller QR code to terminal Options: - -o, --output Output file - -h, --help Show help [boolean] - --version Show version number [boolean] + -o, --output Output file + --version Show version number + -h, --help Show help Examples: - qrcode "some text" Draw in terminal window - qrcode -o out.png "some text" Save as png image - qrcode -d F00 -o out.png "some text" Use red as foreground color + qrcode "some text" Draw in terminal window + qrcode -o out.png "some text" Save as png image + qrcode -d F00 -o out.png "some text" Use red as foreground color ``` If not specified, output type is guessed from file extension.
Recognized extensions are `png`, `svg` and `txt`. diff --git a/bin/qrcode b/bin/qrcode index dd990b63..e49e6d56 100755 --- a/bin/qrcode +++ b/bin/qrcode @@ -1,21 +1,118 @@ #!/usr/bin/env node -var yargs = require('yargs') -var qr = require('../lib') +const { program, Option, InvalidArgumentError } = require('commander') +const QRCode = require('../lib') +const pkg = require('../package.json') -function save (file, text, options) { - qr.toFile(file, text, options, function (err, data) { +const QR_VERSION_RANGE = [1, 40] +const QR_MASK_RANGE = [0, 7] +const ALL_EC_LEVELS = ['L', 'M', 'Q', 'H'] +const OUTPUT_OPTIONS = ['png', 'svg', 'utf8'] + +/** + * Parse CLI arguments and return a CLI instance. + * @returns {import('commander').Command} + */ +function parseArgs() { + return ( + program + .name('qrcode') + .usage('[options] ') + .optionsGroup('QR Code options:') + .option( + '-v, --qversion ', + `QR Code symbol version ${printRange(QR_VERSION_RANGE)}`, + integerBetween(...QR_VERSION_RANGE), + ) + .addOption(new Option('-e, --error ', 'Error correction level').choices(ALL_EC_LEVELS)) + .option( + '-m, --mask ', + `Mask pattern ${printRange(QR_MASK_RANGE)}`, + integerBetween(...QR_MASK_RANGE), + ) + .optionsGroup('Renderer options:') + // IDEA: Maybe use a shared constant for valid renderers, defined by the renderers themselves + .addOption(new Option('-t, --type ', 'Output type').choices(OUTPUT_OPTIONS)) + .option('-i, --inverse', 'Invert colors') + .option('-w, --width ', 'Image width (px)', integerBetween(0)) + .option('-s, --scale ', 'Scale factor', integer) + .option('-q, --qzone ', 'Quiet zone size', integerBetween(0)) + .option('-l, --lightcolor ', 'Light RGBA hex color') + .option('-d, --darkcolor ', 'Dark RGBA hex color') + .option('--small', 'Output smaller QR code to terminal') + .optionsGroup('Options:') + .option('-o, --output ', 'Output file') + .helpOption('-h, --help', 'Show help') + .addHelpText( + 'after', + ` +Examples: + qrcode "some text" Draw in terminal window + qrcode -o out.png "some text" Save as png image + qrcode -d F00 -o out.png "some text" Use red as foreground color +`, + ) + .showHelpAfterError() + .version(pkg.version, '--version', 'Show version number') + // The input string is a variadic argument that will include any remaining + // input after parsing options In commander, this is indicated by the `...` + // suffix. + // The wrapping [] makes the input string arguments optional. + // This allows executing the CLI and reading from stdin, useful in scripts. + // By making the arguments optional, the help can be printed by default. + .argument('[input string...]', undefined) // undefined to hide description + .parse() + ) +} + +/** + * @param {readonly [number, number])} range + */ +function printRange([min, max]) { + return `(${min} - ${max})` +} + +/** + * @param {string} value + */ +function integer(value) { + const parsedValue = parseInt(value, 10) + if (Number.isInteger(parsedValue)) { + return parsedValue + } + + throw new InvalidArgumentError('Must be an integer') +} + +/** + * @param {number} min + * @param {number} [max] + */ +function integerBetween(min, max = Number.MAX_SAFE_INTEGER) { + return (value) => { + const n = integer(value) + + if (min <= n && n <= max) { + return n + } + + throw new InvalidArgumentError(`Must be between ${min} and ${max}`) + } +} + +function save(file, text, options) { + QRCode.toFile(file, text, options, (err, _data) => { if (err) { console.error('Error:', err.message) process.exit(1) } - console.log('saved qrcode to: ' + file + '\n') + console.log('Saved qrcode to: ' + file + '\n') }) } -function print (text, options) { +function print(text, options) { options.type = 'terminal' - qr.toString(text, options, function (err, text) { + QRCode.toString(text, options, (err, text) => { if (err) { console.error('Error:', err.message) process.exit(1) @@ -25,7 +122,7 @@ function print (text, options) { }) } -function parseOptions (args) { +function parseOptions(args) { return { version: args.qversion, errorCorrectionLevel: args.error, @@ -43,10 +140,10 @@ function parseOptions (args) { } } -function processInputs (text, opts) { +function processInput(text, opts) { + // Show help and exit when no input was passed if (!text.length) { - yargs.showHelp() - process.exit(1) + program.help() } if (opts.output) { @@ -56,104 +153,24 @@ function processInputs (text, opts) { } } -var argv = yargs - .detectLocale(false) - .usage('Usage: $0 [options] ') - .option('v', { - alias: 'qversion', - description: 'QR Code symbol version (1 - 40)', - group: 'QR Code options:', - type: 'number' - }) - .option('e', { - alias: 'error', - description: 'Error correction level', - choices: ['L', 'M', 'Q', 'H'], - group: 'QR Code options:' - }) - .option('m', { - alias: 'mask', - description: 'Mask pattern (0 - 7)', - group: 'QR Code options:', - type: 'number' - }) - .option('t', { - alias: 'type', - description: 'Output type', - choices: ['png', 'svg', 'utf8'], - implies: 'output', - group: 'Renderer options:' - }) - .option('i', { - alias: 'inverse', - type: 'boolean', - description: 'Invert colors', - group: 'Renderer options:' - }) - .option('w', { - alias: 'width', - description: 'Image width (px)', - conflicts: 'scale', - group: 'Renderer options:', - type: 'number' - }) - .option('s', { - alias: 'scale', - description: 'Scale factor', - conflicts: 'width', - group: 'Renderer options:', - type: 'number' - }) - .option('q', { - alias: 'qzone', - description: 'Quiet zone size', - group: 'Renderer options:', - type: 'number' - }) - .option('l', { - alias: 'lightcolor', - description: 'Light RGBA hex color', - group: 'Renderer options:' - }) - .option('d', { - alias: 'darkcolor', - description: 'Dark RGBA hex color', - group: 'Renderer options:' - }) - .option('small', { - type: 'boolean', - description: 'Output smaller QR code to terminal', - conflicts: 'type', - group: 'Renderer options:' - }) - .option('o', { - alias: 'output', - description: 'Output file' - }) - .help('h') - .alias('h', 'help') - .version() - .example('$0 "some text"', 'Draw in terminal window') - .example('$0 -o out.png "some text"', 'Save as png image') - .example('$0 -d F00 -o out.png "some text"', 'Use red as foreground color') - .parserConfiguration({'parse-numbers': false}) - .argv +const cli = parseArgs() +const argv = cli.opts() if (process.stdin.isTTY) { - processInputs(argv._.join(' '), argv) + processInput(cli.args.join(' '), argv) } else { - var text = '' + let text = '' process.stdin.setEncoding('utf8') - process.stdin.on('readable', function () { - var chunk = process.stdin.read() + process.stdin.on('readable', () => { + const chunk = process.stdin.read() if (chunk !== null) { text += chunk } }) - process.stdin.on('end', function () { - // this process can be run as a command outside of a tty so if there was no - // data on stdin read from argv - processInputs(text.length?text:argv._.join(' '), argv) + process.stdin.on('end', () => { + // This process can be run as a command outside of a TTY + // so if there was no data on stdin, read the CLI args instead + processInput(text.length ? text : cli.args.join(' '), argv) }) } diff --git a/package-lock.json b/package-lock.json index 99d439ba..bb84531e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1351,12 +1351,14 @@ "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "requires": { "color-convert": "^2.0.1" } @@ -1914,7 +1916,8 @@ "camelcase": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true }, "caniuse-lite": { "version": "1.0.30001282", @@ -2018,6 +2021,7 @@ "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, "requires": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", @@ -2028,6 +2032,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -2035,7 +2040,8 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true }, "color-support": { "version": "1.1.3", @@ -2070,10 +2076,9 @@ } }, "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true + "version": "14.0.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.3.tgz", + "integrity": "sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw==" }, "commondir": { "version": "1.0.1", @@ -2270,7 +2275,8 @@ "decamelize": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true }, "decompress-response": { "version": "4.2.1", @@ -2527,7 +2533,8 @@ "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "encodeurl": { "version": "1.0.2", @@ -3293,6 +3300,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, "requires": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -3426,7 +3434,8 @@ "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==" + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true }, "get-intrinsic": { "version": "1.1.1", @@ -3842,7 +3851,8 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "is-glob": { "version": "4.0.3", @@ -4257,6 +4267,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, "requires": { "p-locate": "^4.1.0" } @@ -4798,6 +4809,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, "requires": { "p-try": "^2.0.0" } @@ -4806,6 +4818,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, "requires": { "p-limit": "^2.2.0" } @@ -4822,7 +4835,8 @@ "p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true }, "package-hash": { "version": "4.0.0", @@ -4898,7 +4912,8 @@ "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true }, "path-is-absolute": { "version": "1.0.1", @@ -5520,7 +5535,8 @@ "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true }, "require-from-string": { "version": "2.0.2", @@ -5531,7 +5547,8 @@ "require-main-filename": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true }, "resolve": { "version": "1.20.0", @@ -5705,7 +5722,8 @@ "set-blocking": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true }, "setprototypeof": { "version": "1.1.1", @@ -6031,6 +6049,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -6094,6 +6113,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -7515,6 +7535,12 @@ "source-map-support": "~0.5.12" }, "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -7910,7 +7936,8 @@ "which-module": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true }, "wide-align": { "version": "1.1.5", @@ -7931,6 +7958,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, "requires": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -7970,7 +7998,8 @@ "y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", - "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true }, "yallist": { "version": "4.0.0", @@ -7988,6 +8017,7 @@ "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, "requires": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -8006,6 +8036,7 @@ "version": "18.1.3", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, "requires": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" diff --git a/package.json b/package.json index 6c9ab00d..1d1fe85b 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,9 @@ "qrcode": "./bin/qrcode" }, "dependencies": { + "commander": "^14.0.3", "dijkstrajs": "^1.0.1", - "pngjs": "^5.0.0", - "yargs": "^15.3.1" + "pngjs": "^5.0.0" }, "devDependencies": { "@babel/core": "^7.9.0",