Accept URL in resolveConfig (#15354)
This commit is contained in:
1 parent
50404103ef
commit
7e45a92707
6 files changed
+94
-75
No files matched your search
@@ -1,11 +1,13 @@
|
||||
#### Accept `URL` in `prettier.resolveConfigFile()` (#15332 by @fisker)
|
||||
#### Accept `URL` in `prettier.{resolveConfig,resolveConfigFile}()` (#15332, #15354 by @fisker)
|
||||
|
||||
[`prettier.resolveConfigFile()`](https://prettier.io/docs/en/api#prettierresolveconfigfilefileurlorpath) now accepts an [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) with `file:` protocol or a url string starts with `file://`.
|
||||
|
||||
```js
|
||||
await prettier.resolveConfigFile(import.meta.url);
|
||||
```
|
||||
[`prettier.resolveConfig()`](https://prettier.io/docs/en/api#prettierresolveconfigfileurlorpath--options) and [`prettier.resolveConfigFile()`](https://prettier.io/docs/en/api#prettierresolveconfigfilefileurlorpath) now accepts an [URL](https://developer.mozilla.org/en-US/docs/Web/API/URL) with `file:` protocol or a url string starts with `file://`.
|
||||
|
||||
```js
|
||||
// `URL`
|
||||
await prettier.resolveConfig(new URL("./path/to/file", import.meta.url));
|
||||
await prettier.resolveConfigFile(new URL("./path/to/file", import.meta.url));
|
||||
|
||||
// URL string
|
||||
await prettier.resolveConfig("file:///path/to/file");
|
||||
await prettier.resolveConfigFile("file:///path/to/file");
|
||||
```
|
||||
+2
-2
@@ -33,9 +33,9 @@ await prettier.formatWithCursor(" 1", { cursorOffset: 2, parser: "babel" });
|
||||
// -> { formatted: '1;\n', cursorOffset: 1 }
|
||||
```
|
||||
|
||||
## `prettier.resolveConfig(filePath [, options])`
|
||||
## `prettier.resolveConfig(fileUrlOrPath [, options])`
|
||||
|
||||
`resolveConfig` can be used to resolve configuration for a given source file, passing its path as the first argument. The config search will start at the file path and continue to search up the directory (you can use `process.cwd()` to start searching from the current directory). Or you can pass directly the path of the config file as `options.config` if you don’t wish to search for it. A promise is returned which will resolve to:
|
||||
`resolveConfig` can be used to resolve configuration for a given source file, passing its path or url as the first argument. The config search will start at the file location and continue to search up the directory (you can use `process.cwd()` to start searching from the current directory). Or you can pass directly the path of the config file as `options.config` if you don’t wish to search for it. A promise is returned which will resolve to:
|
||||
|
||||
- An options object, providing a [config file](configuration.md) was found.
|
||||
- `null`, if no file was found.
|
||||
|
||||
@@ -35,8 +35,9 @@ function loadPrettierConfig(filePath, options) {
|
||||
: search(filePath ? path.resolve(filePath) : undefined);
|
||||
}
|
||||
|
||||
async function resolveConfig(filePath, options) {
|
||||
async function resolveConfig(fileUrlOrPath, options) {
|
||||
options = { useCache: true, ...options };
|
||||
const filePath = toPath(fileUrlOrPath);
|
||||
|
||||
const [result, editorConfigured] = await Promise.all([
|
||||
loadPrettierConfig(filePath, options),
|
||||
|
||||
Vendored
+3
-3
@@ -609,8 +609,8 @@ export interface ResolveConfigOptions {
|
||||
|
||||
/**
|
||||
* `resolveConfig` can be used to resolve configuration for a given source file,
|
||||
* passing its path as the first argument. The config search will start at the
|
||||
* file path and continue to search up the directory.
|
||||
* passing its path or url as the first argument. The config search will start at
|
||||
* the file location and continue to search up the directory.
|
||||
* (You can use `process.cwd()` to start searching from the current directory).
|
||||
*
|
||||
* A promise is returned which will resolve to:
|
||||
@@ -621,7 +621,7 @@ export interface ResolveConfigOptions {
|
||||
* The promise will be rejected if there was an error parsing the configuration file.
|
||||
*/
|
||||
export function resolveConfig(
|
||||
filePath: string,
|
||||
fileUrlOrPath: string | URL,
|
||||
options?: ResolveConfigOptions,
|
||||
): Promise<Options | null>;
|
||||
|
||||
|
||||
@@ -1,18 +1,16 @@
|
||||
import path from "node:path";
|
||||
import createEsmUtils from "esm-utils";
|
||||
import url from "node:url";
|
||||
import prettier from "../../config/prettier-entry.js";
|
||||
|
||||
const { __dirname } = createEsmUtils(import.meta);
|
||||
|
||||
test("resolves configuration from external files and overrides by extname", async () => {
|
||||
await expect(
|
||||
prettier.resolveConfig(
|
||||
path.join(__dirname, "../cli/config/external-overrides/file.js"),
|
||||
new URL("../cli/config/external-overrides/file.js", import.meta.url),
|
||||
),
|
||||
).resolves.toEqual({ tabWidth: 3, semi: false });
|
||||
await expect(
|
||||
prettier.resolveConfig(
|
||||
path.join(__dirname, "../cli/config/external-overrides/file.ts"),
|
||||
new URL("../cli/config/external-overrides/file.ts", import.meta.url),
|
||||
),
|
||||
).resolves.toEqual({ tabWidth: 3, semi: true });
|
||||
});
|
||||
@@ -88,26 +86,21 @@ test("API resolveConfig with no args", async () => {
|
||||
});
|
||||
|
||||
test("API resolveConfig with file arg", async () => {
|
||||
const file = path.resolve(path.join(__dirname, "../cli/config/js/file.js"));
|
||||
const file = new URL("../cli/config/js/file.js", import.meta.url);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
tabWidth: 8,
|
||||
});
|
||||
});
|
||||
|
||||
test("API resolveConfig with file arg and extension override", async () => {
|
||||
const file = path.resolve(
|
||||
path.join(__dirname, "../cli/config/no-config/file.ts"),
|
||||
);
|
||||
const file = new URL("../cli/config/no-config/file.ts", import.meta.url);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
semi: true,
|
||||
});
|
||||
});
|
||||
|
||||
test("API resolveConfig with file arg and .editorconfig", async () => {
|
||||
const file = path.resolve(
|
||||
path.join(__dirname, "../cli/config/editorconfig/file.js"),
|
||||
);
|
||||
|
||||
const file = new URL("../cli/config/editorconfig/file.js", import.meta.url);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
semi: false,
|
||||
});
|
||||
@@ -122,18 +115,19 @@ test("API resolveConfig with file arg and .editorconfig", async () => {
|
||||
});
|
||||
|
||||
test("API resolveConfig with file arg and .editorconfig (key = unset)", async () => {
|
||||
const file = path.resolve(
|
||||
path.join(__dirname, "../cli/config/editorconfig/tab_width=unset.js"),
|
||||
const file = new URL(
|
||||
"../cli/config/editorconfig/tab_width=unset.js",
|
||||
import.meta.url,
|
||||
);
|
||||
|
||||
await expect(
|
||||
prettier.resolveConfig(file, { editorconfig: true }),
|
||||
).resolves.not.toMatchObject({ tabWidth: "unset" });
|
||||
});
|
||||
|
||||
test("API resolveConfig with nested file arg and .editorconfig", async () => {
|
||||
const file = path.resolve(
|
||||
path.join(__dirname, "../cli/config/editorconfig/lib/file.js"),
|
||||
const file = new URL(
|
||||
"../cli/config/editorconfig/lib/file.js",
|
||||
import.meta.url,
|
||||
);
|
||||
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
@@ -150,8 +144,9 @@ test("API resolveConfig with nested file arg and .editorconfig", async () => {
|
||||
});
|
||||
|
||||
test("API resolveConfig with nested file arg and .editorconfig and indent_size = tab", async () => {
|
||||
const file = path.resolve(
|
||||
path.join(__dirname, "../cli/config/editorconfig/lib/indent_size=tab.js"),
|
||||
const file = new URL(
|
||||
"../cli/config/editorconfig/lib/indent_size=tab.js",
|
||||
import.meta.url,
|
||||
);
|
||||
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
@@ -172,44 +167,47 @@ test("API clearConfigCache", () => {
|
||||
});
|
||||
|
||||
test("API resolveConfig overrides work with dotfiles", async () => {
|
||||
const folder = path.join(__dirname, "../cli/config/dot-overrides");
|
||||
await expect(
|
||||
prettier.resolveConfig(path.join(folder, ".foo.json")),
|
||||
).resolves.toMatchObject({
|
||||
const file = new URL(
|
||||
"../cli/config/dot-overrides/.foo.json",
|
||||
import.meta.url,
|
||||
);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
tabWidth: 4,
|
||||
});
|
||||
});
|
||||
|
||||
test("API resolveConfig overrides work with absolute paths", async () => {
|
||||
// Absolute path
|
||||
const file = path.join(__dirname, "../cli/config/filepath/subfolder/file.js");
|
||||
const file = url.fileURLToPath(
|
||||
new URL("../cli/config/filepath/subfolder/file.js", import.meta.url),
|
||||
);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
tabWidth: 6,
|
||||
});
|
||||
});
|
||||
|
||||
test("API resolveConfig overrides excludeFiles", async () => {
|
||||
const notOverride = path.join(
|
||||
__dirname,
|
||||
const notOverride = new URL(
|
||||
"../cli/config/overrides-exclude-files/foo",
|
||||
import.meta.url,
|
||||
);
|
||||
await expect(prettier.resolveConfig(notOverride)).resolves.toMatchObject({
|
||||
singleQuote: true,
|
||||
trailingComma: "all",
|
||||
});
|
||||
|
||||
const singleQuote = path.join(
|
||||
__dirname,
|
||||
const singleQuote = new URL(
|
||||
"../cli/config/overrides-exclude-files/single-quote.js",
|
||||
import.meta.url,
|
||||
);
|
||||
await expect(prettier.resolveConfig(singleQuote)).resolves.toMatchObject({
|
||||
singleQuote: true,
|
||||
trailingComma: "es5",
|
||||
});
|
||||
|
||||
const doubleQuote = path.join(
|
||||
__dirname,
|
||||
const doubleQuote = new URL(
|
||||
"../cli/config/overrides-exclude-files/double-quote.js",
|
||||
import.meta.url,
|
||||
);
|
||||
await expect(prettier.resolveConfig(doubleQuote)).resolves.toMatchObject({
|
||||
singleQuote: false,
|
||||
@@ -218,19 +216,20 @@ test("API resolveConfig overrides excludeFiles", async () => {
|
||||
});
|
||||
|
||||
test("API resolveConfig removes $schema option", async () => {
|
||||
const file = path.resolve(
|
||||
path.join(__dirname, "../cli/config/$schema/index.js"),
|
||||
);
|
||||
const file = new URL("../cli/config/$schema/index.js", import.meta.url);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toEqual({
|
||||
tabWidth: 42,
|
||||
});
|
||||
});
|
||||
|
||||
test("API resolveConfig resolves relative path values based on config filepath", async () => {
|
||||
const currentDir = path.join(__dirname, "../cli/config/resolve-relative");
|
||||
const parentDir = path.resolve(currentDir, "..");
|
||||
const currentDir = new URL(
|
||||
"../cli/config/resolve-relative/",
|
||||
import.meta.url,
|
||||
);
|
||||
const parentDir = path.resolve(url.fileURLToPath(currentDir), "..");
|
||||
await expect(
|
||||
prettier.resolveConfig(`${currentDir}/index.js`),
|
||||
prettier.resolveConfig(new URL("index.js", currentDir)),
|
||||
).resolves.toMatchObject({
|
||||
plugins: [path.join(parentDir, "path-to-plugin")],
|
||||
});
|
||||
@@ -240,29 +239,32 @@ test("API resolveConfig de-references to an external module", async () => {
|
||||
const config = { printWidth: 77, semi: false };
|
||||
await expect(
|
||||
prettier.resolveConfig(
|
||||
path.join(
|
||||
__dirname,
|
||||
new URL(
|
||||
"../cli/config/external-config/cjs-package/index.js",
|
||||
import.meta.url,
|
||||
),
|
||||
),
|
||||
).resolves.toEqual(config);
|
||||
await expect(
|
||||
prettier.resolveConfig(
|
||||
path.join(
|
||||
__dirname,
|
||||
new URL(
|
||||
"../cli/config/external-config/esm-package/index.js",
|
||||
import.meta.url,
|
||||
),
|
||||
),
|
||||
).resolves.toEqual(config);
|
||||
await expect(
|
||||
prettier.resolveConfig(
|
||||
path.join(__dirname, "../cli/config/external-config/esm-file/index.js"),
|
||||
new URL(
|
||||
"../cli/config/external-config/esm-file/index.js",
|
||||
import.meta.url,
|
||||
),
|
||||
),
|
||||
).resolves.toEqual(config);
|
||||
});
|
||||
|
||||
test(".js config file", async () => {
|
||||
const parentDirectory = path.join(__dirname, "../cli/config/rc-js");
|
||||
const parentDirectory = new URL("../cli/config/rc-js/", import.meta.url);
|
||||
|
||||
const config = {
|
||||
trailingComma: "all",
|
||||
@@ -277,7 +279,7 @@ test(".js config file", async () => {
|
||||
"mjs-prettier-config-js-in-type-module",
|
||||
"mjs-prettierrc-js-in-type-module",
|
||||
]) {
|
||||
const file = path.join(parentDirectory, directoryName, "foo.js");
|
||||
const file = new URL(`${directoryName}/foo.js`, parentDirectory);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject(config);
|
||||
}
|
||||
|
||||
@@ -286,7 +288,7 @@ test(".js config file", async () => {
|
||||
"cjs-prettier-config-js-in-type-module",
|
||||
"cjs-prettierrc-js-in-type-module",
|
||||
]) {
|
||||
const file = path.join(parentDirectory, directoryName, "foo.js");
|
||||
const file = new URL(`./${directoryName}/foo.js`, parentDirectory);
|
||||
await expect(prettier.resolveConfig(file)).rejects.toThrow(cjsError);
|
||||
}
|
||||
|
||||
@@ -297,13 +299,13 @@ test(".js config file", async () => {
|
||||
"mjs-prettierrc-js-in-type-commonjs",
|
||||
"mjs-prettierrc-js-in-type-none",
|
||||
]) {
|
||||
const file = path.join(parentDirectory, directoryName, "foo.js");
|
||||
const file = new URL(`./${directoryName}/foo.js`, parentDirectory);
|
||||
await expect(prettier.resolveConfig(file)).rejects.toThrow(mjsError);
|
||||
}
|
||||
});
|
||||
|
||||
test(".cjs config file", async () => {
|
||||
const parentDirectory = path.join(__dirname, "../cli/config/rc-cjs");
|
||||
const parentDirectory = new URL("../cli/config/rc-cjs/", import.meta.url);
|
||||
|
||||
const config = {
|
||||
trailingComma: "all",
|
||||
@@ -318,13 +320,13 @@ test(".cjs config file", async () => {
|
||||
"prettier-config-cjs-in-type-none",
|
||||
"prettier-config-cjs-in-type-module",
|
||||
]) {
|
||||
const file = path.join(parentDirectory, directoryName, "foo.js");
|
||||
const file = new URL(`./${directoryName}/foo.js`, parentDirectory);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject(config);
|
||||
}
|
||||
});
|
||||
|
||||
test(".mjs config file", async () => {
|
||||
const parentDirectory = path.join(__dirname, "../cli/config/rc-mjs");
|
||||
const parentDirectory = new URL("../cli/config/rc-mjs/", import.meta.url);
|
||||
|
||||
const config = {
|
||||
trailingComma: "all",
|
||||
@@ -339,37 +341,51 @@ test(".mjs config file", async () => {
|
||||
"prettier-config-mjs-in-type-none",
|
||||
"prettier-config-mjs-in-type-module",
|
||||
]) {
|
||||
const file = path.join(parentDirectory, directoryName, "foo.js");
|
||||
const file = new URL(`./${directoryName}/foo.js`, parentDirectory);
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject(config);
|
||||
}
|
||||
});
|
||||
|
||||
test(".json5 config file", async () => {
|
||||
const parentDirectory = path.join(__dirname, "../cli/config/rc-json5");
|
||||
const parentDirectory = new URL("../cli/config/rc-json5/", import.meta.url);
|
||||
const config = {
|
||||
trailingComma: "all",
|
||||
printWidth: 81,
|
||||
tabWidth: 3,
|
||||
};
|
||||
const file = path.join(parentDirectory, "json5/foo.js");
|
||||
const file = new URL("./json5/foo.js", parentDirectory);
|
||||
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 parentDirectory = new URL("../cli/config/rc-json5/", import.meta.url);
|
||||
const file = new URL("./invalid/foo.js", parentDirectory);
|
||||
const error = /JSON5: invalid end of input at 2:1/;
|
||||
await expect(prettier.resolveConfig(file)).rejects.toThrow(error);
|
||||
});
|
||||
|
||||
test("support external module with `module` only `exports`", async () => {
|
||||
const directory = path.join(
|
||||
__dirname,
|
||||
"../cli/config/external-config/esm-package-forbids-require",
|
||||
const file = new URL(
|
||||
"../cli/config/external-config/esm-package-forbids-require/index.js",
|
||||
import.meta.url,
|
||||
);
|
||||
const file = path.join(directory, "index.js");
|
||||
|
||||
await expect(prettier.resolveConfig(file)).resolves.toMatchObject({
|
||||
printWidth: 79,
|
||||
});
|
||||
});
|
||||
|
||||
test("API resolveConfig accepts path or URL", async () => {
|
||||
const fileUrl = new URL("../cli/config/js/file.js", import.meta.url);
|
||||
const expectedResult = { tabWidth: 8 };
|
||||
|
||||
const resultByUrl = await prettier.resolveConfig(fileUrl);
|
||||
const resultByUrlHref = await prettier.resolveConfig(fileUrl.href);
|
||||
const resultByPath = await prettier.resolveConfig(url.fileURLToPath(fileUrl));
|
||||
const resultByRelativePath = await prettier.resolveConfig(
|
||||
path.relative(process.cwd(), url.fileURLToPath(fileUrl)),
|
||||
);
|
||||
expect(resultByUrl).toMatchObject(expectedResult);
|
||||
expect(resultByUrlHref).toMatchObject(expectedResult);
|
||||
expect(resultByPath).toMatchObject(expectedResult);
|
||||
expect(resultByRelativePath).toMatchObject(expectedResult);
|
||||
});
|
||||
@@ -1,23 +1,23 @@
|
||||
import * as urlOrPath from "url-or-path";
|
||||
import url from "node:url";
|
||||
import prettier from "../../config/prettier-entry.js";
|
||||
|
||||
test("API resolveConfigFile", async () => {
|
||||
const result = await prettier.resolveConfigFile();
|
||||
expect(result).toEqual(
|
||||
urlOrPath.toPath(new URL("../../../.prettierrc", import.meta.url)),
|
||||
url.fileURLToPath(new URL("../../../.prettierrc", import.meta.url)),
|
||||
);
|
||||
});
|
||||
|
||||
test("API resolveConfigFile accepts path or URL", async () => {
|
||||
const fileUrl = new URL("../cli/config/filepath/foo.js", import.meta.url);
|
||||
const expectedConfigFilePath = urlOrPath.toPath(
|
||||
const expectedConfigFilePath = url.fileURLToPath(
|
||||
new URL("./.prettierrc", fileUrl),
|
||||
);
|
||||
|
||||
const resultByUrl = await prettier.resolveConfigFile(fileUrl);
|
||||
const resultByUrlHref = await prettier.resolveConfigFile(fileUrl.href);
|
||||
const resultByPath = await prettier.resolveConfigFile(
|
||||
urlOrPath.toPath(fileUrl),
|
||||
url.fileURLToPath(fileUrl),
|
||||
);
|
||||
expect(resultByUrl).toEqual(expectedConfigFilePath);
|
||||
expect(resultByUrlHref).toEqual(expectedConfigFilePath);
|
||||
|
||||
Reference in new issue
Block a user