Skip to content

Commit

Permalink
Add @intlify/vue-i18n/no-i18n-t-path-prop rule (#167)
Browse files Browse the repository at this point in the history
  • Loading branch information
ota-meshi authored Feb 23, 2021
1 parent 062230f commit 2d7739b
Show file tree
Hide file tree
Showing 5 changed files with 215 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/rules/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
| [@intlify/vue-i18n/<wbr>no-deprecated-i18n-component](./no-deprecated-i18n-component.html) | disallow using deprecated `<i18n>` components (in Vue I18n 9.0.0+) | :black_nib: |
| [@intlify/vue-i18n/<wbr>no-deprecated-i18n-place-attr](./no-deprecated-i18n-place-attr.html) | disallow using deprecated `place` attribute (Removed in Vue I18n 9.0.0+) | |
| [@intlify/vue-i18n/<wbr>no-html-messages](./no-html-messages.html) | disallow use HTML localization messages | :star: |
| [@intlify/vue-i18n/<wbr>no-i18n-t-path-prop](./no-i18n-t-path-prop.html) | disallow using `path` prop with `<i18n-t>` | :black_nib: |
| [@intlify/vue-i18n/<wbr>no-missing-keys](./no-missing-keys.html) | disallow missing locale message key at localization methods | :star: |
| [@intlify/vue-i18n/<wbr>no-raw-text](./no-raw-text.html) | disallow to string literal in template or JSX | :star: |
| [@intlify/vue-i18n/<wbr>no-v-html](./no-v-html.html) | disallow use of localization methods on v-html to prevent XSS attack | :star: |
Expand Down
68 changes: 68 additions & 0 deletions docs/rules/no-i18n-t-path-prop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
---
title: '@intlify/vue-i18n/no-i18n-t-path-prop'
description: disallow using `path` prop with `<i18n-t>`
---

# @intlify/vue-i18n/no-i18n-t-path-prop

> disallow using `path` prop with `<i18n-t>`
- :black_nib:️ 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.

You cannot use `path` prop with `<i18n-t>` component. Perhaps it's an old habit mistake.

## :book: Rule Details

This rule reports use of `path` prop with `<i18n-t>` component.

:-1: Examples of **incorrect** code for this rule:

<eslint-code-block fix>

<!-- eslint-skip -->

```vue
<script>
/* eslint @intlify/vue-i18n/no-i18n-t-path-prop: 'error' */
</script>
<template>
<div class="app">
<!-- ✗ BAD -->
<i18n-t path="message.greeting" />
</div>
</template>
```

</eslint-code-block>

:+1: Examples of **correct** code for this rule:

<eslint-code-block fix>

<!-- eslint-skip -->

```vue
<script>
/* eslint @intlify/vue-i18n/no-i18n-t-path-prop: 'error' */
</script>
<template>
<div class="app">
<!-- ✓ GOOD -->
<i18n-t keypath="message.greeting" />
<!-- ✓ GOOD -->
<i18n path="message.greeting" />
</div>
</template>
```

</eslint-code-block>

## :books: Further reading

- [Vue I18n > Breaking Changes - Rename to `keypath` prop from `path` prop](https://vue-i18n.intlify.dev/guide/migration/breaking.html#rename-to-keypath-prop-from-path-prop)

## :mag: Implementation

- [Rule source](https://github.com/intlify/eslint-plugin-vue-i18n/blob/master/lib/rules/no-i18n-t-path-prop.ts)
- [Test source](https://github.com/intlify/eslint-plugin-vue-i18n/tree/master/tests/lib/rules/no-i18n-t-path-prop.ts)
2 changes: 2 additions & 0 deletions lib/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import noDeprecatedI18nPlaceAttr from './rules/no-deprecated-i18n-place-attr'
import noDuplicateKeysInLocale from './rules/no-duplicate-keys-in-locale'
import noDynamicKeys from './rules/no-dynamic-keys'
import noHtmlMessages from './rules/no-html-messages'
import noI18nTPathProp from './rules/no-i18n-t-path-prop'
import noMissingKeysInOtherLocales from './rules/no-missing-keys-in-other-locales'
import noMissingKeys from './rules/no-missing-keys'
import noRawText from './rules/no-raw-text'
Expand All @@ -20,6 +21,7 @@ export = {
'no-duplicate-keys-in-locale': noDuplicateKeysInLocale,
'no-dynamic-keys': noDynamicKeys,
'no-html-messages': noHtmlMessages,
'no-i18n-t-path-prop': noI18nTPathProp,
'no-missing-keys-in-other-locales': noMissingKeysInOtherLocales,
'no-missing-keys': noMissingKeys,
'no-raw-text': noRawText,
Expand Down
53 changes: 53 additions & 0 deletions lib/rules/no-i18n-t-path-prop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* @author Yosuke Ota
*/
import {
defineTemplateBodyVisitor,
getAttribute,
getDirective
} from '../utils/index'
import type { RuleContext, RuleListener } from '../types'
import type { AST as VAST } from 'vue-eslint-parser'

function create(context: RuleContext): RuleListener {
return defineTemplateBodyVisitor(context, {
VElement(node: VAST.VElement) {
if (node.name !== 'i18n-t') {
return
}
const pathProp =
getAttribute(node, 'path') || getDirective(node, 'bind', 'path')
if (pathProp) {
context.report({
node: pathProp.key,
messageId: 'disallow',
fix(fixer) {
if (pathProp.directive) {
return fixer.replaceText(pathProp.key.argument!, 'keypath')
} else {
return fixer.replaceText(pathProp.key, 'keypath')
}
}
})
}
}
})
}

export = {
meta: {
type: 'problem',
docs: {
description: 'disallow using `path` prop with `<i18n-t>`',
category: 'Recommended',
recommended: false
},
fixable: 'code',
schema: [],
messages: {
disallow:
'Cannot use `path` prop with `<i18n-t>` component. Use `keypath` prop instead.'
}
},
create
}
91 changes: 91 additions & 0 deletions tests/lib/rules/no-i18n-t-path-prop.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/**
* @author Yosuke Ota
*/
import { RuleTester } from 'eslint'
import rule = require('../../../lib/rules/no-i18n-t-path-prop')

const tester = new RuleTester({
parser: require.resolve('vue-eslint-parser'),
parserOptions: { ecmaVersion: 2015 }
})

tester.run('no-i18n-t-path-prop', rule as never, {
valid: [
{
code: `
<template>
<i18n-t keypath="message.greeting" />
</template>
`
},
{
code: `
<template>
<i18n path="message.greeting" />
</template>
`
}
],
invalid: [
{
code: `
<template>
<i18n-t path="message.greeting" />
</template>
`,
output: `
<template>
<i18n-t keypath="message.greeting" />
</template>
`,
errors: [
{
message:
'Cannot use `path` prop with `<i18n-t>` component. Use `keypath` prop instead.',
line: 3,
column: 17
}
]
},
{
code: `
<template>
<i18n-t :path="messageKey" />
</template>
`,
output: `
<template>
<i18n-t :keypath="messageKey" />
</template>
`,
errors: [
{
message:
'Cannot use `path` prop with `<i18n-t>` component. Use `keypath` prop instead.',
line: 3,
column: 17
}
]
},
{
code: `
<template>
<i18n-t v-bind:path="messageKey" />
</template>
`,
output: `
<template>
<i18n-t v-bind:keypath="messageKey" />
</template>
`,
errors: [
{
message:
'Cannot use `path` prop with `<i18n-t>` component. Use `keypath` prop instead.',
line: 3,
column: 17
}
]
}
]
})

0 comments on commit 2d7739b

Please sign in to comment.