first commit

This commit is contained in:
2026-09-08 20:28:54 +08:00
commit 2ada8d3d5a
37380 changed files with 4886169 additions and 0 deletions
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) Facebook, Inc. and its affiliates.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+11
View File
@@ -0,0 +1,11 @@
# Jest
🃏 Delightful JavaScript Testing
- **👩🏻‍💻 Developer Ready**: Complete and ready to set-up JavaScript testing solution. Works out of the box for any React project.
- **🏃🏽 Instant Feedback**: Failed tests run first. Fast interactive mode can switch between running all tests or only test files related to changed files.
- **📸 Snapshot Testing**: Jest can [capture snapshots](https://jestjs.io/docs/snapshot-testing.html) of React trees or other serializable values to simplify UI testing.
Read More: https://jestjs.io/
+17
View File
@@ -0,0 +1,17 @@
#!/usr/bin/env node
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const importLocal = require('import-local');
if (!importLocal(__filename)) {
if (process.env.NODE_ENV == null) {
process.env.NODE_ENV = 'test';
}
require('../build/cli').run();
}
+497
View File
@@ -0,0 +1,497 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
export declare function check(argv: Config.Argv): true;
export declare const usage = "Usage: $0 [--config=<pathToConfigFile>] [TestPathPattern]";
export declare const docs = "Documentation: https://jestjs.io/";
export declare const options: {
readonly all: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly automock: {
readonly default: undefined;
readonly description: "Automock all files by default.";
readonly type: "boolean";
};
readonly bail: {
readonly alias: "b";
readonly default: undefined;
readonly description: "Exit the test suite immediately after `n` number of failing tests.";
readonly type: "boolean";
};
readonly browser: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly cache: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly cacheDirectory: {
readonly description: string;
readonly type: "string";
};
readonly changedFilesWithAncestor: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly changedSince: {
readonly description: string;
readonly nargs: 1;
readonly type: "string";
};
readonly ci: {
readonly default: boolean;
readonly description: string;
readonly type: "boolean";
};
readonly clearCache: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly clearMocks: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly collectCoverage: {
readonly default: undefined;
readonly description: "Alias for --coverage.";
readonly type: "boolean";
};
readonly collectCoverageFrom: {
readonly description: string;
readonly type: "string";
};
readonly collectCoverageOnlyFrom: {
readonly description: "Explicit list of paths coverage will be restricted to.";
readonly string: true;
readonly type: "array";
};
readonly color: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly colors: {
readonly default: undefined;
readonly description: "Alias for `--color`.";
readonly type: "boolean";
};
readonly config: {
readonly alias: "c";
readonly description: string;
readonly type: "string";
};
readonly coverage: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly coverageDirectory: {
readonly description: "The directory where Jest should output its coverage files.";
readonly type: "string";
};
readonly coveragePathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly coverageProvider: {
readonly choices: readonly ["babel", "v8"];
readonly description: "Select between Babel and V8 to collect coverage";
};
readonly coverageReporters: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly coverageThreshold: {
readonly description: string;
readonly type: "string";
};
readonly debug: {
readonly default: undefined;
readonly description: "Print debugging info about your jest config.";
readonly type: "boolean";
};
readonly detectLeaks: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly detectOpenHandles: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly env: {
readonly description: string;
readonly type: "string";
};
readonly errorOnDeprecated: {
readonly default: false;
readonly description: "Make calling deprecated APIs throw helpful error messages.";
readonly type: "boolean";
};
readonly expand: {
readonly alias: "e";
readonly default: undefined;
readonly description: "Use this flag to show full diffs instead of a patch.";
readonly type: "boolean";
};
readonly filter: {
readonly default: undefined;
readonly description: string;
readonly type: "string";
};
readonly findRelatedTests: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly forceExit: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly globalSetup: {
readonly description: "The path to a module that runs before All Tests.";
readonly type: "string";
};
readonly globalTeardown: {
readonly description: "The path to a module that runs after All Tests.";
readonly type: "string";
};
readonly globals: {
readonly description: string;
readonly type: "string";
};
readonly haste: {
readonly description: "A JSON string with map of variables for the haste module system";
readonly type: "string";
};
readonly init: {
readonly description: "Generate a basic configuration file";
readonly type: "boolean";
};
readonly json: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly lastCommit: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly listTests: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly logHeapUsage: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly mapCoverage: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly maxConcurrency: {
readonly default: 5;
readonly description: string;
readonly type: "number";
};
readonly maxWorkers: {
readonly alias: "w";
readonly description: string;
readonly type: "string";
};
readonly moduleDirectories: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly moduleFileExtensions: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly moduleNameMapper: {
readonly description: string;
readonly type: "string";
};
readonly modulePathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly modulePaths: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly noStackTrace: {
readonly default: undefined;
readonly description: "Disables stack trace in test results output";
readonly type: "boolean";
};
readonly notify: {
readonly default: undefined;
readonly description: "Activates notifications for test results.";
readonly type: "boolean";
};
readonly notifyMode: {
readonly default: "failure-change";
readonly description: "Specifies when notifications will appear for test results.";
readonly type: "string";
};
readonly onlyChanged: {
readonly alias: "o";
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly onlyFailures: {
readonly alias: "f";
readonly default: undefined;
readonly description: "Run tests that failed in the previous execution.";
readonly type: "boolean";
};
readonly outputFile: {
readonly description: string;
readonly type: "string";
};
readonly passWithNoTests: {
readonly default: false;
readonly description: "Will not fail if no tests are found (for example while using `--testPathPattern`.)";
readonly type: "boolean";
};
readonly preset: {
readonly description: "A preset that is used as a base for Jest's configuration.";
readonly type: "string";
};
readonly prettierPath: {
readonly default: undefined;
readonly description: "The path to the \"prettier\" module used for inline snapshots.";
readonly type: "string";
};
readonly projects: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly reporters: {
readonly description: "A list of custom reporters for the test suite.";
readonly string: true;
readonly type: "array";
};
readonly resetMocks: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly resetModules: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly resolver: {
readonly description: "A JSON string which allows the use of a custom resolver.";
readonly type: "string";
};
readonly restoreMocks: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly rootDir: {
readonly description: string;
readonly type: "string";
};
readonly roots: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly runInBand: {
readonly alias: "i";
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly runTestsByPath: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly runner: {
readonly description: "Allows to use a custom runner instead of Jest's default test runner.";
readonly type: "string";
};
readonly setupFiles: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly setupFilesAfterEnv: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly showConfig: {
readonly default: undefined;
readonly description: "Print your jest config and then exits.";
readonly type: "boolean";
};
readonly silent: {
readonly default: undefined;
readonly description: "Prevent tests from printing messages through the console.";
readonly type: "boolean";
};
readonly skipFilter: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly snapshotSerializers: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly testEnvironment: {
readonly description: "Alias for --env";
readonly type: "string";
};
readonly testEnvironmentOptions: {
readonly description: string;
readonly type: "string";
};
readonly testFailureExitCode: {
readonly description: "Exit code of `jest` command if the test run failed";
readonly type: "string";
};
readonly testLocationInResults: {
readonly default: false;
readonly description: "Add `location` information to the test results";
readonly type: "boolean";
};
readonly testMatch: {
readonly description: "The glob patterns Jest uses to detect test files.";
readonly string: true;
readonly type: "array";
};
readonly testNamePattern: {
readonly alias: "t";
readonly description: "Run only tests with a name that matches the regex pattern.";
readonly type: "string";
};
readonly testPathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly testPathPattern: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly testRegex: {
readonly description: "A string or array of string regexp patterns that Jest uses to detect test files.";
readonly string: true;
readonly type: "array";
};
readonly testResultsProcessor: {
readonly description: string;
readonly type: "string";
};
readonly testRunner: {
readonly description: string;
readonly type: "string";
};
readonly testSequencer: {
readonly description: string;
readonly type: "string";
};
readonly testTimeout: {
readonly description: "This option sets the default timeouts of test cases.";
readonly type: "number";
};
readonly testURL: {
readonly description: "This option sets the URL for the jsdom environment.";
readonly type: "string";
};
readonly timers: {
readonly description: string;
readonly type: "string";
};
readonly transform: {
readonly description: string;
readonly type: "string";
};
readonly transformIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly unmockedModulePathPatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly updateSnapshot: {
readonly alias: "u";
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly useStderr: {
readonly default: undefined;
readonly description: "Divert all output to stderr.";
readonly type: "boolean";
};
readonly verbose: {
readonly default: undefined;
readonly description: "Display individual test results with the test suite hierarchy.";
readonly type: "boolean";
};
readonly version: {
readonly alias: "v";
readonly default: undefined;
readonly description: "Print the version and exit";
readonly type: "boolean";
};
readonly watch: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly watchAll: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly watchPathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly watchman: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
};
+761
View File
@@ -0,0 +1,761 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.check = check;
exports.options = exports.docs = exports.usage = void 0;
function _jestConfig() {
const data = require('jest-config');
_jestConfig = function () {
return data;
};
return data;
}
function _isCi() {
const data = _interopRequireDefault(require('is-ci'));
_isCi = function () {
return data;
};
return data;
}
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
function check(argv) {
if (argv.runInBand && argv.hasOwnProperty('maxWorkers')) {
throw new Error(
'Both --runInBand and --maxWorkers were specified, but these two ' +
'options do not make sense together. Which is it?'
);
}
for (const key of [
'onlyChanged',
'lastCommit',
'changedFilesWithAncestor',
'changedSince'
]) {
if (argv[key] && argv.watchAll) {
throw new Error(
`Both --${key} and --watchAll were specified, but these two ` +
'options do not make sense together. Try the --watch option which ' +
'reruns only tests related to changed files.'
);
}
}
if (argv.findRelatedTests && argv._.length === 0) {
throw new Error(
'The --findRelatedTests option requires file paths to be specified.\n' +
'Example usage: jest --findRelatedTests ./src/source.js ' +
'./src/index.js.'
);
}
if (argv.hasOwnProperty('maxWorkers') && argv.maxWorkers === undefined) {
throw new Error(
'The --maxWorkers (-w) option requires a number or string to be specified.\n' +
'Example usage: jest --maxWorkers 2\n' +
'Example usage: jest --maxWorkers 50%\n' +
'Or did you mean --watch?'
);
}
if (
argv.config &&
!(0, _jestConfig().isJSONString)(argv.config) &&
!argv.config.match(
new RegExp(
`\\.(${_jestConfig()
.constants.JEST_CONFIG_EXT_ORDER.map(e => e.substring(1))
.join('|')})$`,
'i'
)
)
) {
throw new Error(
`The --config option requires a JSON string literal, or a file path with one of these extensions: ${_jestConfig().constants.JEST_CONFIG_EXT_ORDER.join(
', '
)}.\nExample usage: jest --config ./jest.config.js`
);
}
return true;
}
const usage = 'Usage: $0 [--config=<pathToConfigFile>] [TestPathPattern]';
exports.usage = usage;
const docs = 'Documentation: https://jestjs.io/';
exports.docs = docs;
const options = {
all: {
default: undefined,
description:
'The opposite of `onlyChanged`. If `onlyChanged` is set by ' +
'default, running jest with `--all` will force Jest to run all tests ' +
'instead of running only tests related to changed files.',
type: 'boolean'
},
automock: {
default: undefined,
description: 'Automock all files by default.',
type: 'boolean'
},
bail: {
alias: 'b',
default: undefined,
description:
'Exit the test suite immediately after `n` number of failing tests.',
type: 'boolean'
},
browser: {
default: undefined,
description:
'Respect the "browser" field in package.json ' +
'when resolving modules. Some packages export different versions ' +
'based on whether they are operating in node.js or a browser.',
type: 'boolean'
},
cache: {
default: undefined,
description:
'Whether to use the transform cache. Disable the cache ' +
'using --no-cache.',
type: 'boolean'
},
cacheDirectory: {
description:
'The directory where Jest should store its cached ' +
' dependency information.',
type: 'string'
},
changedFilesWithAncestor: {
default: undefined,
description:
'Runs tests related to the current changes and the changes made in the ' +
'last commit. Behaves similarly to `--onlyChanged`.',
type: 'boolean'
},
changedSince: {
description:
'Runs tests related to the changes since the provided branch. If the ' +
'current branch has diverged from the given branch, then only changes ' +
'made locally will be tested. Behaves similarly to `--onlyChanged`.',
nargs: 1,
type: 'string'
},
ci: {
default: _isCi().default,
description:
'Whether to run Jest in continuous integration (CI) mode. ' +
'This option is on by default in most popular CI environments. It will ' +
'prevent snapshots from being written unless explicitly requested.',
type: 'boolean'
},
clearCache: {
default: undefined,
description:
'Clears the configured Jest cache directory and then exits. ' +
'Default directory can be found by calling jest --showConfig',
type: 'boolean'
},
clearMocks: {
default: undefined,
description:
'Automatically clear mock calls and instances between every ' +
'test. Equivalent to calling jest.clearAllMocks() between each test.',
type: 'boolean'
},
collectCoverage: {
default: undefined,
description: 'Alias for --coverage.',
type: 'boolean'
},
collectCoverageFrom: {
description:
'A glob pattern relative to <rootDir> matching the files that coverage ' +
'info needs to be collected from.',
type: 'string'
},
collectCoverageOnlyFrom: {
description: 'Explicit list of paths coverage will be restricted to.',
string: true,
type: 'array'
},
color: {
default: undefined,
description:
'Forces test results output color highlighting (even if ' +
'stdout is not a TTY). Set to false if you would like to have no colors.',
type: 'boolean'
},
colors: {
default: undefined,
description: 'Alias for `--color`.',
type: 'boolean'
},
config: {
alias: 'c',
description:
'The path to a jest config file specifying how to find ' +
'and execute tests. If no rootDir is set in the config, the directory ' +
'containing the config file is assumed to be the rootDir for the project.' +
'This can also be a JSON encoded value which Jest will use as configuration.',
type: 'string'
},
coverage: {
default: undefined,
description:
'Indicates that test coverage information should be ' +
'collected and reported in the output.',
type: 'boolean'
},
coverageDirectory: {
description: 'The directory where Jest should output its coverage files.',
type: 'string'
},
coveragePathIgnorePatterns: {
description:
'An array of regexp pattern strings that are matched ' +
'against all file paths before executing the test. If the file path' +
'matches any of the patterns, coverage information will be skipped.',
string: true,
type: 'array'
},
coverageProvider: {
choices: ['babel', 'v8'],
description: 'Select between Babel and V8 to collect coverage'
},
coverageReporters: {
description:
'A list of reporter names that Jest uses when writing ' +
'coverage reports. Any istanbul reporter can be used.',
string: true,
type: 'array'
},
coverageThreshold: {
description:
'A JSON string with which will be used to configure ' +
'minimum threshold enforcement for coverage results',
type: 'string'
},
debug: {
default: undefined,
description: 'Print debugging info about your jest config.',
type: 'boolean'
},
detectLeaks: {
default: false,
description:
'**EXPERIMENTAL**: Detect memory leaks in tests. After executing a ' +
'test, it will try to garbage collect the global object used, and fail ' +
'if it was leaked',
type: 'boolean'
},
detectOpenHandles: {
default: false,
description:
'Print out remaining open handles preventing Jest from exiting at the ' +
'end of a test run. Implies `runInBand`.',
type: 'boolean'
},
env: {
description:
'The test environment used for all tests. This can point to ' +
'any file or node module. Examples: `jsdom`, `node` or ' +
'`path/to/my-environment.js`',
type: 'string'
},
errorOnDeprecated: {
default: false,
description: 'Make calling deprecated APIs throw helpful error messages.',
type: 'boolean'
},
expand: {
alias: 'e',
default: undefined,
description: 'Use this flag to show full diffs instead of a patch.',
type: 'boolean'
},
filter: {
default: undefined,
description:
'Path to a module exporting a filtering function. This method receives ' +
'a list of tests which can be manipulated to exclude tests from ' +
'running. Especially useful when used in conjunction with a testing ' +
'infrastructure to filter known broken tests.',
type: 'string'
},
findRelatedTests: {
default: undefined,
description:
'Find related tests for a list of source files that were ' +
'passed in as arguments. Useful for pre-commit hook integration to run ' +
'the minimal amount of tests necessary.',
type: 'boolean'
},
forceExit: {
default: undefined,
description:
'Force Jest to exit after all tests have completed running. ' +
'This is useful when resources set up by test code cannot be ' +
'adequately cleaned up.',
type: 'boolean'
},
globalSetup: {
description: 'The path to a module that runs before All Tests.',
type: 'string'
},
globalTeardown: {
description: 'The path to a module that runs after All Tests.',
type: 'string'
},
globals: {
description:
'A JSON string with map of global variables that need ' +
'to be available in all test environments.',
type: 'string'
},
haste: {
description:
'A JSON string with map of variables for the haste module system',
type: 'string'
},
init: {
description: 'Generate a basic configuration file',
type: 'boolean'
},
json: {
default: undefined,
description:
'Prints the test results in JSON. This mode will send all ' +
'other test output and user messages to stderr.',
type: 'boolean'
},
lastCommit: {
default: undefined,
description:
'Run all tests affected by file changes in the last commit made. ' +
'Behaves similarly to `--onlyChanged`.',
type: 'boolean'
},
listTests: {
default: false,
description:
'Lists all tests Jest will run given the arguments and ' +
'exits. Most useful in a CI system together with `--findRelatedTests` ' +
'to determine the tests Jest will run based on specific files',
type: 'boolean'
},
logHeapUsage: {
default: undefined,
description:
'Logs the heap usage after every test. Useful to debug ' +
'memory leaks. Use together with `--runInBand` and `--expose-gc` in ' +
'node.',
type: 'boolean'
},
mapCoverage: {
default: undefined,
description:
'Maps code coverage reports against original source code ' +
'when transformers supply source maps.\n\nDEPRECATED',
type: 'boolean'
},
maxConcurrency: {
default: 5,
description:
'Specifies the maximum number of tests that are allowed to run' +
'concurrently. This only affects tests using `test.concurrent`.',
type: 'number'
},
maxWorkers: {
alias: 'w',
description:
'Specifies the maximum number of workers the worker-pool ' +
'will spawn for running tests. This defaults to the number of the ' +
'cores available on your machine. (its usually best not to override ' +
'this default)',
type: 'string'
},
moduleDirectories: {
description:
'An array of directory names to be searched recursively ' +
"up from the requiring module's location.",
string: true,
type: 'array'
},
moduleFileExtensions: {
description:
'An array of file extensions your modules use. If you ' +
'require modules without specifying a file extension, these are the ' +
'extensions Jest will look for. ',
string: true,
type: 'array'
},
moduleNameMapper: {
description:
'A JSON string with a map from regular expressions to ' +
'module names or to arrays of module names that allow to stub ' +
'out resources, like images or styles with a single module',
type: 'string'
},
modulePathIgnorePatterns: {
description:
'An array of regexp pattern strings that are matched ' +
'against all module paths before those paths are to be considered ' +
'"visible" to the module loader.',
string: true,
type: 'array'
},
modulePaths: {
description:
'An alternative API to setting the NODE_PATH env variable, ' +
'modulePaths is an array of absolute paths to additional locations to ' +
'search when resolving modules.',
string: true,
type: 'array'
},
noStackTrace: {
default: undefined,
description: 'Disables stack trace in test results output',
type: 'boolean'
},
notify: {
default: undefined,
description: 'Activates notifications for test results.',
type: 'boolean'
},
notifyMode: {
default: 'failure-change',
description: 'Specifies when notifications will appear for test results.',
type: 'string'
},
onlyChanged: {
alias: 'o',
default: undefined,
description:
'Attempts to identify which tests to run based on which ' +
"files have changed in the current repository. Only works if you're " +
'running tests in a git or hg repository at the moment.',
type: 'boolean'
},
onlyFailures: {
alias: 'f',
default: undefined,
description: 'Run tests that failed in the previous execution.',
type: 'boolean'
},
outputFile: {
description:
'Write test results to a file when the --json option is ' +
'also specified.',
type: 'string'
},
passWithNoTests: {
default: false,
description:
'Will not fail if no tests are found (for example while using `--testPathPattern`.)',
type: 'boolean'
},
preset: {
description: "A preset that is used as a base for Jest's configuration.",
type: 'string'
},
prettierPath: {
default: undefined,
description: 'The path to the "prettier" module used for inline snapshots.',
type: 'string'
},
projects: {
description:
'A list of projects that use Jest to run all tests of all ' +
'projects in a single instance of Jest.',
string: true,
type: 'array'
},
reporters: {
description: 'A list of custom reporters for the test suite.',
string: true,
type: 'array'
},
resetMocks: {
default: undefined,
description:
'Automatically reset mock state between every test. ' +
'Equivalent to calling jest.resetAllMocks() between each test.',
type: 'boolean'
},
resetModules: {
default: undefined,
description:
'If enabled, the module registry for every test file will ' +
'be reset before running each individual test.',
type: 'boolean'
},
resolver: {
description: 'A JSON string which allows the use of a custom resolver.',
type: 'string'
},
restoreMocks: {
default: undefined,
description:
'Automatically restore mock state and implementation between every test. ' +
'Equivalent to calling jest.restoreAllMocks() between each test.',
type: 'boolean'
},
rootDir: {
description:
'The root directory that Jest should scan for tests and ' +
'modules within.',
type: 'string'
},
roots: {
description:
'A list of paths to directories that Jest should use to ' +
'search for files in.',
string: true,
type: 'array'
},
runInBand: {
alias: 'i',
default: undefined,
description:
'Run all tests serially in the current process (rather than ' +
'creating a worker pool of child processes that run tests). This ' +
'is sometimes useful for debugging, but such use cases are pretty ' +
'rare.',
type: 'boolean'
},
runTestsByPath: {
default: false,
description:
'Used when provided patterns are exact file paths. This avoids ' +
'converting them into a regular expression and matching it against ' +
'every single file.',
type: 'boolean'
},
runner: {
description:
"Allows to use a custom runner instead of Jest's default test runner.",
type: 'string'
},
setupFiles: {
description:
'A list of paths to modules that run some code to configure or ' +
'set up the testing environment before each test. ',
string: true,
type: 'array'
},
setupFilesAfterEnv: {
description:
'A list of paths to modules that run some code to configure or ' +
'set up the testing framework before each test ',
string: true,
type: 'array'
},
showConfig: {
default: undefined,
description: 'Print your jest config and then exits.',
type: 'boolean'
},
silent: {
default: undefined,
description: 'Prevent tests from printing messages through the console.',
type: 'boolean'
},
skipFilter: {
default: undefined,
description:
'Disables the filter provided by --filter. Useful for CI jobs, or ' +
'local enforcement when fixing tests.',
type: 'boolean'
},
snapshotSerializers: {
description:
'A list of paths to snapshot serializer modules Jest should ' +
'use for snapshot testing.',
string: true,
type: 'array'
},
testEnvironment: {
description: 'Alias for --env',
type: 'string'
},
testEnvironmentOptions: {
description:
'Test environment options that will be passed to the testEnvironment. ' +
'The relevant options depend on the environment.',
type: 'string' // Object
},
testFailureExitCode: {
description: 'Exit code of `jest` command if the test run failed',
type: 'string' // number
},
testLocationInResults: {
default: false,
description: 'Add `location` information to the test results',
type: 'boolean'
},
testMatch: {
description: 'The glob patterns Jest uses to detect test files.',
string: true,
type: 'array'
},
testNamePattern: {
alias: 't',
description: 'Run only tests with a name that matches the regex pattern.',
type: 'string'
},
testPathIgnorePatterns: {
description:
'An array of regexp pattern strings that are matched ' +
'against all test paths before executing the test. If the test path ' +
'matches any of the patterns, it will be skipped.',
string: true,
type: 'array'
},
testPathPattern: {
description:
'A regexp pattern string that is matched against all tests ' +
'paths before executing the test.',
string: true,
type: 'array'
},
testRegex: {
description:
'A string or array of string regexp patterns that Jest uses to detect test files.',
string: true,
type: 'array'
},
testResultsProcessor: {
description:
'Allows the use of a custom results processor. ' +
'This processor must be a node module that exports ' +
'a function expecting as the first argument the result object.',
type: 'string'
},
testRunner: {
description:
'Allows to specify a custom test runner. The default is ' +
' `jasmine2`. A path to a custom test runner can be provided: ' +
'`<rootDir>/path/to/testRunner.js`.',
type: 'string'
},
testSequencer: {
description:
'Allows to specify a custom test sequencer. The default is ' +
'`@jest/test-sequencer`. A path to a custom test sequencer can be ' +
'provided: `<rootDir>/path/to/testSequencer.js`',
type: 'string'
},
testTimeout: {
description: 'This option sets the default timeouts of test cases.',
type: 'number'
},
testURL: {
description: 'This option sets the URL for the jsdom environment.',
type: 'string'
},
timers: {
description:
'Setting this value to fake allows the use of fake timers ' +
'for functions such as setTimeout.',
type: 'string'
},
transform: {
description:
'A JSON string which maps from regular expressions to paths ' +
'to transformers.',
type: 'string'
},
transformIgnorePatterns: {
description:
'An array of regexp pattern strings that are matched ' +
'against all source file paths before transformation.',
string: true,
type: 'array'
},
unmockedModulePathPatterns: {
description:
'An array of regexp pattern strings that are matched ' +
'against all modules before the module loader will automatically ' +
'return a mock for them.',
string: true,
type: 'array'
},
updateSnapshot: {
alias: 'u',
default: undefined,
description:
'Use this flag to re-record snapshots. ' +
'Can be used together with a test suite pattern or with ' +
'`--testNamePattern` to re-record snapshot for test matching ' +
'the pattern',
type: 'boolean'
},
useStderr: {
default: undefined,
description: 'Divert all output to stderr.',
type: 'boolean'
},
verbose: {
default: undefined,
description:
'Display individual test results with the test suite hierarchy.',
type: 'boolean'
},
version: {
alias: 'v',
default: undefined,
description: 'Print the version and exit',
type: 'boolean'
},
watch: {
default: undefined,
description:
'Watch files for changes and rerun tests related to ' +
'changed files. If you want to re-run all tests when a file has ' +
'changed, use the `--watchAll` option.',
type: 'boolean'
},
watchAll: {
default: undefined,
description:
'Watch files for changes and rerun all tests. If you want ' +
'to re-run only the tests related to the changed files, use the ' +
'`--watch` option.',
type: 'boolean'
},
watchPathIgnorePatterns: {
description:
'An array of regexp pattern strings that are matched ' +
'against all paths before trigger test re-run in watch mode. ' +
'If the test path matches any of the patterns, it will be skipped.',
string: true,
type: 'array'
},
watchman: {
default: undefined,
description:
'Whether to use watchman for file crawling. Disable using ' +
'--no-watchman.',
type: 'boolean'
}
};
exports.options = options;
+96
View File
@@ -0,0 +1,96 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
import yargs = require('yargs');
export declare function run(maybeArgv?: Array<string>, project?: Config.Path): Promise<void>;
export declare const buildArgv: (maybeArgv?: string[] | undefined) => yargs.Arguments<Partial<{
all: boolean;
automock: boolean;
bail: number | boolean;
browser: boolean;
cache: boolean;
cacheDirectory: string;
changedFilesWithAncestor: boolean;
changedSince: string;
ci: boolean;
clearCache: boolean;
clearMocks: boolean;
collectCoverage: boolean;
collectCoverageFrom: string;
collectCoverageOnlyFrom: string[];
color: boolean;
colors: boolean;
config: string;
coverage: boolean;
coverageDirectory: string;
coveragePathIgnorePatterns: string[];
coverageReporters: string[];
coverageThreshold: string;
debug: boolean;
env: string;
expand: boolean;
findRelatedTests: boolean;
forceExit: boolean;
globals: string;
globalSetup: string | null | undefined;
globalTeardown: string | null | undefined;
haste: string;
init: boolean;
json: boolean;
lastCommit: boolean;
logHeapUsage: boolean;
maxWorkers: string | number;
moduleDirectories: string[];
moduleFileExtensions: string[];
moduleNameMapper: string;
modulePathIgnorePatterns: string[];
modulePaths: string[];
noStackTrace: boolean;
notify: boolean;
notifyMode: string;
onlyChanged: boolean;
outputFile: string;
preset: string | null | undefined;
projects: string[];
prettierPath: string | null | undefined;
resetMocks: boolean;
resetModules: boolean;
resolver: string | null | undefined;
restoreMocks: boolean;
rootDir: string;
roots: string[];
runInBand: boolean;
setupFiles: string[];
setupFilesAfterEnv: string[];
showConfig: boolean;
silent: boolean;
snapshotSerializers: string[];
testEnvironment: string;
testFailureExitCode: string | null | undefined;
testMatch: string[];
testNamePattern: string;
testPathIgnorePatterns: string[];
testPathPattern: string[];
testRegex: string | string[];
testResultsProcessor: string;
testRunner: string;
testSequencer: string;
testURL: string;
testTimeout: number | null | undefined;
timers: string;
transform: string;
transformIgnorePatterns: string[];
unmockedModulePathPatterns: string[] | null | undefined;
updateSnapshot: boolean;
useStderr: boolean;
verbose: boolean;
version: boolean;
watch: boolean;
watchAll: boolean;
watchman: boolean;
watchPathIgnorePatterns: string[];
}>>;
+283
View File
@@ -0,0 +1,283 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.run = run;
exports.buildArgv = void 0;
function path() {
const data = _interopRequireWildcard(require('path'));
path = function () {
return data;
};
return data;
}
function _jestUtil() {
const data = require('jest-util');
_jestUtil = function () {
return data;
};
return data;
}
function _jestValidate() {
const data = require('jest-validate');
_jestValidate = function () {
return data;
};
return data;
}
function _jestConfig() {
const data = require('jest-config');
_jestConfig = function () {
return data;
};
return data;
}
function _core() {
const data = require('@jest/core');
_core = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require('chalk'));
_chalk = function () {
return data;
};
return data;
}
function _exit() {
const data = _interopRequireDefault(require('exit'));
_exit = function () {
return data;
};
return data;
}
function _yargs() {
const data = _interopRequireDefault(require('yargs'));
_yargs = function () {
return data;
};
return data;
}
function _realpathNative() {
const data = require('realpath-native');
_realpathNative = function () {
return data;
};
return data;
}
function _init() {
const data = _interopRequireDefault(require('../init'));
_init = function () {
return data;
};
return data;
}
var args = _interopRequireWildcard(require('./args'));
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache() {
if (typeof WeakMap !== 'function') return null;
var cache = new WeakMap();
_getRequireWildcardCache = function () {
return cache;
};
return cache;
}
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache();
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
async function run(maybeArgv, project) {
try {
const argv = buildArgv(maybeArgv);
if (argv.init) {
await (0, _init().default)();
return;
}
const projects = getProjectListFromCLIArgs(argv, project);
const {results, globalConfig} = await (0, _core().runCLI)(argv, projects);
readResultsAndExit(results, globalConfig);
} catch (error) {
(0, _jestUtil().clearLine)(process.stderr);
(0, _jestUtil().clearLine)(process.stdout);
if (error.stack) {
console.error(_chalk().default.red(error.stack));
} else {
console.error(_chalk().default.red(error));
}
(0, _exit().default)(1);
throw error;
}
}
const buildArgv = maybeArgv => {
const version =
(0, _core().getVersion)() +
(__dirname.includes(`packages${path().sep}jest-cli`) ? '-dev' : '');
const rawArgv = maybeArgv || process.argv.slice(2);
const argv = (0, _yargs().default)(rawArgv)
.usage(args.usage)
.version(version)
.alias('help', 'h')
.options(args.options)
.epilogue(args.docs)
.check(args.check).argv;
(0, _jestValidate().validateCLIOptions)(
argv,
{...args.options, deprecationEntries: _jestConfig().deprecationEntries}, // strip leading dashes
Array.isArray(rawArgv)
? rawArgv.map(rawArgv => rawArgv.replace(/^--?/, ''))
: Object.keys(rawArgv)
); // strip dashed args
return Object.keys(argv).reduce(
(result, key) => {
if (!key.includes('-')) {
result[key] = argv[key];
}
return result;
},
{
$0: argv.$0,
_: argv._
}
);
};
exports.buildArgv = buildArgv;
const getProjectListFromCLIArgs = (argv, project) => {
const projects = argv.projects ? argv.projects : [];
if (project) {
projects.push(project);
}
if (!projects.length && process.platform === 'win32') {
try {
projects.push((0, _realpathNative().sync)(process.cwd()));
} catch (err) {
// do nothing, just catch error
// process.binding('fs').realpath can throw, e.g. on mapped drives
}
}
if (!projects.length) {
projects.push(process.cwd());
}
return projects;
};
const readResultsAndExit = (result, globalConfig) => {
const code = !result || result.success ? 0 : globalConfig.testFailureExitCode; // Only exit if needed
process.on('exit', () => {
if (typeof code === 'number' && code !== 0) {
process.exitCode = code;
}
});
if (globalConfig.forceExit) {
if (!globalConfig.detectOpenHandles) {
console.warn(
_chalk().default.bold('Force exiting Jest: ') +
'Have you considered using `--detectOpenHandles` to detect ' +
'async operations that kept running after all tests finished?'
);
}
(0, _exit().default)(code);
} else if (!globalConfig.detectOpenHandles) {
setTimeout(() => {
console.warn(
_chalk().default.yellow.bold(
'Jest did not exit one second after the test run has completed.\n\n'
) +
_chalk().default.yellow(
'This usually means that there are asynchronous operations that ' +
"weren't stopped in your tests. Consider running Jest with " +
'`--detectOpenHandles` to troubleshoot this issue.'
)
);
}, 1000).unref();
}
};
+7
View File
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export { run } from './cli';
+13
View File
@@ -0,0 +1,13 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
Object.defineProperty(exports, 'run', {
enumerable: true,
get: function () {
return _cli.run;
}
});
var _cli = require('./cli');
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export declare class NotFoundPackageJsonError extends Error {
constructor(rootDir: string);
}
export declare class MalformedPackageJsonError extends Error {
constructor(packageJsonPath: string);
}
+35
View File
@@ -0,0 +1,35 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.MalformedPackageJsonError = exports.NotFoundPackageJsonError = void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
class NotFoundPackageJsonError extends Error {
constructor(rootDir) {
super(`Could not find a "package.json" file in ${rootDir}`);
this.name = '';
Error.captureStackTrace(this, () => {});
}
}
exports.NotFoundPackageJsonError = NotFoundPackageJsonError;
class MalformedPackageJsonError extends Error {
constructor(packageJsonPath) {
super(
`There is malformed json in ${packageJsonPath}\n` +
'Fix it, and then run "jest --init"'
);
this.name = '';
Error.captureStackTrace(this, () => {});
}
}
exports.MalformedPackageJsonError = MalformedPackageJsonError;
+8
View File
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare const generateConfigFile: (results: Record<string, unknown>, generateEsm?: boolean) => string;
export default generateConfigFile;
+87
View File
@@ -0,0 +1,87 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function _jestConfig() {
const data = require('jest-config');
_jestConfig = function () {
return data;
};
return data;
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const stringifyOption = (option, map, linePrefix = '') => {
const optionDescription = ` // ${_jestConfig().descriptions[option]}`;
const stringifiedObject = `${option}: ${JSON.stringify(
map[option],
null,
2
)}`;
return (
optionDescription +
'\n' +
stringifiedObject
.split('\n')
.map(line => ' ' + linePrefix + line)
.join('\n') +
',\n'
);
};
const generateConfigFile = (results, generateEsm = false) => {
const {coverage, clearMocks, environment} = results;
const overrides = {};
if (coverage) {
Object.assign(overrides, {
coverageDirectory: 'coverage'
});
}
if (environment === 'node') {
Object.assign(overrides, {
testEnvironment: 'node'
});
}
if (clearMocks) {
Object.assign(overrides, {
clearMocks: true
});
}
const overrideKeys = Object.keys(overrides);
const properties = [];
for (const option in _jestConfig().descriptions) {
const opt = option;
if (overrideKeys.includes(opt)) {
properties.push(stringifyOption(opt, overrides));
} else {
properties.push(stringifyOption(opt, _jestConfig().defaults, '// '));
}
}
return (
'// For a detailed explanation regarding each configuration property, visit:\n' +
'// https://jestjs.io/docs/en/configuration.html\n\n' +
(generateEsm ? 'export default {\n' : 'module.exports = {\n') +
properties.join('\n') +
'};\n'
);
};
var _default = generateConfigFile;
exports.default = _default;
+8
View File
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare const _default: (rootDir?: string) => Promise<void>;
export default _default;
+250
View File
@@ -0,0 +1,250 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
function path() {
const data = _interopRequireWildcard(require('path'));
path = function () {
return data;
};
return data;
}
function fs() {
const data = _interopRequireWildcard(require('graceful-fs'));
fs = function () {
return data;
};
return data;
}
function _chalk() {
const data = _interopRequireDefault(require('chalk'));
_chalk = function () {
return data;
};
return data;
}
function _prompts() {
const data = _interopRequireDefault(require('prompts'));
_prompts = function () {
return data;
};
return data;
}
function _realpathNative() {
const data = require('realpath-native');
_realpathNative = function () {
return data;
};
return data;
}
function _jestConfig() {
const data = require('jest-config');
_jestConfig = function () {
return data;
};
return data;
}
var _questions = _interopRequireWildcard(require('./questions'));
var _errors = require('./errors');
var _generate_config_file = _interopRequireDefault(
require('./generate_config_file')
);
var _modify_package_json = _interopRequireDefault(
require('./modify_package_json')
);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {default: obj};
}
function _getRequireWildcardCache() {
if (typeof WeakMap !== 'function') return null;
var cache = new WeakMap();
_getRequireWildcardCache = function () {
return cache;
};
return cache;
}
function _interopRequireWildcard(obj) {
if (obj && obj.__esModule) {
return obj;
}
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
return {default: obj};
}
var cache = _getRequireWildcardCache();
if (cache && cache.has(obj)) {
return cache.get(obj);
}
var newObj = {};
var hasPropertyDescriptor =
Object.defineProperty && Object.getOwnPropertyDescriptor;
for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = hasPropertyDescriptor
? Object.getOwnPropertyDescriptor(obj, key)
: null;
if (desc && (desc.get || desc.set)) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
}
newObj.default = obj;
if (cache) {
cache.set(obj, newObj);
}
return newObj;
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const {
JEST_CONFIG_BASE_NAME,
JEST_CONFIG_EXT_MJS,
JEST_CONFIG_EXT_JS,
JEST_CONFIG_EXT_ORDER,
PACKAGE_JSON
} = _jestConfig().constants;
const getConfigFilename = ext => JEST_CONFIG_BASE_NAME + ext;
var _default = async (rootDir = (0, _realpathNative().sync)(process.cwd())) => {
// prerequisite checks
const projectPackageJsonPath = path().join(rootDir, PACKAGE_JSON);
if (!fs().existsSync(projectPackageJsonPath)) {
throw new _errors.NotFoundPackageJsonError(rootDir);
}
const questions = _questions.default.slice(0);
let hasJestProperty = false;
let projectPackageJson;
try {
projectPackageJson = JSON.parse(
fs().readFileSync(projectPackageJsonPath, 'utf-8')
);
} catch (error) {
throw new _errors.MalformedPackageJsonError(projectPackageJsonPath);
}
if (projectPackageJson.jest) {
hasJestProperty = true;
}
const existingJestConfigPath = JEST_CONFIG_EXT_ORDER.find(ext =>
fs().existsSync(path().join(rootDir, getConfigFilename(ext)))
);
const jestConfigPath =
existingJestConfigPath ||
path().join(
rootDir,
getConfigFilename(
projectPackageJson.type === 'module'
? JEST_CONFIG_EXT_MJS
: JEST_CONFIG_EXT_JS
)
);
if (hasJestProperty || existingJestConfigPath) {
const result = await (0, _prompts().default)({
initial: true,
message:
'It seems that you already have a jest configuration, do you want to override it?',
name: 'continue',
type: 'confirm'
});
if (!result.continue) {
console.log();
console.log('Aborting...');
return;
}
} // Add test script installation only if needed
if (
!projectPackageJson.scripts ||
projectPackageJson.scripts.test !== 'jest'
) {
questions.unshift(_questions.testScriptQuestion);
} // Start the init process
console.log();
console.log(
_chalk().default.underline(
`The following questions will help Jest to create a suitable configuration for your project\n`
)
);
let promptAborted = false; // @ts-ignore: Return type cannot be object - faulty typings
const results = await (0, _prompts().default)(questions, {
onCancel: () => {
promptAborted = true;
}
});
if (promptAborted) {
console.log();
console.log('Aborting...');
return;
}
const shouldModifyScripts = results.scripts;
if (shouldModifyScripts || hasJestProperty) {
const modifiedPackageJson = (0, _modify_package_json.default)({
projectPackageJson,
shouldModifyScripts
});
fs().writeFileSync(projectPackageJsonPath, modifiedPackageJson);
console.log('');
console.log(
`✏️ Modified ${_chalk().default.cyan(projectPackageJsonPath)}`
);
}
const generatedConfig = (0, _generate_config_file.default)(
results,
projectPackageJson.type === 'module' ||
jestConfigPath.endsWith(JEST_CONFIG_EXT_MJS)
);
fs().writeFileSync(jestConfigPath, generatedConfig);
console.log('');
console.log(
`📝 Configuration file created at ${_chalk().default.cyan(jestConfigPath)}`
);
};
exports.default = _default;
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { ProjectPackageJson } from './types';
declare const modifyPackageJson: ({ projectPackageJson, shouldModifyScripts, }: {
projectPackageJson: ProjectPackageJson;
shouldModifyScripts: boolean;
}) => string;
export default modifyPackageJson;
+28
View File
@@ -0,0 +1,28 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.default = void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const modifyPackageJson = ({projectPackageJson, shouldModifyScripts}) => {
if (shouldModifyScripts) {
projectPackageJson.scripts
? (projectPackageJson.scripts.test = 'jest')
: (projectPackageJson.scripts = {
test: 'jest'
});
}
delete projectPackageJson.jest;
return JSON.stringify(projectPackageJson, null, 2) + '\n';
};
var _default = modifyPackageJson;
exports.default = _default;
+10
View File
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { PromptObject } from 'prompts';
declare const defaultQuestions: Array<PromptObject>;
export default defaultQuestions;
export declare const testScriptQuestion: PromptObject;
+53
View File
@@ -0,0 +1,53 @@
'use strict';
Object.defineProperty(exports, '__esModule', {
value: true
});
exports.testScriptQuestion = exports.default = void 0;
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
const defaultQuestions = [
{
choices: [
{
title: 'node',
value: 'node'
},
{
title: 'jsdom (browser-like)',
value: 'jsdom'
}
],
initial: 0,
message: 'Choose the test environment that will be used for testing',
name: 'environment',
type: 'select'
},
{
initial: false,
message: 'Do you want Jest to add coverage reports?',
name: 'coverage',
type: 'confirm'
},
{
initial: false,
message: 'Automatically clear mock calls and instances between every test?',
name: 'clearMocks',
type: 'confirm'
}
];
var _default = defaultQuestions;
exports.default = _default;
const testScriptQuestion = {
initial: true,
message:
'Would you like to use Jest when running "test" script in "package.json"?',
name: 'scripts',
type: 'confirm'
};
exports.testScriptQuestion = testScriptQuestion;
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import type { Config } from '@jest/types';
export declare type ProjectPackageJson = {
jest?: Partial<Config.InitialOptions>;
scripts?: Record<string, string>;
type?: 'commonjs' | 'module';
};
+1
View File
@@ -0,0 +1 @@
'use strict';
+497
View File
@@ -0,0 +1,497 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Config } from '@jest/types';
export declare function check(argv: Config.Argv): true;
export declare const usage = "Usage: $0 [--config=<pathToConfigFile>] [TestPathPattern]";
export declare const docs = "Documentation: https://jestjs.io/";
export declare const options: {
readonly all: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly automock: {
readonly default: undefined;
readonly description: "Automock all files by default.";
readonly type: "boolean";
};
readonly bail: {
readonly alias: "b";
readonly default: undefined;
readonly description: "Exit the test suite immediately after `n` number of failing tests.";
readonly type: "boolean";
};
readonly browser: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly cache: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly cacheDirectory: {
readonly description: string;
readonly type: "string";
};
readonly changedFilesWithAncestor: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly changedSince: {
readonly description: string;
readonly nargs: 1;
readonly type: "string";
};
readonly ci: {
readonly default: boolean;
readonly description: string;
readonly type: "boolean";
};
readonly clearCache: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly clearMocks: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly collectCoverage: {
readonly default: undefined;
readonly description: "Alias for --coverage.";
readonly type: "boolean";
};
readonly collectCoverageFrom: {
readonly description: string;
readonly type: "string";
};
readonly collectCoverageOnlyFrom: {
readonly description: "Explicit list of paths coverage will be restricted to.";
readonly string: true;
readonly type: "array";
};
readonly color: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly colors: {
readonly default: undefined;
readonly description: "Alias for `--color`.";
readonly type: "boolean";
};
readonly config: {
readonly alias: "c";
readonly description: string;
readonly type: "string";
};
readonly coverage: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly coverageDirectory: {
readonly description: "The directory where Jest should output its coverage files.";
readonly type: "string";
};
readonly coveragePathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly coverageProvider: {
readonly choices: readonly ["babel", "v8"];
readonly description: "Select between Babel and V8 to collect coverage";
};
readonly coverageReporters: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly coverageThreshold: {
readonly description: string;
readonly type: "string";
};
readonly debug: {
readonly default: undefined;
readonly description: "Print debugging info about your jest config.";
readonly type: "boolean";
};
readonly detectLeaks: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly detectOpenHandles: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly env: {
readonly description: string;
readonly type: "string";
};
readonly errorOnDeprecated: {
readonly default: false;
readonly description: "Make calling deprecated APIs throw helpful error messages.";
readonly type: "boolean";
};
readonly expand: {
readonly alias: "e";
readonly default: undefined;
readonly description: "Use this flag to show full diffs instead of a patch.";
readonly type: "boolean";
};
readonly filter: {
readonly default: undefined;
readonly description: string;
readonly type: "string";
};
readonly findRelatedTests: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly forceExit: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly globalSetup: {
readonly description: "The path to a module that runs before All Tests.";
readonly type: "string";
};
readonly globalTeardown: {
readonly description: "The path to a module that runs after All Tests.";
readonly type: "string";
};
readonly globals: {
readonly description: string;
readonly type: "string";
};
readonly haste: {
readonly description: "A JSON string with map of variables for the haste module system";
readonly type: "string";
};
readonly init: {
readonly description: "Generate a basic configuration file";
readonly type: "boolean";
};
readonly json: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly lastCommit: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly listTests: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly logHeapUsage: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly mapCoverage: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly maxConcurrency: {
readonly default: 5;
readonly description: string;
readonly type: "number";
};
readonly maxWorkers: {
readonly alias: "w";
readonly description: string;
readonly type: "string";
};
readonly moduleDirectories: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly moduleFileExtensions: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly moduleNameMapper: {
readonly description: string;
readonly type: "string";
};
readonly modulePathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly modulePaths: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly noStackTrace: {
readonly default: undefined;
readonly description: "Disables stack trace in test results output";
readonly type: "boolean";
};
readonly notify: {
readonly default: undefined;
readonly description: "Activates notifications for test results.";
readonly type: "boolean";
};
readonly notifyMode: {
readonly default: "failure-change";
readonly description: "Specifies when notifications will appear for test results.";
readonly type: "string";
};
readonly onlyChanged: {
readonly alias: "o";
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly onlyFailures: {
readonly alias: "f";
readonly default: undefined;
readonly description: "Run tests that failed in the previous execution.";
readonly type: "boolean";
};
readonly outputFile: {
readonly description: string;
readonly type: "string";
};
readonly passWithNoTests: {
readonly default: false;
readonly description: "Will not fail if no tests are found (for example while using `--testPathPattern`.)";
readonly type: "boolean";
};
readonly preset: {
readonly description: "A preset that is used as a base for Jest's configuration.";
readonly type: "string";
};
readonly prettierPath: {
readonly default: undefined;
readonly description: "The path to the \"prettier\" module used for inline snapshots.";
readonly type: "string";
};
readonly projects: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly reporters: {
readonly description: "A list of custom reporters for the test suite.";
readonly string: true;
readonly type: "array";
};
readonly resetMocks: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly resetModules: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly resolver: {
readonly description: "A JSON string which allows the use of a custom resolver.";
readonly type: "string";
};
readonly restoreMocks: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly rootDir: {
readonly description: string;
readonly type: "string";
};
readonly roots: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly runInBand: {
readonly alias: "i";
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly runTestsByPath: {
readonly default: false;
readonly description: string;
readonly type: "boolean";
};
readonly runner: {
readonly description: "Allows to use a custom runner instead of Jest's default test runner.";
readonly type: "string";
};
readonly setupFiles: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly setupFilesAfterEnv: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly showConfig: {
readonly default: undefined;
readonly description: "Print your jest config and then exits.";
readonly type: "boolean";
};
readonly silent: {
readonly default: undefined;
readonly description: "Prevent tests from printing messages through the console.";
readonly type: "boolean";
};
readonly skipFilter: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly snapshotSerializers: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly testEnvironment: {
readonly description: "Alias for --env";
readonly type: "string";
};
readonly testEnvironmentOptions: {
readonly description: string;
readonly type: "string";
};
readonly testFailureExitCode: {
readonly description: "Exit code of `jest` command if the test run failed";
readonly type: "string";
};
readonly testLocationInResults: {
readonly default: false;
readonly description: "Add `location` information to the test results";
readonly type: "boolean";
};
readonly testMatch: {
readonly description: "The glob patterns Jest uses to detect test files.";
readonly string: true;
readonly type: "array";
};
readonly testNamePattern: {
readonly alias: "t";
readonly description: "Run only tests with a name that matches the regex pattern.";
readonly type: "string";
};
readonly testPathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly testPathPattern: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly testRegex: {
readonly description: "A string or array of string regexp patterns that Jest uses to detect test files.";
readonly string: true;
readonly type: "array";
};
readonly testResultsProcessor: {
readonly description: string;
readonly type: "string";
};
readonly testRunner: {
readonly description: string;
readonly type: "string";
};
readonly testSequencer: {
readonly description: string;
readonly type: "string";
};
readonly testTimeout: {
readonly description: "This option sets the default timeouts of test cases.";
readonly type: "number";
};
readonly testURL: {
readonly description: "This option sets the URL for the jsdom environment.";
readonly type: "string";
};
readonly timers: {
readonly description: string;
readonly type: "string";
};
readonly transform: {
readonly description: string;
readonly type: "string";
};
readonly transformIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly unmockedModulePathPatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly updateSnapshot: {
readonly alias: "u";
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly useStderr: {
readonly default: undefined;
readonly description: "Divert all output to stderr.";
readonly type: "boolean";
};
readonly verbose: {
readonly default: undefined;
readonly description: "Display individual test results with the test suite hierarchy.";
readonly type: "boolean";
};
readonly version: {
readonly alias: "v";
readonly default: undefined;
readonly description: "Print the version and exit";
readonly type: "boolean";
};
readonly watch: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly watchAll: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
readonly watchPathIgnorePatterns: {
readonly description: string;
readonly string: true;
readonly type: "array";
};
readonly watchman: {
readonly default: undefined;
readonly description: string;
readonly type: "boolean";
};
};
+96
View File
@@ -0,0 +1,96 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Config } from '@jest/types';
import yargs = require('yargs');
export declare function run(maybeArgv?: Array<string>, project?: Config.Path): Promise<void>;
export declare const buildArgv: (maybeArgv?: string[] | undefined) => yargs.Arguments<Partial<{
all: boolean;
automock: boolean;
bail: number | boolean;
browser: boolean;
cache: boolean;
cacheDirectory: string;
changedFilesWithAncestor: boolean;
changedSince: string;
ci: boolean;
clearCache: boolean;
clearMocks: boolean;
collectCoverage: boolean;
collectCoverageFrom: string;
collectCoverageOnlyFrom: string[];
color: boolean;
colors: boolean;
config: string;
coverage: boolean;
coverageDirectory: string;
coveragePathIgnorePatterns: string[];
coverageReporters: string[];
coverageThreshold: string;
debug: boolean;
env: string;
expand: boolean;
findRelatedTests: boolean;
forceExit: boolean;
globals: string;
globalSetup: string | null | undefined;
globalTeardown: string | null | undefined;
haste: string;
init: boolean;
json: boolean;
lastCommit: boolean;
logHeapUsage: boolean;
maxWorkers: string | number;
moduleDirectories: string[];
moduleFileExtensions: string[];
moduleNameMapper: string;
modulePathIgnorePatterns: string[];
modulePaths: string[];
noStackTrace: boolean;
notify: boolean;
notifyMode: string;
onlyChanged: boolean;
outputFile: string;
preset: string | null | undefined;
projects: string[];
prettierPath: string | null | undefined;
resetMocks: boolean;
resetModules: boolean;
resolver: string | null | undefined;
restoreMocks: boolean;
rootDir: string;
roots: string[];
runInBand: boolean;
setupFiles: string[];
setupFilesAfterEnv: string[];
showConfig: boolean;
silent: boolean;
snapshotSerializers: string[];
testEnvironment: string;
testFailureExitCode: string | null | undefined;
testMatch: string[];
testNamePattern: string;
testPathIgnorePatterns: string[];
testPathPattern: string[];
testRegex: string | string[];
testResultsProcessor: string;
testRunner: string;
testSequencer: string;
testURL: string;
testTimeout: number | null | undefined;
timers: string;
transform: string;
transformIgnorePatterns: string[];
unmockedModulePathPatterns: string[] | null | undefined;
updateSnapshot: boolean;
useStderr: boolean;
verbose: boolean;
version: boolean;
watch: boolean;
watchAll: boolean;
watchman: boolean;
watchPathIgnorePatterns: string[];
}>>;
+7
View File
@@ -0,0 +1,7 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export { run } from './cli';
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
export declare class NotFoundPackageJsonError extends Error {
constructor(rootDir: string);
}
export declare class MalformedPackageJsonError extends Error {
constructor(packageJsonPath: string);
}
+8
View File
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare const generateConfigFile: (results: Record<string, unknown>, generateEsm?: boolean) => string;
export default generateConfigFile;
+8
View File
@@ -0,0 +1,8 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
declare const _default: (rootDir?: string) => Promise<void>;
export default _default;
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { ProjectPackageJson } from './types';
declare const modifyPackageJson: ({ projectPackageJson, shouldModifyScripts, }: {
projectPackageJson: ProjectPackageJson;
shouldModifyScripts: boolean;
}) => string;
export default modifyPackageJson;
+10
View File
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { PromptObject } from 'prompts';
declare const defaultQuestions: Array<PromptObject>;
export default defaultQuestions;
export declare const testScriptQuestion: PromptObject;
+12
View File
@@ -0,0 +1,12 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import { Config } from '@jest/types';
export declare type ProjectPackageJson = {
jest?: Partial<Config.InitialOptions>;
scripts?: Record<string, string>;
type?: 'commonjs' | 'module';
};
+345
View File
@@ -0,0 +1,345 @@
declare type CSSColor =
| 'aliceblue'
| 'antiquewhite'
| 'aqua'
| 'aquamarine'
| 'azure'
| 'beige'
| 'bisque'
| 'black'
| 'blanchedalmond'
| 'blue'
| 'blueviolet'
| 'brown'
| 'burlywood'
| 'cadetblue'
| 'chartreuse'
| 'chocolate'
| 'coral'
| 'cornflowerblue'
| 'cornsilk'
| 'crimson'
| 'cyan'
| 'darkblue'
| 'darkcyan'
| 'darkgoldenrod'
| 'darkgray'
| 'darkgreen'
| 'darkgrey'
| 'darkkhaki'
| 'darkmagenta'
| 'darkolivegreen'
| 'darkorange'
| 'darkorchid'
| 'darkred'
| 'darksalmon'
| 'darkseagreen'
| 'darkslateblue'
| 'darkslategray'
| 'darkslategrey'
| 'darkturquoise'
| 'darkviolet'
| 'deeppink'
| 'deepskyblue'
| 'dimgray'
| 'dimgrey'
| 'dodgerblue'
| 'firebrick'
| 'floralwhite'
| 'forestgreen'
| 'fuchsia'
| 'gainsboro'
| 'ghostwhite'
| 'gold'
| 'goldenrod'
| 'gray'
| 'green'
| 'greenyellow'
| 'grey'
| 'honeydew'
| 'hotpink'
| 'indianred'
| 'indigo'
| 'ivory'
| 'khaki'
| 'lavender'
| 'lavenderblush'
| 'lawngreen'
| 'lemonchiffon'
| 'lightblue'
| 'lightcoral'
| 'lightcyan'
| 'lightgoldenrodyellow'
| 'lightgray'
| 'lightgreen'
| 'lightgrey'
| 'lightpink'
| 'lightsalmon'
| 'lightseagreen'
| 'lightskyblue'
| 'lightslategray'
| 'lightslategrey'
| 'lightsteelblue'
| 'lightyellow'
| 'lime'
| 'limegreen'
| 'linen'
| 'magenta'
| 'maroon'
| 'mediumaquamarine'
| 'mediumblue'
| 'mediumorchid'
| 'mediumpurple'
| 'mediumseagreen'
| 'mediumslateblue'
| 'mediumspringgreen'
| 'mediumturquoise'
| 'mediumvioletred'
| 'midnightblue'
| 'mintcream'
| 'mistyrose'
| 'moccasin'
| 'navajowhite'
| 'navy'
| 'oldlace'
| 'olive'
| 'olivedrab'
| 'orange'
| 'orangered'
| 'orchid'
| 'palegoldenrod'
| 'palegreen'
| 'paleturquoise'
| 'palevioletred'
| 'papayawhip'
| 'peachpuff'
| 'peru'
| 'pink'
| 'plum'
| 'powderblue'
| 'purple'
| 'rebeccapurple'
| 'red'
| 'rosybrown'
| 'royalblue'
| 'saddlebrown'
| 'salmon'
| 'sandybrown'
| 'seagreen'
| 'seashell'
| 'sienna'
| 'silver'
| 'skyblue'
| 'slateblue'
| 'slategray'
| 'slategrey'
| 'snow'
| 'springgreen'
| 'steelblue'
| 'tan'
| 'teal'
| 'thistle'
| 'tomato'
| 'turquoise'
| 'violet'
| 'wheat'
| 'white'
| 'whitesmoke'
| 'yellow'
| 'yellowgreen';
declare namespace ansiStyles {
interface ColorConvert {
/**
The RGB color space.
@param red - (`0`-`255`)
@param green - (`0`-`255`)
@param blue - (`0`-`255`)
*/
rgb(red: number, green: number, blue: number): string;
/**
The RGB HEX color space.
@param hex - A hexadecimal string containing RGB data.
*/
hex(hex: string): string;
/**
@param keyword - A CSS color name.
*/
keyword(keyword: CSSColor): string;
/**
The HSL color space.
@param hue - (`0`-`360`)
@param saturation - (`0`-`100`)
@param lightness - (`0`-`100`)
*/
hsl(hue: number, saturation: number, lightness: number): string;
/**
The HSV color space.
@param hue - (`0`-`360`)
@param saturation - (`0`-`100`)
@param value - (`0`-`100`)
*/
hsv(hue: number, saturation: number, value: number): string;
/**
The HSV color space.
@param hue - (`0`-`360`)
@param whiteness - (`0`-`100`)
@param blackness - (`0`-`100`)
*/
hwb(hue: number, whiteness: number, blackness: number): string;
/**
Use a [4-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4-bit) to set text color.
*/
ansi(ansi: number): string;
/**
Use an [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
*/
ansi256(ansi: number): string;
}
interface CSPair {
/**
The ANSI terminal control sequence for starting this style.
*/
readonly open: string;
/**
The ANSI terminal control sequence for ending this style.
*/
readonly close: string;
}
interface ColorBase {
readonly ansi: ColorConvert;
readonly ansi256: ColorConvert;
readonly ansi16m: ColorConvert;
/**
The ANSI terminal control sequence for ending this color.
*/
readonly close: string;
}
interface Modifier {
/**
Resets the current color chain.
*/
readonly reset: CSPair;
/**
Make text bold.
*/
readonly bold: CSPair;
/**
Emitting only a small amount of light.
*/
readonly dim: CSPair;
/**
Make text italic. (Not widely supported)
*/
readonly italic: CSPair;
/**
Make text underline. (Not widely supported)
*/
readonly underline: CSPair;
/**
Inverse background and foreground colors.
*/
readonly inverse: CSPair;
/**
Prints the text, but makes it invisible.
*/
readonly hidden: CSPair;
/**
Puts a horizontal line through the center of the text. (Not widely supported)
*/
readonly strikethrough: CSPair;
}
interface ForegroundColor {
readonly black: CSPair;
readonly red: CSPair;
readonly green: CSPair;
readonly yellow: CSPair;
readonly blue: CSPair;
readonly cyan: CSPair;
readonly magenta: CSPair;
readonly white: CSPair;
/**
Alias for `blackBright`.
*/
readonly gray: CSPair;
/**
Alias for `blackBright`.
*/
readonly grey: CSPair;
readonly blackBright: CSPair;
readonly redBright: CSPair;
readonly greenBright: CSPair;
readonly yellowBright: CSPair;
readonly blueBright: CSPair;
readonly cyanBright: CSPair;
readonly magentaBright: CSPair;
readonly whiteBright: CSPair;
}
interface BackgroundColor {
readonly bgBlack: CSPair;
readonly bgRed: CSPair;
readonly bgGreen: CSPair;
readonly bgYellow: CSPair;
readonly bgBlue: CSPair;
readonly bgCyan: CSPair;
readonly bgMagenta: CSPair;
readonly bgWhite: CSPair;
/**
Alias for `bgBlackBright`.
*/
readonly bgGray: CSPair;
/**
Alias for `bgBlackBright`.
*/
readonly bgGrey: CSPair;
readonly bgBlackBright: CSPair;
readonly bgRedBright: CSPair;
readonly bgGreenBright: CSPair;
readonly bgYellowBright: CSPair;
readonly bgBlueBright: CSPair;
readonly bgCyanBright: CSPair;
readonly bgMagentaBright: CSPair;
readonly bgWhiteBright: CSPair;
}
}
declare const ansiStyles: {
readonly modifier: ansiStyles.Modifier;
readonly color: ansiStyles.ForegroundColor & ansiStyles.ColorBase;
readonly bgColor: ansiStyles.BackgroundColor & ansiStyles.ColorBase;
readonly codes: ReadonlyMap<number, number>;
} & ansiStyles.BackgroundColor & ansiStyles.ForegroundColor & ansiStyles.Modifier;
export = ansiStyles;
+163
View File
@@ -0,0 +1,163 @@
'use strict';
const wrapAnsi16 = (fn, offset) => (...args) => {
const code = fn(...args);
return `\u001B[${code + offset}m`;
};
const wrapAnsi256 = (fn, offset) => (...args) => {
const code = fn(...args);
return `\u001B[${38 + offset};5;${code}m`;
};
const wrapAnsi16m = (fn, offset) => (...args) => {
const rgb = fn(...args);
return `\u001B[${38 + offset};2;${rgb[0]};${rgb[1]};${rgb[2]}m`;
};
const ansi2ansi = n => n;
const rgb2rgb = (r, g, b) => [r, g, b];
const setLazyProperty = (object, property, get) => {
Object.defineProperty(object, property, {
get: () => {
const value = get();
Object.defineProperty(object, property, {
value,
enumerable: true,
configurable: true
});
return value;
},
enumerable: true,
configurable: true
});
};
/** @type {typeof import('color-convert')} */
let colorConvert;
const makeDynamicStyles = (wrap, targetSpace, identity, isBackground) => {
if (colorConvert === undefined) {
colorConvert = require('color-convert');
}
const offset = isBackground ? 10 : 0;
const styles = {};
for (const [sourceSpace, suite] of Object.entries(colorConvert)) {
const name = sourceSpace === 'ansi16' ? 'ansi' : sourceSpace;
if (sourceSpace === targetSpace) {
styles[name] = wrap(identity, offset);
} else if (typeof suite === 'object') {
styles[name] = wrap(suite[targetSpace], offset);
}
}
return styles;
};
function assembleStyles() {
const codes = new Map();
const styles = {
modifier: {
reset: [0, 0],
// 21 isn't widely supported and 22 does the same thing
bold: [1, 22],
dim: [2, 22],
italic: [3, 23],
underline: [4, 24],
inverse: [7, 27],
hidden: [8, 28],
strikethrough: [9, 29]
},
color: {
black: [30, 39],
red: [31, 39],
green: [32, 39],
yellow: [33, 39],
blue: [34, 39],
magenta: [35, 39],
cyan: [36, 39],
white: [37, 39],
// Bright color
blackBright: [90, 39],
redBright: [91, 39],
greenBright: [92, 39],
yellowBright: [93, 39],
blueBright: [94, 39],
magentaBright: [95, 39],
cyanBright: [96, 39],
whiteBright: [97, 39]
},
bgColor: {
bgBlack: [40, 49],
bgRed: [41, 49],
bgGreen: [42, 49],
bgYellow: [43, 49],
bgBlue: [44, 49],
bgMagenta: [45, 49],
bgCyan: [46, 49],
bgWhite: [47, 49],
// Bright color
bgBlackBright: [100, 49],
bgRedBright: [101, 49],
bgGreenBright: [102, 49],
bgYellowBright: [103, 49],
bgBlueBright: [104, 49],
bgMagentaBright: [105, 49],
bgCyanBright: [106, 49],
bgWhiteBright: [107, 49]
}
};
// Alias bright black as gray (and grey)
styles.color.gray = styles.color.blackBright;
styles.bgColor.bgGray = styles.bgColor.bgBlackBright;
styles.color.grey = styles.color.blackBright;
styles.bgColor.bgGrey = styles.bgColor.bgBlackBright;
for (const [groupName, group] of Object.entries(styles)) {
for (const [styleName, style] of Object.entries(group)) {
styles[styleName] = {
open: `\u001B[${style[0]}m`,
close: `\u001B[${style[1]}m`
};
group[styleName] = styles[styleName];
codes.set(style[0], style[1]);
}
Object.defineProperty(styles, groupName, {
value: group,
enumerable: false
});
}
Object.defineProperty(styles, 'codes', {
value: codes,
enumerable: false
});
styles.color.close = '\u001B[39m';
styles.bgColor.close = '\u001B[49m';
setLazyProperty(styles.color, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, false));
setLazyProperty(styles.color, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, false));
setLazyProperty(styles.color, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, false));
setLazyProperty(styles.bgColor, 'ansi', () => makeDynamicStyles(wrapAnsi16, 'ansi16', ansi2ansi, true));
setLazyProperty(styles.bgColor, 'ansi256', () => makeDynamicStyles(wrapAnsi256, 'ansi256', ansi2ansi, true));
setLazyProperty(styles.bgColor, 'ansi16m', () => makeDynamicStyles(wrapAnsi16m, 'rgb', rgb2rgb, true));
return styles;
}
// Make the export immutable
Object.defineProperty(module, 'exports', {
enumerable: true,
get: assembleStyles
});
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+56
View File
@@ -0,0 +1,56 @@
{
"name": "ansi-styles",
"version": "4.3.0",
"description": "ANSI escape codes for styling strings in the terminal",
"license": "MIT",
"repository": "chalk/ansi-styles",
"funding": "https://github.com/chalk/ansi-styles?sponsor=1",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd",
"screenshot": "svg-term --command='node screenshot' --out=screenshot.svg --padding=3 --width=55 --height=3 --at=1000 --no-cursor"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"color-convert": "^2.0.1"
},
"devDependencies": {
"@types/color-convert": "^1.9.0",
"ava": "^2.3.0",
"svg-term-cli": "^2.1.1",
"tsd": "^0.11.0",
"xo": "^0.25.3"
}
}
+152
View File
@@ -0,0 +1,152 @@
# ansi-styles [![Build Status](https://travis-ci.org/chalk/ansi-styles.svg?branch=master)](https://travis-ci.org/chalk/ansi-styles)
> [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles) for styling strings in the terminal
You probably want the higher-level [chalk](https://github.com/chalk/chalk) module for styling your strings.
<img src="screenshot.svg" width="900">
## Install
```
$ npm install ansi-styles
```
## Usage
```js
const style = require('ansi-styles');
console.log(`${style.green.open}Hello world!${style.green.close}`);
// Color conversion between 16/256/truecolor
// NOTE: If conversion goes to 16 colors or 256 colors, the original color
// may be degraded to fit that color palette. This means terminals
// that do not support 16 million colors will best-match the
// original color.
console.log(style.bgColor.ansi.hsl(120, 80, 72) + 'Hello world!' + style.bgColor.close);
console.log(style.color.ansi256.rgb(199, 20, 250) + 'Hello world!' + style.color.close);
console.log(style.color.ansi16m.hex('#abcdef') + 'Hello world!' + style.color.close);
```
## API
Each style has an `open` and `close` property.
## Styles
### Modifiers
- `reset`
- `bold`
- `dim`
- `italic` *(Not widely supported)*
- `underline`
- `inverse`
- `hidden`
- `strikethrough` *(Not widely supported)*
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Advanced usage
By default, you get a map of styles, but the styles are also available as groups. They are non-enumerable so they don't show up unless you access them explicitly. This makes it easier to expose only a subset in a higher-level module.
- `style.modifier`
- `style.color`
- `style.bgColor`
###### Example
```js
console.log(style.color.green.open);
```
Raw escape codes (i.e. without the CSI escape prefix `\u001B[` and render mode postfix `m`) are available under `style.codes`, which returns a `Map` with the open codes as keys and close codes as values.
###### Example
```js
console.log(style.codes.get(36));
//=> 39
```
## [256 / 16 million (TrueColor) support](https://gist.github.com/XVilka/8346728)
`ansi-styles` uses the [`color-convert`](https://github.com/Qix-/color-convert) package to allow for converting between various colors and ANSI escapes, with support for 256 and 16 million colors.
The following color spaces from `color-convert` are supported:
- `rgb`
- `hex`
- `keyword`
- `hsl`
- `hsv`
- `hwb`
- `ansi`
- `ansi256`
To use these, call the associated conversion function with the intended output, for example:
```js
style.color.ansi.rgb(100, 200, 15); // RGB to 16 color ansi foreground code
style.bgColor.ansi.rgb(100, 200, 15); // RGB to 16 color ansi background code
style.color.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
style.bgColor.ansi256.hsl(120, 100, 60); // HSL to 256 color ansi foreground code
style.color.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color foreground code
style.bgColor.ansi16m.hex('#C0FFEE'); // Hex (RGB) to 16 million color background code
```
## Related
- [ansi-escapes](https://github.com/sindresorhus/ansi-escapes) - ANSI escape codes for manipulating the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
## For enterprise
Available as part of the Tidelift Subscription.
The maintainers of `ansi-styles` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-ansi-styles?utm_source=npm-ansi-styles&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
+411
View File
@@ -0,0 +1,411 @@
declare const enum LevelEnum {
/**
All colors disabled.
*/
None = 0,
/**
Basic 16 colors support.
*/
Basic = 1,
/**
ANSI 256 colors support.
*/
Ansi256 = 2,
/**
Truecolor 16 million colors support.
*/
TrueColor = 3
}
/**
Basic foreground colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type ForegroundColor =
| 'black'
| 'red'
| 'green'
| 'yellow'
| 'blue'
| 'magenta'
| 'cyan'
| 'white'
| 'gray'
| 'grey'
| 'blackBright'
| 'redBright'
| 'greenBright'
| 'yellowBright'
| 'blueBright'
| 'magentaBright'
| 'cyanBright'
| 'whiteBright';
/**
Basic background colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type BackgroundColor =
| 'bgBlack'
| 'bgRed'
| 'bgGreen'
| 'bgYellow'
| 'bgBlue'
| 'bgMagenta'
| 'bgCyan'
| 'bgWhite'
| 'bgGray'
| 'bgGrey'
| 'bgBlackBright'
| 'bgRedBright'
| 'bgGreenBright'
| 'bgYellowBright'
| 'bgBlueBright'
| 'bgMagentaBright'
| 'bgCyanBright'
| 'bgWhiteBright';
/**
Basic colors.
[More colors here.](https://github.com/chalk/chalk/blob/master/readme.md#256-and-truecolor-color-support)
*/
declare type Color = ForegroundColor | BackgroundColor;
declare type Modifiers =
| 'reset'
| 'bold'
| 'dim'
| 'italic'
| 'underline'
| 'inverse'
| 'hidden'
| 'strikethrough'
| 'visible';
declare namespace chalk {
type Level = LevelEnum;
interface Options {
/**
Specify the color support for Chalk.
By default, color support is automatically detected based on the environment.
*/
level?: Level;
}
interface Instance {
/**
Return a new Chalk instance.
*/
new (options?: Options): Chalk;
}
/**
Detect whether the terminal supports color.
*/
interface ColorSupport {
/**
The color level used by Chalk.
*/
level: Level;
/**
Return whether Chalk supports basic 16 colors.
*/
hasBasic: boolean;
/**
Return whether Chalk supports ANSI 256 colors.
*/
has256: boolean;
/**
Return whether Chalk supports Truecolor 16 million colors.
*/
has16m: boolean;
}
interface ChalkFunction {
/**
Use a template string.
@remarks Template literals are unsupported for nested calls (see [issue #341](https://github.com/chalk/chalk/issues/341))
@example
```
import chalk = require('chalk');
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
```
*/
(text: TemplateStringsArray, ...placeholders: unknown[]): string;
(...text: unknown[]): string;
}
interface Chalk extends ChalkFunction {
/**
Return a new Chalk instance.
*/
Instance: Instance;
/**
The color support for Chalk.
By default, color support is automatically detected based on the environment.
*/
level: Level;
/**
Use HEX value to set text color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.hex('#DEADED');
```
*/
hex(color: string): Chalk;
/**
Use keyword color value to set text color.
@param color - Keyword value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.keyword('orange');
```
*/
keyword(color: string): Chalk;
/**
Use RGB values to set text color.
*/
rgb(red: number, green: number, blue: number): Chalk;
/**
Use HSL values to set text color.
*/
hsl(hue: number, saturation: number, lightness: number): Chalk;
/**
Use HSV values to set text color.
*/
hsv(hue: number, saturation: number, value: number): Chalk;
/**
Use HWB values to set text color.
*/
hwb(hue: number, whiteness: number, blackness: number): Chalk;
/**
Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set text color.
30 <= code && code < 38 || 90 <= code && code < 98
For example, 31 for red, 91 for redBright.
*/
ansi(code: number): Chalk;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set text color.
*/
ansi256(index: number): Chalk;
/**
Use HEX value to set background color.
@param color - Hexadecimal value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.bgHex('#DEADED');
```
*/
bgHex(color: string): Chalk;
/**
Use keyword color value to set background color.
@param color - Keyword value representing the desired color.
@example
```
import chalk = require('chalk');
chalk.bgKeyword('orange');
```
*/
bgKeyword(color: string): Chalk;
/**
Use RGB values to set background color.
*/
bgRgb(red: number, green: number, blue: number): Chalk;
/**
Use HSL values to set background color.
*/
bgHsl(hue: number, saturation: number, lightness: number): Chalk;
/**
Use HSV values to set background color.
*/
bgHsv(hue: number, saturation: number, value: number): Chalk;
/**
Use HWB values to set background color.
*/
bgHwb(hue: number, whiteness: number, blackness: number): Chalk;
/**
Use a [Select/Set Graphic Rendition](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters) (SGR) [color code number](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) to set background color.
30 <= code && code < 38 || 90 <= code && code < 98
For example, 31 for red, 91 for redBright.
Use the foreground code, not the background code (for example, not 41, nor 101).
*/
bgAnsi(code: number): Chalk;
/**
Use a [8-bit unsigned number](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) to set background color.
*/
bgAnsi256(index: number): Chalk;
/**
Modifier: Resets the current color chain.
*/
readonly reset: Chalk;
/**
Modifier: Make text bold.
*/
readonly bold: Chalk;
/**
Modifier: Emitting only a small amount of light.
*/
readonly dim: Chalk;
/**
Modifier: Make text italic. (Not widely supported)
*/
readonly italic: Chalk;
/**
Modifier: Make text underline. (Not widely supported)
*/
readonly underline: Chalk;
/**
Modifier: Inverse background and foreground colors.
*/
readonly inverse: Chalk;
/**
Modifier: Prints the text, but makes it invisible.
*/
readonly hidden: Chalk;
/**
Modifier: Puts a horizontal line through the center of the text. (Not widely supported)
*/
readonly strikethrough: Chalk;
/**
Modifier: Prints the text only when Chalk has a color support level > 0.
Can be useful for things that are purely cosmetic.
*/
readonly visible: Chalk;
readonly black: Chalk;
readonly red: Chalk;
readonly green: Chalk;
readonly yellow: Chalk;
readonly blue: Chalk;
readonly magenta: Chalk;
readonly cyan: Chalk;
readonly white: Chalk;
/*
Alias for `blackBright`.
*/
readonly gray: Chalk;
/*
Alias for `blackBright`.
*/
readonly grey: Chalk;
readonly blackBright: Chalk;
readonly redBright: Chalk;
readonly greenBright: Chalk;
readonly yellowBright: Chalk;
readonly blueBright: Chalk;
readonly magentaBright: Chalk;
readonly cyanBright: Chalk;
readonly whiteBright: Chalk;
readonly bgBlack: Chalk;
readonly bgRed: Chalk;
readonly bgGreen: Chalk;
readonly bgYellow: Chalk;
readonly bgBlue: Chalk;
readonly bgMagenta: Chalk;
readonly bgCyan: Chalk;
readonly bgWhite: Chalk;
/*
Alias for `bgBlackBright`.
*/
readonly bgGray: Chalk;
/*
Alias for `bgBlackBright`.
*/
readonly bgGrey: Chalk;
readonly bgBlackBright: Chalk;
readonly bgRedBright: Chalk;
readonly bgGreenBright: Chalk;
readonly bgYellowBright: Chalk;
readonly bgBlueBright: Chalk;
readonly bgMagentaBright: Chalk;
readonly bgCyanBright: Chalk;
readonly bgWhiteBright: Chalk;
}
}
/**
Main Chalk object that allows to chain styles together.
Call the last one as a method with a string argument.
Order doesn't matter, and later styles take precedent in case of a conflict.
This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
*/
declare const chalk: chalk.Chalk & chalk.ChalkFunction & {
supportsColor: chalk.ColorSupport | false;
Level: typeof LevelEnum;
Color: Color;
ForegroundColor: ForegroundColor;
BackgroundColor: BackgroundColor;
Modifiers: Modifiers;
stderr: chalk.Chalk & {supportsColor: chalk.ColorSupport | false};
};
export = chalk;
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+63
View File
@@ -0,0 +1,63 @@
{
"name": "chalk",
"version": "3.0.0",
"description": "Terminal string styling done right",
"license": "MIT",
"repository": "chalk/chalk",
"main": "source",
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && nyc ava && tsd",
"bench": "matcha benchmark.js"
},
"files": [
"source",
"index.d.ts"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"str",
"ansi",
"style",
"styles",
"tty",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"devDependencies": {
"ava": "^2.4.0",
"coveralls": "^3.0.7",
"execa": "^3.2.0",
"import-fresh": "^3.1.0",
"matcha": "^0.7.0",
"nyc": "^14.1.1",
"resolve-from": "^5.0.0",
"tsd": "^0.7.4",
"xo": "^0.25.3"
},
"xo": {
"rules": {
"unicorn/prefer-string-slice": "off",
"unicorn/prefer-includes": "off"
}
}
}
+304
View File
@@ -0,0 +1,304 @@
<h1 align="center">
<br>
<br>
<img width="320" src="media/logo.svg" alt="Chalk">
<br>
<br>
<br>
</h1>
> Terminal string styling done right
[![Build Status](https://travis-ci.org/chalk/chalk.svg?branch=master)](https://travis-ci.org/chalk/chalk) [![Coverage Status](https://coveralls.io/repos/github/chalk/chalk/badge.svg?branch=master)](https://coveralls.io/github/chalk/chalk?branch=master) [![npm dependents](https://badgen.net/npm/dependents/chalk)](https://www.npmjs.com/package/chalk?activeTab=dependents) [![Downloads](https://badgen.net/npm/dt/chalk)](https://www.npmjs.com/package/chalk) [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://www.youtube.com/watch?v=9auOCbH5Ns4) [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/xojs/xo) ![TypeScript-ready](https://img.shields.io/npm/types/chalk.svg)
<img src="https://cdn.jsdelivr.net/gh/chalk/ansi-styles@8261697c95bf34b6c7767e2cbe9941a851d59385/screenshot.svg" width="900">
## Highlights
- Expressive API
- Highly performant
- Ability to nest styles
- [256/Truecolor color support](#256-and-truecolor-color-support)
- Auto-detects color support
- Doesn't extend `String.prototype`
- Clean and focused
- Actively maintained
- [Used by ~46,000 packages](https://www.npmjs.com/browse/depended/chalk) as of October 1, 2019
## Install
```console
$ npm install chalk
```
## Usage
```js
const chalk = require('chalk');
console.log(chalk.blue('Hello world!'));
```
Chalk comes with an easy to use composable API where you just chain and nest the styles you want.
```js
const chalk = require('chalk');
const log = console.log;
// Combine styled and normal strings
log(chalk.blue('Hello') + ' World' + chalk.red('!'));
// Compose multiple styles using the chainable API
log(chalk.blue.bgRed.bold('Hello world!'));
// Pass in multiple arguments
log(chalk.blue('Hello', 'World!', 'Foo', 'bar', 'biz', 'baz'));
// Nest styles
log(chalk.red('Hello', chalk.underline.bgBlue('world') + '!'));
// Nest styles of the same type even (color, underline, background)
log(chalk.green(
'I am a green line ' +
chalk.blue.underline.bold('with a blue substring') +
' that becomes green again!'
));
// ES2015 template literal
log(`
CPU: ${chalk.red('90%')}
RAM: ${chalk.green('40%')}
DISK: ${chalk.yellow('70%')}
`);
// ES2015 tagged template literal
log(chalk`
CPU: {red ${cpu.totalPercent}%}
RAM: {green ${ram.used / ram.total * 100}%}
DISK: {rgb(255,131,0) ${disk.used / disk.total * 100}%}
`);
// Use RGB colors in terminal emulators that support it.
log(chalk.keyword('orange')('Yay for orange colored text!'));
log(chalk.rgb(123, 45, 67).underline('Underlined reddish color'));
log(chalk.hex('#DEADED').bold('Bold gray!'));
```
Easily define your own themes:
```js
const chalk = require('chalk');
const error = chalk.bold.red;
const warning = chalk.keyword('orange');
console.log(error('Error!'));
console.log(warning('Warning!'));
```
Take advantage of console.log [string substitution](https://nodejs.org/docs/latest/api/console.html#console_console_log_data_args):
```js
const name = 'Sindre';
console.log(chalk.green('Hello %s'), name);
//=> 'Hello Sindre'
```
## API
### chalk.`<style>[.<style>...](string, [string...])`
Example: `chalk.red.bold.underline('Hello', 'world');`
Chain [styles](#styles) and call the last one as a method with a string argument. Order doesn't matter, and later styles take precedent in case of a conflict. This simply means that `chalk.red.yellow.green` is equivalent to `chalk.green`.
Multiple arguments will be separated by space.
### chalk.level
Specifies the level of color support.
Color support is automatically detected, but you can override it by setting the `level` property. You should however only do this in your own code as it applies globally to all Chalk consumers.
If you need to change this in a reusable module, create a new instance:
```js
const ctx = new chalk.Instance({level: 0});
```
| Level | Description |
| :---: | :--- |
| `0` | All colors disabled |
| `1` | Basic color support (16 colors) |
| `2` | 256 color support |
| `3` | Truecolor support (16 million colors) |
### chalk.supportsColor
Detect whether the terminal [supports color](https://github.com/chalk/supports-color). Used internally and handled for you, but exposed for convenience.
Can be overridden by the user with the flags `--color` and `--no-color`. For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
### chalk.stderr and chalk.stderr.supportsColor
`chalk.stderr` contains a separate instance configured with color support detected for `stderr` stream instead of `stdout`. Override rules from `chalk.supportsColor` apply to this too. `chalk.stderr.supportsColor` is exposed for convenience.
## Styles
### Modifiers
- `reset` - Resets the current color chain.
- `bold` - Make text bold.
- `dim` - Emitting only a small amount of light.
- `italic` - Make text italic. *(Not widely supported)*
- `underline` - Make text underline. *(Not widely supported)*
- `inverse`- Inverse background and foreground colors.
- `hidden` - Prints the text, but makes it invisible.
- `strikethrough` - Puts a horizontal line through the center of the text. *(Not widely supported)*
- `visible`- Prints the text only when Chalk has a color level > 0. Can be useful for things that are purely cosmetic.
### Colors
- `black`
- `red`
- `green`
- `yellow`
- `blue`
- `magenta`
- `cyan`
- `white`
- `blackBright` (alias: `gray`, `grey`)
- `redBright`
- `greenBright`
- `yellowBright`
- `blueBright`
- `magentaBright`
- `cyanBright`
- `whiteBright`
### Background colors
- `bgBlack`
- `bgRed`
- `bgGreen`
- `bgYellow`
- `bgBlue`
- `bgMagenta`
- `bgCyan`
- `bgWhite`
- `bgBlackBright` (alias: `bgGray`, `bgGrey`)
- `bgRedBright`
- `bgGreenBright`
- `bgYellowBright`
- `bgBlueBright`
- `bgMagentaBright`
- `bgCyanBright`
- `bgWhiteBright`
## Tagged template literal
Chalk can be used as a [tagged template literal](http://exploringjs.com/es6/ch_template-literals.html#_tagged-template-literals).
```js
const chalk = require('chalk');
const miles = 18;
const calculateFeet = miles => miles * 5280;
console.log(chalk`
There are {bold 5280 feet} in a mile.
In {bold ${miles} miles}, there are {green.bold ${calculateFeet(miles)} feet}.
`);
```
Blocks are delimited by an opening curly brace (`{`), a style, some content, and a closing curly brace (`}`).
Template styles are chained exactly like normal Chalk styles. The following two statements are equivalent:
```js
console.log(chalk.bold.rgb(10, 100, 200)('Hello!'));
console.log(chalk`{bold.rgb(10,100,200) Hello!}`);
```
Note that function styles (`rgb()`, `hsl()`, `keyword()`, etc.) may not contain spaces between parameters.
All interpolated values (`` chalk`${foo}` ``) are converted to strings via the `.toString()` method. All curly braces (`{` and `}`) in interpolated value strings are escaped.
## 256 and Truecolor color support
Chalk supports 256 colors and [Truecolor](https://gist.github.com/XVilka/8346728) (16 million colors) on supported terminal apps.
Colors are downsampled from 16 million RGB values to an ANSI color format that is supported by the terminal emulator (or by specifying `{level: n}` as a Chalk option). For example, Chalk configured to run at level 1 (basic color support) will downsample an RGB value of #FF0000 (red) to 31 (ANSI escape for red).
Examples:
- `chalk.hex('#DEADED').underline('Hello, world!')`
- `chalk.keyword('orange')('Some orange text')`
- `chalk.rgb(15, 100, 204).inverse('Hello!')`
Background versions of these models are prefixed with `bg` and the first level of the module capitalized (e.g. `keyword` for foreground colors and `bgKeyword` for background colors).
- `chalk.bgHex('#DEADED').underline('Hello, world!')`
- `chalk.bgKeyword('orange')('Some orange text')`
- `chalk.bgRgb(15, 100, 204).inverse('Hello!')`
The following color models can be used:
- [`rgb`](https://en.wikipedia.org/wiki/RGB_color_model) - Example: `chalk.rgb(255, 136, 0).bold('Orange!')`
- [`hex`](https://en.wikipedia.org/wiki/Web_colors#Hex_triplet) - Example: `chalk.hex('#FF8800').bold('Orange!')`
- [`keyword`](https://www.w3.org/wiki/CSS/Properties/color/keywords) (CSS keywords) - Example: `chalk.keyword('orange').bold('Orange!')`
- [`hsl`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsl(32, 100, 50).bold('Orange!')`
- [`hsv`](https://en.wikipedia.org/wiki/HSL_and_HSV) - Example: `chalk.hsv(32, 100, 100).bold('Orange!')`
- [`hwb`](https://en.wikipedia.org/wiki/HWB_color_model) - Example: `chalk.hwb(32, 0, 50).bold('Orange!')`
- [`ansi`](https://en.wikipedia.org/wiki/ANSI_escape_code#3/4_bit) - Example: `chalk.ansi(31).bgAnsi(93)('red on yellowBright')`
- [`ansi256`](https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit) - Example: `chalk.bgAnsi256(194)('Honeydew, more or less')`
## Windows
If you're on Windows, do yourself a favor and use [Windows Terminal](https://github.com/microsoft/terminal) instead of `cmd.exe`.
## Origin story
[colors.js](https://github.com/Marak/colors.js) used to be the most popular string styling module, but it has serious deficiencies like extending `String.prototype` which causes all kinds of [problems](https://github.com/yeoman/yo/issues/68) and the package is unmaintained. Although there are other packages, they either do too much or not enough. Chalk is a clean and focused alternative.
## chalk for enterprise
Available as part of the Tidelift Subscription.
The maintainers of chalk and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/npm-chalk?utm_source=npm-chalk&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
## Related
- [chalk-cli](https://github.com/chalk/chalk-cli) - CLI for this module
- [ansi-styles](https://github.com/chalk/ansi-styles) - ANSI escape codes for styling strings in the terminal
- [supports-color](https://github.com/chalk/supports-color) - Detect whether a terminal supports color
- [strip-ansi](https://github.com/chalk/strip-ansi) - Strip ANSI escape codes
- [strip-ansi-stream](https://github.com/chalk/strip-ansi-stream) - Strip ANSI escape codes from a stream
- [has-ansi](https://github.com/chalk/has-ansi) - Check if a string has ANSI escape codes
- [ansi-regex](https://github.com/chalk/ansi-regex) - Regular expression for matching ANSI escape codes
- [wrap-ansi](https://github.com/chalk/wrap-ansi) - Wordwrap a string with ANSI escape codes
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
- [color-convert](https://github.com/qix-/color-convert) - Converts colors between different models
- [chalk-animation](https://github.com/bokub/chalk-animation) - Animate strings in the terminal
- [gradient-string](https://github.com/bokub/gradient-string) - Apply color gradients to strings
- [chalk-pipe](https://github.com/LitoMore/chalk-pipe) - Create chalk style schemes with simpler style strings
- [terminal-link](https://github.com/sindresorhus/terminal-link) - Create clickable links in the terminal
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
+233
View File
@@ -0,0 +1,233 @@
'use strict';
const ansiStyles = require('ansi-styles');
const {stdout: stdoutColor, stderr: stderrColor} = require('supports-color');
const {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
} = require('./util');
// `supportsColor.level` → `ansiStyles.color[name]` mapping
const levelMapping = [
'ansi',
'ansi',
'ansi256',
'ansi16m'
];
const styles = Object.create(null);
const applyOptions = (object, options = {}) => {
if (options.level > 3 || options.level < 0) {
throw new Error('The `level` option should be an integer from 0 to 3');
}
// Detect level if not set manually
const colorLevel = stdoutColor ? stdoutColor.level : 0;
object.level = options.level === undefined ? colorLevel : options.level;
};
class ChalkClass {
constructor(options) {
return chalkFactory(options);
}
}
const chalkFactory = options => {
const chalk = {};
applyOptions(chalk, options);
chalk.template = (...arguments_) => chalkTag(chalk.template, ...arguments_);
Object.setPrototypeOf(chalk, Chalk.prototype);
Object.setPrototypeOf(chalk.template, chalk);
chalk.template.constructor = () => {
throw new Error('`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.');
};
chalk.template.Instance = ChalkClass;
return chalk.template;
};
function Chalk(options) {
return chalkFactory(options);
}
for (const [styleName, style] of Object.entries(ansiStyles)) {
styles[styleName] = {
get() {
const builder = createBuilder(this, createStyler(style.open, style.close, this._styler), this._isEmpty);
Object.defineProperty(this, styleName, {value: builder});
return builder;
}
};
}
styles.visible = {
get() {
const builder = createBuilder(this, this._styler, true);
Object.defineProperty(this, 'visible', {value: builder});
return builder;
}
};
const usedModels = ['rgb', 'hex', 'keyword', 'hsl', 'hsv', 'hwb', 'ansi', 'ansi256'];
for (const model of usedModels) {
styles[model] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(ansiStyles.color[levelMapping[level]][model](...arguments_), ansiStyles.color.close, this._styler);
return createBuilder(this, styler, this._isEmpty);
};
}
};
}
for (const model of usedModels) {
const bgModel = 'bg' + model[0].toUpperCase() + model.slice(1);
styles[bgModel] = {
get() {
const {level} = this;
return function (...arguments_) {
const styler = createStyler(ansiStyles.bgColor[levelMapping[level]][model](...arguments_), ansiStyles.bgColor.close, this._styler);
return createBuilder(this, styler, this._isEmpty);
};
}
};
}
const proto = Object.defineProperties(() => {}, {
...styles,
level: {
enumerable: true,
get() {
return this._generator.level;
},
set(level) {
this._generator.level = level;
}
}
});
const createStyler = (open, close, parent) => {
let openAll;
let closeAll;
if (parent === undefined) {
openAll = open;
closeAll = close;
} else {
openAll = parent.openAll + open;
closeAll = close + parent.closeAll;
}
return {
open,
close,
openAll,
closeAll,
parent
};
};
const createBuilder = (self, _styler, _isEmpty) => {
const builder = (...arguments_) => {
// Single argument is hot path, implicit coercion is faster than anything
// eslint-disable-next-line no-implicit-coercion
return applyStyle(builder, (arguments_.length === 1) ? ('' + arguments_[0]) : arguments_.join(' '));
};
// `__proto__` is used because we must return a function, but there is
// no way to create a function with a different prototype
builder.__proto__ = proto; // eslint-disable-line no-proto
builder._generator = self;
builder._styler = _styler;
builder._isEmpty = _isEmpty;
return builder;
};
const applyStyle = (self, string) => {
if (self.level <= 0 || !string) {
return self._isEmpty ? '' : string;
}
let styler = self._styler;
if (styler === undefined) {
return string;
}
const {openAll, closeAll} = styler;
if (string.indexOf('\u001B') !== -1) {
while (styler !== undefined) {
// Replace any instances already present with a re-opening code
// otherwise only the part of the string until said closing code
// will be colored, and the rest will simply be 'plain'.
string = stringReplaceAll(string, styler.close, styler.open);
styler = styler.parent;
}
}
// We can move both next actions out of loop, because remaining actions in loop won't have
// any/visible effect on parts we add here. Close the styling before a linebreak and reopen
// after next line to fix a bleed issue on macOS: https://github.com/chalk/chalk/pull/92
const lfIndex = string.indexOf('\n');
if (lfIndex !== -1) {
string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
}
return openAll + string + closeAll;
};
let template;
const chalkTag = (chalk, ...strings) => {
const [firstString] = strings;
if (!Array.isArray(firstString)) {
// If chalk() was called by itself or with a string,
// return the string itself as a string.
return strings.join(' ');
}
const arguments_ = strings.slice(1);
const parts = [firstString.raw[0]];
for (let i = 1; i < firstString.length; i++) {
parts.push(
String(arguments_[i - 1]).replace(/[{}\\]/g, '\\$&'),
String(firstString.raw[i])
);
}
if (template === undefined) {
template = require('./templates');
}
return template(chalk, parts.join(''));
};
Object.defineProperties(Chalk.prototype, styles);
const chalk = Chalk(); // eslint-disable-line new-cap
chalk.supportsColor = stdoutColor;
chalk.stderr = Chalk({level: stderrColor ? stderrColor.level : 0}); // eslint-disable-line new-cap
chalk.stderr.supportsColor = stderrColor;
// For TypeScript
chalk.Level = {
None: 0,
Basic: 1,
Ansi256: 2,
TrueColor: 3,
0: 'None',
1: 'Basic',
2: 'Ansi256',
3: 'TrueColor'
};
module.exports = chalk;
+134
View File
@@ -0,0 +1,134 @@
'use strict';
const TEMPLATE_REGEX = /(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi;
const STYLE_REGEX = /(?:^|\.)(\w+)(?:\(([^)]*)\))?/g;
const STRING_REGEX = /^(['"])((?:\\.|(?!\1)[^\\])*)\1$/;
const ESCAPE_REGEX = /\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.)|([^\\])/gi;
const ESCAPES = new Map([
['n', '\n'],
['r', '\r'],
['t', '\t'],
['b', '\b'],
['f', '\f'],
['v', '\v'],
['0', '\0'],
['\\', '\\'],
['e', '\u001B'],
['a', '\u0007']
]);
function unescape(c) {
const u = c[0] === 'u';
const bracket = c[1] === '{';
if ((u && !bracket && c.length === 5) || (c[0] === 'x' && c.length === 3)) {
return String.fromCharCode(parseInt(c.slice(1), 16));
}
if (u && bracket) {
return String.fromCodePoint(parseInt(c.slice(2, -1), 16));
}
return ESCAPES.get(c) || c;
}
function parseArguments(name, arguments_) {
const results = [];
const chunks = arguments_.trim().split(/\s*,\s*/g);
let matches;
for (const chunk of chunks) {
const number = Number(chunk);
if (!Number.isNaN(number)) {
results.push(number);
} else if ((matches = chunk.match(STRING_REGEX))) {
results.push(matches[2].replace(ESCAPE_REGEX, (m, escape, character) => escape ? unescape(escape) : character));
} else {
throw new Error(`Invalid Chalk template style argument: ${chunk} (in style '${name}')`);
}
}
return results;
}
function parseStyle(style) {
STYLE_REGEX.lastIndex = 0;
const results = [];
let matches;
while ((matches = STYLE_REGEX.exec(style)) !== null) {
const name = matches[1];
if (matches[2]) {
const args = parseArguments(name, matches[2]);
results.push([name].concat(args));
} else {
results.push([name]);
}
}
return results;
}
function buildStyle(chalk, styles) {
const enabled = {};
for (const layer of styles) {
for (const style of layer.styles) {
enabled[style[0]] = layer.inverse ? null : style.slice(1);
}
}
let current = chalk;
for (const [styleName, styles] of Object.entries(enabled)) {
if (!Array.isArray(styles)) {
continue;
}
if (!(styleName in current)) {
throw new Error(`Unknown Chalk style: ${styleName}`);
}
current = styles.length > 0 ? current[styleName](...styles) : current[styleName];
}
return current;
}
module.exports = (chalk, temporary) => {
const styles = [];
const chunks = [];
let chunk = [];
// eslint-disable-next-line max-params
temporary.replace(TEMPLATE_REGEX, (m, escapeCharacter, inverse, style, close, character) => {
if (escapeCharacter) {
chunk.push(unescape(escapeCharacter));
} else if (style) {
const string = chunk.join('');
chunk = [];
chunks.push(styles.length === 0 ? string : buildStyle(chalk, styles)(string));
styles.push({inverse, styles: parseStyle(style)});
} else if (close) {
if (styles.length === 0) {
throw new Error('Found extraneous } in Chalk template literal');
}
chunks.push(buildStyle(chalk, styles)(chunk.join('')));
chunk = [];
styles.pop();
} else {
chunk.push(character);
}
});
chunks.push(chunk.join(''));
if (styles.length > 0) {
const errMsg = `Chalk template literal is missing ${styles.length} closing bracket${styles.length === 1 ? '' : 's'} (\`}\`)`;
throw new Error(errMsg);
}
return chunks.join('');
};
+39
View File
@@ -0,0 +1,39 @@
'use strict';
const stringReplaceAll = (string, substring, replacer) => {
let index = string.indexOf(substring);
if (index === -1) {
return string;
}
const substringLength = substring.length;
let endIndex = 0;
let returnValue = '';
do {
returnValue += string.substr(endIndex, index - endIndex) + substring + replacer;
endIndex = index + substringLength;
index = string.indexOf(substring, endIndex);
} while (index !== -1);
returnValue += string.substr(endIndex);
return returnValue;
};
const stringEncaseCRLFWithFirstIndex = (string, prefix, postfix, index) => {
let endIndex = 0;
let returnValue = '';
do {
const gotCR = string[index - 1] === '\r';
returnValue += string.substr(endIndex, (gotCR ? index - 1 : index) - endIndex) + prefix + (gotCR ? '\r\n' : '\n') + postfix;
endIndex = index + 1;
index = string.indexOf('\n', endIndex);
} while (index !== -1);
returnValue += string.substr(endIndex);
return returnValue;
};
module.exports = {
stringReplaceAll,
stringEncaseCRLFWithFirstIndex
};
+76
View File
@@ -0,0 +1,76 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [6.0.0](https://www.github.com/yargs/cliui/compare/v5.0.0...v6.0.0) (2019-11-10)
### ⚠ BREAKING CHANGES
* update deps, drop Node 6
### Code Refactoring
* update deps, drop Node 6 ([62056df](https://www.github.com/yargs/cliui/commit/62056df))
## [5.0.0](https://github.com/yargs/cliui/compare/v4.1.0...v5.0.0) (2019-04-10)
### Bug Fixes
* Update wrap-ansi to fix compatibility with latest versions of chalk. ([#60](https://github.com/yargs/cliui/issues/60)) ([7bf79ae](https://github.com/yargs/cliui/commit/7bf79ae))
### BREAKING CHANGES
* Drop support for node < 6.
<a name="4.1.0"></a>
## [4.1.0](https://github.com/yargs/cliui/compare/v4.0.0...v4.1.0) (2018-04-23)
### Features
* add resetOutput method ([#57](https://github.com/yargs/cliui/issues/57)) ([7246902](https://github.com/yargs/cliui/commit/7246902))
<a name="4.0.0"></a>
## [4.0.0](https://github.com/yargs/cliui/compare/v3.2.0...v4.0.0) (2017-12-18)
### Bug Fixes
* downgrades strip-ansi to version 3.0.1 ([#54](https://github.com/yargs/cliui/issues/54)) ([5764c46](https://github.com/yargs/cliui/commit/5764c46))
* set env variable FORCE_COLOR. ([#56](https://github.com/yargs/cliui/issues/56)) ([7350e36](https://github.com/yargs/cliui/commit/7350e36))
### Chores
* drop support for node < 4 ([#53](https://github.com/yargs/cliui/issues/53)) ([b105376](https://github.com/yargs/cliui/commit/b105376))
### Features
* add fallback for window width ([#45](https://github.com/yargs/cliui/issues/45)) ([d064922](https://github.com/yargs/cliui/commit/d064922))
### BREAKING CHANGES
* officially drop support for Node < 4
<a name="3.2.0"></a>
## [3.2.0](https://github.com/yargs/cliui/compare/v3.1.2...v3.2.0) (2016-04-11)
### Bug Fixes
* reduces tarball size ([acc6c33](https://github.com/yargs/cliui/commit/acc6c33))
### Features
* adds standard-version for release management ([ff84e32](https://github.com/yargs/cliui/commit/ff84e32))
+14
View File
@@ -0,0 +1,14 @@
Copyright (c) 2015, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+115
View File
@@ -0,0 +1,115 @@
# cliui
[![Build Status](https://travis-ci.org/yargs/cliui.svg)](https://travis-ci.org/yargs/cliui)
[![Coverage Status](https://coveralls.io/repos/yargs/cliui/badge.svg?branch=)](https://coveralls.io/r/yargs/cliui?branch=)
[![NPM version](https://img.shields.io/npm/v/cliui.svg)](https://www.npmjs.com/package/cliui)
[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
easily create complex multi-column command-line-interfaces.
## Example
```js
var ui = require('cliui')()
ui.div('Usage: $0 [command] [options]')
ui.div({
text: 'Options:',
padding: [2, 0, 2, 0]
})
ui.div(
{
text: "-f, --file",
width: 20,
padding: [0, 4, 0, 4]
},
{
text: "the file to load." +
chalk.green("(if this description is long it wraps).")
,
width: 20
},
{
text: chalk.red("[required]"),
align: 'right'
}
)
console.log(ui.toString())
```
<img width="500" src="screenshot.png">
## Layout DSL
cliui exposes a simple layout DSL:
If you create a single `ui.div`, passing a string rather than an
object:
* `\n`: characters will be interpreted as new rows.
* `\t`: characters will be interpreted as new columns.
* `\s`: characters will be interpreted as padding.
**as an example...**
```js
var ui = require('./')({
width: 60
})
ui.div(
'Usage: node ./bin/foo.js\n' +
' <regex>\t provide a regex\n' +
' <glob>\t provide a glob\t [required]'
)
console.log(ui.toString())
```
**will output:**
```shell
Usage: node ./bin/foo.js
<regex> provide a regex
<glob> provide a glob [required]
```
## Methods
```js
cliui = require('cliui')
```
### cliui({width: integer})
Specify the maximum width of the UI being generated.
If no width is provided, cliui will try to get the current window's width and use it, and if that doesn't work, width will be set to `80`.
### cliui({wrap: boolean})
Enable or disable the wrapping of text in a column.
### cliui.div(column, column, column)
Create a row with any number of columns, a column
can either be a string, or an object with the following
options:
* **text:** some text to place in the column.
* **width:** the width of a column.
* **align:** alignment, `right` or `center`.
* **padding:** `[top, right, bottom, left]`.
* **border:** should a border be placed around the div?
### cliui.span(column, column, column)
Similar to `div`, except the next row will be appended without
a new line being created.
### cliui.resetOutput()
Resets the UI elements of the current cliui instance, maintaining the values
set for `width` and `wrap`.
+354
View File
@@ -0,0 +1,354 @@
'use strict'
const stringWidth = require('string-width')
const stripAnsi = require('strip-ansi')
const wrap = require('wrap-ansi')
const align = {
right: alignRight,
center: alignCenter
}
const top = 0
const right = 1
const bottom = 2
const left = 3
class UI {
constructor (opts) {
this.width = opts.width
this.wrap = opts.wrap
this.rows = []
}
span (...args) {
const cols = this.div(...args)
cols.span = true
}
resetOutput () {
this.rows = []
}
div (...args) {
if (args.length === 0) {
this.div('')
}
if (this.wrap && this._shouldApplyLayoutDSL(...args)) {
return this._applyLayoutDSL(args[0])
}
const cols = args.map(arg => {
if (typeof arg === 'string') {
return this._colFromString(arg)
}
return arg
})
this.rows.push(cols)
return cols
}
_shouldApplyLayoutDSL (...args) {
return args.length === 1 && typeof args[0] === 'string' &&
/[\t\n]/.test(args[0])
}
_applyLayoutDSL (str) {
const rows = str.split('\n').map(row => row.split('\t'))
let leftColumnWidth = 0
// simple heuristic for layout, make sure the
// second column lines up along the left-hand.
// don't allow the first column to take up more
// than 50% of the screen.
rows.forEach(columns => {
if (columns.length > 1 && stringWidth(columns[0]) > leftColumnWidth) {
leftColumnWidth = Math.min(
Math.floor(this.width * 0.5),
stringWidth(columns[0])
)
}
})
// generate a table:
// replacing ' ' with padding calculations.
// using the algorithmically generated width.
rows.forEach(columns => {
this.div(...columns.map((r, i) => {
return {
text: r.trim(),
padding: this._measurePadding(r),
width: (i === 0 && columns.length > 1) ? leftColumnWidth : undefined
}
}))
})
return this.rows[this.rows.length - 1]
}
_colFromString (text) {
return {
text,
padding: this._measurePadding(text)
}
}
_measurePadding (str) {
// measure padding without ansi escape codes
const noAnsi = stripAnsi(str)
return [0, noAnsi.match(/\s*$/)[0].length, 0, noAnsi.match(/^\s*/)[0].length]
}
toString () {
const lines = []
this.rows.forEach(row => {
this.rowToString(row, lines)
})
// don't display any lines with the
// hidden flag set.
return lines
.filter(line => !line.hidden)
.map(line => line.text)
.join('\n')
}
rowToString (row, lines) {
this._rasterize(row).forEach((rrow, r) => {
let str = ''
rrow.forEach((col, c) => {
const { width } = row[c] // the width with padding.
const wrapWidth = this._negatePadding(row[c]) // the width without padding.
let ts = col // temporary string used during alignment/padding.
if (wrapWidth > stringWidth(col)) {
ts += ' '.repeat(wrapWidth - stringWidth(col))
}
// align the string within its column.
if (row[c].align && row[c].align !== 'left' && this.wrap) {
ts = align[row[c].align](ts, wrapWidth)
if (stringWidth(ts) < wrapWidth) {
ts += ' '.repeat(width - stringWidth(ts) - 1)
}
}
// apply border and padding to string.
const padding = row[c].padding || [0, 0, 0, 0]
if (padding[left]) {
str += ' '.repeat(padding[left])
}
str += addBorder(row[c], ts, '| ')
str += ts
str += addBorder(row[c], ts, ' |')
if (padding[right]) {
str += ' '.repeat(padding[right])
}
// if prior row is span, try to render the
// current row on the prior line.
if (r === 0 && lines.length > 0) {
str = this._renderInline(str, lines[lines.length - 1])
}
})
// remove trailing whitespace.
lines.push({
text: str.replace(/ +$/, ''),
span: row.span
})
})
return lines
}
// if the full 'source' can render in
// the target line, do so.
_renderInline (source, previousLine) {
const leadingWhitespace = source.match(/^ */)[0].length
const target = previousLine.text
const targetTextWidth = stringWidth(target.trimRight())
if (!previousLine.span) {
return source
}
// if we're not applying wrapping logic,
// just always append to the span.
if (!this.wrap) {
previousLine.hidden = true
return target + source
}
if (leadingWhitespace < targetTextWidth) {
return source
}
previousLine.hidden = true
return target.trimRight() + ' '.repeat(leadingWhitespace - targetTextWidth) + source.trimLeft()
}
_rasterize (row) {
const rrows = []
const widths = this._columnWidths(row)
let wrapped
// word wrap all columns, and create
// a data-structure that is easy to rasterize.
row.forEach((col, c) => {
// leave room for left and right padding.
col.width = widths[c]
if (this.wrap) {
wrapped = wrap(col.text, this._negatePadding(col), { hard: true }).split('\n')
} else {
wrapped = col.text.split('\n')
}
if (col.border) {
wrapped.unshift('.' + '-'.repeat(this._negatePadding(col) + 2) + '.')
wrapped.push("'" + '-'.repeat(this._negatePadding(col) + 2) + "'")
}
// add top and bottom padding.
if (col.padding) {
wrapped.unshift(...new Array(col.padding[top] || 0).fill(''))
wrapped.push(...new Array(col.padding[bottom] || 0).fill(''))
}
wrapped.forEach((str, r) => {
if (!rrows[r]) {
rrows.push([])
}
const rrow = rrows[r]
for (let i = 0; i < c; i++) {
if (rrow[i] === undefined) {
rrow.push('')
}
}
rrow.push(str)
})
})
return rrows
}
_negatePadding (col) {
let wrapWidth = col.width
if (col.padding) {
wrapWidth -= (col.padding[left] || 0) + (col.padding[right] || 0)
}
if (col.border) {
wrapWidth -= 4
}
return wrapWidth
}
_columnWidths (row) {
if (!this.wrap) {
return row.map(col => {
return col.width || stringWidth(col.text)
})
}
let unset = row.length
let remainingWidth = this.width
// column widths can be set in config.
const widths = row.map(col => {
if (col.width) {
unset--
remainingWidth -= col.width
return col.width
}
return undefined
})
// any unset widths should be calculated.
const unsetWidth = unset ? Math.floor(remainingWidth / unset) : 0
return widths.map((w, i) => {
if (w === undefined) {
return Math.max(unsetWidth, _minWidth(row[i]))
}
return w
})
}
}
function addBorder (col, ts, style) {
if (col.border) {
if (/[.']-+[.']/.test(ts)) {
return ''
}
if (ts.trim().length !== 0) {
return style
}
return ' '
}
return ''
}
// calculates the minimum width of
// a column, based on padding preferences.
function _minWidth (col) {
const padding = col.padding || []
const minWidth = 1 + (padding[left] || 0) + (padding[right] || 0)
if (col.border) {
return minWidth + 4
}
return minWidth
}
function getWindowWidth () {
/* istanbul ignore next: depends on terminal */
if (typeof process === 'object' && process.stdout && process.stdout.columns) {
return process.stdout.columns
}
}
function alignRight (str, width) {
str = str.trim()
const strWidth = stringWidth(str)
if (strWidth < width) {
return ' '.repeat(width - strWidth) + str
}
return str
}
function alignCenter (str, width) {
str = str.trim()
const strWidth = stringWidth(str)
/* istanbul ignore next */
if (strWidth >= width) {
return str
}
return ' '.repeat((width - strWidth) >> 1) + str
}
module.exports = function (opts = {}) {
return new UI({
width: opts.width || getWindowWidth() || /* istanbul ignore next */ 80,
wrap: opts.wrap !== false
})
}
+65
View File
@@ -0,0 +1,65 @@
{
"name": "cliui",
"version": "6.0.0",
"description": "easily create complex multi-column command-line-interfaces",
"main": "index.js",
"scripts": {
"pretest": "standard",
"test": "nyc mocha",
"coverage": "nyc --reporter=text-lcov mocha | coveralls"
},
"repository": {
"type": "git",
"url": "http://github.com/yargs/cliui.git"
},
"config": {
"blanket": {
"pattern": [
"index.js"
],
"data-cover-never": [
"node_modules",
"test"
],
"output-reporter": "spec"
}
},
"standard": {
"ignore": [
"**/example/**"
],
"globals": [
"it"
]
},
"keywords": [
"cli",
"command-line",
"layout",
"design",
"console",
"wrap",
"table"
],
"author": "Ben Coe <ben@npmjs.com>",
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
},
"devDependencies": {
"chai": "^4.2.0",
"chalk": "^3.0.0",
"coveralls": "^3.0.3",
"mocha": "^6.2.2",
"nyc": "^14.1.1",
"standard": "^12.0.1"
},
"files": [
"index.js"
],
"engine": {
"node": ">=8"
}
}
+54
View File
@@ -0,0 +1,54 @@
# 1.0.0 - 2016-01-07
- Removed: unused speed test
- Added: Automatic routing between previously unsupported conversions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `xxx2xxx()` and `xxx2xxxRaw()` functions
([#27](https://github.com/Qix-/color-convert/pull/27))
- Removed: `convert()` class
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: all functions to lookup dictionary
([#27](https://github.com/Qix-/color-convert/pull/27))
- Changed: `ansi` to `ansi256`
([#27](https://github.com/Qix-/color-convert/pull/27))
- Fixed: argument grouping for functions requiring only one argument
([#27](https://github.com/Qix-/color-convert/pull/27))
# 0.6.0 - 2015-07-23
- Added: methods to handle
[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors) 16/256 colors:
- rgb2ansi16
- rgb2ansi
- hsl2ansi16
- hsl2ansi
- hsv2ansi16
- hsv2ansi
- hwb2ansi16
- hwb2ansi
- cmyk2ansi16
- cmyk2ansi
- keyword2ansi16
- keyword2ansi
- ansi162rgb
- ansi162hsl
- ansi162hsv
- ansi162hwb
- ansi162cmyk
- ansi162keyword
- ansi2rgb
- ansi2hsl
- ansi2hsv
- ansi2hwb
- ansi2cmyk
- ansi2keyword
([#18](https://github.com/harthur/color-convert/pull/18))
# 0.5.3 - 2015-06-02
- Fixed: hsl2hsv does not return `NaN` anymore when using `[0,0,0]`
([#15](https://github.com/harthur/color-convert/issues/15))
---
Check out commit logs for older releases
+21
View File
@@ -0,0 +1,21 @@
Copyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+68
View File
@@ -0,0 +1,68 @@
# color-convert
[![Build Status](https://travis-ci.org/Qix-/color-convert.svg?branch=master)](https://travis-ci.org/Qix-/color-convert)
Color-convert is a color conversion library for JavaScript and node.
It converts all ways between `rgb`, `hsl`, `hsv`, `hwb`, `cmyk`, `ansi`, `ansi16`, `hex` strings, and CSS `keyword`s (will round to closest):
```js
var convert = require('color-convert');
convert.rgb.hsl(140, 200, 100); // [96, 48, 59]
convert.keyword.rgb('blue'); // [0, 0, 255]
var rgbChannels = convert.rgb.channels; // 3
var cmykChannels = convert.cmyk.channels; // 4
var ansiChannels = convert.ansi16.channels; // 1
```
# Install
```console
$ npm install color-convert
```
# API
Simply get the property of the _from_ and _to_ conversion that you're looking for.
All functions have a rounded and unrounded variant. By default, return values are rounded. To get the unrounded (raw) results, simply tack on `.raw` to the function.
All 'from' functions have a hidden property called `.channels` that indicates the number of channels the function expects (not including alpha).
```js
var convert = require('color-convert');
// Hex to LAB
convert.hex.lab('DEADBF'); // [ 76, 21, -2 ]
convert.hex.lab.raw('DEADBF'); // [ 75.56213190997677, 20.653827952644754, -2.290532499330533 ]
// RGB to CMYK
convert.rgb.cmyk(167, 255, 4); // [ 35, 0, 98, 0 ]
convert.rgb.cmyk.raw(167, 255, 4); // [ 34.509803921568626, 0, 98.43137254901961, 0 ]
```
### Arrays
All functions that accept multiple arguments also support passing an array.
Note that this does **not** apply to functions that convert from a color that only requires one value (e.g. `keyword`, `ansi256`, `hex`, etc.)
```js
var convert = require('color-convert');
convert.rgb.hex(123, 45, 67); // '7B2D43'
convert.rgb.hex([123, 45, 67]); // '7B2D43'
```
## Routing
Conversions that don't have an _explicitly_ defined conversion (in [conversions.js](conversions.js)), but can be converted by means of sub-conversions (e.g. XYZ -> **RGB** -> CMYK), are automatically routed together. This allows just about any color model supported by `color-convert` to be converted to any other model, so long as a sub-conversion path exists. This is also true for conversions requiring more than one step in between (e.g. LCH -> **LAB** -> **XYZ** -> **RGB** -> Hex).
Keep in mind that extensive conversions _may_ result in a loss of precision, and exist only to be complete. For a list of "direct" (single-step) conversions, see [conversions.js](conversions.js).
# Contribute
If there is a new model you would like to support, or want to add a direct conversion between two existing models, please send us a pull request.
# License
Copyright &copy; 2011-2016, Heather Arthur and Josh Junon. Licensed under the [MIT License](LICENSE).
+839
View File
@@ -0,0 +1,839 @@
/* MIT license */
/* eslint-disable no-mixed-operators */
const cssKeywords = require('color-name');
// NOTE: conversions should only return primitive values (i.e. arrays, or
// values that give correct `typeof` results).
// do not use box values types (i.e. Number(), String(), etc.)
const reverseKeywords = {};
for (const key of Object.keys(cssKeywords)) {
reverseKeywords[cssKeywords[key]] = key;
}
const convert = {
rgb: {channels: 3, labels: 'rgb'},
hsl: {channels: 3, labels: 'hsl'},
hsv: {channels: 3, labels: 'hsv'},
hwb: {channels: 3, labels: 'hwb'},
cmyk: {channels: 4, labels: 'cmyk'},
xyz: {channels: 3, labels: 'xyz'},
lab: {channels: 3, labels: 'lab'},
lch: {channels: 3, labels: 'lch'},
hex: {channels: 1, labels: ['hex']},
keyword: {channels: 1, labels: ['keyword']},
ansi16: {channels: 1, labels: ['ansi16']},
ansi256: {channels: 1, labels: ['ansi256']},
hcg: {channels: 3, labels: ['h', 'c', 'g']},
apple: {channels: 3, labels: ['r16', 'g16', 'b16']},
gray: {channels: 1, labels: ['gray']}
};
module.exports = convert;
// Hide .channels and .labels properties
for (const model of Object.keys(convert)) {
if (!('channels' in convert[model])) {
throw new Error('missing channels property: ' + model);
}
if (!('labels' in convert[model])) {
throw new Error('missing channel labels property: ' + model);
}
if (convert[model].labels.length !== convert[model].channels) {
throw new Error('channel and label counts mismatch: ' + model);
}
const {channels, labels} = convert[model];
delete convert[model].channels;
delete convert[model].labels;
Object.defineProperty(convert[model], 'channels', {value: channels});
Object.defineProperty(convert[model], 'labels', {value: labels});
}
convert.rgb.hsl = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const min = Math.min(r, g, b);
const max = Math.max(r, g, b);
const delta = max - min;
let h;
let s;
if (max === min) {
h = 0;
} else if (r === max) {
h = (g - b) / delta;
} else if (g === max) {
h = 2 + (b - r) / delta;
} else if (b === max) {
h = 4 + (r - g) / delta;
}
h = Math.min(h * 60, 360);
if (h < 0) {
h += 360;
}
const l = (min + max) / 2;
if (max === min) {
s = 0;
} else if (l <= 0.5) {
s = delta / (max + min);
} else {
s = delta / (2 - max - min);
}
return [h, s * 100, l * 100];
};
convert.rgb.hsv = function (rgb) {
let rdif;
let gdif;
let bdif;
let h;
let s;
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const v = Math.max(r, g, b);
const diff = v - Math.min(r, g, b);
const diffc = function (c) {
return (v - c) / 6 / diff + 1 / 2;
};
if (diff === 0) {
h = 0;
s = 0;
} else {
s = diff / v;
rdif = diffc(r);
gdif = diffc(g);
bdif = diffc(b);
if (r === v) {
h = bdif - gdif;
} else if (g === v) {
h = (1 / 3) + rdif - bdif;
} else if (b === v) {
h = (2 / 3) + gdif - rdif;
}
if (h < 0) {
h += 1;
} else if (h > 1) {
h -= 1;
}
}
return [
h * 360,
s * 100,
v * 100
];
};
convert.rgb.hwb = function (rgb) {
const r = rgb[0];
const g = rgb[1];
let b = rgb[2];
const h = convert.rgb.hsl(rgb)[0];
const w = 1 / 255 * Math.min(r, Math.min(g, b));
b = 1 - 1 / 255 * Math.max(r, Math.max(g, b));
return [h, w * 100, b * 100];
};
convert.rgb.cmyk = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const k = Math.min(1 - r, 1 - g, 1 - b);
const c = (1 - r - k) / (1 - k) || 0;
const m = (1 - g - k) / (1 - k) || 0;
const y = (1 - b - k) / (1 - k) || 0;
return [c * 100, m * 100, y * 100, k * 100];
};
function comparativeDistance(x, y) {
/*
See https://en.m.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance
*/
return (
((x[0] - y[0]) ** 2) +
((x[1] - y[1]) ** 2) +
((x[2] - y[2]) ** 2)
);
}
convert.rgb.keyword = function (rgb) {
const reversed = reverseKeywords[rgb];
if (reversed) {
return reversed;
}
let currentClosestDistance = Infinity;
let currentClosestKeyword;
for (const keyword of Object.keys(cssKeywords)) {
const value = cssKeywords[keyword];
// Compute comparative distance
const distance = comparativeDistance(rgb, value);
// Check if its less, if so set as closest
if (distance < currentClosestDistance) {
currentClosestDistance = distance;
currentClosestKeyword = keyword;
}
}
return currentClosestKeyword;
};
convert.keyword.rgb = function (keyword) {
return cssKeywords[keyword];
};
convert.rgb.xyz = function (rgb) {
let r = rgb[0] / 255;
let g = rgb[1] / 255;
let b = rgb[2] / 255;
// Assume sRGB
r = r > 0.04045 ? (((r + 0.055) / 1.055) ** 2.4) : (r / 12.92);
g = g > 0.04045 ? (((g + 0.055) / 1.055) ** 2.4) : (g / 12.92);
b = b > 0.04045 ? (((b + 0.055) / 1.055) ** 2.4) : (b / 12.92);
const x = (r * 0.4124) + (g * 0.3576) + (b * 0.1805);
const y = (r * 0.2126) + (g * 0.7152) + (b * 0.0722);
const z = (r * 0.0193) + (g * 0.1192) + (b * 0.9505);
return [x * 100, y * 100, z * 100];
};
convert.rgb.lab = function (rgb) {
const xyz = convert.rgb.xyz(rgb);
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
const l = (116 * y) - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.hsl.rgb = function (hsl) {
const h = hsl[0] / 360;
const s = hsl[1] / 100;
const l = hsl[2] / 100;
let t2;
let t3;
let val;
if (s === 0) {
val = l * 255;
return [val, val, val];
}
if (l < 0.5) {
t2 = l * (1 + s);
} else {
t2 = l + s - l * s;
}
const t1 = 2 * l - t2;
const rgb = [0, 0, 0];
for (let i = 0; i < 3; i++) {
t3 = h + 1 / 3 * -(i - 1);
if (t3 < 0) {
t3++;
}
if (t3 > 1) {
t3--;
}
if (6 * t3 < 1) {
val = t1 + (t2 - t1) * 6 * t3;
} else if (2 * t3 < 1) {
val = t2;
} else if (3 * t3 < 2) {
val = t1 + (t2 - t1) * (2 / 3 - t3) * 6;
} else {
val = t1;
}
rgb[i] = val * 255;
}
return rgb;
};
convert.hsl.hsv = function (hsl) {
const h = hsl[0];
let s = hsl[1] / 100;
let l = hsl[2] / 100;
let smin = s;
const lmin = Math.max(l, 0.01);
l *= 2;
s *= (l <= 1) ? l : 2 - l;
smin *= lmin <= 1 ? lmin : 2 - lmin;
const v = (l + s) / 2;
const sv = l === 0 ? (2 * smin) / (lmin + smin) : (2 * s) / (l + s);
return [h, sv * 100, v * 100];
};
convert.hsv.rgb = function (hsv) {
const h = hsv[0] / 60;
const s = hsv[1] / 100;
let v = hsv[2] / 100;
const hi = Math.floor(h) % 6;
const f = h - Math.floor(h);
const p = 255 * v * (1 - s);
const q = 255 * v * (1 - (s * f));
const t = 255 * v * (1 - (s * (1 - f)));
v *= 255;
switch (hi) {
case 0:
return [v, t, p];
case 1:
return [q, v, p];
case 2:
return [p, v, t];
case 3:
return [p, q, v];
case 4:
return [t, p, v];
case 5:
return [v, p, q];
}
};
convert.hsv.hsl = function (hsv) {
const h = hsv[0];
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const vmin = Math.max(v, 0.01);
let sl;
let l;
l = (2 - s) * v;
const lmin = (2 - s) * vmin;
sl = s * vmin;
sl /= (lmin <= 1) ? lmin : 2 - lmin;
sl = sl || 0;
l /= 2;
return [h, sl * 100, l * 100];
};
// http://dev.w3.org/csswg/css-color/#hwb-to-rgb
convert.hwb.rgb = function (hwb) {
const h = hwb[0] / 360;
let wh = hwb[1] / 100;
let bl = hwb[2] / 100;
const ratio = wh + bl;
let f;
// Wh + bl cant be > 1
if (ratio > 1) {
wh /= ratio;
bl /= ratio;
}
const i = Math.floor(6 * h);
const v = 1 - bl;
f = 6 * h - i;
if ((i & 0x01) !== 0) {
f = 1 - f;
}
const n = wh + f * (v - wh); // Linear interpolation
let r;
let g;
let b;
/* eslint-disable max-statements-per-line,no-multi-spaces */
switch (i) {
default:
case 6:
case 0: r = v; g = n; b = wh; break;
case 1: r = n; g = v; b = wh; break;
case 2: r = wh; g = v; b = n; break;
case 3: r = wh; g = n; b = v; break;
case 4: r = n; g = wh; b = v; break;
case 5: r = v; g = wh; b = n; break;
}
/* eslint-enable max-statements-per-line,no-multi-spaces */
return [r * 255, g * 255, b * 255];
};
convert.cmyk.rgb = function (cmyk) {
const c = cmyk[0] / 100;
const m = cmyk[1] / 100;
const y = cmyk[2] / 100;
const k = cmyk[3] / 100;
const r = 1 - Math.min(1, c * (1 - k) + k);
const g = 1 - Math.min(1, m * (1 - k) + k);
const b = 1 - Math.min(1, y * (1 - k) + k);
return [r * 255, g * 255, b * 255];
};
convert.xyz.rgb = function (xyz) {
const x = xyz[0] / 100;
const y = xyz[1] / 100;
const z = xyz[2] / 100;
let r;
let g;
let b;
r = (x * 3.2406) + (y * -1.5372) + (z * -0.4986);
g = (x * -0.9689) + (y * 1.8758) + (z * 0.0415);
b = (x * 0.0557) + (y * -0.2040) + (z * 1.0570);
// Assume sRGB
r = r > 0.0031308
? ((1.055 * (r ** (1.0 / 2.4))) - 0.055)
: r * 12.92;
g = g > 0.0031308
? ((1.055 * (g ** (1.0 / 2.4))) - 0.055)
: g * 12.92;
b = b > 0.0031308
? ((1.055 * (b ** (1.0 / 2.4))) - 0.055)
: b * 12.92;
r = Math.min(Math.max(0, r), 1);
g = Math.min(Math.max(0, g), 1);
b = Math.min(Math.max(0, b), 1);
return [r * 255, g * 255, b * 255];
};
convert.xyz.lab = function (xyz) {
let x = xyz[0];
let y = xyz[1];
let z = xyz[2];
x /= 95.047;
y /= 100;
z /= 108.883;
x = x > 0.008856 ? (x ** (1 / 3)) : (7.787 * x) + (16 / 116);
y = y > 0.008856 ? (y ** (1 / 3)) : (7.787 * y) + (16 / 116);
z = z > 0.008856 ? (z ** (1 / 3)) : (7.787 * z) + (16 / 116);
const l = (116 * y) - 16;
const a = 500 * (x - y);
const b = 200 * (y - z);
return [l, a, b];
};
convert.lab.xyz = function (lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let x;
let y;
let z;
y = (l + 16) / 116;
x = a / 500 + y;
z = y - b / 200;
const y2 = y ** 3;
const x2 = x ** 3;
const z2 = z ** 3;
y = y2 > 0.008856 ? y2 : (y - 16 / 116) / 7.787;
x = x2 > 0.008856 ? x2 : (x - 16 / 116) / 7.787;
z = z2 > 0.008856 ? z2 : (z - 16 / 116) / 7.787;
x *= 95.047;
y *= 100;
z *= 108.883;
return [x, y, z];
};
convert.lab.lch = function (lab) {
const l = lab[0];
const a = lab[1];
const b = lab[2];
let h;
const hr = Math.atan2(b, a);
h = hr * 360 / 2 / Math.PI;
if (h < 0) {
h += 360;
}
const c = Math.sqrt(a * a + b * b);
return [l, c, h];
};
convert.lch.lab = function (lch) {
const l = lch[0];
const c = lch[1];
const h = lch[2];
const hr = h / 360 * 2 * Math.PI;
const a = c * Math.cos(hr);
const b = c * Math.sin(hr);
return [l, a, b];
};
convert.rgb.ansi16 = function (args, saturation = null) {
const [r, g, b] = args;
let value = saturation === null ? convert.rgb.hsv(args)[2] : saturation; // Hsv -> ansi16 optimization
value = Math.round(value / 50);
if (value === 0) {
return 30;
}
let ansi = 30
+ ((Math.round(b / 255) << 2)
| (Math.round(g / 255) << 1)
| Math.round(r / 255));
if (value === 2) {
ansi += 60;
}
return ansi;
};
convert.hsv.ansi16 = function (args) {
// Optimization here; we already know the value and don't need to get
// it converted for us.
return convert.rgb.ansi16(convert.hsv.rgb(args), args[2]);
};
convert.rgb.ansi256 = function (args) {
const r = args[0];
const g = args[1];
const b = args[2];
// We use the extended greyscale palette here, with the exception of
// black and white. normal palette only has 4 greyscale shades.
if (r === g && g === b) {
if (r < 8) {
return 16;
}
if (r > 248) {
return 231;
}
return Math.round(((r - 8) / 247) * 24) + 232;
}
const ansi = 16
+ (36 * Math.round(r / 255 * 5))
+ (6 * Math.round(g / 255 * 5))
+ Math.round(b / 255 * 5);
return ansi;
};
convert.ansi16.rgb = function (args) {
let color = args % 10;
// Handle greyscale
if (color === 0 || color === 7) {
if (args > 50) {
color += 3.5;
}
color = color / 10.5 * 255;
return [color, color, color];
}
const mult = (~~(args > 50) + 1) * 0.5;
const r = ((color & 1) * mult) * 255;
const g = (((color >> 1) & 1) * mult) * 255;
const b = (((color >> 2) & 1) * mult) * 255;
return [r, g, b];
};
convert.ansi256.rgb = function (args) {
// Handle greyscale
if (args >= 232) {
const c = (args - 232) * 10 + 8;
return [c, c, c];
}
args -= 16;
let rem;
const r = Math.floor(args / 36) / 5 * 255;
const g = Math.floor((rem = args % 36) / 6) / 5 * 255;
const b = (rem % 6) / 5 * 255;
return [r, g, b];
};
convert.rgb.hex = function (args) {
const integer = ((Math.round(args[0]) & 0xFF) << 16)
+ ((Math.round(args[1]) & 0xFF) << 8)
+ (Math.round(args[2]) & 0xFF);
const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.hex.rgb = function (args) {
const match = args.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);
if (!match) {
return [0, 0, 0];
}
let colorString = match[0];
if (match[0].length === 3) {
colorString = colorString.split('').map(char => {
return char + char;
}).join('');
}
const integer = parseInt(colorString, 16);
const r = (integer >> 16) & 0xFF;
const g = (integer >> 8) & 0xFF;
const b = integer & 0xFF;
return [r, g, b];
};
convert.rgb.hcg = function (rgb) {
const r = rgb[0] / 255;
const g = rgb[1] / 255;
const b = rgb[2] / 255;
const max = Math.max(Math.max(r, g), b);
const min = Math.min(Math.min(r, g), b);
const chroma = (max - min);
let grayscale;
let hue;
if (chroma < 1) {
grayscale = min / (1 - chroma);
} else {
grayscale = 0;
}
if (chroma <= 0) {
hue = 0;
} else
if (max === r) {
hue = ((g - b) / chroma) % 6;
} else
if (max === g) {
hue = 2 + (b - r) / chroma;
} else {
hue = 4 + (r - g) / chroma;
}
hue /= 6;
hue %= 1;
return [hue * 360, chroma * 100, grayscale * 100];
};
convert.hsl.hcg = function (hsl) {
const s = hsl[1] / 100;
const l = hsl[2] / 100;
const c = l < 0.5 ? (2.0 * s * l) : (2.0 * s * (1.0 - l));
let f = 0;
if (c < 1.0) {
f = (l - 0.5 * c) / (1.0 - c);
}
return [hsl[0], c * 100, f * 100];
};
convert.hsv.hcg = function (hsv) {
const s = hsv[1] / 100;
const v = hsv[2] / 100;
const c = s * v;
let f = 0;
if (c < 1.0) {
f = (v - c) / (1 - c);
}
return [hsv[0], c * 100, f * 100];
};
convert.hcg.rgb = function (hcg) {
const h = hcg[0] / 360;
const c = hcg[1] / 100;
const g = hcg[2] / 100;
if (c === 0.0) {
return [g * 255, g * 255, g * 255];
}
const pure = [0, 0, 0];
const hi = (h % 1) * 6;
const v = hi % 1;
const w = 1 - v;
let mg = 0;
/* eslint-disable max-statements-per-line */
switch (Math.floor(hi)) {
case 0:
pure[0] = 1; pure[1] = v; pure[2] = 0; break;
case 1:
pure[0] = w; pure[1] = 1; pure[2] = 0; break;
case 2:
pure[0] = 0; pure[1] = 1; pure[2] = v; break;
case 3:
pure[0] = 0; pure[1] = w; pure[2] = 1; break;
case 4:
pure[0] = v; pure[1] = 0; pure[2] = 1; break;
default:
pure[0] = 1; pure[1] = 0; pure[2] = w;
}
/* eslint-enable max-statements-per-line */
mg = (1.0 - c) * g;
return [
(c * pure[0] + mg) * 255,
(c * pure[1] + mg) * 255,
(c * pure[2] + mg) * 255
];
};
convert.hcg.hsv = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1.0 - c);
let f = 0;
if (v > 0.0) {
f = c / v;
}
return [hcg[0], f * 100, v * 100];
};
convert.hcg.hsl = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const l = g * (1.0 - c) + 0.5 * c;
let s = 0;
if (l > 0.0 && l < 0.5) {
s = c / (2 * l);
} else
if (l >= 0.5 && l < 1.0) {
s = c / (2 * (1 - l));
}
return [hcg[0], s * 100, l * 100];
};
convert.hcg.hwb = function (hcg) {
const c = hcg[1] / 100;
const g = hcg[2] / 100;
const v = c + g * (1.0 - c);
return [hcg[0], (v - c) * 100, (1 - v) * 100];
};
convert.hwb.hcg = function (hwb) {
const w = hwb[1] / 100;
const b = hwb[2] / 100;
const v = 1 - b;
const c = v - w;
let g = 0;
if (c < 1) {
g = (v - c) / (1 - c);
}
return [hwb[0], c * 100, g * 100];
};
convert.apple.rgb = function (apple) {
return [(apple[0] / 65535) * 255, (apple[1] / 65535) * 255, (apple[2] / 65535) * 255];
};
convert.rgb.apple = function (rgb) {
return [(rgb[0] / 255) * 65535, (rgb[1] / 255) * 65535, (rgb[2] / 255) * 65535];
};
convert.gray.rgb = function (args) {
return [args[0] / 100 * 255, args[0] / 100 * 255, args[0] / 100 * 255];
};
convert.gray.hsl = function (args) {
return [0, 0, args[0]];
};
convert.gray.hsv = convert.gray.hsl;
convert.gray.hwb = function (gray) {
return [0, 100, gray[0]];
};
convert.gray.cmyk = function (gray) {
return [0, 0, 0, gray[0]];
};
convert.gray.lab = function (gray) {
return [gray[0], 0, 0];
};
convert.gray.hex = function (gray) {
const val = Math.round(gray[0] / 100 * 255) & 0xFF;
const integer = (val << 16) + (val << 8) + val;
const string = integer.toString(16).toUpperCase();
return '000000'.substring(string.length) + string;
};
convert.rgb.gray = function (rgb) {
const val = (rgb[0] + rgb[1] + rgb[2]) / 3;
return [val / 255 * 100];
};
+81
View File
@@ -0,0 +1,81 @@
const conversions = require('./conversions');
const route = require('./route');
const convert = {};
const models = Object.keys(conversions);
function wrapRaw(fn) {
const wrappedFn = function (...args) {
const arg0 = args[0];
if (arg0 === undefined || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
return fn(args);
};
// Preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
function wrapRounded(fn) {
const wrappedFn = function (...args) {
const arg0 = args[0];
if (arg0 === undefined || arg0 === null) {
return arg0;
}
if (arg0.length > 1) {
args = arg0;
}
const result = fn(args);
// We're assuming the result is an array here.
// see notice in conversions.js; don't use box types
// in conversion functions.
if (typeof result === 'object') {
for (let len = result.length, i = 0; i < len; i++) {
result[i] = Math.round(result[i]);
}
}
return result;
};
// Preserve .conversion property if there is one
if ('conversion' in fn) {
wrappedFn.conversion = fn.conversion;
}
return wrappedFn;
}
models.forEach(fromModel => {
convert[fromModel] = {};
Object.defineProperty(convert[fromModel], 'channels', {value: conversions[fromModel].channels});
Object.defineProperty(convert[fromModel], 'labels', {value: conversions[fromModel].labels});
const routes = route(fromModel);
const routeModels = Object.keys(routes);
routeModels.forEach(toModel => {
const fn = routes[toModel];
convert[fromModel][toModel] = wrapRounded(fn);
convert[fromModel][toModel].raw = wrapRaw(fn);
});
});
module.exports = convert;
+48
View File
@@ -0,0 +1,48 @@
{
"name": "color-convert",
"description": "Plain color conversion functions",
"version": "2.0.1",
"author": "Heather Arthur <fayearthur@gmail.com>",
"license": "MIT",
"repository": "Qix-/color-convert",
"scripts": {
"pretest": "xo",
"test": "node test/basic.js"
},
"engines": {
"node": ">=7.0.0"
},
"keywords": [
"color",
"colour",
"convert",
"converter",
"conversion",
"rgb",
"hsl",
"hsv",
"hwb",
"cmyk",
"ansi",
"ansi16"
],
"files": [
"index.js",
"conversions.js",
"route.js"
],
"xo": {
"rules": {
"default-case": 0,
"no-inline-comments": 0,
"operator-linebreak": 0
}
},
"devDependencies": {
"chalk": "^2.4.2",
"xo": "^0.24.0"
},
"dependencies": {
"color-name": "~1.1.4"
}
}
+97
View File
@@ -0,0 +1,97 @@
const conversions = require('./conversions');
/*
This function routes a model to all other models.
all functions that are routed have a property `.conversion` attached
to the returned synthetic function. This property is an array
of strings, each with the steps in between the 'from' and 'to'
color models (inclusive).
conversions that are not possible simply are not included.
*/
function buildGraph() {
const graph = {};
// https://jsperf.com/object-keys-vs-for-in-with-closure/3
const models = Object.keys(conversions);
for (let len = models.length, i = 0; i < len; i++) {
graph[models[i]] = {
// http://jsperf.com/1-vs-infinity
// micro-opt, but this is simple.
distance: -1,
parent: null
};
}
return graph;
}
// https://en.wikipedia.org/wiki/Breadth-first_search
function deriveBFS(fromModel) {
const graph = buildGraph();
const queue = [fromModel]; // Unshift -> queue -> pop
graph[fromModel].distance = 0;
while (queue.length) {
const current = queue.pop();
const adjacents = Object.keys(conversions[current]);
for (let len = adjacents.length, i = 0; i < len; i++) {
const adjacent = adjacents[i];
const node = graph[adjacent];
if (node.distance === -1) {
node.distance = graph[current].distance + 1;
node.parent = current;
queue.unshift(adjacent);
}
}
}
return graph;
}
function link(from, to) {
return function (args) {
return to(from(args));
};
}
function wrapConversion(toModel, graph) {
const path = [graph[toModel].parent, toModel];
let fn = conversions[graph[toModel].parent][toModel];
let cur = graph[toModel].parent;
while (graph[cur].parent) {
path.unshift(graph[cur].parent);
fn = link(conversions[graph[cur].parent][cur], fn);
cur = graph[cur].parent;
}
fn.conversion = path;
return fn;
}
module.exports = function (fromModel) {
const graph = deriveBFS(fromModel);
const conversion = {};
const models = Object.keys(graph);
for (let len = models.length, i = 0; i < len; i++) {
const toModel = models[i];
const node = graph[toModel];
if (node.parent === null) {
// No possible conversion, or this node is the source model.
continue;
}
conversion[toModel] = wrapConversion(toModel, graph);
}
return conversion;
};
+8
View File
@@ -0,0 +1,8 @@
The MIT License (MIT)
Copyright (c) 2015 Dmitry Ivanov
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+11
View File
@@ -0,0 +1,11 @@
A JSON with color names and its values. Based on http://dev.w3.org/csswg/css-color/#named-colors.
[![NPM](https://nodei.co/npm/color-name.png?mini=true)](https://nodei.co/npm/color-name/)
```js
var colors = require('color-name');
colors.red //[255,0,0]
```
<a href="LICENSE"><img src="https://upload.wikimedia.org/wikipedia/commons/0/0c/MIT_logo.svg" width="120"/></a>
+152
View File
@@ -0,0 +1,152 @@
'use strict'
module.exports = {
"aliceblue": [240, 248, 255],
"antiquewhite": [250, 235, 215],
"aqua": [0, 255, 255],
"aquamarine": [127, 255, 212],
"azure": [240, 255, 255],
"beige": [245, 245, 220],
"bisque": [255, 228, 196],
"black": [0, 0, 0],
"blanchedalmond": [255, 235, 205],
"blue": [0, 0, 255],
"blueviolet": [138, 43, 226],
"brown": [165, 42, 42],
"burlywood": [222, 184, 135],
"cadetblue": [95, 158, 160],
"chartreuse": [127, 255, 0],
"chocolate": [210, 105, 30],
"coral": [255, 127, 80],
"cornflowerblue": [100, 149, 237],
"cornsilk": [255, 248, 220],
"crimson": [220, 20, 60],
"cyan": [0, 255, 255],
"darkblue": [0, 0, 139],
"darkcyan": [0, 139, 139],
"darkgoldenrod": [184, 134, 11],
"darkgray": [169, 169, 169],
"darkgreen": [0, 100, 0],
"darkgrey": [169, 169, 169],
"darkkhaki": [189, 183, 107],
"darkmagenta": [139, 0, 139],
"darkolivegreen": [85, 107, 47],
"darkorange": [255, 140, 0],
"darkorchid": [153, 50, 204],
"darkred": [139, 0, 0],
"darksalmon": [233, 150, 122],
"darkseagreen": [143, 188, 143],
"darkslateblue": [72, 61, 139],
"darkslategray": [47, 79, 79],
"darkslategrey": [47, 79, 79],
"darkturquoise": [0, 206, 209],
"darkviolet": [148, 0, 211],
"deeppink": [255, 20, 147],
"deepskyblue": [0, 191, 255],
"dimgray": [105, 105, 105],
"dimgrey": [105, 105, 105],
"dodgerblue": [30, 144, 255],
"firebrick": [178, 34, 34],
"floralwhite": [255, 250, 240],
"forestgreen": [34, 139, 34],
"fuchsia": [255, 0, 255],
"gainsboro": [220, 220, 220],
"ghostwhite": [248, 248, 255],
"gold": [255, 215, 0],
"goldenrod": [218, 165, 32],
"gray": [128, 128, 128],
"green": [0, 128, 0],
"greenyellow": [173, 255, 47],
"grey": [128, 128, 128],
"honeydew": [240, 255, 240],
"hotpink": [255, 105, 180],
"indianred": [205, 92, 92],
"indigo": [75, 0, 130],
"ivory": [255, 255, 240],
"khaki": [240, 230, 140],
"lavender": [230, 230, 250],
"lavenderblush": [255, 240, 245],
"lawngreen": [124, 252, 0],
"lemonchiffon": [255, 250, 205],
"lightblue": [173, 216, 230],
"lightcoral": [240, 128, 128],
"lightcyan": [224, 255, 255],
"lightgoldenrodyellow": [250, 250, 210],
"lightgray": [211, 211, 211],
"lightgreen": [144, 238, 144],
"lightgrey": [211, 211, 211],
"lightpink": [255, 182, 193],
"lightsalmon": [255, 160, 122],
"lightseagreen": [32, 178, 170],
"lightskyblue": [135, 206, 250],
"lightslategray": [119, 136, 153],
"lightslategrey": [119, 136, 153],
"lightsteelblue": [176, 196, 222],
"lightyellow": [255, 255, 224],
"lime": [0, 255, 0],
"limegreen": [50, 205, 50],
"linen": [250, 240, 230],
"magenta": [255, 0, 255],
"maroon": [128, 0, 0],
"mediumaquamarine": [102, 205, 170],
"mediumblue": [0, 0, 205],
"mediumorchid": [186, 85, 211],
"mediumpurple": [147, 112, 219],
"mediumseagreen": [60, 179, 113],
"mediumslateblue": [123, 104, 238],
"mediumspringgreen": [0, 250, 154],
"mediumturquoise": [72, 209, 204],
"mediumvioletred": [199, 21, 133],
"midnightblue": [25, 25, 112],
"mintcream": [245, 255, 250],
"mistyrose": [255, 228, 225],
"moccasin": [255, 228, 181],
"navajowhite": [255, 222, 173],
"navy": [0, 0, 128],
"oldlace": [253, 245, 230],
"olive": [128, 128, 0],
"olivedrab": [107, 142, 35],
"orange": [255, 165, 0],
"orangered": [255, 69, 0],
"orchid": [218, 112, 214],
"palegoldenrod": [238, 232, 170],
"palegreen": [152, 251, 152],
"paleturquoise": [175, 238, 238],
"palevioletred": [219, 112, 147],
"papayawhip": [255, 239, 213],
"peachpuff": [255, 218, 185],
"peru": [205, 133, 63],
"pink": [255, 192, 203],
"plum": [221, 160, 221],
"powderblue": [176, 224, 230],
"purple": [128, 0, 128],
"rebeccapurple": [102, 51, 153],
"red": [255, 0, 0],
"rosybrown": [188, 143, 143],
"royalblue": [65, 105, 225],
"saddlebrown": [139, 69, 19],
"salmon": [250, 128, 114],
"sandybrown": [244, 164, 96],
"seagreen": [46, 139, 87],
"seashell": [255, 245, 238],
"sienna": [160, 82, 45],
"silver": [192, 192, 192],
"skyblue": [135, 206, 235],
"slateblue": [106, 90, 205],
"slategray": [112, 128, 144],
"slategrey": [112, 128, 144],
"snow": [255, 250, 250],
"springgreen": [0, 255, 127],
"steelblue": [70, 130, 180],
"tan": [210, 180, 140],
"teal": [0, 128, 128],
"thistle": [216, 191, 216],
"tomato": [255, 99, 71],
"turquoise": [64, 224, 208],
"violet": [238, 130, 238],
"wheat": [245, 222, 179],
"white": [255, 255, 255],
"whitesmoke": [245, 245, 245],
"yellow": [255, 255, 0],
"yellowgreen": [154, 205, 50]
};
+28
View File
@@ -0,0 +1,28 @@
{
"name": "color-name",
"version": "1.1.4",
"description": "A list of color names and its values",
"main": "index.js",
"files": [
"index.js"
],
"scripts": {
"test": "node test.js"
},
"repository": {
"type": "git",
"url": "git@github.com:colorjs/color-name.git"
},
"keywords": [
"color-name",
"color",
"color-keyword",
"keyword"
],
"author": "DY <dfcreative@gmail.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/colorjs/color-name/issues"
},
"homepage": "https://github.com/colorjs/color-name"
}
+39
View File
@@ -0,0 +1,39 @@
/**
Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag.
@param flag - CLI flag to look for. The `--` prefix is optional.
@param argv - CLI arguments. Default: `process.argv`.
@returns Whether the flag exists.
@example
```
// $ ts-node foo.ts -f --unicorn --foo=bar -- --rainbow
// foo.ts
import hasFlag = require('has-flag');
hasFlag('unicorn');
//=> true
hasFlag('--unicorn');
//=> true
hasFlag('f');
//=> true
hasFlag('-f');
//=> true
hasFlag('foo=bar');
//=> true
hasFlag('foo');
//=> false
hasFlag('rainbow');
//=> false
```
*/
declare function hasFlag(flag: string, argv?: string[]): boolean;
export = hasFlag;
+8
View File
@@ -0,0 +1,8 @@
'use strict';
module.exports = (flag, argv = process.argv) => {
const prefix = flag.startsWith('-') ? '' : (flag.length === 1 ? '-' : '--');
const position = argv.indexOf(prefix + flag);
const terminatorPosition = argv.indexOf('--');
return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
};
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+46
View File
@@ -0,0 +1,46 @@
{
"name": "has-flag",
"version": "4.0.0",
"description": "Check if argv has a specific flag",
"license": "MIT",
"repository": "sindresorhus/has-flag",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava && tsd"
},
"files": [
"index.js",
"index.d.ts"
],
"keywords": [
"has",
"check",
"detect",
"contains",
"find",
"flag",
"cli",
"command-line",
"argv",
"process",
"arg",
"args",
"argument",
"arguments",
"getopt",
"minimist",
"optimist"
],
"devDependencies": {
"ava": "^1.4.1",
"tsd": "^0.7.2",
"xo": "^0.24.0"
}
}
+89
View File
@@ -0,0 +1,89 @@
# has-flag [![Build Status](https://travis-ci.org/sindresorhus/has-flag.svg?branch=master)](https://travis-ci.org/sindresorhus/has-flag)
> Check if [`argv`](https://nodejs.org/docs/latest/api/process.html#process_process_argv) has a specific flag
Correctly stops looking after an `--` argument terminator.
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-has-flag?utm_source=npm-has-flag&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
---
## Install
```
$ npm install has-flag
```
## Usage
```js
// foo.js
const hasFlag = require('has-flag');
hasFlag('unicorn');
//=> true
hasFlag('--unicorn');
//=> true
hasFlag('f');
//=> true
hasFlag('-f');
//=> true
hasFlag('foo=bar');
//=> true
hasFlag('foo');
//=> false
hasFlag('rainbow');
//=> false
```
```
$ node foo.js -f --unicorn --foo=bar -- --rainbow
```
## API
### hasFlag(flag, [argv])
Returns a boolean for whether the flag exists.
#### flag
Type: `string`
CLI flag to look for. The `--` prefix is optional.
#### argv
Type: `string[]`<br>
Default: `process.argv`
CLI arguments.
## Security
To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure.
## License
MIT © [Sindre Sorhus](https://sindresorhus.com)
+5
View File
@@ -0,0 +1,5 @@
'use strict';
module.exports = {
stdout: false,
stderr: false
};
+135
View File
@@ -0,0 +1,135 @@
'use strict';
const os = require('os');
const tty = require('tty');
const hasFlag = require('has-flag');
const {env} = process;
let forceColor;
if (hasFlag('no-color') ||
hasFlag('no-colors') ||
hasFlag('color=false') ||
hasFlag('color=never')) {
forceColor = 0;
} else if (hasFlag('color') ||
hasFlag('colors') ||
hasFlag('color=true') ||
hasFlag('color=always')) {
forceColor = 1;
}
if ('FORCE_COLOR' in env) {
if (env.FORCE_COLOR === 'true') {
forceColor = 1;
} else if (env.FORCE_COLOR === 'false') {
forceColor = 0;
} else {
forceColor = env.FORCE_COLOR.length === 0 ? 1 : Math.min(parseInt(env.FORCE_COLOR, 10), 3);
}
}
function translateLevel(level) {
if (level === 0) {
return false;
}
return {
level,
hasBasic: true,
has256: level >= 2,
has16m: level >= 3
};
}
function supportsColor(haveStream, streamIsTTY) {
if (forceColor === 0) {
return 0;
}
if (hasFlag('color=16m') ||
hasFlag('color=full') ||
hasFlag('color=truecolor')) {
return 3;
}
if (hasFlag('color=256')) {
return 2;
}
if (haveStream && !streamIsTTY && forceColor === undefined) {
return 0;
}
const min = forceColor || 0;
if (env.TERM === 'dumb') {
return min;
}
if (process.platform === 'win32') {
// Windows 10 build 10586 is the first Windows release that supports 256 colors.
// Windows 10 build 14931 is the first release that supports 16m/TrueColor.
const osRelease = os.release().split('.');
if (
Number(osRelease[0]) >= 10 &&
Number(osRelease[2]) >= 10586
) {
return Number(osRelease[2]) >= 14931 ? 3 : 2;
}
return 1;
}
if ('CI' in env) {
if (['TRAVIS', 'CIRCLECI', 'APPVEYOR', 'GITLAB_CI', 'GITHUB_ACTIONS', 'BUILDKITE'].some(sign => sign in env) || env.CI_NAME === 'codeship') {
return 1;
}
return min;
}
if ('TEAMCITY_VERSION' in env) {
return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
}
if (env.COLORTERM === 'truecolor') {
return 3;
}
if ('TERM_PROGRAM' in env) {
const version = parseInt((env.TERM_PROGRAM_VERSION || '').split('.')[0], 10);
switch (env.TERM_PROGRAM) {
case 'iTerm.app':
return version >= 3 ? 3 : 2;
case 'Apple_Terminal':
return 2;
// No default
}
}
if (/-256(color)?$/i.test(env.TERM)) {
return 2;
}
if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
return 1;
}
if ('COLORTERM' in env) {
return 1;
}
return min;
}
function getSupportLevel(stream) {
const level = supportsColor(stream, stream && stream.isTTY);
return translateLevel(level);
}
module.exports = {
supportsColor: getSupportLevel,
stdout: translateLevel(supportsColor(true, tty.isatty(1))),
stderr: translateLevel(supportsColor(true, tty.isatty(2)))
};
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+53
View File
@@ -0,0 +1,53 @@
{
"name": "supports-color",
"version": "7.2.0",
"description": "Detect whether a terminal supports color",
"license": "MIT",
"repository": "chalk/supports-color",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && ava"
},
"files": [
"index.js",
"browser.js"
],
"keywords": [
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"ansi",
"styles",
"tty",
"rgb",
"256",
"shell",
"xterm",
"command-line",
"support",
"supports",
"capability",
"detect",
"truecolor",
"16m"
],
"dependencies": {
"has-flag": "^4.0.0"
},
"devDependencies": {
"ava": "^1.4.1",
"import-fresh": "^3.0.0",
"xo": "^0.24.0"
},
"browser": "browser.js"
}
+76
View File
@@ -0,0 +1,76 @@
# supports-color [![Build Status](https://travis-ci.org/chalk/supports-color.svg?branch=master)](https://travis-ci.org/chalk/supports-color)
> Detect whether a terminal supports color
## Install
```
$ npm install supports-color
```
## Usage
```js
const supportsColor = require('supports-color');
if (supportsColor.stdout) {
console.log('Terminal stdout supports color');
}
if (supportsColor.stdout.has256) {
console.log('Terminal stdout supports 256 colors');
}
if (supportsColor.stderr.has16m) {
console.log('Terminal stderr supports 16 million colors (truecolor)');
}
```
## API
Returns an `Object` with a `stdout` and `stderr` property for testing either streams. Each property is an `Object`, or `false` if color is not supported.
The `stdout`/`stderr` objects specifies a level of support for color through a `.level` property and a corresponding flag:
- `.level = 1` and `.hasBasic = true`: Basic color support (16 colors)
- `.level = 2` and `.has256 = true`: 256 color support
- `.level = 3` and `.has16m = true`: Truecolor support (16 million colors)
## Info
It obeys the `--color` and `--no-color` CLI flags.
For situations where using `--color` is not possible, use the environment variable `FORCE_COLOR=1` (level 1), `FORCE_COLOR=2` (level 2), or `FORCE_COLOR=3` (level 3) to forcefully enable color, or `FORCE_COLOR=0` to forcefully disable. The use of `FORCE_COLOR` overrides all other color support checks.
Explicit 256/Truecolor mode can be enabled using the `--color=256` and `--color=16m` flags, respectively.
## Related
- [supports-color-cli](https://github.com/chalk/supports-color-cli) - CLI for this module
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-supports-color?utm_source=npm-supports-color&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
---
+186
View File
@@ -0,0 +1,186 @@
'use strict';
const stringWidth = require('string-width');
const stripAnsi = require('strip-ansi');
const ansiStyles = require('ansi-styles');
const ESCAPES = new Set([
'\u001B',
'\u009B'
]);
const END_CODE = 39;
const wrapAnsi = code => `${ESCAPES.values().next().value}[${code}m`;
// Calculate the length of words split on ' ', ignoring
// the extra characters added by ansi escape codes
const wordLengths = string => string.split(' ').map(character => stringWidth(character));
// Wrap a long word across multiple rows
// Ansi escape codes do not count towards length
const wrapWord = (rows, word, columns) => {
const characters = [...word];
let isInsideEscape = false;
let visible = stringWidth(stripAnsi(rows[rows.length - 1]));
for (const [index, character] of characters.entries()) {
const characterLength = stringWidth(character);
if (visible + characterLength <= columns) {
rows[rows.length - 1] += character;
} else {
rows.push(character);
visible = 0;
}
if (ESCAPES.has(character)) {
isInsideEscape = true;
} else if (isInsideEscape && character === 'm') {
isInsideEscape = false;
continue;
}
if (isInsideEscape) {
continue;
}
visible += characterLength;
if (visible === columns && index < characters.length - 1) {
rows.push('');
visible = 0;
}
}
// It's possible that the last row we copy over is only
// ansi escape characters, handle this edge-case
if (!visible && rows[rows.length - 1].length > 0 && rows.length > 1) {
rows[rows.length - 2] += rows.pop();
}
};
// Trims spaces from a string ignoring invisible sequences
const stringVisibleTrimSpacesRight = str => {
const words = str.split(' ');
let last = words.length;
while (last > 0) {
if (stringWidth(words[last - 1]) > 0) {
break;
}
last--;
}
if (last === words.length) {
return str;
}
return words.slice(0, last).join(' ') + words.slice(last).join('');
};
// The wrap-ansi module can be invoked in either 'hard' or 'soft' wrap mode
//
// 'hard' will never allow a string to take up more than columns characters
//
// 'soft' allows long words to expand past the column length
const exec = (string, columns, options = {}) => {
if (options.trim !== false && string.trim() === '') {
return '';
}
let pre = '';
let ret = '';
let escapeCode;
const lengths = wordLengths(string);
let rows = [''];
for (const [index, word] of string.split(' ').entries()) {
if (options.trim !== false) {
rows[rows.length - 1] = rows[rows.length - 1].trimLeft();
}
let rowLength = stringWidth(rows[rows.length - 1]);
if (index !== 0) {
if (rowLength >= columns && (options.wordWrap === false || options.trim === false)) {
// If we start with a new word but the current row length equals the length of the columns, add a new row
rows.push('');
rowLength = 0;
}
if (rowLength > 0 || options.trim === false) {
rows[rows.length - 1] += ' ';
rowLength++;
}
}
// In 'hard' wrap mode, the length of a line is never allowed to extend past 'columns'
if (options.hard && lengths[index] > columns) {
const remainingColumns = (columns - rowLength);
const breaksStartingThisLine = 1 + Math.floor((lengths[index] - remainingColumns - 1) / columns);
const breaksStartingNextLine = Math.floor((lengths[index] - 1) / columns);
if (breaksStartingNextLine < breaksStartingThisLine) {
rows.push('');
}
wrapWord(rows, word, columns);
continue;
}
if (rowLength + lengths[index] > columns && rowLength > 0 && lengths[index] > 0) {
if (options.wordWrap === false && rowLength < columns) {
wrapWord(rows, word, columns);
continue;
}
rows.push('');
}
if (rowLength + lengths[index] > columns && options.wordWrap === false) {
wrapWord(rows, word, columns);
continue;
}
rows[rows.length - 1] += word;
}
if (options.trim !== false) {
rows = rows.map(stringVisibleTrimSpacesRight);
}
pre = rows.join('\n');
for (const [index, character] of [...pre].entries()) {
ret += character;
if (ESCAPES.has(character)) {
const code = parseFloat(/\d[^m]*/.exec(pre.slice(index, index + 4)));
escapeCode = code === END_CODE ? null : code;
}
const code = ansiStyles.codes.get(Number(escapeCode));
if (escapeCode && code) {
if (pre[index + 1] === '\n') {
ret += wrapAnsi(code);
} else if (character === '\n') {
ret += wrapAnsi(escapeCode);
}
}
}
return ret;
};
// For each newline, invoke the method separately
module.exports = (string, columns, options) => {
return String(string)
.normalize()
.replace(/\r\n/g, '\n')
.split('\n')
.map(line => exec(line, columns, options))
.join('\n');
};
+9
View File
@@ -0,0 +1,9 @@
MIT License
Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+61
View File
@@ -0,0 +1,61 @@
{
"name": "wrap-ansi",
"version": "6.2.0",
"description": "Wordwrap a string with ANSI escape codes",
"license": "MIT",
"repository": "chalk/wrap-ansi",
"author": {
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
},
"engines": {
"node": ">=8"
},
"scripts": {
"test": "xo && nyc ava"
},
"files": [
"index.js"
],
"keywords": [
"wrap",
"break",
"wordwrap",
"wordbreak",
"linewrap",
"ansi",
"styles",
"color",
"colour",
"colors",
"terminal",
"console",
"cli",
"string",
"tty",
"escape",
"formatting",
"rgb",
"256",
"shell",
"xterm",
"log",
"logging",
"command-line",
"text"
],
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"devDependencies": {
"ava": "^2.1.0",
"chalk": "^2.4.2",
"coveralls": "^3.0.3",
"has-ansi": "^3.0.0",
"nyc": "^14.1.1",
"xo": "^0.24.0"
}
}
+97
View File
@@ -0,0 +1,97 @@
# wrap-ansi [![Build Status](https://travis-ci.org/chalk/wrap-ansi.svg?branch=master)](https://travis-ci.org/chalk/wrap-ansi) [![Coverage Status](https://coveralls.io/repos/github/chalk/wrap-ansi/badge.svg?branch=master)](https://coveralls.io/github/chalk/wrap-ansi?branch=master)
> Wordwrap a string with [ANSI escape codes](https://en.wikipedia.org/wiki/ANSI_escape_code#Colors_and_Styles)
## Install
```
$ npm install wrap-ansi
```
## Usage
```js
const chalk = require('chalk');
const wrapAnsi = require('wrap-ansi');
const input = 'The quick brown ' + chalk.red('fox jumped over ') +
'the lazy ' + chalk.green('dog and then ran away with the unicorn.');
console.log(wrapAnsi(input, 20));
```
<img width="331" src="screenshot.png">
## API
### wrapAnsi(string, columns, options?)
Wrap words to the specified column width.
#### string
Type: `string`
String with ANSI escape codes. Like one styled by [`chalk`](https://github.com/chalk/chalk). Newline characters will be normalized to `\n`.
#### columns
Type: `number`
Number of columns to wrap the text to.
#### options
Type: `object`
##### hard
Type: `boolean`<br>
Default: `false`
By default the wrap is soft, meaning long words may extend past the column width. Setting this to `true` will make it hard wrap at the column width.
##### wordWrap
Type: `boolean`<br>
Default: `true`
By default, an attempt is made to split words at spaces, ensuring that they don't extend past the configured columns. If wordWrap is `false`, each column will instead be completely filled splitting words as necessary.
##### trim
Type: `boolean`<br>
Default: `true`
Whitespace on all lines is removed by default. Set this option to `false` if you don't want to trim.
## Related
- [slice-ansi](https://github.com/chalk/slice-ansi) - Slice a string with ANSI escape codes
- [cli-truncate](https://github.com/sindresorhus/cli-truncate) - Truncate a string to a specific width in the terminal
- [chalk](https://github.com/chalk/chalk) - Terminal string styling done right
- [jsesc](https://github.com/mathiasbynens/jsesc) - Generate ASCII-only output from Unicode strings. Useful for creating test fixtures.
## Maintainers
- [Sindre Sorhus](https://github.com/sindresorhus)
- [Josh Junon](https://github.com/qix-)
- [Benjamin Coe](https://github.com/bcoe)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-wrap_ansi?utm_source=npm-wrap-ansi&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>
+601
View File
@@ -0,0 +1,601 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
### [18.1.3](https://www.github.com/yargs/yargs-parser/compare/v18.1.2...v18.1.3) (2020-04-16)
### Bug Fixes
* **setArg:** options using camel-case and dot-notation populated twice ([#268](https://www.github.com/yargs/yargs-parser/issues/268)) ([f7e15b9](https://www.github.com/yargs/yargs-parser/commit/f7e15b9800900b9856acac1a830a5f35847be73e))
### [18.1.2](https://www.github.com/yargs/yargs-parser/compare/v18.1.1...v18.1.2) (2020-03-26)
### Bug Fixes
* **array, nargs:** support -o=--value and --option=--value format ([#262](https://www.github.com/yargs/yargs-parser/issues/262)) ([41d3f81](https://www.github.com/yargs/yargs-parser/commit/41d3f8139e116706b28de9b0de3433feb08d2f13))
### [18.1.1](https://www.github.com/yargs/yargs-parser/compare/v18.1.0...v18.1.1) (2020-03-16)
### Bug Fixes
* \_\_proto\_\_ will now be replaced with \_\_\_proto\_\_\_ in parse ([#258](https://www.github.com/yargs/yargs-parser/issues/258)), patching a potential
prototype pollution vulnerability. This was reported by the Snyk Security Research Team.([63810ca](https://www.github.com/yargs/yargs-parser/commit/63810ca1ae1a24b08293a4d971e70e058c7a41e2))
## [18.1.0](https://www.github.com/yargs/yargs-parser/compare/v18.0.0...v18.1.0) (2020-03-07)
### Features
* introduce single-digit boolean aliases ([#255](https://www.github.com/yargs/yargs-parser/issues/255)) ([9c60265](https://www.github.com/yargs/yargs-parser/commit/9c60265fd7a03cb98e6df3e32c8c5e7508d9f56f))
## [18.0.0](https://www.github.com/yargs/yargs-parser/compare/v17.1.0...v18.0.0) (2020-03-02)
### ⚠ BREAKING CHANGES
* the narg count is now enforced when parsing arrays.
### Features
* NaN can now be provided as a value for nargs, indicating "at least" one value is expected for array ([#251](https://www.github.com/yargs/yargs-parser/issues/251)) ([9db4be8](https://www.github.com/yargs/yargs-parser/commit/9db4be81417a2c7097128db34d86fe70ef4af70c))
## [17.1.0](https://www.github.com/yargs/yargs-parser/compare/v17.0.1...v17.1.0) (2020-03-01)
### Features
* introduce greedy-arrays config, for specifying whether arrays consume multiple positionals ([#249](https://www.github.com/yargs/yargs-parser/issues/249)) ([60e880a](https://www.github.com/yargs/yargs-parser/commit/60e880a837046314d89fa4725f923837fd33a9eb))
### [17.0.1](https://www.github.com/yargs/yargs-parser/compare/v17.0.0...v17.0.1) (2020-02-29)
### Bug Fixes
* normalized keys were not enumerable ([#247](https://www.github.com/yargs/yargs-parser/issues/247)) ([57119f9](https://www.github.com/yargs/yargs-parser/commit/57119f9f17cf27499bd95e61c2f72d18314f11ba))
## [17.0.0](https://www.github.com/yargs/yargs-parser/compare/v16.1.0...v17.0.0) (2020-02-10)
### ⚠ BREAKING CHANGES
* this reverts parsing behavior of booleans to that of yargs@14
* objects used during parsing are now created with a null
prototype. There may be some scenarios where this change in behavior
leaks externally.
### Features
* boolean arguments will not be collected into an implicit array ([#236](https://www.github.com/yargs/yargs-parser/issues/236)) ([34c4e19](https://www.github.com/yargs/yargs-parser/commit/34c4e19bae4e7af63e3cb6fa654a97ed476e5eb5))
* introduce nargs-eats-options config option ([#246](https://www.github.com/yargs/yargs-parser/issues/246)) ([d50822a](https://www.github.com/yargs/yargs-parser/commit/d50822ac10e1b05f2e9643671ca131ac251b6732))
### Bug Fixes
* address bugs with "uknown-options-as-args" ([bc023e3](https://www.github.com/yargs/yargs-parser/commit/bc023e3b13e20a118353f9507d1c999bf388a346))
* array should take precedence over nargs, but enforce nargs ([#243](https://www.github.com/yargs/yargs-parser/issues/243)) ([4cbc188](https://www.github.com/yargs/yargs-parser/commit/4cbc188b7abb2249529a19c090338debdad2fe6c))
* support keys that collide with object prototypes ([#234](https://www.github.com/yargs/yargs-parser/issues/234)) ([1587b6d](https://www.github.com/yargs/yargs-parser/commit/1587b6d91db853a9109f1be6b209077993fee4de))
* unknown options terminated with digits now handled by unknown-options-as-args ([#238](https://www.github.com/yargs/yargs-parser/issues/238)) ([d36cdfa](https://www.github.com/yargs/yargs-parser/commit/d36cdfa854254d7c7e0fe1d583818332ac46c2a5))
## [16.1.0](https://www.github.com/yargs/yargs-parser/compare/v16.0.0...v16.1.0) (2019-11-01)
### ⚠ BREAKING CHANGES
* populate error if incompatible narg/count or array/count options are used (#191)
### Features
* options that have had their default value used are now tracked ([#211](https://www.github.com/yargs/yargs-parser/issues/211)) ([a525234](https://www.github.com/yargs/yargs-parser/commit/a525234558c847deedd73f8792e0a3b77b26e2c0))
* populate error if incompatible narg/count or array/count options are used ([#191](https://www.github.com/yargs/yargs-parser/issues/191)) ([84a401f](https://www.github.com/yargs/yargs-parser/commit/84a401f0fa3095e0a19661670d1570d0c3b9d3c9))
### Reverts
* revert 16.0.0 CHANGELOG entry ([920320a](https://www.github.com/yargs/yargs-parser/commit/920320ad9861bbfd58eda39221ae211540fc1daf))
## [15.0.0](https://github.com/yargs/yargs-parser/compare/v14.0.0...v15.0.0) (2019-10-07)
### Features
* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality ([ef771ca](https://github.com/yargs/yargs-parser/commit/ef771ca))
### BREAKING CHANGES
* rework `collect-unknown-options` into `unknown-options-as-args`, providing more comprehensive functionality
## [14.0.0](https://github.com/yargs/yargs-parser/compare/v13.1.1...v14.0.0) (2019-09-06)
### Bug Fixes
* boolean arrays with default values ([#185](https://github.com/yargs/yargs-parser/issues/185)) ([7d42572](https://github.com/yargs/yargs-parser/commit/7d42572))
* boolean now behaves the same as other array types ([#184](https://github.com/yargs/yargs-parser/issues/184)) ([17ca3bd](https://github.com/yargs/yargs-parser/commit/17ca3bd))
* eatNargs() for 'opt.narg === 0' and boolean typed options ([#188](https://github.com/yargs/yargs-parser/issues/188)) ([c5a1db0](https://github.com/yargs/yargs-parser/commit/c5a1db0))
* maybeCoerceNumber now takes precedence over coerce return value ([#182](https://github.com/yargs/yargs-parser/issues/182)) ([2f26436](https://github.com/yargs/yargs-parser/commit/2f26436))
* take into account aliases when appending arrays from config object ([#199](https://github.com/yargs/yargs-parser/issues/199)) ([f8a2d3f](https://github.com/yargs/yargs-parser/commit/f8a2d3f))
### Features
* add configuration option to "collect-unknown-options" ([#181](https://github.com/yargs/yargs-parser/issues/181)) ([7909cc4](https://github.com/yargs/yargs-parser/commit/7909cc4))
* maybeCoerceNumber() now takes into account arrays ([#187](https://github.com/yargs/yargs-parser/issues/187)) ([31c204b](https://github.com/yargs/yargs-parser/commit/31c204b))
### BREAKING CHANGES
* unless "parse-numbers" is set to "false", arrays of numeric strings are now parsed as numbers, rather than strings.
* we have dropped the broken "defaulted" functionality; we would like to revisit adding this in the future.
* maybeCoerceNumber now takes precedence over coerce return value (#182)
### [13.1.1](https://www.github.com/yargs/yargs-parser/compare/v13.1.0...v13.1.1) (2019-06-10)
### Bug Fixes
* convert values to strings when tokenizing ([#167](https://www.github.com/yargs/yargs-parser/issues/167)) ([57b7883](https://www.github.com/yargs/yargs-parser/commit/57b7883))
* nargs should allow duplicates when duplicate-arguments-array=false ([#164](https://www.github.com/yargs/yargs-parser/issues/164)) ([47ccb0b](https://www.github.com/yargs/yargs-parser/commit/47ccb0b))
* should populate "_" when given config with "short-option-groups" false ([#179](https://www.github.com/yargs/yargs-parser/issues/179)) ([6055974](https://www.github.com/yargs/yargs-parser/commit/6055974))
## [13.1.0](https://github.com/yargs/yargs-parser/compare/v13.0.0...v13.1.0) (2019-05-05)
### Features
* add `strip-aliased` and `strip-dashed` configuration options. ([#172](https://github.com/yargs/yargs-parser/issues/172)) ([a3936aa](https://github.com/yargs/yargs-parser/commit/a3936aa))
* support boolean which do not consume next argument. ([#171](https://github.com/yargs/yargs-parser/issues/171)) ([0ae7fcb](https://github.com/yargs/yargs-parser/commit/0ae7fcb))
<a name="13.0.0"></a>
# [13.0.0](https://github.com/yargs/yargs-parser/compare/v12.0.0...v13.0.0) (2019-02-02)
### Features
* don't coerce number from string with leading '0' or '+' ([#158](https://github.com/yargs/yargs-parser/issues/158)) ([18d0fd5](https://github.com/yargs/yargs-parser/commit/18d0fd5))
### BREAKING CHANGES
* options with leading '+' or '0' now parse as strings
<a name="12.0.0"></a>
# [12.0.0](https://github.com/yargs/yargs-parser/compare/v11.1.1...v12.0.0) (2019-01-29)
### Bug Fixes
* better handling of quoted strings ([#153](https://github.com/yargs/yargs-parser/issues/153)) ([2fb71b2](https://github.com/yargs/yargs-parser/commit/2fb71b2))
### Features
* default value is now used if no right-hand value provided for numbers/strings ([#156](https://github.com/yargs/yargs-parser/issues/156)) ([5a7c46a](https://github.com/yargs/yargs-parser/commit/5a7c46a))
### BREAKING CHANGES
* a flag with no right-hand value no longer populates defaulted options with `undefined`.
* quotes at beginning and endings of strings are not removed during parsing.
<a name="11.1.1"></a>
## [11.1.1](https://github.com/yargs/yargs-parser/compare/v11.1.0...v11.1.1) (2018-11-19)
### Bug Fixes
* ensure empty string is added into argv._ ([#140](https://github.com/yargs/yargs-parser/issues/140)) ([79cda98](https://github.com/yargs/yargs-parser/commit/79cda98))
### Reverts
* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([f4a3063](https://github.com/yargs/yargs-parser/commit/f4a3063))
<a name="11.1.0"></a>
# [11.1.0](https://github.com/yargs/yargs-parser/compare/v11.0.0...v11.1.0) (2018-11-10)
### Bug Fixes
* handling of one char alias ([#139](https://github.com/yargs/yargs-parser/issues/139)) ([ee56e31](https://github.com/yargs/yargs-parser/commit/ee56e31))
### Features
* add halt-at-non-option configuration option ([#130](https://github.com/yargs/yargs-parser/issues/130)) ([a849fce](https://github.com/yargs/yargs-parser/commit/a849fce))
<a name="11.0.0"></a>
# [11.0.0](https://github.com/yargs/yargs-parser/compare/v10.1.0...v11.0.0) (2018-10-06)
### Bug Fixes
* flatten-duplicate-arrays:false for more than 2 arrays ([#128](https://github.com/yargs/yargs-parser/issues/128)) ([2bc395f](https://github.com/yargs/yargs-parser/commit/2bc395f))
* hyphenated flags combined with dot notation broke parsing ([#131](https://github.com/yargs/yargs-parser/issues/131)) ([dc788da](https://github.com/yargs/yargs-parser/commit/dc788da))
* make requiresArg work in conjunction with arrays ([#136](https://github.com/yargs/yargs-parser/issues/136)) ([77ae1d4](https://github.com/yargs/yargs-parser/commit/77ae1d4))
### Chores
* update dependencies ([6dc42a1](https://github.com/yargs/yargs-parser/commit/6dc42a1))
### Features
* also add camelCase array options ([#125](https://github.com/yargs/yargs-parser/issues/125)) ([08c0117](https://github.com/yargs/yargs-parser/commit/08c0117))
* array.type can now be provided, supporting coercion ([#132](https://github.com/yargs/yargs-parser/issues/132)) ([4b8cfce](https://github.com/yargs/yargs-parser/commit/4b8cfce))
### BREAKING CHANGES
* drops Node 4 support
* the argv object is now populated differently (correctly) when hyphens and dot notation are used in conjunction.
<a name="10.1.0"></a>
# [10.1.0](https://github.com/yargs/yargs-parser/compare/v10.0.0...v10.1.0) (2018-06-29)
### Features
* add `set-placeholder-key` configuration ([#123](https://github.com/yargs/yargs-parser/issues/123)) ([19386ee](https://github.com/yargs/yargs-parser/commit/19386ee))
<a name="10.0.0"></a>
# [10.0.0](https://github.com/yargs/yargs-parser/compare/v9.0.2...v10.0.0) (2018-04-04)
### Bug Fixes
* do not set boolean flags if not defined in `argv` ([#119](https://github.com/yargs/yargs-parser/issues/119)) ([f6e6599](https://github.com/yargs/yargs-parser/commit/f6e6599))
### BREAKING CHANGES
* `boolean` flags defined without a `default` value will now behave like other option type and won't be set in the parsed results when the user doesn't set the corresponding CLI arg.
Previous behavior:
```js
var parse = require('yargs-parser');
parse('--flag', {boolean: ['flag']});
// => { _: [], flag: true }
parse('--no-flag', {boolean: ['flag']});
// => { _: [], flag: false }
parse('', {boolean: ['flag']});
// => { _: [], flag: false }
```
New behavior:
```js
var parse = require('yargs-parser');
parse('--flag', {boolean: ['flag']});
// => { _: [], flag: true }
parse('--no-flag', {boolean: ['flag']});
// => { _: [], flag: false }
parse('', {boolean: ['flag']});
// => { _: [] } => flag not set similarly to other option type
```
<a name="9.0.2"></a>
## [9.0.2](https://github.com/yargs/yargs-parser/compare/v9.0.1...v9.0.2) (2018-01-20)
### Bug Fixes
* nargs was still aggressively consuming too many arguments ([9b28aad](https://github.com/yargs/yargs-parser/commit/9b28aad))
<a name="9.0.1"></a>
## [9.0.1](https://github.com/yargs/yargs-parser/compare/v9.0.0...v9.0.1) (2018-01-20)
### Bug Fixes
* nargs was consuming too many arguments ([4fef206](https://github.com/yargs/yargs-parser/commit/4fef206))
<a name="9.0.0"></a>
# [9.0.0](https://github.com/yargs/yargs-parser/compare/v8.1.0...v9.0.0) (2018-01-20)
### Features
* narg arguments no longer consume flag arguments ([#114](https://github.com/yargs/yargs-parser/issues/114)) ([60bb9b3](https://github.com/yargs/yargs-parser/commit/60bb9b3))
### BREAKING CHANGES
* arguments of form --foo, -abc, will no longer be consumed by nargs
<a name="8.1.0"></a>
# [8.1.0](https://github.com/yargs/yargs-parser/compare/v8.0.0...v8.1.0) (2017-12-20)
### Bug Fixes
* allow null config values ([#108](https://github.com/yargs/yargs-parser/issues/108)) ([d8b14f9](https://github.com/yargs/yargs-parser/commit/d8b14f9))
* ensure consistent parsing of dot-notation arguments ([#102](https://github.com/yargs/yargs-parser/issues/102)) ([c9bd79c](https://github.com/yargs/yargs-parser/commit/c9bd79c))
* implement [@antoniom](https://github.com/antoniom)'s fix for camel-case expansion ([3087e1d](https://github.com/yargs/yargs-parser/commit/3087e1d))
* only run coercion functions once, despite aliases. ([#76](https://github.com/yargs/yargs-parser/issues/76)) ([#103](https://github.com/yargs/yargs-parser/issues/103)) ([507aaef](https://github.com/yargs/yargs-parser/commit/507aaef))
* scientific notation circumvented bounds check ([#110](https://github.com/yargs/yargs-parser/issues/110)) ([3571f57](https://github.com/yargs/yargs-parser/commit/3571f57))
* tokenizer should ignore spaces at the beginning of the argString ([#106](https://github.com/yargs/yargs-parser/issues/106)) ([f34ead9](https://github.com/yargs/yargs-parser/commit/f34ead9))
### Features
* make combining arrays a configurable option ([#111](https://github.com/yargs/yargs-parser/issues/111)) ([c8bf536](https://github.com/yargs/yargs-parser/commit/c8bf536))
* merge array from arguments with array from config ([#83](https://github.com/yargs/yargs-parser/issues/83)) ([806ddd6](https://github.com/yargs/yargs-parser/commit/806ddd6))
<a name="8.0.0"></a>
# [8.0.0](https://github.com/yargs/yargs-parser/compare/v7.0.0...v8.0.0) (2017-10-05)
### Bug Fixes
* Ignore multiple spaces between arguments. ([#100](https://github.com/yargs/yargs-parser/issues/100)) ([d137227](https://github.com/yargs/yargs-parser/commit/d137227))
### Features
* allow configuration of prefix for boolean negation ([#94](https://github.com/yargs/yargs-parser/issues/94)) ([00bde7d](https://github.com/yargs/yargs-parser/commit/00bde7d))
* reworking how numbers are parsed ([#104](https://github.com/yargs/yargs-parser/issues/104)) ([fba00eb](https://github.com/yargs/yargs-parser/commit/fba00eb))
### BREAKING CHANGES
* strings that fail `Number.isSafeInteger()` are no longer coerced into numbers.
<a name="7.0.0"></a>
# [7.0.0](https://github.com/yargs/yargs-parser/compare/v6.0.1...v7.0.0) (2017-05-02)
### Chores
* revert populate-- logic ([#91](https://github.com/yargs/yargs-parser/issues/91)) ([6003e6d](https://github.com/yargs/yargs-parser/commit/6003e6d))
### BREAKING CHANGES
* populate-- now defaults to false.
<a name="6.0.1"></a>
## [6.0.1](https://github.com/yargs/yargs-parser/compare/v6.0.0...v6.0.1) (2017-05-01)
### Bug Fixes
* default '--' to undefined when not provided; this is closer to the array API ([#90](https://github.com/yargs/yargs-parser/issues/90)) ([4e739cc](https://github.com/yargs/yargs-parser/commit/4e739cc))
<a name="6.0.0"></a>
# [6.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v6.0.0) (2017-05-01)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
* parsing hints should apply for dot notation keys ([#86](https://github.com/yargs/yargs-parser/issues/86)) ([3e47d62](https://github.com/yargs/yargs-parser/commit/3e47d62))
### Chores
* upgrade to newest version of camelcase ([#87](https://github.com/yargs/yargs-parser/issues/87)) ([f1903aa](https://github.com/yargs/yargs-parser/commit/f1903aa))
### Features
* add -- option which allows arguments after the -- flag to be returned separated from positional arguments ([#84](https://github.com/yargs/yargs-parser/issues/84)) ([2572ca8](https://github.com/yargs/yargs-parser/commit/2572ca8))
* when parsing stops, we now populate "--" by default ([#88](https://github.com/yargs/yargs-parser/issues/88)) ([cd666db](https://github.com/yargs/yargs-parser/commit/cd666db))
### BREAKING CHANGES
* rather than placing arguments in "_", when parsing is stopped via "--"; we now populate an array called "--" by default.
* camelcase now requires Node 4+.
* environment variables will now override config files (args, env, config-file, config-object)
<a name="5.0.0"></a>
# [5.0.0](https://github.com/yargs/yargs-parser/compare/v4.2.1...v5.0.0) (2017-02-18)
### Bug Fixes
* environment variables should take precedence over config file ([#81](https://github.com/yargs/yargs-parser/issues/81)) ([76cee1f](https://github.com/yargs/yargs-parser/commit/76cee1f))
### BREAKING CHANGES
* environment variables will now override config files (args, env, config-file, config-object)
<a name="4.2.1"></a>
## [4.2.1](https://github.com/yargs/yargs-parser/compare/v4.2.0...v4.2.1) (2017-01-02)
### Bug Fixes
* flatten/duplicate regression ([#75](https://github.com/yargs/yargs-parser/issues/75)) ([68d68a0](https://github.com/yargs/yargs-parser/commit/68d68a0))
<a name="4.2.0"></a>
# [4.2.0](https://github.com/yargs/yargs-parser/compare/v4.1.0...v4.2.0) (2016-12-01)
### Bug Fixes
* inner objects in configs had their keys appended to top-level key when dot-notation was disabled ([#72](https://github.com/yargs/yargs-parser/issues/72)) ([0b1b5f9](https://github.com/yargs/yargs-parser/commit/0b1b5f9))
### Features
* allow multiple arrays to be provided, rather than always combining ([#71](https://github.com/yargs/yargs-parser/issues/71)) ([0f0fb2d](https://github.com/yargs/yargs-parser/commit/0f0fb2d))
<a name="4.1.0"></a>
# [4.1.0](https://github.com/yargs/yargs-parser/compare/v4.0.2...v4.1.0) (2016-11-07)
### Features
* apply coercions to default options ([#65](https://github.com/yargs/yargs-parser/issues/65)) ([c79052b](https://github.com/yargs/yargs-parser/commit/c79052b))
* handle dot notation boolean options ([#63](https://github.com/yargs/yargs-parser/issues/63)) ([02c3545](https://github.com/yargs/yargs-parser/commit/02c3545))
<a name="4.0.2"></a>
## [4.0.2](https://github.com/yargs/yargs-parser/compare/v4.0.1...v4.0.2) (2016-09-30)
### Bug Fixes
* whoops, let's make the assign not change the Object key order ([29d069a](https://github.com/yargs/yargs-parser/commit/29d069a))
<a name="4.0.1"></a>
## [4.0.1](https://github.com/yargs/yargs-parser/compare/v4.0.0...v4.0.1) (2016-09-30)
### Bug Fixes
* lodash.assign was deprecated ([#59](https://github.com/yargs/yargs-parser/issues/59)) ([5e7eb11](https://github.com/yargs/yargs-parser/commit/5e7eb11))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/yargs/yargs-parser/compare/v3.2.0...v4.0.0) (2016-09-26)
### Bug Fixes
* coerce should be applied to the final objects and arrays created ([#57](https://github.com/yargs/yargs-parser/issues/57)) ([4ca69da](https://github.com/yargs/yargs-parser/commit/4ca69da))
### BREAKING CHANGES
* coerce is no longer applied to individual arguments in an implicit array.
<a name="3.2.0"></a>
# [3.2.0](https://github.com/yargs/yargs-parser/compare/v3.1.0...v3.2.0) (2016-08-13)
### Features
* coerce full array instead of each element ([#51](https://github.com/yargs/yargs-parser/issues/51)) ([cc4dc56](https://github.com/yargs/yargs-parser/commit/cc4dc56))
<a name="3.1.0"></a>
# [3.1.0](https://github.com/yargs/yargs-parser/compare/v3.0.0...v3.1.0) (2016-08-09)
### Bug Fixes
* address pkgConf parsing bug outlined in [#37](https://github.com/yargs/yargs-parser/issues/37) ([#45](https://github.com/yargs/yargs-parser/issues/45)) ([be76ee6](https://github.com/yargs/yargs-parser/commit/be76ee6))
* better parsing of negative values ([#44](https://github.com/yargs/yargs-parser/issues/44)) ([2e43692](https://github.com/yargs/yargs-parser/commit/2e43692))
* check aliases when guessing defaults for arguments fixes [#41](https://github.com/yargs/yargs-parser/issues/41) ([#43](https://github.com/yargs/yargs-parser/issues/43)) ([f3e4616](https://github.com/yargs/yargs-parser/commit/f3e4616))
### Features
* added coerce option, for providing specialized argument parsing ([#42](https://github.com/yargs/yargs-parser/issues/42)) ([7b49cd2](https://github.com/yargs/yargs-parser/commit/7b49cd2))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/yargs/yargs-parser/compare/v2.4.1...v3.0.0) (2016-08-07)
### Bug Fixes
* parsing issue with numeric character in group of options ([#19](https://github.com/yargs/yargs-parser/issues/19)) ([f743236](https://github.com/yargs/yargs-parser/commit/f743236))
* upgraded lodash.assign ([5d7fdf4](https://github.com/yargs/yargs-parser/commit/5d7fdf4))
### BREAKING CHANGES
* subtle change to how values are parsed in a group of single-character arguments.
* _first released in 3.1.0, better handling of negative values should be considered a breaking change._
<a name="2.4.1"></a>
## [2.4.1](https://github.com/yargs/yargs-parser/compare/v2.4.0...v2.4.1) (2016-07-16)
### Bug Fixes
* **count:** do not increment a default value ([#39](https://github.com/yargs/yargs-parser/issues/39)) ([b04a189](https://github.com/yargs/yargs-parser/commit/b04a189))
<a name="2.4.0"></a>
# [2.4.0](https://github.com/yargs/yargs-parser/compare/v2.3.0...v2.4.0) (2016-04-11)
### Features
* **environment:** Support nested options in environment variables ([#26](https://github.com/yargs/yargs-parser/issues/26)) thanks [@elas7](https://github.com/elas7) \o/ ([020778b](https://github.com/yargs/yargs-parser/commit/020778b))
<a name="2.3.0"></a>
# [2.3.0](https://github.com/yargs/yargs-parser/compare/v2.2.0...v2.3.0) (2016-04-09)
### Bug Fixes
* **boolean:** fix for boolean options with non boolean defaults (#20) ([2dbe86b](https://github.com/yargs/yargs-parser/commit/2dbe86b)), closes [(#20](https://github.com/(/issues/20)
* **package:** remove tests from tarball ([0353c0d](https://github.com/yargs/yargs-parser/commit/0353c0d))
* **parsing:** handle calling short option with an empty string as the next value. ([a867165](https://github.com/yargs/yargs-parser/commit/a867165))
* boolean flag when next value contains the strings 'true' or 'false'. ([69941a6](https://github.com/yargs/yargs-parser/commit/69941a6))
* update dependencies; add standard-version bin for next release (#24) ([822d9d5](https://github.com/yargs/yargs-parser/commit/822d9d5))
### Features
* **configuration:** Allow to pass configuration objects to yargs-parser ([0780900](https://github.com/yargs/yargs-parser/commit/0780900))
* **normalize:** allow normalize to work with arrays ([e0eaa1a](https://github.com/yargs/yargs-parser/commit/e0eaa1a))
+14
View File
@@ -0,0 +1,14 @@
Copyright (c) 2016, Contributors
Permission to use, copy, modify, and/or distribute this software
for any purpose with or without fee is hereby granted, provided
that the above copyright notice and this permission notice
appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE
LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+449
View File
@@ -0,0 +1,449 @@
# yargs-parser
[![Build Status](https://travis-ci.org/yargs/yargs-parser.svg)](https://travis-ci.org/yargs/yargs-parser)
[![NPM version](https://img.shields.io/npm/v/yargs-parser.svg)](https://www.npmjs.com/package/yargs-parser)
[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
The mighty option parser used by [yargs](https://github.com/yargs/yargs).
visit the [yargs website](http://yargs.js.org/) for more examples, and thorough usage instructions.
<img width="250" src="https://raw.githubusercontent.com/yargs/yargs-parser/master/yargs-logo.png">
## Example
```sh
npm i yargs-parser --save
```
```js
var argv = require('yargs-parser')(process.argv.slice(2))
console.log(argv)
```
```sh
node example.js --foo=33 --bar hello
{ _: [], foo: 33, bar: 'hello' }
```
_or parse a string!_
```js
var argv = require('yargs-parser')('--foo=99 --bar=33')
console.log(argv)
```
```sh
{ _: [], foo: 99, bar: 33 }
```
Convert an array of mixed types before passing to `yargs-parser`:
```js
var parse = require('yargs-parser')
parse(['-f', 11, '--zoom', 55].join(' ')) // <-- array to string
parse(['-f', 11, '--zoom', 55].map(String)) // <-- array of strings
```
## API
### require('yargs-parser')(args, opts={})
Parses command line arguments returning a simple mapping of keys and values.
**expects:**
* `args`: a string or array of strings representing the options to parse.
* `opts`: provide a set of hints indicating how `args` should be parsed:
* `opts.alias`: an object representing the set of aliases for a key: `{alias: {foo: ['f']}}`.
* `opts.array`: indicate that keys should be parsed as an array: `{array: ['foo', 'bar']}`.<br>
Indicate that keys should be parsed as an array and coerced to booleans / numbers:<br>
`{array: [{ key: 'foo', boolean: true }, {key: 'bar', number: true}]}`.
* `opts.boolean`: arguments should be parsed as booleans: `{boolean: ['x', 'y']}`.
* `opts.coerce`: provide a custom synchronous function that returns a coerced value from the argument provided
(or throws an error). For arrays the function is called only once for the entire array:<br>
`{coerce: {foo: function (arg) {return modifiedArg}}}`.
* `opts.config`: indicate a key that represents a path to a configuration file (this file will be loaded and parsed).
* `opts.configObjects`: configuration objects to parse, their properties will be set as arguments:<br>
`{configObjects: [{'x': 5, 'y': 33}, {'z': 44}]}`.
* `opts.configuration`: provide configuration options to the yargs-parser (see: [configuration](#configuration)).
* `opts.count`: indicate a key that should be used as a counter, e.g., `-vvv` = `{v: 3}`.
* `opts.default`: provide default values for keys: `{default: {x: 33, y: 'hello world!'}}`.
* `opts.envPrefix`: environment variables (`process.env`) with the prefix provided should be parsed.
* `opts.narg`: specify that a key requires `n` arguments: `{narg: {x: 2}}`.
* `opts.normalize`: `path.normalize()` will be applied to values set to this key.
* `opts.number`: keys should be treated as numbers.
* `opts.string`: keys should be treated as strings (even if they resemble a number `-x 33`).
**returns:**
* `obj`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* [optional] `--`: an array with arguments after the end-of-options flag `--`.
### require('yargs-parser').detailed(args, opts={})
Parses a command line string, returning detailed information required by the
yargs engine.
**expects:**
* `args`: a string or array of strings representing options to parse.
* `opts`: provide a set of hints indicating how `args`, inputs are identical to `require('yargs-parser')(args, opts={})`.
**returns:**
* `argv`: an object representing the parsed value of `args`
* `key/value`: key value pairs for each argument and their aliases.
* `_`: an array representing the positional arguments.
* [optional] `--`: an array with arguments after the end-of-options flag `--`.
* `error`: populated with an error object if an exception occurred during parsing.
* `aliases`: the inferred list of aliases built by combining lists in `opts.alias`.
* `newAliases`: any new aliases added via camel-case expansion:
* `boolean`: `{ fooBar: true }`
* `defaulted`: any new argument created by `opts.default`, no aliases included.
* `boolean`: `{ foo: true }`
* `configuration`: given by default settings and `opts.configuration`.
<a name="configuration"></a>
### Configuration
The yargs-parser applies several automated transformations on the keys provided
in `args`. These features can be turned on and off using the `configuration` field
of `opts`.
```js
var parsed = parser(['--no-dice'], {
configuration: {
'boolean-negation': false
}
})
```
### short option groups
* default: `true`.
* key: `short-option-groups`.
Should a group of short-options be treated as boolean flags?
```sh
node example.js -abc
{ _: [], a: true, b: true, c: true }
```
_if disabled:_
```sh
node example.js -abc
{ _: [], abc: true }
```
### camel-case expansion
* default: `true`.
* key: `camel-case-expansion`.
Should hyphenated arguments be expanded into camel-case aliases?
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true, fooBar: true }
```
_if disabled:_
```sh
node example.js --foo-bar
{ _: [], 'foo-bar': true }
```
### dot-notation
* default: `true`
* key: `dot-notation`
Should keys that contain `.` be treated as objects?
```sh
node example.js --foo.bar
{ _: [], foo: { bar: true } }
```
_if disabled:_
```sh
node example.js --foo.bar
{ _: [], "foo.bar": true }
```
### parse numbers
* default: `true`
* key: `parse-numbers`
Should keys that look like numbers be treated as such?
```sh
node example.js --foo=99.3
{ _: [], foo: 99.3 }
```
_if disabled:_
```sh
node example.js --foo=99.3
{ _: [], foo: "99.3" }
```
### boolean negation
* default: `true`
* key: `boolean-negation`
Should variables prefixed with `--no` be treated as negations?
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if disabled:_
```sh
node example.js --no-foo
{ _: [], "no-foo": true }
```
### combine arrays
* default: `false`
* key: `combine-arrays`
Should arrays be combined when provided by both command line arguments and
a configuration file.
### duplicate arguments array
* default: `true`
* key: `duplicate-arguments-array`
Should arguments be coerced into an array when duplicated:
```sh
node example.js -x 1 -x 2
{ _: [], x: [1, 2] }
```
_if disabled:_
```sh
node example.js -x 1 -x 2
{ _: [], x: 2 }
```
### flatten duplicate arrays
* default: `true`
* key: `flatten-duplicate-arrays`
Should array arguments be coerced into a single array when duplicated:
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [1, 2, 3, 4] }
```
_if disabled:_
```sh
node example.js -x 1 2 -x 3 4
{ _: [], x: [[1, 2], [3, 4]] }
```
### greedy arrays
* default: `true`
* key: `greedy-arrays`
Should arrays consume more than one positional argument following their flag.
```sh
node example --arr 1 2
{ _[], arr: [1, 2] }
```
_if disabled:_
```sh
node example --arr 1 2
{ _[2], arr: [1] }
```
**Note: in `v18.0.0` we are considering defaulting greedy arrays to `false`.**
### nargs eats options
* default: `false`
* key: `nargs-eats-options`
Should nargs consume dash options as well as positional arguments.
### negation prefix
* default: `no-`
* key: `negation-prefix`
The prefix to use for negated boolean variables.
```sh
node example.js --no-foo
{ _: [], foo: false }
```
_if set to `quux`:_
```sh
node example.js --quuxfoo
{ _: [], foo: false }
```
### populate --
* default: `false`.
* key: `populate--`
Should unparsed flags be stored in `--` or `_`.
_If disabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a', 'x', 'y' ], b: true }
```
_If enabled:_
```sh
node example.js a -b -- x y
{ _: [ 'a' ], '--': [ 'x', 'y' ], b: true }
```
### set placeholder key
* default: `false`.
* key: `set-placeholder-key`.
Should a placeholder be added for keys not set via the corresponding CLI argument?
_If disabled:_
```sh
node example.js -a 1 -c 2
{ _: [], a: 1, c: 2 }
```
_If enabled:_
```sh
node example.js -a 1 -c 2
{ _: [], a: 1, b: undefined, c: 2 }
```
### halt at non-option
* default: `false`.
* key: `halt-at-non-option`.
Should parsing stop at the first positional argument? This is similar to how e.g. `ssh` parses its command line.
_If disabled:_
```sh
node example.js -a run b -x y
{ _: [ 'b' ], a: 'run', x: 'y' }
```
_If enabled:_
```sh
node example.js -a run b -x y
{ _: [ 'b', '-x', 'y' ], a: 'run' }
```
### strip aliased
* default: `false`
* key: `strip-aliased`
Should aliases be removed before returning results?
_If disabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1, 'test-alias': 1, testAlias: 1 }
```
_If enabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1 }
```
### strip dashed
* default: `false`
* key: `strip-dashed`
Should dashed keys be removed before returning results? This option has no effect if
`camel-case-expansion` is disabled.
_If disabled:_
```sh
node example.js --test-field 1
{ _: [], 'test-field': 1, testField: 1 }
```
_If enabled:_
```sh
node example.js --test-field 1
{ _: [], testField: 1 }
```
### unknown options as args
* default: `false`
* key: `unknown-options-as-args`
Should unknown options be treated like regular arguments? An unknown option is one that is not
configured in `opts`.
_If disabled_
```sh
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: [], unknownOption: true, knownOption: 2, stringOption: '', unknownOption2: true }
```
_If enabled_
```sh
node example.js --unknown-option --known-option 2 --string-option --unknown-option2
{ _: ['--unknown-option'], knownOption: 2, stringOption: '--unknown-option2' }
```
## Special Thanks
The yargs project evolves from optimist and minimist. It owes its
existence to a lot of James Halliday's hard work. Thanks [substack](https://github.com/substack) **beep** **boop** \o/
## License
ISC
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,40 @@
// take an un-split argv string and tokenize it.
module.exports = function (argString) {
if (Array.isArray(argString)) {
return argString.map(e => typeof e !== 'string' ? e + '' : e)
}
argString = argString.trim()
let i = 0
let prevC = null
let c = null
let opening = null
const args = []
for (let ii = 0; ii < argString.length; ii++) {
prevC = c
c = argString.charAt(ii)
// split on spaces unless we're in quotes.
if (c === ' ' && !opening) {
if (!(prevC === ' ')) {
i++
}
continue
}
// don't split the string if we're in matching
// opening or closing single and double quotes.
if (c === opening) {
opening = null
} else if ((c === "'" || c === '"') && !opening) {
opening = c
}
if (!args[i]) args[i] = ''
args[i] += c
}
return args
}
+46
View File
@@ -0,0 +1,46 @@
{
"name": "yargs-parser",
"version": "18.1.3",
"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"
},
"repository": {
"type": "git",
"url": "https://github.com/yargs/yargs-parser.git"
},
"keywords": [
"argument",
"parser",
"yargs",
"command",
"cli",
"parsing",
"option",
"args",
"argument"
],
"author": "Ben Coe <ben@npmjs.com>",
"license": "ISC",
"devDependencies": {
"c8": "^7.0.1",
"chai": "^4.2.0",
"mocha": "^7.0.0",
"standard": "^14.3.1"
},
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"files": [
"lib",
"index.js"
],
"engines": {
"node": ">=6"
}
}
+420
View File
@@ -0,0 +1,420 @@
# Changelog
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
## [15.4.0](https://www.github.com/yargs/yargs/compare/v15.3.1...v15.4.0) (2020-06-30)
### Features
* adds deprecation option for commands ([027a636](https://www.github.com/yargs/yargs/commit/027a6365b737e13116811a8ef43670196e1fa00a))
* support array of examples ([#1682](https://www.github.com/yargs/yargs/issues/1682)) ([225ab82](https://www.github.com/yargs/yargs/commit/225ab8271938bed3a48d23175f3d580ce8cd1306))
### Bug Fixes
* **docs:** describe usage of `.check()` in more detail ([932cd11](https://www.github.com/yargs/yargs/commit/932cd1177e93f5cc99edfe57a4028e30717bf8fb))
* **i18n:** Japanese translation phrasing ([#1619](https://www.github.com/yargs/yargs/issues/1619)) ([0894175](https://www.github.com/yargs/yargs/commit/089417550ef5a5b8ce3578dd2a989191300b64cd))
* **strict mode:** report default command unknown arguments ([#1626](https://www.github.com/yargs/yargs/issues/1626)) ([69f29a9](https://www.github.com/yargs/yargs/commit/69f29a9cd429d4bb99481238305390107ac75b02))
* **usage:** translate 'options' group only when displaying help ([#1600](https://www.github.com/yargs/yargs/issues/1600)) ([e60b39b](https://www.github.com/yargs/yargs/commit/e60b39b9d3a912c06db43f87c86ba894142b6c1c))
### Reverts
* Revert "chore(deps): update dependency eslint to v7 (#1656)" (#1673) ([34949f8](https://www.github.com/yargs/yargs/commit/34949f89ee7cdf88f7b315659df4b5f62f714842)), closes [#1656](https://www.github.com/yargs/yargs/issues/1656) [#1673](https://www.github.com/yargs/yargs/issues/1673)
### [15.3.1](https://www.github.com/yargs/yargs/compare/v15.3.0...v15.3.1) (2020-03-16)
### Bug Fixes
* \_\_proto\_\_ will now be replaced with \_\_\_proto\_\_\_ in parse ([#258](https://www.github.com/yargs/yargs-parser/issues/258)), patching a potential
prototype pollution vulnerability. This was reported by the Snyk Security Research Team. ([63810ca](https://www.github.com/yargs/yargs-parser/commit/63810ca1ae1a24b08293a4d971e70e058c7a41e2))
## [15.3.0](https://www.github.com/yargs/yargs/compare/v15.2.0...v15.3.0) (2020-03-08)
### Features
* **yargs-parser:** introduce single-digit boolean aliases ([#1576](https://www.github.com/yargs/yargs/issues/1576)) ([3af7f04](https://www.github.com/yargs/yargs/commit/3af7f04cdbfcbd4b3f432aca5144d43f21958c39))
* add usage for single-digit boolean aliases ([#1580](https://www.github.com/yargs/yargs/issues/1580)) ([6014e39](https://www.github.com/yargs/yargs/commit/6014e39bca3a1e8445aa0fb2a435f6181e344c45))
### Bug Fixes
* address ambiguity between nargs of 1 and requiresArg ([#1572](https://www.github.com/yargs/yargs/issues/1572)) ([a5edc32](https://www.github.com/yargs/yargs/commit/a5edc328ecb3f90d1ba09cfe70a0040f68adf50a))
## [15.2.0](https://www.github.com/yargs/yargs/compare/v15.1.0...v15.2.0) (2020-03-01)
### ⚠ BREAKING CHANGES
* **deps:** yargs-parser@17.0.0 no longer implicitly creates arrays out of boolean
arguments when duplicates are provided
### Features
* **completion:** takes negated flags into account when boolean-negation is set ([#1509](https://www.github.com/yargs/yargs/issues/1509)) ([7293ad5](https://www.github.com/yargs/yargs/commit/7293ad50d20ea0fb7dd1ac9b925e90e1bd95dea8))
* **deps:** pull in yargs-parser@17.0.0 ([#1553](https://www.github.com/yargs/yargs/issues/1553)) ([b9409da](https://www.github.com/yargs/yargs/commit/b9409da199ebca515a848489c206b807fab2e65d))
* deprecateOption ([#1559](https://www.github.com/yargs/yargs/issues/1559)) ([8aae333](https://www.github.com/yargs/yargs/commit/8aae3332251d09fa136db17ef4a40d83fa052bc4))
* display appropriate $0 for electron apps ([#1536](https://www.github.com/yargs/yargs/issues/1536)) ([d0e4379](https://www.github.com/yargs/yargs/commit/d0e437912917d6a66bb5128992fa2f566a5f830b))
* introduces strictCommands() subset of strict mode ([#1540](https://www.github.com/yargs/yargs/issues/1540)) ([1d4cca3](https://www.github.com/yargs/yargs/commit/1d4cca395a98b395e6318f0505fc73bef8b01350))
* **deps:** yargs-parser with 'greedy-array' configuration ([#1569](https://www.github.com/yargs/yargs/issues/1569)) ([a03a320](https://www.github.com/yargs/yargs/commit/a03a320dbf5c0ce33d829a857fc04a651c0bb53e))
### Bug Fixes
* help always displayed for the first command parsed having an async handler ([#1535](https://www.github.com/yargs/yargs/issues/1535)) ([d585b30](https://www.github.com/yargs/yargs/commit/d585b303a43746201b05c9c9fda94a444634df33))
* **deps:** fix enumeration for normalized path arguments ([#1567](https://www.github.com/yargs/yargs/issues/1567)) ([0b5b1b0](https://www.github.com/yargs/yargs/commit/0b5b1b0e5f4f9baf393c48e9cc2bc85c1b67a47a))
* **locales:** only translate default option group name ([acc16de](https://www.github.com/yargs/yargs/commit/acc16de6b846ea7332db753646a9cec76b589162))
* **locales:** remove extra space in French for 'default' ([#1564](https://www.github.com/yargs/yargs/issues/1564)) ([ecfc2c4](https://www.github.com/yargs/yargs/commit/ecfc2c474575c6cdbc6d273c94c13181bd1dbaa6))
* **translations:** add French translation for unknown command ([#1563](https://www.github.com/yargs/yargs/issues/1563)) ([18b0b75](https://www.github.com/yargs/yargs/commit/18b0b752424bf560271e670ff95a0f90c8386787))
* **translations:** fix pluralization in error messages. ([#1557](https://www.github.com/yargs/yargs/issues/1557)) ([94fa38c](https://www.github.com/yargs/yargs/commit/94fa38cbab8d86943e87bf41d368ed56dffa6835))
* **yargs:** correct support of bundled electron apps ([#1554](https://www.github.com/yargs/yargs/issues/1554)) ([a0b61ac](https://www.github.com/yargs/yargs/commit/a0b61ac21e2b554aa73dbf1a66d4a7af94047c2f))
## [15.1.0](https://www.github.com/yargs/yargs/compare/v15.0.2...v15.1.0) (2020-01-02)
### Features
* **lang:** add Finnish localization (language code fi) ([222c8fe](https://www.github.com/yargs/yargs/commit/222c8fef2e2ad46e314c337dec96940f896bec35))
* complete short options with a single dash ([#1507](https://www.github.com/yargs/yargs/issues/1507)) ([99011ab](https://www.github.com/yargs/yargs/commit/99011ab5ba90232506ece0a17e59e2001a1ab562))
* onFinishCommand handler ([#1473](https://www.github.com/yargs/yargs/issues/1473)) ([fe380cd](https://www.github.com/yargs/yargs/commit/fe380cd356aa33aef0449facd59c22cab8930ac9))
### Bug Fixes
* getCompletion() was not working for options ([#1495](https://www.github.com/yargs/yargs/issues/1495)) ([463feb2](https://www.github.com/yargs/yargs/commit/463feb2870158eb9df670222b0f0a40a05cf18d0))
* misspelling of package.json `engines` field ([0891d0e](https://www.github.com/yargs/yargs/commit/0891d0ed35b30c83a6d9e9f6a5c5f84d13c546a0))
* populate positionals when unknown-options-as-args is set ([#1508](https://www.github.com/yargs/yargs/issues/1508)) ([bb0f2eb](https://www.github.com/yargs/yargs/commit/bb0f2eb996fa4e19d330b31a01c2036cafa99a7e)), closes [#1444](https://www.github.com/yargs/yargs/issues/1444)
* show 2 dashes on help for single digit option key or alias ([#1493](https://www.github.com/yargs/yargs/issues/1493)) ([63b3dd3](https://www.github.com/yargs/yargs/commit/63b3dd31a455d428902220c1992ae930e18aff5c))
* **docs:** use recommended cjs import syntax for ts examples ([#1513](https://www.github.com/yargs/yargs/issues/1513)) ([f9a18bf](https://www.github.com/yargs/yargs/commit/f9a18bfd624a5013108084f690cd8a1de794c430))
### [15.0.2](https://www.github.com/yargs/yargs/compare/v15.0.1...v15.0.2) (2019-11-19)
### Bug Fixes
* temporary fix for libraries that call Object.freeze() ([#1483](https://www.github.com/yargs/yargs/issues/1483)) ([99c2dc8](https://www.github.com/yargs/yargs/commit/99c2dc850e67c606644f8b0c0bca1a59c87dcbcd))
### [15.0.1](https://www.github.com/yargs/yargs/compare/v15.0.0...v15.0.1) (2019-11-16)
### Bug Fixes
* **deps:** cliui, find-up, and string-width, all drop Node 6 support ([#1479](https://www.github.com/yargs/yargs/issues/1479)) ([6a9ebe2](https://www.github.com/yargs/yargs/commit/6a9ebe2d955e3e979e76c07ffbb1c17fef64cb49))
## [15.0.0](https://www.github.com/yargs/yargs/compare/v14.2.0...v15.0.0) (2019-11-10)
### ⚠ BREAKING CHANGES
* **deps:** yargs-parser now throws on invalid combinations of config (#1470)
* yargs-parser@16.0.0 drops support for Node 6
* drop Node 6 support (#1461)
* remove package.json-based parserConfiguration (#1460)
### Features
* **deps:** yargs-parser now throws on invalid combinations of config ([#1470](https://www.github.com/yargs/yargs/issues/1470)) ([c10c38c](https://www.github.com/yargs/yargs/commit/c10c38cca04298f96b55a7e374a9a134abefffa7))
* expose `Parser` from `require('yargs/yargs')` ([#1477](https://www.github.com/yargs/yargs/issues/1477)) ([1840ba2](https://www.github.com/yargs/yargs/commit/1840ba22f1a24c0ece8e32bbd31db4134a080aee))
### Bug Fixes
* **docs:** TypeScript import to prevent a future major release warning ([#1441](https://www.github.com/yargs/yargs/issues/1441)) ([b1b156a](https://www.github.com/yargs/yargs/commit/b1b156a3eb4ddd6803fbbd56c611a77919293000))
* stop-parse was not being respected by commands ([#1459](https://www.github.com/yargs/yargs/issues/1459)) ([12c82e6](https://www.github.com/yargs/yargs/commit/12c82e62663e928148a7ee2f51629aa26a0f9bb2))
* update to yargs-parser with fix for array default values ([#1463](https://www.github.com/yargs/yargs/issues/1463)) ([ebee59d](https://www.github.com/yargs/yargs/commit/ebee59d9022da538410e69a5c025019ed46d13d2))
* **docs:** update boolean description and examples in docs ([#1474](https://www.github.com/yargs/yargs/issues/1474)) ([afd5b48](https://www.github.com/yargs/yargs/commit/afd5b4871bfeb90d58351ac56c5c44a83ef033e6))
### Miscellaneous Chores
* drop Node 6 support ([#1461](https://www.github.com/yargs/yargs/issues/1461)) ([2ba8ce0](https://www.github.com/yargs/yargs/commit/2ba8ce05e8fefbeffc6cb7488d9ebf6e86cceb1d))
### Code Refactoring
* remove package.json-based parserConfiguration ([#1460](https://www.github.com/yargs/yargs/issues/1460)) ([0d3642b](https://www.github.com/yargs/yargs/commit/0d3642b6f829b637938774c0c6ce5f6bfe1afa51))
## [14.2.0](https://github.com/yargs/yargs/compare/v14.1.0...v14.2.0) (2019-10-07)
### Bug Fixes
* async middleware was called twice ([#1422](https://github.com/yargs/yargs/issues/1422)) ([9a42b63](https://github.com/yargs/yargs/commit/9a42b63))
* fix promise check to accept any spec conform object ([#1424](https://github.com/yargs/yargs/issues/1424)) ([0be43d2](https://github.com/yargs/yargs/commit/0be43d2))
* groups were not being maintained for nested commands ([#1430](https://github.com/yargs/yargs/issues/1430)) ([d38650e](https://github.com/yargs/yargs/commit/d38650e))
* **docs:** broken markdown link ([#1426](https://github.com/yargs/yargs/issues/1426)) ([236e24e](https://github.com/yargs/yargs/commit/236e24e))
* support merging deeply nested configuration ([#1423](https://github.com/yargs/yargs/issues/1423)) ([bae66fe](https://github.com/yargs/yargs/commit/bae66fe))
### Features
* **deps:** introduce yargs-parser with support for unknown-options-as-args ([#1440](https://github.com/yargs/yargs/issues/1440)) ([4d21520](https://github.com/yargs/yargs/commit/4d21520))
## [14.1.0](https://github.com/yargs/yargs/compare/v14.0.0...v14.1.0) (2019-09-06)
### Bug Fixes
* **docs:** fix incorrect parserConfiguration documentation ([2a99124](https://github.com/yargs/yargs/commit/2a99124))
* detect zsh when zsh isnt run as a login prompt ([#1395](https://github.com/yargs/yargs/issues/1395)) ([8792d13](https://github.com/yargs/yargs/commit/8792d13))
* populate correct value on yargs.parsed and stop warning on access ([#1412](https://github.com/yargs/yargs/issues/1412)) ([bb0eb52](https://github.com/yargs/yargs/commit/bb0eb52))
* showCompletionScript was logging script twice ([#1388](https://github.com/yargs/yargs/issues/1388)) ([07c8537](https://github.com/yargs/yargs/commit/07c8537))
* strict() should not ignore hyphenated arguments ([#1414](https://github.com/yargs/yargs/issues/1414)) ([b774b5e](https://github.com/yargs/yargs/commit/b774b5e))
* **docs:** formalize existing callback argument to showHelp ([#1386](https://github.com/yargs/yargs/issues/1386)) ([d217764](https://github.com/yargs/yargs/commit/d217764))
### Features
* make it possible to merge configurations when extending other config. ([#1411](https://github.com/yargs/yargs/issues/1411)) ([5d7ad98](https://github.com/yargs/yargs/commit/5d7ad98))
## [14.0.0](https://github.com/yargs/yargs/compare/v13.3.0...v14.0.0) (2019-07-30)
### ⚠ BREAKING CHANGES
* we now only officially support yargs.$0 parameter and discourage direct access to yargs.parsed
* previously to this fix methods like `yargs.getOptions()` contained the state of the last command to execute.
* do not allow additional positionals in strict mode
### Bug Fixes
* calling parse multiple times now appropriately maintains state ([#1137](https://github.com/yargs/yargs/issues/1137)) ([#1369](https://github.com/yargs/yargs/issues/1369)) ([026b151](https://github.com/yargs/yargs/commit/026b151))
* prefer user supplied script name in usage ([#1383](https://github.com/yargs/yargs/issues/1383)) ([28c74b9](https://github.com/yargs/yargs/commit/28c74b9))
* **deps:** use decamelize from npm instead of vendored copy ([#1377](https://github.com/yargs/yargs/issues/1377)) ([015eeb9](https://github.com/yargs/yargs/commit/015eeb9))
* **examples:** fix usage-options.js to reflect current API ([#1375](https://github.com/yargs/yargs/issues/1375)) ([6e5b76b](https://github.com/yargs/yargs/commit/6e5b76b))
* do not allow additional positionals in strict mode ([35d777c](https://github.com/yargs/yargs/commit/35d777c))
* properties accessed on singleton now reflect current state of instance ([#1366](https://github.com/yargs/yargs/issues/1366)) ([409d35b](https://github.com/yargs/yargs/commit/409d35b))
* tolerate null prototype for config objects with `extends` ([#1376](https://github.com/yargs/yargs/issues/1376)) ([3d26d11](https://github.com/yargs/yargs/commit/3d26d11)), closes [#1372](https://github.com/yargs/yargs/issues/1372)
* yargs.parsed now populated before returning, when yargs.parse() called with no args (#1382) ([e3981fd](https://github.com/yargs/yargs/commit/e3981fd)), closes [#1382](https://github.com/yargs/yargs/issues/1382)
### Features
* adds support for multiple epilog messages ([#1384](https://github.com/yargs/yargs/issues/1384)) ([07a5554](https://github.com/yargs/yargs/commit/07a5554))
* allow completionCommand to be set via showCompletionScript ([#1385](https://github.com/yargs/yargs/issues/1385)) ([5562853](https://github.com/yargs/yargs/commit/5562853))
## [13.3.0](https://www.github.com/yargs/yargs/compare/v13.2.4...v13.3.0) (2019-06-10)
### Bug Fixes
* **deps:** yargs-parser update addressing several parsing bugs ([#1357](https://www.github.com/yargs/yargs/issues/1357)) ([e230d5b](https://www.github.com/yargs/yargs/commit/e230d5b))
### Features
* **i18n:** swap out os-locale dependency for simple inline implementation ([#1356](https://www.github.com/yargs/yargs/issues/1356)) ([4dfa19b](https://www.github.com/yargs/yargs/commit/4dfa19b))
* support defaultDescription for positional arguments ([812048c](https://www.github.com/yargs/yargs/commit/812048c))
### [13.2.4](https://github.com/yargs/yargs/compare/v13.2.3...v13.2.4) (2019-05-13)
### Bug Fixes
* **i18n:** rename unclear 'implication failed' to 'missing dependent arguments' ([#1317](https://github.com/yargs/yargs/issues/1317)) ([bf46813](https://github.com/yargs/yargs/commit/bf46813))
### [13.2.3](https://github.com/yargs/yargs/compare/v13.2.2...v13.2.3) (2019-05-05)
### Bug Fixes
* **deps:** upgrade cliui for compatibility with latest chalk. ([#1330](https://github.com/yargs/yargs/issues/1330)) ([b20db65](https://github.com/yargs/yargs/commit/b20db65))
* address issues with dutch translation ([#1316](https://github.com/yargs/yargs/issues/1316)) ([0295132](https://github.com/yargs/yargs/commit/0295132))
### Tests
* accept differently formatted output ([#1327](https://github.com/yargs/yargs/issues/1327)) ([c294d1b](https://github.com/yargs/yargs/commit/c294d1b))
## [13.2.2](https://github.com/yargs/yargs/compare/v13.2.1...v13.2.2) (2019-03-06)
## [13.2.1](https://github.com/yargs/yargs/compare/v13.2.0...v13.2.1) (2019-02-18)
### Bug Fixes
* add zsh script to files array ([3180224](https://github.com/yargs/yargs/commit/3180224))
* support options/sub-commands in zsh completion ([0a96394](https://github.com/yargs/yargs/commit/0a96394))
# [13.2.0](https://github.com/yargs/yargs/compare/v13.1.0...v13.2.0) (2019-02-15)
### Features
* zsh auto completion ([#1292](https://github.com/yargs/yargs/issues/1292)) ([16c5d25](https://github.com/yargs/yargs/commit/16c5d25)), closes [#1156](https://github.com/yargs/yargs/issues/1156)
<a name="13.1.0"></a>
# [13.1.0](https://github.com/yargs/yargs/compare/v13.0.0...v13.1.0) (2019-02-12)
### Features
* add applyBeforeValidation, for applying sync middleware before validation ([5be206a](https://github.com/yargs/yargs/commit/5be206a))
<a name="13.0.0"></a>
# [13.0.0](https://github.com/yargs/yargs/compare/v12.0.5...v13.0.0) (2019-02-02)
### Bug Fixes
* **deps:** Update os-locale to avoid security vulnerability ([#1270](https://github.com/yargs/yargs/issues/1270)) ([27bf739](https://github.com/yargs/yargs/commit/27bf739))
* **validation:** Use the error as a message when none exists otherwise ([#1268](https://github.com/yargs/yargs/issues/1268)) ([0510fe6](https://github.com/yargs/yargs/commit/0510fe6))
* better bash path completion ([#1272](https://github.com/yargs/yargs/issues/1272)) ([da75ea2](https://github.com/yargs/yargs/commit/da75ea2))
* middleware added multiple times due to reference bug ([#1282](https://github.com/yargs/yargs/issues/1282)) ([64af518](https://github.com/yargs/yargs/commit/64af518))
### Chores
* ~drop Node 6 from testing matrix ([#1287](https://github.com/yargs/yargs/issues/1287)) ([ef16792](https://github.com/yargs/yargs/commit/ef16792))~
* _opting to not drop Node 6 support until April, [see](https://github.com/nodejs/Release)._
* update dependencies ([#1284](https://github.com/yargs/yargs/issues/1284)) ([f25de4f](https://github.com/yargs/yargs/commit/f25de4f))
### Features
* Add `.parserConfiguration()` method, deprecating package.json config ([#1262](https://github.com/yargs/yargs/issues/1262)) ([3c6869a](https://github.com/yargs/yargs/commit/3c6869a))
* adds config option for sorting command output ([#1256](https://github.com/yargs/yargs/issues/1256)) ([6916ce9](https://github.com/yargs/yargs/commit/6916ce9))
* options/positionals with leading '+' and '0' no longer parse as numbers ([#1286](https://github.com/yargs/yargs/issues/1286)) ([e9dc3aa](https://github.com/yargs/yargs/commit/e9dc3aa))
* support promises in middleware ([f3a4e4f](https://github.com/yargs/yargs/commit/f3a4e4f))
### BREAKING CHANGES
* options with leading '+' or '0' now parse as strings
* dropping Node 6 which hits end of life in April 2019
* see [yargs-parser@12.0.0 CHANGELOG](https://github.com/yargs/yargs-parser/blob/master/CHANGELOG.md#breaking-changes)
* we now warn if the yargs stanza package.json is used.
<a name="12.0.5"></a>
## [12.0.5](https://github.com/yargs/yargs/compare/v12.0.4...v12.0.5) (2018-11-19)
### Bug Fixes
* allows camel-case, variadic arguments, and strict mode to be combined ([#1247](https://github.com/yargs/yargs/issues/1247)) ([eacc035](https://github.com/yargs/yargs/commit/eacc035))
<a name="12.0.4"></a>
## [12.0.4](https://github.com/yargs/yargs/compare/v12.0.3...v12.0.4) (2018-11-10)
### Bug Fixes
* don't load config when processing positionals ([5d0dc92](https://github.com/yargs/yargs/commit/5d0dc92))
<a name="12.0.3"></a>
## [12.0.3](https://github.com/yargs/yargs/compare/v12.0.2...v12.0.3) (2018-10-06)
### Bug Fixes
* $0 contains first arg in bundled electron apps ([#1206](https://github.com/yargs/yargs/issues/1206)) ([567820b](https://github.com/yargs/yargs/commit/567820b))
* accept single function for middleware ([66fd6f7](https://github.com/yargs/yargs/commit/66fd6f7)), closes [#1214](https://github.com/yargs/yargs/issues/1214) [#1214](https://github.com/yargs/yargs/issues/1214)
* hide `hidden` options from help output even if they are in a group ([#1221](https://github.com/yargs/yargs/issues/1221)) ([da54028](https://github.com/yargs/yargs/commit/da54028))
* improve Norwegian Bokmål translations ([#1208](https://github.com/yargs/yargs/issues/1208)) ([a458fa4](https://github.com/yargs/yargs/commit/a458fa4))
* improve Norwegian Nynorsk translations ([#1207](https://github.com/yargs/yargs/issues/1207)) ([d422eb5](https://github.com/yargs/yargs/commit/d422eb5))
<a name="12.0.2"></a>
## [12.0.2](https://github.com/yargs/yargs/compare/v12.0.1...v12.0.2) (2018-09-04)
### Bug Fixes
* middleware should work regardless of when method is called ([664b265](https://github.com/yargs/yargs/commit/664b265)), closes [#1178](https://github.com/yargs/yargs/issues/1178)
* translation not working when using __ with a single parameter ([#1183](https://github.com/yargs/yargs/issues/1183)) ([f449aea](https://github.com/yargs/yargs/commit/f449aea))
* upgrade os-locale to version that addresses license issue ([#1195](https://github.com/yargs/yargs/issues/1195)) ([efc0970](https://github.com/yargs/yargs/commit/efc0970))
<a name="12.0.1"></a>
## [12.0.1](https://github.com/yargs/yargs/compare/v12.0.0...v12.0.1) (2018-06-29)
<a name="12.0.0"></a>
# [12.0.0](https://github.com/yargs/yargs/compare/v11.1.0...v12.0.0) (2018-06-26)
### Bug Fixes
* .argv and .parse() now invoke identical code path ([#1126](https://github.com/yargs/yargs/issues/1126)) ([f13ebf4](https://github.com/yargs/yargs/commit/f13ebf4))
* remove the trailing white spaces from the help output ([#1090](https://github.com/yargs/yargs/issues/1090)) ([3f0746c](https://github.com/yargs/yargs/commit/3f0746c))
* **completion:** Avoid default command and recommendations during completion ([#1123](https://github.com/yargs/yargs/issues/1123)) ([036e7c5](https://github.com/yargs/yargs/commit/036e7c5))
### Chores
* test Node.js 6, 8 and 10 ([#1160](https://github.com/yargs/yargs/issues/1160)) ([84f9d2b](https://github.com/yargs/yargs/commit/84f9d2b))
* upgrade to version of yargs-parser that does not populate value for unset boolean ([#1104](https://github.com/yargs/yargs/issues/1104)) ([d4705f4](https://github.com/yargs/yargs/commit/d4705f4))
### Features
* add support for global middleware, useful for shared tasks like metrics ([#1119](https://github.com/yargs/yargs/issues/1119)) ([9d71ac7](https://github.com/yargs/yargs/commit/9d71ac7))
* allow setting scriptName $0 ([#1143](https://github.com/yargs/yargs/issues/1143)) ([a2f2eae](https://github.com/yargs/yargs/commit/a2f2eae))
* remove `setPlaceholderKeys` ([#1105](https://github.com/yargs/yargs/issues/1105)) ([6ee2c82](https://github.com/yargs/yargs/commit/6ee2c82))
### BREAKING CHANGES
* Options absent from `argv` (not set via CLI argument) are now absent from the parsed result object rather than being set with `undefined`
* drop Node 4 from testing matrix, such that we'll gradually start drifting away from supporting Node 4.
* yargs-parser does not populate 'false' when boolean flag is not passed
* tests that assert against help output will need to be updated
<a name="11.1.0"></a>
# [11.1.0](https://github.com/yargs/yargs/compare/v11.0.0...v11.1.0) (2018-03-04)
### Bug Fixes
* choose correct config directory when require.main does not exist ([#1056](https://github.com/yargs/yargs/issues/1056)) ([a04678c](https://github.com/yargs/yargs/commit/a04678c))
### Features
* allow hidden options to be displayed with --show-hidden ([#1061](https://github.com/yargs/yargs/issues/1061)) ([ea862ae](https://github.com/yargs/yargs/commit/ea862ae))
* extend *.rc files in addition to json ([#1080](https://github.com/yargs/yargs/issues/1080)) ([11691a6](https://github.com/yargs/yargs/commit/11691a6))
<a name="11.0.0"></a>
# [11.0.0](https://github.com/yargs/yargs/compare/v10.1.2...v11.0.0) (2018-01-22)
### Bug Fixes
* Set implicit nargs=1 when type=number requiresArg=true ([#1050](https://github.com/yargs/yargs/issues/1050)) ([2b56812](https://github.com/yargs/yargs/commit/2b56812))
### Features
* requiresArg is now simply an alias for nargs(1) ([#1054](https://github.com/yargs/yargs/issues/1054)) ([a3ddacc](https://github.com/yargs/yargs/commit/a3ddacc))
### BREAKING CHANGES
* requiresArg now has significantly different error output, matching nargs.
[Historical Versions](/docs/CHANGELOG-historical.md)
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright 2010 James Halliday (mail@substack.net); Modified work Copyright 2014 Contributors (ben@npmjs.com)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
+140
View File
@@ -0,0 +1,140 @@
<p align="center">
<img width="250" src="/yargs-logo.png">
</p>
<h1 align="center"> Yargs </h1>
<p align="center">
<b >Yargs be a node.js library fer hearties tryin' ter parse optstrings</b>
</p>
<br>
[![Build Status][travis-image]][travis-url]
[![NPM version][npm-image]][npm-url]
[![js-standard-style][standard-image]][standard-url]
[![Coverage][coverage-image]][coverage-url]
[![Conventional Commits][conventional-commits-image]][conventional-commits-url]
[![Slack][slack-image]][slack-url]
## Description :
Yargs helps you build interactive command line tools, by parsing arguments and generating an elegant user interface.
It gives you:
* commands and (grouped) options (`my-program.js serve --port=5000`).
* a dynamically generated help menu based on your arguments.
> <img width="400" src="/screen.png">
* bash-completion shortcuts for commands and options.
* and [tons more](/docs/api.md).
## Installation
Stable version:
```bash
npm i yargs
```
Bleeding edge version with the most recent features:
```bash
npm i yargs@next
```
## Usage :
### Simple Example
```javascript
#!/usr/bin/env node
const {argv} = require('yargs')
if (argv.ships > 3 && argv.distance < 53.5) {
console.log('Plunder more riffiwobbles!')
} else {
console.log('Retreat from the xupptumblers!')
}
```
```bash
$ ./plunder.js --ships=4 --distance=22
Plunder more riffiwobbles!
$ ./plunder.js --ships 12 --distance 98.7
Retreat from the xupptumblers!
```
### Complex Example
```javascript
#!/usr/bin/env node
require('yargs') // eslint-disable-line
.command('serve [port]', 'start the server', (yargs) => {
yargs
.positional('port', {
describe: 'port to bind on',
default: 5000
})
}, (argv) => {
if (argv.verbose) console.info(`start server on :${argv.port}`)
serve(argv.port)
})
.option('verbose', {
alias: 'v',
type: 'boolean',
description: 'Run with verbose logging'
})
.argv
```
Run the example above with `--help` to see the help for the application.
## TypeScript
yargs has type definitions at [@types/yargs][type-definitions].
```
npm i @types/yargs --save-dev
```
See usage examples in [docs](/docs/typescript.md).
## Webpack
See usage examples of yargs with webpack in [docs](/docs/webpack.md).
## Community :
Having problems? want to contribute? join our [community slack](http://devtoolscommunity.herokuapp.com).
## Documentation :
### Table of Contents
* [Yargs' API](/docs/api.md)
* [Examples](/docs/examples.md)
* [Parsing Tricks](/docs/tricks.md)
* [Stop the Parser](/docs/tricks.md#stop)
* [Negating Boolean Arguments](/docs/tricks.md#negate)
* [Numbers](/docs/tricks.md#numbers)
* [Arrays](/docs/tricks.md#arrays)
* [Objects](/docs/tricks.md#objects)
* [Quotes](/docs/tricks.md#quotes)
* [Advanced Topics](/docs/advanced.md)
* [Composing Your App Using Commands](/docs/advanced.md#commands)
* [Building Configurable CLI Apps](/docs/advanced.md#configuration)
* [Customizing Yargs' Parser](/docs/advanced.md#customizing)
* [Contributing](/contributing.md)
[travis-url]: https://travis-ci.org/yargs/yargs
[travis-image]: https://img.shields.io/travis/yargs/yargs/master.svg
[npm-url]: https://www.npmjs.com/package/yargs
[npm-image]: https://img.shields.io/npm/v/yargs.svg
[standard-image]: https://img.shields.io/badge/code%20style-standard-brightgreen.svg
[standard-url]: http://standardjs.com/
[conventional-commits-image]: https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg
[conventional-commits-url]: https://conventionalcommits.org/
[slack-image]: http://devtoolscommunity.herokuapp.com/badge.svg
[slack-url]: http://devtoolscommunity.herokuapp.com
[type-definitions]: https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/yargs
[coverage-image]: https://img.shields.io/nycrc/yargs/yargs
[coverage-url]: https://github.com/yargs/yargs/blob/master/.nycrc
@@ -0,0 +1,2 @@
import { Dictionary } from './common-types';
export declare function applyExtends(config: Dictionary, cwd: string, mergeExtends?: boolean): Dictionary;
+65
View File
@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyExtends = void 0;
const fs = require("fs");
const path = require("path");
const yerror_1 = require("./yerror");
let previouslyVisitedConfigs = [];
function checkForCircularExtends(cfgPath) {
if (previouslyVisitedConfigs.indexOf(cfgPath) > -1) {
throw new yerror_1.YError(`Circular extended configurations: '${cfgPath}'.`);
}
}
function getPathToDefaultConfig(cwd, pathToExtend) {
return path.resolve(cwd, pathToExtend);
}
function mergeDeep(config1, config2) {
const target = {};
function isObject(obj) {
return obj && typeof obj === 'object' && !Array.isArray(obj);
}
Object.assign(target, config1);
for (const key of Object.keys(config2)) {
if (isObject(config2[key]) && isObject(target[key])) {
target[key] = mergeDeep(config1[key], config2[key]);
}
else {
target[key] = config2[key];
}
}
return target;
}
function applyExtends(config, cwd, mergeExtends = false) {
let defaultConfig = {};
if (Object.prototype.hasOwnProperty.call(config, 'extends')) {
if (typeof config.extends !== 'string')
return defaultConfig;
const isPath = /\.json|\..*rc$/.test(config.extends);
let pathToDefault = null;
if (!isPath) {
try {
pathToDefault = require.resolve(config.extends);
}
catch (err) {
// most likely this simply isn't a module.
}
}
else {
pathToDefault = getPathToDefaultConfig(cwd, config.extends);
}
// maybe the module uses key for some other reason,
// err on side of caution.
if (!pathToDefault && !isPath)
return config;
if (!pathToDefault)
throw new yerror_1.YError(`Unable to find extended config '${config.extends}' in '${cwd}'.`);
checkForCircularExtends(pathToDefault);
previouslyVisitedConfigs.push(pathToDefault);
defaultConfig = isPath ? JSON.parse(fs.readFileSync(pathToDefault, 'utf8')) : require(config.extends);
delete config.extends;
defaultConfig = applyExtends(defaultConfig, path.dirname(pathToDefault), mergeExtends);
}
previouslyVisitedConfigs = [];
return mergeExtends ? mergeDeep(defaultConfig, config) : Object.assign({}, defaultConfig, config);
}
exports.applyExtends = applyExtends;
+2
View File
@@ -0,0 +1,2 @@
export declare function argsert(callerArguments: any[], length?: number): void;
export declare function argsert(expected: string, callerArguments: any[], length?: number): void;
+65
View File
@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.argsert = void 0;
const yerror_1 = require("./yerror");
const parse_command_1 = require("./parse-command");
const positionName = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth'];
function argsert(arg1, arg2, arg3) {
function parseArgs() {
return typeof arg1 === 'object'
? [{ demanded: [], optional: [] }, arg1, arg2]
: [parse_command_1.parseCommand(`cmd ${arg1}`), arg2, arg3];
}
// TODO: should this eventually raise an exception.
try {
// preface the argument description with "cmd", so
// that we can run it through yargs' command parser.
let position = 0;
let [parsed, callerArguments, length] = parseArgs();
const args = [].slice.call(callerArguments);
while (args.length && args[args.length - 1] === undefined)
args.pop();
length = length || args.length;
if (length < parsed.demanded.length) {
throw new yerror_1.YError(`Not enough arguments provided. Expected ${parsed.demanded.length} but received ${args.length}.`);
}
const totalCommands = parsed.demanded.length + parsed.optional.length;
if (length > totalCommands) {
throw new yerror_1.YError(`Too many arguments provided. Expected max ${totalCommands} but received ${length}.`);
}
parsed.demanded.forEach((demanded) => {
const arg = args.shift();
const observedType = guessType(arg);
const matchingTypes = demanded.cmd.filter(type => type === observedType || type === '*');
if (matchingTypes.length === 0)
argumentTypeError(observedType, demanded.cmd, position);
position += 1;
});
parsed.optional.forEach((optional) => {
if (args.length === 0)
return;
const arg = args.shift();
const observedType = guessType(arg);
const matchingTypes = optional.cmd.filter(type => type === observedType || type === '*');
if (matchingTypes.length === 0)
argumentTypeError(observedType, optional.cmd, position);
position += 1;
});
}
catch (err) {
console.warn(err.stack);
}
}
exports.argsert = argsert;
function guessType(arg) {
if (Array.isArray(arg)) {
return 'array';
}
else if (arg === null) {
return 'null';
}
return typeof arg;
}
function argumentTypeError(observedType, allowedTypes, position) {
throw new yerror_1.YError(`Invalid ${positionName[position] || 'manyith'} argument. Expected ${allowedTypes.join(' or ')} but received ${observedType}.`);
}
+64
View File
@@ -0,0 +1,64 @@
/// <reference types="node" />
import { Dictionary } from './common-types';
import { Middleware } from './middleware';
import { Positional } from './parse-command';
import { RequireDirectoryOptions } from 'require-directory';
import { UsageInstance } from './usage';
import { ValidationInstance } from './validation';
import { YargsInstance, Options, OptionDefinition, Context, Arguments, DetailedArguments } from './yargs';
export declare function command(yargs: YargsInstance, usage: UsageInstance, validation: ValidationInstance, globalMiddleware?: Middleware[]): CommandInstance;
/** Instance of the command module. */
export interface CommandInstance {
addDirectory(dir: string, context: Context, req: NodeRequireFunction, callerFile: string, opts?: RequireDirectoryOptions<any>): void;
addHandler(handler: CommandHandlerDefinition): void;
addHandler(cmd: string | string[], description: CommandHandler['description'], builder?: CommandBuilderDefinition | CommandBuilder, handler?: CommandHandlerCallback, commandMiddleware?: Middleware[], deprecated?: boolean): void;
cmdToParseOptions(cmdString: string): Positionals;
freeze(): void;
getCommandHandlers(): Dictionary<CommandHandler>;
getCommands(): string[];
hasDefaultCommand(): boolean;
reset(): CommandInstance;
runCommand(command: string | null, yargs: YargsInstance, parsed: DetailedArguments, commandIndex?: number): Arguments | Promise<Arguments>;
runDefaultBuilderOn(yargs: YargsInstance): void;
unfreeze(): void;
}
export interface CommandHandlerDefinition extends Partial<Pick<CommandHandler, 'deprecated' | 'description' | 'handler' | 'middlewares'>> {
aliases?: string[];
builder?: CommandBuilder | CommandBuilderDefinition;
command?: string | string[];
desc?: CommandHandler['description'];
describe?: CommandHandler['description'];
}
export declare function isCommandHandlerDefinition(cmd: string | string[] | CommandHandlerDefinition): cmd is CommandHandlerDefinition;
export interface CommandBuilderDefinition {
builder?: CommandBuilder;
deprecated?: boolean;
handler: CommandHandlerCallback;
middlewares?: Middleware[];
}
export declare function isCommandBuilderDefinition(builder?: CommandBuilder | CommandBuilderDefinition): builder is CommandBuilderDefinition;
export interface CommandHandlerCallback {
(argv: Arguments): any;
}
export interface CommandHandler {
builder: CommandBuilder;
demanded: Positional[];
deprecated?: boolean;
description?: string | false;
handler: CommandHandlerCallback;
middlewares: Middleware[];
optional: Positional[];
original: string;
}
export declare type CommandBuilder = CommandBuilderCallback | Dictionary<OptionDefinition>;
interface CommandBuilderCallback {
(y: YargsInstance): YargsInstance | void;
}
export declare function isCommandBuilderCallback(builder: CommandBuilder): builder is CommandBuilderCallback;
interface Positionals extends Pick<Options, 'alias' | 'array' | 'default'> {
demand: Dictionary<boolean>;
}
export interface FinishCommandHandler {
(handlerResult: any): any;
}
export {};
+416
View File
@@ -0,0 +1,416 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCommandBuilderCallback = exports.isCommandBuilderDefinition = exports.isCommandHandlerDefinition = exports.command = void 0;
const common_types_1 = require("./common-types");
const is_promise_1 = require("./is-promise");
const middleware_1 = require("./middleware");
const parse_command_1 = require("./parse-command");
const path = require("path");
const util_1 = require("util");
const yargs_1 = require("./yargs");
const requireDirectory = require("require-directory");
const whichModule = require("which-module");
const Parser = require("yargs-parser");
const DEFAULT_MARKER = /(^\*)|(^\$0)/;
// handles parsing positional arguments,
// and populating argv with said positional
// arguments.
function command(yargs, usage, validation, globalMiddleware = []) {
const self = {};
let handlers = {};
let aliasMap = {};
let defaultCommand;
self.addHandler = function addHandler(cmd, description, builder, handler, commandMiddleware, deprecated) {
let aliases = [];
const middlewares = middleware_1.commandMiddlewareFactory(commandMiddleware);
handler = handler || (() => { });
if (Array.isArray(cmd)) {
aliases = cmd.slice(1);
cmd = cmd[0];
}
else if (isCommandHandlerDefinition(cmd)) {
let command = (Array.isArray(cmd.command) || typeof cmd.command === 'string') ? cmd.command : moduleName(cmd);
if (cmd.aliases)
command = [].concat(command).concat(cmd.aliases);
self.addHandler(command, extractDesc(cmd), cmd.builder, cmd.handler, cmd.middlewares, cmd.deprecated);
return;
}
// allow a module to be provided instead of separate builder and handler
if (isCommandBuilderDefinition(builder)) {
self.addHandler([cmd].concat(aliases), description, builder.builder, builder.handler, builder.middlewares, builder.deprecated);
return;
}
// parse positionals out of cmd string
const parsedCommand = parse_command_1.parseCommand(cmd);
// remove positional args from aliases only
aliases = aliases.map(alias => parse_command_1.parseCommand(alias).cmd);
// check for default and filter out '*''
let isDefault = false;
const parsedAliases = [parsedCommand.cmd].concat(aliases).filter((c) => {
if (DEFAULT_MARKER.test(c)) {
isDefault = true;
return false;
}
return true;
});
// standardize on $0 for default command.
if (parsedAliases.length === 0 && isDefault)
parsedAliases.push('$0');
// shift cmd and aliases after filtering out '*'
if (isDefault) {
parsedCommand.cmd = parsedAliases[0];
aliases = parsedAliases.slice(1);
cmd = cmd.replace(DEFAULT_MARKER, parsedCommand.cmd);
}
// populate aliasMap
aliases.forEach((alias) => {
aliasMap[alias] = parsedCommand.cmd;
});
if (description !== false) {
usage.command(cmd, description, isDefault, aliases, deprecated);
}
handlers[parsedCommand.cmd] = {
original: cmd,
description,
handler,
builder: builder || {},
middlewares,
deprecated,
demanded: parsedCommand.demanded,
optional: parsedCommand.optional
};
if (isDefault)
defaultCommand = handlers[parsedCommand.cmd];
};
self.addDirectory = function addDirectory(dir, context, req, callerFile, opts) {
opts = opts || {};
// disable recursion to support nested directories of subcommands
if (typeof opts.recurse !== 'boolean')
opts.recurse = false;
// exclude 'json', 'coffee' from require-directory defaults
if (!Array.isArray(opts.extensions))
opts.extensions = ['js'];
// allow consumer to define their own visitor function
const parentVisit = typeof opts.visit === 'function' ? opts.visit : (o) => o;
// call addHandler via visitor function
opts.visit = function visit(obj, joined, filename) {
const visited = parentVisit(obj, joined, filename);
// allow consumer to skip modules with their own visitor
if (visited) {
// check for cyclic reference
// each command file path should only be seen once per execution
if (~context.files.indexOf(joined))
return visited;
// keep track of visited files in context.files
context.files.push(joined);
self.addHandler(visited);
}
return visited;
};
requireDirectory({ require: req, filename: callerFile }, dir, opts);
};
// lookup module object from require()d command and derive name
// if module was not require()d and no name given, throw error
function moduleName(obj) {
const mod = whichModule(obj);
if (!mod)
throw new Error(`No command name given for module: ${util_1.inspect(obj)}`);
return commandFromFilename(mod.filename);
}
// derive command name from filename
function commandFromFilename(filename) {
return path.basename(filename, path.extname(filename));
}
function extractDesc({ describe, description, desc }) {
for (const test of [describe, description, desc]) {
if (typeof test === 'string' || test === false)
return test;
common_types_1.assertNotStrictEqual(test, true);
}
return false;
}
self.getCommands = () => Object.keys(handlers).concat(Object.keys(aliasMap));
self.getCommandHandlers = () => handlers;
self.hasDefaultCommand = () => !!defaultCommand;
self.runCommand = function runCommand(command, yargs, parsed, commandIndex) {
let aliases = parsed.aliases;
const commandHandler = handlers[command] || handlers[aliasMap[command]] || defaultCommand;
const currentContext = yargs.getContext();
let numFiles = currentContext.files.length;
const parentCommands = currentContext.commands.slice();
// what does yargs look like after the builder is run?
let innerArgv = parsed.argv;
let positionalMap = {};
if (command) {
currentContext.commands.push(command);
currentContext.fullCommands.push(commandHandler.original);
}
const builder = commandHandler.builder;
if (isCommandBuilderCallback(builder)) {
// a function can be provided, which builds
// up a yargs chain and possibly returns it.
const builderOutput = builder(yargs.reset(parsed.aliases));
const innerYargs = yargs_1.isYargsInstance(builderOutput) ? builderOutput : yargs;
if (shouldUpdateUsage(innerYargs)) {
innerYargs.getUsageInstance().usage(usageFromParentCommandsCommandHandler(parentCommands, commandHandler), commandHandler.description);
}
innerArgv = innerYargs._parseArgs(null, null, true, commandIndex);
aliases = innerYargs.parsed.aliases;
}
else if (isCommandBuilderOptionDefinitions(builder)) {
// as a short hand, an object can instead be provided, specifying
// the options that a command takes.
const innerYargs = yargs.reset(parsed.aliases);
if (shouldUpdateUsage(innerYargs)) {
innerYargs.getUsageInstance().usage(usageFromParentCommandsCommandHandler(parentCommands, commandHandler), commandHandler.description);
}
Object.keys(commandHandler.builder).forEach((key) => {
innerYargs.option(key, builder[key]);
});
innerArgv = innerYargs._parseArgs(null, null, true, commandIndex);
aliases = innerYargs.parsed.aliases;
}
if (!yargs._hasOutput()) {
positionalMap = populatePositionals(commandHandler, innerArgv, currentContext);
}
const middlewares = globalMiddleware.slice(0).concat(commandHandler.middlewares);
middleware_1.applyMiddleware(innerArgv, yargs, middlewares, true);
// we apply validation post-hoc, so that custom
// checks get passed populated positional arguments.
if (!yargs._hasOutput()) {
yargs._runValidation(innerArgv, aliases, positionalMap, yargs.parsed.error, !command);
}
if (commandHandler.handler && !yargs._hasOutput()) {
yargs._setHasOutput();
// to simplify the parsing of positionals in commands,
// we temporarily populate '--' rather than _, with arguments
const populateDoubleDash = !!yargs.getOptions().configuration['populate--'];
if (!populateDoubleDash)
yargs._copyDoubleDash(innerArgv);
innerArgv = middleware_1.applyMiddleware(innerArgv, yargs, middlewares, false);
let handlerResult;
if (is_promise_1.isPromise(innerArgv)) {
handlerResult = innerArgv.then(argv => commandHandler.handler(argv));
}
else {
handlerResult = commandHandler.handler(innerArgv);
}
const handlerFinishCommand = yargs.getHandlerFinishCommand();
if (is_promise_1.isPromise(handlerResult)) {
yargs.getUsageInstance().cacheHelpMessage();
handlerResult
.then(value => {
if (handlerFinishCommand) {
handlerFinishCommand(value);
}
})
.catch(error => {
try {
yargs.getUsageInstance().fail(null, error);
}
catch (err) {
// fail's throwing would cause an unhandled rejection.
}
})
.then(() => {
yargs.getUsageInstance().clearCachedHelpMessage();
});
}
else {
if (handlerFinishCommand) {
handlerFinishCommand(handlerResult);
}
}
}
if (command) {
currentContext.commands.pop();
currentContext.fullCommands.pop();
}
numFiles = currentContext.files.length - numFiles;
if (numFiles > 0)
currentContext.files.splice(numFiles * -1, numFiles);
return innerArgv;
};
function shouldUpdateUsage(yargs) {
return !yargs.getUsageInstance().getUsageDisabled() &&
yargs.getUsageInstance().getUsage().length === 0;
}
function usageFromParentCommandsCommandHandler(parentCommands, commandHandler) {
const c = DEFAULT_MARKER.test(commandHandler.original) ? commandHandler.original.replace(DEFAULT_MARKER, '').trim() : commandHandler.original;
const pc = parentCommands.filter((c) => { return !DEFAULT_MARKER.test(c); });
pc.push(c);
return `$0 ${pc.join(' ')}`;
}
self.runDefaultBuilderOn = function (yargs) {
common_types_1.assertNotStrictEqual(defaultCommand, undefined);
if (shouldUpdateUsage(yargs)) {
// build the root-level command string from the default string.
const commandString = DEFAULT_MARKER.test(defaultCommand.original)
? defaultCommand.original : defaultCommand.original.replace(/^[^[\]<>]*/, '$0 ');
yargs.getUsageInstance().usage(commandString, defaultCommand.description);
}
const builder = defaultCommand.builder;
if (isCommandBuilderCallback(builder)) {
builder(yargs);
}
else {
Object.keys(builder).forEach((key) => {
yargs.option(key, builder[key]);
});
}
};
// transcribe all positional arguments "command <foo> <bar> [apple]"
// onto argv.
function populatePositionals(commandHandler, argv, context) {
argv._ = argv._.slice(context.commands.length); // nuke the current commands
const demanded = commandHandler.demanded.slice(0);
const optional = commandHandler.optional.slice(0);
const positionalMap = {};
validation.positionalCount(demanded.length, argv._.length);
while (demanded.length) {
const demand = demanded.shift();
populatePositional(demand, argv, positionalMap);
}
while (optional.length) {
const maybe = optional.shift();
populatePositional(maybe, argv, positionalMap);
}
argv._ = context.commands.concat(argv._);
postProcessPositionals(argv, positionalMap, self.cmdToParseOptions(commandHandler.original));
return positionalMap;
}
function populatePositional(positional, argv, positionalMap) {
const cmd = positional.cmd[0];
if (positional.variadic) {
positionalMap[cmd] = argv._.splice(0).map(String);
}
else {
if (argv._.length)
positionalMap[cmd] = [String(argv._.shift())];
}
}
// we run yargs-parser against the positional arguments
// applying the same parsing logic used for flags.
function postProcessPositionals(argv, positionalMap, parseOptions) {
// combine the parsing hints we've inferred from the command
// string with explicitly configured parsing hints.
const options = Object.assign({}, yargs.getOptions());
options.default = Object.assign(parseOptions.default, options.default);
for (const key of Object.keys(parseOptions.alias)) {
options.alias[key] = (options.alias[key] || []).concat(parseOptions.alias[key]);
}
options.array = options.array.concat(parseOptions.array);
delete options.config; // don't load config when processing positionals.
const unparsed = [];
Object.keys(positionalMap).forEach((key) => {
positionalMap[key].map((value) => {
if (options.configuration['unknown-options-as-args'])
options.key[key] = true;
unparsed.push(`--${key}`);
unparsed.push(value);
});
});
// short-circuit parse.
if (!unparsed.length)
return;
const config = Object.assign({}, options.configuration, {
'populate--': true
});
const parsed = Parser.detailed(unparsed, Object.assign({}, options, {
configuration: config
}));
if (parsed.error) {
yargs.getUsageInstance().fail(parsed.error.message, parsed.error);
}
else {
// only copy over positional keys (don't overwrite
// flag arguments that were already parsed).
const positionalKeys = Object.keys(positionalMap);
Object.keys(positionalMap).forEach((key) => {
positionalKeys.push(...parsed.aliases[key]);
});
Object.keys(parsed.argv).forEach((key) => {
if (positionalKeys.indexOf(key) !== -1) {
// any new aliases need to be placed in positionalMap, which
// is used for validation.
if (!positionalMap[key])
positionalMap[key] = parsed.argv[key];
argv[key] = parsed.argv[key];
}
});
}
}
self.cmdToParseOptions = function (cmdString) {
const parseOptions = {
array: [],
default: {},
alias: {},
demand: {}
};
const parsed = parse_command_1.parseCommand(cmdString);
parsed.demanded.forEach((d) => {
const [cmd, ...aliases] = d.cmd;
if (d.variadic) {
parseOptions.array.push(cmd);
parseOptions.default[cmd] = [];
}
parseOptions.alias[cmd] = aliases;
parseOptions.demand[cmd] = true;
});
parsed.optional.forEach((o) => {
const [cmd, ...aliases] = o.cmd;
if (o.variadic) {
parseOptions.array.push(cmd);
parseOptions.default[cmd] = [];
}
parseOptions.alias[cmd] = aliases;
});
return parseOptions;
};
self.reset = () => {
handlers = {};
aliasMap = {};
defaultCommand = undefined;
return self;
};
// used by yargs.parse() to freeze
// the state of commands such that
// we can apply .parse() multiple times
// with the same yargs instance.
const frozens = [];
self.freeze = () => {
frozens.push({
handlers,
aliasMap,
defaultCommand
});
};
self.unfreeze = () => {
const frozen = frozens.pop();
common_types_1.assertNotStrictEqual(frozen, undefined);
({
handlers,
aliasMap,
defaultCommand
} = frozen);
};
return self;
}
exports.command = command;
function isCommandHandlerDefinition(cmd) {
return typeof cmd === 'object';
}
exports.isCommandHandlerDefinition = isCommandHandlerDefinition;
function isCommandBuilderDefinition(builder) {
return typeof builder === 'object' &&
!!builder.builder &&
typeof builder.handler === 'function';
}
exports.isCommandBuilderDefinition = isCommandBuilderDefinition;
function isCommandBuilderCallback(builder) {
return typeof builder === 'function';
}
exports.isCommandBuilderCallback = isCommandBuilderCallback;
function isCommandBuilderOptionDefinitions(builder) {
return typeof builder === 'object';
}
+36
View File
@@ -0,0 +1,36 @@
/**
* An object whose all properties have the same type.
*/
export declare type Dictionary<T = any> = {
[key: string]: T;
};
/**
* Returns the keys of T that match Dictionary<U> and are not arrays.
*/
export declare type DictionaryKeyof<T, U = any> = Exclude<KeyOf<T, Dictionary<U>>, KeyOf<T, any[]>>;
/**
* Returns the keys of T that match U.
*/
export declare type KeyOf<T, U> = Exclude<{
[K in keyof T]: T[K] extends U ? K : never;
}[keyof T], undefined>;
/**
* An array whose first element is not undefined.
*/
export declare type NotEmptyArray<T = any> = [T, ...T[]];
/**
* Returns the type of a Dictionary or array values.
*/
export declare type ValueOf<T> = T extends (infer U)[] ? U : T[keyof T];
/**
* Typing wrapper around assert.notStrictEqual()
*/
export declare function assertNotStrictEqual<N, T>(actual: T | N, expected: N, message?: string | Error): asserts actual is Exclude<T, N>;
/**
* Asserts actual is a single key, not a key array or a key map.
*/
export declare function assertSingleKey(actual: string | string[] | Dictionary): asserts actual is string;
/**
* Typing wrapper around Object.keys()
*/
export declare function objectKeys<T>(object: T): (keyof T)[];
+25
View File
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.objectKeys = exports.assertSingleKey = exports.assertNotStrictEqual = void 0;
const assert_1 = require("assert");
/**
* Typing wrapper around assert.notStrictEqual()
*/
function assertNotStrictEqual(actual, expected, message) {
assert_1.notStrictEqual(actual, expected, message);
}
exports.assertNotStrictEqual = assertNotStrictEqual;
/**
* Asserts actual is a single key, not a key array or a key map.
*/
function assertSingleKey(actual) {
assert_1.strictEqual(typeof actual, 'string');
}
exports.assertSingleKey = assertSingleKey;
/**
* Typing wrapper around Object.keys()
*/
function objectKeys(object) {
return Object.keys(object);
}
exports.objectKeys = objectKeys;
@@ -0,0 +1,2 @@
export declare const completionShTemplate = "###-begin-{{app_name}}-completions-###\n#\n# yargs command completion script\n#\n# Installation: {{app_path}} {{completion_command}} >> ~/.bashrc\n# or {{app_path}} {{completion_command}} >> ~/.bash_profile on OSX.\n#\n_yargs_completions()\n{\n local cur_word args type_list\n\n cur_word=\"${COMP_WORDS[COMP_CWORD]}\"\n args=(\"${COMP_WORDS[@]}\")\n\n # ask yargs to generate completions.\n type_list=$({{app_path}} --get-yargs-completions \"${args[@]}\")\n\n COMPREPLY=( $(compgen -W \"${type_list}\" -- ${cur_word}) )\n\n # if no match was found, fall back to filename completion\n if [ ${#COMPREPLY[@]} -eq 0 ]; then\n COMPREPLY=()\n fi\n\n return 0\n}\ncomplete -o default -F _yargs_completions {{app_name}}\n###-end-{{app_name}}-completions-###\n";
export declare const completionZshTemplate = "###-begin-{{app_name}}-completions-###\n#\n# yargs command completion script\n#\n# Installation: {{app_path}} {{completion_command}} >> ~/.zshrc\n# or {{app_path}} {{completion_command}} >> ~/.zsh_profile on OSX.\n#\n_{{app_name}}_yargs_completions()\n{\n local reply\n local si=$IFS\n IFS=$'\n' reply=($(COMP_CWORD=\"$((CURRENT-1))\" COMP_LINE=\"$BUFFER\" COMP_POINT=\"$CURSOR\" {{app_path}} --get-yargs-completions \"${words[@]}\"))\n IFS=$si\n _describe 'values' reply\n}\ncompdef _{{app_name}}_yargs_completions {{app_name}}\n###-end-{{app_name}}-completions-###\n";
@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.completionZshTemplate = exports.completionShTemplate = void 0;
exports.completionShTemplate = `###-begin-{{app_name}}-completions-###
#
# yargs command completion script
#
# Installation: {{app_path}} {{completion_command}} >> ~/.bashrc
# or {{app_path}} {{completion_command}} >> ~/.bash_profile on OSX.
#
_yargs_completions()
{
local cur_word args type_list
cur_word="\${COMP_WORDS[COMP_CWORD]}"
args=("\${COMP_WORDS[@]}")
# ask yargs to generate completions.
type_list=$({{app_path}} --get-yargs-completions "\${args[@]}")
COMPREPLY=( $(compgen -W "\${type_list}" -- \${cur_word}) )
# if no match was found, fall back to filename completion
if [ \${#COMPREPLY[@]} -eq 0 ]; then
COMPREPLY=()
fi
return 0
}
complete -o default -F _yargs_completions {{app_name}}
###-end-{{app_name}}-completions-###
`;
exports.completionZshTemplate = `###-begin-{{app_name}}-completions-###
#
# yargs command completion script
#
# Installation: {{app_path}} {{completion_command}} >> ~/.zshrc
# or {{app_path}} {{completion_command}} >> ~/.zsh_profile on OSX.
#
_{{app_name}}_yargs_completions()
{
local reply
local si=$IFS
IFS=$'\n' reply=($(COMP_CWORD="$((CURRENT-1))" COMP_LINE="$BUFFER" COMP_POINT="$CURSOR" {{app_path}} --get-yargs-completions "\${words[@]}"))
IFS=$si
_describe 'values' reply
}
compdef _{{app_name}}_yargs_completions {{app_name}}
###-end-{{app_name}}-completions-###
`;
+21
View File
@@ -0,0 +1,21 @@
import { CommandInstance } from './command';
import { UsageInstance } from './usage';
import { YargsInstance } from './yargs';
import { Arguments, DetailedArguments } from 'yargs-parser';
export declare function completion(yargs: YargsInstance, usage: UsageInstance, command: CommandInstance): CompletionInstance;
/** Instance of the completion module. */
export interface CompletionInstance {
completionKey: string;
generateCompletionScript($0: string, cmd: string): string;
getCompletion(args: string[], done: (completions: string[]) => any): any;
registerFunction(fn: CompletionFunction): void;
setParsed(parsed: DetailedArguments): void;
}
export declare type CompletionFunction = SyncCompletionFunction | AsyncCompletionFunction;
interface SyncCompletionFunction {
(current: string, argv: Arguments): string[] | Promise<string[]>;
}
interface AsyncCompletionFunction {
(current: string, argv: Arguments, done: (completions: string[]) => any): any;
}
export {};
+135
View File
@@ -0,0 +1,135 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.completion = void 0;
const command_1 = require("./command");
const templates = require("./completion-templates");
const is_promise_1 = require("./is-promise");
const parse_command_1 = require("./parse-command");
const path = require("path");
const common_types_1 = require("./common-types");
// add bash completions to your
// yargs-powered applications.
function completion(yargs, usage, command) {
const self = {
completionKey: 'get-yargs-completions'
};
let aliases;
self.setParsed = function setParsed(parsed) {
aliases = parsed.aliases;
};
const zshShell = (process.env.SHELL && process.env.SHELL.indexOf('zsh') !== -1) ||
(process.env.ZSH_NAME && process.env.ZSH_NAME.indexOf('zsh') !== -1);
// get a list of completion commands.
// 'args' is the array of strings from the line to be completed
self.getCompletion = function getCompletion(args, done) {
const completions = [];
const current = args.length ? args[args.length - 1] : '';
const argv = yargs.parse(args, true);
const parentCommands = yargs.getContext().commands;
// a custom completion function can be provided
// to completion().
function runCompletionFunction(argv) {
common_types_1.assertNotStrictEqual(completionFunction, null);
if (isSyncCompletionFunction(completionFunction)) {
const result = completionFunction(current, argv);
// promise based completion function.
if (is_promise_1.isPromise(result)) {
return result.then((list) => {
process.nextTick(() => { done(list); });
}).catch((err) => {
process.nextTick(() => { throw err; });
});
}
// synchronous completion function.
return done(result);
}
else {
// asynchronous completion function
return completionFunction(current, argv, (completions) => {
done(completions);
});
}
}
if (completionFunction) {
return is_promise_1.isPromise(argv) ? argv.then(runCompletionFunction) : runCompletionFunction(argv);
}
const handlers = command.getCommandHandlers();
for (let i = 0, ii = args.length; i < ii; ++i) {
if (handlers[args[i]] && handlers[args[i]].builder) {
const builder = handlers[args[i]].builder;
if (command_1.isCommandBuilderCallback(builder)) {
const y = yargs.reset();
builder(y);
return y.argv;
}
}
}
if (!current.match(/^-/) && parentCommands[parentCommands.length - 1] !== current) {
usage.getCommands().forEach((usageCommand) => {
const commandName = parse_command_1.parseCommand(usageCommand[0]).cmd;
if (args.indexOf(commandName) === -1) {
if (!zshShell) {
completions.push(commandName);
}
else {
const desc = usageCommand[1] || '';
completions.push(commandName.replace(/:/g, '\\:') + ':' + desc);
}
}
});
}
if (current.match(/^-/) || (current === '' && completions.length === 0)) {
const descs = usage.getDescriptions();
const options = yargs.getOptions();
Object.keys(options.key).forEach((key) => {
const negable = !!options.configuration['boolean-negation'] && options.boolean.includes(key);
// If the key and its aliases aren't in 'args', add the key to 'completions'
let keyAndAliases = [key].concat(aliases[key] || []);
if (negable)
keyAndAliases = keyAndAliases.concat(keyAndAliases.map(key => `no-${key}`));
function completeOptionKey(key) {
const notInArgs = keyAndAliases.every(val => args.indexOf(`--${val}`) === -1);
if (notInArgs) {
const startsByTwoDashes = (s) => /^--/.test(s);
const isShortOption = (s) => /^[^0-9]$/.test(s);
const dashes = !startsByTwoDashes(current) && isShortOption(key) ? '-' : '--';
if (!zshShell) {
completions.push(dashes + key);
}
else {
const desc = descs[key] || '';
completions.push(dashes + `${key.replace(/:/g, '\\:')}:${desc.replace('__yargsString__:', '')}`);
}
}
}
completeOptionKey(key);
if (negable && !!options.default[key])
completeOptionKey(`no-${key}`);
});
}
done(completions);
};
// generate the completion script to add to your .bashrc.
self.generateCompletionScript = function generateCompletionScript($0, cmd) {
let script = zshShell ? templates.completionZshTemplate : templates.completionShTemplate;
const name = path.basename($0);
// add ./to applications not yet installed as bin.
if ($0.match(/\.js$/))
$0 = `./${$0}`;
script = script.replace(/{{app_name}}/g, name);
script = script.replace(/{{completion_command}}/g, cmd);
return script.replace(/{{app_path}}/g, $0);
};
// register a function to perform your own custom
// completions., this function can be either
// synchrnous or asynchronous.
let completionFunction = null;
self.registerFunction = (fn) => {
completionFunction = fn;
};
return self;
}
exports.completion = completion;
function isSyncCompletionFunction(completionFunction) {
return completionFunction.length < 3;
}
+1
View File
@@ -0,0 +1 @@
export declare function isPromise<T>(maybePromise: T | Promise<T>): maybePromise is Promise<T>;
+9
View File
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPromise = void 0;
function isPromise(maybePromise) {
return !!maybePromise &&
!!maybePromise.then &&
(typeof maybePromise.then === 'function');
}
exports.isPromise = isPromise;
+1
View File
@@ -0,0 +1 @@
export declare function levenshtein(a: string, b: string): number;
+58
View File
@@ -0,0 +1,58 @@
"use strict";
/*
Copyright (c) 2011 Andrei Mackenzie
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.levenshtein = void 0;
// levenshtein distance algorithm, pulled from Andrei Mackenzie's MIT licensed.
// gist, which can be found here: https://gist.github.com/andrei-m/982927
// Compute the edit distance between the two given strings
function levenshtein(a, b) {
if (a.length === 0)
return b.length;
if (b.length === 0)
return a.length;
const matrix = [];
// increment along the first column of each row
let i;
for (i = 0; i <= b.length; i++) {
matrix[i] = [i];
}
// increment each column in the first row
let j;
for (j = 0; j <= a.length; j++) {
matrix[0][j] = j;
}
// Fill in the rest of the matrix
for (i = 1; i <= b.length; i++) {
for (j = 1; j <= a.length; j++) {
if (b.charAt(i - 1) === a.charAt(j - 1)) {
matrix[i][j] = matrix[i - 1][j - 1];
}
else {
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
Math.min(matrix[i][j - 1] + 1, // insertion
matrix[i - 1][j] + 1)); // deletion
}
}
}
return matrix[b.length][a.length];
}
exports.levenshtein = levenshtein;
+10
View File
@@ -0,0 +1,10 @@
import { YargsInstance, Arguments } from './yargs';
export declare function globalMiddlewareFactory<T>(globalMiddleware: Middleware[], context: T): (callback: MiddlewareCallback | MiddlewareCallback[], applyBeforeValidation?: boolean) => T;
export declare function commandMiddlewareFactory(commandMiddleware?: MiddlewareCallback[]): Middleware[];
export declare function applyMiddleware(argv: Arguments | Promise<Arguments>, yargs: YargsInstance, middlewares: Middleware[], beforeValidation: boolean): Arguments | Promise<Arguments>;
export interface MiddlewareCallback {
(argv: Arguments, yargs: YargsInstance): Partial<Arguments> | Promise<Partial<Arguments>>;
}
export interface Middleware extends MiddlewareCallback {
applyBeforeValidation: boolean;
}
+57
View File
@@ -0,0 +1,57 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyMiddleware = exports.commandMiddlewareFactory = exports.globalMiddlewareFactory = void 0;
const argsert_1 = require("./argsert");
const is_promise_1 = require("./is-promise");
function globalMiddlewareFactory(globalMiddleware, context) {
return function (callback, applyBeforeValidation = false) {
argsert_1.argsert('<array|function> [boolean]', [callback, applyBeforeValidation], arguments.length);
if (Array.isArray(callback)) {
for (let i = 0; i < callback.length; i++) {
if (typeof callback[i] !== 'function') {
throw Error('middleware must be a function');
}
callback[i].applyBeforeValidation = applyBeforeValidation;
}
Array.prototype.push.apply(globalMiddleware, callback);
}
else if (typeof callback === 'function') {
callback.applyBeforeValidation = applyBeforeValidation;
globalMiddleware.push(callback);
}
return context;
};
}
exports.globalMiddlewareFactory = globalMiddlewareFactory;
function commandMiddlewareFactory(commandMiddleware) {
if (!commandMiddleware)
return [];
return commandMiddleware.map(middleware => {
middleware.applyBeforeValidation = false;
return middleware;
});
}
exports.commandMiddlewareFactory = commandMiddlewareFactory;
function applyMiddleware(argv, yargs, middlewares, beforeValidation) {
const beforeValidationError = new Error('middleware cannot return a promise when applyBeforeValidation is true');
return middlewares
.reduce((acc, middleware) => {
if (middleware.applyBeforeValidation !== beforeValidation) {
return acc;
}
if (is_promise_1.isPromise(acc)) {
return acc
.then(initialObj => Promise.all([initialObj, middleware(initialObj, yargs)]))
.then(([initialObj, middlewareObj]) => Object.assign(initialObj, middlewareObj));
}
else {
const result = middleware(acc, yargs);
if (beforeValidation && is_promise_1.isPromise(result))
throw beforeValidationError;
return is_promise_1.isPromise(result)
? result.then(middlewareObj => Object.assign(acc, middlewareObj))
: Object.assign(acc, result);
}
}, argv);
}
exports.applyMiddleware = applyMiddleware;
+1
View File
@@ -0,0 +1 @@
export declare function objFilter<T extends object>(original?: T, filter?: (k: keyof T, v: T[keyof T]) => boolean): T;

Some files were not shown because too many files have changed in this diff Show More