Skip to content

Commit 181267d

Browse files
authored
Add alignAttributesVertically option to indent rule (#31)
1 parent fdbff2a commit 181267d

File tree

12 files changed

+933
-552
lines changed

12 files changed

+933
-552
lines changed

docs/rules/indent.md

+23-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ This rule enforces a consistent indentation style in `.svelte`. The default styl
2323

2424
<!--eslint-skip-->
2525
<!-- prettier-ignore -->
26-
2726
```html
2827
<script>
2928
/* eslint @ota-meshi/svelte/indent: "error" */
@@ -51,6 +50,26 @@ CLICK ME!
5150

5251
</eslint-code-block>
5352

53+
::: warning Note
54+
This rule only checks `.svelte` files and does not interfere with other `.js` files. Unfortunately the default `indent` rule when turned on will try to lint both, so in order to make them complementary you can use `overrides` setting and disable `indent` rule on `.svelte` files:
55+
:::
56+
57+
```json
58+
{
59+
"rules": {
60+
"@ota-meshi/svelte/indent": "error"
61+
},
62+
"overrides": [
63+
{
64+
"files": ["*.svelte"],
65+
"rules": {
66+
"indent": "off"
67+
}
68+
}
69+
]
70+
}
71+
```
72+
5473
## :wrench: Options
5574

5675
```json
@@ -60,7 +79,8 @@ CLICK ME!
6079
{
6180
"indent": 2,
6281
"ignoredNodes": [],
63-
"switchCase": 1
82+
"switchCase": 1,
83+
"alignAttributesVertically": false
6484
}
6585
]
6686
}
@@ -69,6 +89,7 @@ CLICK ME!
6989
- `indent` (`number | "tab"`) ... The type of indentation. Default is `2`. If this is a number, it's the number of spaces for one indent. If this is `"tab"`, it uses one tab for one indent.
7090
- `ignoredNodes` ... Can be used to disable indentation checking for any AST node. This accepts an array of [selectors](https://eslint.org/docs/developer-guide/selectors). If an AST node is matched by any of the selectors, the indentation of tokens which are direct children of that node will be ignored. This can be used as an escape hatch to relax the rule if you disagree with the indentation that it enforces for a particular syntactic pattern.
7191
- `switchCase` ... Enforces indentation level for case clauses in switch statements. Default is `1`.
92+
- `alignAttributesVertically` ... Condition for whether attributes should be vertically aligned to the first attribute in multiline case or not. Default is `false`
7293

7394
## :rocket: Version
7495

src/rules/indent-helpers/commons.ts

+8-83
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type { ASTNode, SourceCode } from "../../types"
22
import type { AST } from "svelte-eslint-parser"
33
import { isOpeningParenToken, isClosingParenToken } from "eslint-utils"
44
import { isNotWhitespace, isWhitespace } from "./ast"
5+
import type { OffsetContext } from "./offset-context"
56

67
export type AnyToken = AST.Token | AST.Comment
78
export type MaybeNode = {
@@ -14,93 +15,14 @@ export type IndentOptions = {
1415
indentChar: " " | "\t"
1516
indentSize: number
1617
switchCase: number
18+
alignAttributesVertically: boolean
1719
ignoredNodes: string[]
1820
}
21+
1922
export type IndentContext = {
2023
sourceCode: SourceCode
2124
options: IndentOptions
22-
/**
23-
* Set offset to the given tokens.
24-
*/
25-
setOffset: (
26-
token: AnyToken | null | undefined | (AnyToken | null | undefined)[],
27-
offset: number,
28-
baseToken: AnyToken,
29-
) => void
30-
/**
31-
* Copy offset to the given tokens from srcToken.
32-
*/
33-
copyOffset: (
34-
token: AnyToken | null | undefined | (AnyToken | null | undefined)[],
35-
srcToken: AnyToken,
36-
) => void
37-
38-
/**
39-
* Set baseline offset to the given token.
40-
*/
41-
setOffsetBaseLine: (
42-
token: AnyToken | null | undefined | (AnyToken | null | undefined)[],
43-
offset: number,
44-
) => void
45-
/**
46-
* Ignore all tokens of the given node.
47-
*/
48-
ignore: (node: ASTNode) => void
49-
}
50-
51-
/**
52-
* Set offset to the given nodes.
53-
* The first node is offsetted from the given base token.
54-
*/
55-
export function setOffsetNodes(
56-
{ sourceCode, setOffset }: IndentContext,
57-
nodes: (ASTNode | AnyToken | MaybeNode | null | undefined)[],
58-
baseNodeOrToken: ASTNode | AnyToken | MaybeNode,
59-
lastNodeOrToken: ASTNode | AnyToken | MaybeNode | null,
60-
offset: number,
61-
): void {
62-
const baseToken = sourceCode.getFirstToken(baseNodeOrToken)
63-
64-
let prevToken = sourceCode.getLastToken(baseNodeOrToken)
65-
for (const node of nodes) {
66-
if (node == null) {
67-
continue
68-
}
69-
const elementTokens = getFirstAndLastTokens(
70-
sourceCode,
71-
node,
72-
prevToken.range[1],
73-
)
74-
75-
let t: AnyToken | null = prevToken
76-
while (
77-
(t = sourceCode.getTokenAfter(t, {
78-
includeComments: true,
79-
filter: isNotWhitespace,
80-
})) != null &&
81-
t.range[1] <= elementTokens.firstToken.range[0]
82-
) {
83-
setOffset(t, offset, baseToken)
84-
}
85-
setOffset(elementTokens.firstToken, offset, baseToken)
86-
87-
prevToken = elementTokens.lastToken
88-
}
89-
90-
if (lastNodeOrToken) {
91-
const lastToken = sourceCode.getFirstToken(lastNodeOrToken)
92-
let t: AnyToken | null = prevToken
93-
while (
94-
(t = sourceCode.getTokenAfter(t, {
95-
includeComments: true,
96-
filter: isNotWhitespace,
97-
})) != null &&
98-
t.range[1] <= lastToken.range[0]
99-
) {
100-
setOffset(t, offset, baseToken)
101-
}
102-
setOffset(lastToken, 0, baseToken)
103-
}
25+
offsets: OffsetContext
10426
}
10527

10628
/**
@@ -146,7 +68,10 @@ export function isBeginningOfLine(
14668
sourceCode: SourceCode,
14769
node: ASTNode | AnyToken | MaybeNode,
14870
): boolean {
149-
const prevToken = sourceCode.getTokenBefore(node, { includeComments: false })
71+
const prevToken = sourceCode.getTokenBefore(node, {
72+
includeComments: false,
73+
filter: isNotWhitespace,
74+
})
15075

15176
return !prevToken || prevToken.loc.end.line < node.loc!.start.line
15277
}

0 commit comments

Comments
 (0)