From e8d13cf7f412e0973ab18192197d4e2ee838b1bb Mon Sep 17 00:00:00 2001 From: Armano Date: Wed, 2 Aug 2017 22:23:26 +0200 Subject: [PATCH 1/2] Add `html-indent` rule. --- docs/rules/html-indent.md | 41 +++++++++++++++ lib/rules/html-indent.js | 93 ++++++++++++++++++++++++++++++++++ tests/lib/rules/html-indent.js | 86 +++++++++++++++++++++++++++++++ 3 files changed, 220 insertions(+) create mode 100644 docs/rules/html-indent.md create mode 100644 lib/rules/html-indent.js create mode 100644 tests/lib/rules/html-indent.js diff --git a/docs/rules/html-indent.md b/docs/rules/html-indent.md new file mode 100644 index 000000000..9786c3b13 --- /dev/null +++ b/docs/rules/html-indent.md @@ -0,0 +1,41 @@ +# Enforce consistent indentation in html template (html-indent) + +Please describe the origin of the rule here. + +## :book: Rule Details + +This rule aims to... + +Examples of **incorrect** code for this rule: + +```html + +``` + +Examples of **correct** code for this rule: + +```html + +``` + +## :wrench: Options + +This rule has a mixed option: + +For example, for 2-space indentation: + +``` +vue/html-indent: [2, 2] +``` + +Or for tabbed indentation: + +``` +vue/html-indent: [2, 'tab'] +``` diff --git a/lib/rules/html-indent.js b/lib/rules/html-indent.js new file mode 100644 index 000000000..56c938a1d --- /dev/null +++ b/lib/rules/html-indent.js @@ -0,0 +1,93 @@ +/** + * @fileoverview Enforce consistent indentation in html template + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const utils = require('../utils') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +function create (context) { + const indent = 2 + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + + function checkChildIndent (node, line, column) { + if (node.type !== 'VElement') return + + line++ + + const startLoc = node.startTag.loc.start + + if (startLoc.line <= line) { + context.report({ + node: node.startTag, + loc: node.loc, + message: 'Element has to be in new line.' + }) + } + + line = startLoc.line + + if (!node.selfClosing) { + // context.report({ + // node, + // loc: node.loc, + // message: 'Self-closing should not be used.' + // }) + + // const endLoc = node.endTag.loc + } + } + + // ---------------------------------------------------------------------- + // Public + // ---------------------------------------------------------------------- + + utils.registerTemplateBodyVisitor(context, { + 'VElement[startTag.id.name="template"]' (node) { + if (!node.selfClosing) { + let line = node.loc.start.line + for (const item of node.children) { + line = checkChildIndent(item, line, 1) + } + } + } + }) + + return {} +} + +module.exports = { + meta: { + docs: { + description: 'Enforce consistent indentation in html template', + category: 'Stylistic Issues', + recommended: false + }, + fixable: null, // or "code" or "whitespace" + schema: [ + { + oneOf: [ + { + enum: ['tab'] + }, + { + type: 'integer', + minimum: 0 + } + ] + } + ] + }, + + create +} diff --git a/tests/lib/rules/html-indent.js b/tests/lib/rules/html-indent.js new file mode 100644 index 000000000..6f48fbe4b --- /dev/null +++ b/tests/lib/rules/html-indent.js @@ -0,0 +1,86 @@ +/** + * @fileoverview Enforce consistent indentation in html template + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/html-indent') +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: 'vue-eslint-parser', + parserOptions: { ecmaVersion: 2015 } +}) +ruleTester.run('html-indent', rule, { + + valid: [ + { + filename: 'test.vue', + code: '', + options: [0] + }, + { + filename: 'test.vue', + code: '', + options: [2] + }, + { + filename: 'test.vue', + code: '', + options: ['tab'] + } + ], + + invalid: [ + { + filename: 'test.vue', + code: '', + errors: [{ + message: 'Element has to be in new line.', + type: 'Me too' + }] + }, + { + filename: 'test.vue', + code: '', + options: [2], + errors: [{ + message: 'Element has to be in new line.', + type: 'Me too' + }] + }, + { + filename: 'test.vue', + code: '', + options: [2], + errors: [{ + message: 'Element has to be in new line.', + type: 'Me too' + }] + }, + { + filename: 'test.vue', + code: '', + options: ['tab'], + errors: [{ + message: 'Element has to be in new line.', + type: 'Me too' + }] + }, + { + code: '', + errors: [{ + message: 'Element has to be in new line.', + type: 'Me too' + }] + } + ] +}) From ec6262fef085347ecb88e8fde51a02269645e5e9 Mon Sep 17 00:00:00 2001 From: Armano Date: Thu, 3 Aug 2017 00:31:23 +0200 Subject: [PATCH 2/2] Improve rule --- lib/rules/html-indent.js | 96 ++++++++++++++++++++++++---------- tests/lib/rules/html-indent.js | 86 +++++++++++++++++------------- 2 files changed, 117 insertions(+), 65 deletions(-) diff --git a/lib/rules/html-indent.js b/lib/rules/html-indent.js index 56c938a1d..265edb59a 100644 --- a/lib/rules/html-indent.js +++ b/lib/rules/html-indent.js @@ -10,42 +10,67 @@ const utils = require('../utils') +const REGEXP_VTEXT = /([^\r\n]*)([\r\n]*)([\s\t]*)$/g // Get last text + caret + whitespaces + // ------------------------------------------------------------------------------ // Rule Definition // ------------------------------------------------------------------------------ function create (context) { - const indent = 2 + const sourceCode = context.getSourceCode() + const options = context.options[0] || 2 + const indentCount = options === 'tab' ? 1 : options + const indentType = options === 'tab' ? 'tab' : 'space' + const tagIndent = options === 'tab' ? '\t' : ' '.repeat(options) + const attrIndent = tagIndent // TODO: add way to configure this + let currentIndent = -1 // Start at -1 for