diff --git a/.gitignore b/.gitignore index a56cde83a..165f76571 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea /.nyc_output /coverage /tests/integrations/*/node_modules diff --git a/docs/rules/attribute-hyphenation.md b/docs/rules/attribute-hyphenation.md index e161172fb..3dfd9f152 100644 --- a/docs/rules/attribute-hyphenation.md +++ b/docs/rules/attribute-hyphenation.md @@ -1,17 +1,17 @@ -# enforce attribute naming style in template (vue/attribute-hyphenation) +# enforce attribute naming style on custom components in template (vue/attribute-hyphenation) - :gear: This rule is included in `"plugin:vue/strongly-recommended"` and `"plugin:vue/recommended"`. - :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. ## :wrench: Options -Default casing is set to `always` +Default casing is set to `always` with `['data-', 'aria-', 'slot-scope']` set to be ignored ``` -'vue/attribute-hyphenation': [2, 'always'|'never'] +'vue/attribute-hyphenation': [2, 'always'|'never', { 'ignore': ['custom-prop'] }] ``` -### `"always"` - Use hyphenated name. (It errors on upper case letters.) +### `[2, "always"]` - Use hyphenated name. (It errors on upper case letters.) :+1: Examples of **correct** code`: @@ -25,7 +25,7 @@ Default casing is set to `always` ``` -### `"never"` - Don't use hyphenated name. (It errors on hyphens except `data-` and `aria-`.) +### `[2, "never"]` - Don't use hyphenated name. (It errors on hyphens except `data-`, `aria-` and `slot-scope-`.) :+1: Examples of **correct** code`: @@ -38,3 +38,17 @@ Default casing is set to `always` ```html ``` + +### `[2, "never", { 'ignore': ['custom-prop'] }]` - Don't use hyphenated name but allow custom attributes + +:+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 index 8a394d42a..dc577256c 100644 --- a/lib/rules/attribute-hyphenation.js +++ b/lib/rules/attribute-hyphenation.js @@ -14,7 +14,7 @@ const casing = require('../utils/casing') module.exports = { meta: { docs: { - description: 'enforce attribute naming style in template', + description: 'enforce attribute naming style on custom components in template', category: 'strongly-recommended', url: 'https://github.com/vuejs/eslint-plugin-vue/blob/v4.4.0/docs/rules/attribute-hyphenation.md' }, @@ -22,14 +22,38 @@ module.exports = { schema: [ { enum: ['always', 'never'] + }, + { + type: 'object', + properties: { + 'ignore': { + type: 'array', + items: { + allOf: [ + { type: 'string' }, + { not: { type: 'string', pattern: ':exit$' }}, + { not: { type: 'string', pattern: '^\\s*$' }} + ] + }, + uniqueItems: true, + additionalItems: false + } + }, + additionalProperties: false } ] }, create (context) { const sourceCode = context.getSourceCode() - const options = context.options[0] - const useHyphenated = options !== 'never' + const option = context.options[0] + const optionsPayload = context.options[1] + const useHyphenated = option !== 'never' + const ignoredAttributes = ['data-', 'aria-', 'slot-scope'] + + if (optionsPayload && optionsPayload.ignore) { + ignoredAttributes.push(optionsPayload.ignore) + } const caseConverter = casing.getConverter(useHyphenated ? 'kebab-case' : 'camelCase') @@ -48,9 +72,14 @@ module.exports = { } function isIgnoredAttribute (value) { - if (value.indexOf('data-') !== -1 || value.indexOf('aria-') !== -1) { + const isIgnored = ignoredAttributes.some(function (attr) { + return value.indexOf(attr) !== -1 + }) + + if (isIgnored) { return true } + return useHyphenated ? value.toLowerCase() === value : !/-/.test(value) } diff --git a/tests/lib/rules/attribute-hyphenation.js b/tests/lib/rules/attribute-hyphenation.js index b5dabe4a0..340bd32d6 100644 --- a/tests/lib/rules/attribute-hyphenation.js +++ b/tests/lib/rules/attribute-hyphenation.js @@ -30,18 +30,23 @@ ruleTester.run('attribute-hyphenation', rule, { }, { filename: 'test.vue', - code: '', + code: '', options: ['always'] }, { filename: 'test.vue', - code: '', + code: '', options: ['never'] }, { filename: 'test.vue', - code: '', + code: '', options: ['never'] + }, + { + filename: 'test.vue', + code: '', + options: ['never', { 'ignore': ['custom-hypen'] }] } ],