refactor(options): use supportOptions to generate CLI options (#3622)
* refactor(cli-constant): use supportOptions * refactor(options): use supportOptions * refactor(cli-util): use supportOptions * fix: do not infer parser in multiparser * chore: remove unnecessary package * chore: trigger another travis build * test: add kebab-case test to ensure no regression * test: update snapshotsmaster
parent
3f788d4fb6
commit
dc26445e51
|
@ -36,7 +36,6 @@
|
|||
"graphql": "0.12.3",
|
||||
"ignore": "3.3.7",
|
||||
"jest-docblock": "21.3.0-beta.11",
|
||||
"jest-validate": "21.1.0",
|
||||
"leven": "2.1.0",
|
||||
"mem": "1.1.0",
|
||||
"minimatch": "3.0.4",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
"use strict";
|
||||
|
||||
const camelCase = require("camelcase");
|
||||
const dedent = require("dedent");
|
||||
const dashify = require("dashify");
|
||||
const getSupportInfo = require("../common/support").getSupportInfo;
|
||||
|
||||
const CATEGORY_CONFIG = "Config";
|
||||
const CATEGORY_EDITOR = "Editor";
|
||||
|
@ -64,318 +65,187 @@ const categoryOrder = [
|
|||
* // If the option has a value that is an exception to the regular value
|
||||
* // constraints, indicate that value here (or use a function for more
|
||||
* // flexibility).
|
||||
* exception?: any | ((value: any) => boolean);
|
||||
* exception?: ((value: any) => boolean);
|
||||
*
|
||||
* // Indicate that the option is deprecated. Use a string to add an extra
|
||||
* // message to --help for the option, for example to suggest a replacement
|
||||
* // option.
|
||||
* deprecated?: true | string;
|
||||
*
|
||||
* // Custom function to get the value for the option. Useful for handling
|
||||
* // deprecated options.
|
||||
* // --parser example: (value, argv) => argv["flow-parser"] ? "flow" : value
|
||||
* getter?: (value: any, argv: any) => any;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Note: The options below are sorted alphabetically.
|
||||
*/
|
||||
const detailedOptions = normalizeDetailedOptions({
|
||||
"arrow-parens": {
|
||||
type: "choice",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Include parentheses around a sole arrow function parameter.",
|
||||
choices: [
|
||||
{
|
||||
value: "avoid",
|
||||
description: "Omit parens when possible. Example: `x => x`"
|
||||
},
|
||||
{
|
||||
value: "always",
|
||||
description: "Always include parens. Example: `(x) => x`"
|
||||
const detailedOptions = normalizeDetailedOptions(
|
||||
Object.assign(
|
||||
getSupportInfo(null, {
|
||||
showDeprecated: true,
|
||||
showUnreleased: true
|
||||
}).options.reduce((reduced, option) => {
|
||||
const newOption = Object.assign({}, option, {
|
||||
name: dashify(option.name),
|
||||
forwardToApi: option.name
|
||||
});
|
||||
|
||||
switch (option.name) {
|
||||
case "filepath":
|
||||
Object.assign(newOption, {
|
||||
name: "stdin-filepath",
|
||||
description: "Path to the file to pretend that stdin comes from."
|
||||
});
|
||||
break;
|
||||
case "useFlowParser":
|
||||
newOption.name = "flow-parser";
|
||||
break;
|
||||
case "plugins":
|
||||
newOption.name = "plugin";
|
||||
break;
|
||||
}
|
||||
]
|
||||
},
|
||||
"bracket-spacing": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Print spaces between brackets.",
|
||||
oppositeDescription: "Do not print spaces between brackets."
|
||||
},
|
||||
color: {
|
||||
// The supports-color package (a sub sub dependency) looks directly at
|
||||
// `process.argv` for `--no-color` and such-like options. The reason it is
|
||||
// listed here is to avoid "Ignored unknown option: --no-color" warnings.
|
||||
// See https://github.com/chalk/supports-color/#info for more information.
|
||||
type: "boolean",
|
||||
default: true,
|
||||
description: "Colorize error messages.",
|
||||
oppositeDescription: "Do not colorize error messages."
|
||||
},
|
||||
config: {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
description:
|
||||
"Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).",
|
||||
oppositeDescription: "Do not look for a configuration file."
|
||||
},
|
||||
"config-precedence": {
|
||||
type: "choice",
|
||||
category: CATEGORY_CONFIG,
|
||||
default: "cli-override",
|
||||
choices: [
|
||||
{
|
||||
value: "cli-override",
|
||||
description: "CLI options take precedence over config file"
|
||||
|
||||
switch (newOption.name) {
|
||||
case "cursor-offset":
|
||||
case "range-start":
|
||||
case "range-end":
|
||||
newOption.category = CATEGORY_EDITOR;
|
||||
break;
|
||||
case "stdin-filepath":
|
||||
case "insert-pragma":
|
||||
case "require-pragma":
|
||||
newOption.category = CATEGORY_OTHER;
|
||||
break;
|
||||
case "plugin":
|
||||
newOption.category = CATEGORY_CONFIG;
|
||||
break;
|
||||
default:
|
||||
newOption.category = CATEGORY_FORMAT;
|
||||
break;
|
||||
}
|
||||
|
||||
if (option.deprecated) {
|
||||
delete newOption.forwardToApi;
|
||||
delete newOption.description;
|
||||
delete newOption.oppositeDescription;
|
||||
newOption.deprecated = true;
|
||||
}
|
||||
|
||||
return Object.assign(reduced, { [newOption.name]: newOption });
|
||||
}, {}),
|
||||
{
|
||||
color: {
|
||||
// The supports-color package (a sub sub dependency) looks directly at
|
||||
// `process.argv` for `--no-color` and such-like options. The reason it is
|
||||
// listed here is to avoid "Ignored unknown option: --no-color" warnings.
|
||||
// See https://github.com/chalk/supports-color/#info for more information.
|
||||
type: "boolean",
|
||||
default: true,
|
||||
description: "Colorize error messages.",
|
||||
oppositeDescription: "Do not colorize error messages."
|
||||
},
|
||||
{
|
||||
value: "file-override",
|
||||
description: "Config file take precedence over CLI options"
|
||||
config: {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
description:
|
||||
"Path to a Prettier configuration file (.prettierrc, package.json, prettier.config.js).",
|
||||
oppositeDescription: "Do not look for a configuration file."
|
||||
},
|
||||
{
|
||||
value: "prefer-file",
|
||||
"config-precedence": {
|
||||
type: "choice",
|
||||
category: CATEGORY_CONFIG,
|
||||
default: "cli-override",
|
||||
choices: [
|
||||
{
|
||||
value: "cli-override",
|
||||
description: "CLI options take precedence over config file"
|
||||
},
|
||||
{
|
||||
value: "file-override",
|
||||
description: "Config file take precedence over CLI options"
|
||||
},
|
||||
{
|
||||
value: "prefer-file",
|
||||
description: dedent`
|
||||
If a config file is found will evaluate it and ignore other CLI options.
|
||||
If no config file is found CLI options will evaluate as normal.
|
||||
`
|
||||
}
|
||||
],
|
||||
description:
|
||||
"Define in which order config files and CLI options should be evaluated."
|
||||
},
|
||||
"debug-check": {
|
||||
type: "boolean"
|
||||
},
|
||||
"debug-print-doc": {
|
||||
type: "boolean"
|
||||
},
|
||||
editorconfig: {
|
||||
type: "boolean",
|
||||
category: CATEGORY_CONFIG,
|
||||
description:
|
||||
"Take .editorconfig into account when parsing configuration.",
|
||||
oppositeDescription:
|
||||
"Don't take .editorconfig into account when parsing configuration.",
|
||||
default: true
|
||||
},
|
||||
"find-config-path": {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
description:
|
||||
"Find and print the path to a configuration file for the given input file."
|
||||
},
|
||||
help: {
|
||||
type: "flag",
|
||||
alias: "h",
|
||||
description: dedent`
|
||||
If a config file is found will evaluate it and ignore other CLI options.
|
||||
If no config file is found CLI options will evaluate as normal.
|
||||
Show CLI usage, or details about the given flag.
|
||||
Example: --help write
|
||||
`
|
||||
},
|
||||
"ignore-path": {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
default: ".prettierignore",
|
||||
description: "Path to a file with patterns describing files to ignore."
|
||||
},
|
||||
"list-different": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_OUTPUT,
|
||||
alias: "l",
|
||||
description:
|
||||
"Print the names of files that are different from Prettier's formatting."
|
||||
},
|
||||
loglevel: {
|
||||
type: "choice",
|
||||
description: "What level of logs to report.",
|
||||
default: "log",
|
||||
choices: ["silent", "error", "warn", "log", "debug"]
|
||||
},
|
||||
stdin: {
|
||||
type: "boolean",
|
||||
description: "Force reading input from stdin."
|
||||
},
|
||||
"support-info": {
|
||||
type: "boolean",
|
||||
description: "Print support information as JSON."
|
||||
},
|
||||
version: {
|
||||
type: "boolean",
|
||||
alias: "v",
|
||||
description: "Print Prettier version."
|
||||
},
|
||||
"with-node-modules": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_CONFIG,
|
||||
description: "Process files inside 'node_modules' directory."
|
||||
},
|
||||
write: {
|
||||
type: "boolean",
|
||||
category: CATEGORY_OUTPUT,
|
||||
description: "Edit files in-place. (Beware!)"
|
||||
}
|
||||
],
|
||||
description:
|
||||
"Define in which order config files and CLI options should be evaluated."
|
||||
},
|
||||
"cursor-offset": {
|
||||
type: "int",
|
||||
category: CATEGORY_EDITOR,
|
||||
exception: -1,
|
||||
forwardToApi: true,
|
||||
description: dedent`
|
||||
Print (to stderr) where a cursor at the given position would move to after formatting.
|
||||
This option cannot be used with --range-start and --range-end.
|
||||
`
|
||||
},
|
||||
"debug-check": {
|
||||
type: "boolean"
|
||||
},
|
||||
"debug-print-doc": {
|
||||
type: "boolean"
|
||||
},
|
||||
editorconfig: {
|
||||
type: "boolean",
|
||||
category: CATEGORY_CONFIG,
|
||||
description: "Take .editorconfig into account when parsing configuration.",
|
||||
oppositeDescription:
|
||||
"Don't take .editorconfig into account when parsing configuration.",
|
||||
default: true
|
||||
},
|
||||
"find-config-path": {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
description:
|
||||
"Find and print the path to a configuration file for the given input file."
|
||||
},
|
||||
"flow-parser": {
|
||||
// Deprecated in 0.0.10
|
||||
type: "boolean",
|
||||
category: CATEGORY_FORMAT,
|
||||
deprecated: "Use `--parser flow` instead."
|
||||
},
|
||||
help: {
|
||||
type: "flag",
|
||||
alias: "h",
|
||||
description: dedent`
|
||||
Show CLI usage, or details about the given flag.
|
||||
Example: --help write
|
||||
`
|
||||
},
|
||||
"ignore-path": {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
default: ".prettierignore",
|
||||
description: "Path to a file with patterns describing files to ignore."
|
||||
},
|
||||
"insert-pragma": {
|
||||
type: "boolean",
|
||||
forwardToApi: true,
|
||||
description: dedent`
|
||||
Insert @format pragma into file's first docblock comment.
|
||||
`
|
||||
},
|
||||
"jsx-bracket-same-line": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Put > on the last line instead of at a new line."
|
||||
},
|
||||
"list-different": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_OUTPUT,
|
||||
alias: "l",
|
||||
description:
|
||||
"Print the names of files that are different from Prettier's formatting."
|
||||
},
|
||||
loglevel: {
|
||||
type: "choice",
|
||||
description: "What level of logs to report.",
|
||||
default: "log",
|
||||
choices: ["silent", "error", "warn", "log", "debug"]
|
||||
},
|
||||
parser: {
|
||||
type: "choice",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
exception: value => typeof value === "string", // Allow path to a parser module.
|
||||
choices: [
|
||||
"flow",
|
||||
"babylon",
|
||||
"typescript",
|
||||
"css",
|
||||
{ value: "postcss", deprecated: true, redirect: "css" },
|
||||
"less",
|
||||
"scss",
|
||||
"json",
|
||||
// "glimmer",
|
||||
"graphql",
|
||||
"markdown",
|
||||
"vue"
|
||||
],
|
||||
description: "Which parser to use.",
|
||||
getter: (value, argv) => (argv["flow-parser"] ? "flow" : value)
|
||||
},
|
||||
plugin: {
|
||||
type: "path",
|
||||
category: CATEGORY_CONFIG,
|
||||
description:
|
||||
"Add a plugin. Multiple plugins can be passed as separate `--plugin`s.",
|
||||
forwardToApi: "plugins",
|
||||
array: true
|
||||
},
|
||||
"print-width": {
|
||||
type: "int",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "The line length where Prettier will try wrap."
|
||||
},
|
||||
"prose-wrap": {
|
||||
type: "choice",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "How to wrap prose. (markdown)",
|
||||
choices: [
|
||||
{
|
||||
value: "always",
|
||||
description: "Wrap prose if it exceeds the print width."
|
||||
},
|
||||
{ value: "never", description: "Do not wrap prose." },
|
||||
{ value: "preserve", description: "Wrap prose as-is." },
|
||||
{ value: false, deprecated: true, redirect: "never" }
|
||||
]
|
||||
},
|
||||
"range-end": {
|
||||
type: "int",
|
||||
category: CATEGORY_EDITOR,
|
||||
forwardToApi: true,
|
||||
exception: Infinity,
|
||||
description: dedent`
|
||||
Format code ending at a given character offset (exclusive).
|
||||
The range will extend forwards to the end of the selected statement.
|
||||
This option cannot be used with --cursor-offset.
|
||||
`
|
||||
},
|
||||
"range-start": {
|
||||
type: "int",
|
||||
category: CATEGORY_EDITOR,
|
||||
forwardToApi: true,
|
||||
description: dedent`
|
||||
Format code starting at a given character offset.
|
||||
The range will extend backwards to the start of the first line containing the selected statement.
|
||||
This option cannot be used with --cursor-offset.
|
||||
`
|
||||
},
|
||||
"require-pragma": {
|
||||
type: "boolean",
|
||||
forwardToApi: true,
|
||||
description: dedent`
|
||||
Require either '@prettier' or '@format' to be present in the file's first docblock comment
|
||||
in order for it to be formatted.
|
||||
`
|
||||
},
|
||||
semi: {
|
||||
type: "boolean",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Print semicolons.",
|
||||
oppositeDescription:
|
||||
"Do not print semicolons, except at the beginning of lines which may need them."
|
||||
},
|
||||
"single-quote": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Use single quotes instead of double quotes."
|
||||
},
|
||||
stdin: {
|
||||
type: "boolean",
|
||||
description: "Force reading input from stdin."
|
||||
},
|
||||
"stdin-filepath": {
|
||||
type: "path",
|
||||
forwardToApi: "filepath",
|
||||
description: "Path to the file to pretend that stdin comes from."
|
||||
},
|
||||
"support-info": {
|
||||
type: "boolean",
|
||||
description: "Print support information as JSON."
|
||||
},
|
||||
"tab-width": {
|
||||
type: "int",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Number of spaces per indentation level."
|
||||
},
|
||||
"trailing-comma": {
|
||||
type: "choice",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
choices: [
|
||||
{ value: "none", description: "No trailing commas." },
|
||||
{
|
||||
value: "es5",
|
||||
description:
|
||||
"Trailing commas where valid in ES5 (objects, arrays, etc.)"
|
||||
},
|
||||
{
|
||||
value: "all",
|
||||
description:
|
||||
"Trailing commas wherever possible (including function arguments)."
|
||||
},
|
||||
{ value: "", deprecated: true, redirect: "es5" }
|
||||
],
|
||||
description: "Print trailing commas wherever possible when multi-line."
|
||||
},
|
||||
"use-tabs": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_FORMAT,
|
||||
forwardToApi: true,
|
||||
description: "Indent with tabs instead of spaces."
|
||||
},
|
||||
version: {
|
||||
type: "boolean",
|
||||
alias: "v",
|
||||
description: "Print Prettier version."
|
||||
},
|
||||
"with-node-modules": {
|
||||
type: "boolean",
|
||||
category: CATEGORY_CONFIG,
|
||||
description: "Process files inside 'node_modules' directory."
|
||||
},
|
||||
write: {
|
||||
type: "boolean",
|
||||
category: CATEGORY_OUTPUT,
|
||||
description: "Edit files in-place. (Beware!)"
|
||||
}
|
||||
});
|
||||
}
|
||||
)
|
||||
);
|
||||
|
||||
const minimistOptions = {
|
||||
boolean: detailedOptions
|
||||
|
@ -385,6 +255,7 @@ const minimistOptions = {
|
|||
.filter(option => option.type !== "boolean")
|
||||
.map(option => option.name),
|
||||
default: detailedOptions
|
||||
.filter(option => !option.deprecated)
|
||||
.filter(option => option.default !== undefined)
|
||||
.reduce(
|
||||
(current, option) =>
|
||||
|
@ -415,20 +286,18 @@ function normalizeDetailedOptions(rawDetailedOptions) {
|
|||
return Object.assign({}, option, {
|
||||
name,
|
||||
category: option.category || CATEGORY_OTHER,
|
||||
forwardToApi:
|
||||
option.forwardToApi &&
|
||||
(typeof option.forwardToApi === "string"
|
||||
? option.forwardToApi
|
||||
: camelCase(name)),
|
||||
choices:
|
||||
option.choices &&
|
||||
option.choices.map(choice =>
|
||||
Object.assign(
|
||||
option.choices.map(choice => {
|
||||
const newChoice = Object.assign(
|
||||
{ description: "", deprecated: false },
|
||||
typeof choice === "object" ? choice : { value: choice }
|
||||
)
|
||||
),
|
||||
getter: option.getter || (value => value)
|
||||
);
|
||||
if (newChoice.value === true) {
|
||||
newChoice.value = ""; // backward compability for original boolean option
|
||||
}
|
||||
return newChoice;
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
|
|
104
src/cli/index.js
104
src/cli/index.js
|
@ -5,58 +5,76 @@ const minimist = require("minimist");
|
|||
const prettier = require("../../index");
|
||||
const constant = require("./constant");
|
||||
const util = require("./util");
|
||||
const validator = require("./validator");
|
||||
const normalizer = require("../main/options-normalizer");
|
||||
const logger = require("./logger");
|
||||
|
||||
function run(args) {
|
||||
const rawArgv = minimist(args, constant.minimistOptions);
|
||||
try {
|
||||
const rawArgv = minimist(args, constant.minimistOptions);
|
||||
|
||||
process.env[logger.ENV_LOG_LEVEL] =
|
||||
rawArgv["loglevel"] || constant.detailedOptionMap["loglevel"].default;
|
||||
process.env[logger.ENV_LOG_LEVEL] =
|
||||
rawArgv["loglevel"] || constant.detailedOptionMap["loglevel"].default;
|
||||
|
||||
const argv = util.normalizeConfig("cli", rawArgv);
|
||||
|
||||
logger.debug(`normalized argv: ${JSON.stringify(argv)}`);
|
||||
|
||||
argv.__args = args;
|
||||
argv.__filePatterns = argv["_"];
|
||||
|
||||
validator.validateArgv(argv);
|
||||
|
||||
if (argv["version"]) {
|
||||
logger.log(prettier.version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (argv["help"] !== undefined) {
|
||||
logger.log(
|
||||
typeof argv["help"] === "string" && argv["help"] !== ""
|
||||
? util.createDetailedUsage(argv["help"])
|
||||
: util.createUsage()
|
||||
const argv = normalizer.normalizeCliOptions(
|
||||
rawArgv,
|
||||
constant.detailedOptions,
|
||||
{ logger }
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (argv["support-info"]) {
|
||||
logger.log(
|
||||
prettier.format(JSON.stringify(prettier.getSupportInfo()), {
|
||||
parser: "json"
|
||||
})
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
logger.debug(`normalized argv: ${JSON.stringify(argv)}`);
|
||||
|
||||
const hasFilePatterns = argv.__filePatterns.length !== 0;
|
||||
const useStdin = argv["stdin"] || (!hasFilePatterns && !process.stdin.isTTY);
|
||||
argv.__args = args;
|
||||
argv.__filePatterns = argv["_"];
|
||||
|
||||
if (argv["find-config-path"]) {
|
||||
util.logResolvedConfigPathOrDie(argv["find-config-path"]);
|
||||
} else if (useStdin) {
|
||||
util.formatStdin(argv);
|
||||
} else if (hasFilePatterns) {
|
||||
util.formatFiles(argv);
|
||||
} else {
|
||||
logger.log(util.createUsage());
|
||||
if (argv["write"] && argv["debug-check"]) {
|
||||
logger.error("Cannot use --write and --debug-check together.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (argv["find-config-path"] && argv.__filePatterns.length) {
|
||||
logger.error("Cannot use --find-config-path with multiple files");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (argv["version"]) {
|
||||
logger.log(prettier.version);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (argv["help"] !== undefined) {
|
||||
logger.log(
|
||||
typeof argv["help"] === "string" && argv["help"] !== ""
|
||||
? util.createDetailedUsage(argv["help"])
|
||||
: util.createUsage()
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (argv["support-info"]) {
|
||||
logger.log(
|
||||
prettier.format(JSON.stringify(prettier.getSupportInfo()), {
|
||||
parser: "json"
|
||||
})
|
||||
);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const hasFilePatterns = argv.__filePatterns.length !== 0;
|
||||
const useStdin =
|
||||
argv["stdin"] || (!hasFilePatterns && !process.stdin.isTTY);
|
||||
|
||||
if (argv["find-config-path"]) {
|
||||
util.logResolvedConfigPathOrDie(argv["find-config-path"]);
|
||||
} else if (useStdin) {
|
||||
util.formatStdin(argv);
|
||||
} else if (hasFilePatterns) {
|
||||
util.formatFiles(argv);
|
||||
} else {
|
||||
logger.log(util.createUsage());
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
|
174
src/cli/util.js
174
src/cli/util.js
|
@ -16,27 +16,28 @@ const cleanAST = require("../common/clean-ast").cleanAST;
|
|||
const errors = require("../common/errors");
|
||||
const resolver = require("../config/resolve-config");
|
||||
const constant = require("./constant");
|
||||
const validator = require("./validator");
|
||||
const options = require("../main/options");
|
||||
const apiDefaultOptions = options.defaults;
|
||||
const normalizeOptions = options.normalize;
|
||||
const optionsModule = require("../main/options");
|
||||
const apiDefaultOptions = optionsModule.defaults;
|
||||
const optionsNormalizer = require("../main/options-normalizer");
|
||||
const logger = require("./logger");
|
||||
const thirdParty = require("../common/third-party");
|
||||
const optionInfos = require("../common/support").getSupportInfo(null, {
|
||||
showDeprecated: true,
|
||||
showUnreleased: true
|
||||
}).options;
|
||||
|
||||
const OPTION_USAGE_THRESHOLD = 25;
|
||||
const CHOICE_USAGE_MARGIN = 3;
|
||||
const CHOICE_USAGE_INDENTATION = 2;
|
||||
|
||||
function getOptions(argv) {
|
||||
return constant.detailedOptions.filter(option => option.forwardToApi).reduce(
|
||||
(current, option) =>
|
||||
Object.assign(current, {
|
||||
[option.forwardToApi]: option.array
|
||||
? [].concat(argv[option.name] || [])
|
||||
: argv[option.name]
|
||||
}),
|
||||
{}
|
||||
);
|
||||
return constant.detailedOptions
|
||||
.filter(option => option.forwardToApi)
|
||||
.reduce(
|
||||
(current, option) =>
|
||||
Object.assign(current, { [option.forwardToApi]: argv[option.name] }),
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
function cliifyOptions(object) {
|
||||
|
@ -130,7 +131,7 @@ function format(argv, input, opt) {
|
|||
"prettier(input) !== prettier(prettier(input))\n" + diff(pp, pppp)
|
||||
);
|
||||
} else {
|
||||
const normalizedOpts = normalizeOptions(opt);
|
||||
const normalizedOpts = optionsModule.normalize(opt);
|
||||
const ast = cleanAST(
|
||||
prettier.__debug.parse(input, opt).ast,
|
||||
normalizedOpts
|
||||
|
@ -192,7 +193,8 @@ function getOptionsForFile(argv, filepath) {
|
|||
{ filepath },
|
||||
applyConfigPrecedence(
|
||||
argv,
|
||||
options && normalizeConfig("api", options, constant.detailedOptionMap)
|
||||
options &&
|
||||
optionsNormalizer.normalizeApiOptions(options, optionInfos, { logger })
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -205,8 +207,7 @@ function getOptionsForFile(argv, filepath) {
|
|||
|
||||
function parseArgsToOptions(argv, overrideDefaults) {
|
||||
return getOptions(
|
||||
normalizeConfig(
|
||||
"cli",
|
||||
optionsNormalizer.normalizeCliOptions(
|
||||
minimist(
|
||||
argv.__args,
|
||||
Object.assign({
|
||||
|
@ -219,7 +220,8 @@ function parseArgsToOptions(argv, overrideDefaults) {
|
|||
)
|
||||
})
|
||||
),
|
||||
{ warning: false }
|
||||
constant.detailedOptions,
|
||||
{ logger: false }
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -463,12 +465,18 @@ function createOptionUsage(option, threshold) {
|
|||
`${option.description}${
|
||||
optionDefaultValue === undefined
|
||||
? ""
|
||||
: `\nDefaults to ${optionDefaultValue}.`
|
||||
: `\nDefaults to ${createDefaultValueDisplay(optionDefaultValue)}.`
|
||||
}`,
|
||||
threshold
|
||||
);
|
||||
}
|
||||
|
||||
function createDefaultValueDisplay(value) {
|
||||
return Array.isArray(value)
|
||||
? `[${value.map(createDefaultValueDisplay).join(", ")}]`
|
||||
: value;
|
||||
}
|
||||
|
||||
function createOptionUsageHeader(option) {
|
||||
const name = `--${option.name}`;
|
||||
const alias = option.alias ? `-${option.alias},` : null;
|
||||
|
@ -574,7 +582,7 @@ function createDetailedUsage(optionName) {
|
|||
const optionDefaultValue = getOptionDefaultValue(option.name);
|
||||
const defaults =
|
||||
optionDefaultValue !== undefined
|
||||
? `\n\nDefault: ${optionDefaultValue}`
|
||||
? `\n\nDefault: ${createDefaultValueDisplay(optionDefaultValue)}`
|
||||
: "";
|
||||
|
||||
return `${header}${description}${choices}${defaults}`;
|
||||
|
@ -612,135 +620,11 @@ function groupBy(array, getKey) {
|
|||
}, Object.create(null));
|
||||
}
|
||||
|
||||
/** @param {'api' | 'cli'} type */
|
||||
function normalizeConfig(type, rawConfig, options) {
|
||||
if (type === "api" && rawConfig === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
options = options || {};
|
||||
|
||||
const consoleWarn =
|
||||
options.warning === false ? () => {} : logger.warn.bind(logger);
|
||||
|
||||
const normalized = {};
|
||||
|
||||
Object.keys(rawConfig).forEach(rawKey => {
|
||||
const rawValue = rawConfig[rawKey];
|
||||
|
||||
const key = type === "cli" ? rawKey : dashify(rawKey);
|
||||
|
||||
if (type === "cli" && key === "_") {
|
||||
normalized[rawKey] = rawValue;
|
||||
return;
|
||||
}
|
||||
|
||||
if (type === "cli" && key.length === 1) {
|
||||
// do nothing with alias
|
||||
return;
|
||||
}
|
||||
|
||||
let option = constant.detailedOptionMap[key];
|
||||
if (type === "api" && option === undefined) {
|
||||
option = constant.apiDetailedOptionMap[key];
|
||||
}
|
||||
|
||||
// unknown option
|
||||
if (option === undefined) {
|
||||
if (type === "api") {
|
||||
consoleWarn(`Ignored unknown option: ${rawKey}`);
|
||||
} else {
|
||||
const optionName = rawValue === false ? `no-${rawKey}` : rawKey;
|
||||
consoleWarn(`Ignored unknown option: --${optionName}`);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const value = getValue(rawValue, option);
|
||||
|
||||
if (option.exception !== undefined) {
|
||||
if (typeof option.exception === "function") {
|
||||
if (option.exception(value)) {
|
||||
normalized[rawKey] = value;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (value === option.exception) {
|
||||
normalized[rawKey] = value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
switch (option.type) {
|
||||
case "int":
|
||||
validator.validateIntOption(type, value, option);
|
||||
normalized[rawKey] = Number(value);
|
||||
break;
|
||||
case "choice":
|
||||
validator.validateChoiceOption(type, value, option);
|
||||
normalized[rawKey] = value;
|
||||
break;
|
||||
default:
|
||||
normalized[rawKey] = value;
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error(error.message);
|
||||
process.exit(2);
|
||||
}
|
||||
});
|
||||
|
||||
return normalized;
|
||||
|
||||
function getOptionName(option) {
|
||||
return type === "cli" ? `--${option.name}` : camelCase(option.name);
|
||||
}
|
||||
|
||||
function getRedirectName(option, choice) {
|
||||
return type === "cli"
|
||||
? `--${option.name}=${choice.redirect}`
|
||||
: `{ ${camelCase(option.name)}: ${JSON.stringify(choice.redirect)} }`;
|
||||
}
|
||||
|
||||
function getValue(rawValue, option) {
|
||||
const optionName = getOptionName(option);
|
||||
if (rawValue && option.deprecated) {
|
||||
let warning = `\`${optionName}\` is deprecated.`;
|
||||
if (typeof option.deprecated === "string") {
|
||||
warning += ` ${option.deprecated}`;
|
||||
}
|
||||
consoleWarn(warning);
|
||||
}
|
||||
|
||||
const value = option.getter(rawValue, rawConfig);
|
||||
|
||||
if (option.type === "choice") {
|
||||
const choice = option.choices.find(choice => choice.value === rawValue);
|
||||
if (choice !== undefined && choice.deprecated) {
|
||||
const warningDescription =
|
||||
rawValue === ""
|
||||
? "without an argument"
|
||||
: `with value \`${rawValue}\``;
|
||||
const redirectName = getRedirectName(option, choice);
|
||||
consoleWarn(
|
||||
`\`${optionName}\` ${warningDescription} is deprecated. Prettier now treats it as: \`${redirectName}\`.`
|
||||
);
|
||||
return choice.redirect;
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
logResolvedConfigPathOrDie,
|
||||
format,
|
||||
formatStdin,
|
||||
formatFiles,
|
||||
createUsage,
|
||||
createDetailedUsage,
|
||||
normalizeConfig
|
||||
createDetailedUsage
|
||||
};
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
const camelCase = require("camelcase");
|
||||
const logger = require("./logger");
|
||||
|
||||
function validateArgv(argv) {
|
||||
if (argv["write"] && argv["debug-check"]) {
|
||||
logger.error("Cannot use --write and --debug-check together.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (argv["find-config-path"] && argv.__filePatterns.length) {
|
||||
logger.error("Cannot use --find-config-path with multiple files");
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
function getOptionName(type, option) {
|
||||
return type === "cli" ? `--${option.name}` : camelCase(option.name);
|
||||
}
|
||||
|
||||
function validateIntOption(type, value, option) {
|
||||
if (!/^\d+$/.test(value) || (type === "api" && typeof value !== "number")) {
|
||||
const optionName = getOptionName(type, option);
|
||||
throw new Error(
|
||||
`Invalid ${optionName} value.\n` +
|
||||
`Expected an integer, but received: ${JSON.stringify(value)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function validateChoiceOption(type, value, option) {
|
||||
if (!option.choices.some(choice => choice.value === value)) {
|
||||
const optionName = getOptionName(type, option);
|
||||
throw new Error(
|
||||
`Invalid option for ${optionName}.\n` +
|
||||
`Expected ${getJoinedChoices()}, but received: ${JSON.stringify(value)}`
|
||||
);
|
||||
}
|
||||
|
||||
function getJoinedChoices() {
|
||||
const choices = option.choices
|
||||
.filter(choice => !choice.deprecated)
|
||||
.map(choice => `"${choice.value}"`);
|
||||
const head = choices.slice(0, -2);
|
||||
const tail = choices.slice(-2);
|
||||
return head.concat(tail.join(" or ")).join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
validateArgv,
|
||||
validateIntOption,
|
||||
validateChoiceOption
|
||||
};
|
|
@ -14,6 +14,7 @@ const CATEGORY_SPECIAL = "Special";
|
|||
* @property {string} since - available since version
|
||||
* @property {string} category
|
||||
* @property {'int' | 'boolean' | 'choice' | 'path'} type
|
||||
* @property {boolean} array - indicate it's an array of the specified type
|
||||
* @property {boolean?} deprecated - deprecated since version
|
||||
* @property {OptionRedirectInfo?} redirect - redirect deprecated option
|
||||
* @property {string} description
|
||||
|
@ -21,9 +22,10 @@ const CATEGORY_SPECIAL = "Special";
|
|||
* @property {OptionValueInfo} default
|
||||
* @property {OptionRangeInfo?} range - for type int
|
||||
* @property {OptionChoiceInfo?} choices - for type choice
|
||||
* @property {(value: any) => boolean} exception
|
||||
*
|
||||
* @typedef {number | boolean | string} OptionValue
|
||||
* @typedef {OptionValue | Array<{ since: string, value: OptionValue}>} OptionValueInfo
|
||||
* @typedef {OptionValue | [{ value: OptionValue[] }] | Array<{ since: string, value: OptionValue}>} OptionValueInfo
|
||||
*
|
||||
* @typedef {Object} OptionRedirectInfo
|
||||
* @property {string} option
|
||||
|
@ -75,9 +77,11 @@ const supportOptions = {
|
|||
type: "choice",
|
||||
default: "babylon",
|
||||
description: "Which parser to use.",
|
||||
exception: value =>
|
||||
typeof value === "string" || typeof value === "function",
|
||||
choices: [
|
||||
{ value: "babylon", description: "JavaScript" },
|
||||
{ value: "flow", description: "Flow" },
|
||||
{ value: "babylon", description: "JavaScript" },
|
||||
{ value: "typescript", since: "1.4.0", description: "TypeScript" },
|
||||
{ value: "css", since: "1.7.1", description: "CSS" },
|
||||
{
|
||||
|
@ -91,9 +95,20 @@ const supportOptions = {
|
|||
{ value: "scss", since: "1.7.1", description: "SCSS" },
|
||||
{ value: "json", since: "1.5.0", description: "JSON" },
|
||||
{ value: "graphql", since: "1.5.0", description: "GraphQL" },
|
||||
{ value: "markdown", since: "1.8.0", description: "Markdown" }
|
||||
{ value: "markdown", since: "1.8.0", description: "Markdown" },
|
||||
{ value: "vue", since: "1.10.0", description: "Vue" }
|
||||
]
|
||||
},
|
||||
plugins: {
|
||||
since: "1.10.0",
|
||||
type: "path",
|
||||
array: true,
|
||||
default: [{ value: [] }],
|
||||
category: CATEGORY_GLOBAL,
|
||||
description:
|
||||
"Add a plugin. Multiple plugins can be passed as separate `--plugin`s.",
|
||||
exception: value => typeof value === "string" || typeof value === "object"
|
||||
},
|
||||
printWidth: {
|
||||
since: "0.0.0",
|
||||
category: CATEGORY_GLOBAL,
|
||||
|
@ -208,11 +223,14 @@ function getSupportInfo(version, opts) {
|
|||
const newOption = Object.assign({}, option);
|
||||
|
||||
if (Array.isArray(newOption.default)) {
|
||||
newOption.default = newOption.default
|
||||
.filter(filterSince)
|
||||
.sort((info1, info2) =>
|
||||
semver.compare(info2.since, info1.since)
|
||||
)[0].value;
|
||||
newOption.default =
|
||||
newOption.default.length === 1
|
||||
? newOption.default[0].value
|
||||
: newOption.default
|
||||
.filter(filterSince)
|
||||
.sort((info1, info2) =>
|
||||
semver.compare(info2.since, info1.since)
|
||||
)[0].value;
|
||||
}
|
||||
|
||||
if (Array.isArray(newOption.choices)) {
|
||||
|
|
|
@ -34,7 +34,7 @@ function embed(path, print, textToDoc, options) {
|
|||
return null;
|
||||
|
||||
function getParserName(lang) {
|
||||
const supportInfo = support.getSupportInfo(undefined, {
|
||||
const supportInfo = support.getSupportInfo(null, {
|
||||
plugins: options.plugins,
|
||||
pluginsLoaded: true
|
||||
});
|
||||
|
|
|
@ -20,7 +20,8 @@ function textToDoc(text, partialNextOptions, parentOptions) {
|
|||
Object.assign({}, parentOptions, partialNextOptions, {
|
||||
parentParser: parentOptions.parser,
|
||||
originalText: text
|
||||
})
|
||||
}),
|
||||
{ passThrough: true, inferParser: false }
|
||||
);
|
||||
|
||||
const result = require("./parser").parse(text, nextOptions);
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
"use strict";
|
||||
|
||||
function apiDescriptor(name, value) {
|
||||
return arguments.length === 1
|
||||
? JSON.stringify(name)
|
||||
: `\`{ ${apiDescriptor(name)}: ${JSON.stringify(value)} }\``;
|
||||
}
|
||||
|
||||
function cliDescriptor(name, value) {
|
||||
return value === false
|
||||
? `\`--no-${name}\``
|
||||
: value === true || arguments.length === 1
|
||||
? `\`--${name}\``
|
||||
: value === ""
|
||||
? `\`--${name}\` without an argument`
|
||||
: `\`--${name}=${value}\``;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
apiDescriptor,
|
||||
cliDescriptor
|
||||
};
|
|
@ -0,0 +1,153 @@
|
|||
"use strict";
|
||||
|
||||
const leven = require("leven");
|
||||
const validator = require("./options-validator");
|
||||
const descriptors = require("./options-descriptor");
|
||||
|
||||
function normalizeOptions(options, optionInfos, opts) {
|
||||
opts = opts || {};
|
||||
const logger =
|
||||
opts.logger === false
|
||||
? { warn() {} }
|
||||
: opts.logger !== undefined ? opts.logger : console;
|
||||
const descriptor = opts.descriptor || descriptors.apiDescriptor;
|
||||
const passThrough = opts.passThrough || [];
|
||||
|
||||
const optionInfoMap = optionInfos.reduce(
|
||||
(reduced, optionInfo) =>
|
||||
Object.assign(reduced, { [optionInfo.name]: optionInfo }),
|
||||
{}
|
||||
);
|
||||
const normalizedOptions = Object.keys(options).reduce((newOptions, key) => {
|
||||
const optionInfo = optionInfoMap[key];
|
||||
|
||||
let optionName = key;
|
||||
let optionValue = options[key];
|
||||
|
||||
if (!optionInfo) {
|
||||
if (passThrough === true || passThrough.indexOf(optionName) !== -1) {
|
||||
newOptions[optionName] = optionValue;
|
||||
} else {
|
||||
logger.warn(
|
||||
createUnknownOptionMessage(
|
||||
optionName,
|
||||
optionValue,
|
||||
optionInfos,
|
||||
descriptor
|
||||
)
|
||||
);
|
||||
}
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
if (!optionInfo.deprecated) {
|
||||
optionValue = normalizeOption(optionValue, optionInfo);
|
||||
} else if (typeof optionInfo.redirect === "string") {
|
||||
logger.warn(createRedirectOptionMessage(optionInfo, descriptor));
|
||||
optionName = optionInfo.redirect;
|
||||
} else if (optionValue) {
|
||||
logger.warn(createRedirectOptionMessage(optionInfo, descriptor));
|
||||
optionValue = optionInfo.redirect.value;
|
||||
optionName = optionInfo.redirect.option;
|
||||
}
|
||||
|
||||
if (optionInfo.choices) {
|
||||
const choiceInfo = optionInfo.choices.find(
|
||||
choice => choice.value === optionValue
|
||||
);
|
||||
if (choiceInfo && choiceInfo.deprecated) {
|
||||
logger.warn(
|
||||
createRedirectChoiceMessage(optionInfo, choiceInfo, descriptor)
|
||||
);
|
||||
optionValue = choiceInfo.redirect;
|
||||
}
|
||||
}
|
||||
|
||||
if (optionInfo.array && !Array.isArray(optionValue)) {
|
||||
optionValue = [optionValue];
|
||||
}
|
||||
|
||||
if (optionValue !== optionInfo.default) {
|
||||
validator.validateOption(optionValue, optionInfoMap[optionName], {
|
||||
descriptor
|
||||
});
|
||||
}
|
||||
|
||||
newOptions[optionName] = optionValue;
|
||||
return newOptions;
|
||||
}, {});
|
||||
|
||||
return normalizedOptions;
|
||||
}
|
||||
|
||||
function normalizeOption(option, optionInfo) {
|
||||
return optionInfo.type === "int" ? Number(option) : option;
|
||||
}
|
||||
|
||||
function createUnknownOptionMessage(key, value, optionInfos, descriptor) {
|
||||
const messages = [`Ignored unknown option ${descriptor(key, value)}.`];
|
||||
|
||||
const suggestedOptionInfo = optionInfos.find(
|
||||
optionInfo => leven(optionInfo.name, key) < 3
|
||||
);
|
||||
if (suggestedOptionInfo) {
|
||||
messages.push(`Did you mean ${JSON.stringify(suggestedOptionInfo.name)}?`);
|
||||
}
|
||||
|
||||
return messages.join(" ");
|
||||
}
|
||||
|
||||
function createRedirectOptionMessage(optionInfo, descriptor) {
|
||||
return `${descriptor(
|
||||
optionInfo.name
|
||||
)} is deprecated. Prettier now treats it as ${
|
||||
typeof optionInfo.redirect === "string"
|
||||
? descriptor(optionInfo.redirect)
|
||||
: descriptor(optionInfo.redirect.option, optionInfo.redirect.value)
|
||||
}.`;
|
||||
}
|
||||
|
||||
function createRedirectChoiceMessage(optionInfo, choiceInfo, descriptor) {
|
||||
return `${descriptor(
|
||||
optionInfo.name,
|
||||
choiceInfo.value
|
||||
)} is deprecated. Prettier now treats it as ${descriptor(
|
||||
optionInfo.name,
|
||||
choiceInfo.redirect
|
||||
)}.`;
|
||||
}
|
||||
|
||||
function normalizeApiOptions(options, optionInfos, opts) {
|
||||
return normalizeOptions(
|
||||
options,
|
||||
optionInfos,
|
||||
Object.assign({ descriptor: descriptors.apiDescriptor }, opts)
|
||||
);
|
||||
}
|
||||
|
||||
function normalizeCliOptions(options, optionInfos, opts) {
|
||||
const args = options["_"] || [];
|
||||
|
||||
const newOptions = normalizeOptions(
|
||||
Object.keys(options).reduce(
|
||||
(reduced, key) =>
|
||||
Object.assign(
|
||||
reduced,
|
||||
key.length === 1 // omit alias
|
||||
? null
|
||||
: { [key]: options[key] }
|
||||
),
|
||||
{}
|
||||
),
|
||||
optionInfos,
|
||||
Object.assign({ descriptor: descriptors.cliDescriptor }, opts)
|
||||
);
|
||||
newOptions["_"] = args;
|
||||
|
||||
return newOptions;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
normalizeApiOptions,
|
||||
normalizeCliOptions
|
||||
};
|
|
@ -0,0 +1,81 @@
|
|||
"use strict";
|
||||
|
||||
const descriptors = require("./options-descriptor");
|
||||
|
||||
function validateOption(value, optionInfo, opts) {
|
||||
opts = opts || {};
|
||||
const descriptor = opts.descriptor || descriptors.apiDescriptor;
|
||||
|
||||
if (
|
||||
typeof optionInfo.exception === "function" &&
|
||||
optionInfo.exception(value)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
validateOptionType(value, optionInfo);
|
||||
} catch (error) {
|
||||
throw new Error(
|
||||
`Invalid \`${descriptor(optionInfo.name)}\` value. ${
|
||||
error.message
|
||||
}, but received \`${JSON.stringify(value)}\`.`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function validateOptionType(value, optionInfo) {
|
||||
if (optionInfo.array) {
|
||||
if (!Array.isArray(value)) {
|
||||
throw new Error(`Expected an array`);
|
||||
}
|
||||
value.forEach(v =>
|
||||
validateOptionType(v, Object.assign({}, optionInfo, { array: false }))
|
||||
);
|
||||
} else {
|
||||
switch (optionInfo.type) {
|
||||
case "int":
|
||||
validateIntOption(value);
|
||||
break;
|
||||
case "boolean":
|
||||
validateBooleanOption(value);
|
||||
break;
|
||||
case "choice":
|
||||
validateChoiceOption(value, optionInfo.choices);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function validateBooleanOption(value) {
|
||||
if (typeof value !== "boolean") {
|
||||
throw new Error(`Expected a boolean`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateIntOption(value) {
|
||||
if (
|
||||
!(
|
||||
typeof value === "number" &&
|
||||
Math.floor(value) === value &&
|
||||
value >= 0 &&
|
||||
value !== Infinity
|
||||
)
|
||||
) {
|
||||
throw new Error(`Expected an integer`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateChoiceOption(value, choiceInfos) {
|
||||
if (!choiceInfos.some(choiceInfo => choiceInfo.value === value)) {
|
||||
const choices = choiceInfos
|
||||
.filter(choiceInfo => !choiceInfo.deprecated)
|
||||
.map(choiceInfo => JSON.stringify(choiceInfo.value))
|
||||
.sort();
|
||||
const head = choices.slice(0, -2);
|
||||
const tail = choices.slice(-2);
|
||||
throw new Error(`Expected ${head.concat(tail.join(" or ")).join(", ")}`);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { validateOption };
|
|
@ -1,142 +1,82 @@
|
|||
"use strict";
|
||||
|
||||
const path = require("path");
|
||||
|
||||
const validate = require("jest-validate").validate;
|
||||
const deprecatedConfig = require("./deprecated");
|
||||
const getSupportInfo = require("../common/support").getSupportInfo;
|
||||
const supportInfo = getSupportInfo(null, { showUnreleased: true });
|
||||
const normalizer = require("./options-normalizer");
|
||||
const loadPlugins = require("../common/load-plugins");
|
||||
const resolveParser = require("./parser").resolveParser;
|
||||
const getPrinter = require("./get-printer");
|
||||
|
||||
const defaults = {
|
||||
cursorOffset: -1,
|
||||
rangeStart: 0,
|
||||
rangeEnd: Infinity,
|
||||
useTabs: false,
|
||||
tabWidth: 2,
|
||||
printWidth: 80,
|
||||
singleQuote: false,
|
||||
trailingComma: "none",
|
||||
bracketSpacing: true,
|
||||
jsxBracketSameLine: false,
|
||||
parser: "babylon",
|
||||
parentParser: "",
|
||||
insertPragma: false,
|
||||
requirePragma: false,
|
||||
semi: true,
|
||||
proseWrap: "preserve",
|
||||
arrowParens: "avoid",
|
||||
plugins: [],
|
||||
const hiddenDefaults = {
|
||||
astFormat: "estree",
|
||||
printer: {},
|
||||
__inJsTemplate: false
|
||||
printer: {}
|
||||
};
|
||||
|
||||
const exampleConfig = Object.assign({}, defaults, {
|
||||
filepath: "path/to/Filename",
|
||||
printWidth: 80,
|
||||
originalText: "text"
|
||||
});
|
||||
const defaults = supportInfo.options.reduce(
|
||||
(reduced, optionInfo) =>
|
||||
Object.assign(reduced, { [optionInfo.name]: optionInfo.default }),
|
||||
Object.assign({}, hiddenDefaults)
|
||||
);
|
||||
|
||||
// Copy options and fill in default values.
|
||||
function normalize(options) {
|
||||
const normalized = Object.assign({}, options || {});
|
||||
const filepath = normalized.filepath;
|
||||
function normalize(options, opts) {
|
||||
opts = opts || {};
|
||||
|
||||
normalized.plugins = loadPlugins(normalized.plugins);
|
||||
const rawOptions = Object.assign({}, options);
|
||||
rawOptions.plugins = loadPlugins(rawOptions.plugins);
|
||||
|
||||
if (
|
||||
filepath &&
|
||||
!normalized.parentParser &&
|
||||
(!normalized.parser || normalized.parser === defaults.parser)
|
||||
) {
|
||||
const extension = path.extname(filepath);
|
||||
const filename = path.basename(filepath).toLowerCase();
|
||||
|
||||
const language = getSupportInfo(null, {
|
||||
plugins: normalized.plugins,
|
||||
pluginsLoaded: true
|
||||
}).languages.find(
|
||||
language =>
|
||||
typeof language.since === "string" &&
|
||||
(language.extensions.indexOf(extension) > -1 ||
|
||||
(language.filenames &&
|
||||
language.filenames.find(name => name.toLowerCase() === filename)))
|
||||
);
|
||||
|
||||
if (language) {
|
||||
normalized.parser = language.parsers[0];
|
||||
if (opts.inferParser !== false) {
|
||||
if (
|
||||
rawOptions.filepath &&
|
||||
(!rawOptions.parser || rawOptions.parser === defaults.parser)
|
||||
) {
|
||||
const inferredParser = inferParser(
|
||||
rawOptions.filepath,
|
||||
rawOptions.plugins
|
||||
);
|
||||
if (inferredParser) {
|
||||
rawOptions.parser = inferredParser;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (normalized.parser === "json") {
|
||||
normalized.trailingComma = "none";
|
||||
}
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (typeof normalized.trailingComma === "boolean") {
|
||||
// Support a deprecated boolean type for the trailing comma config
|
||||
// for a few versions. This code can be removed later.
|
||||
normalized.trailingComma = "es5";
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
"Warning: `trailingComma` without any argument is deprecated. " +
|
||||
'Specify "none", "es5", or "all".'
|
||||
);
|
||||
}
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (typeof normalized.proseWrap === "boolean") {
|
||||
normalized.proseWrap = normalized.proseWrap ? "always" : "never";
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
"Warning: `proseWrap` with boolean value is deprecated. " +
|
||||
'Use "always", "never", or "preserve" instead.'
|
||||
);
|
||||
}
|
||||
|
||||
/* istanbul ignore if */
|
||||
if (normalized.parser === "postcss") {
|
||||
normalized.parser = "css";
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'Warning: `parser` with value "postcss" is deprecated. ' +
|
||||
'Use "css", "less" or "scss" instead.'
|
||||
);
|
||||
}
|
||||
|
||||
const parserBackup = normalized.parser;
|
||||
if (typeof normalized.parser === "function") {
|
||||
// Delete the function from the object to pass validation.
|
||||
delete normalized.parser;
|
||||
}
|
||||
|
||||
validate(normalized, { exampleConfig, deprecatedConfig });
|
||||
|
||||
// Restore the option back to a function;
|
||||
normalized.parser = parserBackup;
|
||||
|
||||
// For backward compatibility. Deprecated in 0.0.10
|
||||
/* istanbul ignore if */
|
||||
if ("useFlowParser" in normalized) {
|
||||
normalized.parser = normalized.useFlowParser ? "flow" : "babylon";
|
||||
delete normalized.useFlowParser;
|
||||
}
|
||||
|
||||
normalized.astFormat = resolveParser(normalized).astFormat;
|
||||
normalized.printer = getPrinter(normalized);
|
||||
rawOptions.astFormat = resolveParser(rawOptions).astFormat;
|
||||
rawOptions.printer = getPrinter(rawOptions);
|
||||
|
||||
Object.keys(defaults).forEach(k => {
|
||||
if (normalized[k] == null) {
|
||||
normalized[k] = defaults[k];
|
||||
if (rawOptions[k] == null) {
|
||||
rawOptions[k] = defaults[k];
|
||||
}
|
||||
});
|
||||
|
||||
return normalized;
|
||||
if (rawOptions.parser === "json") {
|
||||
rawOptions.trailingComma = "none";
|
||||
}
|
||||
|
||||
return normalizer.normalizeApiOptions(
|
||||
rawOptions,
|
||||
supportInfo.options,
|
||||
Object.assign({ passThrough: Object.keys(hiddenDefaults) }, opts)
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = { normalize, defaults };
|
||||
function inferParser(filepath, plugins) {
|
||||
const extension = path.extname(filepath);
|
||||
const filename = path.basename(filepath).toLowerCase();
|
||||
|
||||
const language = getSupportInfo(null, {
|
||||
plugins,
|
||||
pluginsLoaded: true
|
||||
}).languages.find(
|
||||
language =>
|
||||
typeof language.since === "string" &&
|
||||
(language.extensions.indexOf(extension) > -1 ||
|
||||
(language.filenames &&
|
||||
language.filenames.find(name => name.toLowerCase() === filename)))
|
||||
);
|
||||
|
||||
return language && language.parsers[0];
|
||||
}
|
||||
|
||||
module.exports = { normalize, defaults, hiddenDefaults };
|
||||
|
|
|
@ -10,7 +10,7 @@ exports[`boolean flags do not swallow the next argument (stdout) 1`] = `
|
|||
exports[`boolean flags do not swallow the next argument (write) 1`] = `Array []`;
|
||||
|
||||
exports[`deprecated option values are warned (stderr) 1`] = `
|
||||
"[warn] \`--trailing-comma\` without an argument is deprecated. Prettier now treats it as: \`--trailing-comma=es5\`.
|
||||
"[warn] \`--trailing-comma\` without an argument is deprecated. Prettier now treats it as \`--trailing-comma=es5\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -22,7 +22,7 @@ exports[`deprecated option values are warned (stdout) 1`] = `
|
|||
exports[`deprecated option values are warned (write) 1`] = `Array []`;
|
||||
|
||||
exports[`deprecated options are warned (stderr) 1`] = `
|
||||
"[warn] \`--flow-parser\` is deprecated. Use \`--parser flow\` instead.
|
||||
"[warn] \`--flow-parser\` is deprecated. Prettier now treats it as \`--parser=flow\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -43,7 +43,7 @@ exports[`negated options work (stdout) 1`] = `
|
|||
exports[`negated options work (write) 1`] = `Array []`;
|
||||
|
||||
exports[`unknown negated options are warned (stderr) 1`] = `
|
||||
"[warn] Ignored unknown option: --no-unknown
|
||||
"[warn] Ignored unknown option \`--no-unknown\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -55,7 +55,7 @@ exports[`unknown negated options are warned (stdout) 1`] = `
|
|||
exports[`unknown negated options are warned (write) 1`] = `Array []`;
|
||||
|
||||
exports[`unknown options are warned (stderr) 1`] = `
|
||||
"[warn] Ignored unknown option: --unknown
|
||||
"[warn] Ignored unknown option \`--unknown\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
|
@ -1,7 +1,16 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`show warning with kebab-case option key (stderr) 1`] = `
|
||||
"[warn] Ignored unknown option \`{ \\"print-width\\": 3 }\`. Did you mean \\"printWidth\\"?
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`show warning with kebab-case option key (stdout) 1`] = `""`;
|
||||
|
||||
exports[`show warning with kebab-case option key (write) 1`] = `Array []`;
|
||||
|
||||
exports[`show warning with unknown option (stderr) 1`] = `
|
||||
"[warn] Ignored unknown option: hello
|
||||
"[warn] Ignored unknown option \`{ \\"hello\\": \\"world\\" }\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -19,8 +28,7 @@ exports[`throw error with invalid config format (stdout) 1`] = `""`;
|
|||
exports[`throw error with invalid config format (write) 1`] = `Array []`;
|
||||
|
||||
exports[`throw error with invalid config option (int) (stderr) 1`] = `
|
||||
"[error] Invalid tabWidth value.
|
||||
[error] Expected an integer, but received: 0.5
|
||||
"[error] Invalid \`\\"tabWidth\\"\` value. Expected an integer, but received \`0.5\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -29,8 +37,7 @@ exports[`throw error with invalid config option (int) (stdout) 1`] = `""`;
|
|||
exports[`throw error with invalid config option (int) (write) 1`] = `Array []`;
|
||||
|
||||
exports[`throw error with invalid config option (trailingComma) (stderr) 1`] = `
|
||||
"[error] Invalid option for trailingComma.
|
||||
[error] Expected \\"none\\", \\"es5\\" or \\"all\\", but received: \\"wow\\"
|
||||
"[error] Invalid \`\\"trailingComma\\"\` value. Expected \\"all\\", \\"es5\\" or \\"none\\", but received \`\\"wow\\"\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -39,8 +46,7 @@ exports[`throw error with invalid config option (trailingComma) (stdout) 1`] = `
|
|||
exports[`throw error with invalid config option (trailingComma) (write) 1`] = `Array []`;
|
||||
|
||||
exports[`throw error with invalid config precedence option (configPrecedence) (stderr) 1`] = `
|
||||
"[error] Invalid option for --config-precedence.
|
||||
[error] Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received: \\"option/configPrecedence\\"
|
||||
"[error] Invalid \`\`--config-precedence\`\` value. Expected \\"cli-override\\", \\"file-override\\" or \\"prefer-file\\", but received \`\\"option/configPrecedence\\"\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
|
@ -271,16 +271,16 @@ exports[`show detailed usage with --help parser (stdout) 1`] = `
|
|||
|
||||
Valid options:
|
||||
|
||||
flow
|
||||
babylon
|
||||
typescript
|
||||
css
|
||||
less
|
||||
scss
|
||||
json
|
||||
graphql
|
||||
markdown
|
||||
vue
|
||||
flow Flow
|
||||
babylon JavaScript
|
||||
typescript TypeScript
|
||||
css CSS
|
||||
less Less
|
||||
scss SCSS
|
||||
json JSON
|
||||
graphql GraphQL
|
||||
markdown Markdown
|
||||
vue Vue
|
||||
|
||||
Default: babylon
|
||||
"
|
||||
|
@ -294,6 +294,8 @@ exports[`show detailed usage with --help plugin (stdout) 1`] = `
|
|||
"--plugin <path>
|
||||
|
||||
Add a plugin. Multiple plugins can be passed as separate \`--plugin\`s.
|
||||
|
||||
Default: []
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -565,6 +567,7 @@ Config options:
|
|||
--ignore-path <path> Path to a file with patterns describing files to ignore.
|
||||
Defaults to .prettierignore.
|
||||
--plugin <path> Add a plugin. Multiple plugins can be passed as separate \`--plugin\`s.
|
||||
Defaults to [].
|
||||
--with-node-modules Process files inside 'node_modules' directory.
|
||||
|
||||
Editor options:
|
||||
|
@ -634,16 +637,16 @@ exports[`show warning with --help not-found (typo) (stdout) 1`] = `
|
|||
|
||||
Valid options:
|
||||
|
||||
flow
|
||||
babylon
|
||||
typescript
|
||||
css
|
||||
less
|
||||
scss
|
||||
json
|
||||
graphql
|
||||
markdown
|
||||
vue
|
||||
flow Flow
|
||||
babylon JavaScript
|
||||
typescript TypeScript
|
||||
css CSS
|
||||
less Less
|
||||
scss SCSS
|
||||
json JSON
|
||||
graphql GraphQL
|
||||
markdown Markdown
|
||||
vue Vue
|
||||
|
||||
Default: babylon
|
||||
"
|
||||
|
@ -706,6 +709,7 @@ Config options:
|
|||
--ignore-path <path> Path to a file with patterns describing files to ignore.
|
||||
Defaults to .prettierignore.
|
||||
--plugin <path> Add a plugin. Multiple plugins can be passed as separate \`--plugin\`s.
|
||||
Defaults to [].
|
||||
--with-node-modules Process files inside 'node_modules' directory.
|
||||
|
||||
Editor options:
|
||||
|
|
|
@ -17,8 +17,8 @@ exports[`API getSupportInfo() with version 0.0.0 -> 1.0.0 1`] = `
|
|||
+ },
|
||||
+ \\"parser\\": Object {
|
||||
+ \\"choices\\": Array [
|
||||
+ \\"babylon\\",
|
||||
+ \\"flow\\",
|
||||
+ \\"babylon\\",
|
||||
+ ],
|
||||
+ \\"default\\": \\"babylon\\",
|
||||
+ \\"type\\": \\"choice\\",
|
||||
|
@ -174,8 +174,8 @@ exports[`API getSupportInfo() with version 1.0.0 -> 1.4.0 1`] = `
|
|||
},
|
||||
\\"parser\\": Object {
|
||||
\\"choices\\": Array [
|
||||
\\"babylon\\",
|
||||
\\"flow\\",
|
||||
\\"babylon\\",
|
||||
+ \\"typescript\\",
|
||||
+ \\"postcss\\",
|
||||
],
|
||||
|
@ -238,8 +238,8 @@ exports[`API getSupportInfo() with version 1.4.0 -> 1.5.0 1`] = `
|
|||
\\"JavaScript\\": Array [
|
||||
@@ -47,10 +53,12 @@
|
||||
\\"choices\\": Array [
|
||||
\\"babylon\\",
|
||||
\\"flow\\",
|
||||
\\"babylon\\",
|
||||
\\"typescript\\",
|
||||
\\"postcss\\",
|
||||
+ \\"json\\",
|
||||
|
@ -287,8 +287,8 @@ exports[`API getSupportInfo() with version 1.5.0 -> 1.7.1 1`] = `
|
|||
@@ -52,11 +52,13 @@
|
||||
\\"parser\\": Object {
|
||||
\\"choices\\": Array [
|
||||
\\"babylon\\",
|
||||
\\"flow\\",
|
||||
\\"babylon\\",
|
||||
\\"typescript\\",
|
||||
- \\"postcss\\",
|
||||
+ \\"css\\",
|
||||
|
@ -419,7 +419,27 @@ exports[`API getSupportInfo() with version 1.8.2 -> undefined 1`] = `
|
|||
\\"type\\": \\"boolean\\",
|
||||
},
|
||||
\\"cursorOffset\\": Object {
|
||||
@@ -80,14 +91,15 @@
|
||||
@@ -65,14 +76,19 @@
|
||||
\\"less\\",
|
||||
\\"scss\\",
|
||||
\\"json\\",
|
||||
\\"graphql\\",
|
||||
\\"markdown\\",
|
||||
+ \\"vue\\",
|
||||
],
|
||||
\\"default\\": \\"babylon\\",
|
||||
\\"type\\": \\"choice\\",
|
||||
},
|
||||
+ \\"plugins\\": Object {
|
||||
+ \\"default\\": Array [],
|
||||
+ \\"type\\": \\"path\\",
|
||||
+ },
|
||||
\\"printWidth\\": Object {
|
||||
\\"default\\": 80,
|
||||
\\"range\\": Object {
|
||||
\\"end\\": Infinity,
|
||||
\\"start\\": 0,
|
||||
@@ -80,14 +96,15 @@
|
||||
},
|
||||
\\"type\\": \\"int\\",
|
||||
},
|
||||
|
@ -695,8 +715,8 @@ exports[`CLI --support-info (stdout) 1`] = `
|
|||
\\"default\\": \\"babylon\\",
|
||||
\\"description\\": \\"Which parser to use.\\",
|
||||
\\"choices\\": [
|
||||
{ \\"value\\": \\"babylon\\", \\"description\\": \\"JavaScript\\" },
|
||||
{ \\"value\\": \\"flow\\", \\"description\\": \\"Flow\\" },
|
||||
{ \\"value\\": \\"babylon\\", \\"description\\": \\"JavaScript\\" },
|
||||
{
|
||||
\\"value\\": \\"typescript\\",
|
||||
\\"since\\": \\"1.4.0\\",
|
||||
|
@ -707,9 +727,20 @@ exports[`CLI --support-info (stdout) 1`] = `
|
|||
{ \\"value\\": \\"scss\\", \\"since\\": \\"1.7.1\\", \\"description\\": \\"SCSS\\" },
|
||||
{ \\"value\\": \\"json\\", \\"since\\": \\"1.5.0\\", \\"description\\": \\"JSON\\" },
|
||||
{ \\"value\\": \\"graphql\\", \\"since\\": \\"1.5.0\\", \\"description\\": \\"GraphQL\\" },
|
||||
{ \\"value\\": \\"markdown\\", \\"since\\": \\"1.8.0\\", \\"description\\": \\"Markdown\\" }
|
||||
{ \\"value\\": \\"markdown\\", \\"since\\": \\"1.8.0\\", \\"description\\": \\"Markdown\\" },
|
||||
{ \\"value\\": \\"vue\\", \\"since\\": \\"1.10.0\\", \\"description\\": \\"Vue\\" }
|
||||
]
|
||||
},
|
||||
{
|
||||
\\"name\\": \\"plugins\\",
|
||||
\\"since\\": \\"1.10.0\\",
|
||||
\\"type\\": \\"path\\",
|
||||
\\"array\\": true,
|
||||
\\"default\\": [],
|
||||
\\"category\\": \\"Global\\",
|
||||
\\"description\\":
|
||||
\\"Add a plugin. Multiple plugins can be passed as separate \`--plugin\`s.\\"
|
||||
},
|
||||
{
|
||||
\\"name\\": \\"printWidth\\",
|
||||
\\"since\\": \\"0.0.0\\",
|
||||
|
|
|
@ -232,8 +232,7 @@ function rcYaml() {
|
|||
exports[`CLI overrides take precedence without --config-precedence (write) 1`] = `Array []`;
|
||||
|
||||
exports[`CLI validate options with --config-precedence cli-override (stderr) 1`] = `
|
||||
"[error] Invalid printWidth value.
|
||||
[error] Expected an integer, but received: 0.5
|
||||
"[error] Invalid \`\\"printWidth\\"\` value. Expected an integer, but received \`0.5\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -242,8 +241,7 @@ exports[`CLI validate options with --config-precedence cli-override (stdout) 1`]
|
|||
exports[`CLI validate options with --config-precedence cli-override (write) 1`] = `Array []`;
|
||||
|
||||
exports[`CLI validate options with --config-precedence file-override (stderr) 1`] = `
|
||||
"[error] Invalid printWidth value.
|
||||
[error] Expected an integer, but received: 0.5
|
||||
"[error] Invalid \`\\"printWidth\\"\` value. Expected an integer, but received \`0.5\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
@ -252,8 +250,7 @@ exports[`CLI validate options with --config-precedence file-override (stdout) 1`
|
|||
exports[`CLI validate options with --config-precedence file-override (write) 1`] = `Array []`;
|
||||
|
||||
exports[`CLI validate options with --config-precedence prefer-file (stderr) 1`] = `
|
||||
"[error] Invalid printWidth value.
|
||||
[error] Expected an integer, but received: 0.5
|
||||
"[error] Invalid \`\\"printWidth\\"\` value. Expected an integer, but received \`0.5\`.
|
||||
"
|
||||
`;
|
||||
|
||||
|
|
|
@ -45,3 +45,9 @@ describe("show warning with unknown option", () => {
|
|||
status: 0
|
||||
});
|
||||
});
|
||||
|
||||
describe("show warning with kebab-case option key", () => {
|
||||
runPrettier("cli/config/invalid", ["--config", "option/kebab-case"]).test({
|
||||
status: 0
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"config-precedence": "invalidValue"
|
||||
"configPrecedence": "invalidValue"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"print-width": 3
|
||||
}
|
|
@ -1,3 +1,3 @@
|
|||
{
|
||||
"trailing-comma": "wow"
|
||||
"trailingComma": "wow"
|
||||
}
|
20
yarn.lock
20
yarn.lock
|
@ -2593,10 +2593,6 @@ jest-get-type@21.3.0-beta.15:
|
|||
version "21.3.0-beta.15"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.3.0-beta.15.tgz#d5a510c32683124576eaba69b66a1ba3c25ed67c"
|
||||
|
||||
jest-get-type@^21.0.2:
|
||||
version "21.0.2"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.0.2.tgz#304e6b816dd33cd1f47aba0597bcad258a509fc6"
|
||||
|
||||
jest-get-type@^21.2.0:
|
||||
version "21.2.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-get-type/-/jest-get-type-21.2.0.tgz#f6376ab9db4b60d81e39f30749c6c466f40d4a23"
|
||||
|
@ -2742,15 +2738,6 @@ jest-util@^21.2.1:
|
|||
jest-validate "^21.2.1"
|
||||
mkdirp "^0.5.1"
|
||||
|
||||
jest-validate@21.1.0:
|
||||
version "21.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.1.0.tgz#39d01115544a758bce49f221a5fcbb24ebdecc65"
|
||||
dependencies:
|
||||
chalk "^2.0.1"
|
||||
jest-get-type "^21.0.2"
|
||||
leven "^2.1.0"
|
||||
pretty-format "^21.1.0"
|
||||
|
||||
jest-validate@^21.2.1:
|
||||
version "21.2.1"
|
||||
resolved "https://registry.yarnpkg.com/jest-validate/-/jest-validate-21.2.1.tgz#cc0cbca653cd54937ba4f2a111796774530dd3c7"
|
||||
|
@ -3601,13 +3588,6 @@ pretty-format@^20.0.3:
|
|||
ansi-regex "^2.1.1"
|
||||
ansi-styles "^3.0.0"
|
||||
|
||||
pretty-format@^21.1.0:
|
||||
version "21.1.0"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.1.0.tgz#557428254323832ee8b7c971cb613442bea67f61"
|
||||
dependencies:
|
||||
ansi-regex "^3.0.0"
|
||||
ansi-styles "^3.2.0"
|
||||
|
||||
pretty-format@^21.2.1:
|
||||
version "21.2.1"
|
||||
resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-21.2.1.tgz#ae5407f3cf21066cd011aa1ba5fce7b6a2eddb36"
|
||||
|
|
Loading…
Reference in New Issue