@kurateh/eslint-plugin 0.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/README.md +8 -0
- package/dist/index.d.mts +1165 -0
- package/dist/index.d.ts +1165 -0
- package/dist/index.js +411 -0
- package/dist/index.mjs +400 -0
- package/package.json +55 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import react from 'eslint-plugin-react';
|
|
3
|
+
import reactHook from 'eslint-plugin-react-hooks';
|
|
4
|
+
import globals from 'globals';
|
|
5
|
+
import importPlugin from 'eslint-plugin-import';
|
|
6
|
+
import tseslint from 'typescript-eslint';
|
|
7
|
+
import { readFileSync, existsSync } from 'node:fs';
|
|
8
|
+
import { join, dirname, relative } from 'node:path';
|
|
9
|
+
import { ESLintUtils } from '@typescript-eslint/utils';
|
|
10
|
+
import js from '@eslint/js';
|
|
11
|
+
import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
|
|
12
|
+
import unusedImportsPlugin from 'eslint-plugin-unused-imports';
|
|
13
|
+
|
|
14
|
+
createRequire(import.meta.url);
|
|
15
|
+
var __defProp = Object.defineProperty;
|
|
16
|
+
var __defProps = Object.defineProperties;
|
|
17
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
18
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
19
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
20
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
21
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
22
|
+
var __spreadValues = (a, b) => {
|
|
23
|
+
for (var prop in b || (b = {}))
|
|
24
|
+
if (__hasOwnProp.call(b, prop))
|
|
25
|
+
__defNormalProp(a, prop, b[prop]);
|
|
26
|
+
if (__getOwnPropSymbols)
|
|
27
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
28
|
+
if (__propIsEnum.call(b, prop))
|
|
29
|
+
__defNormalProp(a, prop, b[prop]);
|
|
30
|
+
}
|
|
31
|
+
return a;
|
|
32
|
+
};
|
|
33
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
34
|
+
var createRule = ESLintUtils.RuleCreator.withoutDocs;
|
|
35
|
+
|
|
36
|
+
// src/rules/import-path.ts
|
|
37
|
+
var TS_CONFIG_FILE_NAMES = ["tsconfig.path.json", "tsconfig.json"];
|
|
38
|
+
var has = (map, path) => {
|
|
39
|
+
let inner = map;
|
|
40
|
+
for (const step of path.split(".")) {
|
|
41
|
+
inner = inner[step];
|
|
42
|
+
if (inner === void 0) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
var findFilePath = (filename, initialPath) => {
|
|
49
|
+
let dir = initialPath;
|
|
50
|
+
do {
|
|
51
|
+
dir = dirname(dir);
|
|
52
|
+
} while (!existsSync(join(dir, filename)) && dir !== "/");
|
|
53
|
+
const filePath = join(dir, filename);
|
|
54
|
+
if (!existsSync(filePath)) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
return filePath;
|
|
58
|
+
};
|
|
59
|
+
var getAbsolutePathInfo = (fileName) => {
|
|
60
|
+
for (const configPath of TS_CONFIG_FILE_NAMES) {
|
|
61
|
+
const filePath = findFilePath(configPath, fileName);
|
|
62
|
+
if (filePath === void 0) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const baseDir = dirname(filePath);
|
|
66
|
+
const tsPathConfig = JSON.parse(
|
|
67
|
+
readFileSync(filePath, {
|
|
68
|
+
encoding: "utf-8"
|
|
69
|
+
})
|
|
70
|
+
);
|
|
71
|
+
const result = {
|
|
72
|
+
baseUrl: "",
|
|
73
|
+
paths: {}
|
|
74
|
+
};
|
|
75
|
+
if (has(tsPathConfig, "compilerOptions.baseUrl")) {
|
|
76
|
+
result.baseUrl = join(baseDir, tsPathConfig.compilerOptions.baseUrl);
|
|
77
|
+
}
|
|
78
|
+
if (has(tsPathConfig, "compilerOptions.paths")) {
|
|
79
|
+
result.paths = Object.fromEntries(
|
|
80
|
+
Object.entries(tsPathConfig.compilerOptions.paths).map(
|
|
81
|
+
([key, value]) => [
|
|
82
|
+
key.replace(/\/\*$/, "/"),
|
|
83
|
+
value.map((path) => join(baseDir, path).replace(/\/\*$/, "/"))
|
|
84
|
+
]
|
|
85
|
+
)
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
return result;
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
};
|
|
92
|
+
var import_path_default = createRule({
|
|
93
|
+
meta: {
|
|
94
|
+
type: "suggestion",
|
|
95
|
+
fixable: "code",
|
|
96
|
+
messages: {
|
|
97
|
+
shouldBeRelativePath: 'When importing a child module, you must use the relative path. Use "{{expectedPath}}" instead of "{{source}}".',
|
|
98
|
+
shouldBeAbsolutePath: 'When importing a parent module, you must use the absolute path. Use "{{expectedPath}}" instead of "{{source}}".'
|
|
99
|
+
},
|
|
100
|
+
schema: [],
|
|
101
|
+
docs: {
|
|
102
|
+
description: "Enforce import path according to the location of the imported file."
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
defaultOptions: [],
|
|
106
|
+
create: (context) => {
|
|
107
|
+
return {
|
|
108
|
+
ImportDeclaration: (node) => {
|
|
109
|
+
const fileName = context.getFilename();
|
|
110
|
+
const absolutePathInfo = getAbsolutePathInfo(fileName);
|
|
111
|
+
if (absolutePathInfo === void 0) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const source = node.source.value;
|
|
115
|
+
if (source.startsWith("..")) {
|
|
116
|
+
const sourceAbsolutePath2 = join(dirname(fileName), source);
|
|
117
|
+
for (const [alias, paths] of Object.entries(absolutePathInfo.paths)) {
|
|
118
|
+
for (const path of paths) {
|
|
119
|
+
if (sourceAbsolutePath2.startsWith(path)) {
|
|
120
|
+
const expectedPath2 = sourceAbsolutePath2.replace(path, alias);
|
|
121
|
+
context.report({
|
|
122
|
+
node,
|
|
123
|
+
messageId: "shouldBeAbsolutePath",
|
|
124
|
+
data: {
|
|
125
|
+
expectedPath: expectedPath2,
|
|
126
|
+
source
|
|
127
|
+
},
|
|
128
|
+
fix(fixer) {
|
|
129
|
+
return fixer.replaceText(node.source, `"${expectedPath2}"`);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
let sourceAbsolutePath;
|
|
139
|
+
for (const [alias, paths] of Object.entries(absolutePathInfo.paths)) {
|
|
140
|
+
for (const path of paths) {
|
|
141
|
+
if (source.startsWith(alias)) {
|
|
142
|
+
sourceAbsolutePath = join(path, source.replace(alias, ""));
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (sourceAbsolutePath !== void 0) {
|
|
147
|
+
break;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
if (sourceAbsolutePath === void 0) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const sourceRelativePath = relative(
|
|
154
|
+
dirname(fileName),
|
|
155
|
+
sourceAbsolutePath
|
|
156
|
+
);
|
|
157
|
+
if (sourceRelativePath.startsWith("..")) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const expectedPath = "./" + sourceRelativePath;
|
|
161
|
+
context.report({
|
|
162
|
+
node,
|
|
163
|
+
messageId: "shouldBeRelativePath",
|
|
164
|
+
data: {
|
|
165
|
+
expectedPath,
|
|
166
|
+
source
|
|
167
|
+
},
|
|
168
|
+
fix(fixer) {
|
|
169
|
+
return fixer.replaceText(node.source, `"${expectedPath}"`);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// src/rules/index.ts
|
|
179
|
+
var rules_default = {
|
|
180
|
+
"import-path": import_path_default
|
|
181
|
+
};
|
|
182
|
+
var recommended_default = [
|
|
183
|
+
js.configs.recommended,
|
|
184
|
+
importPlugin.flatConfigs.recommended,
|
|
185
|
+
eslintPluginPrettierRecommended,
|
|
186
|
+
{
|
|
187
|
+
languageOptions: {
|
|
188
|
+
ecmaVersion: 2020,
|
|
189
|
+
sourceType: "module",
|
|
190
|
+
globals: __spreadValues(__spreadValues(__spreadValues({}, globals.es2017), globals.browser), globals.node)
|
|
191
|
+
},
|
|
192
|
+
plugins: {
|
|
193
|
+
"unused-imports": unusedImportsPlugin
|
|
194
|
+
},
|
|
195
|
+
ignores: ["node_modules/", "dist/", "build/", "coverage/"],
|
|
196
|
+
rules: {
|
|
197
|
+
// eslint
|
|
198
|
+
"object-shorthand": 1,
|
|
199
|
+
"no-unused-vars": [
|
|
200
|
+
1,
|
|
201
|
+
{
|
|
202
|
+
ignoreRestSiblings: true,
|
|
203
|
+
vars: "all",
|
|
204
|
+
args: "after-used",
|
|
205
|
+
argsIgnorePattern: "^_",
|
|
206
|
+
varsIgnorePattern: "^_"
|
|
207
|
+
}
|
|
208
|
+
],
|
|
209
|
+
"no-param-reassign": [
|
|
210
|
+
2,
|
|
211
|
+
{
|
|
212
|
+
props: true,
|
|
213
|
+
ignorePropertyModificationsForRegex: ["^draft$", "Draft$"]
|
|
214
|
+
}
|
|
215
|
+
],
|
|
216
|
+
camelcase: [1, { allow: ["^\\w*_[A-Z]*$"] }],
|
|
217
|
+
"no-var": 2,
|
|
218
|
+
// prettier
|
|
219
|
+
"prettier/prettier": [
|
|
220
|
+
1,
|
|
221
|
+
{
|
|
222
|
+
trailingComma: "all",
|
|
223
|
+
tabWidth: 2,
|
|
224
|
+
semi: true,
|
|
225
|
+
singleQuote: false,
|
|
226
|
+
endOfLine: "auto"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
usePrettierrc: false
|
|
230
|
+
}
|
|
231
|
+
],
|
|
232
|
+
// import
|
|
233
|
+
"import/no-unresolved": 0,
|
|
234
|
+
"import/no-extraneous-dependencies": [
|
|
235
|
+
2,
|
|
236
|
+
{
|
|
237
|
+
devDependencies: [
|
|
238
|
+
"**/*.test.*",
|
|
239
|
+
"**/*.stories.*",
|
|
240
|
+
"**/*.config.*",
|
|
241
|
+
"**/*.spec.*"
|
|
242
|
+
]
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
"import/order": [
|
|
246
|
+
1,
|
|
247
|
+
{
|
|
248
|
+
alphabetize: {
|
|
249
|
+
order: "asc",
|
|
250
|
+
caseInsensitive: true
|
|
251
|
+
},
|
|
252
|
+
"newlines-between": "always",
|
|
253
|
+
groups: [
|
|
254
|
+
"builtin",
|
|
255
|
+
"external",
|
|
256
|
+
"internal",
|
|
257
|
+
["parent", "sibling", "index"]
|
|
258
|
+
],
|
|
259
|
+
pathGroups: [
|
|
260
|
+
{
|
|
261
|
+
pattern: "~*/**",
|
|
262
|
+
group: "internal"
|
|
263
|
+
},
|
|
264
|
+
{
|
|
265
|
+
pattern: "@*/**",
|
|
266
|
+
group: "internal"
|
|
267
|
+
}
|
|
268
|
+
]
|
|
269
|
+
}
|
|
270
|
+
],
|
|
271
|
+
// unused-imports
|
|
272
|
+
"unused-imports/no-unused-imports": 2
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
];
|
|
276
|
+
|
|
277
|
+
// src/configs/typescript.ts
|
|
278
|
+
var typescript_default = [
|
|
279
|
+
...recommended_default,
|
|
280
|
+
// eslint-disable-next-line import/no-named-as-default-member
|
|
281
|
+
...tseslint.configs.recommended,
|
|
282
|
+
importPlugin.flatConfigs.typescript,
|
|
283
|
+
{
|
|
284
|
+
// ESLint config block에 file이 있으면 해당 파일을 검사할 차례가 와서야 plugin이 적용됨
|
|
285
|
+
// 따라서 이 Plugin을 끄려면 Config File에서 file: "~~"을 넣어야 됨
|
|
286
|
+
// 이 과정을 없애기 위해 plugin 적용을 앞서 진행
|
|
287
|
+
plugins: {
|
|
288
|
+
"@kurateh": { rules: rules_default, meta: { name: "@kurateh" } }
|
|
289
|
+
}
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
files: ["**/*.ts", "**/*.tsx", "**/*.mts", "**/*.cts"],
|
|
293
|
+
settings: {
|
|
294
|
+
"import/resolver": {
|
|
295
|
+
typescript: {
|
|
296
|
+
alwaysTryTypes: true,
|
|
297
|
+
// always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
|
|
298
|
+
// Choose from one of the "project" configs below or omit to use <root>/tsconfig.json by default
|
|
299
|
+
// use <root>/path/to/folder/tsconfig.json
|
|
300
|
+
project: "tsconfig.json"
|
|
301
|
+
// Multiple tsconfigs (Useful for monorepos)
|
|
302
|
+
// use a glob pattern
|
|
303
|
+
// project: "packages/*/tsconfig.json",
|
|
304
|
+
// use an array
|
|
305
|
+
// project: [
|
|
306
|
+
// "packages/module-a/tsconfig.json",
|
|
307
|
+
// "packages/module-b/tsconfig.json"
|
|
308
|
+
// ],
|
|
309
|
+
// use an array of glob patterns
|
|
310
|
+
// project: [
|
|
311
|
+
// "packages/*/tsconfig.json",
|
|
312
|
+
// "other-packages/*/
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
},
|
|
316
|
+
rules: {
|
|
317
|
+
// eslint
|
|
318
|
+
"@kurateh/import-path": 1,
|
|
319
|
+
"object-shorthand": 1,
|
|
320
|
+
"no-unused-vars": 0,
|
|
321
|
+
"@typescript-eslint/no-unused-vars": [
|
|
322
|
+
1,
|
|
323
|
+
{
|
|
324
|
+
ignoreRestSiblings: true,
|
|
325
|
+
vars: "all",
|
|
326
|
+
args: "after-used",
|
|
327
|
+
argsIgnorePattern: "^_",
|
|
328
|
+
varsIgnorePattern: "^_"
|
|
329
|
+
}
|
|
330
|
+
],
|
|
331
|
+
"@typescript-eslint/consistent-type-imports": [
|
|
332
|
+
1,
|
|
333
|
+
{
|
|
334
|
+
fixStyle: "inline-type-imports"
|
|
335
|
+
}
|
|
336
|
+
],
|
|
337
|
+
"no-param-reassign": [
|
|
338
|
+
2,
|
|
339
|
+
{
|
|
340
|
+
props: true,
|
|
341
|
+
ignorePropertyModificationsForRegex: ["^draft$", "Draft$"]
|
|
342
|
+
}
|
|
343
|
+
],
|
|
344
|
+
camelcase: [1, { allow: ["^\\w*_[A-Z]*$"] }],
|
|
345
|
+
"no-var": 2,
|
|
346
|
+
"import-plugin/no-unresolved": 0
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
];
|
|
350
|
+
|
|
351
|
+
// src/configs/react.ts
|
|
352
|
+
var _a, _b;
|
|
353
|
+
var react_default = [
|
|
354
|
+
...typescript_default,
|
|
355
|
+
(_b = (_a = react.configs.flat) == null ? void 0 : _a.recommended) != null ? _b : {},
|
|
356
|
+
{
|
|
357
|
+
plugins: { "react-hooks": reactHook },
|
|
358
|
+
files: ["**/*.{js,jsx,mjs,cjs,ts,tsx}"],
|
|
359
|
+
languageOptions: {
|
|
360
|
+
parserOptions: {
|
|
361
|
+
ecmaFeatures: {
|
|
362
|
+
jsx: true
|
|
363
|
+
}
|
|
364
|
+
},
|
|
365
|
+
globals: __spreadValues({}, globals.browser)
|
|
366
|
+
},
|
|
367
|
+
rules: __spreadProps(__spreadValues({}, reactHook.configs.recommended.rules), {
|
|
368
|
+
"react/react-in-jsx-scope": 0,
|
|
369
|
+
"react/function-component-definition": [
|
|
370
|
+
2,
|
|
371
|
+
{
|
|
372
|
+
namedComponents: "arrow-function",
|
|
373
|
+
unnamedComponents: "arrow-function"
|
|
374
|
+
}
|
|
375
|
+
],
|
|
376
|
+
"react/jsx-curly-brace-presence": [
|
|
377
|
+
1,
|
|
378
|
+
{
|
|
379
|
+
props: "never",
|
|
380
|
+
children: "never"
|
|
381
|
+
}
|
|
382
|
+
],
|
|
383
|
+
"react/prop-types": 0,
|
|
384
|
+
"react/require-default-props": 0,
|
|
385
|
+
"react/display-name": 0
|
|
386
|
+
})
|
|
387
|
+
}
|
|
388
|
+
];
|
|
389
|
+
|
|
390
|
+
// src/index.ts
|
|
391
|
+
var index_default = {
|
|
392
|
+
configs: {
|
|
393
|
+
recommended: recommended_default,
|
|
394
|
+
typescript: typescript_default,
|
|
395
|
+
react: react_default
|
|
396
|
+
},
|
|
397
|
+
rules: rules_default
|
|
398
|
+
};
|
|
399
|
+
|
|
400
|
+
export { index_default as default };
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kurateh/eslint-plugin",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"exports": {
|
|
5
|
+
".": {
|
|
6
|
+
"import": "./dist/index.mjs",
|
|
7
|
+
"require": "./dist/index.js"
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"keywords": [
|
|
14
|
+
"eslint",
|
|
15
|
+
"plugin"
|
|
16
|
+
],
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"engines": {
|
|
19
|
+
"node": ">=22"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@kurateh/eslint-plugin": "file:",
|
|
23
|
+
"@types/node": "^22.10.2",
|
|
24
|
+
"@types/react": "^19.0.2",
|
|
25
|
+
"eslint": "^9.17.0",
|
|
26
|
+
"prettier": "^3.4.2",
|
|
27
|
+
"react": "^19.0.0",
|
|
28
|
+
"tsup": "^8.3.5",
|
|
29
|
+
"typescript": "^5.7.2"
|
|
30
|
+
},
|
|
31
|
+
"dependencies": {
|
|
32
|
+
"@eslint/js": "^9.17.0",
|
|
33
|
+
"@typescript-eslint/eslint-plugin": "^8.18.1",
|
|
34
|
+
"@typescript-eslint/parser": "^8.18.1",
|
|
35
|
+
"@typescript-eslint/utils": "^8.18.1",
|
|
36
|
+
"eslint-config-prettier": "^9.1.0",
|
|
37
|
+
"eslint-import-resolver-typescript": "^3.7.0",
|
|
38
|
+
"eslint-plugin-import": "^2.31.0",
|
|
39
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
40
|
+
"eslint-plugin-react": "^7.37.2",
|
|
41
|
+
"eslint-plugin-react-hooks": "^5.1.0",
|
|
42
|
+
"eslint-plugin-unused-imports": "^4.1.4",
|
|
43
|
+
"globals": "^15.14.0",
|
|
44
|
+
"typescript-eslint": "^8.18.1"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"eslint": ">=9"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build": "tsup",
|
|
51
|
+
"lint": "eslint .",
|
|
52
|
+
"type-check": "tsc --noEmit",
|
|
53
|
+
"version": "npm version"
|
|
54
|
+
}
|
|
55
|
+
}
|