@simplysm/lint 13.0.99 → 14.0.1

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/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@simplysm/lint",
3
- "version": "13.0.99",
4
- "description": "Simplysm package - Lint configuration (ESLint)",
5
- "author": "simplysm",
3
+ "version": "14.0.1",
4
+ "description": "심플리즘 패키지 - ESLint plugin",
5
+ "author": "심플리즘",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
@@ -12,8 +12,7 @@
12
12
  "type": "module",
13
13
  "files": [
14
14
  "dist",
15
- "src",
16
- "tests"
15
+ "src"
17
16
  ],
18
17
  "sideEffects": false,
19
18
  "exports": {
@@ -27,19 +26,17 @@
27
26
  }
28
27
  },
29
28
  "dependencies": {
30
- "@typescript-eslint/utils": "^8.57.1",
29
+ "@typescript-eslint/utils": "^8.57.2",
30
+ "angular-eslint": "^21.3.1",
31
31
  "eslint": "^9.39.4",
32
32
  "eslint-import-resolver-typescript": "^4.4.4",
33
33
  "eslint-plugin-import": "^2.32.0",
34
- "eslint-plugin-solid": "^0.14.5",
35
- "eslint-plugin-tailwindcss": "^3.18.2",
36
34
  "eslint-plugin-unused-imports": "^4.4.1",
37
- "globals": "^17.4.0",
38
35
  "typescript": "^5.9.3",
39
- "typescript-eslint": "^8.57.1"
36
+ "typescript-eslint": "^8.57.2"
40
37
  },
41
38
  "devDependencies": {
42
- "@types/eslint-plugin-tailwindcss": "^3.17.0",
43
- "@typescript-eslint/rule-tester": "^8.57.1"
39
+ "@typescript-eslint/rule-tester": "^8.57.2",
40
+ "@types/node": "^20.19.37"
44
41
  }
45
42
  }
@@ -1,24 +1,11 @@
1
- import globals from "globals";
2
1
  import tseslint, { type FlatConfig } from "typescript-eslint";
2
+ import angular from "angular-eslint";
3
3
  import plugin from "./eslint-plugin";
4
4
  import importPlugin from "eslint-plugin-import";
5
5
  import unusedImportsPlugin from "eslint-plugin-unused-imports";
6
- import solidPlugin from "eslint-plugin-solid";
7
- import tailwindcssPlugin from "eslint-plugin-tailwindcss";
8
- import { defineConfig, globalIgnores } from "eslint/config";
9
6
  import { ESLint } from "eslint";
10
7
  import { fileURLToPath } from "url";
11
8
 
12
- //#region Common rules configuration
13
-
14
- /**
15
- * Common rules for JS/TS
16
- * - no-console: Prohibit console usage in production code (prevent performance degradation)
17
- * - no-warning-comments: Warn about TODO/FIXME comments (to check for incomplete code)
18
- * - eqeqeq: Enforce `===` usage (allow `== null` for null checks)
19
- * - no-self-compare: Prevent typos like `x === x`
20
- * - array-callback-return: Prevent missing return in map/filter, etc.
21
- */
22
9
  const commonRules: FlatConfig.Rules = {
23
10
  "no-console": "error",
24
11
  "no-warning-comments": "warn",
@@ -32,7 +19,7 @@ const noNodeBuiltinsRules: FlatConfig.Rules = {
32
19
  "error",
33
20
  {
34
21
  name: "Buffer",
35
- message: "Use Uint8Array. For complex operations, use BytesUtils from @simplysm/core-common.",
22
+ message: "Uint8Array 사용하세요. 복잡한 연산에는 @simplysm/core-common의 BytesUtils를 사용하세요.",
36
23
  },
37
24
  ],
38
25
  "no-restricted-imports": [
@@ -42,26 +29,21 @@ const noNodeBuiltinsRules: FlatConfig.Rules = {
42
29
  {
43
30
  name: "buffer",
44
31
  message:
45
- "Use Uint8Array. For complex operations, use BytesUtils from @simplysm/core-common.",
32
+ "Uint8Array 사용하세요. 복잡한 연산에는 @simplysm/core-common의 BytesUtils를 사용하세요.",
46
33
  },
47
34
  {
48
35
  name: "events",
49
- message: "Use EventEmitter from @simplysm/core-common.",
36
+ message: "@simplysm/core-common의 EventEmitter를 사용하세요.",
50
37
  },
51
38
  {
52
39
  name: "eventemitter3",
53
- message: "Use EventEmitter from @simplysm/core-common.",
40
+ message: "@simplysm/core-common의 EventEmitter를 사용하세요.",
54
41
  },
55
42
  ],
56
43
  },
57
44
  ],
58
45
  };
59
46
 
60
- /**
61
- * Unused import handling rules
62
- * - Auto-remove unused imports
63
- * - Allow unused variables/parameters with `_` prefix (e.g., `_unused`)
64
- */
65
47
  const unusedImportsRules: FlatConfig.Rules = {
66
48
  "unused-imports/no-unused-imports": "error",
67
49
  "unused-imports/no-unused-vars": [
@@ -75,29 +57,24 @@ const unusedImportsRules: FlatConfig.Rules = {
75
57
  ],
76
58
  };
77
59
 
78
- //#endregion
79
-
80
- export default defineConfig([
81
- globalIgnores([
82
- // Skip traversal itself in directory/** form
83
- "**/node_modules/**",
84
- "**/dist/**",
85
- "**/.*/**",
86
- "**/_*/**",
87
- ]),
60
+ export default tseslint.config(
61
+ {
62
+ ignores: [
63
+ // directory/** 형태의 순회 자체를 건너뜀
64
+ "**/node_modules/**",
65
+ "**/dist/**",
66
+ "**/.*/**",
67
+ "**/_*/**",
68
+ ],
69
+ },
88
70
  {
89
71
  languageOptions: {
90
- globals: {
91
- ...globals.node,
92
- ...globals.es2024,
93
- ...globals.browser,
94
- },
95
72
  ecmaVersion: 2024,
96
73
  sourceType: "module",
97
74
  },
98
75
  },
99
76
  {
100
- files: ["**/*.js", "**/*.jsx"],
77
+ files: ["**/*.js", "**/*.mjs", "**/*.cjs"],
101
78
  plugins: {
102
79
  "import": importPlugin,
103
80
  "@simplysm": plugin as unknown as ESLint.Plugin,
@@ -126,15 +103,17 @@ export default defineConfig([
126
103
  },
127
104
  ],
128
105
 
129
- // Common rules for JS/TS
106
+ // JS/TS 공통 규칙
130
107
  "@simplysm/no-subpath-imports-from-simplysm": "error",
131
108
  "@simplysm/no-hard-private": "error",
132
109
 
133
110
  ...noNodeBuiltinsRules,
134
111
  },
135
112
  },
113
+ ...angular.configs.tsRecommended,
136
114
  {
137
- files: ["**/*.ts", "**/*.tsx"],
115
+ files: ["**/*.ts"],
116
+ processor: angular.processInlineTemplates,
138
117
  plugins: {
139
118
  "@typescript-eslint": tseslint.plugin,
140
119
  "@simplysm": plugin as unknown as ESLint.Plugin,
@@ -187,16 +166,11 @@ export default defineConfig([
187
166
  ],
188
167
  "@typescript-eslint/prefer-readonly": "error",
189
168
 
190
- // Prevent mistakes: passing async function to void callback (prevent error loss)
191
- // - arguments: false → allow socket.on("event", async () => {}) (handled with internal try-catch)
192
- // - attributes: false → allow JSX event handlers (SolidJS compatible)
193
169
  "@typescript-eslint/no-misused-promises": [
194
170
  "error",
195
- { checksVoidReturn: { arguments: false, attributes: false } },
171
+ { checksVoidReturn: { arguments: false } },
196
172
  ],
197
- // Prevent mistakes: throwing non-Error objects (prevent stack trace loss)
198
173
  "@typescript-eslint/only-throw-error": "error",
199
- // Prevent mistakes: using delete on arrays (prevent sparse array bugs)
200
174
  "@typescript-eslint/no-array-delete": "error",
201
175
 
202
176
  "@simplysm/no-hard-private": "error",
@@ -206,80 +180,19 @@ export default defineConfig([
206
180
  ...unusedImportsRules,
207
181
  ...noNodeBuiltinsRules,
208
182
 
209
- "import/no-extraneous-dependencies": [
210
- "error",
211
- {
212
- devDependencies: [
213
- "**/lib/**",
214
- "**/eslint.config.ts",
215
- "**/simplysm.ts",
216
- "**/vitest.config.ts",
217
- "**/vitest-e2e.config.ts",
218
- "**/vitest.setup.ts",
219
- "**/vitest.setup.ts",
220
- ],
221
- },
222
- ],
183
+ "import/no-extraneous-dependencies": "error",
223
184
  },
224
185
  },
225
- // Test folders: allow root devDependencies (vitest, etc.)
226
186
  {
227
- files: [
228
- "**/tests/**/*.ts",
229
- "**/tests/**/*.tsx",
230
- "**/tests-e2e/**/*.ts",
231
- "**/tests-e2e/**/*.tsx",
232
- ],
187
+ files: ["**/*.html"],
188
+ extends: [...angular.configs.templateRecommended, ...angular.configs.templateAccessibility],
189
+ },
190
+ {
191
+ files: ["**/tests/**/*.ts"],
233
192
  rules: {
234
193
  "no-console": "off",
235
194
  "import/no-extraneous-dependencies": "off",
236
195
  "@simplysm/ts-no-throw-not-implemented-error": "off",
237
196
  },
238
197
  },
239
- // SolidJS TSX files: explicitly configure all rules (error)
240
- {
241
- files: ["**/*.ts", "**/*.tsx"],
242
- plugins: {
243
- solid: solidPlugin as unknown as ESLint.Plugin,
244
- tailwindcss: tailwindcssPlugin as unknown as ESLint.Plugin,
245
- },
246
- settings: {
247
- tailwindcss: {
248
- // Support template literal tags: recognize clsx`py-0.5 px-1.5` form
249
- tags: ["clsx"],
250
- },
251
- },
252
- rules: {
253
- // ─── Prevent mistakes ───
254
- "solid/reactivity": "off",
255
- "solid/no-destructure": "error", // Props destructuring → reactivity loss
256
- "solid/components-return-once": "error", // early return → bugs
257
- "solid/jsx-no-duplicate-props": "error", // Duplicate props
258
- "solid/jsx-no-undef": ["error", { typescriptEnabled: true }], // Undefined variables
259
- "solid/no-react-deps": "error", // React dependency array mistakes
260
- "solid/no-react-specific-props": "error", // React props mistakes (className, etc.)
261
-
262
- // ─── Security ───
263
- "solid/no-innerhtml": "error", // Prevent XSS
264
- "solid/jsx-no-script-url": "error", // Prevent javascript: URLs
265
-
266
- // ─── Tooling support ───
267
- "solid/jsx-uses-vars": "error", // Prevent false positives in unused import detection
268
-
269
- // ─── Conventions ───
270
- "solid/prefer-for": "error", // Recommend For component
271
- "solid/event-handlers": "error", // Event handler naming
272
- "solid/imports": "error", // Import consistency
273
- "solid/style-prop": "error", // style prop format
274
- "solid/self-closing-comp": "error", // Self-closing tags
275
-
276
- // ─── Tailwind CSS ───
277
- "tailwindcss/classnames-order": "warn", // Auto-sort class order
278
- "tailwindcss/enforces-negative-arbitrary-values": "error", // Unify negative arbitrary value format
279
- "tailwindcss/enforces-shorthand": "error", // Recommend shorthand usage
280
- "tailwindcss/no-contradicting-classname": "error", // Prohibit conflicting classes (p-2 p-4, etc.)
281
- "tailwindcss/no-custom-classname": "error", // Prohibit custom classes not in Tailwind
282
- "tailwindcss/no-unnecessary-arbitrary-value": "error", // Prohibit unnecessary arbitrary values
283
- },
284
- },
285
- ]);
198
+ );
@@ -18,27 +18,27 @@ function isClassMemberWithAccessibility(
18
18
  }
19
19
 
20
20
  /**
21
- * ESLint rule that restricts ECMAScript private fields (`#field`) and enforces TypeScript `private` keyword usage.
21
+ * ECMAScript private 필드(`#field`) 제한하고 TypeScript `private` 키워드 사용을 강제하는 ESLint 규칙.
22
22
  *
23
23
  * @remarks
24
- * This rule checks:
25
- * - Class field declarations: `#field`
26
- * - Class method declarations: `#method()`
27
- * - Class accessor declarations: `accessor #field`
28
- * - Member access expressions: `this.#field`
24
+ * 규칙이 검사하는 항목:
25
+ * - 클래스 필드 선언: `#field`
26
+ * - 클래스 메서드 선언: `#method()`
27
+ * - 클래스 접근자 선언: `accessor #field`
28
+ * - 멤버 접근 표현식: `this.#field`
29
29
  */
30
30
  export default createRule({
31
31
  name: "no-hard-private",
32
32
  meta: {
33
33
  type: "problem",
34
34
  docs: {
35
- description: 'Enforces TypeScript "private _" style instead of hard private fields (#).',
35
+ description: 'hard private 필드(#) 대신 TypeScript "private _" 스타일을 강제합니다.',
36
36
  },
37
37
  messages: {
38
38
  preferSoftPrivate:
39
- 'Hard private fields (#) are not allowed. Use the "private _" style instead.',
39
+ 'hard private 필드(#) 사용할 없습니다. "private _" 스타일을 사용하세요.',
40
40
  nameConflict:
41
- 'Cannot convert hard private field "#{{name}}" to "_{{name}}". A member with the same name already exists.',
41
+ 'hard private 필드 "#{{name}}"을(를) "_{{name}}"(으)로 변환할 없습니다. 동일한 이름의 멤버가 이미 존재합니다.',
42
42
  },
43
43
  fixable: "code",
44
44
  schema: [],
@@ -46,11 +46,11 @@ export default createRule({
46
46
  defaultOptions: [],
47
47
  create(context) {
48
48
  const sourceCode = context.sourceCode;
49
- // Stack structure for supporting nested classes
49
+ // 중첩 클래스 지원을 위한 스택 구조
50
50
  const classStack: Set<string>[] = [];
51
51
 
52
52
  return {
53
- // 0. Collect member names when entering a class
53
+ // 0. 클래스 진입 멤버 이름 수집
54
54
  "ClassBody"(node: TSESTree.ClassBody) {
55
55
  const memberNames = new Set<string>();
56
56
  for (const member of node.body) {
@@ -67,7 +67,7 @@ export default createRule({
67
67
  classStack.pop();
68
68
  },
69
69
 
70
- // 1. Detect declarations (PropertyDefinition, MethodDefinition, AccessorProperty)
70
+ // 1. 선언 감지 (PropertyDefinition, MethodDefinition, AccessorProperty)
71
71
  "PropertyDefinition > PrivateIdentifier, MethodDefinition > PrivateIdentifier, AccessorProperty > PrivateIdentifier"(
72
72
  node: TSESTree.PrivateIdentifier,
73
73
  ) {
@@ -76,11 +76,11 @@ export default createRule({
76
76
  return;
77
77
  }
78
78
 
79
- const identifierName = node.name; // Name without the '#' character
79
+ const identifierName = node.name; // '#' 문자를 제외한 이름
80
80
  const targetName = `_${identifierName}`;
81
81
  const currentClassMembers = classStack.at(-1);
82
82
 
83
- // Check for name conflicts
83
+ // 이름 충돌 확인
84
84
  if (currentClassMembers?.has(targetName)) {
85
85
  context.report({
86
86
  node,
@@ -96,25 +96,25 @@ export default createRule({
96
96
  fix(fixer) {
97
97
  const fixes: RuleFix[] = [];
98
98
 
99
- // 1-1. Rename (#a -> _a)
99
+ // 1-1. 이름 변경 (#a -> _a)
100
100
  fixes.push(fixer.replaceText(node, targetName));
101
101
 
102
- // 1-2. Calculate the position to add the 'private' access modifier
102
+ // 1-2. 'private' 접근 제어자를 추가할 위치 계산
103
103
  if (parent.accessibility == null) {
104
- // Default insertion position: beginning of parent node (including static, async, etc)
104
+ // 기본 삽입 위치: 부모 노드의 시작 (static, async 등 포함)
105
105
  let tokenToInsertBefore = sourceCode.getFirstToken(parent);
106
106
 
107
- // If decorators exist, insert before the token after the last decorator
107
+ // 데코레이터가 있으면 마지막 데코레이터 다음 토큰 앞에 삽입
108
108
  // (@Deco private static _foo)
109
109
  if (parent.decorators.length > 0) {
110
110
  const lastDecorator = parent.decorators.at(-1)!;
111
111
  tokenToInsertBefore = sourceCode.getTokenAfter(lastDecorator);
112
112
  }
113
113
 
114
- // tokenToInsertBefore is now 'static', 'async', 'readonly', or a variable name ('_foo').
115
- // Inserting 'private ' before it naturally results in the correct order 'private static ...'.
116
- // If tokenToInsertBefore is null, it indicates an exceptional situation such as an AST parsing error.
117
- // In such cases, skip the entire fix to prevent an incomplete fix that only renames.
114
+ // tokenToInsertBefore 현재 'static', 'async', 'readonly', 또는 변수명('_foo')입니다.
115
+ // 앞에 'private ' 삽입하면 자연스럽게 'private static ...' 순서가 됩니다.
116
+ // tokenToInsertBefore null이면 AST 파싱 오류 등의 예외 상황을 나타냅니다.
117
+ // 이런 경우 이름만 변경되는 불완전한 수정을 방지하기 위해 전체 수정을 건너뜁니다.
118
118
  if (tokenToInsertBefore == null) {
119
119
  return [];
120
120
  }
@@ -126,7 +126,7 @@ export default createRule({
126
126
  });
127
127
  },
128
128
 
129
- // 2. Detect usage (this.#field)
129
+ // 2. 사용 감지 (this.#field)
130
130
  "MemberExpression > PrivateIdentifier"(node: TSESTree.PrivateIdentifier) {
131
131
  const identifierName = node.name;
132
132
  context.report({
@@ -2,13 +2,13 @@ import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils";
2
2
  import { createRule } from "../utils/create-rule";
3
3
 
4
4
  /**
5
- * ESLint rule that prohibits 'src' subpath imports from `@simplysm/*` packages.
5
+ * `@simplysm/*` 패키지에서 'src' 하위 경로 import를 금지하는 ESLint 규칙.
6
6
  *
7
7
  * @remarks
8
- * This rule checks:
9
- * - Static import statements: `import ... from '...'`
10
- * - Dynamic imports: `import('...')`
11
- * - Re-export statements: `export { ... } from '...'`, `export * from '...'`
8
+ * 규칙이 검사하는 항목:
9
+ * - 정적 import 문: `import ... from '...'`
10
+ * - 동적 import: `import('...')`
11
+ * - 재내보내기 문: `export { ... } from '...'`, `export * from '...'`
12
12
  */
13
13
  export default createRule({
14
14
  name: "no-subpath-imports-from-simplysm",
@@ -16,13 +16,13 @@ export default createRule({
16
16
  type: "problem",
17
17
  docs: {
18
18
  description:
19
- "Prohibits 'src' subpath imports from @simplysm packages. (e.g., @simplysm/pkg/src/x → prohibited)",
19
+ "@simplysm 패키지에서 'src' 하위 경로 import를 금지합니다. (예: @simplysm/pkg/src/x → 금지)",
20
20
  },
21
21
  fixable: "code",
22
22
  schema: [],
23
23
  messages: {
24
24
  noSubpathImport:
25
- "Cannot import 'src' subpath from '@simplysm/{{pkg}}' package: '{{importPath}}'",
25
+ "'@simplysm/{{pkg}}' 패키지에서 'src' 하위 경로를 import할 수 없습니다: '{{importPath}}'",
26
26
  },
27
27
  },
28
28
  defaultOptions: [],
@@ -32,8 +32,8 @@ export default createRule({
32
32
 
33
33
  const parts = importPath.split("/");
34
34
 
35
- // Allowed: @simplysm/pkg, @simplysm/pkg/xxx, @simplysm/pkg/xxx/yyy
36
- // Prohibited: @simplysm/pkg/src, @simplysm/pkg/src/xxx
35
+ // 허용: @simplysm/pkg, @simplysm/pkg/xxx, @simplysm/pkg/xxx/yyy
36
+ // 금지: @simplysm/pkg/src, @simplysm/pkg/src/xxx
37
37
  if (parts.length >= 3 && parts[2] === "src") {
38
38
  const fixedPath = `@simplysm/${parts[1]}`;
39
39
  context.report({
@@ -52,12 +52,12 @@ export default createRule({
52
52
  }
53
53
 
54
54
  return {
55
- // Static import: import { x } from '...'
55
+ // 정적 import: import { x } from '...'
56
56
  ImportDeclaration(node) {
57
57
  checkAndReport(node.source, node.source.value);
58
58
  },
59
59
 
60
- // Dynamic import: import('...')
60
+ // 동적 import: import('...')
61
61
  ImportExpression(node) {
62
62
  if (node.source.type !== AST_NODE_TYPES.Literal) return;
63
63
  const importPath = node.source.value;
@@ -65,13 +65,13 @@ export default createRule({
65
65
  checkAndReport(node.source, importPath);
66
66
  },
67
67
 
68
- // Re-export: export { x } from '...'
68
+ // 재내보내기: export { x } from '...'
69
69
  ExportNamedDeclaration(node) {
70
70
  if (!node.source) return;
71
71
  checkAndReport(node.source, node.source.value);
72
72
  },
73
73
 
74
- // Re-export all: export * from '...'
74
+ // 전체 재내보내기: export * from '...'
75
75
  ExportAllDeclaration(node) {
76
76
  checkAndReport(node.source, node.source.value);
77
77
  },
@@ -2,25 +2,25 @@ import { AST_NODE_TYPES, ASTUtils, type TSESTree } from "@typescript-eslint/util
2
2
  import { createRule } from "../utils/create-rule";
3
3
 
4
4
  /**
5
- * ESLint rule that detects and warns about the use of `NotImplementedError` from `@simplysm/core-common`.
5
+ * `@simplysm/core-common`의 `NotImplementedError` 사용을 감지하고 경고하는 ESLint 규칙.
6
6
  *
7
7
  * @remarks
8
- * This rule detects code that instantiates `NotImplementedError` imported from `@simplysm/core-common` using `new`.
9
- * It prevents unimplemented code from being included in production.
8
+ * `@simplysm/core-common`에서 import한 `NotImplementedError`를 `new`로 인스턴스화하는 코드를 감지합니다.
9
+ * 미구현 코드가 프로덕션에 포함되는 것을 방지합니다.
10
10
  *
11
- * Supported import forms:
11
+ * 지원하는 import 형태:
12
12
  * - named import: `import { NotImplementedError } from "@simplysm/core-common"`
13
13
  * - aliased import: `import { NotImplementedError as NIE } from "@simplysm/core-common"`
14
14
  * - namespace import: `import * as CC from "@simplysm/core-common"` → `new CC.NotImplementedError()`
15
15
  *
16
- * Dynamic imports (`await import(...)`) are not detected.
16
+ * 동적 import (`await import(...)`) 감지하지 않습니다.
17
17
  */
18
18
  export default createRule({
19
19
  name: "ts-no-throw-not-implemented-error",
20
20
  meta: {
21
21
  type: "suggestion",
22
22
  docs: {
23
- description: "Warns about 'NotImplementedError' usage",
23
+ description: "'NotImplementedError' 사용에 대해 경고합니다",
24
24
  },
25
25
  schema: [],
26
26
  messages: {
@@ -30,10 +30,10 @@ export default createRule({
30
30
  defaultOptions: [],
31
31
  create(context) {
32
32
  /**
33
- * Checks if an identifier is imported from @simplysm/core-common.
34
- * @param identifier - The identifier to check
35
- * @param expectedImportedName - The original name to check for named imports (undefined for namespace imports)
36
- * @returns true if the import source is @simplysm/core-common, false otherwise
33
+ * 식별자가 @simplysm/core-common에서 import되었는지 확인합니다.
34
+ * @param identifier - 확인할 식별자
35
+ * @param expectedImportedName - named import에서 확인할 원래 이름 (namespace import의 경우 undefined)
36
+ * @returns import 소스가 @simplysm/core-common이면 true, 아니면 false
37
37
  */
38
38
  function isImportedFromSimplysm(
39
39
  identifier: TSESTree.Identifier,
@@ -48,7 +48,7 @@ export default createRule({
48
48
  if (def.parent.type !== AST_NODE_TYPES.ImportDeclaration) continue;
49
49
  if (def.parent.source.value !== "@simplysm/core-common") continue;
50
50
 
51
- // named/aliased import: import { NotImplementedError } or import { NotImplementedError as NIE }
51
+ // named/aliased import: import { NotImplementedError } 또는 import { NotImplementedError as NIE }
52
52
  if (def.node.type === AST_NODE_TYPES.ImportSpecifier && expectedImportedName != null) {
53
53
  const imported = def.node.imported;
54
54
  if (
@@ -75,12 +75,12 @@ export default createRule({
75
75
  NewExpression(node: TSESTree.NewExpression) {
76
76
  let shouldReport = false;
77
77
 
78
- // Case 1: new NotImplementedError() or new NIE() (named/aliased import)
78
+ // 케이스 1: new NotImplementedError() 또는 new NIE() (named/aliased import)
79
79
  if (node.callee.type === AST_NODE_TYPES.Identifier) {
80
80
  shouldReport = isImportedFromSimplysm(node.callee, "NotImplementedError");
81
81
  }
82
82
 
83
- // Case 2: new CC.NotImplementedError() (namespace import)
83
+ // 케이스 2: new CC.NotImplementedError() (namespace import)
84
84
  else if (
85
85
  node.callee.type === AST_NODE_TYPES.MemberExpression &&
86
86
  node.callee.property.type === AST_NODE_TYPES.Identifier &&
@@ -92,7 +92,7 @@ export default createRule({
92
92
 
93
93
  if (!shouldReport) return;
94
94
 
95
- let msg = "Not implemented";
95
+ let msg = "미구현";
96
96
  const firstArg = node.arguments.at(0);
97
97
  if (
98
98
  firstArg?.type === AST_NODE_TYPES.Literal &&
@@ -1,11 +1,11 @@
1
1
  import { ESLintUtils } from "@typescript-eslint/utils";
2
2
 
3
3
  /**
4
- * Factory function to create ESLint rules.
4
+ * ESLint 규칙을 생성하는 팩토리 함수.
5
5
  *
6
6
  * @remarks
7
- * Wraps `RuleCreator` from `@typescript-eslint/utils` and
8
- * automatically generates rule documentation URLs.
7
+ * `@typescript-eslint/utils`의 `RuleCreator`를 래핑하며
8
+ * 규칙 문서 URL을 자동으로 생성합니다.
9
9
  *
10
10
  * @example
11
11
  * ```typescript
package/README.md DELETED
@@ -1,81 +0,0 @@
1
- # @simplysm/lint
2
-
3
- Simplysm package - Lint configuration (ESLint). Provides an ESLint plugin with custom rules and a recommended flat config for TypeScript, SolidJS, and Tailwind CSS projects.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @simplysm/lint
9
- ```
10
-
11
- ## Entrypoints
12
-
13
- This package has two entrypoints:
14
-
15
- | Entrypoint | Import Path | Description |
16
- |------------|-------------|-------------|
17
- | ESLint Plugin | `@simplysm/lint/eslint-plugin` | Custom ESLint rules |
18
- | Recommended Config | `@simplysm/lint/eslint-recommended` | Full recommended flat config |
19
-
20
- ## API Overview
21
-
22
- ### ESLint Plugin (`@simplysm/lint/eslint-plugin`)
23
-
24
- Default export is an ESLint plugin object with `rules`:
25
-
26
- | Rule | Type | Fixable | Description |
27
- |------|------|---------|-------------|
28
- | `no-hard-private` | problem | Yes | Enforces TypeScript `private _` style instead of hard private fields (`#`). Auto-fixes `#field` to `private _field` and `this.#field` to `this._field`. |
29
- | `no-subpath-imports-from-simplysm` | problem | Yes | Prohibits `src` subpath imports from `@simplysm/*` packages (e.g., `@simplysm/pkg/src/x` is prohibited). Auto-fixes to package root import. |
30
- | `ts-no-throw-not-implemented-error` | suggestion | No | Warns about `NotImplementedError` usage from `@simplysm/core-common`. Detects named, aliased, and namespace imports. |
31
-
32
- ### Recommended Config (`@simplysm/lint/eslint-recommended`)
33
-
34
- Default export is a full ESLint flat config array that includes:
35
-
36
- - **Global ignores**: `node_modules`, `dist`, dotfiles, underscore-prefixed directories
37
- - **JS/JSX rules**: Common rules + unused imports + import dependency checks + custom `@simplysm` rules
38
- - **TS/TSX rules**: TypeScript-specific rules (strict boolean expressions, no floating promises, prefer readonly, etc.) + all JS rules
39
- - **Test overrides**: Relaxed rules for `tests/` and `tests-e2e/` directories (allows console, no extraneous deps check)
40
- - **SolidJS rules**: No destructure, components-return-once, no-innerhtml, prefer-for, etc.
41
- - **Tailwind CSS rules**: Classnames order, enforces shorthand, no contradicting classname, no custom classname
42
-
43
- #### Included Plugins
44
-
45
- | Plugin | Prefix | Purpose |
46
- |--------|--------|---------|
47
- | `@typescript-eslint` | `@typescript-eslint/` | TypeScript type-aware linting |
48
- | `@simplysm` (this package) | `@simplysm/` | Custom Simplysm rules |
49
- | `eslint-plugin-import` | `import/` | Import/export validation |
50
- | `eslint-plugin-unused-imports` | `unused-imports/` | Auto-remove unused imports |
51
- | `eslint-plugin-solid` | `solid/` | SolidJS best practices |
52
- | `eslint-plugin-tailwindcss` | `tailwindcss/` | Tailwind CSS class validation |
53
-
54
- ## Usage Examples
55
-
56
- ### Use the recommended config
57
-
58
- ```typescript
59
- // eslint.config.ts
60
- import recommended from "@simplysm/lint/eslint-recommended";
61
-
62
- export default recommended;
63
- ```
64
-
65
- ### Use the plugin with custom rules
66
-
67
- ```typescript
68
- // eslint.config.ts
69
- import plugin from "@simplysm/lint/eslint-plugin";
70
-
71
- export default [
72
- {
73
- plugins: { "@simplysm": plugin },
74
- rules: {
75
- "@simplysm/no-hard-private": "error",
76
- "@simplysm/no-subpath-imports-from-simplysm": "error",
77
- "@simplysm/ts-no-throw-not-implemented-error": "warn",
78
- },
79
- },
80
- ];
81
- ```