eslint-plugin-imports-regulation 0.2.8 → 0.2.9

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.
@@ -1,5 +1,5 @@
1
1
  import type { TSESLint } from '@typescript-eslint/utils';
2
- type MessageIds = 'groupOrder' | 'blankLinesBetween' | 'unexpectedBlankLine' | 'typeSpecifiersLast' | 'markTypeOnly' | 'typeOnlyImport' | 'typeOnlySpecifier' | 'blankLinesAfter';
2
+ type MessageIds = 'groupOrder' | 'blankLinesBetween' | 'unexpectedBlankLine' | 'blankLineBelowComment' | 'typeSpecifiersLast' | 'markTypeOnly' | 'typeOnlyImport' | 'typeOnlySpecifier' | 'blankLinesAfter';
3
3
  type Origin = 'external' | 'internal';
4
4
  type Options = [
5
5
  {
@@ -66,6 +66,7 @@ const rule = {
66
66
  groupOrder: 'Expected this {{group}} import before the {{other}} imports.',
67
67
  blankLinesBetween: 'Expected {{expected}} blank {{lines}} between external imports and internal imports, found {{actual}}.',
68
68
  unexpectedBlankLine: 'Expected no blank lines between imports in the same group, found {{actual}}.',
69
+ blankLineBelowComment: 'Expected no blank lines between a comment and the import it belongs to, found {{actual}}.',
69
70
  typeSpecifiersLast: 'Type specifiers must come after value specifiers.',
70
71
  markTypeOnly: 'An import of nothing but types must be written `import type { A }`.',
71
72
  typeOnlyImport: 'Everything this imports is only used as a type — write `import type`.',
@@ -389,6 +390,32 @@ const rule = {
389
390
  }
390
391
  return entries;
391
392
  };
393
+ /**
394
+ * An entry's text with the blank lines below its comments taken out, and how many there were.
395
+ * Only the whitespace between comments is looked at: a blank line inside a block comment is
396
+ * the comment's own.
397
+ */
398
+ const tightened = (entry) => {
399
+ let blank = 0;
400
+ let text = '';
401
+ let cursor = entry.start;
402
+ const closeGap = (to) => {
403
+ const gap = source.text.slice(cursor, to);
404
+ const breaks = (gap.match(BREAK_GLOBAL) ?? []).length;
405
+ blank += Math.max(breaks - 1, 0);
406
+ text += breaks > 1 ? `${eol}${/[^\r\n]*$/.exec(gap)?.[0] ?? ''}` : gap;
407
+ };
408
+ for (const comment of source.getAllComments()) {
409
+ if (comment.range[0] < entry.start || comment.range[1] > entry.node.range[0])
410
+ continue;
411
+ closeGap(comment.range[0]);
412
+ text += source.text.slice(comment.range[0], comment.range[1]);
413
+ cursor = comment.range[1];
414
+ }
415
+ closeGap(entry.node.range[0]);
416
+ text += source.text.slice(entry.node.range[0], entry.end);
417
+ return { blank, text };
418
+ };
392
419
  const lineAt = (index) => source.lines[index] ?? '';
393
420
  const isBlank = (index) => lineAt(index).trim() === '';
394
421
  /**
@@ -457,7 +484,7 @@ const rule = {
457
484
  const boundary = isInternalGroup(entry.group) !== isInternalGroup(previous.group);
458
485
  text += eol.repeat(boundary ? blankLinesBetween + 1 : 1);
459
486
  }
460
- text += source.text.slice(entry.start, entry.end);
487
+ text += tightened(entry).text;
461
488
  previous = entry;
462
489
  }
463
490
  return fixer.replaceTextRange([first.start, last.end], text);
@@ -484,6 +511,15 @@ const rule = {
484
511
  const blank = Math.max((gap.match(BREAK_GLOBAL) ?? []).length - 1, 0);
485
512
  const boundary = isInternalGroup(entry.group) !== isInternalGroup(previous.group);
486
513
  const wanted = boundary ? blankLinesBetween : 0;
514
+ const below = tightened(entry).blank;
515
+ if (below > 0) {
516
+ context.report({
517
+ node: entry.node,
518
+ messageId: 'blankLineBelowComment',
519
+ data: { actual: String(below) },
520
+ fix: rewrite,
521
+ });
522
+ }
487
523
  if (blank === wanted)
488
524
  continue;
489
525
  // Every gap, each with the whole-run fix: ESLint applies one, and the rest are gone on
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-imports-regulation",
3
- "version": "0.2.8",
3
+ "version": "0.2.9",
4
4
  "description": "Order imports: external type-only, external, blank line, internal type-only, internal — with type specifiers last inside each import.",
5
5
  "author": "Robert Sandiford",
6
6
  "type": "module",