@blumintinc/eslint-plugin-blumint 1.20.110 → 1.20.111
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/lib/index.js +1 -1
- package/lib/rules/enforce-global-constants.js +5 -1
- package/lib/rules/logical-top-to-bottom-grouping.js +7 -1
- package/lib/rules/vertically-group-related-functions.js +8 -2
- package/lib/utils/shebang.d.ts +19 -0
- package/lib/utils/shebang.js +32 -0
- package/package.json +1 -1
- package/release-manifest.json +30 -0
package/lib/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.enforceGlobalConstants = void 0;
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
const createRule_1 = require("../utils/createRule");
|
|
6
|
+
const shebang_1 = require("../utils/shebang");
|
|
6
7
|
const ASTHelpers_1 = require("../utils/ASTHelpers");
|
|
7
8
|
exports.enforceGlobalConstants = (0, createRule_1.createRule)({
|
|
8
9
|
name: 'enforce-global-constants',
|
|
@@ -269,7 +270,10 @@ exports.enforceGlobalConstants = (0, createRule_1.createRule)({
|
|
|
269
270
|
}
|
|
270
271
|
else {
|
|
271
272
|
const body = program.body;
|
|
272
|
-
|
|
273
|
+
// A shebang has to stay at character 0 or the file stops parsing
|
|
274
|
+
// (TS18026), so it bounds the insertion the same way the
|
|
275
|
+
// directive prologue below does.
|
|
276
|
+
let insertPos = (0, shebang_1.afterShebang)(text);
|
|
273
277
|
let afterDirectiveIdx = -1;
|
|
274
278
|
for (let i = 0; i < body.length; i++) {
|
|
275
279
|
const stmt = body[i];
|
|
@@ -4,6 +4,7 @@ exports.logicalTopToBottomGrouping = void 0;
|
|
|
4
4
|
const utils_1 = require("@typescript-eslint/utils");
|
|
5
5
|
const ASTHelpers_1 = require("../utils/ASTHelpers");
|
|
6
6
|
const createRule_1 = require("../utils/createRule");
|
|
7
|
+
const shebang_1 = require("../utils/shebang");
|
|
7
8
|
const TYPE_EXPRESSION_WRAPPERS = new Set([
|
|
8
9
|
utils_1.AST_NODE_TYPES.TSAsExpression,
|
|
9
10
|
utils_1.AST_NODE_TYPES.TSTypeAssertion,
|
|
@@ -730,7 +731,12 @@ function findEarliestSafeIndex(body, startIndex, dependencies, { allowHooks, sto
|
|
|
730
731
|
* comments directly above it reads as its preamble.
|
|
731
732
|
*/
|
|
732
733
|
function getLeadingComments(statement, sourceCode) {
|
|
733
|
-
|
|
734
|
+
// A shebang belongs to the file, not to the statement below it. Left in the
|
|
735
|
+
// preamble, relocating the first statement carries `#!` off character 0 and
|
|
736
|
+
// the output stops parsing.
|
|
737
|
+
const comments = sourceCode
|
|
738
|
+
.getCommentsBefore(statement)
|
|
739
|
+
.filter((comment) => !(0, shebang_1.isShebangComment)(sourceCode, comment));
|
|
734
740
|
const ownLine = comments.findIndex((comment) => {
|
|
735
741
|
const previous = sourceCode.getTokenBefore(comment, {
|
|
736
742
|
includeComments: true,
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.verticallyGroupRelatedFunctions = void 0;
|
|
4
4
|
const createRule_1 = require("../utils/createRule");
|
|
5
5
|
const ASTHelpers_1 = require("../utils/ASTHelpers");
|
|
6
|
+
const shebang_1 = require("../utils/shebang");
|
|
6
7
|
const DEFAULT_OPTIONS = {
|
|
7
8
|
exportPlacement: 'ignore',
|
|
8
9
|
dependencyDirection: 'callers-first',
|
|
@@ -329,10 +330,15 @@ function getStatementRangeWithComments(statement, sourceCode, consumedComments,
|
|
|
329
330
|
// below would drag an interleaved statement's own end-of-line comment along
|
|
330
331
|
// when the following function is relocated. Only own-line comments count as
|
|
331
332
|
// leading comments.
|
|
332
|
-
const leadingCommentsOf = (target) => filterComments(sourceCode.getCommentsBefore(target) || [])
|
|
333
|
+
const leadingCommentsOf = (target) => filterComments(sourceCode.getCommentsBefore(target) || [])
|
|
334
|
+
.filter((comment) => {
|
|
333
335
|
const tokenBefore = sourceCode.getTokenBefore(comment);
|
|
334
336
|
return (!tokenBefore || tokenBefore.loc.end.line !== comment.loc.start.line);
|
|
335
|
-
})
|
|
337
|
+
})
|
|
338
|
+
// A shebang belongs to the file, not to the statement below it. Left in
|
|
339
|
+
// the span, relocating the first statement carries `#!` off character 0
|
|
340
|
+
// and the output stops parsing.
|
|
341
|
+
.filter((comment) => !(0, shebang_1.isShebangComment)(sourceCode, comment));
|
|
336
342
|
const commentsBefore = leadingCommentsOf(statement);
|
|
337
343
|
const nextLeadingComments = nextStatement
|
|
338
344
|
? new Set(leadingCommentsOf(nextStatement))
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TSESLint, TSESTree } from '@typescript-eslint/utils';
|
|
2
|
+
/**
|
|
3
|
+
* A shebang is only a shebang at character 0. One byte in front of it and the
|
|
4
|
+
* file stops parsing outright (`TS18026: '#!' can only be used at the start of
|
|
5
|
+
* a file`) and stops being executable.
|
|
6
|
+
*
|
|
7
|
+
* ESLint hands it to rules as an ordinary leading comment of the first
|
|
8
|
+
* statement, which is what makes it easy to lose: a fixer that relocates a
|
|
9
|
+
* statement together with its leading comments carries the shebang into the
|
|
10
|
+
* middle of the file, and one that splices at offset 0 pushes it off line 1.
|
|
11
|
+
* `importInsertion` already encodes this for the rules that add an import;
|
|
12
|
+
* these are the same rule for the ones that reorder or hoist.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isShebangComment(sourceCode: Pick<TSESLint.SourceCode, 'text'>, comment: TSESTree.Comment): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* The first offset at which text may be spliced without displacing a shebang.
|
|
17
|
+
* Zero for the overwhelmingly common file that has none.
|
|
18
|
+
*/
|
|
19
|
+
export declare function afterShebang(text: string): number;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.afterShebang = exports.isShebangComment = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* A shebang is only a shebang at character 0. One byte in front of it and the
|
|
6
|
+
* file stops parsing outright (`TS18026: '#!' can only be used at the start of
|
|
7
|
+
* a file`) and stops being executable.
|
|
8
|
+
*
|
|
9
|
+
* ESLint hands it to rules as an ordinary leading comment of the first
|
|
10
|
+
* statement, which is what makes it easy to lose: a fixer that relocates a
|
|
11
|
+
* statement together with its leading comments carries the shebang into the
|
|
12
|
+
* middle of the file, and one that splices at offset 0 pushes it off line 1.
|
|
13
|
+
* `importInsertion` already encodes this for the rules that add an import;
|
|
14
|
+
* these are the same rule for the ones that reorder or hoist.
|
|
15
|
+
*/
|
|
16
|
+
function isShebangComment(sourceCode, comment) {
|
|
17
|
+
return comment.range[0] === 0 && sourceCode.text.startsWith('#!');
|
|
18
|
+
}
|
|
19
|
+
exports.isShebangComment = isShebangComment;
|
|
20
|
+
/**
|
|
21
|
+
* The first offset at which text may be spliced without displacing a shebang.
|
|
22
|
+
* Zero for the overwhelmingly common file that has none.
|
|
23
|
+
*/
|
|
24
|
+
function afterShebang(text) {
|
|
25
|
+
if (!text.startsWith('#!')) {
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
const lineEnd = text.indexOf('\n');
|
|
29
|
+
return lineEnd === -1 ? text.length : lineEnd + 1;
|
|
30
|
+
}
|
|
31
|
+
exports.afterShebang = afterShebang;
|
|
32
|
+
//# sourceMappingURL=shebang.js.map
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -1,4 +1,34 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "1.20.111",
|
|
4
|
+
"date": "2026-08-05T13:37:20.101Z",
|
|
5
|
+
"rules": [
|
|
6
|
+
{
|
|
7
|
+
"name": "enforce-global-constants",
|
|
8
|
+
"changeType": "fix",
|
|
9
|
+
"issues": [
|
|
10
|
+
1739
|
|
11
|
+
],
|
|
12
|
+
"summary": "hoist below a shebang, not above it (closes #1739)"
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
"name": "logical-top-to-bottom-grouping",
|
|
16
|
+
"changeType": "fix",
|
|
17
|
+
"issues": [
|
|
18
|
+
1738
|
|
19
|
+
],
|
|
20
|
+
"summary": "keep a shebang at character 0 when reordering (closes #1738)"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "vertically-group-related-functions",
|
|
24
|
+
"changeType": "fix",
|
|
25
|
+
"issues": [
|
|
26
|
+
1737
|
|
27
|
+
],
|
|
28
|
+
"summary": "keep a shebang at character 0 when reordering (closes #1737)"
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
},
|
|
2
32
|
{
|
|
3
33
|
"version": "1.20.110",
|
|
4
34
|
"date": "2026-08-05T11:59:59.800Z",
|