Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ignoreTags option #2609

Merged
merged 12 commits into from
Nov 27, 2024
24 changes: 22 additions & 2 deletions docs/rules/attribute-hyphenation.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ This rule enforces using hyphenated attribute names on custom components in Vue
```json
{
"vue/attribute-hyphenation": ["error", "always" | "never", {
"ignore": []
"ignore": [],
"exclude": []
FloEdelmann marked this conversation as resolved.
Show resolved Hide resolved
}]
}
```
Expand All @@ -46,7 +47,8 @@ and all the [SVG attributes](https://developer.mozilla.org/en-US/docs/Web/SVG/At

- `"always"` (default) ... Use hyphenated name.
- `"never"` ... Don't use hyphenated name except the ones that are ignored.
waynzh marked this conversation as resolved.
Show resolved Hide resolved
- `"ignore"` ... Array of ignored names
- `"ignore"` ... Array of ignored names.
- `"exclude"` ... Array of exclude tag names.

### `"always"`

Expand Down Expand Up @@ -109,6 +111,24 @@ Don't use hyphenated name but allow custom attributes

</eslint-code-block>

### `"never", { "exclude": ["/^custom-/"] }`

Exclude tags from applying this rule.

<eslint-code-block fix :rules="{'vue/attribute-hyphenation': ['error', 'never', { exclude: ['/^custom-/'] }]}">

```vue
<template>
<!-- ✓ GOOD -->
<custom-component custom-prop="prop" />

<!-- ✗ BAD -->
<my-component custom-prop="prop" />
waynzh marked this conversation as resolved.
Show resolved Hide resolved
</template>
```

</eslint-code-block>

## :couple: Related Rules

- [vue/v-on-event-hyphenation](./v-on-event-hyphenation.md)
Expand Down
24 changes: 22 additions & 2 deletions docs/rules/v-on-event-hyphenation.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,16 @@ This rule enforces using hyphenated v-on event names on custom components in Vue
{
"vue/v-on-event-hyphenation": ["error", "always" | "never", {
"autofix": false,
"ignore": []
"ignore": [],
"exclude": []
}]
}
```

- `"always"` (default) ... Use hyphenated name.
- `"never"` ... Don't use hyphenated name.
waynzh marked this conversation as resolved.
Show resolved Hide resolved
- `"ignore"` ... Array of ignored names
- `"ignore"` ... Array of ignored names.
- `"exclude"` ... Array of exclude tag names.
- `"autofix"` ... If `true`, enable autofix. If you are using Vue 2, we recommend that you do not use it due to its side effects.

### `"always"`
Expand Down Expand Up @@ -104,6 +106,24 @@ Don't use hyphenated name but allow custom event names

</eslint-code-block>

### `"never", { "exclude": ["/^custom-/"] }`

Exclude tags from applying this rule.

<eslint-code-block fix :rules="{'vue/v-on-event-hyphenation': ['error', 'never', { exclude: ['/^custom-/'], autofix: true }]}">

```vue
<template>
<!-- ✓ GOOD -->
<custom-component v-on:custom-event="handleEvent" />

<!-- ✗ BAD -->
<my-component v-on:custom-event="handleEvent" />
waynzh marked this conversation as resolved.
Show resolved Hide resolved
</template>
```

</eslint-code-block>

## :couple: Related Rules

- [vue/custom-event-name-casing](./custom-event-name-casing.md)
Expand Down
23 changes: 21 additions & 2 deletions lib/rules/attribute-hyphenation.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

const utils = require('../utils')
const casing = require('../utils/casing')
const { toRegExp } = require('../utils/regexp')
const svgAttributes = require('../utils/svg-attributes-weird-case.json')

/**
Expand Down Expand Up @@ -56,6 +57,12 @@ module.exports = {
},
uniqueItems: true,
additionalItems: false
},
exclude: {
type: 'array',
items: { type: 'string' },
uniqueItems: true,
additionalItems: false
}
},
additionalProperties: false
Expand All @@ -72,6 +79,10 @@ module.exports = {
const option = context.options[0]
const optionsPayload = context.options[1]
const useHyphenated = option !== 'never'
/** @type {RegExp[]} */
const excludedTags = ((optionsPayload && optionsPayload.exclude) || []).map(
toRegExp
)
const ignoredAttributes = ['data-', 'aria-', 'slot-scope', ...svgAttributes]

if (optionsPayload && optionsPayload.ignore) {
Expand Down Expand Up @@ -130,11 +141,19 @@ module.exports = {
return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
}

/**
* @param {string} name
*/
waynzh marked this conversation as resolved.
Show resolved Hide resolved
function isExcludedTags(name) {
return excludedTags.some((re) => re.test(name))
}

return utils.defineTemplateBodyVisitor(context, {
VAttribute(node) {
const element = node.parent.parent
if (
!utils.isCustomComponent(node.parent.parent) &&
node.parent.parent.name !== 'slot'
(!utils.isCustomComponent(element) && element.name !== 'slot') ||
isExcludedTags(element.rawName)
)
return

Expand Down
26 changes: 25 additions & 1 deletion lib/rules/v-on-event-hyphenation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

const utils = require('../utils')
const casing = require('../utils/casing')
const { toRegExp } = require('../utils/regexp')

module.exports = {
meta: {
Expand Down Expand Up @@ -35,6 +36,12 @@ module.exports = {
},
uniqueItems: true,
additionalItems: false
},
exclude: {
type: 'array',
items: { type: 'string' },
uniqueItems: true,
additionalItems: false
}
},
additionalProperties: false
Expand All @@ -56,6 +63,10 @@ module.exports = {
const useHyphenated = option !== 'never'
/** @type {string[]} */
const ignoredAttributes = (optionsPayload && optionsPayload.ignore) || []
/** @type {RegExp[]} */
const excludedTags = ((optionsPayload && optionsPayload.exclude) || []).map(
toRegExp
)
const autofix = Boolean(optionsPayload && optionsPayload.autofix)

const caseConverter = casing.getConverter(
Expand Down Expand Up @@ -99,9 +110,22 @@ module.exports = {
return useHyphenated ? value.toLowerCase() === value : !/-/.test(value)
}

/**
* @param {string} name
*/
waynzh marked this conversation as resolved.
Show resolved Hide resolved
function isExcludedTags(name) {
return excludedTags.some((re) => re.test(name))
}

return utils.defineTemplateBodyVisitor(context, {
"VAttribute[directive=true][key.name.name='on']"(node) {
if (!utils.isCustomComponent(node.parent.parent)) return
const element = node.parent.parent
if (
!utils.isCustomComponent(element) ||
isExcludedTags(element.rawName)
) {
return
}
if (!node.key.argument || node.key.argument.type !== 'VIdentifier') {
return
}
Expand Down
32 changes: 32 additions & 0 deletions tests/lib/rules/attribute-hyphenation.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,16 @@ ruleTester.run('attribute-hyphenation', rule, {
filename: 'test.vue',
code: '<template><div><custom :myName.sync="prop"></custom></div></template>',
options: ['never']
},
{
filename: 'test.vue',
code: `
<template>
<VueComponent my-prop></VueComponent>
<custom-component my-prop></custom-component>
</template>
`,
options: ['never', { exclude: ['VueComponent', '/^custom-/'] }]
}
],

Expand Down Expand Up @@ -450,6 +460,28 @@ ruleTester.run('attribute-hyphenation', rule, {
line: 1
}
]
},
{
code: `
<template>
<custom my-prop/>
<CustomComponent my-prop/>
</template>
`,
output: `
<template>
<custom myProp/>
<CustomComponent my-prop/>
</template>
`,
options: ['never', { exclude: ['CustomComponent'] }],
errors: [
{
message: "Attribute 'my-prop' can't be hyphenated.",
type: 'VIdentifier',
line: 3
}
]
}
]
})
33 changes: 33 additions & 0 deletions tests/lib/rules/v-on-event-hyphenation.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,23 @@ tester.run('v-on-event-hyphenation', rule, {
</template>
`,
options: ['never', { ignore: ['custom'] }]
},
{
code: `
<template>
<VueComponent v-on:custom-event="events"/>
</template>
`,
options: ['never', { ignore: ['custom-event'] }]
},
{
code: `
<template>
<VueComponent v-on:custom-event="events"/>
<custom-component v-on:custom-event="events"/>
</template>
`,
options: ['never', { exclude: ['/^Vue/', 'custom-component'] }]
}
],
invalid: [
Expand Down Expand Up @@ -179,6 +196,22 @@ tester.run('v-on-event-hyphenation', rule, {
"v-on event '@upDate:model-value' can't be hyphenated.",
"v-on event '@up-date:model-value' can't be hyphenated."
]
},
{
code: `
<template>
<VueComponent v-on:custom-event="events"/>
<CustomComponent v-on:custom-event="events"/>
</template>
`,
output: `
<template>
<VueComponent v-on:customEvent="events"/>
<CustomComponent v-on:custom-event="events"/>
</template>
`,
options: ['never', { autofix: true, exclude: ['CustomComponent'] }],
errors: ["v-on event 'v-on:custom-event' can't be hyphenated."]
}
]
})
Loading