Files
test-repo/bin/prettier.js
T

240 lines
6.8 KiB
JavaScript
Raw Normal View History

2016-11-29 12:14:10 -05:00
#!/usr/bin/env node
2017-01-10 12:18:22 -05:00
"use strict";
2017-01-28 07:50:22 -08:00
2016-11-29 12:14:10 -05:00
const fs = require("fs");
2017-01-11 07:57:16 -08:00
const getStdin = require("get-stdin");
2017-01-23 16:37:57 +01:00
const glob = require("glob");
const minimist = require("minimist");
2017-01-22 01:42:13 +01:00
const prettier = require("../index");
2016-11-29 12:14:10 -05:00
const argv = minimist(process.argv.slice(2), {
2017-01-13 15:03:53 -05:00
boolean: [
"write",
"stdin",
"single-quote",
2017-01-18 12:45:44 -08:00
"trailing-comma",
2017-01-22 01:48:18 +01:00
"bracket-spacing",
// 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.
"color",
2017-01-26 19:13:32 +01:00
"help",
"version",
2017-01-20 09:54:32 -08:00
"debug-print-doc",
2017-02-07 07:04:44 -08:00
"debug-check",
// Deprecated in 0.0.10
"flow-parser"
2017-01-13 15:03:53 -05:00
],
2017-01-26 19:13:32 +01:00
string: ["print-width", "tab-width", "parser"],
default: { color: true, "bracket-spacing": true, parser: "babylon" },
2017-01-26 19:13:32 +01:00
alias: { help: "h", version: "v" },
unknown: param => {
if (param.startsWith("-")) {
console.warn("Ignored unknown option: " + param + "\n");
2017-01-26 19:13:32 +01:00
return false;
}
}
});
2017-01-18 12:45:44 -08:00
if (argv["version"]) {
2017-01-22 01:42:13 +01:00
console.log(prettier.version);
2017-01-18 12:45:44 -08:00
process.exit(0);
}
2017-01-23 16:37:57 +01:00
const filepatterns = argv["_"];
2017-01-10 21:45:04 +01:00
const write = argv["write"];
2017-01-26 19:13:32 +01:00
const stdin = argv["stdin"] || !filepatterns.length && !process.stdin.isTTY;
2016-11-29 12:14:10 -05:00
2017-01-26 19:13:32 +01:00
if (argv["help"] || !filepatterns.length && !stdin) {
2017-01-09 23:03:35 -05:00
console.log(
2017-01-18 15:31:46 -08:00
"Usage: prettier [opts] [filename ...]\n\n" +
"Available options:\n" +
2017-01-22 01:48:18 +01:00
" --write Edit the file in-place. (Beware!)\n" +
" --stdin Read input from stdin.\n" +
" --print-width <int> Specify the length of line that the printer will wrap on. Defaults to 80.\n" +
" --tab-width <int> Specify the number of spaces per indentation-level. Defaults to 2.\n" +
2017-01-22 01:48:18 +01:00
" --single-quote Use single quotes instead of double.\n" +
" --trailing-comma Print trailing commas wherever possible.\n" +
" --bracket-spacing Put spaces between brackets. Defaults to true.\n" +
2017-01-22 01:48:18 +01:00
" --parser <flow|babylon> Specify which parse to use. Defaults to babylon.\n" +
" --color Colorize error messages. Defaults to true.\n" +
" --version Print prettier version.\n" +
"\n" +
"Boolean options can be turned off like this:\n" +
" --no-bracket-spacing\n" +
" --bracket-spacing=false"
2017-01-09 23:03:35 -05:00
);
2017-01-26 19:13:32 +01:00
process.exit(argv["help"] ? 0 : 1);
2017-01-09 23:03:35 -05:00
}
2017-01-26 19:13:32 +01:00
function getParserOption() {
const optionName = "parser";
const value = argv[optionName];
if (value === undefined) {
return value;
}
// For backward compatibility. Deprecated in 0.0.10
if (argv["flow-parser"]) {
2017-01-21 18:23:29 +01:00
console.warn("`--flow-parser` is deprecated. Use `--parser flow` instead.");
return "flow";
}
2017-01-26 19:13:32 +01:00
if (value === "flow" || value === "babylon") {
return value;
}
2017-01-26 19:13:32 +01:00
console.warn(
"Ignoring unknown --" +
optionName +
' value, falling back to "babylon":\n' +
' Expected "flow" or "babylon", but received: ' +
JSON.stringify(value)
);
return "babylon";
}
2017-01-26 19:13:32 +01:00
function getIntOption(optionName) {
const value = argv[optionName];
if (value === undefined) {
return value;
}
if (/^\d+$/.test(value)) {
return Number(value);
}
console.error(
"Invalid --" +
optionName +
" value. Expected an integer, but received: " +
JSON.stringify(value)
);
process.exit(1);
}
2017-01-20 09:54:32 -08:00
const options = {
2017-01-26 19:13:32 +01:00
printWidth: getIntOption("print-width"),
tabWidth: getIntOption("tab-width"),
2017-01-20 09:54:32 -08:00
bracketSpacing: argv["bracket-spacing"],
2017-01-26 19:13:32 +01:00
parser: getParserOption(),
2017-01-20 09:54:32 -08:00
singleQuote: argv["single-quote"],
trailingComma: argv["trailing-comma"]
};
2017-01-11 07:57:16 -08:00
function format(input) {
2017-01-20 09:54:32 -08:00
if (argv["debug-print-doc"]) {
2017-01-22 01:42:13 +01:00
const doc = prettier.__debug.printToDoc(input, options);
return prettier.__debug.formatDoc(doc);
2017-01-20 09:54:32 -08:00
}
2017-02-07 07:04:44 -08:00
if (argv["debug-check"]) {
const pp = prettier.format(input, options);
const pppp = prettier.format(pp, options);
if (pp !== pppp) {
const diff = require('diff').createTwoFilesPatch('', '', pp, pppp, '', '', {context: 2});
console.error(diff);
}
return;
}
2017-01-22 01:42:13 +01:00
return prettier.format(input, options);
2017-01-11 07:57:16 -08:00
}
2017-01-10 22:00:19 -08:00
2017-01-26 19:13:32 +01:00
function handleError(filename, e) {
const isParseError = Boolean(e && e.loc);
const isValidationError = /Validation Error/.test(e && e.message);
// For parse errors and validation errors, we only want to show the error
// message formatted in a nice way. `String(e)` takes care of that. Other
// (unexpected) errors are passed as-is as a separate argument to
// `console.error`. That includes the stack trace (if any), and shows a nice
// `util.inspect` of throws things that aren't `Error` objects. (The Flow
// parser has mistakenly thrown arrays sometimes.)
if (isParseError) {
console.error(filename + ": " + String(e));
} else if (isValidationError) {
console.error(String(e));
// If validation fails for one file, it will fail for all of them.
process.exit(1);
} else {
console.error(filename + ":", e);
}
// Don't exit the process if one file failed
process.exitCode = 2;
}
2017-01-11 07:57:16 -08:00
if (stdin) {
getStdin().then(input => {
2017-01-10 22:10:00 -08:00
try {
// Don't use `console.log` here since it adds an extra newline at the end.
process.stdout.write(format(input));
2017-01-10 22:10:00 -08:00
} catch (e) {
2017-01-26 19:13:32 +01:00
handleError("stdin", e);
2017-01-10 22:10:00 -08:00
return;
}
2017-01-10 21:45:04 +01:00
});
2017-01-11 07:57:16 -08:00
} else {
2017-01-23 16:37:57 +01:00
eachFilename(filepatterns, filename => {
2017-01-11 07:57:16 -08:00
fs.readFile(filename, "utf8", (err, input) => {
2017-02-07 07:04:44 -08:00
if (write || argv["debug-check"]) {
2017-01-11 07:57:16 -08:00
console.log(filename);
}
if (err) {
console.error("Unable to read file: " + filename + "\n" + err);
// Don't exit the process if one file failed
process.exitCode = 2;
return;
}
let output;
try {
output = format(input);
2017-01-11 07:57:16 -08:00
} catch (e) {
2017-01-26 19:13:32 +01:00
handleError(filename, e);
2017-01-11 07:57:16 -08:00
return;
}
if (write) {
2017-01-29 16:09:22 +01:00
// Don't write the file if it won't change in order not to invalidate
// mtime based caches.
if (output !== input) {
fs.writeFile(filename, output, "utf8", err => {
if (err) {
console.error("Unable to write file: " + filename + "\n" + err);
// Don't exit the process if one file failed
process.exitCode = 2;
}
});
}
2017-01-11 07:57:16 -08:00
} else {
// Don't use `console.log` here since it adds an extra newline at the end.
process.stdout.write(output);
2017-01-11 07:57:16 -08:00
}
});
});
}
2017-01-23 16:37:57 +01:00
function eachFilename(patterns, callback) {
patterns.forEach(pattern => {
glob(pattern, (err, filenames) => {
if (err) {
console.error("Unable to expand glob pattern: " + pattern + "\n" + err);
// Don't exit the process if one pattern failed
process.exitCode = 2;
return;
}
filenames.forEach(filename => {
callback(filename);
});
});
});
}