12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 |
- /**
- * @author Toru Nagashima
- * @copyright 2016 Toru Nagashima. All rights reserved.
- * See LICENSE file in root directory for full license.
- */
- 'use strict'
- // ------------------------------------------------------------------------------
- // Requirements
- // ------------------------------------------------------------------------------
- const utils = require('../utils')
- // ------------------------------------------------------------------------------
- // Helpers
- // ------------------------------------------------------------------------------
- function getPhrase (lineBreaks) {
- switch (lineBreaks) {
- case 0: return 'no line breaks'
- case 1: return '1 line break'
- default: return `${lineBreaks} line breaks`
- }
- }
- // ------------------------------------------------------------------------------
- // Rule Definition
- // ------------------------------------------------------------------------------
- module.exports = {
- meta: {
- type: 'layout',
- docs: {
- description: "require or disallow a line break before tag's closing brackets",
- category: 'strongly-recommended',
- url: 'https://eslint.vuejs.org/rules/html-closing-bracket-newline.html'
- },
- fixable: 'whitespace',
- schema: [{
- type: 'object',
- properties: {
- 'singleline': { enum: ['always', 'never'] },
- 'multiline': { enum: ['always', 'never'] }
- },
- additionalProperties: false
- }]
- },
- create (context) {
- const options = Object.assign({}, {
- singleline: 'never',
- multiline: 'always'
- }, context.options[0] || {})
- const template = context.parserServices.getTemplateBodyTokenStore && context.parserServices.getTemplateBodyTokenStore()
- return utils.defineTemplateBodyVisitor(context, {
- 'VStartTag, VEndTag' (node) {
- const closingBracketToken = template.getLastToken(node)
- if (closingBracketToken.type !== 'HTMLSelfClosingTagClose' && closingBracketToken.type !== 'HTMLTagClose') {
- return
- }
- const prevToken = template.getTokenBefore(closingBracketToken)
- const type = (node.loc.start.line === prevToken.loc.end.line) ? 'singleline' : 'multiline'
- const expectedLineBreaks = (options[type] === 'always') ? 1 : 0
- const actualLineBreaks = (closingBracketToken.loc.start.line - prevToken.loc.end.line)
- if (actualLineBreaks !== expectedLineBreaks) {
- context.report({
- node,
- loc: {
- start: prevToken.loc.end,
- end: closingBracketToken.loc.start
- },
- message: 'Expected {{expected}} before closing bracket, but {{actual}} found.',
- data: {
- expected: getPhrase(expectedLineBreaks),
- actual: getPhrase(actualLineBreaks)
- },
- fix (fixer) {
- const range = [prevToken.range[1], closingBracketToken.range[0]]
- const text = '\n'.repeat(expectedLineBreaks)
- return fixer.replaceTextRange(range, text)
- }
- })
- }
- }
- })
- }
- }
|