diff --git a/docs/rules/prop-name-casing.md b/docs/rules/prop-name-casing.md index 1f9f82624..43598c783 100644 --- a/docs/rules/prop-name-casing.md +++ b/docs/rules/prop-name-casing.md @@ -39,12 +39,18 @@ export default { ```json { - "vue/prop-name-casing": ["error", "camelCase" | "snake_case"] + "vue/prop-name-casing": ["error", + "camelCase" | "snake_case", + { + "ignoreProps": [] + } + ] } ``` - `"camelCase"` (default) ... Enforce property names in `props` to camel case. - `"snake_case"` ... Enforce property names in `props` to snake case. +- `ignoreProps` (`string[]`) ... An array of prop names (or patterns) that don't need to follow the specified casing. ### `"snake_case"` @@ -67,6 +73,31 @@ export default { +### `"ignoreProps": ["foo-bar", "/^_[a-z]+/u"]` + + + +```vue + +``` + + + ## :couple: Related Rules - [vue/attribute-hyphenation](./attribute-hyphenation.md) diff --git a/lib/rules/prop-name-casing.js b/lib/rules/prop-name-casing.js index ba8fcc1b4..fd4f0dc31 100644 --- a/lib/rules/prop-name-casing.js +++ b/lib/rules/prop-name-casing.js @@ -6,6 +6,7 @@ const utils = require('../utils') const casing = require('../utils/casing') +const { toRegExp } = require('../utils/regexp') const allowedCaseOptions = ['camelCase', 'snake_case'] /** @@ -15,6 +16,8 @@ const allowedCaseOptions = ['camelCase', 'snake_case'] /** @param {RuleContext} context */ function create(context) { const options = context.options[0] + /** @type {RegExp[]} */ + const ignoreProps = (context.options[1]?.ignoreProps || []).map(toRegExp) const caseType = allowedCaseOptions.includes(options) ? options : 'camelCase' const checker = casing.getChecker(caseType) @@ -27,7 +30,7 @@ function create(context) { if (propName == null) { continue } - if (!checker(propName)) { + if (!checker(propName) && !ignoreProps.some((re) => re.test(propName))) { context.report({ node: item.node, messageId: 'invalidCase', @@ -64,6 +67,17 @@ module.exports = { schema: [ { enum: allowedCaseOptions + }, + { + type: 'object', + properties: { + ignoreProps: { + type: 'array', + items: { type: 'string' }, + uniqueItems: true + } + }, + additionalProperties: false } ], messages: { diff --git a/tests/lib/rules/prop-name-casing.js b/tests/lib/rules/prop-name-casing.js index 65748dc49..a83893a5a 100644 --- a/tests/lib/rules/prop-name-casing.js +++ b/tests/lib/rules/prop-name-casing.js @@ -149,7 +149,7 @@ ruleTester.run('prop-name-casing', rule, { languageOptions }, { - // valiable computed property name does not warn + // variable computed property name does not warn filename: 'test.vue', code: ` export default { @@ -161,7 +161,7 @@ ruleTester.run('prop-name-casing', rule, { languageOptions }, { - // valiable computed property name does not warn + // variable computed property name does not warn filename: 'test.vue', code: ` export default { @@ -359,6 +359,23 @@ ruleTester.run('prop-name-casing', rule, { parser: require.resolve('@typescript-eslint/parser') } } + }, + { + filename: 'test.vue', + code: ` + export default { + props: { + 'ignored-pattern-test': String, + ignored_prop: Number, + validProp: Boolean + } + } + `, + options: [ + 'camelCase', + { ignoreProps: ['ignored_prop', '/^ignored-pattern-/'] } + ], + languageOptions } ], @@ -686,6 +703,54 @@ ruleTester.run('prop-name-casing', rule, { } ] } - ]) + ]), + { + filename: 'test.vue', + code: ` + export default { + props: { + notIgnored_prop: String, + 'other-pattern': Number, + 'pattern-valid': String + } + } + `, + options: ['camelCase', { ignoreProps: ['ignored_prop', '/^pattern-/'] }], + languageOptions, + errors: [ + { + message: 'Prop "notIgnored_prop" is not in camelCase.', + type: 'Property', + line: 4 + }, + { + message: 'Prop "other-pattern" is not in camelCase.', + type: 'Property', + line: 5 + } + ] + }, + { + filename: 'test.vue', + code: ` + export default { + props: ['notIgnored_prop', 'pattern_invalid', 'validProp', 'pattern-valid'] + } + `, + options: ['camelCase', { ignoreProps: ['ignored_prop', '/^pattern-/'] }], + languageOptions, + errors: [ + { + message: 'Prop "notIgnored_prop" is not in camelCase.', + type: 'Literal', + line: 3 + }, + { + message: 'Prop "pattern_invalid" is not in camelCase.', + type: 'Literal', + line: 3 + } + ] + } ] })