Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4c97f17

Browse files
armano2michalsnik
authored andcommitted
Add mustache-curly-spacing rule. (#153)
* Add `mustache-curly-spacing` rule. fixes #150 * Rename mustache-curly-spacing to mustache-interpolation-spacing
1 parent 541c238 commit 4c97f17

File tree

3 files changed

+326
-0
lines changed

3 files changed

+326
-0
lines changed
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# enforce unified spacing in mustache interpolations. (mustache-interpolation-spacing)
2+
3+
- :wrench: The `--fix` option on the [command line](http://eslint.org/docs/user-guide/command-line-interface#fix) can automatically fix some of the problems reported by this rule.
4+
5+
## :book: Rule Details
6+
7+
This rule aims to enforce unified spacing in mustache interpolations.
8+
9+
:-1: Examples of **incorrect** code for this rule:
10+
11+
```html
12+
<template>
13+
<div>{{ text }}</div>
14+
</template>
15+
```
16+
17+
:+1: Examples of **correct** code for this rule:
18+
19+
```html
20+
<template>
21+
<div>{{ text }}</div>
22+
</template>
23+
```
24+
25+
## :wrench: Options
26+
27+
Default spacing is set to `always`
28+
29+
```
30+
'vue/mustache-interpolation-spacing': [2, 'always'|'never']
31+
```
32+
33+
### `"always"` - Expect one space between expression and curly brackets.
34+
35+
:+1: Examples of **correct** code`:
36+
37+
```html
38+
<template>
39+
<div>{{ text }}</div>
40+
</template>
41+
```
42+
43+
:-1: Examples of **incorrect** code`:
44+
45+
```html
46+
<template>
47+
<div>{{text}}</div>
48+
</template>
49+
```
50+
51+
### `"never"` - Expect no spaces between expression and curly brackets.
52+
53+
:+1: Examples of **correct** code`:
54+
55+
```html
56+
<template>
57+
<div>{{text}}</div>
58+
</template>
59+
```
60+
61+
:-1: Examples of **incorrect** code`:
62+
63+
```html
64+
<template>
65+
<div>{{ text }}</div>
66+
</template>
67+
```
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
/**
2+
* @fileoverview enforce unified spacing in mustache interpolations.
3+
* @author Armano
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const utils = require('../utils')
12+
13+
// ------------------------------------------------------------------------------
14+
// Rule Definition
15+
// ------------------------------------------------------------------------------
16+
17+
module.exports = {
18+
meta: {
19+
docs: {
20+
description: 'enforce unified spacing in mustache interpolations.',
21+
category: 'Stylistic Issues',
22+
recommended: false
23+
},
24+
fixable: 'whitespace',
25+
schema: [
26+
{
27+
enum: ['always', 'never']
28+
}
29+
]
30+
},
31+
32+
create (context) {
33+
const options = context.options[0]
34+
const optSpaces = options !== 'never'
35+
const template = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore()
36+
37+
// ----------------------------------------------------------------------
38+
// Helpers
39+
// ----------------------------------------------------------------------
40+
41+
function checkTokens (leftToken, rightToken) {
42+
if (leftToken.loc.end.line === rightToken.loc.start.line) {
43+
const spaces = rightToken.loc.start.column - leftToken.loc.end.column
44+
const noSpacesFound = spaces === 0
45+
46+
if (optSpaces === noSpacesFound) {
47+
context.report({
48+
node: rightToken,
49+
loc: {
50+
start: leftToken.loc.end,
51+
end: rightToken.loc.start
52+
},
53+
message: 'Found {{spaces}} whitespaces, {{type}} expected.',
54+
data: {
55+
spaces: spaces === 0 ? 'none' : spaces,
56+
type: optSpaces ? '1' : 'none'
57+
},
58+
fix: (fixer) => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], optSpaces ? ' ' : '')
59+
})
60+
}
61+
}
62+
}
63+
64+
// ----------------------------------------------------------------------
65+
// Public
66+
// ----------------------------------------------------------------------
67+
68+
utils.registerTemplateBodyVisitor(context, {
69+
'VExpressionContainer[expression!=null]' (node) {
70+
const tokens = template.getTokens(node, {
71+
includeComments: true,
72+
filter: token => token.type !== 'HTMLWhitespace' // When there is only whitespace between ignore it
73+
})
74+
75+
const startToken = tokens.shift()
76+
if (!startToken || startToken.type !== 'VExpressionStart') return
77+
const endToken = tokens.pop()
78+
if (!endToken || endToken.type !== 'VExpressionEnd') return
79+
80+
if (tokens.length > 0) {
81+
checkTokens(startToken, tokens[0])
82+
checkTokens(tokens[tokens.length - 1], endToken)
83+
} else {
84+
checkTokens(startToken, endToken)
85+
}
86+
}
87+
})
88+
89+
return { }
90+
}
91+
}
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/**
2+
* @fileoverview enforce unified spacing in mustache interpolations.
3+
* @author Armano
4+
*/
5+
'use strict'
6+
7+
// ------------------------------------------------------------------------------
8+
// Requirements
9+
// ------------------------------------------------------------------------------
10+
11+
const rule = require('../../../lib/rules/mustache-interpolation-spacing')
12+
const RuleTester = require('eslint').RuleTester
13+
14+
// ------------------------------------------------------------------------------
15+
// Tests
16+
// ------------------------------------------------------------------------------
17+
18+
const ruleTester = new RuleTester({
19+
parser: 'vue-eslint-parser',
20+
parserOptions: { ecmaVersion: 2015 }
21+
})
22+
23+
ruleTester.run('mustache-interpolation-spacing', rule, {
24+
25+
valid: [
26+
{
27+
filename: 'test.vue',
28+
code: '<template></template>'
29+
},
30+
{
31+
filename: 'test.vue',
32+
code: '<template><div></div></template>'
33+
},
34+
{
35+
filename: 'test.vue',
36+
code: '<template> <div id=" "></div> </template>'
37+
},
38+
{
39+
filename: 'test.vue',
40+
code: '<template> <div :style=" " :class=" foo " v-if=foo ></div> </template>'
41+
},
42+
{
43+
filename: 'test.vue',
44+
code: '<template><div>{{ text }}</div></template>'
45+
},
46+
{
47+
filename: 'test.vue',
48+
code: '<template><div>{{ }}</div></template>'
49+
},
50+
{
51+
filename: 'test.vue',
52+
code: '<template><div>{{ }}</div></template>',
53+
options: ['always']
54+
},
55+
{
56+
filename: 'test.vue',
57+
code: '<template><div>{{}}</div></template>',
58+
options: ['never']
59+
},
60+
{
61+
filename: 'test.vue',
62+
code: '<template><div>{{text}}</div></template>',
63+
options: ['never']
64+
},
65+
{
66+
filename: 'test.vue',
67+
code: '<template><div>{{ text }}</div></template>',
68+
options: ['always']
69+
},
70+
{
71+
filename: 'test.vue',
72+
code: '<template><div>{{ }}</div></template>',
73+
options: ['always']
74+
},
75+
{
76+
filename: 'test.vue',
77+
code: '<template><div>{{ }}</div></template>',
78+
options: ['never']
79+
},
80+
{
81+
filename: 'test.vue',
82+
code: '<template><div>{{ text }}</div></template>',
83+
options: ['always']
84+
}
85+
],
86+
87+
invalid: [
88+
{
89+
filename: 'test.vue',
90+
code: '<template><div>{{ text}}</div></template>',
91+
output: '<template><div>{{ text }}</div></template>',
92+
options: ['always'],
93+
errors: [{
94+
message: 'Found none whitespaces, 1 expected.',
95+
type: 'VExpressionEnd'
96+
}]
97+
},
98+
{
99+
filename: 'test.vue',
100+
code: '<template><div>{{text }}</div></template>',
101+
output: '<template><div>{{ text }}</div></template>',
102+
options: ['always'],
103+
errors: [{
104+
message: 'Found none whitespaces, 1 expected.',
105+
type: 'Identifier'
106+
}]
107+
},
108+
{
109+
filename: 'test.vue',
110+
code: '<template><div>{{ text}}</div></template>',
111+
output: '<template><div>{{text}}</div></template>',
112+
options: ['never'],
113+
errors: [{
114+
message: 'Found 1 whitespaces, none expected.',
115+
type: 'Identifier'
116+
}]
117+
},
118+
{
119+
filename: 'test.vue',
120+
code: '<template><div>{{text }}</div></template>',
121+
output: '<template><div>{{text}}</div></template>',
122+
options: ['never'],
123+
errors: [{
124+
message: 'Found 1 whitespaces, none expected.',
125+
type: 'VExpressionEnd'
126+
}]
127+
},
128+
{
129+
filename: 'test.vue',
130+
code: '<template><div>{{text}}</div></template>',
131+
output: '<template><div>{{ text }}</div></template>',
132+
options: ['always'],
133+
errors: [{
134+
message: 'Found none whitespaces, 1 expected.',
135+
type: 'Identifier'
136+
}, {
137+
message: 'Found none whitespaces, 1 expected.',
138+
type: 'VExpressionEnd'
139+
}]
140+
},
141+
{
142+
filename: 'test.vue',
143+
code: '<template><div>{{ text }}</div></template>',
144+
output: '<template><div>{{text}}</div></template>',
145+
options: ['never'],
146+
errors: [{
147+
message: 'Found 1 whitespaces, none expected.',
148+
type: 'Identifier'
149+
}, {
150+
message: 'Found 1 whitespaces, none expected.',
151+
type: 'VExpressionEnd'
152+
}]
153+
},
154+
{
155+
filename: 'test.vue',
156+
code: '<template><div>{{ text }}</div></template>',
157+
output: '<template><div>{{text}}</div></template>',
158+
options: ['never'],
159+
errors: [{
160+
message: 'Found 3 whitespaces, none expected.',
161+
type: 'Identifier'
162+
}, {
163+
message: 'Found 3 whitespaces, none expected.',
164+
type: 'VExpressionEnd'
165+
}]
166+
}
167+
]
168+
})

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /