Support shared Prettier configuration (#5963)
* Support external configuration * Document changes * Update existing snapshots * Update existing snapshots (2) * Fix typo in docs * Add example config repomaster
parent
ef48f71b7b
commit
f32b289032
|
@ -42,6 +42,35 @@ Examples:
|
||||||
|
|
||||||
-->
|
-->
|
||||||
|
|
||||||
|
- Config: Support shared configurations ([#5963] by [@azz])
|
||||||
|
|
||||||
|
Sharing a Prettier configuration is simple: just publish a module that exports a configuration object, say `@company/prettier-config`, and reference it in your `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "my-cool-library",
|
||||||
|
"version": "9000.0.1",
|
||||||
|
"prettier": "@company/prettier-config"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't want to use `package.json`, you can use any of the supported extensions to export a string, e.g. `.prettierrc.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"@company/prettier-config"
|
||||||
|
```
|
||||||
|
|
||||||
|
An example configuration repository is available [here](https://github.com/azz/prettier-config).
|
||||||
|
|
||||||
|
> Note: This method does **not** offer a way to _extend_ the configuration to overwrite some properties from the shared configuration. If you need to do that, import the file in a `.prettierrc.js` file and export the modifications, e.g:
|
||||||
|
>
|
||||||
|
> ```js
|
||||||
|
> module.exports = {
|
||||||
|
> ...require("@company/prettier-config"),
|
||||||
|
> semi: false
|
||||||
|
> };
|
||||||
|
> ```
|
||||||
|
|
||||||
- JavaScript: Add an option to modify when Prettier quotes object properties ([#5934] by [@azz])
|
- JavaScript: Add an option to modify when Prettier quotes object properties ([#5934] by [@azz])
|
||||||
**`--quote-props <as-needed|preserve|consistent>`**
|
**`--quote-props <as-needed|preserve|consistent>`**
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,35 @@ overrides:
|
||||||
|
|
||||||
`files` is required for each override, and may be a string or array of strings. `excludeFiles` may be optionally provided to exclude files for a given rule, and may also be a string or array of strings.
|
`files` is required for each override, and may be a string or array of strings. `excludeFiles` may be optionally provided to exclude files for a given rule, and may also be a string or array of strings.
|
||||||
|
|
||||||
|
## Sharing configurations
|
||||||
|
|
||||||
|
Sharing a Prettier configuration is simple: just publish a module that exports a configuration object, say `@company/prettier-config`, and reference it in your `package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"name": "my-cool-library",
|
||||||
|
"version": "9000.0.1",
|
||||||
|
"prettier": "@company/prettier-config"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't want to use `package.json`, you can use any of the supported extensions to export a string, e.g. `.prettierrc.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"@company/prettier-config"
|
||||||
|
```
|
||||||
|
|
||||||
|
An example configuration repository is available [here](https://github.com/azz/prettier-config).
|
||||||
|
|
||||||
|
> Note: This method does **not** offer a way to _extend_ the configuration to overwrite some properties from the shared configuration. If you need to do that, import the file in a `.prettierrc.js` file and export the modifications, e.g:
|
||||||
|
>
|
||||||
|
> ```js
|
||||||
|
> module.exports = {
|
||||||
|
> ...require("@company/prettier-config"),
|
||||||
|
> semi: false
|
||||||
|
> };
|
||||||
|
> ```
|
||||||
|
|
||||||
## Setting the [parser](options.md#parser) option
|
## Setting the [parser](options.md#parser) option
|
||||||
|
|
||||||
By default, Prettier automatically infers which parser to use based on the input file extension. Combined with `overrides` you can teach Prettier how to parse files it does not recognize.
|
By default, Prettier automatically infers which parser to use based on the input file extension. Combined with `overrides` you can teach Prettier how to parse files it does not recognize.
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
const thirdParty = require("../common/third-party");
|
const thirdParty = require("../common/third-party");
|
||||||
const minimatch = require("minimatch");
|
const minimatch = require("minimatch");
|
||||||
|
const resolve = require("resolve");
|
||||||
const path = require("path");
|
const path = require("path");
|
||||||
const mem = require("mem");
|
const mem = require("mem");
|
||||||
|
|
||||||
|
@ -13,6 +14,13 @@ const getExplorerMemoized = mem(opts => {
|
||||||
cache: opts.cache,
|
cache: opts.cache,
|
||||||
transform: result => {
|
transform: result => {
|
||||||
if (result && result.config) {
|
if (result && result.config) {
|
||||||
|
if (typeof result.config === "string") {
|
||||||
|
const modulePath = resolve.sync(result.config, {
|
||||||
|
basedir: path.dirname(result.filepath)
|
||||||
|
});
|
||||||
|
result.config = eval("require")(modulePath);
|
||||||
|
}
|
||||||
|
|
||||||
if (typeof result.config !== "object") {
|
if (typeof result.config !== "object") {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Config is only allowed to be an object, ` +
|
`Config is only allowed to be an object, ` +
|
||||||
|
|
|
@ -28,7 +28,7 @@ exports[`throw error for unsupported extension (stdout) 1`] = `""`;
|
||||||
exports[`throw error for unsupported extension (write) 1`] = `Array []`;
|
exports[`throw error for unsupported extension (write) 1`] = `Array []`;
|
||||||
|
|
||||||
exports[`throw error with invalid config format (stderr) 1`] = `
|
exports[`throw error with invalid config format (stderr) 1`] = `
|
||||||
"[error] Invalid configuration file: Config is only allowed to be an object, but received string in \\"<cwd>/tests_integration/cli/config/invalid/file/.prettierrc\\"
|
"[error] Invalid configuration file: Cannot find module '--invalid--' from '<cwd>/tests_integration/cli/config/invalid/file'
|
||||||
"
|
"
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,9 @@ function f() {
|
||||||
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
console.log(
|
||||||
|
\\"should have no semi\\"
|
||||||
|
)
|
||||||
console.log(
|
console.log(
|
||||||
\\"jest/__best-tests__/file.js should have semi\\"
|
\\"jest/__best-tests__/file.js should have semi\\"
|
||||||
);
|
);
|
||||||
|
@ -130,6 +133,7 @@ function f() {
|
||||||
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
console.log(\\"should have no semi\\")
|
||||||
console.log(\\"jest/__best-tests__/file.js should have semi\\");
|
console.log(\\"jest/__best-tests__/file.js should have semi\\");
|
||||||
console.log(\\"jest/Component.js should not have semi\\")
|
console.log(\\"jest/Component.js should not have semi\\")
|
||||||
console.log(\\"jest/Component.test.js should have semi\\");
|
console.log(\\"jest/Component.test.js should have semi\\");
|
||||||
|
@ -192,6 +196,15 @@ function packageTs() {
|
||||||
|
|
||||||
exports[`resolves configuration from external files and overrides by extname (write) 1`] = `Array []`;
|
exports[`resolves configuration from external files and overrides by extname (write) 1`] = `Array []`;
|
||||||
|
|
||||||
|
exports[`resolves external configuration from package.json (stderr) 1`] = `""`;
|
||||||
|
|
||||||
|
exports[`resolves external configuration from package.json (stdout) 1`] = `
|
||||||
|
"console.log(\\"should have no semi\\")
|
||||||
|
"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`resolves external configuration from package.json (write) 1`] = `Array []`;
|
||||||
|
|
||||||
exports[`resolves json configuration file with --find-config-path file (stderr) 1`] = `""`;
|
exports[`resolves json configuration file with --find-config-path file (stderr) 1`] = `""`;
|
||||||
|
|
||||||
exports[`resolves json configuration file with --find-config-path file (stdout) 1`] = `
|
exports[`resolves json configuration file with --find-config-path file (stdout) 1`] = `
|
||||||
|
|
|
@ -102,6 +102,9 @@ function f() {
|
||||||
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
console.log(
|
||||||
|
\\"should have no semi\\"
|
||||||
|
)
|
||||||
console.log(
|
console.log(
|
||||||
\\"jest/__best-tests__/file.js should have semi\\"
|
\\"jest/__best-tests__/file.js should have semi\\"
|
||||||
);
|
);
|
||||||
|
@ -191,6 +194,9 @@ function f() {
|
||||||
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
\\"should have space width 2 despite ../.editorconfig specifying 8, because ./.hg is present\\"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
console.log(
|
||||||
|
\\"should have no semi\\"
|
||||||
|
)
|
||||||
console.log(
|
console.log(
|
||||||
\\"jest/__best-tests__/file.js should have semi\\"
|
\\"jest/__best-tests__/file.js should have semi\\"
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,6 +25,12 @@ describe("accepts configuration from --config", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("resolves external configuration from package.json", () => {
|
||||||
|
runPrettier("cli/config/", ["external-config/index.js"]).test({
|
||||||
|
status: 0
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("resolves configuration file with --find-config-path file", () => {
|
describe("resolves configuration file with --find-config-path file", () => {
|
||||||
runPrettier("cli/config/", ["--find-config-path", "no-config/file.js"]).test({
|
runPrettier("cli/config/", ["--find-config-path", "no-config/file.js"]).test({
|
||||||
status: 0
|
status: 0
|
||||||
|
@ -262,3 +268,11 @@ test("API resolveConfig resolves relative path values based on config filepath",
|
||||||
pluginSearchDirs: [path.join(parentDir, "path-to-plugin-search-dir")]
|
pluginSearchDirs: [path.join(parentDir, "path-to-plugin-search-dir")]
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("API resolveConfig de-references to an external module", () => {
|
||||||
|
const currentDir = path.join(__dirname, "../cli/config/external-config");
|
||||||
|
expect(prettier.resolveConfig.sync(`${currentDir}/index.js`)).toEqual({
|
||||||
|
printWidth: 77,
|
||||||
|
semi: false
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
console.log("should have no semi");
|
4
tests_integration/cli/config/external-config/node_modules/@company/prettier-config/index.json
generated
vendored
Normal file
4
tests_integration/cli/config/external-config/node_modules/@company/prettier-config/index.json
generated
vendored
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"printWidth": 77,
|
||||||
|
"semi": false
|
||||||
|
}
|
5
tests_integration/cli/config/external-config/node_modules/@company/prettier-config/package.json
generated
vendored
Normal file
5
tests_integration/cli/config/external-config/node_modules/@company/prettier-config/package.json
generated
vendored
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"name": "@company/prettier-config",
|
||||||
|
"main": "index.json",
|
||||||
|
"version": "0.0.0"
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"prettier": "@company/prettier-config"
|
||||||
|
}
|
Loading…
Reference in New Issue