From 7a056dc45f01d0da29dfd2178aa32d1410709118 Mon Sep 17 00:00:00 2001 From: Armano Date: Thu, 3 Aug 2017 00:55:37 +0200 Subject: [PATCH 1/2] Update vue-eslint-parser to version 2.0.0-beta.3 --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3496e7ced..21b7a2a59 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3198,9 +3198,9 @@ "dev": true }, "vue-eslint-parser": { - "version": "2.0.0-beta.2", - "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.0-beta.2.tgz", - "integrity": "sha512-bcoX+jDpF7xY3nbPK9W6yBiH7I0WOFA1SU0LnYkusZzY6ZRGbJWOiyNpl1TWAkNmLH0Az2uGVVnzsBVB1aSl6w==", + "version": "2.0.0-beta.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-2.0.0-beta.3.tgz", + "integrity": "sha512-/h9CORTgmIPEsu6PKXY5IbNzcwCkb1aV5mpnSojwNcShdWi+VKXi95HMnpiWuLAa3M6Hh2tMENwR/twyrX3h1w==", "requires": { "debug": "2.6.8", "eslint-scope": "3.7.1", diff --git a/package.json b/package.json index c6bc95c0a..2c1457f89 100644 --- a/package.json +++ b/package.json @@ -45,7 +45,7 @@ }, "dependencies": { "requireindex": "^1.1.0", - "vue-eslint-parser": "^2.0.0-beta.2" + "vue-eslint-parser": "^2.0.0-beta.3" }, "devDependencies": { "@types/node": "^4.2.16", From a6342f4b17c2c053ca4e89f569ff3ffe7eaea8d3 Mon Sep 17 00:00:00 2001 From: Armano Date: Thu, 3 Aug 2017 00:56:02 +0200 Subject: [PATCH 2/2] Add rule `html-attributes-casing`. fixes #92 --- docs/rules/attribute-hyphenation.md | 53 +++++++++++ lib/rules/attribute-hyphenation.js | 76 +++++++++++++++ tests/lib/rules/attribute-hyphenation.js | 116 +++++++++++++++++++++++ 3 files changed, 245 insertions(+) create mode 100644 docs/rules/attribute-hyphenation.md create mode 100644 lib/rules/attribute-hyphenation.js create mode 100644 tests/lib/rules/attribute-hyphenation.js diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md new file mode 100644 index 000000000..7d83c9fad --- /dev/null +++ b/docs/rules/attribute-hyphenation.md @@ -0,0 +1,53 @@ +# Define if attributes on cusom components can be hyphened. (attribute-hyphenation) + +## :wrench: Options + +Default casing is set to `always` + +``` +'vue/attribute-hyphenation': [2, 'always'|'never'] +``` + +### `"always"` - Use hyphenated name. (It errors on upper case letters.) + +:+1: Examples of **correct** code`: + +```html + +``` + +:-1: Examples of **incorrect** code`: + +```html + +``` + +### `"never"` - Don't use hyphenated name. (It errors on hyphens except `data-` and `aria-`.) + +:+1: Examples of **correct** code`: + +```html + +``` + +:-1: Examples of **incorrect** code`: + +```html + +``` diff --git a/lib/rules/attribute-hyphenation.js b/lib/rules/attribute-hyphenation.js new file mode 100644 index 000000000..177b7a10a --- /dev/null +++ b/lib/rules/attribute-hyphenation.js @@ -0,0 +1,76 @@ +/** + * @fileoverview Define a style for the props casing in templates. + * @author Armano + */ +'use strict' + +const utils = require('../utils') +const casing = require('../utils/casing') + +// ------------------------------------------------------------------------------ +// Rule Definition +// ------------------------------------------------------------------------------ + +function create (context) { + const sourceCode = context.getSourceCode() + const options = context.options[0] + const useHyphenated = options !== 'never' + + const caseConverter = casing.getConverter(useHyphenated ? 'kebab-case' : 'camelCase') + + function reportIssue (node, name) { + const text = sourceCode.getText(node.key) + + context.report({ + node: node.key, + loc: node.loc, + message: useHyphenated ? "Attribute '{{text}}' must be hyphenated." : "Attribute '{{text}}' cann't be hyphenated.", + data: { + text + }, + fix: fixer => fixer.replaceText(node.key, text.replace(name, caseConverter(name))) + }) + } + + function isIgnoredAttribute (value) { + if (value.indexOf('data-') !== -1 || value.indexOf('aria-') !== -1) { + return true + } + return useHyphenated ? value.toLowerCase() === value : !/-/.test(value) + } + + // ---------------------------------------------------------------------- + // Public + // ---------------------------------------------------------------------- + + utils.registerTemplateBodyVisitor(context, { + VAttribute (node) { + if (!utils.isCustomComponent(node.parent.parent)) return + + const name = !node.directive ? node.key.rawName : node.key.name === 'bind' ? node.key.raw.argument : false + if (!name || isIgnoredAttribute(name)) return + + reportIssue(node, name) + } + }) + + return {} +} + +module.exports = { + meta: { + docs: { + description: 'Define a style for the props casing in templates.', + category: 'Stylistic Issues', + recommended: false + }, + fixable: 'code', + schema: [ + { + enum: ['always', 'never'] + } + ] + }, + + create +} diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js new file mode 100644 index 000000000..b5dabe4a0 --- /dev/null +++ b/tests/lib/rules/attribute-hyphenation.js @@ -0,0 +1,116 @@ +/** + * @fileoverview Define a style for the props casing in templates. + * @author Armano + */ +'use strict' + +// ------------------------------------------------------------------------------ +// Requirements +// ------------------------------------------------------------------------------ + +const rule = require('../../../lib/rules/attribute-hyphenation') + +const RuleTester = require('eslint').RuleTester + +// ------------------------------------------------------------------------------ +// Tests +// ------------------------------------------------------------------------------ + +const ruleTester = new RuleTester({ + parser: 'vue-eslint-parser', + parserOptions: { ecmaVersion: 2015 } +}) + +ruleTester.run('attribute-hyphenation', rule, { + + valid: [ + { + filename: 'test.vue', + code: '' + }, + { + filename: 'test.vue', + code: '', + options: ['always'] + }, + { + filename: 'test.vue', + code: '', + options: ['never'] + }, + { + filename: 'test.vue', + code: '', + options: ['never'] + } + ], + + invalid: [ + { + filename: 'test.vue', + code: '', + output: '', + options: ['never'], + errors: [{ + message: "Attribute 'my-prop' cann't be hyphenated.", + type: 'VIdentifier', + line: 1 + }] + }, + { + filename: 'test.vue', + code: '', + output: '', + options: ['always'], + errors: [{ + message: "Attribute 'MyProp' must be hyphenated.", + type: 'VIdentifier', + line: 1 + }] + }, + { + filename: 'test.vue', + code: '', + output: '', + options: ['never'], + errors: [{ + message: "Attribute ':my-prop' cann't be hyphenated.", + type: 'VDirectiveKey', + line: 1 + }] + }, + { + filename: 'test.vue', + code: '', + output: '', + options: ['always'], + errors: [{ + message: "Attribute ':MyProp' must be hyphenated.", + type: 'VDirectiveKey', + line: 1 + }] + }, + { + filename: 'test.vue', + code: '', + output: '', + options: ['never'], + errors: [{ + message: "Attribute 'v-bind:my-prop' cann't be hyphenated.", + type: 'VDirectiveKey', + line: 1 + }] + }, + { + filename: 'test.vue', + code: '', + output: '', + options: ['always'], + errors: [{ + message: "Attribute 'v-bind:MyProp' must be hyphenated.", + type: 'VDirectiveKey', + line: 1 + }] + } + ] +})