@kurateh/eslint-plugin 2.0.0-beta.1 → 10.0.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.ko.md ADDED
@@ -0,0 +1,77 @@
1
+ # @kurateh/eslint-plugin
2
+
3
+ [English](./README.md) | 한국어
4
+
5
+ 개인적인 ESLint 규칙과 권장 설정을 포함하는 플러그인입니다.
6
+
7
+ ## 환경 요구 사항
8
+ - **NodeJS**: >=22
9
+ - **ESLint**: >= 9 (Flat Config 전용)
10
+ - **TypeScript**: >= 5.7.2
11
+
12
+ ## 1. 사용법
13
+
14
+ ### 설치
15
+ ```bash
16
+ pnpm add -D @kurateh/eslint-plugin
17
+ # 또는
18
+ npm install --save-dev @kurateh/eslint-plugin
19
+ ```
20
+
21
+ ### ESLint 설정 (`eslint.config.mjs`)
22
+ 이 플러그인은 ESLint Flat Config를 지원합니다. 다음과 같이 설정을 추가할 수 있습니다.
23
+
24
+ ```javascript
25
+ import kuratehPlugin from "@kurateh/eslint-plugin";
26
+
27
+ export default [
28
+ // 권장 설정 적용
29
+ kuratehPlugin.configs.recommended,
30
+
31
+ // React 환경인 경우 추가 설정 적용
32
+ kuratehPlugin.configs.react,
33
+
34
+ {
35
+ plugins: {
36
+ "@kurateh": kuratehPlugin,
37
+ },
38
+ rules: {
39
+ // 특정 규칙을 커스텀하고 싶은 경우
40
+ "@kurateh/import-path": "error",
41
+ },
42
+ },
43
+ ];
44
+ ```
45
+
46
+ ### 제공되는 설정
47
+ - `configs.recommended`: 일반적인 TypeScript 프로젝트를 위한 권장 설정 (Prettier 포함).
48
+ - `configs.react`: React 프로젝트를 위한 추가 설정 (Hooks 규칙 포함).
49
+
50
+ ## 2. GitHub Actions를 통한 배포 방법
51
+
52
+ 이 프로젝트는 GitHub Actions를 통해 NPM 저장소에 자동으로 배포됩니다.
53
+
54
+ ### 배포 절차
55
+ 1. **CHANGELOG.md 작성**: 배포 전에 `CHANGELOG.md`의 `## [Unreleased]` 섹션 아래에 이번 버전에 포함된 변경 사항을 기록합니다.
56
+ * **작성 예시**:
57
+ ```markdown
58
+ ## [Unreleased]
59
+ ### Added
60
+ - 새로운 규칙 `@kurateh/new-rule` 추가
61
+ ### Fixed
62
+ - `import-path` 규칙의 오탐 문제 수정
63
+ ```
64
+ 2. GitHub 저장소의 **Actions** 탭으로 이동합니다.
65
+ 3. 왼쪽 워크플로우 목록에서 **Release package**를 선택합니다.
66
+ 4. **Run workflow** 버튼을 클릭합니다.
67
+ 5. 다음 옵션 중 하나를 선택하거나 입력합니다:
68
+ - **Release type**: `patch`, `minor`, `major` 중 하나를 선택하여 버전을 올립니다.
69
+ - **Custom version (선택 사항)**: 특정 버전으로 바로 배포하고 싶을 때 입력합니다 (예: `10.0.0`). 이 값을 입력하면 `Release type`은 무시됩니다.
70
+ 6. **Run workflow**를 클릭하면 다음 과정이 자동으로 진행됩니다:
71
+ - 빌드 및 테스트 수행
72
+ - `CHANGELOG.md`의 `[Unreleased]` 섹션이 새 버전 번호로 업데이트됨
73
+ - `package.json` 버전 업데이트 및 변경 사항 커밋/태그 생성
74
+ - NPM 배포 및 GitHub Release 생성 (Changelog 내용이 Release 노트로 포함됨)
75
+
76
+ ---
77
+ **주의**: 배포를 위해서는 `NPMJS_ACCESS_TOKEN`이 GitHub Secrets에 등록되어 있어야 합니다.
package/README.md CHANGED
@@ -1,8 +1,77 @@
1
1
  # @kurateh/eslint-plugin
2
2
 
3
- ## Environment
4
- - NodeJS: >=22
5
- - ESLint: >= 9 (Flat Config)
6
- - Typescript: >= 5.7.2
3
+ English | [한국어](./README.ko.md)
7
4
 
8
- ## Publish
5
+ An ESLint plugin containing personal ESLint rules and recommended configurations.
6
+
7
+ ## Requirements
8
+ - **NodeJS**: >=22
9
+ - **ESLint**: >= 9 (Flat Config only)
10
+ - **TypeScript**: >= 5.7.2
11
+
12
+ ## 1. Usage
13
+
14
+ ### Installation
15
+ ```bash
16
+ pnpm add -D @kurateh/eslint-plugin
17
+ # or
18
+ npm install --save-dev @kurateh/eslint-plugin
19
+ ```
20
+
21
+ ### ESLint Configuration (`eslint.config.mjs`)
22
+ This plugin supports ESLint Flat Config. You can add configurations as follows:
23
+
24
+ ```javascript
25
+ import kuratehPlugin from "@kurateh/eslint-plugin";
26
+
27
+ export default [
28
+ // Apply recommended configuration
29
+ kuratehPlugin.configs.recommended,
30
+
31
+ // Apply additional configuration for React environments
32
+ kuratehPlugin.configs.react,
33
+
34
+ {
35
+ plugins: {
36
+ "@kurateh": kuratehPlugin,
37
+ },
38
+ rules: {
39
+ // Customize specific rules if needed
40
+ "@kurateh/import-path": "error",
41
+ },
42
+ },
43
+ ];
44
+ ```
45
+
46
+ ### Provided Configurations
47
+ - `configs.recommended`: Recommended configuration for general TypeScript projects (includes Prettier).
48
+ - `configs.react`: Additional configuration for React projects (includes React Hooks rules).
49
+
50
+ ## 2. Deployment via GitHub Actions
51
+
52
+ This project is automatically deployed to the NPM registry via GitHub Actions.
53
+
54
+ ### Deployment Process
55
+ 1. **Update CHANGELOG.md**: Before deployment, record the changes for the new version under the `## [Unreleased]` section in `CHANGELOG.md`.
56
+ * **Writing Example**:
57
+ ```markdown
58
+ ## [Unreleased]
59
+ ### Added
60
+ - New rule `@kurateh/new-rule`
61
+ ### Fixed
62
+ - Fixed false positive in `import-path` rule
63
+ ```
64
+ 2. Go to the **Actions** tab of the GitHub repository.
65
+ 3. Select **Release package** from the workflow list on the left.
66
+ 4. Click the **Run workflow** button.
67
+ 5. Select or enter one of the following options:
68
+ - **Release type**: Select one of `patch`, `minor`, `major` to bump the version.
69
+ - **Custom version (Optional)**: Enter a specific version to deploy immediately (e.g., `10.0.0`). If provided, `Release type` is ignored.
70
+ 6. Click **Run workflow** to trigger the following automated steps:
71
+ - Run build and tests.
72
+ - Update the `[Unreleased]` section in `CHANGELOG.md` to the new version number.
73
+ - Update the version in `package.json`, commit changes, and create a tag.
74
+ - Publish to NPM and create a GitHub Release (Changelog content will be used as Release notes).
75
+
76
+ ---
77
+ **Note**: `NPMJS_ACCESS_TOKEN` must be registered in GitHub Secrets for successful deployment.
@@ -1,40 +1,39 @@
1
- import { createRequire } from 'module';
2
- import react from 'eslint-plugin-react';
3
- import reactHooks from 'eslint-plugin-react-hooks';
4
- import globals from 'globals';
5
- import js from '@eslint/js';
6
- import importPlugin from 'eslint-plugin-import';
7
- import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
8
- import unusedImportsPlugin from 'eslint-plugin-unused-imports';
9
- import tseslint from 'typescript-eslint';
10
- import { readFileSync, existsSync } from 'fs';
11
- import { join, dirname, relative } from 'path';
12
- import { ESLintUtils } from '@typescript-eslint/utils';
1
+ 'use strict';
13
2
 
14
- createRequire(import.meta.url);
15
- var __defProp = Object.defineProperty;
16
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
17
- var __hasOwnProp = Object.prototype.hasOwnProperty;
18
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
19
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
20
- var __spreadValues = (a, b) => {
21
- for (var prop in b || (b = {}))
22
- if (__hasOwnProp.call(b, prop))
23
- __defNormalProp(a, prop, b[prop]);
24
- if (__getOwnPropSymbols)
25
- for (var prop of __getOwnPropSymbols(b)) {
26
- if (__propIsEnum.call(b, prop))
27
- __defNormalProp(a, prop, b[prop]);
28
- }
29
- return a;
30
- };
31
- var createRule = ESLintUtils.RuleCreator.withoutDocs;
3
+ var fs = require('fs');
4
+ var react = require('eslint-plugin-react');
5
+ var reactHooks = require('eslint-plugin-react-hooks');
6
+ var globals = require('globals');
7
+ var js = require('@eslint/js');
8
+ var importPlugin = require('eslint-plugin-import');
9
+ var eslintPluginPrettierRecommended = require('eslint-plugin-prettier/recommended');
10
+ var unusedImportsPlugin = require('eslint-plugin-unused-imports');
11
+ var tseslint = require('typescript-eslint');
12
+ var path = require('path');
13
+ var utils = require('@typescript-eslint/utils');
14
+
15
+ var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
16
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
17
+
18
+ var react__default = /*#__PURE__*/_interopDefault(react);
19
+ var reactHooks__default = /*#__PURE__*/_interopDefault(reactHooks);
20
+ var globals__default = /*#__PURE__*/_interopDefault(globals);
21
+ var js__default = /*#__PURE__*/_interopDefault(js);
22
+ var importPlugin__default = /*#__PURE__*/_interopDefault(importPlugin);
23
+ var eslintPluginPrettierRecommended__default = /*#__PURE__*/_interopDefault(eslintPluginPrettierRecommended);
24
+ var unusedImportsPlugin__default = /*#__PURE__*/_interopDefault(unusedImportsPlugin);
25
+ var tseslint__default = /*#__PURE__*/_interopDefault(tseslint);
26
+ var path__default = /*#__PURE__*/_interopDefault(path);
27
+
28
+ // src/index.ts
29
+ var createRule = utils.ESLintUtils.RuleCreator.withoutDocs;
32
30
 
33
31
  // src/rules/import-path.ts
32
+ var posix = path__default.default.posix;
34
33
  var TS_CONFIG_FILE_NAMES = ["tsconfig.path.json", "tsconfig.json"];
35
- var has = (map, path) => {
34
+ var has = (map, path2) => {
36
35
  let inner = map;
37
- for (const step of path.split(".")) {
36
+ for (const step of path2.split(".")) {
38
37
  inner = inner[step];
39
38
  if (inner === void 0) {
40
39
  return false;
@@ -42,28 +41,35 @@ var has = (map, path) => {
42
41
  }
43
42
  return true;
44
43
  };
44
+ var normalizePath = (p) => p.replace(/\\/g, "/");
45
45
  var findFilePath = (filename, initialPath) => {
46
46
  let dir = initialPath;
47
+ let lastDir;
47
48
  do {
48
- dir = dirname(dir);
49
- } while (!existsSync(join(dir, filename)) && dir !== "/");
50
- const filePath = join(dir, filename);
51
- if (!existsSync(filePath)) {
49
+ lastDir = dir;
50
+ dir = posix.dirname(dir);
51
+ } while (!fs.existsSync(path.join(dir, filename)) && dir !== lastDir);
52
+ const filePath = path.join(dir, filename);
53
+ if (!fs.existsSync(filePath)) {
52
54
  return;
53
55
  }
54
- return filePath;
56
+ return normalizePath(filePath);
55
57
  };
56
58
  var getAbsolutePathInfo = (fileName) => {
59
+ const normalizedFileName = normalizePath(fileName);
57
60
  for (const configPath of TS_CONFIG_FILE_NAMES) {
58
- const filePath = findFilePath(configPath, fileName);
61
+ const filePath = findFilePath(configPath, normalizedFileName);
59
62
  if (filePath === void 0) {
60
63
  continue;
61
64
  }
62
- const baseDir = dirname(filePath);
65
+ const baseDir = normalizePath(posix.dirname(filePath));
63
66
  const tsPathConfig = JSON.parse(
64
- readFileSync(filePath, {
67
+ fs.readFileSync(filePath, {
65
68
  encoding: "utf-8"
66
- }).replace(/("(?:[^"\\]|\\.)*")|\/\/.*/g, (_, string) => string || "").replace(
69
+ }).replace(
70
+ /("(?:[^"\\]|\\.)*")|\/\/.*/g,
71
+ (_, string) => string || ""
72
+ ).replace(
67
73
  /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,
68
74
  (_, string) => string || ""
69
75
  ).replace(/,(?=\s*[\]}])/g, "")
@@ -73,14 +79,18 @@ var getAbsolutePathInfo = (fileName) => {
73
79
  paths: {}
74
80
  };
75
81
  if (has(tsPathConfig, "compilerOptions.baseUrl")) {
76
- result.baseUrl = join(baseDir, tsPathConfig.compilerOptions.baseUrl);
82
+ result.baseUrl = normalizePath(
83
+ posix.join(baseDir, tsPathConfig.compilerOptions.baseUrl)
84
+ );
77
85
  }
78
86
  if (has(tsPathConfig, "compilerOptions.paths")) {
79
87
  result.paths = Object.fromEntries(
80
88
  Object.entries(tsPathConfig.compilerOptions.paths).map(
81
89
  ([key, value]) => [
82
90
  key.replace(/\/\*$/, "/"),
83
- value.map((path) => join(baseDir, path).replace(/\/\*$/, "/"))
91
+ value.map(
92
+ (path2) => normalizePath(posix.join(baseDir, path2)).replace(/\/\*$/, "/")
93
+ )
84
94
  ]
85
95
  )
86
96
  );
@@ -104,20 +114,22 @@ var import_path_default = createRule({
104
114
  },
105
115
  defaultOptions: [],
106
116
  create: (context) => {
117
+ const fileName = normalizePath(context.filename);
118
+ const absolutePathInfo = getAbsolutePathInfo(fileName);
107
119
  return {
108
120
  ImportDeclaration: (node) => {
109
- const fileName = context.getFilename();
110
- const absolutePathInfo = getAbsolutePathInfo(fileName);
111
121
  if (absolutePathInfo === void 0) {
112
122
  return;
113
123
  }
114
124
  const source = node.source.value;
115
125
  if (source.startsWith("..")) {
116
- const sourceAbsolutePath2 = join(dirname(fileName), source);
126
+ const sourceAbsolutePath2 = normalizePath(
127
+ posix.join(posix.dirname(fileName), source)
128
+ );
117
129
  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);
130
+ for (const path2 of paths) {
131
+ if (sourceAbsolutePath2.startsWith(path2)) {
132
+ const expectedPath2 = sourceAbsolutePath2.replace(path2, alias);
121
133
  context.report({
122
134
  node,
123
135
  messageId: "shouldBeAbsolutePath",
@@ -137,9 +149,11 @@ var import_path_default = createRule({
137
149
  }
138
150
  let sourceAbsolutePath;
139
151
  for (const [alias, paths] of Object.entries(absolutePathInfo.paths)) {
140
- for (const path of paths) {
152
+ for (const path2 of paths) {
141
153
  if (source.startsWith(alias)) {
142
- sourceAbsolutePath = join(path, source.replace(alias, ""));
154
+ sourceAbsolutePath = normalizePath(
155
+ posix.join(path2, source.replace(alias, ""))
156
+ );
143
157
  break;
144
158
  }
145
159
  }
@@ -150,9 +164,8 @@ var import_path_default = createRule({
150
164
  if (sourceAbsolutePath === void 0) {
151
165
  return;
152
166
  }
153
- const sourceRelativePath = relative(
154
- dirname(fileName),
155
- sourceAbsolutePath
167
+ const sourceRelativePath = normalizePath(
168
+ posix.relative(posix.dirname(fileName), sourceAbsolutePath)
156
169
  );
157
170
  if (sourceRelativePath.startsWith("..")) {
158
171
  return;
@@ -182,11 +195,11 @@ var rules_default = {
182
195
 
183
196
  // src/configs/recommended.ts
184
197
  var config = [
185
- js.configs.recommended,
186
- importPlugin.flatConfigs.recommended,
187
- eslintPluginPrettierRecommended,
188
- ...tseslint.configs.recommended,
189
- importPlugin.flatConfigs.typescript,
198
+ js__default.default.configs.recommended,
199
+ importPlugin__default.default.flatConfigs.recommended,
200
+ eslintPluginPrettierRecommended__default.default,
201
+ ...tseslint__default.default.configs.recommended,
202
+ importPlugin__default.default.flatConfigs.typescript,
190
203
  {
191
204
  // ESLint config block에 file이 있으면 해당 파일을 검사할 차례가 와서야 plugin이 적용됨
192
205
  // 따라서 이 Plugin을 끄려면 Config File에서 file: "~~"을 넣어야 됨
@@ -222,12 +235,16 @@ var config = [
222
235
  }
223
236
  },
224
237
  plugins: {
225
- "unused-imports": unusedImportsPlugin
238
+ "unused-imports": unusedImportsPlugin__default.default
226
239
  },
227
240
  languageOptions: {
228
241
  ecmaVersion: "latest",
229
242
  sourceType: "module",
230
- globals: __spreadValues(__spreadValues(__spreadValues({}, globals.es2017), globals.browser), globals.node)
243
+ globals: {
244
+ ...globals__default.default.es2017,
245
+ ...globals__default.default.browser,
246
+ ...globals__default.default.node
247
+ }
231
248
  },
232
249
  rules: {
233
250
  // eslint
@@ -323,8 +340,8 @@ var recommended_default = config;
323
340
  // src/configs/react.ts
324
341
  var config2 = [
325
342
  ...recommended_default,
326
- react.configs.flat.recommended,
327
- reactHooks.configs.flat.recommended,
343
+ react__default.default.configs.flat.recommended,
344
+ reactHooks__default.default.configs.flat.recommended,
328
345
  {
329
346
  files: ["**/*.{js,jsx,mjs,cjs,ts,tsx}"],
330
347
  languageOptions: {
@@ -333,7 +350,9 @@ var config2 = [
333
350
  jsx: true
334
351
  }
335
352
  },
336
- globals: __spreadValues({}, globals.browser)
353
+ globals: {
354
+ ...globals__default.default.browser
355
+ }
337
356
  },
338
357
  rules: {
339
358
  "react/react-in-jsx-scope": 0,
@@ -361,7 +380,15 @@ var config2 = [
361
380
  var react_default = config2;
362
381
 
363
382
  // src/index.ts
383
+ var pkg = JSON.parse(
384
+ fs.readFileSync(new URL("../package.json", (typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('index.cjs', document.baseURI).href))), "utf-8")
385
+ );
364
386
  var plugin = {
387
+ meta: {
388
+ name: "eslint-plugin",
389
+ namespace: "@kurateh",
390
+ version: pkg.version
391
+ },
365
392
  configs: {
366
393
  recommended: recommended_default,
367
394
  react: react_default
@@ -370,4 +397,4 @@ var plugin = {
370
397
  };
371
398
  var index_default = plugin;
372
399
 
373
- export { index_default as default };
400
+ module.exports = index_default;
@@ -0,0 +1,5 @@
1
+ import { ESLint } from 'eslint';
2
+
3
+ declare const plugin: ESLint.Plugin;
4
+
5
+ export { plugin as default };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,5 @@
1
- import * as eslint from 'eslint';
1
+ import { ESLint } from 'eslint';
2
2
 
3
- declare const plugin: {
4
- configs: {
5
- recommended: (eslint.Linter.Config<eslint.Linter.RulesRecord> | {
6
- readonly rules: Readonly<eslint.Linter.RulesRecord>;
7
- })[];
8
- react: (eslint.Linter.Config<eslint.Linter.RulesRecord> | {
9
- readonly rules: Readonly<eslint.Linter.RulesRecord>;
10
- })[];
11
- };
12
- rules: Record<string, eslint.Rule.RuleModule>;
13
- };
3
+ declare const plugin: ESLint.Plugin;
14
4
 
15
5
  export { plugin as default };
package/dist/index.js CHANGED
@@ -1,51 +1,25 @@
1
- 'use strict';
1
+ import { createRequire } from 'module';
2
+ import { readFileSync, existsSync } from 'fs';
3
+ import react from 'eslint-plugin-react';
4
+ import reactHooks from 'eslint-plugin-react-hooks';
5
+ import globals from 'globals';
6
+ import js from '@eslint/js';
7
+ import importPlugin from 'eslint-plugin-import';
8
+ import eslintPluginPrettierRecommended from 'eslint-plugin-prettier/recommended';
9
+ import unusedImportsPlugin from 'eslint-plugin-unused-imports';
10
+ import tseslint from 'typescript-eslint';
11
+ import path, { join } from 'path';
12
+ import { ESLintUtils } from '@typescript-eslint/utils';
2
13
 
3
- var react = require('eslint-plugin-react');
4
- var reactHooks = require('eslint-plugin-react-hooks');
5
- var globals = require('globals');
6
- var js = require('@eslint/js');
7
- var importPlugin = require('eslint-plugin-import');
8
- var eslintPluginPrettierRecommended = require('eslint-plugin-prettier/recommended');
9
- var unusedImportsPlugin = require('eslint-plugin-unused-imports');
10
- var tseslint = require('typescript-eslint');
11
- var fs = require('fs');
12
- var path = require('path');
13
- var utils = require('@typescript-eslint/utils');
14
-
15
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
16
-
17
- var react__default = /*#__PURE__*/_interopDefault(react);
18
- var reactHooks__default = /*#__PURE__*/_interopDefault(reactHooks);
19
- var globals__default = /*#__PURE__*/_interopDefault(globals);
20
- var js__default = /*#__PURE__*/_interopDefault(js);
21
- var importPlugin__default = /*#__PURE__*/_interopDefault(importPlugin);
22
- var eslintPluginPrettierRecommended__default = /*#__PURE__*/_interopDefault(eslintPluginPrettierRecommended);
23
- var unusedImportsPlugin__default = /*#__PURE__*/_interopDefault(unusedImportsPlugin);
24
- var tseslint__default = /*#__PURE__*/_interopDefault(tseslint);
25
-
26
- var __defProp = Object.defineProperty;
27
- var __getOwnPropSymbols = Object.getOwnPropertySymbols;
28
- var __hasOwnProp = Object.prototype.hasOwnProperty;
29
- var __propIsEnum = Object.prototype.propertyIsEnumerable;
30
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
31
- var __spreadValues = (a, b) => {
32
- for (var prop in b || (b = {}))
33
- if (__hasOwnProp.call(b, prop))
34
- __defNormalProp(a, prop, b[prop]);
35
- if (__getOwnPropSymbols)
36
- for (var prop of __getOwnPropSymbols(b)) {
37
- if (__propIsEnum.call(b, prop))
38
- __defNormalProp(a, prop, b[prop]);
39
- }
40
- return a;
41
- };
42
- var createRule = utils.ESLintUtils.RuleCreator.withoutDocs;
14
+ createRequire(import.meta.url);
15
+ var createRule = ESLintUtils.RuleCreator.withoutDocs;
43
16
 
44
17
  // src/rules/import-path.ts
18
+ var posix = path.posix;
45
19
  var TS_CONFIG_FILE_NAMES = ["tsconfig.path.json", "tsconfig.json"];
46
- var has = (map, path) => {
20
+ var has = (map, path2) => {
47
21
  let inner = map;
48
- for (const step of path.split(".")) {
22
+ for (const step of path2.split(".")) {
49
23
  inner = inner[step];
50
24
  if (inner === void 0) {
51
25
  return false;
@@ -53,28 +27,35 @@ var has = (map, path) => {
53
27
  }
54
28
  return true;
55
29
  };
30
+ var normalizePath = (p) => p.replace(/\\/g, "/");
56
31
  var findFilePath = (filename, initialPath) => {
57
32
  let dir = initialPath;
33
+ let lastDir;
58
34
  do {
59
- dir = path.dirname(dir);
60
- } while (!fs.existsSync(path.join(dir, filename)) && dir !== "/");
61
- const filePath = path.join(dir, filename);
62
- if (!fs.existsSync(filePath)) {
35
+ lastDir = dir;
36
+ dir = posix.dirname(dir);
37
+ } while (!existsSync(join(dir, filename)) && dir !== lastDir);
38
+ const filePath = join(dir, filename);
39
+ if (!existsSync(filePath)) {
63
40
  return;
64
41
  }
65
- return filePath;
42
+ return normalizePath(filePath);
66
43
  };
67
44
  var getAbsolutePathInfo = (fileName) => {
45
+ const normalizedFileName = normalizePath(fileName);
68
46
  for (const configPath of TS_CONFIG_FILE_NAMES) {
69
- const filePath = findFilePath(configPath, fileName);
47
+ const filePath = findFilePath(configPath, normalizedFileName);
70
48
  if (filePath === void 0) {
71
49
  continue;
72
50
  }
73
- const baseDir = path.dirname(filePath);
51
+ const baseDir = normalizePath(posix.dirname(filePath));
74
52
  const tsPathConfig = JSON.parse(
75
- fs.readFileSync(filePath, {
53
+ readFileSync(filePath, {
76
54
  encoding: "utf-8"
77
- }).replace(/("(?:[^"\\]|\\.)*")|\/\/.*/g, (_, string) => string || "").replace(
55
+ }).replace(
56
+ /("(?:[^"\\]|\\.)*")|\/\/.*/g,
57
+ (_, string) => string || ""
58
+ ).replace(
78
59
  /("(?:[^"\\]|\\.)*")|\/\*[\s\S]*?\*\//g,
79
60
  (_, string) => string || ""
80
61
  ).replace(/,(?=\s*[\]}])/g, "")
@@ -84,14 +65,18 @@ var getAbsolutePathInfo = (fileName) => {
84
65
  paths: {}
85
66
  };
86
67
  if (has(tsPathConfig, "compilerOptions.baseUrl")) {
87
- result.baseUrl = path.join(baseDir, tsPathConfig.compilerOptions.baseUrl);
68
+ result.baseUrl = normalizePath(
69
+ posix.join(baseDir, tsPathConfig.compilerOptions.baseUrl)
70
+ );
88
71
  }
89
72
  if (has(tsPathConfig, "compilerOptions.paths")) {
90
73
  result.paths = Object.fromEntries(
91
74
  Object.entries(tsPathConfig.compilerOptions.paths).map(
92
75
  ([key, value]) => [
93
76
  key.replace(/\/\*$/, "/"),
94
- value.map((path$1) => path.join(baseDir, path$1).replace(/\/\*$/, "/"))
77
+ value.map(
78
+ (path2) => normalizePath(posix.join(baseDir, path2)).replace(/\/\*$/, "/")
79
+ )
95
80
  ]
96
81
  )
97
82
  );
@@ -115,20 +100,22 @@ var import_path_default = createRule({
115
100
  },
116
101
  defaultOptions: [],
117
102
  create: (context) => {
103
+ const fileName = normalizePath(context.filename);
104
+ const absolutePathInfo = getAbsolutePathInfo(fileName);
118
105
  return {
119
106
  ImportDeclaration: (node) => {
120
- const fileName = context.getFilename();
121
- const absolutePathInfo = getAbsolutePathInfo(fileName);
122
107
  if (absolutePathInfo === void 0) {
123
108
  return;
124
109
  }
125
110
  const source = node.source.value;
126
111
  if (source.startsWith("..")) {
127
- const sourceAbsolutePath2 = path.join(path.dirname(fileName), source);
112
+ const sourceAbsolutePath2 = normalizePath(
113
+ posix.join(posix.dirname(fileName), source)
114
+ );
128
115
  for (const [alias, paths] of Object.entries(absolutePathInfo.paths)) {
129
- for (const path of paths) {
130
- if (sourceAbsolutePath2.startsWith(path)) {
131
- const expectedPath2 = sourceAbsolutePath2.replace(path, alias);
116
+ for (const path2 of paths) {
117
+ if (sourceAbsolutePath2.startsWith(path2)) {
118
+ const expectedPath2 = sourceAbsolutePath2.replace(path2, alias);
132
119
  context.report({
133
120
  node,
134
121
  messageId: "shouldBeAbsolutePath",
@@ -148,9 +135,11 @@ var import_path_default = createRule({
148
135
  }
149
136
  let sourceAbsolutePath;
150
137
  for (const [alias, paths] of Object.entries(absolutePathInfo.paths)) {
151
- for (const path$1 of paths) {
138
+ for (const path2 of paths) {
152
139
  if (source.startsWith(alias)) {
153
- sourceAbsolutePath = path.join(path$1, source.replace(alias, ""));
140
+ sourceAbsolutePath = normalizePath(
141
+ posix.join(path2, source.replace(alias, ""))
142
+ );
154
143
  break;
155
144
  }
156
145
  }
@@ -161,9 +150,8 @@ var import_path_default = createRule({
161
150
  if (sourceAbsolutePath === void 0) {
162
151
  return;
163
152
  }
164
- const sourceRelativePath = path.relative(
165
- path.dirname(fileName),
166
- sourceAbsolutePath
153
+ const sourceRelativePath = normalizePath(
154
+ posix.relative(posix.dirname(fileName), sourceAbsolutePath)
167
155
  );
168
156
  if (sourceRelativePath.startsWith("..")) {
169
157
  return;
@@ -193,11 +181,11 @@ var rules_default = {
193
181
 
194
182
  // src/configs/recommended.ts
195
183
  var config = [
196
- js__default.default.configs.recommended,
197
- importPlugin__default.default.flatConfigs.recommended,
198
- eslintPluginPrettierRecommended__default.default,
199
- ...tseslint__default.default.configs.recommended,
200
- importPlugin__default.default.flatConfigs.typescript,
184
+ js.configs.recommended,
185
+ importPlugin.flatConfigs.recommended,
186
+ eslintPluginPrettierRecommended,
187
+ ...tseslint.configs.recommended,
188
+ importPlugin.flatConfigs.typescript,
201
189
  {
202
190
  // ESLint config block에 file이 있으면 해당 파일을 검사할 차례가 와서야 plugin이 적용됨
203
191
  // 따라서 이 Plugin을 끄려면 Config File에서 file: "~~"을 넣어야 됨
@@ -233,12 +221,16 @@ var config = [
233
221
  }
234
222
  },
235
223
  plugins: {
236
- "unused-imports": unusedImportsPlugin__default.default
224
+ "unused-imports": unusedImportsPlugin
237
225
  },
238
226
  languageOptions: {
239
227
  ecmaVersion: "latest",
240
228
  sourceType: "module",
241
- globals: __spreadValues(__spreadValues(__spreadValues({}, globals__default.default.es2017), globals__default.default.browser), globals__default.default.node)
229
+ globals: {
230
+ ...globals.es2017,
231
+ ...globals.browser,
232
+ ...globals.node
233
+ }
242
234
  },
243
235
  rules: {
244
236
  // eslint
@@ -334,8 +326,8 @@ var recommended_default = config;
334
326
  // src/configs/react.ts
335
327
  var config2 = [
336
328
  ...recommended_default,
337
- react__default.default.configs.flat.recommended,
338
- reactHooks__default.default.configs.flat.recommended,
329
+ react.configs.flat.recommended,
330
+ reactHooks.configs.flat.recommended,
339
331
  {
340
332
  files: ["**/*.{js,jsx,mjs,cjs,ts,tsx}"],
341
333
  languageOptions: {
@@ -344,7 +336,9 @@ var config2 = [
344
336
  jsx: true
345
337
  }
346
338
  },
347
- globals: __spreadValues({}, globals__default.default.browser)
339
+ globals: {
340
+ ...globals.browser
341
+ }
348
342
  },
349
343
  rules: {
350
344
  "react/react-in-jsx-scope": 0,
@@ -372,7 +366,15 @@ var config2 = [
372
366
  var react_default = config2;
373
367
 
374
368
  // src/index.ts
369
+ var pkg = JSON.parse(
370
+ readFileSync(new URL("../package.json", import.meta.url), "utf-8")
371
+ );
375
372
  var plugin = {
373
+ meta: {
374
+ name: "eslint-plugin",
375
+ namespace: "@kurateh",
376
+ version: pkg.version
377
+ },
376
378
  configs: {
377
379
  recommended: recommended_default,
378
380
  react: react_default
@@ -381,4 +383,4 @@ var plugin = {
381
383
  };
382
384
  var index_default = plugin;
383
385
 
384
- module.exports = index_default;
386
+ export { index_default as default };
package/package.json CHANGED
@@ -1,10 +1,18 @@
1
1
  {
2
2
  "name": "@kurateh/eslint-plugin",
3
- "version": "2.0.0-beta.1",
3
+ "version": "10.0.0",
4
+ "type": "module",
5
+ "author": {
6
+ "name": "kurateh",
7
+ "email": "me@kurateh.com"
8
+ },
9
+ "repository": {
10
+ "url": "https://github.com/kurateh/eslint-plugin"
11
+ },
4
12
  "exports": {
5
13
  ".": {
6
- "import": "./dist/index.mjs",
7
- "require": "./dist/index.js"
14
+ "import": "./dist/index.js",
15
+ "require": "./dist/index.cjs"
8
16
  }
9
17
  },
10
18
  "files": [
@@ -20,28 +28,30 @@
20
28
  },
21
29
  "devDependencies": {
22
30
  "@kurateh/eslint-plugin": "file:",
23
- "@types/node": "^22.10.2",
24
- "@types/react": "^19.2.7",
25
- "eslint": "~9.17.0",
26
- "prettier": "^3.7.4",
27
- "react": "^19.2.3",
31
+ "@types/node": "~24",
32
+ "@types/react": "^19.2.14",
33
+ "@typescript-eslint/rule-tester": "^8.59.0",
34
+ "eslint": "~10.2.1",
35
+ "prettier": "^3.8.3",
36
+ "react": "^19.2.5",
28
37
  "tsup": "^8.5.1",
29
- "typescript": "^5.9.3"
38
+ "typescript": "^6.0.3",
39
+ "vitest": "^4.1.5"
30
40
  },
31
41
  "dependencies": {
32
- "@eslint/js": "^9.39.2",
33
- "@typescript-eslint/eslint-plugin": "^8.50.0",
34
- "@typescript-eslint/parser": "^8.50.0",
35
- "@typescript-eslint/utils": "^8.50.0",
42
+ "@eslint/js": "^10.0.1",
43
+ "@typescript-eslint/eslint-plugin": "^8.59.0",
44
+ "@typescript-eslint/parser": "^8.59.0",
45
+ "@typescript-eslint/utils": "^8.59.0",
36
46
  "eslint-config-prettier": "^10.1.8",
37
47
  "eslint-import-resolver-typescript": "^4.4.4",
38
48
  "eslint-plugin-import": "^2.32.0",
39
- "eslint-plugin-prettier": "^5.5.4",
49
+ "eslint-plugin-prettier": "^5.5.5",
40
50
  "eslint-plugin-react": "^7.37.5",
41
- "eslint-plugin-react-hooks": "^7.0.1",
42
- "eslint-plugin-unused-imports": "^4.3.0",
43
- "globals": "^16.5.0",
44
- "typescript-eslint": "^8.50.0"
51
+ "eslint-plugin-react-hooks": "^7.1.1",
52
+ "eslint-plugin-unused-imports": "^4.4.1",
53
+ "globals": "^17.5.0",
54
+ "typescript-eslint": "^8.59.0"
45
55
  },
46
56
  "peerDependencies": {
47
57
  "eslint": ">=9"
@@ -49,7 +59,9 @@
49
59
  "scripts": {
50
60
  "build": "tsup",
51
61
  "lint": "eslint .",
62
+ "format": "prettier --write .",
52
63
  "type-check": "tsc --noEmit",
64
+ "test": "vitest run",
53
65
  "version": "npm version"
54
66
  }
55
67
  }
package/dist/index.d.mts DELETED
@@ -1,15 +0,0 @@
1
- import * as eslint from 'eslint';
2
-
3
- declare const plugin: {
4
- configs: {
5
- recommended: (eslint.Linter.Config<eslint.Linter.RulesRecord> | {
6
- readonly rules: Readonly<eslint.Linter.RulesRecord>;
7
- })[];
8
- react: (eslint.Linter.Config<eslint.Linter.RulesRecord> | {
9
- readonly rules: Readonly<eslint.Linter.RulesRecord>;
10
- })[];
11
- };
12
- rules: Record<string, eslint.Rule.RuleModule>;
13
- };
14
-
15
- export { plugin as default };