From 6d71385ad8940434f75c0961e08430d50fd0fb81 Mon Sep 17 00:00:00 2001 From: pralkarz <31964869+pralkarz@users.noreply.github.com> Date: Sun, 9 Feb 2025 23:05:10 +0100 Subject: [PATCH 1/8] Ported test suite: patterns --- package-lock.json | 14 +-- package.json | 2 +- src/index.ts | 2 +- .../[...with-square-brackets-and-dots].js | 4 + .../square-brackets/[with-square-brackets].js | 4 + test/__fixtures__/patterns/directory/file.js | 1 + .../nested-directory/nested-directory-file.js | 1 + .../patterns/file.will-never-support | 0 .../patterns/node_modules/node-module.js | 1 + .../patterns/other-directory/file.js | 1 + .../nested-directory/nested-directory-file.js | 1 + .../patterns/other-regular-modules.js | 1 + test/__fixtures__/patterns/regular-module.js | 1 + .../error-on-unmatched-pattern.js.snap | 2 +- .../__snapshots__/ignore-unknown.js.snap | 4 +- test/__tests__/__snapshots__/patterns.js.snap | 82 ++++++++++++++ test/__tests__/patterns.js | 101 ++++++++++++++++++ 17 files changed, 210 insertions(+), 12 deletions(-) create mode 100644 test/__fixtures__/patterns-special-characters/dots/[...with-square-brackets-and-dots].js create mode 100644 test/__fixtures__/patterns-special-characters/square-brackets/[with-square-brackets].js create mode 100644 test/__fixtures__/patterns/directory/file.js create mode 100644 test/__fixtures__/patterns/directory/nested-directory/nested-directory-file.js create mode 100644 test/__fixtures__/patterns/file.will-never-support create mode 100644 test/__fixtures__/patterns/node_modules/node-module.js create mode 100644 test/__fixtures__/patterns/other-directory/file.js create mode 100644 test/__fixtures__/patterns/other-directory/nested-directory/nested-directory-file.js create mode 100644 test/__fixtures__/patterns/other-regular-modules.js create mode 100644 test/__fixtures__/patterns/regular-module.js create mode 100644 test/__tests__/__snapshots__/patterns.js.snap create mode 100644 test/__tests__/patterns.js diff --git a/package-lock.json b/package-lock.json index 1f883cb..69bd323 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,7 +26,7 @@ "specialist": "^1.4.5", "tiny-editorconfig": "^1.0.0", "tiny-jsonc": "^1.0.1", - "tiny-readdir-glob": "^1.22.24", + "tiny-readdir-glob": "^1.23.0", "tiny-spinner": "^2.0.4", "worktank": "^2.7.3", "zeptomatch": "^2.0.0", @@ -5779,9 +5779,9 @@ } }, "node_modules/tiny-readdir-glob": { - "version": "1.22.24", - "resolved": "https://registry.npmjs.org/tiny-readdir-glob/-/tiny-readdir-glob-1.22.24.tgz", - "integrity": "sha512-HPDNMin7GoyPMesJNkAeT0ERU51ZWFby2RXEE2MHeVeO4c0i07679cuEMKzhKNBlBrBKoVjOmaie5y+FnRwL8g==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/tiny-readdir-glob/-/tiny-readdir-glob-1.23.0.tgz", + "integrity": "sha512-ElwCbSNP9ElOsrxGHieDswd27w/72JyyrlMyFsP/hAA/xEZbt8euWTEunxQ6bapfiCtGW799Ip0I4HnQ+ZPd6g==", "dependencies": { "tiny-readdir": "^2.7.0", "zeptomatch": "^1.2.2", @@ -10580,9 +10580,9 @@ } }, "tiny-readdir-glob": { - "version": "1.22.24", - "resolved": "https://registry.npmjs.org/tiny-readdir-glob/-/tiny-readdir-glob-1.22.24.tgz", - "integrity": "sha512-HPDNMin7GoyPMesJNkAeT0ERU51ZWFby2RXEE2MHeVeO4c0i07679cuEMKzhKNBlBrBKoVjOmaie5y+FnRwL8g==", + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/tiny-readdir-glob/-/tiny-readdir-glob-1.23.0.tgz", + "integrity": "sha512-ElwCbSNP9ElOsrxGHieDswd27w/72JyyrlMyFsP/hAA/xEZbt8euWTEunxQ6bapfiCtGW799Ip0I4HnQ+ZPd6g==", "requires": { "tiny-readdir": "^2.7.0", "zeptomatch": "^1.2.2", diff --git a/package.json b/package.json index 3e8a507..e8992ab 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "specialist": "^1.4.5", "tiny-editorconfig": "^1.0.0", "tiny-jsonc": "^1.0.1", - "tiny-readdir-glob": "^1.22.24", + "tiny-readdir-glob": "^1.23.0", "tiny-spinner": "^2.0.4", "worktank": "^2.7.3", "zeptomatch": "^2.0.0", diff --git a/src/index.ts b/src/index.ts index 11cc15c..b3f8541 100644 --- a/src/index.ts +++ b/src/index.ts @@ -200,7 +200,7 @@ async function runGlobs(options: Options, pluginsDefaultOptions: PluginsOptions, if (!totalMatched && !totalIgnored) { if (options.errorOnUnmatchedPattern) { - stderr.prefixed.error(`No files matching the given patterns were found`); + stderr.prefixed.error(`No files matching the given patterns were found.`); } } diff --git a/test/__fixtures__/patterns-special-characters/dots/[...with-square-brackets-and-dots].js b/test/__fixtures__/patterns-special-characters/dots/[...with-square-brackets-and-dots].js new file mode 100644 index 0000000..ad47336 --- /dev/null +++ b/test/__fixtures__/patterns-special-characters/dots/[...with-square-brackets-and-dots].js @@ -0,0 +1,4 @@ +foo( + + +) diff --git a/test/__fixtures__/patterns-special-characters/square-brackets/[with-square-brackets].js b/test/__fixtures__/patterns-special-characters/square-brackets/[with-square-brackets].js new file mode 100644 index 0000000..ad47336 --- /dev/null +++ b/test/__fixtures__/patterns-special-characters/square-brackets/[with-square-brackets].js @@ -0,0 +1,4 @@ +foo( + + +) diff --git a/test/__fixtures__/patterns/directory/file.js b/test/__fixtures__/patterns/directory/file.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/directory/file.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__fixtures__/patterns/directory/nested-directory/nested-directory-file.js b/test/__fixtures__/patterns/directory/nested-directory/nested-directory-file.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/directory/nested-directory/nested-directory-file.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__fixtures__/patterns/file.will-never-support b/test/__fixtures__/patterns/file.will-never-support new file mode 100644 index 0000000..e69de29 diff --git a/test/__fixtures__/patterns/node_modules/node-module.js b/test/__fixtures__/patterns/node_modules/node-module.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/node_modules/node-module.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__fixtures__/patterns/other-directory/file.js b/test/__fixtures__/patterns/other-directory/file.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/other-directory/file.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__fixtures__/patterns/other-directory/nested-directory/nested-directory-file.js b/test/__fixtures__/patterns/other-directory/nested-directory/nested-directory-file.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/other-directory/nested-directory/nested-directory-file.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__fixtures__/patterns/other-regular-modules.js b/test/__fixtures__/patterns/other-regular-modules.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/other-regular-modules.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__fixtures__/patterns/regular-module.js b/test/__fixtures__/patterns/regular-module.js new file mode 100644 index 0000000..ad9a93a --- /dev/null +++ b/test/__fixtures__/patterns/regular-module.js @@ -0,0 +1 @@ +'use strict'; diff --git a/test/__tests__/__snapshots__/error-on-unmatched-pattern.js.snap b/test/__tests__/__snapshots__/error-on-unmatched-pattern.js.snap index ab48a0c..327d815 100644 --- a/test/__tests__/__snapshots__/error-on-unmatched-pattern.js.snap +++ b/test/__tests__/__snapshots__/error-on-unmatched-pattern.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`error on unmatched pattern (stderr) 1`] = `"[error] No files matching the given patterns were found"`; +exports[`error on unmatched pattern (stderr) 1`] = `"[error] No files matching the given patterns were found."`; exports[`error on unmatched pattern (stdout) 1`] = `""`; diff --git a/test/__tests__/__snapshots__/ignore-unknown.js.snap b/test/__tests__/__snapshots__/ignore-unknown.js.snap index 02de4fb..247fef9 100644 --- a/test/__tests__/__snapshots__/ignore-unknown.js.snap +++ b/test/__tests__/__snapshots__/ignore-unknown.js.snap @@ -6,13 +6,13 @@ exports[`Ignored file (stdout) 1`] = `""`; exports[`Ignored file (write) 1`] = `[]`; -exports[`None exist file (stderr) 1`] = `"[error] No files matching the given patterns were found"`; +exports[`None exist file (stderr) 1`] = `"[error] No files matching the given patterns were found."`; exports[`None exist file (stdout) 1`] = `""`; exports[`None exist file (write) 1`] = `[]`; -exports[`Not matching pattern (stderr) 1`] = `"[error] No files matching the given patterns were found"`; +exports[`Not matching pattern (stderr) 1`] = `"[error] No files matching the given patterns were found."`; exports[`Not matching pattern (stdout) 1`] = `""`; diff --git a/test/__tests__/__snapshots__/patterns.js.snap b/test/__tests__/__snapshots__/patterns.js.snap new file mode 100644 index 0000000..d2bc8ff --- /dev/null +++ b/test/__tests__/__snapshots__/patterns.js.snap @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`exits with an informative message when there are no patterns provided (stderr) 1`] = ` +" + Expected at least one target file/dir/glob +" +`; + +exports[`exits with an informative message when there are no patterns provided (stdout) 1`] = `""`; + +exports[`exits with an informative message when there are no patterns provided (write) 1`] = `[]`; + +exports[`multiple patterns (stderr) 1`] = `""`; + +exports[`multiple patterns (stdout) 1`] = ` +"directory/file.js +directory/nested-directory/nested-directory-file.js +other-directory/file.js +other-directory/nested-directory/nested-directory-file.js" +`; + +exports[`multiple patterns (write) 1`] = `[]`; + +exports[`multiple patterns with a negated pattern (stderr) 1`] = `""`; + +exports[`multiple patterns with a negated pattern (stdout) 1`] = ` +"directory/file.js +other-directory/file.js +other-regular-modules.js +regular-module.js" +`; + +exports[`multiple patterns with a negated pattern (write) 1`] = `[]`; + +exports[`multiple patterns with a negated pattern and leading \`./\`, ignores node_modules by default (stderr) 1`] = `""`; + +exports[`multiple patterns with a negated pattern and leading \`./\`, ignores node_modules by default (stdout) 1`] = ` +"other-directory/file.js +other-directory/nested-directory/nested-directory-file.js +other-regular-modules.js +regular-module.js" +`; + +exports[`multiple patterns with a negated pattern and leading \`./\`, ignores node_modules by default (write) 1`] = `[]`; + +exports[`multiple patterns with a negated pattern, doesn't ignore node_modules with the --with-node-modules flag (stderr) 1`] = `""`; + +exports[`multiple patterns with a negated pattern, doesn't ignore node_modules with the --with-node-modules flag (stdout) 1`] = ` +"node_modules/node-module.js +other-directory/file.js +other-directory/nested-directory/nested-directory-file.js +other-regular-modules.js +regular-module.js" +`; + +exports[`multiple patterns with a negated pattern, doesn't ignore node_modules with the --with-node-modules flag (write) 1`] = `[]`; + +exports[`multiple patterns with a negated pattern, ignores node_modules by default (stderr) 1`] = `""`; + +exports[`multiple patterns with a negated pattern, ignores node_modules by default (stdout) 1`] = ` +"other-directory/file.js +other-directory/nested-directory/nested-directory-file.js +other-regular-modules.js +regular-module.js" +`; + +exports[`multiple patterns with a negated pattern, ignores node_modules by default (write) 1`] = `[]`; + +exports[`multiple patterns with an extra non-existent pattern (stderr) 1`] = `""`; + +exports[`multiple patterns with an extra non-existent pattern (stdout) 1`] = ` +"directory/file.js +directory/nested-directory/nested-directory-file.js" +`; + +exports[`multiple patterns with an extra non-existent pattern (write) 1`] = `[]`; + +exports[`multiple patterns, throws an error and exits with a non-zero code when there are no matches (stderr) 1`] = `"[error] No files matching the given patterns were found."`; + +exports[`multiple patterns, throws an error and exits with a non-zero code when there are no matches (stdout) 1`] = `""`; + +exports[`multiple patterns, throws an error and exits with a non-zero code when there are no matches (write) 1`] = `[]`; diff --git a/test/__tests__/patterns.js b/test/__tests__/patterns.js new file mode 100644 index 0000000..db1243e --- /dev/null +++ b/test/__tests__/patterns.js @@ -0,0 +1,101 @@ +import { runCli } from "../utils"; + +describe("multiple patterns", () => { + runCli("patterns", [ + "directory/**/*.js", + "other-directory/**/*.js", + "-l", + ]).test({ + status: 1, + }); +}); + +describe("multiple patterns with an extra non-existent pattern", () => { + runCli("patterns", [ + "directory/**/*.js", + "non-existent.js", + "-l", + ]).test({ + status: 1, + }); +}); + +describe("multiple patterns with a negated pattern", () => { + runCli("patterns", [ + "**/*.js", + "!**/nested-directory/**", + "-l", + ]).test({ + status: 1, + }); +}); + +describe("multiple patterns with a negated pattern, ignores node_modules by default", () => { + runCli("patterns", [ + "**/*.js", + "!directory/**", + "-l", + ]).test({ + status: 1, + }); +}); + +// TODO: Handle leading `./` and `../` in patterns. +describe.skip("multiple patterns with a negated pattern and leading `./`, ignores node_modules by default", () => { + runCli("patterns", [ + "./**/*.js", + "!./directory/**", + "-l", + ]).test({ + status: 1, + }); +}); + +describe("multiple patterns with a negated pattern, doesn't ignore node_modules with the --with-node-modules flag", () => { + runCli("patterns", [ + "**/*.js", + "!directory/**", + "-l", + "--with-node-modules", + ]).test({ + status: 1, + }); +}); + +describe("exits with an informative message when there are no patterns provided", () => { + runCli("patterns").test({ + status: 1, + }); +}); + +describe("multiple patterns, throws an error and exits with a non-zero code when there are no matches", () => { + runCli("patterns", [ + "non-existent.js", + "other-non-existent.js", + "-l", + ]).test({ + status: 1, + }); +}); + +describe("file names with special characters", () => { + runCli("patterns-special-characters/square-brackets", [ + "[with-square-brackets].js", + "-l", + ]).test({ + status: 1, + write: [], + stderr: "", + stdout: "[with-square-brackets].js", + }); + + runCli("patterns-special-characters/dots", [ + "[...with-square-brackets-and-dots].js", + "-l", + ]).test({ + status: 1, + write: [], + stderr: "", + stdout: "[...with-square-brackets-and-dots].js", + }); +}); From 585f1be4de383177350106b52125c459d180903b Mon Sep 17 00:00:00 2001 From: James Garbutt <43081j@users.noreply.github.com> Date: Tue, 4 Mar 2025 14:44:17 +0100 Subject: [PATCH 2/8] test: migrate stdin-filepath tests Copies the stdin-filepath tests from prettier. Notable differences: - Blocked by #21 - Syntax errors output the `stdin-filepath` basename in prettier but not in this CLI (e.g. `[Error] foo.js SyntaxError blah`) --- package-lock.json | 2 + package.json | 1 + src/index.ts | 2 +- src/utils.ts | 4 +- test/__fixtures__/editorconfig/.editorconfig | 18 +++ test/__fixtures__/editorconfig/file.js | 3 + test/__fixtures__/editorconfig/lib/file.js | 3 + .../editorconfig/lib/indent_size=tab.js | 3 + .../editorconfig/repo-root/.hg/.gitkeep | 2 + .../editorconfig/repo-root/file.js | 3 + .../__fixtures__/stdin-ignore/.prettierignore | 1 + .../__snapshots__/stdin-filepath.js.snap | 85 ++++++++++ test/__tests__/stdin-filepath.js | 147 ++++++++++++++++++ 13 files changed, 272 insertions(+), 2 deletions(-) create mode 100644 test/__fixtures__/editorconfig/.editorconfig create mode 100644 test/__fixtures__/editorconfig/file.js create mode 100644 test/__fixtures__/editorconfig/lib/file.js create mode 100644 test/__fixtures__/editorconfig/lib/indent_size=tab.js create mode 100644 test/__fixtures__/editorconfig/repo-root/.hg/.gitkeep create mode 100644 test/__fixtures__/editorconfig/repo-root/file.js create mode 100644 test/__fixtures__/stdin-ignore/.prettierignore create mode 100644 test/__tests__/__snapshots__/stdin-filepath.js.snap create mode 100644 test/__tests__/stdin-filepath.js diff --git a/package-lock.json b/package-lock.json index 2d208cd..01d3691 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,7 @@ "@types/js-yaml": "^4.0.9", "@types/node": "^20.12.7", "cross-env": "^7.0.3", + "dedent": "^1.5.3", "jest": "^29.7.0", "jest-snapshot-serializer-ansi": "^2.1.0", "jest-snapshot-serializer-raw": "^2.0.0", @@ -2308,6 +2309,7 @@ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", "dev": true, + "license": "MIT", "peerDependencies": { "babel-plugin-macros": "^3.1.0" }, diff --git a/package.json b/package.json index 48e4502..6caebff 100644 --- a/package.json +++ b/package.json @@ -65,6 +65,7 @@ "@types/js-yaml": "^4.0.9", "@types/node": "^20.12.7", "cross-env": "^7.0.3", + "dedent": "^1.5.3", "jest": "^29.7.0", "jest-snapshot-serializer-ansi": "^2.1.0", "jest-snapshot-serializer-raw": "^2.0.0", diff --git a/src/index.ts b/src/index.ts index 8bc33e0..d2fb1bf 100644 --- a/src/index.ts +++ b/src/index.ts @@ -16,7 +16,7 @@ import { fastRelativePath, isNull, isString, isUndefined, negate, pluralize, tri import type { FormatOptions, Options, PluginsOptions } from "./types.js"; async function run(options: Options, pluginsDefaultOptions: PluginsOptions, pluginsCustomOptions: PluginsOptions): Promise { - if (options.globs.length || !isString(await getStdin())) { + if (options.globs.length || (!isString(await getStdin()) && !("stdinFilepath" in options))) { return runGlobs(options, pluginsDefaultOptions, pluginsCustomOptions); } else { return runStdin(options, pluginsDefaultOptions, pluginsCustomOptions); diff --git a/src/utils.ts b/src/utils.ts index 88d05b2..a713db3 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -330,7 +330,9 @@ async function normalizeOptions(options: unknown, targets: unknown[]): Promise 1 | .name { display: none; } +[error] | ^" +`; + +exports[`throw error if stdin content incompatible with stdin-filepath (stdout) 1`] = `""`; + +exports[`throw error if stdin content incompatible with stdin-filepath (write) 1`] = `[]`; diff --git a/test/__tests__/stdin-filepath.js b/test/__tests__/stdin-filepath.js new file mode 100644 index 0000000..e161b3c --- /dev/null +++ b/test/__tests__/stdin-filepath.js @@ -0,0 +1,147 @@ +import { runCli } from "../utils"; +import dedent from "dedent"; + +describe("format correctly if stdin content compatible with stdin-filepath", () => { + runCli( + "", + ["--stdin-filepath", "abc.css"], + { input: ".name { display: none; }" }, // css + ).test({ + status: 0, + }); +}); + +describe("throw error if stdin content incompatible with stdin-filepath", () => { + runCli( + "", + ["--stdin-filepath", "abc.js"], + { input: ".name { display: none; }" }, // css + ).test({ + status: "non-zero", + }); +}); + +describe("gracefully handle stdin-filepath with nonexistent directory", () => { + runCli( + "", + ["--stdin-filepath", "definitely/nonexistent/path.css"], + { input: ".name { display: none; }" }, // css + ).test({ + status: 0, + }); +}); + +describe("apply editorconfig for stdin-filepath with nonexistent file", () => { + runCli("", ["--stdin-filepath", "editorconfig/nonexistent.js"], { + input: dedent` + function f() { + console.log("should be indented with a tab"); + } + `, // js + }).test({ + status: 0, + }); +}); + +describe("apply editorconfig for stdin-filepath with nonexistent directory", () => { + runCli( + "", + ["--stdin-filepath", "editorconfig/nonexistent/one/two/three.js"], + { + input: dedent` + function f() { + console.log("should be indented with a tab"); + } + `, // js + }, + ).test({ + status: 0, + }); +}); + +describe("apply editorconfig for stdin-filepath with a deep path", () => { + runCli( + "", + ["--stdin-filepath", "editorconfig/" + "a/".repeat(30) + "three.js"], + { + input: dedent` + function f() { + console.log("should be indented with a tab"); + } + `, // js + }, + ).test({ + status: 0, + }); +}); + +describe("apply editorconfig for stdin-filepath in root", () => { + const code = dedent` + function f() { + console.log("should be indented with a tab"); + } + `; + runCli("", ["--stdin-filepath", "/foo.js"], { + input: code, // js + }).test({ + status: 0, + stdout: code, + stderr: "", + write: [], + }); +}); + +describe("apply editorconfig for stdin-filepath with a deep path", () => { + runCli( + "", + ["--stdin-filepath", "editorconfig/" + "a/".repeat(30) + "three.js"], + { + input: dedent` + function f() { + console.log("should be indented with a tab"); + } + `, // js + }, + ).test({ + status: 0, + }); +}); + +describe("don’t apply editorconfig outside project for stdin-filepath with nonexistent directory", () => { + runCli( + "", + [ + "--stdin-filepath", + "editorconfig/repo-root/nonexistent/one/two/three.js", + ], + { + input: dedent` + function f() { + console.log("should be indented with 2 spaces"); + } + `, // js + }, + ).test({ + status: 0, + }); +}); + +describe("output file as-is if stdin-filepath matched patterns in ignore-path", () => { + runCli("stdin-ignore", ["--stdin-filepath", "ignore/example.js"], { + input: "hello_world( );", + }).test({ + stdout: "hello_world( );", + status: 0, + }); +}); + +describe("Should format stdin even if it's empty", () => { + runCli("", ["--stdin-filepath", "example.js"], { + isTTY: true, + }).test({ + stdout: "", + status: 0, + stderr: "", + write: [], + }); +}); From 086c44cd505c06098aeec84e962044a6957c27cd Mon Sep 17 00:00:00 2001 From: pralkarz Date: Wed, 23 Apr 2025 00:16:49 +0200 Subject: [PATCH 3/8] test: add the progress so far --- src/config_editorconfig.ts | 2 +- src/index.ts | 6 +++++- src/known.ts | 2 +- .../__snapshots__/stdin-filepath.js.snap | 8 ++++---- test/__tests__/stdin-filepath.js | 20 +++++++++++-------- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/config_editorconfig.ts b/src/config_editorconfig.ts index aee3ccb..db15d0d 100644 --- a/src/config_editorconfig.ts +++ b/src/config_editorconfig.ts @@ -10,7 +10,7 @@ const getEditorConfig = memoize((folderPath: string, filesNames: string[]): Prom for (let i = 0, l = filesNames.length; i < l; i++) { const fileName = filesNames[i]; const filePath = fastJoinedPath(folderPath, fileName); - if (!Known.hasFilePath(filePath)) continue; + // if (!Known.hasFilePath(filePath)) continue; return fs.readFile(filePath, "utf8").then(EditorConfig.parse).catch(noop); } }); diff --git a/src/index.ts b/src/index.ts index d2fb1bf..4383655 100644 --- a/src/index.ts +++ b/src/index.ts @@ -32,7 +32,11 @@ async function runStdin(options: Options, pluginsDefaultOptions: PluginsOptions, const fileContent = (await getStdin()) || ""; try { - const formatted = await prettier.format(fileName, fileContent, options.formatOptions, options.contextOptions, pluginsDefaultOptions, pluginsCustomOptions); + const editorConfigNames = options.editorConfig ? [".editorconfig"] : []; + const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(fileName, editorConfigNames)) : {}; + const formatOptions = { ...editorConfig, ...options.formatOptions }; + + const formatted = await prettier.format(fileName, fileContent, formatOptions, options.contextOptions, pluginsDefaultOptions, pluginsCustomOptions); if (options.check || options.list) { if (formatted !== fileContent) { stdout.warn("(stdin)"); diff --git a/src/known.ts b/src/known.ts index f285557..7b5bca0 100644 --- a/src/known.ts +++ b/src/known.ts @@ -2,7 +2,7 @@ class Known { private filesPaths: Set = new Set(); - private filesNames: Set = new Set(); + filesNames: Set = new Set(); addFilesPaths = (filesPaths: Array | Set): void => { if (!this.filesPaths.size) { diff --git a/test/__tests__/__snapshots__/stdin-filepath.js.snap b/test/__tests__/__snapshots__/stdin-filepath.js.snap index edf3697..3b87617 100644 --- a/test/__tests__/__snapshots__/stdin-filepath.js.snap +++ b/test/__tests__/__snapshots__/stdin-filepath.js.snap @@ -40,15 +40,15 @@ exports[`apply editorconfig for stdin-filepath with nonexistent file (stdout) 1` exports[`apply editorconfig for stdin-filepath with nonexistent file (write) 1`] = `[]`; -exports[`don’t apply editorconfig outside project for stdin-filepath with nonexistent directory (stderr) 1`] = `""`; +exports[`don't apply editorconfig outside project for stdin-filepath with nonexistent directory (stderr) 1`] = `""`; -exports[`don’t apply editorconfig outside project for stdin-filepath with nonexistent directory (stdout) 1`] = ` +exports[`don't apply editorconfig outside project for stdin-filepath with nonexistent directory (stdout) 1`] = ` "function f() { - console.log("should be indented with 2 spaces") + console.log("should be indented with 2 spaces"); }" `; -exports[`don’t apply editorconfig outside project for stdin-filepath with nonexistent directory (write) 1`] = `[]`; +exports[`don't apply editorconfig outside project for stdin-filepath with nonexistent directory (write) 1`] = `[]`; exports[`format correctly if stdin content compatible with stdin-filepath (stderr) 1`] = `""`; diff --git a/test/__tests__/stdin-filepath.js b/test/__tests__/stdin-filepath.js index e161b3c..98b486d 100644 --- a/test/__tests__/stdin-filepath.js +++ b/test/__tests__/stdin-filepath.js @@ -32,7 +32,7 @@ describe("gracefully handle stdin-filepath with nonexistent directory", () => { }); describe("apply editorconfig for stdin-filepath with nonexistent file", () => { - runCli("", ["--stdin-filepath", "editorconfig/nonexistent.js"], { + runCli("editorconfig", ["--stdin-filepath", "nonexistent.js"], { input: dedent` function f() { console.log("should be indented with a tab"); @@ -45,8 +45,8 @@ describe("apply editorconfig for stdin-filepath with nonexistent file", () => { describe("apply editorconfig for stdin-filepath with nonexistent directory", () => { runCli( - "", - ["--stdin-filepath", "editorconfig/nonexistent/one/two/three.js"], + "editorconfig", + ["--stdin-filepath", "nonexistent/one/two/three.js"], { input: dedent` function f() { @@ -61,8 +61,8 @@ describe("apply editorconfig for stdin-filepath with nonexistent directory", () describe("apply editorconfig for stdin-filepath with a deep path", () => { runCli( - "", - ["--stdin-filepath", "editorconfig/" + "a/".repeat(30) + "three.js"], + "editorconfig", + ["--stdin-filepath", "a/".repeat(30) + "three.js"], { input: dedent` function f() { @@ -75,6 +75,8 @@ describe("apply editorconfig for stdin-filepath with a deep path", () => { }); }); +// TODO: This is currently a false positive as no config actually gets resolved, but Prettier +// somehow formats the input correctly anyway. describe("apply editorconfig for stdin-filepath in root", () => { const code = dedent` function f() { @@ -93,8 +95,8 @@ describe("apply editorconfig for stdin-filepath in root", () => { describe("apply editorconfig for stdin-filepath with a deep path", () => { runCli( - "", - ["--stdin-filepath", "editorconfig/" + "a/".repeat(30) + "three.js"], + "editorconfig", + ["--stdin-filepath", "a/".repeat(30) + "three.js"], { input: dedent` function f() { @@ -107,7 +109,9 @@ describe("apply editorconfig for stdin-filepath with a deep path", () => { }); }); -describe("don’t apply editorconfig outside project for stdin-filepath with nonexistent directory", () => { +// TODO: This is currently a false positive. Gotta investigate how it's handled in Prettier v3 to +// gauge the expected behavior. +describe("don't apply editorconfig outside project for stdin-filepath with nonexistent directory", () => { runCli( "", [ From f1c2dc1e2022e47d68a53c8f85447db88b7c20ae Mon Sep 17 00:00:00 2001 From: pralkarz Date: Wed, 23 Apr 2025 00:20:21 +0200 Subject: [PATCH 4/8] chore: restore the `private` modifier --- src/known.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/known.ts b/src/known.ts index 7b5bca0..f285557 100644 --- a/src/known.ts +++ b/src/known.ts @@ -2,7 +2,7 @@ class Known { private filesPaths: Set = new Set(); - filesNames: Set = new Set(); + private filesNames: Set = new Set(); addFilesPaths = (filesPaths: Array | Set): void => { if (!this.filesPaths.size) { From fd0e3b03641c0979502434b24369bf7ba54351b8 Mon Sep 17 00:00:00 2001 From: pralkarz Date: Wed, 23 Apr 2025 09:31:10 +0200 Subject: [PATCH 5/8] test: resolve Prettier configs --- src/config_editorconfig.ts | 14 +++++------ src/config_prettier.ts | 28 ++++++++++++---------- src/index.ts | 8 +++++-- src/utils.ts | 4 ++++ test/__fixtures__/editorconfig/.prettierrc | 8 +++++++ test/__tests__/stdin-filepath.js | 2 +- 6 files changed, 41 insertions(+), 23 deletions(-) create mode 100644 test/__fixtures__/editorconfig/.prettierrc diff --git a/src/config_editorconfig.ts b/src/config_editorconfig.ts index db15d0d..441b9fd 100644 --- a/src/config_editorconfig.ts +++ b/src/config_editorconfig.ts @@ -6,11 +6,11 @@ import { fastJoinedPath, findLastIndex, isUndefined, memoize, noop, zipObjectUnl import type { Config, ConfigWithOverrides } from "tiny-editorconfig"; import type { FormatOptions, PromiseMaybe } from "./types.js"; -const getEditorConfig = memoize((folderPath: string, filesNames: string[]): PromiseMaybe => { +const getEditorConfig = memoize((folderPath: string, filesNames: string[], ignoreKnown = false): PromiseMaybe => { for (let i = 0, l = filesNames.length; i < l; i++) { const fileName = filesNames[i]; const filePath = fastJoinedPath(folderPath, fileName); - // if (!Known.hasFilePath(filePath)) continue; + if (!ignoreKnown && !Known.hasFilePath(filePath)) continue; return fs.readFile(filePath, "utf8").then(EditorConfig.parse).catch(noop); } }); @@ -21,18 +21,18 @@ const getEditorConfigsMap = async (foldersPaths: string[], filesNames: string[]) return map; }; -const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string[]): Promise => { - const config = await getEditorConfig(folderPath, filesNames); +const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown = false): Promise => { + const config = await getEditorConfig(folderPath, filesNames, ignoreKnown); const folderPathUp = path.dirname(folderPath); - const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp, filesNames) : []; + const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp, filesNames, ignoreKnown) : []; const configs = config ? [...configsUp, config] : configsUp; const lastRootIndex = findLastIndex(configs, (config) => config.root); return lastRootIndex > 0 ? configs.slice(lastRootIndex) : configs; }); -const getEditorConfigResolved = async (filePath: string, filesNames: string[]): Promise => { +const getEditorConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown = false): Promise => { const folderPath = path.dirname(filePath); - const configs = await getEditorConfigsUp(folderPath, filesNames); + const configs = await getEditorConfigsUp(folderPath, filesNames, ignoreKnown); const config = EditorConfig.resolve(configs, filePath); return config; }; diff --git a/src/config_prettier.ts b/src/config_prettier.ts index 31aeaaf..48d555f 100644 --- a/src/config_prettier.ts +++ b/src/config_prettier.ts @@ -94,20 +94,22 @@ const Ext2Loader: Record Promise> = { mjs: Loaders.js, }; -const getPrettierConfig = (folderPath: string, fileName: string): PromiseMaybe => { +const getPrettierConfig = (folderPath: string, fileName: string, ignoreKnown = false): PromiseMaybe => { const filePath = fastJoinedPath(folderPath, fileName); - if (!Known.hasFilePath(filePath)) return; + if (!ignoreKnown && !Known.hasFilePath(filePath)) return; const loader = File2Loader[fileName] || File2Loader["default"]; const normalize = (config: unknown) => (isObject(config) ? { ...config, ...normalizePrettierOptions(config, folderPath) } : undefined); return loader(filePath).then(normalize).catch(noop); }; -const getPrettierConfigs = memoize(async (folderPath: string, filesNames: string[]): Promise => { - const configsRaw = await Promise.all(filesNames.map((fileName) => getPrettierConfig(folderPath, fileName))); - const configs = configsRaw.filter(isTruthy); - if (!configs.length) return; - return configs; -}); +const getPrettierConfigs = memoize( + async (folderPath: string, filesNames: string[], ignoreKnown: boolean = false): Promise => { + const configsRaw = await Promise.all(filesNames.map((fileName) => getPrettierConfig(folderPath, fileName, ignoreKnown))); + const configs = configsRaw.filter(isTruthy); + if (!configs.length) return; + return configs; + }, +); const getPrettierConfigsMap = async (foldersPaths: string[], filesNames: string[]): Promise>> => { const configs = await Promise.all(foldersPaths.map((folderPath) => getPrettierConfigs(folderPath, filesNames))); @@ -115,17 +117,17 @@ const getPrettierConfigsMap = async (foldersPaths: string[], filesNames: string[ return map; }; -const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: string[]): Promise => { - const config = (await getPrettierConfigs(folderPath, filesNames))?.[0]; +const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown: boolean = false): Promise => { + const config = (await getPrettierConfigs(folderPath, filesNames, ignoreKnown))?.[0]; const folderPathUp = path.dirname(folderPath); - const configsUp = folderPath !== folderPathUp ? await getPrettierConfigsUp(folderPathUp, filesNames) : []; + const configsUp = folderPath !== folderPathUp ? await getPrettierConfigsUp(folderPathUp, filesNames, ignoreKnown) : []; const configs = config ? [...configsUp, config] : configsUp; return configs; }); -const getPrettierConfigResolved = async (filePath: string, filesNames: string[]): Promise => { +const getPrettierConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown = false): Promise => { const folderPath = path.dirname(filePath); - const configs = await getPrettierConfigsUp(folderPath, filesNames); + const configs = await getPrettierConfigsUp(folderPath, filesNames, ignoreKnown); let resolved: PrettierConfig = {}; for (let ci = 0, cl = configs.length; ci < cl; ci++) { diff --git a/src/index.ts b/src/index.ts index 4383655..c466a4a 100644 --- a/src/index.ts +++ b/src/index.ts @@ -33,8 +33,12 @@ async function runStdin(options: Options, pluginsDefaultOptions: PluginsOptions, try { const editorConfigNames = options.editorConfig ? [".editorconfig"] : []; - const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(fileName, editorConfigNames)) : {}; - const formatOptions = { ...editorConfig, ...options.formatOptions }; + const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(fileName, editorConfigNames, true)) : {}; + + const prettierConfigNames = options.config ? without(Object.keys(File2Loader), ["default"]) : []; + const prettierConfig = options.config ? await getPrettierConfigResolved(fileName, prettierConfigNames, true) : {}; + + const formatOptions = { ...editorConfig, ...prettierConfig, ...options.formatOptions }; const formatted = await prettier.format(fileName, fileContent, formatOptions, options.contextOptions, pluginsDefaultOptions, pluginsCustomOptions); if (options.check || options.list) { diff --git a/src/utils.ts b/src/utils.ts index 74e9e82..c2674f0 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -41,6 +41,10 @@ function fastRelativeChildPath(fromPath: string, toPath: string): string | undef return toPath.slice(fromPath.length + 1); } } + + if (fromPath === ".") { + return toPath; + } } function findLastIndex(array: T[], predicate: (value: T, index: number, array: T[]) => unknown): number { diff --git a/test/__fixtures__/editorconfig/.prettierrc b/test/__fixtures__/editorconfig/.prettierrc new file mode 100644 index 0000000..963886d --- /dev/null +++ b/test/__fixtures__/editorconfig/.prettierrc @@ -0,0 +1,8 @@ +endOfLine: 'auto' +overrides: +- files: "**/*.js" + options: + semi: false +- files: "**/*.ts" + options: + semi: true diff --git a/test/__tests__/stdin-filepath.js b/test/__tests__/stdin-filepath.js index 98b486d..f09f92a 100644 --- a/test/__tests__/stdin-filepath.js +++ b/test/__tests__/stdin-filepath.js @@ -93,7 +93,7 @@ describe("apply editorconfig for stdin-filepath in root", () => { }); }); -describe("apply editorconfig for stdin-filepath with a deep path", () => { +describe.only("apply editorconfig for stdin-filepath with a deep path", () => { runCli( "editorconfig", ["--stdin-filepath", "a/".repeat(30) + "three.js"], From d5324f4b78a7445d68137cee3070418805ec912b Mon Sep 17 00:00:00 2001 From: pralkarz Date: Wed, 23 Apr 2025 09:31:34 +0200 Subject: [PATCH 6/8] test: remove leftover `.only` --- test/__tests__/stdin-filepath.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/__tests__/stdin-filepath.js b/test/__tests__/stdin-filepath.js index f09f92a..98b486d 100644 --- a/test/__tests__/stdin-filepath.js +++ b/test/__tests__/stdin-filepath.js @@ -93,7 +93,7 @@ describe("apply editorconfig for stdin-filepath in root", () => { }); }); -describe.only("apply editorconfig for stdin-filepath with a deep path", () => { +describe("apply editorconfig for stdin-filepath with a deep path", () => { runCli( "editorconfig", ["--stdin-filepath", "a/".repeat(30) + "three.js"], From ce18801f70754348e5cb94d3f006b1caa404badf Mon Sep 17 00:00:00 2001 From: pralkarz Date: Wed, 23 Apr 2025 10:03:20 +0200 Subject: [PATCH 7/8] test: resolve ignore files --- src/config_editorconfig.ts | 6 +++--- src/config_ignore.ts | 22 +++++++++++----------- src/config_prettier.ts | 4 ++-- src/index.ts | 20 ++++++++++++++------ 4 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/config_editorconfig.ts b/src/config_editorconfig.ts index 441b9fd..c5a9114 100644 --- a/src/config_editorconfig.ts +++ b/src/config_editorconfig.ts @@ -6,7 +6,7 @@ import { fastJoinedPath, findLastIndex, isUndefined, memoize, noop, zipObjectUnl import type { Config, ConfigWithOverrides } from "tiny-editorconfig"; import type { FormatOptions, PromiseMaybe } from "./types.js"; -const getEditorConfig = memoize((folderPath: string, filesNames: string[], ignoreKnown = false): PromiseMaybe => { +const getEditorConfig = memoize((folderPath: string, filesNames: string[], ignoreKnown?: boolean): PromiseMaybe => { for (let i = 0, l = filesNames.length; i < l; i++) { const fileName = filesNames[i]; const filePath = fastJoinedPath(folderPath, fileName); @@ -21,7 +21,7 @@ const getEditorConfigsMap = async (foldersPaths: string[], filesNames: string[]) return map; }; -const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown = false): Promise => { +const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { const config = await getEditorConfig(folderPath, filesNames, ignoreKnown); const folderPathUp = path.dirname(folderPath); const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp, filesNames, ignoreKnown) : []; @@ -30,7 +30,7 @@ const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string return lastRootIndex > 0 ? configs.slice(lastRootIndex) : configs; }); -const getEditorConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown = false): Promise => { +const getEditorConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { const folderPath = path.dirname(filePath); const configs = await getEditorConfigsUp(folderPath, filesNames, ignoreKnown); const config = EditorConfig.resolve(configs, filePath); diff --git a/src/config_ignore.ts b/src/config_ignore.ts index 75015af..c3a6af6 100644 --- a/src/config_ignore.ts +++ b/src/config_ignore.ts @@ -5,14 +5,14 @@ import Known from "./known.js"; import { fastJoinedPath, fastRelativeChildPath, isString, isUndefined, memoize, noop, someOf, zipObjectUnless } from "./utils.js"; import type { Ignore, PromiseMaybe } from "./types.js"; -const getIgnoreContent = (folderPath: string, fileName: string): PromiseMaybe => { +const getIgnoreContent = (folderPath: string, fileName: string, ignoreKnown?: boolean): PromiseMaybe => { const filePath = fastJoinedPath(folderPath, fileName); - if (!Known.hasFilePath(filePath)) return; + if (!ignoreKnown && !Known.hasFilePath(filePath)) return; return fs.readFile(filePath, "utf8").catch(noop); }; -const getIgnoresContent = memoize(async (folderPath: string, filesNames: string[]): Promise => { - const contentsRaw = await Promise.all(filesNames.map((fileName) => getIgnoreContent(folderPath, fileName))); +const getIgnoresContent = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { + const contentsRaw = await Promise.all(filesNames.map((fileName) => getIgnoreContent(folderPath, fileName, ignoreKnown))); const contents = contentsRaw.filter(isString); if (!contents.length) return; return contents; @@ -39,26 +39,26 @@ const getIgnoreBys = (foldersPaths: string[], filesContents: string[][]): Ignore return ignore; }; -const getIgnores = memoize(async (folderPath: string, filesNames: string[]): Promise => { - const contents = await getIgnoresContent(folderPath, filesNames); +const getIgnores = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { + const contents = await getIgnoresContent(folderPath, filesNames, ignoreKnown); if (!contents?.length) return; const ignore = getIgnoreBy(folderPath, contents); return ignore; }); -const getIgnoresUp = memoize(async (folderPath: string, filesNames: string[]): Promise => { - const ignore = await getIgnores(folderPath, filesNames); +const getIgnoresUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { + const ignore = await getIgnores(folderPath, filesNames, ignoreKnown); const folderPathUp = path.dirname(folderPath); - const ignoreUp = folderPath !== folderPathUp ? await getIgnoresUp(folderPathUp, filesNames) : undefined; + const ignoreUp = folderPath !== folderPathUp ? await getIgnoresUp(folderPathUp, filesNames, ignoreKnown) : undefined; const ignores = ignore ? (ignoreUp ? [ignore, ignoreUp] : [ignore]) : ignoreUp ? [ignoreUp] : []; if (!ignores.length) return; const ignoreAll = someOf(ignores); return ignoreAll; }); -const getIgnoreResolved = async (filePath: string, filesNames: string[]): Promise => { +const getIgnoreResolved = async (filePath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { const folderPath = path.dirname(filePath); - const ignore = await getIgnoresUp(folderPath, filesNames); + const ignore = await getIgnoresUp(folderPath, filesNames, ignoreKnown); const ignored = !!ignore?.(filePath); return ignored; }; diff --git a/src/config_prettier.ts b/src/config_prettier.ts index 48d555f..048226a 100644 --- a/src/config_prettier.ts +++ b/src/config_prettier.ts @@ -94,7 +94,7 @@ const Ext2Loader: Record Promise> = { mjs: Loaders.js, }; -const getPrettierConfig = (folderPath: string, fileName: string, ignoreKnown = false): PromiseMaybe => { +const getPrettierConfig = (folderPath: string, fileName: string, ignoreKnown?: boolean): PromiseMaybe => { const filePath = fastJoinedPath(folderPath, fileName); if (!ignoreKnown && !Known.hasFilePath(filePath)) return; const loader = File2Loader[fileName] || File2Loader["default"]; @@ -125,7 +125,7 @@ const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: stri return configs; }); -const getPrettierConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown = false): Promise => { +const getPrettierConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { const folderPath = path.dirname(filePath); const configs = await getPrettierConfigsUp(folderPath, filesNames, ignoreKnown); let resolved: PrettierConfig = {}; diff --git a/src/index.ts b/src/index.ts index c466a4a..7e9bf58 100644 --- a/src/index.ts +++ b/src/index.ts @@ -31,15 +31,23 @@ async function runStdin(options: Options, pluginsDefaultOptions: PluginsOptions, const fileName = options.stdinFilepath || "stdin"; const fileContent = (await getStdin()) || ""; - try { - const editorConfigNames = options.editorConfig ? [".editorconfig"] : []; - const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(fileName, editorConfigNames, true)) : {}; + const ignoreNames = options.ignore ? [".gitignore", ".prettierignore"] : []; + const isIgnored = await getIgnoreResolved(fileName, ignoreNames, true); + if (isIgnored) { + stdout.always(trimFinalNewline(fileContent)); + process.exitCode = 0; + return; + } - const prettierConfigNames = options.config ? without(Object.keys(File2Loader), ["default"]) : []; - const prettierConfig = options.config ? await getPrettierConfigResolved(fileName, prettierConfigNames, true) : {}; + const editorConfigNames = options.editorConfig ? [".editorconfig"] : []; + const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(fileName, editorConfigNames, true)) : {}; - const formatOptions = { ...editorConfig, ...prettierConfig, ...options.formatOptions }; + const prettierConfigNames = options.config ? without(Object.keys(File2Loader), ["default"]) : []; + const prettierConfig = options.config ? await getPrettierConfigResolved(fileName, prettierConfigNames, true) : {}; + const formatOptions = { ...editorConfig, ...prettierConfig, ...options.formatOptions }; + + try { const formatted = await prettier.format(fileName, fileContent, formatOptions, options.contextOptions, pluginsDefaultOptions, pluginsCustomOptions); if (options.check || options.list) { if (formatted !== fileContent) { From 12698feb982da2347fb563ba3614f74c58465149 Mon Sep 17 00:00:00 2001 From: pralkarz Date: Tue, 6 May 2025 17:54:08 +0200 Subject: [PATCH 8/8] test: populate `Known` in `runStdin` --- src/config_editorconfig.ts | 14 +++++++------- src/config_ignore.ts | 22 +++++++++++----------- src/config_prettier.ts | 28 +++++++++++++--------------- src/index.ts | 26 +++++++++++++++++++++----- 4 files changed, 52 insertions(+), 38 deletions(-) diff --git a/src/config_editorconfig.ts b/src/config_editorconfig.ts index c5a9114..aee3ccb 100644 --- a/src/config_editorconfig.ts +++ b/src/config_editorconfig.ts @@ -6,11 +6,11 @@ import { fastJoinedPath, findLastIndex, isUndefined, memoize, noop, zipObjectUnl import type { Config, ConfigWithOverrides } from "tiny-editorconfig"; import type { FormatOptions, PromiseMaybe } from "./types.js"; -const getEditorConfig = memoize((folderPath: string, filesNames: string[], ignoreKnown?: boolean): PromiseMaybe => { +const getEditorConfig = memoize((folderPath: string, filesNames: string[]): PromiseMaybe => { for (let i = 0, l = filesNames.length; i < l; i++) { const fileName = filesNames[i]; const filePath = fastJoinedPath(folderPath, fileName); - if (!ignoreKnown && !Known.hasFilePath(filePath)) continue; + if (!Known.hasFilePath(filePath)) continue; return fs.readFile(filePath, "utf8").then(EditorConfig.parse).catch(noop); } }); @@ -21,18 +21,18 @@ const getEditorConfigsMap = async (foldersPaths: string[], filesNames: string[]) return map; }; -const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { - const config = await getEditorConfig(folderPath, filesNames, ignoreKnown); +const getEditorConfigsUp = memoize(async (folderPath: string, filesNames: string[]): Promise => { + const config = await getEditorConfig(folderPath, filesNames); const folderPathUp = path.dirname(folderPath); - const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp, filesNames, ignoreKnown) : []; + const configsUp = folderPath !== folderPathUp ? await getEditorConfigsUp(folderPathUp, filesNames) : []; const configs = config ? [...configsUp, config] : configsUp; const lastRootIndex = findLastIndex(configs, (config) => config.root); return lastRootIndex > 0 ? configs.slice(lastRootIndex) : configs; }); -const getEditorConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { +const getEditorConfigResolved = async (filePath: string, filesNames: string[]): Promise => { const folderPath = path.dirname(filePath); - const configs = await getEditorConfigsUp(folderPath, filesNames, ignoreKnown); + const configs = await getEditorConfigsUp(folderPath, filesNames); const config = EditorConfig.resolve(configs, filePath); return config; }; diff --git a/src/config_ignore.ts b/src/config_ignore.ts index c3a6af6..75015af 100644 --- a/src/config_ignore.ts +++ b/src/config_ignore.ts @@ -5,14 +5,14 @@ import Known from "./known.js"; import { fastJoinedPath, fastRelativeChildPath, isString, isUndefined, memoize, noop, someOf, zipObjectUnless } from "./utils.js"; import type { Ignore, PromiseMaybe } from "./types.js"; -const getIgnoreContent = (folderPath: string, fileName: string, ignoreKnown?: boolean): PromiseMaybe => { +const getIgnoreContent = (folderPath: string, fileName: string): PromiseMaybe => { const filePath = fastJoinedPath(folderPath, fileName); - if (!ignoreKnown && !Known.hasFilePath(filePath)) return; + if (!Known.hasFilePath(filePath)) return; return fs.readFile(filePath, "utf8").catch(noop); }; -const getIgnoresContent = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { - const contentsRaw = await Promise.all(filesNames.map((fileName) => getIgnoreContent(folderPath, fileName, ignoreKnown))); +const getIgnoresContent = memoize(async (folderPath: string, filesNames: string[]): Promise => { + const contentsRaw = await Promise.all(filesNames.map((fileName) => getIgnoreContent(folderPath, fileName))); const contents = contentsRaw.filter(isString); if (!contents.length) return; return contents; @@ -39,26 +39,26 @@ const getIgnoreBys = (foldersPaths: string[], filesContents: string[][]): Ignore return ignore; }; -const getIgnores = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { - const contents = await getIgnoresContent(folderPath, filesNames, ignoreKnown); +const getIgnores = memoize(async (folderPath: string, filesNames: string[]): Promise => { + const contents = await getIgnoresContent(folderPath, filesNames); if (!contents?.length) return; const ignore = getIgnoreBy(folderPath, contents); return ignore; }); -const getIgnoresUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { - const ignore = await getIgnores(folderPath, filesNames, ignoreKnown); +const getIgnoresUp = memoize(async (folderPath: string, filesNames: string[]): Promise => { + const ignore = await getIgnores(folderPath, filesNames); const folderPathUp = path.dirname(folderPath); - const ignoreUp = folderPath !== folderPathUp ? await getIgnoresUp(folderPathUp, filesNames, ignoreKnown) : undefined; + const ignoreUp = folderPath !== folderPathUp ? await getIgnoresUp(folderPathUp, filesNames) : undefined; const ignores = ignore ? (ignoreUp ? [ignore, ignoreUp] : [ignore]) : ignoreUp ? [ignoreUp] : []; if (!ignores.length) return; const ignoreAll = someOf(ignores); return ignoreAll; }); -const getIgnoreResolved = async (filePath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { +const getIgnoreResolved = async (filePath: string, filesNames: string[]): Promise => { const folderPath = path.dirname(filePath); - const ignore = await getIgnoresUp(folderPath, filesNames, ignoreKnown); + const ignore = await getIgnoresUp(folderPath, filesNames); const ignored = !!ignore?.(filePath); return ignored; }; diff --git a/src/config_prettier.ts b/src/config_prettier.ts index 048226a..31aeaaf 100644 --- a/src/config_prettier.ts +++ b/src/config_prettier.ts @@ -94,22 +94,20 @@ const Ext2Loader: Record Promise> = { mjs: Loaders.js, }; -const getPrettierConfig = (folderPath: string, fileName: string, ignoreKnown?: boolean): PromiseMaybe => { +const getPrettierConfig = (folderPath: string, fileName: string): PromiseMaybe => { const filePath = fastJoinedPath(folderPath, fileName); - if (!ignoreKnown && !Known.hasFilePath(filePath)) return; + if (!Known.hasFilePath(filePath)) return; const loader = File2Loader[fileName] || File2Loader["default"]; const normalize = (config: unknown) => (isObject(config) ? { ...config, ...normalizePrettierOptions(config, folderPath) } : undefined); return loader(filePath).then(normalize).catch(noop); }; -const getPrettierConfigs = memoize( - async (folderPath: string, filesNames: string[], ignoreKnown: boolean = false): Promise => { - const configsRaw = await Promise.all(filesNames.map((fileName) => getPrettierConfig(folderPath, fileName, ignoreKnown))); - const configs = configsRaw.filter(isTruthy); - if (!configs.length) return; - return configs; - }, -); +const getPrettierConfigs = memoize(async (folderPath: string, filesNames: string[]): Promise => { + const configsRaw = await Promise.all(filesNames.map((fileName) => getPrettierConfig(folderPath, fileName))); + const configs = configsRaw.filter(isTruthy); + if (!configs.length) return; + return configs; +}); const getPrettierConfigsMap = async (foldersPaths: string[], filesNames: string[]): Promise>> => { const configs = await Promise.all(foldersPaths.map((folderPath) => getPrettierConfigs(folderPath, filesNames))); @@ -117,17 +115,17 @@ const getPrettierConfigsMap = async (foldersPaths: string[], filesNames: string[ return map; }; -const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: string[], ignoreKnown: boolean = false): Promise => { - const config = (await getPrettierConfigs(folderPath, filesNames, ignoreKnown))?.[0]; +const getPrettierConfigsUp = memoize(async (folderPath: string, filesNames: string[]): Promise => { + const config = (await getPrettierConfigs(folderPath, filesNames))?.[0]; const folderPathUp = path.dirname(folderPath); - const configsUp = folderPath !== folderPathUp ? await getPrettierConfigsUp(folderPathUp, filesNames, ignoreKnown) : []; + const configsUp = folderPath !== folderPathUp ? await getPrettierConfigsUp(folderPathUp, filesNames) : []; const configs = config ? [...configsUp, config] : configsUp; return configs; }); -const getPrettierConfigResolved = async (filePath: string, filesNames: string[], ignoreKnown?: boolean): Promise => { +const getPrettierConfigResolved = async (filePath: string, filesNames: string[]): Promise => { const folderPath = path.dirname(filePath); - const configs = await getPrettierConfigsUp(folderPath, filesNames, ignoreKnown); + const configs = await getPrettierConfigsUp(folderPath, filesNames); let resolved: PrettierConfig = {}; for (let ci = 0, cl = configs.length; ci < cl; ci++) { diff --git a/src/index.ts b/src/index.ts index 7e9bf58..1602aa8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -28,22 +28,38 @@ async function runStdin(options: Options, pluginsDefaultOptions: PluginsOptions, const stdout = new Logger(options.logLevel, "stdout"); const prettier = await import("./prettier_serial.js"); + const rootPath = process.cwd(); + const projectPath = getProjectPath(rootPath); + const fileName = options.stdinFilepath || "stdin"; const fileContent = (await getStdin()) || ""; + const [_filesPaths, filesNames, filesNamesToPaths, _filesExplicitPaths, filesFoundPaths, foldersFoundPaths] = await getTargetsPaths(rootPath, [fileName], false); // prettier-ignore + const [_foldersPathsTargets, foldersExtraPaths] = getExpandedFoldersPaths(foldersFoundPaths, projectPath); + const filesExtraPaths = await getFoldersChildrenPaths([rootPath, ...foldersExtraPaths]); + const filesExtraNames = filesExtraPaths.map((filePath) => path.basename(filePath)); + + Known.addFilesPaths(filesFoundPaths); + Known.addFilesPaths(filesExtraPaths); + + Known.addFilesNames(filesNames); + Known.addFilesNames(filesExtraNames); + const ignoreNames = options.ignore ? [".gitignore", ".prettierignore"] : []; - const isIgnored = await getIgnoreResolved(fileName, ignoreNames, true); + const isIgnored = await getIgnoreResolved(path.join(rootPath, fileName), ignoreNames); if (isIgnored) { stdout.always(trimFinalNewline(fileContent)); process.exitCode = 0; return; } - const editorConfigNames = options.editorConfig ? [".editorconfig"] : []; - const editorConfig = options.editorConfig ? getEditorConfigFormatOptions(await getEditorConfigResolved(fileName, editorConfigNames, true)) : {}; + const editorConfigNames = options.editorConfig ? [".editorconfig"].filter(Known.hasFileName) : []; + const editorConfig = options.editorConfig + ? getEditorConfigFormatOptions(await getEditorConfigResolved(path.join(rootPath, fileName), editorConfigNames)) + : {}; - const prettierConfigNames = options.config ? without(Object.keys(File2Loader), ["default"]) : []; - const prettierConfig = options.config ? await getPrettierConfigResolved(fileName, prettierConfigNames, true) : {}; + const prettierConfigNames = options.config ? without(Object.keys(File2Loader), ["default"]).filter(Known.hasFileName) : []; + const prettierConfig = options.config ? await getPrettierConfigResolved(path.join(rootPath, fileName), prettierConfigNames) : {}; const formatOptions = { ...editorConfig, ...prettierConfig, ...options.formatOptions };