Skip to content

Commit 842fec9

Browse files
Merge pull request #384 from vladislavarsenev/RyderKishan/main
ignore files
2 parents 3347f3f + 9acb229 commit 842fec9

8 files changed

Lines changed: 170 additions & 5 deletions

File tree

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,12 @@ In the end, the plugin returns final imports with _third party imports_ on top a
292292

293293
The _third party imports_ position (it's top by default) can be overridden using the `<THIRD_PARTY_MODULES>` special word in the `importOrder`.
294294

295+
### Pattern Matching Implementation
296+
297+
This plugin uses [minimatch](https://github.com/isaacs/minimatch) for pattern matching of import paths. The matching is performed using the exact version specified in the plugin's dependencies to ensure consistent behavior. This is important to note because different versions of minimatch or other glob matching libraries might have subtle differences in their pattern matching behavior.
298+
299+
If you're experiencing unexpected matching behavior, please ensure you're using patterns compatible with minimatch's syntax, which might differ slightly from other glob implementations.
300+
295301
### FAQ / Troubleshooting
296302

297303
Having some trouble or an issue ? You can check [FAQ / Troubleshooting section](./docs/TROUBLESHOOTING.md).
@@ -326,10 +332,10 @@ debug some code in the plugin, check [Debugging Guidelines](./docs/DEBUG.md)
326332

327333
### Maintainers
328334

329-
| [Ayush Sharma](https://github.com/ayusharma) | [Behrang Yarahmadi](https://github.com/byara) | [Vladislav Arsenev](https://github.com/vladislavarsenev) |
330-
| ------------------------------------------------------------------------ | --------------------------------------------------------------------- |--------------------------------------------------------------------------|
331-
| ![ayusharma](https://avatars2.githubusercontent.com/u/6918450?s=120&v=4) | ![@byara](https://avatars2.githubusercontent.com/u/6979966?s=120&v=4) |![@vladislavarsenev](https://avatars.githubusercontent.com/u/51095682?s=120&v=4)|
332-
| [@ayusharma](https://twitter.com/ayusharma_) | [@behrang_y](https://twitter.com/behrang_y) | |
335+
| [Ayush Sharma](https://github.com/ayusharma) | [Behrang Yarahmadi](https://github.com/byara) |
336+
| ------------------------------------------------------------------------ | --------------------------------------------------------------------- |
337+
| ![ayusharma](https://avatars2.githubusercontent.com/u/6918450?s=120&v=4) | ![@byara](https://avatars2.githubusercontent.com/u/6979966?s=120&v=4) |
338+
| [@ayusharma\_](https://twitter.com/ayusharma_) | [@behrang_y](https://twitter.com/behrang_y) |
333339

334340
### Disclaimer
335341

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,16 @@
4141
"@babel/types": "^7.28.0",
4242
"javascript-natural-sort": "^0.7.1",
4343
"lodash-es": "^4.17.21",
44-
"parse-imports-exports": "^0.2.4"
44+
"parse-imports-exports": "^0.2.4",
45+
"minimatch": "^9.0.0"
4546
},
4647
"devDependencies": {
4748
"@babel/core": "^7.26.7",
4849
"@types/babel__core": "^7.20.5",
4950
"@types/babel__generator": "^7.27.0",
5051
"@types/babel__traverse": "^7.20.7",
5152
"@types/lodash-es": "^4.17.12",
53+
"@types/minimatch": "^5.1.2",
5254
"@types/node": "^22.10.10",
5355
"@vue/compiler-sfc": "^3.5.13",
5456
"prettier": "^3.4.2",

src/index.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ const emberParsers = await createEmberParsers();
1515
const svelteParsers = await createSvelteParsers();
1616

1717
const options: Options = {
18+
importOrderExclude: {
19+
type: 'path',
20+
category: 'Global',
21+
array: true,
22+
default: [{ value: [] }],
23+
description:
24+
'Provide a list of glob patterns to exclude from import sorting.',
25+
},
1826
importOrder: {
1927
type: 'path',
2028
category: 'Global',

src/preprocessors/preprocessor.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { getCodeFromAst } from '../utils/get-code-from-ast.js';
88
import { getExperimentalParserPlugins } from '../utils/get-experimental-parser-plugins.js';
99
import { getSortedNodes } from '../utils/get-sorted-nodes.js';
1010
import { isSortImportsIgnored } from '../utils/is-sort-imports-ignored.js';
11+
import { shouldSkipFile } from '../utils/should-skip-file.js';
1112

1213
export function preprocessor(code: string, options: PrettierOptions) {
1314
const {
@@ -20,8 +21,18 @@ export function preprocessor(code: string, options: PrettierOptions) {
2021
importOrderSortByLength,
2122
importOrderSideEffects,
2223
importOrderImportAttributesKeyword,
24+
importOrderExclude,
25+
filepath,
2326
} = options;
2427

28+
// Check if the file should be skipped
29+
if (
30+
filepath &&
31+
shouldSkipFile(filepath, (importOrderExclude || []) as string[])
32+
) {
33+
return code;
34+
}
35+
2536
const parserOptions: ParserOptions = {
2637
sourceType: 'module',
2738
plugins: getExperimentalParserPlugins(importOrderParserPlugins),
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { describe, expect, it } from 'vitest';
2+
3+
import { shouldSkipFile } from '../should-skip-file';
4+
5+
describe('shouldSkipFile', () => {
6+
it('should return false when skipPatterns is empty', () => {
7+
expect(shouldSkipFile('src/file.ts', [])).toBe(false);
8+
});
9+
10+
it('should return false when no patterns match', () => {
11+
const patterns = ['test/*.ts', 'lib/*.js'];
12+
expect(shouldSkipFile('src/file.ts', patterns)).toBe(false);
13+
});
14+
15+
it('should return true when file matches a pattern', () => {
16+
const patterns = ['src/*.ts', 'lib/*.js'];
17+
expect(shouldSkipFile('src/file.ts', patterns)).toBe(true);
18+
});
19+
20+
it('should handle glob patterns correctly', () => {
21+
const patterns = ['*.test.ts', 'generated/**'];
22+
expect(shouldSkipFile('Button.test.ts', patterns)).toBe(true);
23+
expect(shouldSkipFile('generated/types.ts', patterns)).toBe(true);
24+
expect(shouldSkipFile('src/Button.ts', patterns)).toBe(false);
25+
});
26+
27+
it('should match filename-only patterns against basename', () => {
28+
const patterns = ['*.js', 'example.ts'];
29+
expect(shouldSkipFile('/long/path/to/file.js', patterns)).toBe(true);
30+
expect(shouldSkipFile('/different/path/example.ts', patterns)).toBe(
31+
true,
32+
);
33+
expect(shouldSkipFile('/path/to/file.ts', patterns)).toBe(false);
34+
});
35+
36+
it('should handle special characters in filenames', () => {
37+
const patterns = ['*.spec.ts', '*test*.js'];
38+
expect(shouldSkipFile('my-component.spec.ts', patterns)).toBe(true);
39+
expect(shouldSkipFile('my.test.js', patterns)).toBe(true);
40+
expect(shouldSkipFile('test.jsx', patterns)).toBe(false);
41+
});
42+
43+
it('should handle multiple patterns with mixed path separators', () => {
44+
const patterns = ['src/*.ts', 'test/*.js', '*.test.tsx'];
45+
expect(shouldSkipFile('src/file.ts', patterns)).toBe(true);
46+
expect(shouldSkipFile('test/file.js', patterns)).toBe(true);
47+
expect(shouldSkipFile('component.test.tsx', patterns)).toBe(true);
48+
expect(shouldSkipFile('src/sub/file.ts', patterns)).toBe(false);
49+
});
50+
51+
it('should handle exact filename matches', () => {
52+
const patterns = ['example.js', 'tsconfig.json'];
53+
expect(shouldSkipFile('/any/path/example.js', patterns)).toBe(true);
54+
expect(shouldSkipFile('/root/tsconfig.json', patterns)).toBe(true);
55+
expect(shouldSkipFile('/path/to/example.test.js', patterns)).toBe(
56+
false,
57+
);
58+
});
59+
60+
it('should handle directory patterns', () => {
61+
const patterns = ['test/**/*.*', 'generated/**/*.*'];
62+
expect(shouldSkipFile('test/file.ts', patterns)).toBe(true);
63+
expect(shouldSkipFile('test/unit/component.js', patterns)).toBe(true);
64+
expect(shouldSkipFile('generated/types.ts', patterns)).toBe(true);
65+
expect(shouldSkipFile('src/components/button.ts', patterns)).toBe(
66+
false,
67+
);
68+
});
69+
});

src/utils/should-skip-file.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { minimatch } from 'minimatch';
2+
import path from 'path';
3+
4+
/**
5+
* Checks if the current file path matches any of the patterns in importOrderExclude
6+
* @param filePath The path of the current file being processed
7+
* @param skipPatterns Array of patterns for files to skip
8+
* @returns boolean indicating whether the file should be skipped
9+
*/
10+
export function shouldSkipFile(
11+
filepath: string,
12+
skipPatterns: string[],
13+
): boolean {
14+
if (skipPatterns.length === 0) {
15+
return false;
16+
}
17+
18+
const normalizedPath = filepath.split(path.sep).join('/');
19+
const filename = path.basename(filepath);
20+
21+
return skipPatterns.some((pattern) => {
22+
// Normalize pattern to use forward slashes
23+
const normalizedPattern = pattern.split(path.sep).join('/');
24+
25+
// If pattern doesn't contain '/', match against filename only
26+
if (!normalizedPattern.includes('/')) {
27+
return minimatch(filename, normalizedPattern, { matchBase: true });
28+
}
29+
30+
// Otherwise match against full path
31+
return minimatch(normalizedPath, normalizedPattern);
32+
});
33+
}

types/index.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,18 @@ used to order imports within each match group.
121121
* _Default behavior:_ When not specified, @babel/generator will try to match the style in the input code based on the AST shape.
122122
*/
123123
importOrderImportAttributesKeyword?: 'assert' | 'with' | 'with-legacy';
124+
125+
/**
126+
* An array of glob patterns for files that should be skipped by the import sorting.
127+
* Files matching these patterns will not have their imports sorted.
128+
*
129+
* ```
130+
* "importOrderExclude": ["*.test.ts", "src/generated/**"]
131+
* ```
132+
*
133+
* @default []
134+
*/
135+
importOrderExclude?: string[];
124136
}
125137

126138
export type PrettierConfig = PluginConfig & Config;

yarn.lock

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,11 @@
665665
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93"
666666
integrity sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==
667667

668+
"@types/minimatch@^5.1.2":
669+
version "5.1.2"
670+
resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca"
671+
integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==
672+
668673
"@types/node@^22.10.10":
669674
version "22.10.10"
670675
resolved "https://registry.npmjs.org/@types/node/-/node-22.10.10.tgz"
@@ -802,6 +807,18 @@ axobject-query@^4.0.0:
802807
resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz"
803808
integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==
804809

810+
balanced-match@^1.0.0:
811+
version "1.0.2"
812+
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
813+
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
814+
815+
brace-expansion@^2.0.1:
816+
version "2.0.2"
817+
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7"
818+
integrity sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==
819+
dependencies:
820+
balanced-match "^1.0.0"
821+
805822
browserslist@^4.24.0:
806823
version "4.24.2"
807824
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz"
@@ -1053,6 +1070,13 @@ mdn-data@2.0.30:
10531070
resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz"
10541071
integrity sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==
10551072

1073+
minimatch@^9.0.0:
1074+
version "9.0.5"
1075+
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
1076+
integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
1077+
dependencies:
1078+
brace-expansion "^2.0.1"
1079+
10561080
ms@^2.1.3:
10571081
version "2.1.3"
10581082
resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz"

0 commit comments

Comments
 (0)