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 +=
|
|
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.
|
|
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",
|