Skip to content

Commit 5281fa4

Browse files
authored
Add TypeScript test case and add TypeScript FAQ to doc. (#110)
1 parent 83cc9a3 commit 5281fa4

File tree

9 files changed

+150
-10
lines changed

9 files changed

+150
-10
lines changed

docs/started.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,16 +79,28 @@ eslint "src/**/*.{js,vue,json}"
7979
# eslint "src/**/*.{js,vue,json5}"
8080
```
8181

82-
#### How to use custom parser?
82+
### How to use custom parser?
8383

8484
If you want to use custom parsers such as [babel-eslint](https://www.npmjs.com/package/babel-eslint) or [typescript-eslint-parser](https://www.npmjs.com/package/typescript-eslint-parser), you have to use `parserOptions.parser` option instead of `parser` option. Because this plugin requires [vue-eslint-parser](https://www.npmjs.com/package/vue-eslint-parser) to parse `.vue` files, so this plugin doesn't work if you overwrote `parser` option.
8585

86+
Also, `parserOptions` configured at the top level affect `.json` and `.yaml`. This plugin needs to use special parsers to parse `.json` and `.yaml`, so to correctly parse each extension, use the `overrides` option and overwrite the options again.
87+
8688
```diff
8789
- "parser": "babel-eslint",
8890
"parserOptions": {
8991
+ "parser": "babel-eslint",
9092
"sourceType": "module"
91-
}
93+
},
94+
+ "overrides": [
95+
+ {
96+
+ "files": ["*.json", "*.json5"],
97+
+ "extends": ["plugin:@intlify/vue-i18n/base"],
98+
+ },
99+
+ {
100+
+ "files": ["*.yaml", "*.yml"],
101+
+ "extends": ["plugin:@intlify/vue-i18n/base"],
102+
+ }
103+
+ ]
92104
```
93105

94106
## :question: FAQ

lib/utils/collect-keys.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,8 @@ function collectKeyResourcesFromFiles(fileNames: string[]) {
136136
debug('collectKeysFromFiles', fileNames)
137137

138138
const cliEngine = new CLIEngine({})
139+
// eslint-disable-next-line @typescript-eslint/no-var-requires
140+
cliEngine.addPlugin('@intlify/vue-i18n', require('../index')) // for Test
139141

140142
const results = []
141143

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@
9797
"docs": "vuepress dev docs",
9898
"docs:build": "vuepress build docs",
9999
"generate": "ts-node scripts/update.ts",
100-
"lint": "eslint --ext js,ts lib scripts tests docs/.vuepress --ignore-pattern \"!.*\"",
100+
"lint": "eslint --ext js,ts lib scripts tests/lib docs/.vuepress --ignore-pattern \"!.*\"",
101101
"lint:docs": "eslint --ext js,vue,md docs --ignore-pattern \"!.*\"",
102102
"release:prepare": "shipjs prepare",
103103
"release:trigger": "shipjs trigger",
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
module.exports = {
2+
root: true,
3+
extends: ['plugin:@intlify/vue-i18n/base'],
4+
parserOptions: {
5+
parser: '@typescript-eslint/parser'
6+
},
7+
rules: {
8+
'@intlify/vue-i18n/no-unused-keys': ["error", {
9+
"src": "./src",
10+
"extensions": [".tsx", ".ts", ".vue"],
11+
"enableFix": true,
12+
}]
13+
},
14+
settings: {
15+
'vue-i18n': {
16+
localeDir: {
17+
pattern: `./locales/*.{json,yaml,yml}`,
18+
localeKey: 'file'
19+
}
20+
}
21+
},
22+
overrides: [
23+
{
24+
files: ['*.json', '*.json5'],
25+
extends: ['plugin:@intlify/vue-i18n/base'],
26+
},
27+
{
28+
files: ['*.yaml', '*.yml'],
29+
extends: ['plugin:@intlify/vue-i18n/base'],
30+
}
31+
]
32+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"hello": "hello world",
3+
"messages": {
4+
"hello": "hi DIO!",
5+
"link": "@:message.hello",
6+
"nested": {
7+
"hello": "hi jojo!"
8+
}
9+
},
10+
"hello_dio": "hello underscore DIO!",
11+
"hello {name}": "hello {name}!",
12+
"hello-dio": "hello hyphen DIO!"
13+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
hello: "ハローワールド"
2+
messages:
3+
hello: "こんにちは、DIO!"
4+
link: "@:message.hello"
5+
nested:
6+
hello: "こんにちは、ジョジョ!"
7+
hello_dio: "こんにちは、アンダースコア DIO!"
8+
"hello {name}": "こんにちは、{name}!"
9+
hello-dio: "こんにちは、ハイフン DIO!"
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<template>
2+
<div id="app">
3+
<p v-t="'hello_dio'">{{ $t('messages.hello') }}</p>
4+
</div>
5+
</template>
6+
7+
<script lang="ts">
8+
export default {
9+
name: 'App' as const,
10+
created() {
11+
this.$i18n.t('hello {name}', { name: 'DIO' })
12+
}
13+
}
14+
</script>
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
const $t = (a:any) => {}
2+
$t('hello')

tests/lib/rules/no-unused-keys.ts

Lines changed: 63 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -892,7 +892,7 @@ describe('no-unused-keys with fixtures', () => {
892892
describe('errors', () => {
893893
it('settings.vue-i18n.localeDir', () => {
894894
const linter = new CLIEngine({
895-
cwd,
895+
cwd: join(cwd, './valid'),
896896
baseConfig: {
897897
extends: [baseConfigPath]
898898
},
@@ -909,7 +909,7 @@ describe('no-unused-keys with fixtures', () => {
909909
linter.addPlugin('@intlify/vue-i18n', plugin)
910910

911911
const messages = linter.executeOnFiles(['.'])
912-
assert.equal(messages.errorCount, 6)
912+
assert.equal(messages.errorCount, 3)
913913
messages.results
914914
.map(result => {
915915
return result.messages.filter(
@@ -929,7 +929,7 @@ describe('no-unused-keys with fixtures', () => {
929929
describe('valid', () => {
930930
it('should be not detected unsued keys', () => {
931931
const linter = new CLIEngine({
932-
cwd,
932+
cwd: join(cwd, './valid/vue-cli-format'),
933933
baseConfig: {
934934
extends: [baseConfigPath],
935935
settings: {
@@ -964,7 +964,7 @@ describe('no-unused-keys with fixtures', () => {
964964

965965
it('should be not detected unsued keys for constructor-option-format', () => {
966966
const linter = new CLIEngine({
967-
cwd,
967+
cwd: join(cwd, './valid/constructor-option-format'),
968968
baseConfig: {
969969
extends: [baseConfigPath],
970970
settings: {
@@ -1004,7 +1004,7 @@ describe('no-unused-keys with fixtures', () => {
10041004
describe('invalid', () => {
10051005
it('should be detected unsued keys', () => {
10061006
const linter = new CLIEngine({
1007-
cwd,
1007+
cwd: join(cwd, './invalid/vue-cli-format'),
10081008
baseConfig: {
10091009
extends: [baseConfigPath],
10101010
settings: {
@@ -1225,7 +1225,7 @@ hello_dio: "こんにちは、アンダースコア DIO!"
12251225

12261226
it('should be detected unsued keys for constructor-option-format', () => {
12271227
const linter = new CLIEngine({
1228-
cwd,
1228+
cwd: join(cwd, './invalid/constructor-option-format'),
12291229
baseConfig: {
12301230
extends: [baseConfigPath],
12311231
settings: {
@@ -1542,18 +1542,74 @@ hello_dio: "こんにちは、アンダースコア DIO!"
15421542
}
15431543
)
15441544
})
1545+
1546+
it('should be detected unsued keys with typescript', () => {
1547+
process.chdir(join(cwd, './invalid/typescript'))
1548+
const linter = new CLIEngine({
1549+
cwd: join(cwd, './invalid/typescript'),
1550+
extensions: ['.js', '.vue', '.json', '.yaml', '.yml', '.ts']
1551+
})
1552+
linter.addPlugin('@intlify/vue-i18n', plugin)
1553+
1554+
const messages = linter.executeOnFiles(['.'])
1555+
assert.equal(messages.errorCount, 6)
1556+
1557+
assert.deepStrictEqual(
1558+
getResult(
1559+
messages,
1560+
'../../fixtures/no-unused-keys/invalid/typescript/locales/en.json',
1561+
{ messageOnly: true }
1562+
),
1563+
{
1564+
errors: [
1565+
"unused 'messages.link' key",
1566+
"unused 'messages.nested.hello' key",
1567+
"unused 'hello-dio' key"
1568+
]
1569+
}
1570+
)
1571+
1572+
assert.deepStrictEqual(
1573+
getResult(
1574+
messages,
1575+
'../../fixtures/no-unused-keys/invalid/typescript/locales/ja.yaml',
1576+
{ messageOnly: true }
1577+
),
1578+
{
1579+
errors: [
1580+
"unused 'messages.link' key",
1581+
"unused 'messages.nested.hello' key",
1582+
"unused 'hello-dio' key"
1583+
]
1584+
}
1585+
)
1586+
})
15451587
})
15461588
})
15471589

1548-
function getResult(messages: CLIEngine.LintReport, path: string) {
1590+
function getResult(
1591+
messages: CLIEngine.LintReport,
1592+
path: string,
1593+
options?: { messageOnly?: boolean }
1594+
) {
15491595
const fullPath = resolve(__dirname, path)
15501596
const result = messages.results.find(result => result.filePath === fullPath)!
1597+
const messageOnly = options?.messageOnly ?? false
1598+
if (messageOnly) {
1599+
return {
1600+
errors: result.messages.map(message => {
1601+
assert.equal(message.ruleId, '@intlify/vue-i18n/no-unused-keys')
1602+
return message.message
1603+
})
1604+
}
1605+
}
15511606
const output = SourceCodeFixer.applyFixes(result.source, result.messages)
15521607
.output
15531608
return {
15541609
output,
15551610
errors: result.messages.map(message => {
15561611
assert.equal(message.ruleId, '@intlify/vue-i18n/no-unused-keys')
1612+
15571613
return {
15581614
message: message.message,
15591615
line: message.line,

0 commit comments

Comments
 (0)