source: frontend/node_modules/webpack/lib/cli.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 11 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 25.1 KB
Line 
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5
6"use strict";
7
8const path = require("path");
9const tty = require("tty");
10const webpackSchema =
11 /** @type {EXPECTED_ANY} */
12 (require("../schemas/WebpackOptions.json"));
13
14/** @typedef {import("json-schema").JSONSchema4} JSONSchema4 */
15/** @typedef {import("json-schema").JSONSchema6} JSONSchema6 */
16/** @typedef {import("json-schema").JSONSchema7} JSONSchema7 */
17/** @typedef {JSONSchema4 | JSONSchema6 | JSONSchema7} JSONSchema */
18/** @typedef {JSONSchema & { absolutePath: boolean, instanceof: string, cli: { helper?: boolean, exclude?: boolean, description?: string, negatedDescription?: string, resetDescription?: string } }} Schema */
19
20// TODO add originPath to PathItem for better errors
21/**
22 * Defines the path item type used by this module.
23 * @typedef {object} PathItem
24 * @property {Schema} schema the part of the schema
25 * @property {string} path the path in the config
26 */
27
28/** @typedef {"unknown-argument" | "unexpected-non-array-in-path" | "unexpected-non-object-in-path" | "multiple-values-unexpected" | "invalid-value"} ProblemType */
29
30/** @typedef {string | number | boolean | RegExp} Value */
31
32/**
33 * Defines the problem type used by this module.
34 * @typedef {object} Problem
35 * @property {ProblemType} type
36 * @property {string} path
37 * @property {string} argument
38 * @property {Value=} value
39 * @property {number=} index
40 * @property {string=} expected
41 */
42
43/**
44 * Defines the local problem type used by this module.
45 * @typedef {object} LocalProblem
46 * @property {ProblemType} type
47 * @property {string} path
48 * @property {string=} expected
49 */
50
51/** @typedef {{ [key: string]: EnumValue }} EnumValueObject */
52/** @typedef {EnumValue[]} EnumValueArray */
53/** @typedef {string | number | boolean | EnumValueObject | EnumValueArray | null} EnumValue */
54
55/**
56 * Defines the argument config type used by this module.
57 * @typedef {object} ArgumentConfig
58 * @property {string=} description
59 * @property {string=} negatedDescription
60 * @property {string} path
61 * @property {boolean} multiple
62 * @property {"enum" | "string" | "path" | "number" | "boolean" | "RegExp" | "reset"} type
63 * @property {EnumValue[]=} values
64 */
65
66/** @typedef {"string" | "number" | "boolean"} SimpleType */
67
68/**
69 * Defines the argument type used by this module.
70 * @typedef {object} Argument
71 * @property {string | undefined} description
72 * @property {SimpleType} simpleType
73 * @property {boolean} multiple
74 * @property {ArgumentConfig[]} configs
75 */
76
77/** @typedef {Record<string, Argument>} Flags */
78
79/** @typedef {Record<string, EXPECTED_ANY>} ObjectConfiguration */
80
81/**
82 * Returns object of arguments.
83 * @param {Schema=} schema a json schema to create arguments for (by default webpack schema is used)
84 * @returns {Flags} object of arguments
85 */
86const getArguments = (schema = webpackSchema) => {
87 /** @type {Flags} */
88 const flags = {};
89
90 /**
91 * Path to argument name.
92 * @param {string} input input
93 * @returns {string} result
94 */
95 const pathToArgumentName = (input) =>
96 input
97 .replace(/\./g, "-")
98 .replace(/\[\]/g, "")
99 .replace(
100 /(\p{Uppercase_Letter}+|\p{Lowercase_Letter}|\d)(\p{Uppercase_Letter}+)/gu,
101 "$1-$2"
102 )
103 .replace(/-?[^\p{Uppercase_Letter}\p{Lowercase_Letter}\d]+/gu, "-")
104 .toLowerCase();
105
106 /**
107 * Returns schema part.
108 * @param {string} path path
109 * @returns {Schema} schema part
110 */
111 const getSchemaPart = (path) => {
112 const newPath = path.split("/");
113
114 let schemaPart = schema;
115
116 for (let i = 1; i < newPath.length; i++) {
117 const inner = schemaPart[/** @type {keyof Schema} */ (newPath[i])];
118
119 if (!inner) {
120 break;
121 }
122
123 schemaPart = inner;
124 }
125
126 return schemaPart;
127 };
128
129 /**
130 * Returns description.
131 * @param {PathItem[]} path path in the schema
132 * @returns {string | undefined} description
133 */
134 const getDescription = (path) => {
135 for (const { schema } of path) {
136 if (schema.cli) {
137 if (schema.cli.helper) continue;
138 if (schema.cli.description) return schema.cli.description;
139 }
140 if (schema.description) return schema.description;
141 }
142 };
143
144 /**
145 * Gets negated description.
146 * @param {PathItem[]} path path in the schema
147 * @returns {string | undefined} negative description
148 */
149 const getNegatedDescription = (path) => {
150 for (const { schema } of path) {
151 if (schema.cli) {
152 if (schema.cli.helper) continue;
153 if (schema.cli.negatedDescription) return schema.cli.negatedDescription;
154 }
155 }
156 };
157
158 /**
159 * Gets reset description.
160 * @param {PathItem[]} path path in the schema
161 * @returns {string | undefined} reset description
162 */
163 const getResetDescription = (path) => {
164 for (const { schema } of path) {
165 if (schema.cli) {
166 if (schema.cli.helper) continue;
167 if (schema.cli.resetDescription) return schema.cli.resetDescription;
168 }
169 }
170 };
171
172 /**
173 * Schema to argument config.
174 * @param {Schema} schemaPart schema
175 * @returns {Pick<ArgumentConfig, "type" | "values"> | undefined} partial argument config
176 */
177 const schemaToArgumentConfig = (schemaPart) => {
178 if (schemaPart.enum) {
179 return {
180 type: "enum",
181 values: schemaPart.enum
182 };
183 }
184 switch (schemaPart.type) {
185 case "number":
186 return {
187 type: "number"
188 };
189 case "string":
190 return {
191 type: schemaPart.absolutePath ? "path" : "string"
192 };
193 case "boolean":
194 return {
195 type: "boolean"
196 };
197 }
198 if (schemaPart.instanceof === "RegExp") {
199 return {
200 type: "RegExp"
201 };
202 }
203 return undefined;
204 };
205
206 /**
207 * Adds the provided path to this object.
208 * @param {PathItem[]} path path in the schema
209 * @returns {void}
210 */
211 const addResetFlag = (path) => {
212 const schemaPath = path[0].path;
213 const name = pathToArgumentName(`${schemaPath}.reset`);
214 const description =
215 getResetDescription(path) ||
216 `Clear all items provided in '${schemaPath}' configuration. ${getDescription(
217 path
218 )}`;
219 flags[name] = {
220 configs: [
221 {
222 type: "reset",
223 multiple: false,
224 description,
225 path: schemaPath
226 }
227 ],
228 description: undefined,
229 simpleType:
230 /** @type {SimpleType} */
231 (/** @type {unknown} */ (undefined)),
232 multiple: /** @type {boolean} */ (/** @type {unknown} */ (undefined))
233 };
234 };
235
236 /**
237 * Adds the provided path to this object.
238 * @param {PathItem[]} path full path in schema
239 * @param {boolean} multiple inside of an array
240 * @returns {number} number of arguments added
241 */
242 const addFlag = (path, multiple) => {
243 const argConfigBase = schemaToArgumentConfig(path[0].schema);
244 if (!argConfigBase) return 0;
245
246 const negatedDescription = getNegatedDescription(path);
247 const name = pathToArgumentName(path[0].path);
248 /** @type {ArgumentConfig} */
249 const argConfig = {
250 ...argConfigBase,
251 multiple,
252 description: getDescription(path),
253 path: path[0].path
254 };
255
256 if (negatedDescription) {
257 argConfig.negatedDescription = negatedDescription;
258 }
259
260 if (!flags[name]) {
261 flags[name] = {
262 configs: [],
263 description: undefined,
264 simpleType:
265 /** @type {SimpleType} */
266 (/** @type {unknown} */ (undefined)),
267 multiple: /** @type {boolean} */ (/** @type {unknown} */ (undefined))
268 };
269 }
270
271 if (
272 flags[name].configs.some(
273 (item) => JSON.stringify(item) === JSON.stringify(argConfig)
274 )
275 ) {
276 return 0;
277 }
278
279 if (
280 flags[name].configs.some(
281 (item) => item.type === argConfig.type && item.multiple !== multiple
282 )
283 ) {
284 if (multiple) {
285 throw new Error(
286 `Conflicting schema for ${path[0].path} with ${argConfig.type} type (array type must be before single item type)`
287 );
288 }
289 return 0;
290 }
291
292 flags[name].configs.push(argConfig);
293
294 return 1;
295 };
296
297 // TODO support `not` and `if/then/else`
298 // TODO support `const`, but we don't use it on our schema
299 /**
300 * Returns added arguments.
301 * @param {Schema} schemaPart the current schema
302 * @param {string} schemaPath the current path in the schema
303 * @param {PathItem[]} path all previous visited schemaParts
304 * @param {string | null} inArray if inside of an array, the path to the array
305 * @returns {number} added arguments
306 */
307 const traverse = (schemaPart, schemaPath = "", path = [], inArray = null) => {
308 while (schemaPart.$ref) {
309 schemaPart = getSchemaPart(schemaPart.$ref);
310 }
311
312 const repetitions = path.filter(({ schema }) => schema === schemaPart);
313 if (
314 repetitions.length >= 2 ||
315 repetitions.some(({ path }) => path === schemaPath)
316 ) {
317 return 0;
318 }
319
320 if (schemaPart.cli && schemaPart.cli.exclude) return 0;
321
322 /** @type {PathItem[]} */
323 const fullPath = [{ schema: schemaPart, path: schemaPath }, ...path];
324
325 let addedArguments = 0;
326
327 addedArguments += addFlag(fullPath, Boolean(inArray));
328
329 if (schemaPart.type === "object") {
330 if (schemaPart.properties) {
331 for (const property of Object.keys(schemaPart.properties)) {
332 addedArguments += traverse(
333 /** @type {Schema} */
334 (schemaPart.properties[property]),
335 schemaPath ? `${schemaPath}.${property}` : property,
336 fullPath,
337 inArray
338 );
339 }
340 }
341
342 return addedArguments;
343 }
344
345 if (schemaPart.type === "array") {
346 if (inArray) {
347 return 0;
348 }
349 if (Array.isArray(schemaPart.items)) {
350 const i = 0;
351 for (const item of schemaPart.items) {
352 addedArguments += traverse(
353 /** @type {Schema} */
354 (item),
355 `${schemaPath}.${i}`,
356 fullPath,
357 schemaPath
358 );
359 }
360
361 return addedArguments;
362 }
363
364 addedArguments += traverse(
365 /** @type {Schema} */
366 (schemaPart.items),
367 `${schemaPath}[]`,
368 fullPath,
369 schemaPath
370 );
371
372 if (addedArguments > 0) {
373 addResetFlag(fullPath);
374 addedArguments++;
375 }
376
377 return addedArguments;
378 }
379
380 const maybeOf = schemaPart.oneOf || schemaPart.anyOf || schemaPart.allOf;
381
382 if (maybeOf) {
383 const items = maybeOf;
384
385 for (let i = 0; i < items.length; i++) {
386 addedArguments += traverse(
387 /** @type {Schema} */
388 (items[i]),
389 schemaPath,
390 fullPath,
391 inArray
392 );
393 }
394
395 return addedArguments;
396 }
397
398 return addedArguments;
399 };
400
401 traverse(schema);
402
403 // Summarize flags
404 for (const name of Object.keys(flags)) {
405 /** @type {Argument} */
406 const argument = flags[name];
407 argument.description = argument.configs.reduce((desc, { description }) => {
408 if (!desc) return description;
409 if (!description) return desc;
410 if (desc.includes(description)) return desc;
411 return `${desc} ${description}`;
412 }, /** @type {string | undefined} */ (undefined));
413 argument.simpleType =
414 /** @type {SimpleType} */
415 (
416 argument.configs.reduce((t, argConfig) => {
417 /** @type {SimpleType} */
418 let type = "string";
419 switch (argConfig.type) {
420 case "number":
421 type = "number";
422 break;
423 case "reset":
424 case "boolean":
425 type = "boolean";
426 break;
427 case "enum": {
428 const values =
429 /** @type {NonNullable<ArgumentConfig["values"]>} */
430 (argConfig.values);
431
432 if (values.every((v) => typeof v === "boolean")) type = "boolean";
433 if (values.every((v) => typeof v === "number")) type = "number";
434 break;
435 }
436 }
437 if (t === undefined) return type;
438 return t === type ? t : "string";
439 }, /** @type {SimpleType | undefined} */ (undefined))
440 );
441 argument.multiple = argument.configs.some((c) => c.multiple);
442 }
443
444 return flags;
445};
446
447/** @type {WeakMap<EXPECTED_OBJECT, number>} */
448const cliAddedItems = new WeakMap();
449
450/** @typedef {string | number} Property */
451
452/**
453 * Gets object and property.
454 * @param {ObjectConfiguration} config configuration
455 * @param {string} schemaPath path in the config
456 * @param {number | undefined} index index of value when multiple values are provided, otherwise undefined
457 * @returns {{ problem?: LocalProblem, object?: ObjectConfiguration, property?: Property, value?: EXPECTED_OBJECT | EXPECTED_ANY[] }} problem or object with property and value
458 */
459const getObjectAndProperty = (config, schemaPath, index = 0) => {
460 if (!schemaPath) return { value: config };
461 const parts = schemaPath.split(".");
462 const property = /** @type {string} */ (parts.pop());
463 let current = config;
464 let i = 0;
465 for (const part of parts) {
466 const isArray = part.endsWith("[]");
467 const name = isArray ? part.slice(0, -2) : part;
468 let value = current[name];
469 if (isArray) {
470 if (value === undefined) {
471 value = {};
472 current[name] = [...Array.from({ length: index }), value];
473 cliAddedItems.set(current[name], index + 1);
474 } else if (!Array.isArray(value)) {
475 return {
476 problem: {
477 type: "unexpected-non-array-in-path",
478 path: parts.slice(0, i).join(".")
479 }
480 };
481 } else {
482 let addedItems = cliAddedItems.get(value) || 0;
483 while (addedItems <= index) {
484 value.push(undefined);
485 addedItems++;
486 }
487 cliAddedItems.set(value, addedItems);
488 const x = value.length - addedItems + index;
489 if (value[x] === undefined) {
490 value[x] = {};
491 } else if (value[x] === null || typeof value[x] !== "object") {
492 return {
493 problem: {
494 type: "unexpected-non-object-in-path",
495 path: parts.slice(0, i).join(".")
496 }
497 };
498 }
499 value = value[x];
500 }
501 } else if (value === undefined) {
502 value = current[name] = {};
503 } else if (value === null || typeof value !== "object") {
504 return {
505 problem: {
506 type: "unexpected-non-object-in-path",
507 path: parts.slice(0, i).join(".")
508 }
509 };
510 }
511 current = value;
512 i++;
513 }
514 const value = current[property];
515 if (property.endsWith("[]")) {
516 const name = property.slice(0, -2);
517 const value = current[name];
518 if (value === undefined) {
519 current[name] = [...Array.from({ length: index }), undefined];
520 cliAddedItems.set(current[name], index + 1);
521 return { object: current[name], property: index, value: undefined };
522 } else if (!Array.isArray(value)) {
523 current[name] = [value, ...Array.from({ length: index }), undefined];
524 cliAddedItems.set(current[name], index + 1);
525 return { object: current[name], property: index + 1, value: undefined };
526 }
527 let addedItems = cliAddedItems.get(value) || 0;
528 while (addedItems <= index) {
529 value.push(undefined);
530 addedItems++;
531 }
532 cliAddedItems.set(value, addedItems);
533 const x = value.length - addedItems + index;
534 if (value[x] === undefined) {
535 value[x] = {};
536 } else if (value[x] === null || typeof value[x] !== "object") {
537 return {
538 problem: {
539 type: "unexpected-non-object-in-path",
540 path: schemaPath
541 }
542 };
543 }
544 return {
545 object: value,
546 property: x,
547 value: value[x]
548 };
549 }
550 return { object: current, property, value };
551};
552
553/**
554 * Updates value using the provided config.
555 * @param {ObjectConfiguration} config configuration
556 * @param {string} schemaPath path in the config
557 * @param {ParsedValue} value parsed value
558 * @param {number | undefined} index index of value when multiple values are provided, otherwise undefined
559 * @returns {LocalProblem | null} problem or null for success
560 */
561const setValue = (config, schemaPath, value, index) => {
562 const { problem, object, property } = getObjectAndProperty(
563 config,
564 schemaPath,
565 index
566 );
567 if (problem) return problem;
568 /** @type {ObjectConfiguration} */
569 (object)[/** @type {Property} */ (property)] = value;
570 return null;
571};
572
573/**
574 * Process argument config.
575 * @param {ArgumentConfig} argConfig processing instructions
576 * @param {ObjectConfiguration} config configuration
577 * @param {Value} value the value
578 * @param {number | undefined} index the index if multiple values provided
579 * @returns {LocalProblem | null} a problem if any
580 */
581const processArgumentConfig = (argConfig, config, value, index) => {
582 if (index !== undefined && !argConfig.multiple) {
583 return {
584 type: "multiple-values-unexpected",
585 path: argConfig.path
586 };
587 }
588 const parsed = parseValueForArgumentConfig(argConfig, value);
589 if (parsed === undefined) {
590 return {
591 type: "invalid-value",
592 path: argConfig.path,
593 expected: getExpectedValue(argConfig)
594 };
595 }
596 const problem = setValue(config, argConfig.path, parsed, index);
597 if (problem) return problem;
598 return null;
599};
600
601/**
602 * Gets expected value.
603 * @param {ArgumentConfig} argConfig processing instructions
604 * @returns {string | undefined} expected message
605 */
606const getExpectedValue = (argConfig) => {
607 switch (argConfig.type) {
608 case "boolean":
609 return "true | false";
610 case "RegExp":
611 return "regular expression (example: /ab?c*/)";
612 case "enum":
613 return /** @type {NonNullable<ArgumentConfig["values"]>} */ (
614 argConfig.values
615 )
616 .map((v) => `${v}`)
617 .join(" | ");
618 case "reset":
619 return "true (will reset the previous value to an empty array)";
620 default:
621 return argConfig.type;
622 }
623};
624
625/** @typedef {null | string | number | boolean | RegExp | EnumValue | []} ParsedValue */
626
627const DECIMAL_NUMBER_REGEXP = /^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i;
628
629/**
630 * Parses value for argument config.
631 * @param {ArgumentConfig} argConfig processing instructions
632 * @param {Value} value the value
633 * @returns {ParsedValue | undefined} parsed value
634 */
635const parseValueForArgumentConfig = (argConfig, value) => {
636 switch (argConfig.type) {
637 case "string":
638 if (typeof value === "string") {
639 return value;
640 }
641 break;
642 case "path":
643 if (typeof value === "string") {
644 return path.resolve(value);
645 }
646 break;
647 case "number":
648 if (typeof value === "number") return value;
649 if (typeof value === "string" && DECIMAL_NUMBER_REGEXP.test(value)) {
650 const n = Number(value);
651 if (!Number.isNaN(n)) return n;
652 }
653 break;
654 case "boolean":
655 if (typeof value === "boolean") return value;
656 if (value === "true") return true;
657 if (value === "false") return false;
658 break;
659 case "RegExp":
660 if (value instanceof RegExp) return value;
661 if (typeof value === "string") {
662 // cspell:word yugi
663 const match = /^\/(.*)\/([yugi]*)$/.exec(value);
664 if (match && !/[^\\]\//.test(match[1])) {
665 return new RegExp(match[1], match[2]);
666 }
667 }
668 break;
669 case "enum": {
670 const values =
671 /** @type {EnumValue[]} */
672 (argConfig.values);
673 if (values.includes(/** @type {Exclude<Value, RegExp>} */ (value))) {
674 return value;
675 }
676 for (const item of values) {
677 if (`${item}` === value) return item;
678 }
679 break;
680 }
681 case "reset":
682 if (value === true) return [];
683 break;
684 }
685};
686
687/** @typedef {Record<string, Value[]>} Values */
688
689/**
690 * Processes the provided arg.
691 * @param {Flags} args object of arguments
692 * @param {ObjectConfiguration} config configuration
693 * @param {Values} values object with values
694 * @returns {Problem[] | null} problems or null for success
695 */
696const processArguments = (args, config, values) => {
697 /** @type {Problem[]} */
698 const problems = [];
699 for (const key of Object.keys(values)) {
700 const arg = args[key];
701 if (!arg) {
702 problems.push({
703 type: "unknown-argument",
704 path: "",
705 argument: key
706 });
707 continue;
708 }
709 /**
710 * Processes the provided value.
711 * @param {Value} value value
712 * @param {number | undefined} i index
713 */
714 const processValue = (value, i) => {
715 /** @type {Problem[]} */
716 const currentProblems = [];
717 for (const argConfig of arg.configs) {
718 const problem = processArgumentConfig(argConfig, config, value, i);
719 if (!problem) {
720 return;
721 }
722 currentProblems.push({
723 ...problem,
724 argument: key,
725 value,
726 index: i
727 });
728 }
729 problems.push(...currentProblems);
730 };
731 const value = values[key];
732 if (Array.isArray(value)) {
733 for (let i = 0; i < value.length; i++) {
734 processValue(value[i], i);
735 }
736 } else {
737 processValue(value, undefined);
738 }
739 }
740 if (problems.length === 0) return null;
741 return problems;
742};
743
744/**
745 * Checks whether this object is color supported.
746 * @returns {boolean} true when colors supported, otherwise false
747 */
748const isColorSupported = () => {
749 const { env = {}, argv = [], platform = "" } = process;
750
751 const isDisabled = "NO_COLOR" in env || argv.includes("--no-color");
752 const isForced = "FORCE_COLOR" in env || argv.includes("--color");
753 const isWindows = platform === "win32";
754 const isDumbTerminal = env.TERM === "dumb";
755
756 const isCompatibleTerminal = tty.isatty(1) && env.TERM && !isDumbTerminal;
757
758 const isCI =
759 "CI" in env &&
760 ("GITHUB_ACTIONS" in env || "GITLAB_CI" in env || "CIRCLECI" in env);
761
762 return (
763 !isDisabled &&
764 (isForced || (isWindows && !isDumbTerminal) || isCompatibleTerminal || isCI)
765 );
766};
767
768/**
769 * Returns result.
770 * @param {number} index index
771 * @param {string} string string
772 * @param {string} close close
773 * @param {string=} replace replace
774 * @param {string=} head head
775 * @param {string=} tail tail
776 * @param {number=} next next
777 * @returns {string} result
778 */
779const replaceClose = (
780 index,
781 string,
782 close,
783 replace,
784 head = string.slice(0, Math.max(0, index)) + replace,
785 tail = string.slice(Math.max(0, index + close.length)),
786 next = tail.indexOf(close)
787) => head + (next < 0 ? tail : replaceClose(next, tail, close, replace));
788
789/**
790 * Returns result.
791 * @param {number} index index to replace
792 * @param {string} string string
793 * @param {string} open open string
794 * @param {string} close close string
795 * @param {string=} replace extra replace
796 * @returns {string} result
797 */
798const clearBleed = (index, string, open, close, replace) =>
799 index < 0
800 ? open + string + close
801 : open + replaceClose(index, string, close, replace) + close;
802
803/** @typedef {(value: EXPECTED_ANY) => string} PrintFunction */
804
805/**
806 * Returns function to create color.
807 * @param {string} open open string
808 * @param {string} close close string
809 * @param {string=} replace extra replace
810 * @param {number=} at at
811 * @returns {PrintFunction} function to create color
812 */
813const filterEmpty =
814 (open, close, replace = open, at = open.length + 1) =>
815 (string) =>
816 string || !(string === "" || string === undefined)
817 ? clearBleed(`${string}`.indexOf(close, at), string, open, close, replace)
818 : "";
819
820/**
821 * Returns result.
822 * @param {number} open open code
823 * @param {number} close close code
824 * @param {string=} replace extra replace
825 * @returns {PrintFunction} result
826 */
827const init = (open, close, replace) =>
828 filterEmpty(`\u001B[${open}m`, `\u001B[${close}m`, replace);
829
830/**
831 * Defines the colors type used by this module.
832 * @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
833 */
834
835/**
836 * Defines the colors options type used by this module.
837 * @typedef {object} ColorsOptions
838 * @property {boolean=} useColor force use colors
839 */
840
841/**
842 * Creates a colors from the provided colors option.
843 * @param {ColorsOptions=} options options
844 * @returns {Colors} colors
845 */
846const createColors = ({ useColor = isColorSupported() } = {}) => ({
847 reset: useColor ? init(0, 0) : String,
848 bold: useColor ? init(1, 22, "\u001B[22m\u001B[1m") : String,
849 dim: useColor ? init(2, 22, "\u001B[22m\u001B[2m") : String,
850 italic: useColor ? init(3, 23) : String,
851 underline: useColor ? init(4, 24) : String,
852 inverse: useColor ? init(7, 27) : String,
853 hidden: useColor ? init(8, 28) : String,
854 strikethrough: useColor ? init(9, 29) : String,
855 black: useColor ? init(30, 39) : String,
856 red: useColor ? init(31, 39) : String,
857 green: useColor ? init(32, 39) : String,
858 yellow: useColor ? init(33, 39) : String,
859 blue: useColor ? init(34, 39) : String,
860 magenta: useColor ? init(35, 39) : String,
861 cyan: useColor ? init(36, 39) : String,
862 white: useColor ? init(37, 39) : String,
863 gray: useColor ? init(90, 39) : String,
864 bgBlack: useColor ? init(40, 49) : String,
865 bgRed: useColor ? init(41, 49) : String,
866 bgGreen: useColor ? init(42, 49) : String,
867 bgYellow: useColor ? init(43, 49) : String,
868 bgBlue: useColor ? init(44, 49) : String,
869 bgMagenta: useColor ? init(45, 49) : String,
870 bgCyan: useColor ? init(46, 49) : String,
871 bgWhite: useColor ? init(47, 49) : String,
872 blackBright: useColor ? init(90, 39) : String,
873 redBright: useColor ? init(91, 39) : String,
874 greenBright: useColor ? init(92, 39) : String,
875 yellowBright: useColor ? init(93, 39) : String,
876 blueBright: useColor ? init(94, 39) : String,
877 magentaBright: useColor ? init(95, 39) : String,
878 cyanBright: useColor ? init(96, 39) : String,
879 whiteBright: useColor ? init(97, 39) : String,
880 bgBlackBright: useColor ? init(100, 49) : String,
881 bgRedBright: useColor ? init(101, 49) : String,
882 bgGreenBright: useColor ? init(102, 49) : String,
883 bgYellowBright: useColor ? init(103, 49) : String,
884 bgBlueBright: useColor ? init(104, 49) : String,
885 bgMagentaBright: useColor ? init(105, 49) : String,
886 bgCyanBright: useColor ? init(106, 49) : String,
887 bgWhiteBright: useColor ? init(107, 49) : String
888});
889
890module.exports.createColors = createColors;
891module.exports.getArguments = getArguments;
892module.exports.isColorSupported = isColorSupported;
893module.exports.processArguments = processArguments;
Note: See TracBrowser for help on using the repository browser.