routie dev init since i didn't adhere to any proper guidance up until now
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Anthony Fu <https://github.com/antfu>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
# eslint-config-flat-gitignore
|
||||
|
||||
[![npm version][npm-version-src]][npm-version-href]
|
||||
[![npm downloads][npm-downloads-src]][npm-downloads-href]
|
||||
[![bundle][bundle-src]][bundle-href]
|
||||
[![JSDocs][jsdocs-src]][jsdocs-href]
|
||||
[![License][license-src]][license-href]
|
||||
|
||||
`.gitignore` support for [ESLint Flat Config](https://eslint.org/docs/latest/use/configure/configuration-files-new).
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
npm i -D eslint-config-flat-gitignore
|
||||
```
|
||||
|
||||
```js
|
||||
// eslint.config.js
|
||||
import gitignore from 'eslint-config-flat-gitignore'
|
||||
|
||||
export default [
|
||||
// recommended putting it at the first
|
||||
gitignore(),
|
||||
// your other configs here
|
||||
]
|
||||
```
|
||||
|
||||
By default it will only looks for `.gitignore` but NOT `.eslintignore`, as we would recommended move away from `.eslintignore` to declare directly in `eslint.config.js` for single source of truth. If you still want it, you can pass the `files` option to specify the files to look for.
|
||||
|
||||
```js
|
||||
gitignore({
|
||||
files: [
|
||||
'.gitignore',
|
||||
'.eslintignore',
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
By default, this plugin throws if any of the ignore files are missing. This can be disabled by passing setting the `strict` option to `false`.
|
||||
|
||||
```js
|
||||
gitignore({
|
||||
files: [
|
||||
'.gitignore',
|
||||
'.eslintignore',
|
||||
],
|
||||
strict: false,
|
||||
})
|
||||
```
|
||||
|
||||
By default, this plugin will try to look up the directory tree and match the first `.gitignore` file. You can disable this by setting the `root` option to `true`, or specify the `files` option to a specific path.
|
||||
|
||||
```js
|
||||
gitignore({
|
||||
root: true
|
||||
})
|
||||
```
|
||||
|
||||
If you want to include recursive `.gitignore` files (for example in monorepos), enable the `recursive` option.
|
||||
|
||||
```js
|
||||
gitignore({
|
||||
recursive: true,
|
||||
})
|
||||
```
|
||||
|
||||
If you want recursive discovery but need to skip specific directory names, pass an object to `recursive` with `skipDirs`.
|
||||
|
||||
```js
|
||||
gitignore({
|
||||
recursive: {
|
||||
// Skip any directory with this name at any depth
|
||||
skipDirs: ['dist', 'coverage'],
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
`skipDirs` matches directory names (not paths) and applies in addition to the built-in skipped directories: `.git` and `node_modules`.
|
||||
|
||||
This plugin will also automatically detect git submodule file `.gitmodules` and ignore all files under the submodule dirs. If you want to disable or customize this behavior, you can pass the `filesGitModules` option.
|
||||
|
||||
<!-- eslint-skip -->
|
||||
```js
|
||||
gitignore({
|
||||
filesGitModules: [], // disable
|
||||
filesGitModules: ['path/to/.gitmodules'], // customize
|
||||
})
|
||||
```
|
||||
|
||||
## Sponsors
|
||||
|
||||
<p align="center">
|
||||
<a href="https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg">
|
||||
<img src='https://cdn.jsdelivr.net/gh/antfu/static/sponsors.svg' alt='Sponsors' />
|
||||
</a>
|
||||
</p>
|
||||
|
||||
## License
|
||||
|
||||
[MIT](./LICENSE) License © 2023-PRESENT [Anthony Fu](https://github.com/antfu)
|
||||
|
||||
<!-- Badges -->
|
||||
|
||||
[npm-version-src]: https://img.shields.io/npm/v/eslint-config-flat-gitignore?style=flat&colorA=080f12&colorB=1fa669
|
||||
[npm-version-href]: https://npmjs.com/package/eslint-config-flat-gitignore
|
||||
[npm-downloads-src]: https://img.shields.io/npm/dm/eslint-config-flat-gitignore?style=flat&colorA=080f12&colorB=1fa669
|
||||
[npm-downloads-href]: https://npmjs.com/package/eslint-config-flat-gitignore
|
||||
[bundle-src]: https://img.shields.io/bundlephobia/minzip/eslint-config-flat-gitignore?style=flat&colorA=080f12&colorB=1fa669&label=minzip
|
||||
[bundle-href]: https://bundlephobia.com/result?p=eslint-config-flat-gitignore
|
||||
[license-src]: https://img.shields.io/github/license/antfu/eslint-config-flat-gitignore.svg?style=flat&colorA=080f12&colorB=1fa669
|
||||
[license-href]: https://github.com/antfu/eslint-config-flat-gitignore/blob/main/LICENSE
|
||||
[jsdocs-src]: https://img.shields.io/badge/jsdocs-reference-080f12?style=flat&colorA=080f12&colorB=1fa669
|
||||
[jsdocs-href]: https://www.jsdocs.io/package/eslint-config-flat-gitignore
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
interface FlatGitignoreOptions {
|
||||
/**
|
||||
* Name of the configuration.
|
||||
* @default 'gitignore'
|
||||
*/
|
||||
name?: string;
|
||||
/**
|
||||
* Path to `.gitignore` files, or files with compatible formats like `.eslintignore`.
|
||||
* @default ['.gitignore'] // or findUpSync('.gitignore')
|
||||
*/
|
||||
files?: string | string[];
|
||||
/**
|
||||
* Path to `.gitmodules` file.
|
||||
* @default ['.gitmodules'] // or findUpSync('.gitmodules')
|
||||
*/
|
||||
filesGitModules?: string | string[];
|
||||
/**
|
||||
* Throw an error if gitignore file not found.
|
||||
* @default true
|
||||
*/
|
||||
strict?: boolean;
|
||||
/**
|
||||
* Mark the current working directory as the root directory,
|
||||
* disable searching for `.gitignore` files in parent directories.
|
||||
*
|
||||
* This option is not effective when `files` is explicitly specified.
|
||||
* @default false
|
||||
*/
|
||||
root?: boolean;
|
||||
/**
|
||||
* Current working directory.
|
||||
* Used to resolve relative paths.
|
||||
* @default process.cwd()
|
||||
*/
|
||||
cwd?: string;
|
||||
/**
|
||||
* Also include recursive `.gitignore` files under `cwd`.
|
||||
*
|
||||
* This option is useful for monorepos or projects that keep
|
||||
* per-folder `.gitignore` files.
|
||||
*
|
||||
* Pass `{ skipDirs: ['name'] }` to skip directory names while
|
||||
* scanning recursively. `skipDirs` matches by directory name at
|
||||
* any depth (not by path), and is applied in addition to `.git`
|
||||
* and `node_modules`.
|
||||
* @default false
|
||||
*/
|
||||
recursive?: boolean | {
|
||||
skipDirs: string[];
|
||||
};
|
||||
}
|
||||
interface FlatConfigItem {
|
||||
ignores: string[];
|
||||
name?: string;
|
||||
}
|
||||
declare function ignore(options?: FlatGitignoreOptions): FlatConfigItem;
|
||||
|
||||
export { ignore as default };
|
||||
export type { FlatConfigItem, FlatGitignoreOptions };
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
import fs from 'node:fs';
|
||||
import path, { join, resolve, relative, dirname } from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { convertIgnorePatternToMinimatch } from '@eslint/compat';
|
||||
import 'node:fs/promises';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
|
||||
function toArray(array) {
|
||||
array = array ?? [];
|
||||
return Array.isArray(array) ? array : [array];
|
||||
}
|
||||
|
||||
const toPath = urlOrPath => urlOrPath instanceof URL ? fileURLToPath(urlOrPath) : urlOrPath;
|
||||
|
||||
function findUpSync(name, {
|
||||
cwd = process.cwd(),
|
||||
type = 'file',
|
||||
stopAt,
|
||||
} = {}) {
|
||||
let directory = path.resolve(toPath(cwd) ?? '');
|
||||
const {root} = path.parse(directory);
|
||||
stopAt = path.resolve(directory, toPath(stopAt) ?? root);
|
||||
const isAbsoluteName = path.isAbsolute(name);
|
||||
|
||||
while (directory) {
|
||||
const filePath = isAbsoluteName ? name : path.join(directory, name);
|
||||
|
||||
try {
|
||||
const stats = fs.statSync(filePath, {throwIfNoEntry: false});
|
||||
if ((type === 'file' && stats?.isFile()) || (type === 'directory' && stats?.isDirectory())) {
|
||||
return filePath;
|
||||
}
|
||||
} catch {}
|
||||
|
||||
if (directory === stopAt || directory === root) {
|
||||
break;
|
||||
}
|
||||
|
||||
directory = path.dirname(directory);
|
||||
}
|
||||
}
|
||||
|
||||
const GITIGNORE = ".gitignore";
|
||||
const GITMODULES = ".gitmodules";
|
||||
const RE_NEWLINE = /\r?\n/u;
|
||||
const RE_PARENT_PATH = /^(?:\.\.\/)+$/;
|
||||
const RE_PATH_SEP = /[/\\]/;
|
||||
const RE_SUBMODULE_PATH = /path\s*=\s*(.+)/u;
|
||||
function ignore(options = {}) {
|
||||
const ignores = [];
|
||||
const {
|
||||
cwd = process.cwd(),
|
||||
root = false,
|
||||
recursive = false,
|
||||
files: _files = root ? GITIGNORE : findUpSync(GITIGNORE, { cwd }) || [],
|
||||
filesGitModules: _filesGitModules = root ? fs.existsSync(join(cwd, GITMODULES)) ? GITMODULES : [] : findUpSync(GITMODULES, { cwd }) || [],
|
||||
strict = true
|
||||
} = options;
|
||||
const files = new Set(toArray(_files).map((file) => resolve(cwd, file)));
|
||||
if (recursive) {
|
||||
const additionalIgnoreDirs = typeof recursive === "boolean" ? [] : recursive.skipDirs;
|
||||
for (const file of findNestedFiles(cwd, GITIGNORE, additionalIgnoreDirs))
|
||||
files.add(file);
|
||||
}
|
||||
const filesList = [...files];
|
||||
const filesGitModules = toArray(_filesGitModules).map((file) => resolve(cwd, file));
|
||||
for (const file of filesList) {
|
||||
let content = "";
|
||||
try {
|
||||
content = fs.readFileSync(file, "utf8");
|
||||
} catch (error) {
|
||||
if (strict)
|
||||
throw error;
|
||||
continue;
|
||||
}
|
||||
const relativePath = relative(cwd, dirname(file)).replaceAll("\\", "/");
|
||||
const globs = content.split(RE_NEWLINE).filter((line) => line && !line.startsWith("#")).map((line) => convertIgnorePatternToMinimatch(line)).map((glob) => relativeMinimatch(glob, relativePath, cwd)).filter((glob) => glob !== null);
|
||||
ignores.push(...globs);
|
||||
}
|
||||
for (const file of filesGitModules) {
|
||||
let content = "";
|
||||
try {
|
||||
content = fs.readFileSync(file, "utf8");
|
||||
} catch (error) {
|
||||
if (strict)
|
||||
throw error;
|
||||
continue;
|
||||
}
|
||||
const dirs = parseGitSubmodules(content);
|
||||
ignores.push(...dirs.map((dir) => `${dir}/**`));
|
||||
}
|
||||
if (strict && filesList.length === 0)
|
||||
throw new Error("No .gitignore file found");
|
||||
return {
|
||||
name: options.name || "gitignore",
|
||||
ignores
|
||||
};
|
||||
}
|
||||
function findNestedFiles(cwd, fileName, additionalIgnoreDirs) {
|
||||
const files = [];
|
||||
const directoriesToSkip = /* @__PURE__ */ new Set([".git", "node_modules", ...additionalIgnoreDirs]);
|
||||
const queue = [cwd];
|
||||
while (queue.length) {
|
||||
const directory = queue.shift();
|
||||
const entries = fs.readdirSync(directory, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
const absolutePath = join(directory, entry.name);
|
||||
if (entry.isFile() && entry.name === fileName)
|
||||
files.push(absolutePath);
|
||||
if (entry.isDirectory() && !directoriesToSkip.has(entry.name))
|
||||
queue.push(absolutePath);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
function relativeMinimatch(pattern, relativePath, cwd) {
|
||||
if (["", ".", "/"].includes(relativePath))
|
||||
return pattern;
|
||||
const negated = pattern.startsWith("!") ? "!" : "";
|
||||
let cleanPattern = negated ? pattern.slice(1) : pattern;
|
||||
if (!relativePath.endsWith("/"))
|
||||
relativePath = `${relativePath}/`;
|
||||
const isParent = relativePath.startsWith("..");
|
||||
if (!isParent)
|
||||
return `${negated}${relativePath}${cleanPattern}`;
|
||||
if (!RE_PARENT_PATH.test(relativePath))
|
||||
throw new Error("The ignore file location should be either a parent or child directory");
|
||||
if (cleanPattern.startsWith("**"))
|
||||
return pattern;
|
||||
const parents = relative(resolve(cwd, relativePath), cwd).split(RE_PATH_SEP);
|
||||
while (parents.length && cleanPattern.startsWith(`${parents[0]}/`)) {
|
||||
cleanPattern = cleanPattern.slice(parents[0].length + 1);
|
||||
parents.shift();
|
||||
}
|
||||
if (cleanPattern.startsWith("**"))
|
||||
return `${negated}${cleanPattern}`;
|
||||
if (parents.length === 0)
|
||||
return `${negated}${cleanPattern}`;
|
||||
return null;
|
||||
}
|
||||
function parseGitSubmodules(content) {
|
||||
return content.split(RE_NEWLINE).map((line) => RE_SUBMODULE_PATH.exec(line)).filter((match) => match !== null).map((match) => match[1].trim());
|
||||
}
|
||||
|
||||
export { ignore as default };
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
{
|
||||
"name": "eslint-config-flat-gitignore",
|
||||
"type": "module",
|
||||
"version": "2.3.0",
|
||||
"description": ".gitignore support for ESLint Flat Config",
|
||||
"author": "Anthony Fu <anthonyfu117@hotmail.com>",
|
||||
"license": "MIT",
|
||||
"funding": "https://github.com/sponsors/antfu",
|
||||
"homepage": "https://github.com/antfu/eslint-config-flat-gitignore#readme",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/antfu/eslint-config-flat-gitignore.git"
|
||||
},
|
||||
"bugs": "https://github.com/antfu/eslint-config-flat-gitignore/issues",
|
||||
"keywords": [
|
||||
"eslint-config",
|
||||
"eslint-flat-config"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"exports": {
|
||||
".": "./dist/index.mjs"
|
||||
},
|
||||
"main": "./dist/index.mjs",
|
||||
"module": "./dist/index.mjs",
|
||||
"types": "./dist/index.d.mts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"peerDependencies": {
|
||||
"eslint": "^9.5.0 || ^10.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@eslint/compat": "^2.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@antfu/eslint-config": "^7.7.3",
|
||||
"@antfu/ni": "^30.0.0",
|
||||
"@antfu/utils": "^9.3.0",
|
||||
"@types/node": "^25.5.0",
|
||||
"bumpp": "^11.0.1",
|
||||
"eslint": "^10.1.0",
|
||||
"find-up-simple": "^1.0.1",
|
||||
"lint-staged": "^16.4.0",
|
||||
"pnpm": "^10.32.1",
|
||||
"simple-git-hooks": "^2.13.1",
|
||||
"tsx": "^4.21.0",
|
||||
"typescript": "^5.9.3",
|
||||
"unbuild": "^3.6.1",
|
||||
"vite": "^8.0.2",
|
||||
"vitest": "^4.1.1"
|
||||
},
|
||||
"simple-git-hooks": {
|
||||
"pre-commit": "pnpm lint-staged"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*": "eslint --fix"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "unbuild",
|
||||
"dev": "unbuild --stub",
|
||||
"lint": "eslint .",
|
||||
"release": "bumpp",
|
||||
"start": "tsx src/index.ts",
|
||||
"test": "vitest --pool=forks",
|
||||
"typecheck": "tsc --noEmit"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user