Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(config): support TOML configuration files #4877

Merged
merged 14 commits into from Aug 3, 2018
9 changes: 9 additions & 0 deletions docs/configuration.md
Expand Up @@ -6,6 +6,7 @@ title: Configuration File
Prettier uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file support. This means you can configure prettier via:

- A `.prettierrc` file, written in YAML or JSON, with optional extensions: `.yaml/.yml/.json/.js`.
- A `.prettierrc.toml` file, written in TOML (the `.toml` extension is _required_).
- A `prettier.config.js` file that exports an object.
- A `"prettier"` key in your `package.json` file.

Expand Down Expand Up @@ -42,6 +43,14 @@ printWidth: 100
parser: flow
```

TOML:

```toml
# .prettierrc.toml
printWidth = 100
parser = "flow"
```

## Configuration Overrides

Prettier borrows eslint's [override format](http://eslint.org/docs/user-guide/configuring#example-configuration). This allows you to apply configuration to specific files.
Expand Down
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -17,6 +17,7 @@
"@babel/code-frame": "7.0.0-beta.46",
"@babel/parser": "7.0.0-beta.49",
"@glimmer/syntax": "0.30.3",
"@iarna/toml": "2.0.0",
"camelcase": "4.1.0",
"chalk": "2.1.0",
"cjk-regex": "1.0.2",
Expand Down
14 changes: 14 additions & 0 deletions src/config/resolve-config.js
Expand Up @@ -6,6 +6,7 @@ const path = require("path");
const mem = require("mem");

const resolveEditorConfig = require("./resolve-config-editorconfig");
const loadToml = require("../utils/load-toml");

const getExplorerMemoized = mem(opts => {
const explorer = thirdParty.cosmiconfig("prettier", {
Expand All @@ -22,6 +23,19 @@ const getExplorerMemoized = mem(opts => {
delete result.config.$schema;
}
return result;
},
searchPlaces: [
"package.json",
".prettierrc",
".prettierrc.json",
".prettierrc.yaml",
".prettierrc.yml",
".prettierrc.js",
"prettier.config.js",
".prettierrc.toml"
],
loaders: {
".toml": loadToml
}
});

Expand Down
12 changes: 12 additions & 0 deletions src/utils/load-toml.js
@@ -0,0 +1,12 @@
"use strict";

const toml = require("@iarna/toml");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could use @iarna/toml/parse-string to further reduce the bundle size.


module.exports = function(filePath, content) {
try {
return toml.parse(content);
} catch (error) {
error.message = `TOML Error in ${filePath}:\n${error.message}`;
throw error;
}
};
Expand Up @@ -62,6 +62,16 @@ function rcJson() {
],
);
}
function rcToml() {
console.log.apply(
null,
[
'rc-toml/file.js',
'should have trailing comma',
'and single quotes',
],
);
}
function rcYaml() {
console.log.apply(
null,
Expand Down Expand Up @@ -142,6 +152,13 @@ function rcJson() {
'and single quotes',
]);
}
function rcToml() {
console.log.apply(null, [
'rc-toml/file.js',
'should have trailing comma',
'and single quotes',
]);
}
function rcYaml() {
console.log.apply(null, [
'rc-yaml/file.js',
Expand Down Expand Up @@ -181,6 +198,15 @@ exports[`resolves json configuration file with --find-config-path file (stdout)

exports[`resolves json configuration file with --find-config-path file (write) 1`] = `Array []`;

exports[`resolves toml configuration file with --find-config-path file (stderr) 1`] = `""`;

exports[`resolves toml configuration file with --find-config-path file (stdout) 1`] = `
"rc-toml/.prettierrc.toml
"
`;

exports[`resolves toml configuration file with --find-config-path file (write) 1`] = `Array []`;

exports[`resolves yaml configuration file with --find-config-path file (stderr) 1`] = `""`;

exports[`resolves yaml configuration file with --find-config-path file (stdout) 1`] = `
Expand Down
36 changes: 36 additions & 0 deletions tests_integration/__tests__/__snapshots__/load-toml.js.snap
@@ -0,0 +1,36 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`TOML loads toml successfully 1`] = `
Object {
"database": Object {
"connection_max": 5000,
"enabled": true,
"ports": Array [
8001,
8001,
8002,
],
"server": "192.168.1.1",
Symbol(type): Symbol(table),
Symbol(declared): true,
},
"owner": Object {
"dob": 1979-05-27T15:32:00.000Z,
"name": "Tom Preston-Werner",
Symbol(type): Symbol(table),
Symbol(declared): true,
},
"title": "TOML Example",
Symbol(type): Symbol(table),
Symbol(declared): false,
}
`;

exports[`TOML throws error on incorrect toml 1`] = `
"TOML Error in load-toml.js:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The currentFile looks weird to me, it confused me why there's a TOML parsing error for a js file. We should rename it to something ends with .toml.

Unknown character \\"47\\" at row 1, col 2, pos 1:
1> ///ERROR///
^

"
`;
Expand Up @@ -139,6 +139,16 @@ function rcJson() {
],
);
}
function rcToml() {
console.log.apply(
null,
[
'rc-toml/file.js',
'should have trailing comma',
'and single quotes',
],
);
}
function rcYaml() {
console.log.apply(
null,
Expand Down Expand Up @@ -216,6 +226,16 @@ function rcJson() {
],
);
}
function rcToml() {
console.log.apply(
null,
[
'rc-toml/file.js',
'should have trailing comma',
'and single quotes',
],
);
}
function rcYaml() {
console.log.apply(
null,
Expand Down
6 changes: 6 additions & 0 deletions tests_integration/__tests__/config-resolution.js
Expand Up @@ -43,6 +43,12 @@ describe("resolves yaml configuration file with --find-config-path file", () =>
});
});

describe("resolves toml configuration file with --find-config-path file", () => {
runPrettier("cli/config/", ["--find-config-path", "rc-toml/file.js"]).test({
status: 0
});
});

describe("prints nothing when no file found with --find-config-path", () => {
runPrettier("cli/config/", ["--find-config-path", ".."]).test({
stdout: "",
Expand Down
37 changes: 37 additions & 0 deletions tests_integration/__tests__/load-toml.js
@@ -0,0 +1,37 @@
"use strict";

const loadToml = require("../../src/utils/load-toml");

describe("TOML", () => {
const currentFile = "load-toml.js";

const exampleToml = `
# This is a TOML document.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00 # First class dates
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
`;

const wrongToml = "///ERROR///";

test("loads toml successfully", () => {
const parsedToml = loadToml(currentFile, exampleToml);
expect(parsedToml).toMatchSnapshot();
});

test("throws error on incorrect toml", () => {
expect(() => {
loadToml(currentFile, wrongToml);
}).toThrow();

expect(() => {
loadToml(currentFile, wrongToml);
}).toThrowErrorMatchingSnapshot();
});
});
2 changes: 2 additions & 0 deletions tests_integration/cli/config/rc-toml/.prettierrc.toml
@@ -0,0 +1,2 @@
trailingComma = "all"
singleQuote = true
7 changes: 7 additions & 0 deletions tests_integration/cli/config/rc-toml/file.js
@@ -0,0 +1,7 @@
function rcToml() {
console.log.apply(null, [
"rc-toml/file.js",
"should have trailing comma",
"and single quotes"
]);
}
4 changes: 4 additions & 0 deletions yarn.lock
Expand Up @@ -563,6 +563,10 @@
dependencies:
"@glimmer/util" "^0.30.3"

"@iarna/toml@2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.0.0.tgz#7802115684397785b3b6dc8a3ba50e30d7a7422b"

"@types/commander@^2.11.0":
version "2.12.2"
resolved "https://registry.yarnpkg.com/@types/commander/-/commander-2.12.2.tgz#183041a23842d4281478fa5d23c5ca78e6fd08ae"
Expand Down