Skip to content

Commit 95fd13f

Browse files
New Add vue/new-line-between-multiline-property rule (#1080)
* feat: init commit * feat: add test, make rule configurable * docs: update docπŸ“– * chore: update version * lint fix * test: πŸ’ add test case * test: πŸ’ fix report when multi-line-property in callExpression * test: πŸ’ fix test in change request * test: πŸ’ js doc * test: πŸ’ Vue.component() * docs: ✏️ docs * fix: πŸ› using sourceCode api * fix: πŸ› using getTokenBewteen instead of getAlltoken * fix: πŸ› lint error
1 parent 4a141ce commit 95fd13f

File tree

7 files changed

+837
-0
lines changed

7 files changed

+837
-0
lines changed

β€Ždocs/.vuepress/public/favicon.png

-1 Bytes
Loading

β€Ždocs/rules/README.md

+1
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ For example:
293293
| [vue/html-comment-content-spacing](./html-comment-content-spacing.md) | enforce unified spacing in HTML comments | :wrench: |
294294
| [vue/html-comment-indent](./html-comment-indent.md) | enforce consistent indentation in HTML comments | :wrench: |
295295
| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | |
296+
| [vue/new-line-between-multi-line-property](./new-line-between-multi-line-property.md) | enforce new lines between multi-line properties in Vue components | :wrench: |
296297
| [vue/no-bare-strings-in-template](./no-bare-strings-in-template.md) | disallow the use of bare strings in `<template>` | |
297298
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
298299
| [vue/no-duplicate-attr-inheritance](./no-duplicate-attr-inheritance.md) | enforce `inheritAttrs` to be set to `false` when using `v-bind="$attrs"` | |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
---
2+
pageClass: rule-details
3+
sidebarDepth: 0
4+
title: vue/new-line-between-multi-line-property
5+
description: enforce new lines between multi-line properties in Vue components
6+
---
7+
# vue/new-line-between-multi-line-property
8+
> enforce new lines between multi-line properties in Vue components
9+
10+
- :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.
11+
12+
## :book: Rule Details
13+
14+
This rule aims at enforcing new lines between multi-line properties in Vue components to help readability
15+
16+
Examples of **incorrect** code for this rule:
17+
18+
<eslint-code-block fix :rules="{'vue/new-line-between-multi-line-property': ['error']}">
19+
20+
```vue
21+
<script>
22+
export default {
23+
props: {
24+
value: {
25+
type: String,
26+
required: true
27+
},
28+
focused: {
29+
type: Boolean,
30+
default: false,
31+
required: true
32+
},
33+
34+
label: String,
35+
icon: String
36+
},
37+
computed: {
38+
39+
}
40+
}
41+
</script>
42+
```
43+
44+
</eslint-code-block>
45+
46+
47+
Examples of **correct** code for this rule:
48+
49+
<eslint-code-block fix :rules="{'vue/new-line-between-multi-line-property': ['error']}">
50+
51+
```vue
52+
<script>
53+
export default {
54+
props: {
55+
value: {
56+
type: String,
57+
required: true
58+
},
59+
60+
focused: {
61+
type: Boolean,
62+
default: false,
63+
required: true
64+
},
65+
66+
label: String,
67+
icon: String
68+
},
69+
70+
computed: {
71+
72+
}
73+
}
74+
</script>
75+
```
76+
77+
</eslint-code-block>
78+
79+
## :wrench: Option
80+
```json
81+
{
82+
"vue/new-line-between-multiline-property": ["error", {
83+
"minLineOfMultilineProperty": 2
84+
}]
85+
}
86+
```
87+
- `minLineOfMultilineProperty` ... `type: number`, Define the minimum number of rows for a multi-line property .`type:` number, `default:` 2 , `min:`: 2
88+
## :books: Further Reading
89+
Nothing here
90+
## :mag: Implementation
91+
92+
- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/new-line-between-multi-line-property.js)
93+
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/new-line-between-multi-line-property.js)

β€Žlib/configs/no-layout-rules.js

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ module.exports = {
3030
'vue/max-len': 'off',
3131
'vue/multiline-html-element-content-newline': 'off',
3232
'vue/mustache-interpolation-spacing': 'off',
33+
'vue/new-line-between-multi-line-property': 'off',
3334
'vue/no-extra-parens': 'off',
3435
'vue/no-multi-spaces': 'off',
3536
'vue/no-spaces-around-equal-signs-in-attribute': 'off',

β€Žlib/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ module.exports = {
4747
'multiline-html-element-content-newline': require('./rules/multiline-html-element-content-newline'),
4848
'mustache-interpolation-spacing': require('./rules/mustache-interpolation-spacing'),
4949
'name-property-casing': require('./rules/name-property-casing'),
50+
'new-line-between-multi-line-property': require('./rules/new-line-between-multi-line-property'),
5051
'no-arrow-functions-in-watch': require('./rules/no-arrow-functions-in-watch'),
5152
'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
5253
'no-bare-strings-in-template': require('./rules/no-bare-strings-in-template'),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
* @fileoverview Enforce new lines between multi-line properties in Vue components.
3+
* @author IWANABETHATGUY
4+
*/
5+
'use strict'
6+
7+
const utils = require('../utils')
8+
// ------------------------------------------------------------------------------
9+
// Rule Definition
10+
// ------------------------------------------------------------------------------
11+
// @ts-ignore
12+
module.exports = {
13+
meta: {
14+
type: 'layout',
15+
docs: {
16+
description:
17+
'enforce new lines between multi-line properties in Vue components',
18+
categories: undefined,
19+
url:
20+
'https://eslint.vuejs.org/rules/new-line-between-multi-line-property.html'
21+
},
22+
fixable: 'whitespace', // or "code" or "whitespace"
23+
schema: [
24+
{
25+
type: 'object',
26+
properties: {
27+
// number of line you want to insert after multi-line property
28+
minLineOfMultilineProperty: {
29+
type: 'number',
30+
minimum: 2
31+
}
32+
}
33+
}
34+
]
35+
},
36+
37+
/** @param {RuleContext} context */
38+
create(context) {
39+
// always insert one line
40+
const insertLine = 1
41+
42+
let minLineOfMultilineProperty = 2
43+
if (
44+
context.options &&
45+
context.options[0] &&
46+
context.options[0].minLineOfMultilineProperty
47+
) {
48+
minLineOfMultilineProperty = context.options[0].minLineOfMultilineProperty
49+
}
50+
51+
/** @type {any[]} */
52+
const callStack = []
53+
const sourceCode = context.getSourceCode()
54+
return Object.assign(
55+
utils.defineVueVisitor(context, {
56+
CallExpression(node) {
57+
callStack.push(node)
58+
},
59+
'CallExpression:exit'() {
60+
callStack.pop()
61+
},
62+
63+
/**
64+
* @param {ObjectExpression} node
65+
*/
66+
ObjectExpression(node) {
67+
if (callStack.length) {
68+
return
69+
}
70+
const properties = node.properties
71+
for (let i = 1; i < properties.length; i++) {
72+
const cur = properties[i]
73+
const pre = properties[i - 1]
74+
75+
const leadingComments = sourceCode
76+
.getTokensBetween(pre, cur, { includeComments: true })
77+
.filter((token) => ['Line', 'Block'].includes(token.type))
78+
const lineCountOfPreProperty =
79+
pre.loc.end.line - pre.loc.start.line + 1
80+
let curStartLine = cur.loc.start.line
81+
if (leadingComments.length) {
82+
curStartLine = leadingComments[0].loc.start.line
83+
}
84+
const lineCountBetweenCurAndPreProperty =
85+
curStartLine - pre.loc.end.line - 1
86+
if (
87+
lineCountOfPreProperty >= minLineOfMultilineProperty &&
88+
lineCountBetweenCurAndPreProperty < insertLine
89+
) {
90+
context.report({
91+
node: pre,
92+
loc: pre.loc,
93+
message:
94+
'Enforce new lines between multi-line properties in Vue components.',
95+
// @ts-ignore
96+
fix(fixer) {
97+
let firstPositionOfLine = cur.range[0] - cur.loc.start.column
98+
if (leadingComments.length) {
99+
const firstComment = leadingComments[0]
100+
firstPositionOfLine =
101+
firstComment.range[0] - firstComment.loc.start.column
102+
}
103+
// this action equal to insert number of line before node
104+
return fixer.insertTextAfterRange(
105+
[firstPositionOfLine, firstPositionOfLine],
106+
'\n'
107+
// to avoid conflict with no-multiple-empty-lines, only insert one newline
108+
)
109+
}
110+
})
111+
}
112+
}
113+
}
114+
})
115+
)
116+
}
117+
}

0 commit comments

Comments
Β (0)