diff --git a/lib/cli.js b/lib/cli.js index b52562b2ecb..4bc007fc26d 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -6,6 +6,7 @@ "use strict"; const path = require("path"); +const tty = require("tty"); const webpackSchema = require("../schemas/WebpackOptions.json"); /** @typedef {import("json-schema").JSONSchema4} JSONSchema4 */ @@ -712,5 +713,181 @@ const processArguments = (args, config, values) => { return problems; }; +/** + * @returns {boolean} true when colors supported, otherwise false + */ +const isColorSupported = () => { + const { env = {}, argv = [], platform = "" } = process; + + const isDisabled = "NO_COLOR" in env || argv.includes("--no-color"); + const isForced = "FORCE_COLOR" in env || argv.includes("--color"); + const isWindows = platform === "win32"; + const isDumbTerminal = env.TERM === "dumb"; + + const isCompatibleTerminal = tty.isatty(1) && env.TERM && !isDumbTerminal; + + const isCI = + "CI" in env && + ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env); + + return ( + !isDisabled && + (isForced || (isWindows && !isDumbTerminal) || isCompatibleTerminal || isCI) + ); +}; + +/** + * @param {number} index index + * @param {string} string string + * @param {string} close close + * @param {string=} replace replace + * @param {string=} head head + * @param {string=} tail tail + * @param {number=} next next + * @returns {string} result + */ +const replaceClose = ( + index, + string, + close, + replace, + head = string.slice(0, Math.max(0, index)) + replace, + tail = string.slice(Math.max(0, index + close.length)), + next = tail.indexOf(close) +) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace)); + +/** + * @param {number} index index to replace + * @param {string} string string + * @param {string} open open string + * @param {string} close close string + * @param {string=} replace extra replace + * @returns {string} result + */ +const clearBleed = (index, string, open, close, replace) => + index < 0 + ? open + string + close + : open + replaceClose(index, string, close, replace) + close; + +/** @typedef {(value: EXPECTED_ANY) => string} PrintFunction */ + +/** + * @param {string} open open string + * @param {string} close close string + * @param {string=} replace extra replace + * @param {number=} at at + * @returns {PrintFunction} function to create color + */ +const filterEmpty = + (open, close, replace = open, at = open.length + 1) => + (string) => + string || !(string === "" || string === undefined) + ? clearBleed(`${string}`.indexOf(close, at), string, open, close, replace) + : ""; + +/** + * @param {number} open open code + * @param {number} close close code + * @param {string=} replace extra replace + * @returns {PrintFunction} result + */ +const init = (open, close, replace) => + filterEmpty(`\u001B[${open}m`, `\u001B[${close}m`, replace); + +/** + * @typedef {{ + * reset: PrintFunction + * bold: PrintFunction + * dim: PrintFunction + * italic: PrintFunction + * underline: PrintFunction + * inverse: PrintFunction + * hidden: PrintFunction + * strikethrough: PrintFunction + * black: PrintFunction + * red: PrintFunction + * green: PrintFunction + * yellow: PrintFunction + * blue: PrintFunction + * magenta: PrintFunction + * cyan: PrintFunction + * white: PrintFunction + * gray: PrintFunction + * bgBlack: PrintFunction + * bgRed: PrintFunction + * bgGreen: PrintFunction + * bgYellow: PrintFunction + * bgBlue: PrintFunction + * bgMagenta: PrintFunction + * bgCyan: PrintFunction + * bgWhite: PrintFunction + * blackBright: PrintFunction + * redBright: PrintFunction + * greenBright: PrintFunction + * yellowBright: PrintFunction + * blueBright: PrintFunction + * magentaBright: PrintFunction + * cyanBright: PrintFunction + * whiteBright: PrintFunction + * bgBlackBright: PrintFunction + * bgRedBright: PrintFunction + * bgGreenBright: PrintFunction + * bgYellowBright: PrintFunction + * bgBlueBright: PrintFunction + * bgMagentaBright: PrintFunction + * bgCyanBright: PrintFunction + * bgWhiteBright: PrintFunction + }} Colors */ + +/** + * @param {{ useColor?: boolean }=} options options + * @returns {Colors} colors + */ +const createColors = ({ useColor = isColorSupported() } = {}) => ({ + reset: useColor ? init(0, 0) : String, + bold: useColor ? init(1, 22, "\u001B[22m\u001B[1m") : String, + dim: useColor ? init(2, 22, "\u001B[22m\u001B[2m") : String, + italic: useColor ? init(3, 23) : String, + underline: useColor ? init(4, 24) : String, + inverse: useColor ? init(7, 27) : String, + hidden: useColor ? init(8, 28) : String, + strikethrough: useColor ? init(9, 29) : String, + black: useColor ? init(30, 39) : String, + red: useColor ? init(31, 39) : String, + green: useColor ? init(32, 39) : String, + yellow: useColor ? init(33, 39) : String, + blue: useColor ? init(34, 39) : String, + magenta: useColor ? init(35, 39) : String, + cyan: useColor ? init(36, 39) : String, + white: useColor ? init(37, 39) : String, + gray: useColor ? init(90, 39) : String, + bgBlack: useColor ? init(40, 49) : String, + bgRed: useColor ? init(41, 49) : String, + bgGreen: useColor ? init(42, 49) : String, + bgYellow: useColor ? init(43, 49) : String, + bgBlue: useColor ? init(44, 49) : String, + bgMagenta: useColor ? init(45, 49) : String, + bgCyan: useColor ? init(46, 49) : String, + bgWhite: useColor ? init(47, 49) : String, + blackBright: useColor ? init(90, 39) : String, + redBright: useColor ? init(91, 39) : String, + greenBright: useColor ? init(92, 39) : String, + yellowBright: useColor ? init(93, 39) : String, + blueBright: useColor ? init(94, 39) : String, + magentaBright: useColor ? init(95, 39) : String, + cyanBright: useColor ? init(96, 39) : String, + whiteBright: useColor ? init(97, 39) : String, + bgBlackBright: useColor ? init(100, 49) : String, + bgRedBright: useColor ? init(101, 49) : String, + bgGreenBright: useColor ? init(102, 49) : String, + bgYellowBright: useColor ? init(103, 49) : String, + bgBlueBright: useColor ? init(104, 49) : String, + bgMagentaBright: useColor ? init(105, 49) : String, + bgCyanBright: useColor ? init(106, 49) : String, + bgWhiteBright: useColor ? init(107, 49) : String +}); + +module.exports.createColors = createColors; module.exports.getArguments = getArguments; +module.exports.isColorSupported = isColorSupported; module.exports.processArguments = processArguments; diff --git a/package.json b/package.json index 56b9a1a452f..67a02206592 100644 --- a/package.json +++ b/package.json @@ -133,7 +133,7 @@ "es6-promise-polyfill": "^1.2.0", "eslint": "^9.29.0", "eslint-config-prettier": "^10.1.1", - "eslint-config-webpack": "^4.3.0", + "eslint-config-webpack": "^4.4.1", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jest": "^29.0.1", "eslint-plugin-jsdoc": "^51.2.3", diff --git a/test/Cli.basictest.js b/test/Cli.basictest.js index ff06ea4b78d..3ea6d95f1af 100644 --- a/test/Cli.basictest.js +++ b/test/Cli.basictest.js @@ -1,90 +1,94 @@ "use strict"; -const { getArguments, processArguments } = require("../").cli; +const { createColors, getArguments, isColorSupported, processArguments } = + require("../").cli; describe("Cli", () => { - it("should generate the correct cli flags", () => { - expect(getArguments()).toMatchSnapshot(); - }); + describe("getArguments", () => { + it("should generate the correct cli flags", () => { + expect(getArguments()).toMatchSnapshot(); + }); - it("should generate the correct cli flags with custom schema", () => { - const schema = { - title: "custom CLI options", - type: "object", - additionalProperties: false, - properties: { - "with-reset-description": { - type: "array", - items: { - type: "string" + it("should generate the correct cli flags with custom schema", () => { + const schema = { + title: "custom CLI options", + type: "object", + additionalProperties: false, + properties: { + "with-reset-description": { + type: "array", + items: { + type: "string" + }, + description: "original description", + cli: { + resetDescription: "custom reset" + } }, - description: "original description", - cli: { - resetDescription: "custom reset" - } - }, - "with-cli-description": { - type: "string", - description: "original description", - cli: { - description: "description for CLI option" - } - }, - "with-negative-description": { - type: "boolean", - description: "original description", - cli: { - negatedDescription: "custom negative description" - } - }, - "with-both-cli-and-negative-description": { - type: "boolean", - description: "original description", - cli: { - description: "description for CLI option", - negatedDescription: "custom negative description" + "with-cli-description": { + type: "string", + description: "original description", + cli: { + description: "description for CLI option" + } + }, + "with-negative-description": { + type: "boolean", + description: "original description", + cli: { + negatedDescription: "custom negative description" + } + }, + "with-both-cli-and-negative-description": { + type: "boolean", + description: "original description", + cli: { + description: "description for CLI option", + negatedDescription: "custom negative description" + } } } - } - }; + }; - expect(getArguments(schema)).toMatchSnapshot(); + expect(getArguments(schema)).toMatchSnapshot(); + }); }); - const test = (name, values, config, fn) => { - it(`should correctly process arguments for ${name}`, () => { - const args = getArguments(); - const problems = processArguments(args, config, values); - fn(expect(problems || config)); - }); - }; + describe("processArguments", () => { + const test = (name, values, config, fn) => { + it(`should correctly process arguments for ${name}`, () => { + const args = getArguments(); + const problems = processArguments(args, config, values); + fn(expect(problems || config)); + }); + }; - test("none", {}, {}, (e) => e.toMatchInlineSnapshot("Object {}")); + test("none", {}, {}, (e) => e.toMatchInlineSnapshot("Object {}")); - test("root boolean", { bail: true }, {}, (e) => - e.toMatchInlineSnapshot(` + test("root boolean", { bail: true }, {}, (e) => + e.toMatchInlineSnapshot(` Object { "bail": true, } `) - ); + ); - test("root single item of multiple", { entry: "./a.js" }, {}, (e) => - e.toMatchInlineSnapshot(` + test("root single item of multiple", { entry: "./a.js" }, {}, (e) => + e.toMatchInlineSnapshot(` Object { "entry": Array [ "./a.js", ], } `) - ); + ); - test( - "root single item of multiple with existing item", - { entry: "./a.js" }, - { entry: "./old.js" }, - (e) => - e.toMatchInlineSnapshot(` + test( + "root single item of multiple with existing item", + { entry: "./a.js" }, + { entry: "./old.js" }, + (e) => + e.toMatchInlineSnapshot(` Object { "entry": Array [ "./old.js", @@ -92,14 +96,14 @@ describe("Cli", () => { ], } `) - ); + ); - test( - "root single item of multiple with existing items", - { entry: "./a.js" }, - { entry: ["./old1.js", "./old2.js"] }, - (e) => - e.toMatchInlineSnapshot(` + test( + "root single item of multiple with existing items", + { entry: "./a.js" }, + { entry: ["./old1.js", "./old2.js"] }, + (e) => + e.toMatchInlineSnapshot(` Object { "entry": Array [ "./old1.js", @@ -108,10 +112,10 @@ describe("Cli", () => { ], } `) - ); + ); - test("root multiple items", { entry: ["./a.js", "./b.js"] }, {}, (e) => - e.toMatchInlineSnapshot(` + test("root multiple items", { entry: ["./a.js", "./b.js"] }, {}, (e) => + e.toMatchInlineSnapshot(` Object { "entry": Array [ "./a.js", @@ -119,14 +123,14 @@ describe("Cli", () => { ], } `) - ); + ); - test( - "root multiple items with existing item", - { entry: ["./a.js", "./b.js"] }, - { entry: "./old.js" }, - (e) => - e.toMatchInlineSnapshot(` + test( + "root multiple items with existing item", + { entry: ["./a.js", "./b.js"] }, + { entry: "./old.js" }, + (e) => + e.toMatchInlineSnapshot(` Object { "entry": Array [ "./old.js", @@ -135,14 +139,14 @@ describe("Cli", () => { ], } `) - ); + ); - test( - "root multiple items with existing items", - { entry: ["./a.js", "./b.js"] }, - { entry: ["./old1.js", "./old2.js"] }, - (e) => - e.toMatchInlineSnapshot(` + test( + "root multiple items with existing items", + { entry: ["./a.js", "./b.js"] }, + { entry: ["./old1.js", "./old2.js"] }, + (e) => + e.toMatchInlineSnapshot(` Object { "entry": Array [ "./old1.js", @@ -152,24 +156,24 @@ describe("Cli", () => { ], } `) - ); + ); - test("nested boolean", { "experiments-top-level-await": true }, {}, (e) => - e.toMatchInlineSnapshot(` + test("nested boolean", { "experiments-top-level-await": true }, {}, (e) => + e.toMatchInlineSnapshot(` Object { "experiments": Object { "topLevelAwait": true, }, } `) - ); + ); - test( - "nested regexp", - { "stats-warnings-filter": ["/module/", "path"] }, - {}, - (e) => - e.toMatchInlineSnapshot(` + test( + "nested regexp", + { "stats-warnings-filter": ["/module/", "path"] }, + {}, + (e) => + e.toMatchInlineSnapshot(` Object { "stats": Object { "warningsFilter": Array [ @@ -179,17 +183,17 @@ describe("Cli", () => { }, } `) - ); - - test( - "nested multiple", - { - "module-rules-test": ["/\\.css$/", "/\\.js$/"], - "module-rules-use": ["css-loader", "babel-loader"] - }, - {}, - (e) => - e.toMatchInlineSnapshot(` + ); + + test( + "nested multiple", + { + "module-rules-test": ["/\\.css$/", "/\\.js$/"], + "module-rules-use": ["css-loader", "babel-loader"] + }, + {}, + (e) => + e.toMatchInlineSnapshot(` Object { "module": Object { "rules": Array [ @@ -205,30 +209,30 @@ describe("Cli", () => { }, } `) - ); - - test( - "reset array", - { - "stats-warnings-filter-reset": true, - "stats-warnings-filter": "path", - "module-rules-reset": true, - "module-rules-test": ["/\\.css$/", "/\\.js$/"], - "module-rules-use": ["css-loader", "babel-loader"] - }, - { - stats: { warningsFilter: [/a/, /b/] }, - module: { - rules: [ - { - test: /\.js$/, - use: "typescript-loader" - } - ] - } - }, - (e) => - e.toMatchInlineSnapshot(` + ); + + test( + "reset array", + { + "stats-warnings-filter-reset": true, + "stats-warnings-filter": "path", + "module-rules-reset": true, + "module-rules-test": ["/\\.css$/", "/\\.js$/"], + "module-rules-use": ["css-loader", "babel-loader"] + }, + { + stats: { warningsFilter: [/a/, /b/] }, + module: { + rules: [ + { + test: /\.js$/, + use: "typescript-loader" + } + ] + } + }, + (e) => + e.toMatchInlineSnapshot(` Object { "module": Object { "rules": Array [ @@ -249,18 +253,18 @@ describe("Cli", () => { }, } `) - ); - - test( - "numbers", - { - "watch-options-aggregate-timeout": 100, - "watch-options-poll": "100", - "output-chunk-load-timeout": "20000" - }, - {}, - (e) => - e.toMatchInlineSnapshot(` + ); + + test( + "numbers", + { + "watch-options-aggregate-timeout": 100, + "watch-options-poll": "100", + "output-chunk-load-timeout": "20000" + }, + {}, + (e) => + e.toMatchInlineSnapshot(` Object { "output": Object { "chunkLoadTimeout": 20000, @@ -271,22 +275,22 @@ describe("Cli", () => { }, } `) - ); - - test( - "booleans and enums", - { - "optimization-used-exports": true, - "output-compare-before-emit": false, - "output-iife": "true", - "output-library-name": ["hello", "world"], - "output-library-umd-named-define": "false", - "stats-logging": "verbose", - amd: "false" - }, - {}, - (e) => - e.toMatchInlineSnapshot(` + ); + + test( + "booleans and enums", + { + "optimization-used-exports": true, + "output-compare-before-emit": false, + "output-iife": "true", + "output-library-name": ["hello", "world"], + "output-library-umd-named-define": "false", + "stats-logging": "verbose", + amd: "false" + }, + {}, + (e) => + e.toMatchInlineSnapshot(` Object { "amd": false, "optimization": Object { @@ -308,28 +312,28 @@ describe("Cli", () => { }, } `) - ); - - // cspell:ignore filsystem - test( - "errors", - { - "output-library-name": "non-object", - "resolve-loader-unsafe-cache": [true, false], - "output-chunk-load-timeout": "20000x", - "cache-type": "filsystem", - "entry-reset": false, - "module-unknown-context-reg-exp": "ab?c*", - "module-wrapped-context-reg-exp": 123, - "my-argument": true - }, - { - output: { - library: "hello" - } - }, - (e) => - e.toMatchInlineSnapshot(` + ); + + // cspell:ignore filsystem + test( + "errors", + { + "output-library-name": "non-object", + "resolve-loader-unsafe-cache": [true, false], + "output-chunk-load-timeout": "20000x", + "cache-type": "filsystem", + "entry-reset": false, + "module-unknown-context-reg-exp": "ab?c*", + "module-wrapped-context-reg-exp": 123, + "my-argument": true + }, + { + output: { + library: "hello" + } + }, + (e) => + e.toMatchInlineSnapshot(` Array [ Object { "argument": "output-library-name", @@ -415,5 +419,182 @@ describe("Cli", () => { }, ] `) - ); + ); + }); + + describe("isColorSupported", () => { + const OLD_ENV = process.env; + + beforeEach(() => { + // Most important - it clears the cache + jest.resetModules(); + process.env = { ...OLD_ENV }; + }); + + afterAll(() => { + process.env = OLD_ENV; + }); + + it("env NO_COLOR", () => { + process.env.NO_COLOR = "1"; + + expect(isColorSupported()).toBe(false); + }); + + it("env FORCE_COLOR", () => { + process.env.FORCE_COLOR = "1"; + + expect(isColorSupported()).toBe(true); + }); + + it("env TERM", () => { + const isCI = + "CI" in process.env && + ("GITHUB_ACTIONS" in process.env || + "GITLAB_CI" in process.env || + "CIRCLECI" in process.env); + + process.env.TERM = "dumb"; + + expect(isColorSupported()).toBe(isCI); + }); + + it("env CI", () => { + process.env.CI = "1"; + + expect(isColorSupported()).toBe(true); + }); + + it("env GITHUB_ACTIONS", () => { + process.env.GITHUB_ACTIONS = "1"; + + expect(isColorSupported()).toBe(true); + }); + + it("env GITLAB_CI", () => { + process.env.GITLAB_CI = "1"; + + expect(isColorSupported()).toBe(true); + }); + + it("env CIRCLECI", () => { + process.env.CIRCLECI = "1"; + + expect(isColorSupported()).toBe(true); + }); + }); + + describe("createColors", () => { + const colorsMap = [ + ["reset", "\u001B[0m", "\u001B[0m"], + ["bold", "\u001B[1m", "\u001B[22m"], + ["dim", "\u001B[2m", "\u001B[22m"], + ["italic", "\u001B[3m", "\u001B[23m"], + ["underline", "\u001B[4m", "\u001B[24m"], + ["inverse", "\u001B[7m", "\u001B[27m"], + ["hidden", "\u001B[8m", "\u001B[28m"], + ["strikethrough", "\u001B[9m", "\u001B[29m"], + ["black", "\u001B[30m", "\u001B[39m"], + ["red", "\u001B[31m", "\u001B[39m"], + ["green", "\u001B[32m", "\u001B[39m"], + ["yellow", "\u001B[33m", "\u001B[39m"], + ["blue", "\u001B[34m", "\u001B[39m"], + ["magenta", "\u001B[35m", "\u001B[39m"], + ["cyan", "\u001B[36m", "\u001B[39m"], + ["white", "\u001B[37m", "\u001B[39m"], + ["gray", "\u001B[90m", "\u001B[39m"], + ["bgBlack", "\u001B[40m", "\u001B[49m"], + ["bgRed", "\u001B[41m", "\u001B[49m"], + ["bgGreen", "\u001B[42m", "\u001B[49m"], + ["bgYellow", "\u001B[43m", "\u001B[49m"], + ["bgBlue", "\u001B[44m", "\u001B[49m"], + ["bgMagenta", "\u001B[45m", "\u001B[49m"], + ["bgCyan", "\u001B[46m", "\u001B[49m"], + ["bgWhite", "\u001B[47m", "\u001B[49m"], + ["blackBright", "\u001B[90m", "\u001B[39m"], + ["redBright", "\u001B[91m", "\u001B[39m"], + ["greenBright", "\u001B[92m", "\u001B[39m"], + ["yellowBright", "\u001B[93m", "\u001B[39m"], + ["blueBright", "\u001B[94m", "\u001B[39m"], + ["magentaBright", "\u001B[95m", "\u001B[39m"], + ["cyanBright", "\u001B[96m", "\u001B[39m"], + ["whiteBright", "\u001B[97m", "\u001B[39m"], + ["bgBlackBright", "\u001B[100m", "\u001B[49m"], + ["bgRedBright", "\u001B[101m", "\u001B[49m"], + ["bgGreenBright", "\u001B[102m", "\u001B[49m"], + ["bgYellowBright", "\u001B[103m", "\u001B[49m"], + ["bgBlueBright", "\u001B[104m", "\u001B[49m"], + ["bgMagentaBright", "\u001B[105m", "\u001B[49m"], + ["bgCyanBright", "\u001B[106m", "\u001B[49m"], + ["bgWhiteBright", "\u001B[107m", "\u001B[49m"] + ]; + + const colors = createColors({ useColor: true }); + + it("simple", () => { + for (const [name, open, close] of colorsMap) { + expect(colors[name](name)).toBe(open + name + close); + } + }); + + it("nesting", () => { + expect( + colors.bold(`bold ${colors.red(`red ${colors.dim("dim")} red`)} bold`) + ).toBe( + /* cspell:disable-next-line */ + "\u001B[1mbold \u001B[31mred \u001B[2mdim\u001B[22m\u001B[1m red\u001B[39m bold\u001B[22m" + ); + expect( + colors.magenta( + `magenta ${colors.yellow( + `yellow ${colors.cyan("cyan")} ${colors.red("red")} ${colors.green( + "green" + )} yellow` + )} magenta` + ) + ).toBe( + /* cspell:disable-next-line */ + "\u001B[35mmagenta \u001B[33myellow \u001B[36mcyan\u001B[33m \u001B[31mred\u001B[33m \u001B[32mgreen\u001B[33m yellow\u001B[35m magenta\u001B[39m" + ); + }); + + it("numbers & others", () => { + for (const n of [new Date(), -1e10, -1, -0.1, 0, 0.1, 1, 1e10]) { + expect(colors.red(n)).toBe(`\u001B[31m${n}\u001B[39m`); + } + }); + + it("empty & falsy values", () => { + expect(colors.blue()).toBe(""); + expect(colors.blue("")).toBe(""); + expect(colors.blue(undefined)).toBe(""); + expect(colors.blue(0)).toBe("\u001B[34m0\u001B[39m"); + // eslint-disable-next-line unicorn/prefer-number-properties + expect(colors.blue(NaN)).toBe("\u001B[34mNaN\u001B[39m"); + expect(colors.blue(Number.NaN)).toBe("\u001B[34mNaN\u001B[39m"); + /* cspell:disable-next-line */ + expect(colors.blue(null)).toBe("\u001B[34mnull\u001B[39m"); + /* cspell:disable-next-line */ + expect(colors.blue(true)).toBe("\u001B[34mtrue\u001B[39m"); + /* cspell:disable-next-line */ + expect(colors.blue(false)).toBe("\u001B[34mfalse\u001B[39m"); + expect(colors.blue(Infinity)).toBe("\u001B[34mInfinity\u001B[39m"); + }); + + const noColors = createColors({ useColor: false }); + + it("simple (no colors)", () => { + for (const [name] of colorsMap) { + expect(noColors[name](name)).toBe(name); + } + }); + + const defaultColors = createColors(); + + it("simple (colors by default)", () => { + for (const [name, open, close] of colorsMap) { + expect(defaultColors[name](name)).toBe(open + name + close); + } + }); + }); }); diff --git a/test/__snapshots__/Cli.basictest.js.snap b/test/__snapshots__/Cli.basictest.js.snap index 6aba60c2da1..982f9fd2163 100644 --- a/test/__snapshots__/Cli.basictest.js.snap +++ b/test/__snapshots__/Cli.basictest.js.snap @@ -1,6 +1,6 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP +// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing -exports[`Cli should generate the correct cli flags 1`] = ` +exports[`Cli getArguments should generate the correct cli flags 1`] = ` Object { "amd": Object { "configs": Array [ @@ -10385,7 +10385,7 @@ Object { } `; -exports[`Cli should generate the correct cli flags with custom schema 1`] = ` +exports[`Cli getArguments should generate the correct cli flags with custom schema 1`] = ` Object { "with-both-cli-and-negative-description": Object { "configs": Array [ diff --git a/types.d.ts b/types.d.ts index 885aca9fa47..2fa4312278f 100644 --- a/types.d.ts +++ b/types.d.ts @@ -1951,6 +1951,49 @@ type CodeValuePrimitive = | boolean | Function | RegExp; +declare interface Colors { + reset: (value?: any) => string; + bold: (value?: any) => string; + dim: (value?: any) => string; + italic: (value?: any) => string; + underline: (value?: any) => string; + inverse: (value?: any) => string; + hidden: (value?: any) => string; + strikethrough: (value?: any) => string; + black: (value?: any) => string; + red: (value?: any) => string; + green: (value?: any) => string; + yellow: (value?: any) => string; + blue: (value?: any) => string; + magenta: (value?: any) => string; + cyan: (value?: any) => string; + white: (value?: any) => string; + gray: (value?: any) => string; + bgBlack: (value?: any) => string; + bgRed: (value?: any) => string; + bgGreen: (value?: any) => string; + bgYellow: (value?: any) => string; + bgBlue: (value?: any) => string; + bgMagenta: (value?: any) => string; + bgCyan: (value?: any) => string; + bgWhite: (value?: any) => string; + blackBright: (value?: any) => string; + redBright: (value?: any) => string; + greenBright: (value?: any) => string; + yellowBright: (value?: any) => string; + blueBright: (value?: any) => string; + magentaBright: (value?: any) => string; + cyanBright: (value?: any) => string; + whiteBright: (value?: any) => string; + bgBlackBright: (value?: any) => string; + bgRedBright: (value?: any) => string; + bgGreenBright: (value?: any) => string; + bgYellowBright: (value?: any) => string; + bgBlueBright: (value?: any) => string; + bgMagentaBright: (value?: any) => string; + bgCyanBright: (value?: any) => string; + bgWhiteBright: (value?: any) => string; +} declare interface Comparator { (a: T, b: T): 0 | 1 | -1; } @@ -17412,6 +17455,7 @@ declare namespace exports { ) => void; export const version: string; export namespace cli { + export let createColors: (__0?: { useColor?: boolean }) => Colors; export let getArguments: ( schema?: | (JSONSchema4 & { @@ -17448,6 +17492,7 @@ declare namespace exports { }; }) ) => Flags; + export let isColorSupported: () => boolean; export let processArguments: ( args: Flags, config: ObjectConfiguration, diff --git a/yarn.lock b/yarn.lock index f4416992c06..b43f33607ff 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3319,10 +3319,10 @@ eslint-config-prettier@^10.1.1: resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz#00c18d7225043b6fbce6a665697377998d453782" integrity sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw== -eslint-config-webpack@^4.3.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/eslint-config-webpack/-/eslint-config-webpack-4.4.0.tgz#56fae0c217c1226b3ce9f3e00f4ce62d8f1cc6b1" - integrity sha512-W0hMYVayDR4Sk+owcKtJDNEoiFDTHNzQJk/wnIBOxh6xjgOVj9MnHPtIP6AB3Ru2Suc+T8juIjfxyn3vuM0ptg== +eslint-config-webpack@^4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/eslint-config-webpack/-/eslint-config-webpack-4.4.1.tgz#cfcb77c3295c8f1c3fcbd523d71e2ccc7092e16a" + integrity sha512-IPerJYT5ErPUbrVUCNVQF5RmCUrnA1Am8D1wJufetmEu4hsZXzigy4wP6uroLv8s9GBpiEPM5NZ0PHmao4tUMw== dependencies: detect-indent "^7.0.1" jsonc-eslint-parser "^2.4.0"