@so1ve/eslint-plugin 3.21.0 → 3.22.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/dist/index.d.ts CHANGED
@@ -1,40 +1,54 @@
1
1
  import { ESLintUtils } from "@typescript-eslint/utils";
2
2
 
3
3
  //#region src/rules/function-style.d.ts
4
- type MessageIds$9 = "arrow" | "declaration";
5
- declare const rule: ESLintUtils.RuleModule<MessageIds$9>;
4
+ type MessageIds$10 = "arrow" | "declaration";
5
+ type Options$10 = [];
6
+ declare const rule$10: ESLintUtils.RuleModule<MessageIds$10, Options$10>;
7
+ //#endregion
8
+ //#region src/rules/html-spaced-comment.d.ts
9
+ type MessageIds$9 = "expectedSpaceBefore" | "expectedSpaceAfter";
10
+ type Options$9 = [];
11
+ declare const rule$9: ESLintUtils.RuleModule<MessageIds$9, Options$9>;
6
12
  //#endregion
7
13
  //#region src/rules/import-dedupe.d.ts
8
14
  type MessageIds$8 = "importDedupe";
9
- declare const rule$1: ESLintUtils.RuleModule<MessageIds$8>;
15
+ type Options$8 = [];
16
+ declare const rule$8: ESLintUtils.RuleModule<MessageIds$8, Options$8>;
17
+ //#endregion
18
+ //#region src/rules/import-export-newline.d.ts
19
+ type MessageIds$7 = "newlineAfterLastImport" | "newlineBeforeExport" | "newlineAfterExport";
20
+ type Options$7 = [];
21
+ declare const rule$7: ESLintUtils.RuleModule<MessageIds$7, Options$7>;
10
22
  //#endregion
11
23
  //#region src/rules/no-import-promises-as.d.ts
12
- type MessageIds$7 = "noImportPromisesAs";
13
- declare const rule$2: ESLintUtils.RuleModule<MessageIds$7>;
24
+ type MessageIds$6 = "noImportPromisesAs";
25
+ type Options$6 = [];
26
+ declare const rule$6: ESLintUtils.RuleModule<MessageIds$6, Options$6>;
14
27
  //#endregion
15
28
  //#region src/rules/no-inline-type-import.d.ts
16
- type MessageIds$6 = "noInlineTypeImport";
17
- declare const rule$3: ESLintUtils.RuleModule<MessageIds$6>;
29
+ type MessageIds$5 = "noInlineTypeImport";
30
+ type Options$5 = [];
31
+ declare const rule$5: ESLintUtils.RuleModule<MessageIds$5, Options$5>;
18
32
  //#endregion
19
33
  //#region src/rules/no-negated-comparison.d.ts
20
- type MessageIds$5 = "noNegatedComparison";
21
- declare const rule$4: ESLintUtils.RuleModule<MessageIds$5>;
34
+ type MessageIds$4 = "noNegatedComparison";
35
+ type Options$4 = [];
36
+ declare const rule$4: ESLintUtils.RuleModule<MessageIds$4, Options$4>;
22
37
  //#endregion
23
38
  //#region src/rules/no-useless-template-string.d.ts
24
- type MessageIds$4 = "noUselessTemplateString";
25
- declare const rule$5: ESLintUtils.RuleModule<MessageIds$4>;
26
- //#endregion
27
- //#region src/rules/pad-after-last-import.d.ts
28
- type MessageIds$3 = "padAfterLastImport";
29
- declare const rule$6: ESLintUtils.RuleModule<MessageIds$3>;
39
+ type MessageIds$3 = "noUselessTemplateString";
40
+ type Options$3 = [];
41
+ declare const rule$3: ESLintUtils.RuleModule<MessageIds$3, Options$3>;
30
42
  //#endregion
31
43
  //#region src/rules/prefer-ts-expect-error.d.ts
32
44
  type MessageIds$2 = "preferExpectErrorComment";
33
- declare const rule$7: ESLintUtils.RuleModule<MessageIds$2>;
45
+ type Options$2 = [];
46
+ declare const rule$2: ESLintUtils.RuleModule<MessageIds$2, Options$2>;
34
47
  //#endregion
35
48
  //#region src/rules/require-async-with-await.d.ts
36
49
  type MessageIds$1 = "requireAsyncWithAwait";
37
- declare const rule$8: ESLintUtils.RuleModule<MessageIds$1>;
50
+ type Options$1 = [];
51
+ declare const rule$1: ESLintUtils.RuleModule<MessageIds$1, Options$1>;
38
52
  //#endregion
39
53
  //#region src/rules/vue-root-element-sort-attributes.d.ts
40
54
  type MessageIds = "wrongOrder";
@@ -42,21 +56,22 @@ type Options = [{
42
56
  script?: string[];
43
57
  [otherElement: string]: string[] | undefined;
44
58
  }];
45
- declare const rule$9: ESLintUtils.RuleModule<MessageIds, Options>;
59
+ declare const rule: ESLintUtils.RuleModule<MessageIds, Options>;
46
60
  //#endregion
47
61
  //#region src/index.d.ts
48
62
  declare const _default: {
49
63
  rules: {
50
- "function-style": typeof rule;
51
- "import-dedupe": typeof rule$1;
52
- "no-import-promises-as": typeof rule$2;
53
- "no-inline-type-import": typeof rule$3;
64
+ "function-style": typeof rule$10;
65
+ "html-spaced-comment": typeof rule$9;
66
+ "import-dedupe": typeof rule$8;
67
+ "import-export-newline": typeof rule$7;
68
+ "no-import-promises-as": typeof rule$6;
69
+ "no-inline-type-import": typeof rule$5;
54
70
  "no-negated-comparison": typeof rule$4;
55
- "no-useless-template-string": typeof rule$5;
56
- "pad-after-last-import": typeof rule$6;
57
- "prefer-ts-expect-error": typeof rule$7;
58
- "require-async-with-await": typeof rule$8;
59
- "vue-root-element-sort-attributes": typeof rule$9;
71
+ "no-useless-template-string": typeof rule$3;
72
+ "prefer-ts-expect-error": typeof rule$2;
73
+ "require-async-with-await": typeof rule$1;
74
+ "vue-root-element-sort-attributes": typeof rule;
60
75
  };
61
76
  };
62
77
  //#endregion
package/dist/index.js CHANGED
@@ -16,9 +16,9 @@ function getPreviousNode(node) {
16
16
 
17
17
  //#endregion
18
18
  //#region src/rules/function-style.ts
19
- const RULE_NAME$8 = "function-style";
20
- const rule$9 = createEslintRule({
21
- name: RULE_NAME$8,
19
+ const RULE_NAME$9 = "function-style";
20
+ const rule$10 = createEslintRule({
21
+ name: RULE_NAME$9,
22
22
  meta: {
23
23
  type: "problem",
24
24
  docs: { description: "Enforce function style." },
@@ -153,7 +153,45 @@ const rule$9 = createEslintRule({
153
153
  };
154
154
  }
155
155
  });
156
- var function_style_default = rule$9;
156
+ var function_style_default = rule$10;
157
+
158
+ //#endregion
159
+ //#region src/rules/html-spaced-comment.ts
160
+ const RULE_NAME$8 = "html-spaced-comment";
161
+ const rule$9 = createEslintRule({
162
+ name: RULE_NAME$8,
163
+ meta: {
164
+ type: "layout",
165
+ docs: { description: "Enforce consistent spacing in HTML comments" },
166
+ fixable: "whitespace",
167
+ schema: [],
168
+ messages: {
169
+ expectedSpaceBefore: "Expected space after '<!--'.",
170
+ expectedSpaceAfter: "Expected space before '-->'."
171
+ }
172
+ },
173
+ defaultOptions: [],
174
+ create: (context) => ({ Comment(node) {
175
+ if (node.value?.type !== "CommentContent") return;
176
+ const rawValue = node.value.value;
177
+ if (rawValue.trim().length === 0) return;
178
+ if (!rawValue.startsWith(" ")) context.report({
179
+ node: node.value,
180
+ messageId: "expectedSpaceBefore",
181
+ fix(fixer) {
182
+ return fixer.insertTextBefore(node.value, " ");
183
+ }
184
+ });
185
+ if (!rawValue.endsWith(" ")) context.report({
186
+ node: node.value,
187
+ messageId: "expectedSpaceAfter",
188
+ fix(fixer) {
189
+ return fixer.insertTextAfter(node.value, " ");
190
+ }
191
+ });
192
+ } })
193
+ });
194
+ var html_spaced_comment_default = rule$9;
157
195
 
158
196
  //#endregion
159
197
  //#region src/rules/import-dedupe.ts
@@ -194,17 +232,101 @@ const rule$8 = createEslintRule({
194
232
  });
195
233
  var import_dedupe_default = rule$8;
196
234
 
235
+ //#endregion
236
+ //#region src/rules/import-export-newline.ts
237
+ const RULE_NAME$6 = "import-export-newline";
238
+ const isExportDeclaration = (node) => node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" || node.type === "ExportAllDeclaration";
239
+ function getSiblingNode(node, direction) {
240
+ const parent = node.parent;
241
+ if (!parent || !("body" in parent) || !Array.isArray(parent.body)) return null;
242
+ const body = parent.body;
243
+ const index = body.indexOf(node);
244
+ if (index === -1) return null;
245
+ return direction === "prev" ? index > 0 ? body[index - 1] : null : index < body.length - 1 ? body[index + 1] : null;
246
+ }
247
+ const rule$7 = createEslintRule({
248
+ name: RULE_NAME$6,
249
+ meta: {
250
+ type: "problem",
251
+ docs: { description: "Enforce spacing between imports and exports." },
252
+ fixable: "code",
253
+ schema: [],
254
+ messages: {
255
+ newlineAfterLastImport: "Expected a blank line after the last import.",
256
+ newlineBeforeExport: "Expected a blank line before the export.",
257
+ newlineAfterExport: "Expected a blank line after the export."
258
+ }
259
+ },
260
+ defaultOptions: [],
261
+ create: (context) => {
262
+ const sourceCode = context.sourceCode;
263
+ let lastImportNode = null;
264
+ const exportNodes = [];
265
+ function checkExport(node) {
266
+ exportNodes.push(node);
267
+ }
268
+ function shouldHaveNewline(node, direction) {
269
+ let token;
270
+ let commentLine;
271
+ let expectedLine;
272
+ let tokenLine;
273
+ if (direction === "after") {
274
+ token = sourceCode.getTokenAfter(node);
275
+ commentLine = sourceCode.getCommentsAfter(node)[0]?.loc.start.line;
276
+ expectedLine = node.loc.end.line + 1;
277
+ tokenLine = token?.loc.start.line;
278
+ } else {
279
+ token = sourceCode.getTokenBefore(node);
280
+ commentLine = sourceCode.getCommentsBefore(node)[0]?.loc.end.line;
281
+ expectedLine = node.loc.start.line - 1;
282
+ tokenLine = token?.loc.end.line;
283
+ }
284
+ return token && (expectedLine === tokenLine || expectedLine === commentLine) && (direction === "after" ? token.value !== "}" && token.value !== "<\/script>" : true);
285
+ }
286
+ return {
287
+ ImportDeclaration(node) {
288
+ lastImportNode = node;
289
+ },
290
+ ExportNamedDeclaration: checkExport,
291
+ ExportDefaultDeclaration: checkExport,
292
+ ExportAllDeclaration: checkExport,
293
+ "Program:exit"() {
294
+ if (lastImportNode && shouldHaveNewline(lastImportNode, "after")) context.report({
295
+ node: lastImportNode,
296
+ messageId: "newlineAfterLastImport",
297
+ fix: (fixer) => fixer.insertTextAfter(lastImportNode, "\n")
298
+ });
299
+ for (const node of exportNodes) {
300
+ const prevNode = getSiblingNode(node, "prev");
301
+ if ((!prevNode || !isExportDeclaration(prevNode)) && !(lastImportNode && prevNode === lastImportNode) && shouldHaveNewline(node, "before")) context.report({
302
+ node,
303
+ messageId: "newlineBeforeExport",
304
+ fix: (fixer) => fixer.insertTextBefore(node, "\n")
305
+ });
306
+ const nextNode = getSiblingNode(node, "next");
307
+ if (nextNode && !isExportDeclaration(nextNode) && shouldHaveNewline(node, "after")) context.report({
308
+ node,
309
+ messageId: "newlineAfterExport",
310
+ fix: (fixer) => fixer.insertTextAfter(node, "\n")
311
+ });
312
+ }
313
+ }
314
+ };
315
+ }
316
+ });
317
+ var import_export_newline_default = rule$7;
318
+
197
319
  //#endregion
198
320
  //#region src/rules/no-import-promises-as.ts
199
- const RULE_NAME$6 = "no-import-promises-as";
321
+ const RULE_NAME$5 = "no-import-promises-as";
200
322
  const POSSIBLE_IMPORT_SOURCES = [
201
323
  "dns",
202
324
  "fs",
203
325
  "readline",
204
326
  "stream"
205
327
  ].flatMap((s) => [s, `node:${s}`]);
206
- const rule$7 = createEslintRule({
207
- name: RULE_NAME$6,
328
+ const rule$6 = createEslintRule({
329
+ name: RULE_NAME$5,
208
330
  meta: {
209
331
  type: "problem",
210
332
  docs: { description: "Disallow import promises as." },
@@ -234,11 +356,11 @@ const rule$7 = createEslintRule({
234
356
  } };
235
357
  }
236
358
  });
237
- var no_import_promises_as_default = rule$7;
359
+ var no_import_promises_as_default = rule$6;
238
360
 
239
361
  //#endregion
240
362
  //#region src/rules/no-inline-type-import.ts
241
- const RULE_NAME$5 = "no-inline-type-import";
363
+ const RULE_NAME$4 = "no-inline-type-import";
242
364
  function generateImportsText(specifiers) {
243
365
  let text = "{ ";
244
366
  const texts = [];
@@ -265,8 +387,8 @@ function generateValueImportText(defaultImportSpecifier, valueSpecifiers) {
265
387
  if (hasValueImport) text += generateImportsText(valueSpecifiers);
266
388
  return text;
267
389
  }
268
- const rule$6 = createEslintRule({
269
- name: RULE_NAME$5,
390
+ const rule$5 = createEslintRule({
391
+ name: RULE_NAME$4,
270
392
  meta: {
271
393
  type: "layout",
272
394
  docs: { description: "Disallow inline type import." },
@@ -297,11 +419,11 @@ const rule$6 = createEslintRule({
297
419
  });
298
420
  } })
299
421
  });
300
- var no_inline_type_import_default = rule$6;
422
+ var no_inline_type_import_default = rule$5;
301
423
 
302
424
  //#endregion
303
425
  //#region src/rules/no-negated-comparison.ts
304
- const RULE_NAME$4 = "no-negated-comparison";
426
+ const RULE_NAME$3 = "no-negated-comparison";
305
427
  const negatedToPositive = {
306
428
  "==": "!=",
307
429
  "===": "!==",
@@ -313,8 +435,8 @@ const negatedToPositive = {
313
435
  ">=": "<"
314
436
  };
315
437
  const negatives = Object.keys(negatedToPositive);
316
- const rule$5 = createEslintRule({
317
- name: RULE_NAME$4,
438
+ const rule$4 = createEslintRule({
439
+ name: RULE_NAME$3,
318
440
  meta: {
319
441
  type: "problem",
320
442
  docs: { description: "Disallow negated comparison." },
@@ -338,13 +460,13 @@ const rule$5 = createEslintRule({
338
460
  });
339
461
  } })
340
462
  });
341
- var no_negated_comparison_default = rule$5;
463
+ var no_negated_comparison_default = rule$4;
342
464
 
343
465
  //#endregion
344
466
  //#region src/rules/no-useless-template-string.ts
345
- const RULE_NAME$3 = "no-useless-template-string";
346
- const rule$4 = createEslintRule({
347
- name: RULE_NAME$3,
467
+ const RULE_NAME$2 = "no-useless-template-string";
468
+ const rule$3 = createEslintRule({
469
+ name: RULE_NAME$2,
348
470
  meta: {
349
471
  type: "problem",
350
472
  docs: { description: "No useless template string." },
@@ -365,45 +487,7 @@ const rule$4 = createEslintRule({
365
487
  });
366
488
  } })
367
489
  });
368
- var no_useless_template_string_default = rule$4;
369
-
370
- //#endregion
371
- //#region src/rules/pad-after-last-import.ts
372
- const RULE_NAME$2 = "pad-after-last-import";
373
- const rule$3 = createEslintRule({
374
- name: RULE_NAME$2,
375
- meta: {
376
- type: "problem",
377
- docs: { description: "Pad after the last import." },
378
- fixable: "code",
379
- schema: [],
380
- messages: { padAfterLastImport: "Expected a blank line after the last import." }
381
- },
382
- defaultOptions: [],
383
- create: (context) => {
384
- const sourceCode = context.sourceCode;
385
- let lastImportNode = null;
386
- return {
387
- ImportDeclaration(node) {
388
- lastImportNode = node;
389
- },
390
- "Program:exit"() {
391
- if (lastImportNode) {
392
- const nextToken = sourceCode.getTokenAfter(lastImportNode);
393
- const firstCommentAfterTokenStartLine = sourceCode.getCommentsAfter(lastImportNode)[0]?.loc.start.line;
394
- const expectedLine = lastImportNode.loc.end.line + 1;
395
- const nextTokenStartLine = nextToken?.loc.start.line;
396
- if (nextToken && nextToken.value !== "<\/script>" && (expectedLine === nextTokenStartLine || expectedLine === firstCommentAfterTokenStartLine)) context.report({
397
- node: lastImportNode,
398
- messageId: "padAfterLastImport",
399
- fix: (fixer) => fixer.insertTextAfter(lastImportNode, "\n")
400
- });
401
- }
402
- }
403
- };
404
- }
405
- });
406
- var pad_after_last_import_default = rule$3;
490
+ var no_useless_template_string_default = rule$3;
407
491
 
408
492
  //#endregion
409
493
  //#region src/rules/prefer-ts-expect-error.ts
@@ -561,12 +645,13 @@ var vue_root_element_sort_attributes_default = rule;
561
645
  //#region src/index.ts
562
646
  var src_default = { rules: {
563
647
  "function-style": function_style_default,
648
+ "html-spaced-comment": html_spaced_comment_default,
564
649
  "import-dedupe": import_dedupe_default,
650
+ "import-export-newline": import_export_newline_default,
565
651
  "no-import-promises-as": no_import_promises_as_default,
566
652
  "no-inline-type-import": no_inline_type_import_default,
567
653
  "no-negated-comparison": no_negated_comparison_default,
568
654
  "no-useless-template-string": no_useless_template_string_default,
569
- "pad-after-last-import": pad_after_last_import_default,
570
655
  "prefer-ts-expect-error": prefer_ts_expect_error_default,
571
656
  "require-async-with-await": require_async_with_await_default,
572
657
  "vue-root-element-sort-attributes": vue_root_element_sort_attributes_default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@so1ve/eslint-plugin",
3
- "version": "3.21.0",
3
+ "version": "3.22.0",
4
4
  "author": "Ray <i@mk1.io> (https://github.com/so1ve/)",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -33,10 +33,11 @@
33
33
  "access": "public"
34
34
  },
35
35
  "dependencies": {
36
- "@typescript-eslint/types": "^8.47.0",
37
- "@typescript-eslint/utils": "^8.47.0"
36
+ "@typescript-eslint/types": "^8.50.1",
37
+ "@typescript-eslint/utils": "^8.50.1"
38
38
  },
39
39
  "devDependencies": {
40
+ "@html-eslint/parser": "^0.52.0",
40
41
  "vue-eslint-parser": "^10.2.0"
41
42
  }
42
43
  }