Skip to content

Commit 05cbda4

Browse files
committed
feat: adding sort-scripts-elements.ts rule
Signed-off-by: axel7083 <[email protected]>
1 parent 858fc22 commit 05cbda4

File tree

7 files changed

+51
-15
lines changed

7 files changed

+51
-15
lines changed

packages/eslint-plugin-svelte/src/rules/sort-scripts-elements.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { createRule } from '../utils/index.js';
22
import type { RuleContext } from '../types.js';
33
import type { AST } from 'svelte-eslint-parser';
4+
import type { Range } from 'svelte-eslint-parser/lib/ast/common.js';
45

56
const DEFAULT_ORDER: string[] = [
67
'ImportDeclaration',
78
'TSTypeAliasDeclaration',
9+
'TSInterfaceDeclaration',
810
'VariableDeclaration',
911
'FunctionDeclaration'
1012
];
@@ -74,18 +76,25 @@ export default createRule('sort-scripts-elements', {
7476
fix: (fixer) => {
7577
const foo: { order: number; text: string }[] = [];
7678

79+
const ranges: Range[] = [];
7780
for (let i = 0; i < statements.length; i++) {
78-
// Getting the comments between previous and current statement
79-
const comments = sourceCode
80-
.getCommentsInside({
81-
type: 'Null',
82-
range: [
83-
// Get comment between the last statement and current
84-
i === 0 ? node.startTag.range[1] : statements[i - 1].range[1],
85-
i === statements.length - 1 ? svelteEndTag.range[0] : statements[i].range[0]
86-
]
87-
})
88-
.map((comment) => sourceCode.getText(comment));
81+
// the first token start after the previous statement
82+
let start: number;
83+
if (i === 0) {
84+
// special case: first statement, we copy everything from <script> <--
85+
start = node.startTag.range[1];
86+
} else {
87+
start = ranges[i - 1][1];
88+
}
89+
90+
let end: number;
91+
if (i === statements.length - 1) {
92+
end = svelteEndTag.range[0] - 1;
93+
} else {
94+
end = statements[i].range[1];
95+
}
96+
97+
ranges.push([start, end]);
8998

9099
/**
91100
* We need to handle the missing \t\n
@@ -95,17 +104,20 @@ export default createRule('sort-scripts-elements', {
95104
*/
96105
foo.push({
97106
order: MAPPING.get(statements[i].type) ?? Number.MAX_SAFE_INTEGER,
98-
text: comments.join('') + sourceCode.getText(statements[i])
107+
text: sourceCode.getText({
108+
range: [start, end],
109+
type: 'Null'
110+
})
99111
});
100112
}
101113

102114
const text = foo
103115
.sort((a, b) => a.order - b.order)
104116
.map(({ text }) => text)
105-
.join('\n');
117+
.join('');
106118

107119
return [
108-
fixer.replaceTextRange([node.startTag.range[1] + 1, svelteEndTag.range[0] - 1], text)
120+
fixer.replaceTextRange([node.startTag.range[1], svelteEndTag.range[0] - 1], text)
109121
];
110122
}
111123
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- message: Scripts is not sorted.
2+
line: 1
3+
column: 1
4+
suggestions: null
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script lang="ts">
2+
let count: Foo = $state({ bar: 'dummy' });
3+
interface Foo {
4+
bar: string;
5+
}
6+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script lang="ts">
2+
interface Foo {
3+
bar: string;
4+
}
5+
let count: Foo = $state({ bar: 'dummy' });
6+
</script>

packages/eslint-plugin-svelte/tests/fixtures/rules/sort-scripts-elements/invalid/default/type-before-import-input.svelte

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<script lang="ts">
22
type Foo = string;
33
import Bar from './bar.svelte';
4-
4+
55
function hello(): string {
66
return 'world';
77
}
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
<script lang="ts">
22
import Bar from './bar.svelte';
33
type Foo = string;
4+
5+
function hello(): string {
6+
return 'world';
7+
}
48
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<script>
2+
// I am not a problem
3+
import component from './foo';
4+
</script>

0 commit comments

Comments
 (0)