diff --git a/cspell.json b/cspell.json index 67866f185..4916f67fe 100644 --- a/cspell.json +++ b/cspell.json @@ -181,6 +181,7 @@ "l’objectif", "lcov", "libdef", + "lilconfig", "linearize", "linebreak", "linebreaks", @@ -342,8 +343,8 @@ "typecasted", "typecheck", "typeof", - "Uchino", "Ubie", + "Uchino", "Umidbek", "unaries", "uncook", diff --git a/docs/api.md b/docs/api.md index 080e5eb15..bbcebfac1 100644 --- a/docs/api.md +++ b/docs/api.md @@ -66,7 +66,7 @@ If `options.editorconfig` is `true` and an [`.editorconfig` file](https://editor The promise will be rejected if there was an error parsing the configuration file. -The search starts at `process.cwd()`, or at `filePath` if provided. Please see the [cosmiconfig docs](https://github.com/davidtheclark/cosmiconfig#explorersearch) for details on how the resolving works. +The search starts at `process.cwd()`, or at `filePath` if provided. Please see the [lilconfig docs](https://github.com/antonk52/lilconfig) for details on how the resolving works. ```js const configFile = await prettier.resolveConfigFile(filePath); diff --git a/docs/configuration.md b/docs/configuration.md index dbf4435df..fc81084c2 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -3,7 +3,7 @@ id: configuration title: Configuration File --- -Prettier uses [cosmiconfig](https://github.com/davidtheclark/cosmiconfig) for configuration file support. This means you can configure Prettier via (in order of precedence): +Prettier uses [lilconfig](https://github.com/antonk52/lilconfig) for configuration file support. This means you can configure Prettier via (in order of precedence): - A `"prettier"` key in your `package.json` file. - A `.prettierrc` file written in JSON or YAML. diff --git a/package.json b/package.json index c9852f68e..e4c0c21b9 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,6 @@ "ci-info": "3.8.0", "cjk-regex": "3.0.0", "collapse-white-space": "1.0.6", - "cosmiconfig": "8.2.0", "css-units-list": "2.0.1", "dashify": "2.0.0", "diff": "5.1.0", @@ -74,8 +73,10 @@ "ignore": "5.2.4", "import-meta-resolve": "3.0.0", "jest-docblock": "29.6.3", + "js-yaml": "4.1.0", "json5": "2.2.3", "leven": "4.0.0", + "lilconfig": "2.1.0", "lines-and-columns": "2.0.3", "linguist-languages": "7.26.1", "mem": "9.0.2", @@ -84,6 +85,7 @@ "minimist": "1.2.8", "n-readlines": "1.0.1", "outdent": "0.8.0", + "parse-json": "7.0.0", "please-upgrade-node": "3.2.0", "postcss": "8.4.28", "postcss-less": "6.0.0", diff --git a/scripts/build/config.js b/scripts/build/config.js index 85946cf8f..a3f3f5072 100644 --- a/scripts/build/config.js +++ b/scripts/build/config.js @@ -554,6 +554,10 @@ const nodejsFiles = [ paths: [require.resolve("@babel/code-frame")], }), }, + { + module: getPackageFile("js-yaml/dist/js-yaml.mjs"), + path: getPackageFile("js-yaml/lib/loader.js"), + }, ], addDefaultExport: true, }, @@ -582,19 +586,10 @@ const nodejsFiles = [ input: "src/common/mockable.js", outputBaseName: "internal/internal", replaceModule: [ - // cosmiconfig@6 -> import-fresh can't find parentModule, since module is bundled { - module: require.resolve("parent-module"), - path: path.join(dirname, "./shims/parent-module.cjs"), - }, - // `@babel/code-frame` and `@babel/highlight` use compatible `chalk`, but they installed separately - { - module: require.resolve("chalk", { - paths: [require.resolve("@babel/highlight")], - }), - path: require.resolve("chalk", { - paths: [require.resolve("@babel/code-frame")], - }), + module: require.resolve("lilconfig"), + find: "exports.lilconfigSync = lilconfigSync;", + replacement: "", }, ], }, diff --git a/scripts/build/shims/parent-module.cjs b/scripts/build/shims/parent-module.cjs deleted file mode 100644 index 113b1684d..000000000 --- a/scripts/build/shims/parent-module.cjs +++ /dev/null @@ -1,5 +0,0 @@ -"use strict"; - -const parentModule = (file) => file; - -module.exports = parentModule; diff --git a/src/common/mockable.js b/src/common/mockable.js index ec2a5d160..1f406ced2 100644 --- a/src/common/mockable.js +++ b/src/common/mockable.js @@ -1,5 +1,5 @@ import fs from "node:fs/promises"; -import { cosmiconfig } from "cosmiconfig"; +import { lilconfig } from "lilconfig"; import { sync as findParentDir } from "find-parent-dir"; import getStdin from "get-stdin"; import { isCI } from "ci-info"; @@ -9,7 +9,7 @@ function writeFormattedFile(file, data) { } const mockable = { - cosmiconfig, + lilconfig, findParentDir, getStdin, isCI: () => isCI, diff --git a/src/config/get-prettier-config-explorer.js b/src/config/get-prettier-config-explorer.js index e39379aee..a2ceeef5a 100644 --- a/src/config/get-prettier-config-explorer.js +++ b/src/config/get-prettier-config-explorer.js @@ -1,9 +1,12 @@ +import { pathToFileURL } from "node:url"; import parseToml from "@iarna/toml/parse-async.js"; import parseJson5 from "json5/lib/parse.js"; +import yaml from "js-yaml"; +import parseJson from "parse-json"; import mockable from "../common/mockable.js"; import loadExternalConfig from "./load-external-config.js"; -const { cosmiconfig } = mockable; +const { lilconfig } = mockable; const searchPlaces = [ "package.json", @@ -21,6 +24,20 @@ const searchPlaces = [ ".prettierrc.toml", ]; +async function loadJs(filepath /*, content*/) { + const module = await import(pathToFileURL(filepath).href); + return module.default; +} + +function loadYaml(filepath, content) { + try { + return yaml.load(content); + } catch (/** @type {any} */ error) { + error.message = `YAML Error in ${filepath}:\n${error.message}`; + throw error; + } +} + const loaders = { async ".toml"(filePath, content) { try { @@ -38,6 +55,19 @@ const loaders = { throw error; } }, + ".json"(filePath, content) { + try { + return parseJson(content); + } catch (/** @type {any} */ error) { + error.message = `JSON Error in ${filePath}:\n${error.message}`; + throw error; + } + }, + ".js": loadJs, + ".mjs": loadJs, + ".yaml": loadYaml, + ".yml": loadYaml, + noExt: loadYaml, }; async function transform(result) { @@ -73,16 +103,10 @@ async function transform(result) { } /** - * @param {{cache: boolean }} options - * @return {ReturnType} + * @return {ReturnType} */ -function getExplorer(options) { - return cosmiconfig("prettier", { - cache: options.cache, - transform, - searchPlaces, - loaders, - }); +function getExplorer() { + return lilconfig("prettier", { searchPlaces, loaders, transform }); } export default getExplorer; diff --git a/src/config/resolve-config.js b/src/config/resolve-config.js index 0473e4a2f..a867080bf 100644 --- a/src/config/resolve-config.js +++ b/src/config/resolve-config.js @@ -29,7 +29,9 @@ function loadPrettierConfig(filePath, options) { const { load, search } = getPrettierConfigExplorer({ cache: Boolean(useCache), }); - return configPath ? load(configPath) : search(filePath); + return configPath + ? load(configPath) + : search(filePath ? path.resolve(filePath) : undefined); } async function resolveConfig(filePath, options) { @@ -62,7 +64,7 @@ async function resolveConfig(filePath, options) { async function resolveConfigFile(filePath) { const { search } = getPrettierConfigExplorer({ cache: false }); - const result = await search(filePath); + const result = await search(filePath ? path.resolve(filePath) : undefined); return result ? result.filepath : null; } diff --git a/tests/integration/__tests__/config-resolution.js b/tests/integration/__tests__/config-resolution.js index 4e0cb05d0..dfd518295 100644 --- a/tests/integration/__tests__/config-resolution.js +++ b/tests/integration/__tests__/config-resolution.js @@ -281,7 +281,7 @@ test(".js config file", async () => { await expect(prettier.resolveConfig(file)).resolves.toMatchObject(config); } - const cjsError = /require\(\) of ES (?:Module|module)/; + const cjsError = /module is not defined in ES module scope/; for (const directoryName of [ "cjs-prettier-config-js-in-type-module", "cjs-prettierrc-js-in-type-module", diff --git a/tests/integration/__tests__/mockable.js b/tests/integration/__tests__/mockable.js index 2018bd136..bde8dcb97 100644 --- a/tests/integration/__tests__/mockable.js +++ b/tests/integration/__tests__/mockable.js @@ -6,12 +6,12 @@ import { mockable } from "../env.js"; const { __dirname } = createEsmUtils(import.meta); // This don't has to be the same result as `prettier.resolveConfig`, -// Because we are testing with default `cosmiconfigOptions` -describe("cosmiconfig", () => { - let cosmiconfig; +// Because we are testing with default `lilconfigOptions` +describe("lilconfig", () => { + let lilconfig; beforeAll(async () => { ({ - default: { cosmiconfig }, + default: { lilconfig }, } = await import(pathToFileURL(mockable))); }); @@ -45,8 +45,7 @@ describe("cosmiconfig", () => { for (const { title, dirname, file, value } of configs) { test(`async version ${title}`, async () => { - const { config, filepath } = - await cosmiconfig("prettier").search(dirname); + const { config, filepath } = await lilconfig("prettier").search(dirname); expect(config).toEqual(value); expect(filepath).toBe(file); }); diff --git a/tests/integration/cli-worker.js b/tests/integration/cli-worker.js index 7c8743af6..bc7283ae1 100644 --- a/tests/integration/cli-worker.js +++ b/tests/integration/cli-worker.js @@ -3,7 +3,7 @@ import fs from "node:fs"; import path from "node:path"; import url from "node:url"; import readline from "node:readline"; -import { cosmiconfig } from "cosmiconfig"; +import { lilconfig } from "lilconfig"; import { prettierCli, mockable as mockableModuleFile } from "./env.js"; const normalizeToPosix = @@ -66,8 +66,8 @@ async function run() { // eslint-disable-next-line require-await mockable.getStdin = async () => options.input || ""; mockable.isCI = () => Boolean(options.ci); - mockable.cosmiconfig = (moduleName, options) => - cosmiconfig(moduleName, { + mockable.lilconfig = (moduleName, options) => + lilconfig(moduleName, { ...options, stopDir: url.fileURLToPath(new URL("./cli", import.meta.url)), }); diff --git a/yarn.lock b/yarn.lock index 1d9e598c6..3c2e6137e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -52,7 +52,7 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:7.22.10, @babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.5": +"@babel/code-frame@npm:7.22.10, @babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.21.4, @babel/code-frame@npm:^7.22.5": version: 7.22.10 resolution: "@babel/code-frame@npm:7.22.10" dependencies: @@ -592,9 +592,9 @@ __metadata: linkType: hard "@cspell/dict-css@npm:^4.0.6": - version: 4.0.6 - resolution: "@cspell/dict-css@npm:4.0.6" - checksum: fc816014e4dfd78d4a00cd311c8f96657d899e10767766cdcdfbaf61beac8dd4d23e903dc40b679f31da7df03e7d4eb593a81810c50eeddbbb190b0d605160f0 + version: 4.0.7 + resolution: "@cspell/dict-css@npm:4.0.7" + checksum: 17a628450665f77a7b87edf98d12aa9f406b6805ca4a7e25ff1a9a58e9a0ae190583fd030b8143af5964f85dabfd1d510021f9072c2bbd478b547ac419689451 languageName: node linkType: hard @@ -2915,18 +2915,6 @@ __metadata: languageName: node linkType: hard -"cosmiconfig@npm:8.2.0": - version: 8.2.0 - resolution: "cosmiconfig@npm:8.2.0" - dependencies: - import-fresh: ^3.2.1 - js-yaml: ^4.1.0 - parse-json: ^5.0.0 - path-type: ^4.0.0 - checksum: 836d5d8efa750f3fb17b03d6ca74cd3154ed025dffd045304b3ef59637f662bde1e5dc88f8830080d180ec60841719cf4ea2ce73fb21ec694b16865c478ff297 - languageName: node - linkType: hard - "cross-env@npm:7.0.3": version: 7.0.3 resolution: "cross-env@npm:7.0.3" @@ -3351,7 +3339,7 @@ __metadata: languageName: node linkType: hard -"error-ex@npm:^1.3.1": +"error-ex@npm:^1.3.1, error-ex@npm:^1.3.2": version: 1.3.2 resolution: "error-ex@npm:1.3.2" dependencies: @@ -3360,7 +3348,7 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4, es-abstract@npm:^1.21.2, es-abstract@npm:^1.21.3": +"es-abstract@npm:^1.19.0, es-abstract@npm:^1.20.4, es-abstract@npm:^1.21.2, es-abstract@npm:^1.22.1": version: 1.22.1 resolution: "es-abstract@npm:1.22.1" dependencies: @@ -3408,13 +3396,13 @@ __metadata: linkType: hard "es-iterator-helpers@npm:^1.0.12": - version: 1.0.13 - resolution: "es-iterator-helpers@npm:1.0.13" + version: 1.0.14 + resolution: "es-iterator-helpers@npm:1.0.14" dependencies: asynciterator.prototype: ^1.0.0 call-bind: ^1.0.2 define-properties: ^1.2.0 - es-abstract: ^1.21.3 + es-abstract: ^1.22.1 es-set-tostringtag: ^2.0.1 function-bind: ^1.1.1 get-intrinsic: ^1.2.1 @@ -3425,7 +3413,7 @@ __metadata: internal-slot: ^1.0.5 iterator.prototype: ^1.1.0 safe-array-concat: ^1.0.0 - checksum: 1b08ae7388439121fee1129cb23497abd7bf23dd440f7fa44d119c9f92f38f9b7d75b7d98453fcd15948a7eb58abb2a48c673c7250d2e15871abe3641f567ed7 + checksum: 484ca398389d5e259855e2d848573233985a7e7a4126c5de62c8a554174495aea47320ae1d2b55b757ece62ac1cb8455532aa61fd123fe4e01d0567eb2d7adfa languageName: node linkType: hard @@ -5799,6 +5787,17 @@ __metadata: languageName: node linkType: hard +"js-yaml@npm:4.1.0, js-yaml@npm:^4.1.0": + version: 4.1.0 + resolution: "js-yaml@npm:4.1.0" + dependencies: + argparse: ^2.0.1 + bin: + js-yaml: bin/js-yaml.js + checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a + languageName: node + linkType: hard + "js-yaml@npm:^3.13.1": version: 3.14.1 resolution: "js-yaml@npm:3.14.1" @@ -5811,17 +5810,6 @@ __metadata: languageName: node linkType: hard -"js-yaml@npm:^4.1.0": - version: 4.1.0 - resolution: "js-yaml@npm:4.1.0" - dependencies: - argparse: ^2.0.1 - bin: - js-yaml: bin/js-yaml.js - checksum: c7830dfd456c3ef2c6e355cc5a92e6700ceafa1d14bba54497b34a99f0376cecbb3e9ac14d3e5849b426d5a5140709a66237a8c991c675431271c4ce5504151a - languageName: node - linkType: hard - "jsdoctypeparser@npm:^9.0.0": version: 9.0.0 resolution: "jsdoctypeparser@npm:9.0.0" @@ -5879,6 +5867,13 @@ __metadata: languageName: node linkType: hard +"json-parse-even-better-errors@npm:^3.0.0": + version: 3.0.0 + resolution: "json-parse-even-better-errors@npm:3.0.0" + checksum: f1970b5220c7fa23d888565510752c3d5e863f93668a202fcaa719739fa41485dfc6a1db212f702ebd3c873851cc067aebc2917e3f79763cae2fdb95046f38f3 + languageName: node + linkType: hard + "json-schema-traverse@npm:^0.4.1": version: 0.4.1 resolution: "json-schema-traverse@npm:0.4.1" @@ -5965,6 +5960,13 @@ __metadata: languageName: node linkType: hard +"lilconfig@npm:2.1.0": + version: 2.1.0 + resolution: "lilconfig@npm:2.1.0" + checksum: 8549bb352b8192375fed4a74694cd61ad293904eee33f9d4866c2192865c44c4eb35d10782966242634e0cbc1e91fe62b1247f148dc5514918e3a966da7ea117 + languageName: node + linkType: hard + "lines-and-columns@npm:2.0.3, lines-and-columns@npm:^2.0.3": version: 2.0.3 resolution: "lines-and-columns@npm:2.0.3" @@ -6857,6 +6859,19 @@ __metadata: languageName: node linkType: hard +"parse-json@npm:7.0.0": + version: 7.0.0 + resolution: "parse-json@npm:7.0.0" + dependencies: + "@babel/code-frame": ^7.21.4 + error-ex: ^1.3.2 + json-parse-even-better-errors: ^3.0.0 + lines-and-columns: ^2.0.3 + type-fest: ^3.8.0 + checksum: de6c756f65af568439a7ac87c830e5a8b98bd25160a8832872183588a139f9c8fd8bab96c8bc49788f5a957a59d8de7b5a3fa8a01027248b3079433f81dd5590 + languageName: node + linkType: hard + "parse-json@npm:^4.0.0": version: 4.0.0 resolution: "parse-json@npm:4.0.0" @@ -7161,7 +7176,6 @@ __metadata: ci-info: 3.8.0 cjk-regex: 3.0.0 collapse-white-space: 1.0.6 - cosmiconfig: 8.2.0 cross-env: 7.0.3 cspell: 7.0.1 css-units-list: 2.0.1 @@ -7210,8 +7224,10 @@ __metadata: jest-snapshot-serializer-ansi: 2.1.0 jest-snapshot-serializer-raw: 2.0.0 jest-watch-typeahead: 2.2.2 + js-yaml: 4.1.0 json5: 2.2.3 leven: 4.0.0 + lilconfig: 2.1.0 lines-and-columns: 2.0.3 linguist-languages: 7.26.1 magic-string: 0.30.3 @@ -7222,6 +7238,7 @@ __metadata: n-readlines: 1.0.1 npm-run-all: 4.1.5 outdent: 0.8.0 + parse-json: 7.0.0 path-browserify: 1.0.1 please-upgrade-node: 3.2.0 postcss: 8.4.28 @@ -8497,10 +8514,10 @@ __metadata: languageName: node linkType: hard -"type-fest@npm:^3.0.0": - version: 3.12.0 - resolution: "type-fest@npm:3.12.0" - checksum: 11cb6f40e42f92c462a13677eafedf5c48353eaefa8e489a146e55fe0ae5cecd59a2ba03cd6b294345b5ea304361891a6313c23ed959fa0117f63fb71ee6cbab +"type-fest@npm:^3.0.0, type-fest@npm:^3.8.0": + version: 3.13.1 + resolution: "type-fest@npm:3.13.1" + checksum: c06b0901d54391dc46de3802375f5579868949d71f93b425ce564e19a428a0d411ae8d8cb0e300d330071d86152c3ea86e744c3f2860a42a79585b6ec2fdae8e languageName: node linkType: hard