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 cdd4163

Browse files
mysticateamichalsnik
authored andcommitted
[New] Add html-closing-bracket-newline (fixes #169) (#190)
* New: html-closing-bracket-newline (fixes #169) * update .md
1 parent 98cdafa commit cdd4163

File tree

4 files changed

+511
-0
lines changed

4 files changed

+511
-0
lines changed

‎README.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,13 @@ Enforce all the rules in this category, as well as all higher priority rules, wi
178178
| | [order-in-components](./docs/rules/order-in-components.md) | enforce order of properties in components |
179179
| | [this-in-template](./docs/rules/this-in-template.md) | enforce usage of `this` in template |
180180

181+
182+
### Uncategorized
183+
184+
| | Rule ID | Description |
185+
|:---|:--------|:------------|
186+
| :wrench: | [html-closing-bracket-newline](./docs/rules/html-closing-bracket-newline.md) | require or disallow a line break before tag's closing brackets |
187+
181188
<!--RULES_TABLE_END-->
182189

183190
## :couple: FAQ
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
# require or disallow a line break before tag's closing brackets (html-closing-bracket-newline)
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+
People have own preference about the location of closing brackets.
6+
This rule enforces a line break (or no line break) before tag's closing brackets.
7+
8+
```html
9+
<div
10+
id="foo"
11+
class="bar"> <!-- On the same line with the last attribute. -->
12+
</div>
13+
14+
<div
15+
id="foo"
16+
class="bar"
17+
> <!-- On the next line. -->
18+
</div>
19+
```
20+
21+
## Rule Details
22+
23+
```json
24+
{
25+
"html-closing-bracket-newline": ["error", {
26+
"singleline": "never",
27+
"multiline": "never"
28+
}]
29+
}
30+
```
31+
32+
- `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.
33+
- `"never"` ... disallow line breaks before the closing bracket. This is the default.
34+
- `"always"` ... require one line break before the closing bracket.
35+
- `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.
36+
- `"never"` ... disallow line breaks before the closing bracket. This is the default.
37+
- `"always"` ... require one line break before the closing bracket.
38+
39+
Plus, you can use [`vue/html-indent`](./html-indent.md) rule to enforce indent-level of the closing brackets.
40+
41+
:-1: Examples of **incorrect** code for this rule:
42+
43+
```html
44+
/*eslint html-closing-bracket-newline: "error"*/
45+
46+
<div id="foo" class="bar"
47+
>
48+
<div
49+
id="foo"
50+
class="bar"
51+
>
52+
<div
53+
id="foo"
54+
class="bar"
55+
>
56+
```
57+
58+
:+1: Examples of **correct** code for this rule:
59+
60+
```html
61+
/*eslint html-closing-bracket-newline: "error"*/
62+
63+
<div id="foo" class="bar">
64+
<div
65+
id="foo"
66+
class="bar">
67+
```
68+
69+
:-1: Examples of **incorrect** code for `{ "multiline": "always" }`:
70+
71+
```html
72+
/*eslint html-closing-bracket-newline: ["error", { multiline: always }]*/
73+
74+
<div id="foo" class="bar"
75+
>
76+
<div
77+
id="foo"
78+
class="bar">
79+
```
80+
81+
:+1: Examples of **correct** code for `{ "multiline": "always" }`:
82+
83+
```html
84+
/*eslint html-closing-bracket-newline: ["error", { multiline: always }]*/
85+
86+
<div id="foo" class="bar">
87+
<div
88+
id="foo"
89+
class="bar"
90+
>
91+
<div
92+
id="foo"
93+
class="bar"
94+
>
95+
```
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* @author Toru Nagashima
3+
* @copyright 2016 Toru Nagashima. All rights reserved.
4+
* See LICENSE file in root directory for full license.
5+
*/
6+
'use strict'
7+
8+
// ------------------------------------------------------------------------------
9+
// Requirements
10+
// ------------------------------------------------------------------------------
11+
12+
const utils = require('../utils')
13+
14+
// ------------------------------------------------------------------------------
15+
// Helpers
16+
// ------------------------------------------------------------------------------
17+
18+
function getPhrase (lineBreaks) {
19+
switch (lineBreaks) {
20+
case 0: return 'no line breaks'
21+
case 1: return '1 line break'
22+
default: return `${lineBreaks} line breaks`
23+
}
24+
}
25+
26+
/**
27+
* Creates AST event handlers for html-closing-bracket-newline.
28+
*
29+
* @param {RuleContext} context - The rule context.
30+
* @returns {object} AST event handlers.
31+
*/
32+
function create (context) {
33+
const options = context.options[0] || {}
34+
const template = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore()
35+
36+
return utils.defineTemplateBodyVisitor(context, {
37+
'VStartTag, VEndTag' (node) {
38+
const closingBracketToken = template.getLastToken(node)
39+
if (closingBracketToken.type !== 'HTMLSelfClosingTagClose' && closingBracketToken.type !== 'HTMLTagClose') {
40+
return
41+
}
42+
43+
const prevToken = template.getTokenBefore(closingBracketToken)
44+
const type = (node.loc.start.line === prevToken.loc.end.line) ? 'singleline' : 'multiline'
45+
const expectedLineBreaks = (options[type] === 'always') ? 1 : 0
46+
const actualLineBreaks = (closingBracketToken.loc.start.line - prevToken.loc.end.line)
47+
48+
if (actualLineBreaks !== expectedLineBreaks) {
49+
context.report({
50+
node,
51+
loc: {
52+
start: prevToken.loc.end,
53+
end: closingBracketToken.loc.start
54+
},
55+
message: 'Expected {{expected}} before closing bracket, but {{actual}} found.',
56+
data: {
57+
expected: getPhrase(expectedLineBreaks),
58+
actual: getPhrase(actualLineBreaks)
59+
},
60+
fix (fixer) {
61+
const range = [prevToken.range[1], closingBracketToken.range[0]]
62+
const text = '\n'.repeat(expectedLineBreaks)
63+
return fixer.replaceTextRange(range, text)
64+
}
65+
})
66+
}
67+
}
68+
})
69+
}
70+
71+
// ------------------------------------------------------------------------------
72+
// Rule Definition
73+
// ------------------------------------------------------------------------------
74+
75+
module.exports = {
76+
create,
77+
meta: {
78+
docs: {
79+
description: "require or disallow a line break before tag's closing brackets",
80+
category: undefined
81+
},
82+
fixable: 'whitespace',
83+
schema: [{
84+
type: 'object',
85+
properties: {
86+
'singleline': { enum: ['always', 'never'] },
87+
'multiline': { enum: ['always', 'never'] }
88+
},
89+
additionalProperties: false
90+
}]
91+
}
92+
}

0 commit comments

Comments
(0)

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