summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/flags.rs57
-rwxr-xr-xstd/prettier/main.ts179
-rw-r--r--std/prettier/main_test.ts156
-rw-r--r--std/prettier/testdata/5.ts1
-rw-r--r--std/prettier/testdata/config_file_js/.prettierrc.js5
-rw-r--r--std/prettier/testdata/config_file_json/.prettierrc.json4
-rw-r--r--std/prettier/testdata/config_file_toml/.prettierrc.toml2
-rw-r--r--std/prettier/testdata/config_file_ts/.prettierrc.ts5
-rw-r--r--std/prettier/testdata/ignore_file/.prettierignore3
-rw-r--r--std/prettier/testdata/ignore_file/0.js1
-rw-r--r--std/prettier/testdata/ignore_file/0.ts1
-rw-r--r--std/prettier/testdata/ignore_file/1.js1
-rw-r--r--std/prettier/testdata/ignore_file/1.ts1
-rw-r--r--std/prettier/testdata/ignore_file/README.md5
-rw-r--r--std/prettier/testdata/ignore_file/typescript.prettierignore3
15 files changed, 414 insertions, 10 deletions
diff --git a/cli/flags.rs b/cli/flags.rs
index 693d290c4..393ca48b6 100644
--- a/cli/flags.rs
+++ b/cli/flags.rs
@@ -341,6 +341,32 @@ Automatically downloads Prettier dependencies on first run.
deno fmt myfile1.ts myfile2.ts",
)
.arg(
+ Arg::with_name("prettierrc")
+ .long("prettierrc")
+ .value_name("auto|disable|FILE")
+ .help("Specify the configuration file of the prettier.
+ auto: Auto detect prettier configuration file in current working dir.
+ disable: Disable load configuration file.
+ FILE: Load specified prettier configuration file. support .json/.toml/.js/.ts file
+ ")
+ .takes_value(true)
+ .require_equals(true)
+ .default_value("auto")
+ )
+ .arg(
+ Arg::with_name("ignore-path")
+ .long("ignore-path")
+ .value_name("auto|disable|FILE")
+ .help("Path to a file containing patterns that describe files to ignore.
+ auto: Auto detect .pretierignore file in current working dir.
+ disable: Disable load .prettierignore file.
+ FILE: Load specified prettier ignore file.
+ ")
+ .takes_value(true)
+ .require_equals(true)
+ .default_value("auto")
+ )
+ .arg(
Arg::with_name("stdout")
.long("stdout")
.help("Output formated code to stdout")
@@ -966,6 +992,8 @@ pub fn flags_from_vec(
}
let prettier_flags = [
+ ["1", "prettierrc"],
+ ["1", "ignore-path"],
["1", "print-width"],
["1", "tab-width"],
["0", "use-tabs"],
@@ -989,7 +1017,11 @@ pub fn flags_from_vec(
if t == "0" {
argv.push(format!("--{}", keyword));
} else {
- argv.push(format!("--{}", keyword));
+ if keyword == "prettierrc" {
+ argv.push("--config".to_string());
+ } else {
+ argv.push(format!("--{}", keyword));
+ }
argv.push(fmt_match.value_of(keyword).unwrap().to_string());
}
}
@@ -1384,7 +1416,11 @@ mod tests {
PRETTIER_URL,
"script_1.ts",
"script_2.ts",
- "--write"
+ "--write",
+ "--config",
+ "auto",
+ "--ignore-path",
+ "auto"
]
);
}
@@ -1602,7 +1638,16 @@ mod tests {
assert_eq!(subcommand, DenoSubcommand::Run);
assert_eq!(
argv,
- svec!["deno", PRETTIER_URL, "script_1.ts", "script_2.ts"]
+ svec![
+ "deno",
+ PRETTIER_URL,
+ "script_1.ts",
+ "script_2.ts",
+ "--config",
+ "auto",
+ "--ignore-path",
+ "auto"
+ ]
);
}
@@ -2043,6 +2088,7 @@ mod tests {
let (flags, subcommand, argv) = flags_from_vec(svec![
"deno",
"fmt",
+ "--prettierrc=auto",
"--print-width=100",
"--tab-width=4",
"--use-tabs",
@@ -2054,6 +2100,7 @@ mod tests {
"--quote-props=preserve",
"--jsx-single-quote",
"--jsx-bracket-same-line",
+ "--ignore-path=.prettier-ignore",
"script.ts"
]);
assert_eq!(
@@ -2072,6 +2119,10 @@ mod tests {
PRETTIER_URL,
"script.ts",
"--write",
+ "--config",
+ "auto",
+ "--ignore-path",
+ ".prettier-ignore",
"--print-width",
"100",
"--tab-width",
diff --git a/std/prettier/main.ts b/std/prettier/main.ts
index 2b5aa3e5d..cd8800d23 100755
--- a/std/prettier/main.ts
+++ b/std/prettier/main.ts
@@ -24,6 +24,8 @@
// This script formats the given source files. If the files are omitted, it
// formats the all files in the repository.
import { parse } from "../flags/mod.ts";
+import * as path from "../path/mod.ts";
+import * as toml from "../encoding/toml.ts";
import { ExpandGlobOptions, WalkInfo, expandGlob } from "../fs/mod.ts";
import { prettier, prettierPlugins } from "./prettier.ts";
const { args, cwd, exit, readAll, readFile, stdin, stdout, writeFile } = Deno;
@@ -40,6 +42,10 @@ Options:
it will output to stdout, Defaults to
false.
--ignore <path> Ignore the given path(s).
+ --ignore-path <auto|disable|path> Path to a file containing patterns that
+ describe files to ignore. Optional
+ value: auto/disable/filepath. Defaults
+ to null.
--stdin Specifies to read the code from stdin.
If run the command in a pipe, you do not
need to specify this flag.
@@ -49,6 +55,10 @@ Options:
parser for stdin. available parser:
typescript/babel/markdown/json. Defaults
to typescript.
+ --config <auto|disable|path> Specify the configuration file of the
+ prettier.
+ Optional value: auto/disable/filepath.
+ Defaults to null.
JS/TS Styling Options:
--print-width <int> The line length where Prettier will try
@@ -106,7 +116,7 @@ Example:
// Available parsers
type ParserLabel = "typescript" | "babel" | "markdown" | "json";
-interface PrettierOptions {
+interface PrettierBuildInOptions {
printWidth: number;
tabWidth: number;
useTabs: boolean;
@@ -120,6 +130,9 @@ interface PrettierOptions {
arrowParens: string;
proseWrap: string;
endOfLine: string;
+}
+
+interface PrettierOptions extends PrettierBuildInOptions {
write: boolean;
}
@@ -343,10 +356,134 @@ async function* getTargetFiles(
}
}
+/**
+ * auto detect prettier configuration file and return config if file exist.
+ */
+async function autoResolveConfig(): Promise<PrettierBuildInOptions> {
+ const configFileNamesMap = {
+ ".prettierrc.json": 1,
+ ".prettierrc.yaml": 1,
+ ".prettierrc.yml": 1,
+ ".prettierrc.js": 1,
+ ".prettierrc.ts": 1,
+ "prettier.config.js": 1,
+ "prettier.config.ts": 1,
+ ".prettierrc.toml": 1
+ };
+
+ const files = await Deno.readDir(".");
+
+ for (const f of files) {
+ if (f.isFile() && configFileNamesMap[f.name]) {
+ const c = await resolveConfig(f.name);
+ if (c) {
+ return c;
+ }
+ }
+ }
+
+ return;
+}
+
+/**
+ * parse prettier configuration file.
+ * @param filepath the configuration file path.
+ * support extension name with .json/.toml/.js
+ */
+async function resolveConfig(
+ filepath: string
+): Promise<PrettierBuildInOptions> {
+ let config: PrettierOptions = undefined;
+
+ function generateError(msg: string): Error {
+ return new Error(`Invalid prettier configuration file: ${msg}.`);
+ }
+
+ const raw = new TextDecoder().decode(await Deno.readFile(filepath));
+
+ switch (path.extname(filepath)) {
+ case ".json":
+ try {
+ config = JSON.parse(raw) as PrettierOptions;
+ } catch (err) {
+ throw generateError(err.message);
+ }
+ break;
+ case ".yml":
+ case ".yaml":
+ // TODO: Unimplemented loading yaml / yml configuration file yet.
+ break;
+ case ".toml":
+ try {
+ config = toml.parse(raw) as PrettierOptions;
+ } catch (err) {
+ throw generateError(err.message);
+ }
+ break;
+ case ".js":
+ case ".ts":
+ const absPath = path.isAbsolute(filepath)
+ ? filepath
+ : path.join(cwd(), filepath);
+
+ try {
+ const output = await import(
+ // TODO: Remove platform condition
+ // after https://github.com/denoland/deno/issues/3355 fixed
+ Deno.build.os === "win" ? "file://" + absPath : absPath
+ );
+
+ if (output && output.default) {
+ config = output.default;
+ } else {
+ throw new Error(
+ "Prettier of JS version should have default exports."
+ );
+ }
+ } catch (err) {
+ throw generateError(err.message);
+ }
+
+ break;
+ default:
+ break;
+ }
+
+ return config;
+}
+
+/**
+ * auto detect .prettierignore and return pattern if file exist.
+ */
+async function autoResolveIgnoreFile(): Promise<string[]> {
+ const files = await Deno.readDir(".");
+
+ for (const f of files) {
+ if (f.isFile() && f.name === ".prettierignore") {
+ return await resolveIgnoreFile(f.name);
+ }
+ }
+
+ return [];
+}
+
+/**
+ * parse prettier ignore file.
+ * @param filepath the ignore file path.
+ */
+async function resolveIgnoreFile(filepath: string): Promise<string[]> {
+ const raw = new TextDecoder().decode(await Deno.readFile(filepath));
+
+ return raw
+ .split("\n")
+ .filter((v: string) => !!v.trim() && v.trim().indexOf("#") !== 0)
+ .map(v => v);
+}
+
async function main(opts): Promise<void> {
- const { help, ignore, check, _: args } = opts;
+ const { help, check, _: args } = opts;
- const prettierOpts: PrettierOptions = {
+ let prettierOpts: PrettierOptions = {
printWidth: Number(opts["print-width"]),
tabWidth: Number(opts["tab-width"]),
useTabs: Boolean(opts["use-tabs"]),
@@ -368,10 +505,37 @@ async function main(opts): Promise<void> {
exit(0);
}
- const files = getTargetFiles(
- args.length ? args : ["."],
- Array.isArray(ignore) ? ignore : [ignore]
- );
+ const configFilepath = opts["config"];
+
+ if (configFilepath && configFilepath !== "disable") {
+ const config =
+ configFilepath === "auto"
+ ? await autoResolveConfig()
+ : await resolveConfig(configFilepath);
+
+ if (config) {
+ prettierOpts = { ...prettierOpts, ...config };
+ }
+ }
+
+ let ignore = opts.ignore as string[];
+
+ if (!Array.isArray(ignore)) {
+ ignore = [ignore];
+ }
+
+ const ignoreFilepath = opts["ignore-path"];
+
+ if (ignoreFilepath && ignoreFilepath !== "disable") {
+ const ignorePatterns: string[] =
+ ignoreFilepath === "auto"
+ ? await autoResolveIgnoreFile()
+ : await resolveIgnoreFile(ignoreFilepath);
+
+ ignore = ignore.concat(ignorePatterns);
+ }
+
+ const files = getTargetFiles(args.length ? args : ["."], ignore);
const tty = Deno.isTTY();
@@ -396,6 +560,7 @@ main(
parse(args.slice(1), {
string: [
"ignore",
+ "ignore-path",
"printWidth",
"tab-width",
"trailing-comma",
diff --git a/std/prettier/main_test.ts b/std/prettier/main_test.ts
index 16c19ed03..a63890741 100644
--- a/std/prettier/main_test.ts
+++ b/std/prettier/main_test.ts
@@ -378,4 +378,160 @@ test(async function testPrettierReadFromStdin(): Promise<void> {
}
});
+test(async function testPrettierWithAutoConfig(): Promise<void> {
+ const configs = [
+ "config_file_json",
+ "config_file_toml",
+ "config_file_js",
+ "config_file_ts"
+ ];
+
+ for (const configName of configs) {
+ const cwd = join(testdata, configName);
+ const prettierFile = join(Deno.cwd(), "prettier", "main.ts");
+ const { stdout, stderr } = Deno.run({
+ args: [
+ execPath(),
+ "run",
+ "--allow-read",
+ "--allow-env",
+ prettierFile,
+ "../5.ts",
+ "--config",
+ "auto"
+ ],
+ stdout: "piped",
+ stderr: "piped",
+ cwd
+ });
+
+ const output = decoder.decode(await Deno.readAll(stdout));
+ const errMsg = decoder.decode(await Deno.readAll(stderr));
+
+ assertEquals(
+ errMsg
+ .split(EOL)
+ .filter((line: string) => line.indexOf("Compile") !== 0)
+ .join(EOL),
+ ""
+ );
+
+ assertEquals(output, `console.log('0');\n`);
+ }
+});
+
+test(async function testPrettierWithSpecifiedConfig(): Promise<void> {
+ interface Config {
+ dir: string;
+ name: string;
+ }
+ const configs: Config[] = [
+ {
+ dir: "config_file_json",
+ name: ".prettierrc.json"
+ },
+ {
+ dir: "config_file_toml",
+ name: ".prettierrc.toml"
+ },
+ {
+ dir: "config_file_js",
+ name: ".prettierrc.js"
+ },
+ {
+ dir: "config_file_ts",
+ name: ".prettierrc.ts"
+ }
+ ];
+
+ for (const config of configs) {
+ const cwd = join(testdata, config.dir);
+ const prettierFile = join(Deno.cwd(), "prettier", "main.ts");
+ const { stdout, stderr } = Deno.run({
+ args: [
+ execPath(),
+ "run",
+ "--allow-read",
+ "--allow-env",
+ prettierFile,
+ "../5.ts",
+ "--config",
+ config.name
+ ],
+ stdout: "piped",
+ stderr: "piped",
+ cwd
+ });
+
+ const output = decoder.decode(await Deno.readAll(stdout));
+ const errMsg = decoder.decode(await Deno.readAll(stderr));
+
+ assertEquals(
+ errMsg
+ .split(EOL)
+ .filter((line: string) => line.indexOf("Compile") !== 0)
+ .join(EOL),
+ ""
+ );
+
+ assertEquals(output, `console.log('0');\n`);
+ }
+});
+
+test(async function testPrettierWithAutoIgnore(): Promise<void> {
+ // only format typescript file
+ const cwd = join(testdata, "ignore_file");
+ const prettierFile = join(Deno.cwd(), "prettier", "main.ts");
+ const { stdout, stderr } = Deno.run({
+ args: [
+ execPath(),
+ "run",
+ "--allow-read",
+ "--allow-env",
+ prettierFile,
+ "**/*",
+ "--ignore-path",
+ "auto"
+ ],
+ stdout: "piped",
+ stderr: "piped",
+ cwd
+ });
+
+ assertEquals(decoder.decode(await Deno.readAll(stderr)), "");
+
+ assertEquals(
+ decoder.decode(await Deno.readAll(stdout)),
+ `console.log("typescript");\nconsole.log("typescript1");\n`
+ );
+});
+
+test(async function testPrettierWithSpecifiedIgnore(): Promise<void> {
+ // only format javascript file
+ const cwd = join(testdata, "ignore_file");
+ const prettierFile = join(Deno.cwd(), "prettier", "main.ts");
+ const { stdout, stderr } = Deno.run({
+ args: [
+ execPath(),
+ "run",
+ "--allow-read",
+ "--allow-env",
+ prettierFile,
+ "**/*",
+ "--ignore-path",
+ "typescript.prettierignore"
+ ],
+ stdout: "piped",
+ stderr: "piped",
+ cwd
+ });
+
+ assertEquals(decoder.decode(await Deno.readAll(stderr)), "");
+
+ assertEquals(
+ decoder.decode(await Deno.readAll(stdout)),
+ `console.log("javascript");\nconsole.log("javascript1");\n`
+ );
+});
+
runIfMain(import.meta);
diff --git a/std/prettier/testdata/5.ts b/std/prettier/testdata/5.ts
new file mode 100644
index 000000000..f1b5b9cf1
--- /dev/null
+++ b/std/prettier/testdata/5.ts
@@ -0,0 +1 @@
+console.log("0" )
diff --git a/std/prettier/testdata/config_file_js/.prettierrc.js b/std/prettier/testdata/config_file_js/.prettierrc.js
new file mode 100644
index 000000000..ba52f4d09
--- /dev/null
+++ b/std/prettier/testdata/config_file_js/.prettierrc.js
@@ -0,0 +1,5 @@
+// prettier.config.js or .prettierrc.js
+export default {
+ singleQuote: true,
+ trailingComma: "all"
+};
diff --git a/std/prettier/testdata/config_file_json/.prettierrc.json b/std/prettier/testdata/config_file_json/.prettierrc.json
new file mode 100644
index 000000000..a20502b7f
--- /dev/null
+++ b/std/prettier/testdata/config_file_json/.prettierrc.json
@@ -0,0 +1,4 @@
+{
+ "singleQuote": true,
+ "trailingComma": "all"
+}
diff --git a/std/prettier/testdata/config_file_toml/.prettierrc.toml b/std/prettier/testdata/config_file_toml/.prettierrc.toml
new file mode 100644
index 000000000..e5aa41d6e
--- /dev/null
+++ b/std/prettier/testdata/config_file_toml/.prettierrc.toml
@@ -0,0 +1,2 @@
+singleQuote = true
+trailingComma= "all"
diff --git a/std/prettier/testdata/config_file_ts/.prettierrc.ts b/std/prettier/testdata/config_file_ts/.prettierrc.ts
new file mode 100644
index 000000000..ba52f4d09
--- /dev/null
+++ b/std/prettier/testdata/config_file_ts/.prettierrc.ts
@@ -0,0 +1,5 @@
+// prettier.config.js or .prettierrc.js
+export default {
+ singleQuote: true,
+ trailingComma: "all"
+};
diff --git a/std/prettier/testdata/ignore_file/.prettierignore b/std/prettier/testdata/ignore_file/.prettierignore
new file mode 100644
index 000000000..717509839
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/.prettierignore
@@ -0,0 +1,3 @@
+# ignore javascript/markdown file
+*.js
+*.md
diff --git a/std/prettier/testdata/ignore_file/0.js b/std/prettier/testdata/ignore_file/0.js
new file mode 100644
index 000000000..74c289409
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/0.js
@@ -0,0 +1 @@
+console.log("javascript" )
diff --git a/std/prettier/testdata/ignore_file/0.ts b/std/prettier/testdata/ignore_file/0.ts
new file mode 100644
index 000000000..e21cddf3d
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/0.ts
@@ -0,0 +1 @@
+console.log("typescript" )
diff --git a/std/prettier/testdata/ignore_file/1.js b/std/prettier/testdata/ignore_file/1.js
new file mode 100644
index 000000000..5bdbd94d9
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/1.js
@@ -0,0 +1 @@
+console.log("javascript1" )
diff --git a/std/prettier/testdata/ignore_file/1.ts b/std/prettier/testdata/ignore_file/1.ts
new file mode 100644
index 000000000..21b56c25c
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/1.ts
@@ -0,0 +1 @@
+console.log("typescript1" )
diff --git a/std/prettier/testdata/ignore_file/README.md b/std/prettier/testdata/ignore_file/README.md
new file mode 100644
index 000000000..0b7d72a6f
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/README.md
@@ -0,0 +1,5 @@
+test format
+
+```javascript
+console.log('')
+``` \ No newline at end of file
diff --git a/std/prettier/testdata/ignore_file/typescript.prettierignore b/std/prettier/testdata/ignore_file/typescript.prettierignore
new file mode 100644
index 000000000..212f62eef
--- /dev/null
+++ b/std/prettier/testdata/ignore_file/typescript.prettierignore
@@ -0,0 +1,3 @@
+# ignore typescript/markdown file
+*.ts
+*.md