Skip to content

Commit 9f7ce26

Browse files
authored
Add mustache-spacing rule (#77)
* Add mustache-spacing rule * update * fix
1 parent 4fb095b commit 9f7ce26

26 files changed

+2260
-71
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ These rules relate to style guidelines, and are therefore quite subjective:
282282
| [@ota-meshi/svelte/html-quotes](https://ota-meshi.github.io/eslint-plugin-svelte/rules/html-quotes.html) | enforce quotes style of HTML attributes | :wrench: |
283283
| [@ota-meshi/svelte/indent](https://ota-meshi.github.io/eslint-plugin-svelte/rules/indent.html) | enforce consistent indentation | :wrench: |
284284
| [@ota-meshi/svelte/max-attributes-per-line](https://ota-meshi.github.io/eslint-plugin-svelte/rules/max-attributes-per-line.html) | enforce the maximum number of attributes per line | :wrench: |
285+
| [@ota-meshi/svelte/mustache-spacing](https://ota-meshi.github.io/eslint-plugin-svelte/rules/mustache-spacing.html) | enforce unified spacing in mustache | :wrench: |
285286
| [@ota-meshi/svelte/prefer-class-directive](https://ota-meshi.github.io/eslint-plugin-svelte/rules/prefer-class-directive.html) | require class directives instead of ternary expressions | :wrench: |
286287
| [@ota-meshi/svelte/shorthand-attribute](https://ota-meshi.github.io/eslint-plugin-svelte/rules/shorthand-attribute.html) | enforce use of shorthand syntax in attribute | :wrench: |
287288
| [@ota-meshi/svelte/spaced-html-comment](https://ota-meshi.github.io/eslint-plugin-svelte/rules/spaced-html-comment.html) | enforce consistent spacing after the `<!--` and before the `-->` in a HTML comment | :wrench: |

docs/rules/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ These rules relate to style guidelines, and are therefore quite subjective:
5050
| [@ota-meshi/svelte/html-quotes](./html-quotes.md) | enforce quotes style of HTML attributes | :wrench: |
5151
| [@ota-meshi/svelte/indent](./indent.md) | enforce consistent indentation | :wrench: |
5252
| [@ota-meshi/svelte/max-attributes-per-line](./max-attributes-per-line.md) | enforce the maximum number of attributes per line | :wrench: |
53+
| [@ota-meshi/svelte/mustache-spacing](./mustache-spacing.md) | enforce unified spacing in mustache | :wrench: |
5354
| [@ota-meshi/svelte/prefer-class-directive](./prefer-class-directive.md) | require class directives instead of ternary expressions | :wrench: |
5455
| [@ota-meshi/svelte/shorthand-attribute](./shorthand-attribute.md) | enforce use of shorthand syntax in attribute | :wrench: |
5556
| [@ota-meshi/svelte/spaced-html-comment](./spaced-html-comment.md) | enforce consistent spacing after the `<!--` and before the `-->` in a HTML comment | :wrench: |

docs/rules/mustache-spacing.md

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
---
2+
pageClass: "rule-details"
3+
sidebarDepth: 0
4+
title: "@ota-meshi/svelte/mustache-spacing"
5+
description: "enforce unified spacing in mustache"
6+
---
7+
8+
# @ota-meshi/svelte/mustache-spacing
9+
10+
> enforce unified spacing in mustache
11+
12+
- :exclamation: <badge text="This rule has not been released yet." vertical="middle" type="error"> **_This rule has not been released yet._** </badge>
13+
- :wrench: The `--fix` option on the [command line](https://eslint.org/docs/user-guide/command-line-interface#fixing-problems) can automatically fix some of the problems reported by this rule.
14+
15+
## :book: Rule Details
16+
17+
This rule aims at enforcing unified spacing in mustaches.
18+
19+
<eslint-code-block fix>
20+
21+
<!-- prettier-ignore-start -->
22+
<!--eslint-skip-->
23+
24+
```svelte
25+
<script>
26+
/* eslint @ota-meshi/svelte/mustache-spacing: "error" */
27+
</script>
28+
29+
<!-- ✓ GOOD -->
30+
{name}
31+
<input bind:value={text} class="foo {bar}" />
32+
<input {id} {...attrs} />
33+
{@html page}
34+
{@debug o1, o2}
35+
36+
{#if c1}...{:else if c2}...{:else}...{/if}
37+
38+
{#each list as item}...{/each}
39+
40+
{#await p}...{:then val}...{:catch err}...{/await}
41+
42+
{#key id}...{/key}
43+
44+
<!-- ✗ BAD -->
45+
{ name }
46+
<input bind:value={ text } class="foo { bar }" />
47+
<input { id } { ...attrs } />
48+
{ @html page }
49+
{ @debug o1, o2 }
50+
51+
{ #if c1 }...{ :else if c2 }...{ :else }...{ /if }
52+
53+
{ #each list as item }...{ /each }
54+
55+
{ #await p }...{ :then val }...{ :catch err }...{ /await }
56+
57+
{ #key id }...{ /key }
58+
```
59+
60+
</eslint-code-block>
61+
62+
<!-- prettier-ignore-end -->
63+
64+
## :wrench: Options
65+
66+
```json
67+
{
68+
"@ota-meshi/svelte/mustache-spacing": [
69+
"error",
70+
{
71+
"textExpressions": "never", // or "always"
72+
"attributesAndProps": "never", // or "always"
73+
"directiveExpressions": "never", // or "always"
74+
"tags": {
75+
"openingBrace": "never", // or "always"
76+
"closingBrace": "never" // or "always" or "always-after-expression"
77+
}
78+
}
79+
]
80+
}
81+
```
82+
83+
- `"never"` ... Expect one space between token and curly brackets. This is default.
84+
- `"always"` ... Expect no spaces between token and curly brackets. This is default.
85+
- `"always-after-expression"` ... Expect one space between expression and closing curly brackets, if the expression before the closing curly bracket.
86+
- `textExpressions` ... Enforces the style of the mustache for the text expressions. e.g. `{text}`.
87+
- `attributesAndProps` ... Enforces the style of the mustache for the attributes and props. e.g. `<input value={text}`.
88+
- `directiveExpressions` ... Enforces the style of the mustache for the directive expressions. e.g. `<input bind:value={text}`.
89+
- `tags` ... Enforces the style of the mustache for the mustache tags. e.g. `{#if condition}`.
90+
91+
## :mag: Implementation
92+
93+
- [Rule source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/src/rules/mustache-spacing.ts)
94+
- [Test source](https://github.com/ota-meshi/eslint-plugin-svelte/blob/main/tests/src/rules/mustache-spacing.ts)

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"debug": "^4.3.1",
5353
"eslint-utils": "^3.0.0",
5454
"sourcemap-codec": "^1.4.8",
55-
"svelte-eslint-parser": "^0.6.0"
55+
"svelte-eslint-parser": "^0.7.0"
5656
},
5757
"peerDependencies": {
5858
"eslint": "^7.0.0 || ^8.0.0-0",

src/rules/html-quotes.ts

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
import type { AST } from "svelte-eslint-parser"
2-
import {
3-
isClosingParenToken,
4-
isNotClosingBraceToken,
5-
isNotOpeningBraceToken,
6-
isOpeningParenToken,
7-
} from "eslint-utils"
82
import { createRule } from "../utils"
93
import type { QuoteAndRange } from "../utils/ast-utils"
4+
import { getMustacheTokens } from "../utils/ast-utils"
105
import { getAttributeValueQuoteAndRange } from "../utils/ast-utils"
116

127
const QUOTE_CHARS = {
@@ -154,7 +149,7 @@ export default createRule("html-quotes", {
154149

155150
/** Verify for standard attribute */
156151
function verifyForValues(attr: AST.SvelteAttribute) {
157-
const quoteAndRange = getAttributeValueQuoteAndRange(attr, context)
152+
const quoteAndRange = getAttributeValueQuoteAndRange(attr, sourceCode)
158153
verifyQuote(preferQuote, quoteAndRange)
159154
}
160155

@@ -165,7 +160,7 @@ export default createRule("html-quotes", {
165160
kind: "text"
166161
},
167162
) {
168-
const quoteAndRange = getAttributeValueQuoteAndRange(attr, context)
163+
const quoteAndRange = getAttributeValueQuoteAndRange(attr, sourceCode)
169164
const text = sourceCode.text.slice(...valueNode.range)
170165
verifyQuote(
171166
avoidInvalidUnquotedInHTML && !canBeUnquotedInHTML(text)
@@ -178,31 +173,15 @@ export default createRule("html-quotes", {
178173
/** Verify for directive value */
179174
function verifyForDirective(
180175
attr: AST.SvelteDirective | AST.SvelteSpecialDirective,
181-
valueNode: NonNullable<AST.SvelteDirective["expression"]>,
182176
) {
183-
let beforeToken = sourceCode.getTokenBefore(valueNode)
184-
let afterToken = sourceCode.getTokenAfter(valueNode)
185-
while (
186-
beforeToken &&
187-
afterToken &&
188-
isOpeningParenToken(beforeToken) &&
189-
isClosingParenToken(afterToken)
190-
) {
191-
beforeToken = sourceCode.getTokenBefore(beforeToken)
192-
afterToken = sourceCode.getTokenAfter(afterToken)
193-
}
194-
if (
195-
!beforeToken ||
196-
!afterToken ||
197-
isNotOpeningBraceToken(beforeToken) ||
198-
isNotClosingBraceToken(afterToken)
199-
) {
177+
const mustacheTokens = getMustacheTokens(attr, sourceCode)
178+
if (!mustacheTokens) {
200179
return
201180
}
202-
const quoteAndRange = getAttributeValueQuoteAndRange(attr, context)
181+
const quoteAndRange = getAttributeValueQuoteAndRange(attr, sourceCode)
203182
const text = sourceCode.text.slice(
204-
beforeToken.range[0],
205-
afterToken.range[1],
183+
mustacheTokens.openToken.range[0],
184+
mustacheTokens.closeToken.range[1],
206185
)
207186
verifyQuote(
208187
avoidInvalidUnquotedInHTML && !canBeUnquotedInHTML(text)
@@ -236,7 +215,7 @@ export default createRule("html-quotes", {
236215
// shorthand
237216
return
238217
}
239-
verifyForDirective(node, node.expression)
218+
verifyForDirective(node)
240219
},
241220
}
242221
},

src/rules/indent-helpers/svelte.ts

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -411,17 +411,13 @@ export function defineVisitor(context: IndentContext): NodeListener {
411411
offsets.setOffsetToken(closeCloseTagToken, 0, openCloseTagToken)
412412
},
413413
SvelteAwaitPendingBlock(node: AST.SvelteAwaitPendingBlock) {
414-
const first = sourceCode.getFirstToken(node, {
415-
includeComments: false,
416-
filter: isNotWhitespace,
417-
})!
418-
const offset = isBeginningOfLine(sourceCode, first) ? 0 : 1
414+
const openToken = sourceCode.getFirstToken(node)
419415
for (const child of node.children) {
420416
const token = sourceCode.getFirstToken(child, {
421417
includeComments: false,
422418
filter: isNotWhitespace,
423419
})
424-
offsets.setOffsetToken(token, offset, first)
420+
offsets.setOffsetToken(token, 1, openToken)
425421
}
426422
},
427423
SvelteAwaitThenBlock(node: AST.SvelteAwaitThenBlock) {

0 commit comments

Comments
 (0)