diff --git a/docs/rules/html-closing-bracket-newline.md b/docs/rules/html-closing-bracket-newline.md
index ac6c505d8..f47d4ac7b 100644
--- a/docs/rules/html-closing-bracket-newline.md
+++ b/docs/rules/html-closing-bracket-newline.md
@@ -5,6 +5,7 @@ title: vue/html-closing-bracket-newline
description: require or disallow a line break before tag's closing brackets
since: v4.1.0
---
+
# vue/html-closing-bracket-newline
> require or disallow a line break before tag's closing brackets
@@ -58,19 +59,31 @@ This rule aims to warn the right angle brackets which are at the location other
```json
{
- "vue/html-closing-bracket-newline": ["error", {
- "singleline": "never",
- "multiline": "always"
- }]
+ "vue/html-closing-bracket-newline": [
+ "error",
+ {
+ "singleline": "never",
+ "multiline": "always",
+ "selfClosingTag": {
+ "singleline": "never",
+ "multiline": "always"
+ }
+ }
+ ]
}
```
-- `singleline` ... the configuration for single-line elements. It's a single-line element if the element does not have attributes or the last attribute is on the same line as the opening bracket.
- - `"never"` (default) ... disallow line breaks before the closing bracket.
- - `"always"` ... require one line break before the closing bracket.
-- `multiline` ... the configuration for multiline elements. It's a multiline element if the last attribute is not on the same line of the opening bracket.
- - `"never"` ... disallow line breaks before the closing bracket.
- - `"always"` (default) ... require one line break before the closing bracket.
+- `singleline` (`"never"` by default) ... the configuration for single-line elements. It's a single-line element if the element does not have attributes or the last attribute is on the same line as the opening bracket.
+- `multiline` (`"always"` by default) ... the configuration for multiline elements. It's a multiline element if the last attribute is not on the same line of the opening bracket.
+- `selfClosingTag.singleline` ... the configuration for single-line self closing elements.
+- `selfClosingTag.multiline` ... the configuration for multiline self closing elements.
+
+Every option can be set to one of the following values:
+
+- `"always"` ... require one line break before the closing bracket.
+- `"never"` ... disallow line breaks before the closing bracket.
+
+If `selfClosingTag` is not specified, the `singleline` and `multiline` options are inherited for self-closing tags.
Plus, you can use [`vue/html-indent`](./html-indent.md) rule to enforce indent-level of the closing brackets.
@@ -95,6 +108,25 @@ Plus, you can use [`vue/html-indent`](./html-indent.md) rule to enforce indent-l
+### `"selfClosingTag": { "multiline": "always" }`
+
+
+
+```vue
+
+
+
+
+
+
+
+```
+
+
+
## :rocket: Version
This rule was introduced in eslint-plugin-vue v4.1.0
diff --git a/lib/rules/html-closing-bracket-newline.js b/lib/rules/html-closing-bracket-newline.js
index c353c35d3..58f7fc8e8 100644
--- a/lib/rules/html-closing-bracket-newline.js
+++ b/lib/rules/html-closing-bracket-newline.js
@@ -24,6 +24,45 @@ function getPhrase(lineBreaks) {
}
}
+/**
+ * @typedef LineBreakBehavior
+ * @type {('always'|'never')}
+ */
+
+/**
+ * @typedef LineType
+ * @type {('singleline'|'multiline')}
+ */
+
+/**
+ * @typedef RuleOptions
+ * @type {object}
+ * @property {LineBreakBehavior} singleline - The behavior for single line tags.
+ * @property {LineBreakBehavior} multiline - The behavior for multiline tags.
+ * @property {object} selfClosingTag
+ * @property {LineBreakBehavior} selfClosingTag.singleline - The behavior for single line self closing tags.
+ * @property {LineBreakBehavior} selfClosingTag.multiline - The behavior for multiline self closing tags.
+ */
+
+/**
+ * @param {VStartTag | VEndTag} node - The node representing a start or end tag.
+ * @param {RuleOptions} options - The options for line breaks.
+ * @param {LineType} type - The type of line break.
+ * @returns {number} - The expected line breaks.
+ */
+function getExpectedLineBreaks(node, options, type) {
+ const isSelfClosingTag = node.type === 'VStartTag' && node.selfClosing
+ if (
+ isSelfClosingTag &&
+ options.selfClosingTag &&
+ options.selfClosingTag[type]
+ ) {
+ return options.selfClosingTag[type] === 'always' ? 1 : 0
+ }
+
+ return options[type] === 'always' ? 1 : 0
+}
+
module.exports = {
meta: {
type: 'layout',
@@ -39,7 +78,16 @@ module.exports = {
type: 'object',
properties: {
singleline: { enum: ['always', 'never'] },
- multiline: { enum: ['always', 'never'] }
+ multiline: { enum: ['always', 'never'] },
+ selfClosingTag: {
+ type: 'object',
+ properties: {
+ singleline: { enum: ['always', 'never'] },
+ multiline: { enum: ['always', 'never'] }
+ },
+ additionalProperties: false,
+ minProperties: 1
+ }
},
additionalProperties: false
}
@@ -80,7 +128,9 @@ module.exports = {
node.loc.start.line === prevToken.loc.end.line
? 'singleline'
: 'multiline'
- const expectedLineBreaks = options[type] === 'always' ? 1 : 0
+
+ const expectedLineBreaks = getExpectedLineBreaks(node, options, type)
+
const actualLineBreaks =
closingBracketToken.loc.start.line - prevToken.loc.end.line
diff --git a/tests/lib/rules/html-closing-bracket-newline.js b/tests/lib/rules/html-closing-bracket-newline.js
index 523b2d53a..3a032ba86 100644
--- a/tests/lib/rules/html-closing-bracket-newline.js
+++ b/tests/lib/rules/html-closing-bracket-newline.js
@@ -116,6 +116,42 @@ tester.run('html-closing-bracket-newline', rule, {
}
]
},
+ {
+ code: `
+
+
+
+
+ `,
+ options: [
+ {
+ selfClosingTag: {
+ singleline: 'never',
+ multiline: 'always'
+ }
+ }
+ ]
+ },
+ {
+ code: `
+
+
+
+
+ `,
+ options: [
+ {
+ selfClosingTag: {
+ singleline: 'always',
+ multiline: 'never'
+ }
+ }
+ ]
+ },
// Ignore if no closing brackets
`
@@ -479,6 +515,106 @@ tester.run('html-closing-bracket-newline', rule, {
endColumn: 23
}
]
+ },
+ {
+ code: `
+
+
+
+ `,
+ output: `
+
+
+
+ `,
+ options: [
+ {
+ selfClosingTag: {
+ singleline: 'never',
+ multiline: 'always'
+ }
+ }
+ ],
+ errors: [
+ 'Expected no line breaks before closing bracket, but 1 line break found.'
+ ]
+ },
+ {
+ code: `
+
+
+
+ `,
+ output: `
+
+
+
+ `,
+ options: [
+ {
+ selfClosingTag: {
+ singleline: 'never',
+ multiline: 'always'
+ }
+ }
+ ],
+ errors: [
+ 'Expected 1 line break before closing bracket, but no line breaks found.'
+ ]
+ },
+ {
+ code: `
+
+
+
+ `,
+ output: `
+
+
+
+ `,
+ options: [
+ {
+ selfClosingTag: {
+ singleline: 'always',
+ multiline: 'never'
+ }
+ }
+ ],
+ errors: [
+ 'Expected 1 line break before closing bracket, but no line breaks found.'
+ ]
+ },
+ {
+ code: `
+
+
+
+ `,
+ output: `
+
+
+
+ `,
+ options: [
+ {
+ selfClosingTag: {
+ singleline: 'always',
+ multiline: 'never'
+ }
+ }
+ ],
+ errors: [
+ 'Expected no line breaks before closing bracket, but 1 line break found.'
+ ]
}
]
})