Skip to content

Commit

Permalink
New Add vue/new-line-between-multiline-property rule (#1080)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
IWANABETHATGUY committed Dec 16, 2020
1 parent 4a141ce commit 95fd13f
Show file tree
Hide file tree
Showing 7 changed files with 837 additions and 0 deletions.
Binary file modified docs/.vuepress/public/favicon.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions docs/rules/README.md
Expand Up @@ -293,6 +293,7 @@ For example:
| [vue/html-comment-content-spacing](./html-comment-content-spacing.md) | enforce unified spacing in HTML comments | :wrench: |
| [vue/html-comment-indent](./html-comment-indent.md) | enforce consistent indentation in HTML comments | :wrench: |
| [vue/match-component-file-name](./match-component-file-name.md) | require component name property to match its file name | |
| [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: |
| [vue/no-bare-strings-in-template](./no-bare-strings-in-template.md) | disallow the use of bare strings in `<template>` | |
| [vue/no-boolean-default](./no-boolean-default.md) | disallow boolean defaults | :wrench: |
| [vue/no-duplicate-attr-inheritance](./no-duplicate-attr-inheritance.md) | enforce `inheritAttrs` to be set to `false` when using `v-bind="$attrs"` | |
Expand Down
93 changes: 93 additions & 0 deletions docs/rules/new-line-between-multi-line-property.md
@@ -0,0 +1,93 @@
---
pageClass: rule-details
sidebarDepth: 0
title: vue/new-line-between-multi-line-property
description: enforce new lines between multi-line properties in Vue components
---
# vue/new-line-between-multi-line-property
> enforce new lines between multi-line properties in Vue components
- :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.

## :book: Rule Details

This rule aims at enforcing new lines between multi-line properties in Vue components to help readability

Examples of **incorrect** code for this rule:

<eslint-code-block fix :rules="{'vue/new-line-between-multi-line-property': ['error']}">

```vue
<script>
export default {
props: {
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false,
required: true
},
label: String,
icon: String
},
computed: {
}
}
</script>
```

</eslint-code-block>


Examples of **correct** code for this rule:

<eslint-code-block fix :rules="{'vue/new-line-between-multi-line-property': ['error']}">

```vue
<script>
export default {
props: {
value: {
type: String,
required: true
},
focused: {
type: Boolean,
default: false,
required: true
},
label: String,
icon: String
},
computed: {
}
}
</script>
```

</eslint-code-block>

## :wrench: Option
```json
{
"vue/new-line-between-multiline-property": ["error", {
"minLineOfMultilineProperty": 2
}]
}
```
- `minLineOfMultilineProperty` ... `type: number`, Define the minimum number of rows for a multi-line property .`type:` number, `default:` 2 , `min:`: 2
## :books: Further Reading
Nothing here
## :mag: Implementation

- [Rule source](https://github.com/vuejs/eslint-plugin-vue/blob/master/lib/rules/new-line-between-multi-line-property.js)
- [Test source](https://github.com/vuejs/eslint-plugin-vue/blob/master/tests/lib/rules/new-line-between-multi-line-property.js)
1 change: 1 addition & 0 deletions lib/configs/no-layout-rules.js
Expand Up @@ -30,6 +30,7 @@ module.exports = {
'vue/max-len': 'off',
'vue/multiline-html-element-content-newline': 'off',
'vue/mustache-interpolation-spacing': 'off',
'vue/new-line-between-multi-line-property': 'off',
'vue/no-extra-parens': 'off',
'vue/no-multi-spaces': 'off',
'vue/no-spaces-around-equal-signs-in-attribute': 'off',
Expand Down
1 change: 1 addition & 0 deletions lib/index.js
Expand Up @@ -47,6 +47,7 @@ module.exports = {
'multiline-html-element-content-newline': require('./rules/multiline-html-element-content-newline'),
'mustache-interpolation-spacing': require('./rules/mustache-interpolation-spacing'),
'name-property-casing': require('./rules/name-property-casing'),
'new-line-between-multi-line-property': require('./rules/new-line-between-multi-line-property'),
'no-arrow-functions-in-watch': require('./rules/no-arrow-functions-in-watch'),
'no-async-in-computed-properties': require('./rules/no-async-in-computed-properties'),
'no-bare-strings-in-template': require('./rules/no-bare-strings-in-template'),
Expand Down
117 changes: 117 additions & 0 deletions lib/rules/new-line-between-multi-line-property.js
@@ -0,0 +1,117 @@
/**
* @fileoverview Enforce new lines between multi-line properties in Vue components.
* @author IWANABETHATGUY
*/
'use strict'

const utils = require('../utils')
// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------
// @ts-ignore
module.exports = {
meta: {
type: 'layout',
docs: {
description:
'enforce new lines between multi-line properties in Vue components',
categories: undefined,
url:
'https://eslint.vuejs.org/rules/new-line-between-multi-line-property.html'
},
fixable: 'whitespace', // or "code" or "whitespace"
schema: [
{
type: 'object',
properties: {
// number of line you want to insert after multi-line property
minLineOfMultilineProperty: {
type: 'number',
minimum: 2
}
}
}
]
},

/** @param {RuleContext} context */
create(context) {
// always insert one line
const insertLine = 1

let minLineOfMultilineProperty = 2
if (
context.options &&
context.options[0] &&
context.options[0].minLineOfMultilineProperty
) {
minLineOfMultilineProperty = context.options[0].minLineOfMultilineProperty
}

/** @type {any[]} */
const callStack = []
const sourceCode = context.getSourceCode()
return Object.assign(
utils.defineVueVisitor(context, {
CallExpression(node) {
callStack.push(node)
},
'CallExpression:exit'() {
callStack.pop()
},

/**
* @param {ObjectExpression} node
*/
ObjectExpression(node) {
if (callStack.length) {
return
}
const properties = node.properties
for (let i = 1; i < properties.length; i++) {
const cur = properties[i]
const pre = properties[i - 1]

const leadingComments = sourceCode
.getTokensBetween(pre, cur, { includeComments: true })
.filter((token) => ['Line', 'Block'].includes(token.type))
const lineCountOfPreProperty =
pre.loc.end.line - pre.loc.start.line + 1
let curStartLine = cur.loc.start.line
if (leadingComments.length) {
curStartLine = leadingComments[0].loc.start.line
}
const lineCountBetweenCurAndPreProperty =
curStartLine - pre.loc.end.line - 1
if (
lineCountOfPreProperty >= minLineOfMultilineProperty &&
lineCountBetweenCurAndPreProperty < insertLine
) {
context.report({
node: pre,
loc: pre.loc,
message:
'Enforce new lines between multi-line properties in Vue components.',
// @ts-ignore
fix(fixer) {
let firstPositionOfLine = cur.range[0] - cur.loc.start.column
if (leadingComments.length) {
const firstComment = leadingComments[0]
firstPositionOfLine =
firstComment.range[0] - firstComment.loc.start.column
}
// this action equal to insert number of line before node
return fixer.insertTextAfterRange(
[firstPositionOfLine, firstPositionOfLine],
'\n'
// to avoid conflict with no-multiple-empty-lines, only insert one newline
)
}
})
}
}
}
})
)
}
}

0 comments on commit 95fd13f

Please sign in to comment.