diff --git a/changelog_unreleased/api/pr-8890.md b/changelog_unreleased/api/pr-8890.md index ab1882f93..9bcfeb182 100644 --- a/changelog_unreleased/api/pr-8890.md +++ b/changelog_unreleased/api/pr-8890.md @@ -1,3 +1,7 @@ -#### Support `.prettierrc.cjs` and `prettier.config.cjs` config file ([#8890](https://github.com/prettier/prettier/pull/8890) by [@fisker](https://github.com/fisker)) +#### Support `.cjs` and `.json5` configuration files ([#8890](https://github.com/prettier/prettier/pull/8890), [#8957](https://github.com/prettier/prettier/pull/8957) by [@fisker](https://github.com/fisker)) -New config files `.prettierrc.cjs` and `prettier.config.cjs` are supported. +Added new format of configuration files: + +- `.prettierrc.json5` +- `.prettierrc.cjs` +- `prettier.config.cjs` diff --git a/docs/configuration.md b/docs/configuration.md index e60f00cd4..ca89213f0 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -7,7 +7,7 @@ Prettier uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for co - A `"prettier"` key in your `package.json` file. - A `.prettierrc` file written in JSON or YAML. -- A `.prettierrc.json`, `.prettierrc.yml`, or `.prettierrc.yaml` file. +- A `.prettierrc.json`, `.prettierrc.yml`, `.prettierrc.yaml`, or `.prettierrc.json5` file. - A `.prettierrc.js`, `.prettierrc.cjs`, `prettier.config.js`, or `prettier.config.cjs` file that exports an object using `module.exports`. - A `.prettierrc.toml` file. diff --git a/package.json b/package.json index 3b87c3383..b394175fe 100644 --- a/package.json +++ b/package.json @@ -52,6 +52,7 @@ "html-void-elements": "1.0.5", "ignore": "4.0.6", "jest-docblock": "26.0.0", + "json5": "2.1.3", "leven": "3.1.0", "lines-and-columns": "1.1.6", "linguist-languages": "7.10.0", diff --git a/src/config/resolve-config.js b/src/config/resolve-config.js index ca7bbf1ea..090be9b15 100644 --- a/src/config/resolve-config.js +++ b/src/config/resolve-config.js @@ -6,6 +6,7 @@ const mem = require("mem"); const thirdParty = require("../common/third-party"); const loadToml = require("../utils/load-toml"); +const loadJson5 = require("../utils/load-json5"); const resolve = require("../common/resolve"); const resolveEditorConfig = require("./resolve-config-editorconfig"); @@ -39,6 +40,7 @@ const getExplorerMemoized = mem( ".prettierrc.json", ".prettierrc.yaml", ".prettierrc.yml", + ".prettierrc.json5", ".prettierrc.js", ".prettierrc.cjs", "prettier.config.js", @@ -47,6 +49,7 @@ const getExplorerMemoized = mem( ], loaders: { ".toml": loadToml, + ".json5": loadJson5, }, }); diff --git a/src/utils/load-json5.js b/src/utils/load-json5.js new file mode 100644 index 000000000..126aaf64c --- /dev/null +++ b/src/utils/load-json5.js @@ -0,0 +1,12 @@ +"use strict"; + +const { parse } = require("json5"); + +module.exports = function (filePath, content) { + try { + return parse(content); + } catch (error) { + error.message = `JSON5 Error in ${filePath}:\n${error.message}`; + throw error; + } +}; diff --git a/tests_integration/__tests__/config-resolution.js b/tests_integration/__tests__/config-resolution.js index 872fa89f7..bea830899 100644 --- a/tests_integration/__tests__/config-resolution.js +++ b/tests_integration/__tests__/config-resolution.js @@ -308,3 +308,27 @@ test(".cjs config file", async () => { await expect(prettier.resolveConfig(file)).resolves.toMatchObject(config); } }); + +test(".json5 config file", async () => { + const parentDirectory = path.join(__dirname, "../cli/config/rc-json5"); + const config = { + trailingComma: "all", + printWidth: 81, + tabWidth: 3, + }; + const file = path.join(parentDirectory, "json5/foo.js"); + + expect(prettier.resolveConfig.sync(file)).toEqual(config); + await expect(prettier.resolveConfig(file)).resolves.toMatchObject(config); +}); + +test(".json5 config file(invalid)", async () => { + const parentDirectory = path.join(__dirname, "../cli/config/rc-json5"); + const file = path.join(parentDirectory, "invalid/foo.js"); + const error = /JSON5: invalid end of input at 2:1/; + + expect(() => { + prettier.resolveConfig.sync(file); + }).toThrowError(error); + await expect(prettier.resolveConfig(file)).rejects.toThrow(error); +}); diff --git a/tests_integration/cli/config/rc-json5/invalid/.prettierrc.json5 b/tests_integration/cli/config/rc-json5/invalid/.prettierrc.json5 new file mode 100644 index 000000000..98232c64f --- /dev/null +++ b/tests_integration/cli/config/rc-json5/invalid/.prettierrc.json5 @@ -0,0 +1 @@ +{ diff --git a/tests_integration/cli/config/rc-json5/json5/.prettierrc.json5 b/tests_integration/cli/config/rc-json5/json5/.prettierrc.json5 new file mode 100644 index 000000000..8cdc1a362 --- /dev/null +++ b/tests_integration/cli/config/rc-json5/json5/.prettierrc.json5 @@ -0,0 +1,6 @@ +{ +// comment + trailingComma: 'all', + printWidth: +81, + tabWidth: 3., +} diff --git a/yarn.lock b/yarn.lock index 4430facc2..f890e7f8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5309,6 +5309,13 @@ json-stringify-safe@~5.0.1: resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= +json5@2.1.3, json5@^2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" + integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== + dependencies: + minimist "^1.2.5" + json5@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" @@ -5316,13 +5323,6 @@ json5@^1.0.1: dependencies: minimist "^1.2.0" -json5@^2.1.2: - version "2.1.3" - resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.3.tgz#c9b0f7fa9233bfe5807fe66fcf3a5617ed597d43" - integrity sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA== - dependencies: - minimist "^1.2.5" - jsonfile@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.0.1.tgz#98966cba214378c8c84b82e085907b40bf614179"