@w5s/eslint-config-ignore 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +34 -0
- package/dist/index.d.ts +59 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
- package/src/defaultIgnores.ts +44 -0
- package/src/eslintIgnores.ts +90 -0
- package/src/index.ts +4 -0
- package/src/internal/ignoreFileFind.ts +17 -0
- package/src/internal/ignoreFileParse.ts +5 -0
- package/src/internal/ignoreRuleResolve.ts +31 -0
- package/src/meta.ts +8 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021 Julien Polo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# W5S ESLint ignore configuration _(@w5s/eslint-config-ignore)_
|
|
2
|
+
|
|
3
|
+
[![NPM Version][package-version-svg]][package-url]
|
|
4
|
+
[![License][license-image]][license-url]
|
|
5
|
+
|
|
6
|
+
> Shared ignore configuration generator for ESLint presets.
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```console
|
|
11
|
+
npm install --save-dev @w5s/eslint-config-ignore
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { ignores } from '@w5s/eslint-config-ignore';
|
|
18
|
+
|
|
19
|
+
export default [ignores()];
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## API
|
|
23
|
+
|
|
24
|
+
- `ignores(options?)`
|
|
25
|
+
- `options.ignores?: string[]`
|
|
26
|
+
|
|
27
|
+
## License
|
|
28
|
+
|
|
29
|
+
[MIT][license-url]
|
|
30
|
+
|
|
31
|
+
[package-version-svg]: https://img.shields.io/npm/v/@w5s/eslint-config-ignore.svg?style=flat-square
|
|
32
|
+
[package-url]: https://www.npmjs.com/package/@w5s/eslint-config-ignore
|
|
33
|
+
[license-image]: https://img.shields.io/badge/license-MIT-green.svg?style=flat-square
|
|
34
|
+
[license-url]: ../../LICENSE
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//#region src/meta.d.ts
|
|
2
|
+
declare const meta: Readonly<{
|
|
3
|
+
name: string;
|
|
4
|
+
version: string;
|
|
5
|
+
buildNumber: number;
|
|
6
|
+
}>;
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/eslintIgnores.d.ts
|
|
9
|
+
/**
|
|
10
|
+
* Create a new eslint configuration object
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // eslint.config.js
|
|
15
|
+
* export default [
|
|
16
|
+
* await eslintIgnores({
|
|
17
|
+
* ignores: [
|
|
18
|
+
* // Add custom paths here
|
|
19
|
+
* ]
|
|
20
|
+
* })
|
|
21
|
+
* ];
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @param options
|
|
25
|
+
*/
|
|
26
|
+
declare function eslintIgnores(options?: ESLintIgnoreOptions): Promise<ESLintIgnoreConfig>;
|
|
27
|
+
interface ESLintIgnoreConfig {
|
|
28
|
+
/**
|
|
29
|
+
* The configuration name
|
|
30
|
+
*/
|
|
31
|
+
name: string;
|
|
32
|
+
/**
|
|
33
|
+
* The file globs to ignore
|
|
34
|
+
*/
|
|
35
|
+
ignores: Array<string>;
|
|
36
|
+
}
|
|
37
|
+
interface ESLintIgnoreOptions {
|
|
38
|
+
/**
|
|
39
|
+
* Override configuration name
|
|
40
|
+
*/
|
|
41
|
+
name?: ESLintIgnoreConfig['name'];
|
|
42
|
+
/**
|
|
43
|
+
* Override current working directory
|
|
44
|
+
*/
|
|
45
|
+
cwd?: string;
|
|
46
|
+
/**
|
|
47
|
+
* Override or customize ignore patterns.
|
|
48
|
+
* - If passed an array, it appends patterns to the merged ignore list.
|
|
49
|
+
* - If passed a function, it receives the merged list and returns the final array.
|
|
50
|
+
*/
|
|
51
|
+
ignores?: ESLintIgnoreConfig['ignores'] | ((ignores: ESLintIgnoreConfig['ignores']) => ESLintIgnoreConfig['ignores']);
|
|
52
|
+
/**
|
|
53
|
+
* Include recommended settings and default ignored files
|
|
54
|
+
*/
|
|
55
|
+
recommended?: boolean | undefined;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { ESLintIgnoreConfig, ESLintIgnoreOptions, type ESLintIgnoreOptions as Options, eslintIgnores as default, eslintIgnores, meta };
|
|
59
|
+
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import nodePath from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import parseGitignore from "parse-gitignore";
|
|
5
|
+
import { findUp } from "find-up";
|
|
6
|
+
//#region src/meta.ts
|
|
7
|
+
const meta = Object.freeze({
|
|
8
|
+
name: "@w5s/eslint-config-ignore",
|
|
9
|
+
version: "1.1.0",
|
|
10
|
+
buildNumber: 1
|
|
11
|
+
});
|
|
12
|
+
//#endregion
|
|
13
|
+
//#region src/defaultIgnores.ts
|
|
14
|
+
const defaultIgnores = [
|
|
15
|
+
"**/package-lock.json",
|
|
16
|
+
"**/yarn.lock",
|
|
17
|
+
"**/pnpm-lock.yaml",
|
|
18
|
+
"**/bun.lockb",
|
|
19
|
+
"**/output",
|
|
20
|
+
"**/.output",
|
|
21
|
+
"**/coverage",
|
|
22
|
+
"**/temp",
|
|
23
|
+
"**/.temp",
|
|
24
|
+
"**/tmp",
|
|
25
|
+
"**/.tmp",
|
|
26
|
+
"**/.cache",
|
|
27
|
+
"**/*.min.*",
|
|
28
|
+
"**/*.timestamp-*.mjs",
|
|
29
|
+
".go/",
|
|
30
|
+
".pnpm-store/",
|
|
31
|
+
"**/.vitepress/cache",
|
|
32
|
+
"**/.vite-inspect",
|
|
33
|
+
"**/.history",
|
|
34
|
+
"**/.nuxt",
|
|
35
|
+
"**/.next",
|
|
36
|
+
"**/.svelte-kit",
|
|
37
|
+
"**/.vercel",
|
|
38
|
+
"**/.idea",
|
|
39
|
+
"**/.yarn",
|
|
40
|
+
"**/__snapshots__/**",
|
|
41
|
+
".modules/",
|
|
42
|
+
"**/.context",
|
|
43
|
+
"**/.claude",
|
|
44
|
+
"**/.agents",
|
|
45
|
+
"**/.*/skills"
|
|
46
|
+
];
|
|
47
|
+
//#endregion
|
|
48
|
+
//#region src/internal/ignoreFileParse.ts
|
|
49
|
+
function ignoreFileParse(input) {
|
|
50
|
+
return parseGitignore.parse(input).patterns;
|
|
51
|
+
}
|
|
52
|
+
//#endregion
|
|
53
|
+
//#region src/internal/ignoreFileFind.ts
|
|
54
|
+
async function ignoreFileFind(cwd) {
|
|
55
|
+
return (await Promise.all([
|
|
56
|
+
findUp(nodePath.join("", ".gitignore"), { cwd }),
|
|
57
|
+
findUp(nodePath.join("android", ".gitignore"), { cwd }),
|
|
58
|
+
findUp(nodePath.join("ios", ".gitignore"), { cwd })
|
|
59
|
+
])).filter((filePath) => filePath !== void 0).map((filePath) => nodePath.relative(cwd, filePath));
|
|
60
|
+
}
|
|
61
|
+
//#endregion
|
|
62
|
+
//#region src/internal/ignoreRuleResolve.ts
|
|
63
|
+
/**
|
|
64
|
+
* Resolve a raw ignore rule from a `.gitignore` file into a path
|
|
65
|
+
* relative to the configured working directory.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```ts
|
|
69
|
+
* import { ignoreRuleResolve } from './internal/ignoreRuleResolve.js';
|
|
70
|
+
*
|
|
71
|
+
* ignoreRuleResolve('.', 'dist'); // 'dist'
|
|
72
|
+
* ignoreRuleResolve('.', '/dist'); // 'dist'
|
|
73
|
+
* ignoreRuleResolve('android', 'android-build'); // 'android/android-build'
|
|
74
|
+
* ignoreRuleResolve('android', '!android-build'); // '!android/android-build'
|
|
75
|
+
* ```
|
|
76
|
+
*
|
|
77
|
+
* @internal
|
|
78
|
+
* @param prefix A path prefix that points to the directory containing the `.gitignore` file.
|
|
79
|
+
* @param rule The raw ignore rule parsed from `.gitignore`.
|
|
80
|
+
* @returns A normalized ignore pattern relative to the root `cwd`.
|
|
81
|
+
*/
|
|
82
|
+
function ignoreRuleResolve(prefix, rule) {
|
|
83
|
+
const negated = rule.startsWith("!");
|
|
84
|
+
const normalizedPattern = negated ? rule.slice(1) : rule;
|
|
85
|
+
const trimmedPattern = normalizedPattern.startsWith("/") ? normalizedPattern.slice(1) : normalizedPattern;
|
|
86
|
+
const relativeIgnorePath = nodePath.join(prefix, trimmedPattern);
|
|
87
|
+
return negated ? `!${relativeIgnorePath}` : relativeIgnorePath;
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
90
|
+
//#region src/eslintIgnores.ts
|
|
91
|
+
/**
|
|
92
|
+
* Create a new eslint configuration object
|
|
93
|
+
*
|
|
94
|
+
* @example
|
|
95
|
+
* ```ts
|
|
96
|
+
* // eslint.config.js
|
|
97
|
+
* export default [
|
|
98
|
+
* await eslintIgnores({
|
|
99
|
+
* ignores: [
|
|
100
|
+
* // Add custom paths here
|
|
101
|
+
* ]
|
|
102
|
+
* })
|
|
103
|
+
* ];
|
|
104
|
+
* ```
|
|
105
|
+
*
|
|
106
|
+
* @param options
|
|
107
|
+
*/
|
|
108
|
+
async function eslintIgnores(options = {}) {
|
|
109
|
+
const cwd = options.cwd ?? process.cwd();
|
|
110
|
+
const recommended = options.recommended ?? true;
|
|
111
|
+
const ignoreFilePaths = await ignoreFileFind(cwd);
|
|
112
|
+
const ignoreGlobs = await Promise.all(ignoreFilePaths.map(async (ignoreFilePathRelative) => {
|
|
113
|
+
const ignoreFilePath = nodePath.join(cwd, ignoreFilePathRelative);
|
|
114
|
+
const patterns = ignoreFileParse(String(await fs.promises.readFile(ignoreFilePath)));
|
|
115
|
+
const ignoreDirectoryRelative = nodePath.dirname(ignoreFilePathRelative);
|
|
116
|
+
return patterns.map((pattern) => ignoreRuleResolve(ignoreDirectoryRelative, pattern));
|
|
117
|
+
}));
|
|
118
|
+
const mergedIgnores = [...recommended ? defaultIgnores : [], ...ignoreGlobs.flat()];
|
|
119
|
+
const ignores = typeof options.ignores === "function" ? options.ignores(mergedIgnores) : options.ignores ? [...mergedIgnores, ...options.ignores] : mergedIgnores;
|
|
120
|
+
return {
|
|
121
|
+
name: options.name ?? "w5s/eslint-ignore",
|
|
122
|
+
ignores
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//#endregion
|
|
126
|
+
export { eslintIgnores as default, eslintIgnores, meta };
|
|
127
|
+
|
|
128
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/meta.ts","../src/defaultIgnores.ts","../src/internal/ignoreFileParse.ts","../src/internal/ignoreFileFind.ts","../src/internal/ignoreRuleResolve.ts","../src/eslintIgnores.ts"],"sourcesContent":["export const meta = Object.freeze({\n // @ts-ignore - these variables are injected at build time\n name: (typeof __PACKAGE_NAME__ === 'undefined' ? '' : __PACKAGE_NAME__) as string,\n // @ts-ignore - these variables are injected at build time\n version: (typeof __PACKAGE_VERSION__ === 'undefined' ? '' : __PACKAGE_VERSION__) as string,\n // @ts-ignore - these variables are injected at build time\n buildNumber: 1 as number, // (typeof __PACKAGE_BUILD_NUMBER__ === 'undefined' ? 0 : __PACKAGE_BUILD_NUMBER__) as number,\n});\n","export const defaultIgnores = [\n // Lock files\n '**/package-lock.json',\n '**/yarn.lock',\n '**/pnpm-lock.yaml',\n '**/bun.lockb',\n\n // Commonly ignored\n '**/output',\n '**/.output',\n '**/coverage',\n '**/temp',\n '**/.temp',\n '**/tmp',\n '**/.tmp',\n '**/.cache',\n\n // Well known extensions to ignore\n '**/*.min.*',\n '**/*.timestamp-*.mjs',\n\n // Framework specific temporary folder\n '.go/',\n '.pnpm-store/',\n '**/.vitepress/cache',\n '**/.vite-inspect',\n '**/.history',\n '**/.nuxt',\n '**/.next',\n '**/.svelte-kit',\n '**/.vercel',\n '**/.idea',\n '**/.yarn',\n '**/__snapshots__/**',\n\n // git submodules (makefile-core / makefile-ci)\n '.modules/',\n\n // AI related\n '**/.context',\n '**/.claude',\n '**/.agents',\n '**/.*/skills',\n];\n","import parseGitignore from 'parse-gitignore';\n\nexport function ignoreFileParse(input: string): Array<string> {\n return parseGitignore.parse(input).patterns;\n};\n","import nodePath from 'node:path';\nimport { findUp } from 'find-up';\n\nexport async function ignoreFileFind(cwd: string): Promise<Array<string>> {\n const files = await Promise.all(\n [\n findUp(nodePath.join('', '.gitignore'), { cwd }),\n // TODO: refactor as generic exploration\n findUp(nodePath.join('android', '.gitignore'), { cwd }),\n findUp(nodePath.join('ios', '.gitignore'), { cwd }),\n ],\n );\n\n return files\n .filter((filePath): filePath is string => filePath !== undefined)\n .map((filePath) => nodePath.relative(cwd, filePath));\n}\n","import nodePath from 'node:path';\n\n/**\n * Resolve a raw ignore rule from a `.gitignore` file into a path\n * relative to the configured working directory.\n *\n * @example\n * ```ts\n * import { ignoreRuleResolve } from './internal/ignoreRuleResolve.js';\n *\n * ignoreRuleResolve('.', 'dist'); // 'dist'\n * ignoreRuleResolve('.', '/dist'); // 'dist'\n * ignoreRuleResolve('android', 'android-build'); // 'android/android-build'\n * ignoreRuleResolve('android', '!android-build'); // '!android/android-build'\n * ```\n *\n * @internal\n * @param prefix A path prefix that points to the directory containing the `.gitignore` file.\n * @param rule The raw ignore rule parsed from `.gitignore`.\n * @returns A normalized ignore pattern relative to the root `cwd`.\n */\nexport function ignoreRuleResolve(prefix: string, rule: string) {\n const negated = rule.startsWith('!');\n const normalizedPattern = negated ? rule.slice(1) : rule;\n const trimmedPattern = normalizedPattern.startsWith('/')\n ? normalizedPattern.slice(1)\n : normalizedPattern;\n const relativeIgnorePath = nodePath.join(prefix, trimmedPattern);\n\n return negated ? `!${relativeIgnorePath}` : relativeIgnorePath;\n}\n","import fs from 'node:fs';\nimport nodePath from 'node:path';\nimport process from 'node:process';\nimport { defaultIgnores } from './defaultIgnores.js';\nimport { ignoreFileParse } from './internal/ignoreFileParse.js';\nimport { ignoreFileFind } from './internal/ignoreFileFind.js';\nimport { ignoreRuleResolve } from './internal/ignoreRuleResolve.js';\n\n/**\n * Create a new eslint configuration object\n *\n * @example\n * ```ts\n * // eslint.config.js\n * export default [\n * await eslintIgnores({\n * ignores: [\n * // Add custom paths here\n * ]\n * })\n * ];\n * ```\n *\n * @param options\n */\nexport async function eslintIgnores(options: ESLintIgnoreOptions = {}): Promise<ESLintIgnoreConfig> {\n const cwd = options.cwd ?? process.cwd();\n const recommended = options.recommended ?? true;\n const ignoreFilePaths = await ignoreFileFind(cwd);\n const ignoreGlobs = (await Promise.all(ignoreFilePaths.map(async (ignoreFilePathRelative) => {\n const ignoreFilePath = nodePath.join(cwd, ignoreFilePathRelative);\n const ignoreFileContent = String(await fs.promises.readFile(ignoreFilePath));\n const patterns = ignoreFileParse(ignoreFileContent);\n const ignoreDirectoryRelative = nodePath.dirname(ignoreFilePathRelative);\n\n return patterns.map((pattern) => ignoreRuleResolve(ignoreDirectoryRelative, pattern));\n })));\n\n const mergedIgnores = [\n ...(recommended ? defaultIgnores : []),\n ...ignoreGlobs.flat(),\n ];\n\n const ignores = typeof options.ignores === 'function'\n ? options.ignores(mergedIgnores)\n : options.ignores\n ? [...mergedIgnores, ...options.ignores]\n : mergedIgnores;\n\n return {\n name: options.name ?? 'w5s/eslint-ignore',\n ignores,\n };\n}\n\nexport interface ESLintIgnoreConfig {\n /**\n * The configuration name\n */\n name: string;\n\n /**\n * The file globs to ignore\n */\n ignores: Array<string>;\n}\n\nexport interface ESLintIgnoreOptions {\n /**\n * Override configuration name\n */\n name?: ESLintIgnoreConfig['name'];\n\n /**\n * Override current working directory\n */\n cwd?: string;\n\n /**\n * Override or customize ignore patterns.\n * - If passed an array, it appends patterns to the merged ignore list.\n * - If passed a function, it receives the merged list and returns the final array.\n */\n ignores?: ESLintIgnoreConfig['ignores'] | ((ignores: ESLintIgnoreConfig['ignores']) => ESLintIgnoreConfig['ignores']);\n\n /**\n * Include recommended settings and default ignored files\n */\n recommended?: boolean | undefined;\n}\n"],"mappings":";;;;;;AAAA,MAAa,OAAO,OAAO,OAAO;CAEhC,MAAA;CAEA,SAAA;CAEA,aAAa;AACf,CAAC;;;ACPD,MAAa,iBAAiB;CAE5B;CACA;CACA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CACA;CAGA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CAGA;CAGA;CACA;CACA;CACA;AACF;;;ACzCA,SAAgB,gBAAgB,OAA8B;CAC5D,OAAO,eAAe,MAAM,KAAK,CAAC,CAAC;AACrC;;;ACDA,eAAsB,eAAe,KAAqC;CAUxE,QAAO,MATa,QAAQ,IAC1B;EACE,OAAO,SAAS,KAAK,IAAI,YAAY,GAAG,EAAE,IAAI,CAAC;EAE/C,OAAO,SAAS,KAAK,WAAW,YAAY,GAAG,EAAE,IAAI,CAAC;EACtD,OAAO,SAAS,KAAK,OAAO,YAAY,GAAG,EAAE,IAAI,CAAC;CACpD,CACF,EAAA,CAGG,QAAQ,aAAiC,aAAa,KAAA,CAAS,CAAC,CAChE,KAAK,aAAa,SAAS,SAAS,KAAK,QAAQ,CAAC;AACvD;;;;;;;;;;;;;;;;;;;;;;ACKA,SAAgB,kBAAkB,QAAgB,MAAc;CAC9D,MAAM,UAAU,KAAK,WAAW,GAAG;CACnC,MAAM,oBAAoB,UAAU,KAAK,MAAM,CAAC,IAAI;CACpD,MAAM,iBAAiB,kBAAkB,WAAW,GAAG,IACnD,kBAAkB,MAAM,CAAC,IACzB;CACJ,MAAM,qBAAqB,SAAS,KAAK,QAAQ,cAAc;CAE/D,OAAO,UAAU,IAAI,uBAAuB;AAC9C;;;;;;;;;;;;;;;;;;;;ACLA,eAAsB,cAAc,UAA+B,CAAC,GAAgC;CAClG,MAAM,MAAM,QAAQ,OAAO,QAAQ,IAAI;CACvC,MAAM,cAAc,QAAQ,eAAe;CAC3C,MAAM,kBAAkB,MAAM,eAAe,GAAG;CAChD,MAAM,cAAe,MAAM,QAAQ,IAAI,gBAAgB,IAAI,OAAO,2BAA2B;EAC3F,MAAM,iBAAiB,SAAS,KAAK,KAAK,sBAAsB;EAEhE,MAAM,WAAW,gBADS,OAAO,MAAM,GAAG,SAAS,SAAS,cAAc,CACzB,CAAC;EAClD,MAAM,0BAA0B,SAAS,QAAQ,sBAAsB;EAEvE,OAAO,SAAS,KAAK,YAAY,kBAAkB,yBAAyB,OAAO,CAAC;CACtF,CAAC,CAAC;CAEF,MAAM,gBAAgB,CACpB,GAAI,cAAc,iBAAiB,CAAC,GACpC,GAAG,YAAY,KAAK,CACtB;CAEA,MAAM,UAAU,OAAO,QAAQ,YAAY,aACvC,QAAQ,QAAQ,aAAa,IAC7B,QAAQ,UACN,CAAC,GAAG,eAAe,GAAG,QAAQ,OAAO,IACrC;CAEN,OAAO;EACL,MAAM,QAAQ,QAAQ;EACtB;CACF;AACF"}
|
package/package.json
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@w5s/eslint-config-ignore",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Shared ESLint ignore configuration generator",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"eslint",
|
|
7
|
+
"config",
|
|
8
|
+
"ignore"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://github.com/w5s/project-config/blob/main/packages/eslint-config-ignore#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/w5s/project-config/issues"
|
|
13
|
+
},
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+ssh@github.com:w5s/project-config.git",
|
|
17
|
+
"directory": "packages/eslint-config-ignore"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"author": "Julien Polo <julien.polo@gmail.com>",
|
|
21
|
+
"type": "module",
|
|
22
|
+
"exports": {
|
|
23
|
+
".": {
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/index.d.ts",
|
|
26
|
+
"default": "./dist/index.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"./dist/*": "./dist/*"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist/",
|
|
33
|
+
"src/",
|
|
34
|
+
"index.js",
|
|
35
|
+
"index.d.ts",
|
|
36
|
+
"!*.d.ts.map",
|
|
37
|
+
"!**/*.spec.*",
|
|
38
|
+
"!**/__tests__/**"
|
|
39
|
+
],
|
|
40
|
+
"scripts": {
|
|
41
|
+
"postpack": "clean-package restore"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"find-up": "^8.0.0",
|
|
45
|
+
"parse-gitignore": "^2.0.0"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"eslint": "9.x || 10.x",
|
|
49
|
+
"typescript": "4.x || 5.x || 6.x"
|
|
50
|
+
},
|
|
51
|
+
"peerDependenciesMeta": {
|
|
52
|
+
"eslint": {
|
|
53
|
+
"optional": true
|
|
54
|
+
},
|
|
55
|
+
"typescript": {
|
|
56
|
+
"optional": true
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"node": ">=22.0.0"
|
|
61
|
+
},
|
|
62
|
+
"publishConfig": {
|
|
63
|
+
"access": "public"
|
|
64
|
+
},
|
|
65
|
+
"sideEffect": false,
|
|
66
|
+
"gitHead": "fc447207d2af5368f809a9a90d0e4056344b812a"
|
|
67
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export const defaultIgnores = [
|
|
2
|
+
// Lock files
|
|
3
|
+
'**/package-lock.json',
|
|
4
|
+
'**/yarn.lock',
|
|
5
|
+
'**/pnpm-lock.yaml',
|
|
6
|
+
'**/bun.lockb',
|
|
7
|
+
|
|
8
|
+
// Commonly ignored
|
|
9
|
+
'**/output',
|
|
10
|
+
'**/.output',
|
|
11
|
+
'**/coverage',
|
|
12
|
+
'**/temp',
|
|
13
|
+
'**/.temp',
|
|
14
|
+
'**/tmp',
|
|
15
|
+
'**/.tmp',
|
|
16
|
+
'**/.cache',
|
|
17
|
+
|
|
18
|
+
// Well known extensions to ignore
|
|
19
|
+
'**/*.min.*',
|
|
20
|
+
'**/*.timestamp-*.mjs',
|
|
21
|
+
|
|
22
|
+
// Framework specific temporary folder
|
|
23
|
+
'.go/',
|
|
24
|
+
'.pnpm-store/',
|
|
25
|
+
'**/.vitepress/cache',
|
|
26
|
+
'**/.vite-inspect',
|
|
27
|
+
'**/.history',
|
|
28
|
+
'**/.nuxt',
|
|
29
|
+
'**/.next',
|
|
30
|
+
'**/.svelte-kit',
|
|
31
|
+
'**/.vercel',
|
|
32
|
+
'**/.idea',
|
|
33
|
+
'**/.yarn',
|
|
34
|
+
'**/__snapshots__/**',
|
|
35
|
+
|
|
36
|
+
// git submodules (makefile-core / makefile-ci)
|
|
37
|
+
'.modules/',
|
|
38
|
+
|
|
39
|
+
// AI related
|
|
40
|
+
'**/.context',
|
|
41
|
+
'**/.claude',
|
|
42
|
+
'**/.agents',
|
|
43
|
+
'**/.*/skills',
|
|
44
|
+
];
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import nodePath from 'node:path';
|
|
3
|
+
import process from 'node:process';
|
|
4
|
+
import { defaultIgnores } from './defaultIgnores.js';
|
|
5
|
+
import { ignoreFileParse } from './internal/ignoreFileParse.js';
|
|
6
|
+
import { ignoreFileFind } from './internal/ignoreFileFind.js';
|
|
7
|
+
import { ignoreRuleResolve } from './internal/ignoreRuleResolve.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Create a new eslint configuration object
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // eslint.config.js
|
|
15
|
+
* export default [
|
|
16
|
+
* await eslintIgnores({
|
|
17
|
+
* ignores: [
|
|
18
|
+
* // Add custom paths here
|
|
19
|
+
* ]
|
|
20
|
+
* })
|
|
21
|
+
* ];
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* @param options
|
|
25
|
+
*/
|
|
26
|
+
export async function eslintIgnores(options: ESLintIgnoreOptions = {}): Promise<ESLintIgnoreConfig> {
|
|
27
|
+
const cwd = options.cwd ?? process.cwd();
|
|
28
|
+
const recommended = options.recommended ?? true;
|
|
29
|
+
const ignoreFilePaths = await ignoreFileFind(cwd);
|
|
30
|
+
const ignoreGlobs = (await Promise.all(ignoreFilePaths.map(async (ignoreFilePathRelative) => {
|
|
31
|
+
const ignoreFilePath = nodePath.join(cwd, ignoreFilePathRelative);
|
|
32
|
+
const ignoreFileContent = String(await fs.promises.readFile(ignoreFilePath));
|
|
33
|
+
const patterns = ignoreFileParse(ignoreFileContent);
|
|
34
|
+
const ignoreDirectoryRelative = nodePath.dirname(ignoreFilePathRelative);
|
|
35
|
+
|
|
36
|
+
return patterns.map((pattern) => ignoreRuleResolve(ignoreDirectoryRelative, pattern));
|
|
37
|
+
})));
|
|
38
|
+
|
|
39
|
+
const mergedIgnores = [
|
|
40
|
+
...(recommended ? defaultIgnores : []),
|
|
41
|
+
...ignoreGlobs.flat(),
|
|
42
|
+
];
|
|
43
|
+
|
|
44
|
+
const ignores = typeof options.ignores === 'function'
|
|
45
|
+
? options.ignores(mergedIgnores)
|
|
46
|
+
: options.ignores
|
|
47
|
+
? [...mergedIgnores, ...options.ignores]
|
|
48
|
+
: mergedIgnores;
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
name: options.name ?? 'w5s/eslint-ignore',
|
|
52
|
+
ignores,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export interface ESLintIgnoreConfig {
|
|
57
|
+
/**
|
|
58
|
+
* The configuration name
|
|
59
|
+
*/
|
|
60
|
+
name: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* The file globs to ignore
|
|
64
|
+
*/
|
|
65
|
+
ignores: Array<string>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface ESLintIgnoreOptions {
|
|
69
|
+
/**
|
|
70
|
+
* Override configuration name
|
|
71
|
+
*/
|
|
72
|
+
name?: ESLintIgnoreConfig['name'];
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Override current working directory
|
|
76
|
+
*/
|
|
77
|
+
cwd?: string;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Override or customize ignore patterns.
|
|
81
|
+
* - If passed an array, it appends patterns to the merged ignore list.
|
|
82
|
+
* - If passed a function, it receives the merged list and returns the final array.
|
|
83
|
+
*/
|
|
84
|
+
ignores?: ESLintIgnoreConfig['ignores'] | ((ignores: ESLintIgnoreConfig['ignores']) => ESLintIgnoreConfig['ignores']);
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Include recommended settings and default ignored files
|
|
88
|
+
*/
|
|
89
|
+
recommended?: boolean | undefined;
|
|
90
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import nodePath from 'node:path';
|
|
2
|
+
import { findUp } from 'find-up';
|
|
3
|
+
|
|
4
|
+
export async function ignoreFileFind(cwd: string): Promise<Array<string>> {
|
|
5
|
+
const files = await Promise.all(
|
|
6
|
+
[
|
|
7
|
+
findUp(nodePath.join('', '.gitignore'), { cwd }),
|
|
8
|
+
// TODO: refactor as generic exploration
|
|
9
|
+
findUp(nodePath.join('android', '.gitignore'), { cwd }),
|
|
10
|
+
findUp(nodePath.join('ios', '.gitignore'), { cwd }),
|
|
11
|
+
],
|
|
12
|
+
);
|
|
13
|
+
|
|
14
|
+
return files
|
|
15
|
+
.filter((filePath): filePath is string => filePath !== undefined)
|
|
16
|
+
.map((filePath) => nodePath.relative(cwd, filePath));
|
|
17
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import nodePath from 'node:path';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a raw ignore rule from a `.gitignore` file into a path
|
|
5
|
+
* relative to the configured working directory.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```ts
|
|
9
|
+
* import { ignoreRuleResolve } from './internal/ignoreRuleResolve.js';
|
|
10
|
+
*
|
|
11
|
+
* ignoreRuleResolve('.', 'dist'); // 'dist'
|
|
12
|
+
* ignoreRuleResolve('.', '/dist'); // 'dist'
|
|
13
|
+
* ignoreRuleResolve('android', 'android-build'); // 'android/android-build'
|
|
14
|
+
* ignoreRuleResolve('android', '!android-build'); // '!android/android-build'
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* @internal
|
|
18
|
+
* @param prefix A path prefix that points to the directory containing the `.gitignore` file.
|
|
19
|
+
* @param rule The raw ignore rule parsed from `.gitignore`.
|
|
20
|
+
* @returns A normalized ignore pattern relative to the root `cwd`.
|
|
21
|
+
*/
|
|
22
|
+
export function ignoreRuleResolve(prefix: string, rule: string) {
|
|
23
|
+
const negated = rule.startsWith('!');
|
|
24
|
+
const normalizedPattern = negated ? rule.slice(1) : rule;
|
|
25
|
+
const trimmedPattern = normalizedPattern.startsWith('/')
|
|
26
|
+
? normalizedPattern.slice(1)
|
|
27
|
+
: normalizedPattern;
|
|
28
|
+
const relativeIgnorePath = nodePath.join(prefix, trimmedPattern);
|
|
29
|
+
|
|
30
|
+
return negated ? `!${relativeIgnorePath}` : relativeIgnorePath;
|
|
31
|
+
}
|
package/src/meta.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export const meta = Object.freeze({
|
|
2
|
+
// @ts-ignore - these variables are injected at build time
|
|
3
|
+
name: (typeof __PACKAGE_NAME__ === 'undefined' ? '' : __PACKAGE_NAME__) as string,
|
|
4
|
+
// @ts-ignore - these variables are injected at build time
|
|
5
|
+
version: (typeof __PACKAGE_VERSION__ === 'undefined' ? '' : __PACKAGE_VERSION__) as string,
|
|
6
|
+
// @ts-ignore - these variables are injected at build time
|
|
7
|
+
buildNumber: 1 as number, // (typeof __PACKAGE_BUILD_NUMBER__ === 'undefined' ? 0 : __PACKAGE_BUILD_NUMBER__) as number,
|
|
8
|
+
});
|