Skip to content

Commit 7852561

Browse files
authored
Replacing with TypeScript (#97)
* Replacing with TypeScript * Fix docs build
1 parent 1deb997 commit 7852561

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+2005
-936
lines changed

.eslintrc.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,27 @@ module.exports = {
1212
'prettier',
1313
'prettier/vue'
1414
],
15-
plugins: [],
15+
plugins: ['@typescript-eslint'],
1616
parserOptions: {
1717
ecmaVersion: 2015
1818
},
1919
rules: {
2020
'object-shorthand': 'error'
21-
}
21+
},
22+
overrides: [
23+
{
24+
files: ['*.ts'],
25+
extends: [
26+
'plugin:@typescript-eslint/recommended',
27+
'prettier/@typescript-eslint'
28+
],
29+
parser: 'vue-eslint-parser',
30+
parserOptions: {
31+
parser: '@typescript-eslint/parser'
32+
},
33+
rules: {
34+
'@typescript-eslint/no-non-null-assertion': 'off'
35+
}
36+
}
37+
]
2238
}

.github/workflows/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,6 @@ jobs:
3131
- name: Test
3232
run: yarn test
3333
- name: Integration Test
34-
run: yarn test:integrations
34+
run: |
35+
yarn build
36+
yarn test:integrations

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ coverage
66
*.log
77
*.swp
88
*~
9+
/dist

.vscode/settings.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
{
22
"eslint.options": { "configFile": ".eslintrc.js" },
33
"eslint.validate": [
4-
"javascript"
4+
"javascript",
5+
"typescript"
56
],
67
"eslint.alwaysShowStatus": true,
78
"eslint.packageManager": "yarn",

docs/.vuepress/config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
'use strict'
66

7+
require('ts-node').register()
78
const { withCategories } = require('../../scripts/lib/rules')
89
require('../../scripts/update-docs-headers')
910
require('../../scripts/update-docs-index')

lib/configs.js

Lines changed: 0 additions & 7 deletions
This file was deleted.

lib/configs.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/** DON'T EDIT THIS FILE; was created by scripts. */
2+
import base from './configs/base'
3+
import recommended from './configs/recommended'
4+
5+
export = {
6+
base,
7+
recommended
8+
}

lib/configs/base.js renamed to lib/configs/base.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
'use strict'
2-
3-
module.exports = {
1+
export = {
42
parser: require.resolve('vue-eslint-parser'),
53
plugins: ['@intlify/vue-i18n'],
64
overrides: [

lib/configs/recommended.js renamed to lib/configs/recommended.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
/** DON'T EDIT THIS FILE; was created by scripts. */
2-
'use strict'
3-
4-
module.exports = {
2+
export = {
53
extends: [require.resolve('./base')],
64
parserOptions: {
75
ecmaVersion: 2018,

lib/index.js renamed to lib/index.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22
* @fileoverview ESLint plugin for vue-i18n
33
* @author kazuya kawaguchi (a.k.a. kazupon)
44
*/
5-
'use strict'
5+
import configs from './configs'
6+
import rules from './rules'
67

7-
module.exports = {
8-
configs: require('./configs'),
9-
rules: require('./rules')
8+
export = {
9+
configs,
10+
rules
1011
}

lib/rules.js

Lines changed: 0 additions & 11 deletions
This file was deleted.

lib/rules.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/** DON'T EDIT THIS FILE; was created by scripts. */
2+
import noDynamicKeys from './rules/no-dynamic-keys'
3+
import noHtmlMessages from './rules/no-html-messages'
4+
import noMissingKeys from './rules/no-missing-keys'
5+
import noRawText from './rules/no-raw-text'
6+
import noUnusedKeys from './rules/no-unused-keys'
7+
import noVHtml from './rules/no-v-html'
8+
9+
export = {
10+
'no-dynamic-keys': noDynamicKeys,
11+
'no-html-messages': noHtmlMessages,
12+
'no-missing-keys': noMissingKeys,
13+
'no-raw-text': noRawText,
14+
'no-unused-keys': noUnusedKeys,
15+
'no-v-html': noVHtml
16+
}

lib/rules/no-dynamic-keys.js renamed to lib/rules/no-dynamic-keys.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
/**
22
* @author kazuya kawaguchi (a.k.a. kazupon)
33
*/
4-
'use strict'
4+
import { defineTemplateBodyVisitor } from '../utils/index'
5+
import type { RuleContext, RuleListener } from '../types'
6+
import type { AST as VAST } from 'vue-eslint-parser'
57

6-
const { defineTemplateBodyVisitor } = require('../utils/index')
7-
8-
function checkDirective(context, node) {
8+
function checkDirective(context: RuleContext, node: VAST.VDirective) {
99
if (
1010
node.value &&
1111
node.value.type === 'VExpressionContainer' &&
@@ -20,29 +20,37 @@ function checkDirective(context, node) {
2020
}
2121
}
2222

23-
function checkComponent(context, node) {
23+
function checkComponent(context: RuleContext, node: VAST.VDirectiveKey) {
24+
const parent: VAST.VDirective = node.parent as never // typebug?
2425
if (
2526
node.name.type === 'VIdentifier' &&
2627
node.name.name === 'bind' &&
28+
node.argument &&
2729
node.argument.type === 'VIdentifier' &&
2830
node.argument.name === 'path' &&
29-
node.parent.value &&
30-
node.parent.value.type === 'VExpressionContainer' &&
31-
node.parent.value.expression &&
32-
node.parent.value.expression.type === 'Identifier'
31+
parent.value &&
32+
parent.value.type === 'VExpressionContainer' &&
33+
parent.value.expression &&
34+
parent.value.expression.type === 'Identifier'
3335
) {
34-
const name = node.parent.value.expression.name
36+
const name = parent.value.expression.name
3537
context.report({
3638
node,
3739
message: `'${name}' dynamic key is used'`
3840
})
3941
}
4042
}
4143

42-
function checkCallExpression(context, node) {
44+
function checkCallExpression(
45+
context: RuleContext,
46+
node: VAST.ESLintCallExpression
47+
) {
4348
const funcName =
44-
(node.callee.type === 'MemberExpression' && node.callee.property.name) ||
45-
node.callee.name
49+
(node.callee.type === 'MemberExpression' &&
50+
node.callee.property.type === 'Identifier' &&
51+
node.callee.property.name) ||
52+
(node.callee.type === 'Identifier' && node.callee.name) ||
53+
''
4654

4755
if (
4856
!/^(\$t|t|\$tc|tc)$/.test(funcName) ||
@@ -62,37 +70,37 @@ function checkCallExpression(context, node) {
6270
}
6371
}
6472

65-
function create(context) {
73+
function create(context: RuleContext): RuleListener {
6674
return defineTemplateBodyVisitor(
6775
context,
6876
{
69-
"VAttribute[directive=true][key.name='t']"(node) {
77+
"VAttribute[directive=true][key.name='t']"(node: VAST.VDirective) {
7078
checkDirective(context, node)
7179
},
7280

73-
"VAttribute[directive=true][key.name.name='t']"(node) {
81+
"VAttribute[directive=true][key.name.name='t']"(node: VAST.VDirective) {
7482
checkDirective(context, node)
7583
},
7684

7785
'VElement:matches([name=i18n], [name=i18n-t]) > VStartTag > VAttribute[directive=true] > VDirectiveKey'(
78-
node
86+
node: VAST.VDirectiveKey
7987
) {
8088
checkComponent(context, node)
8189
},
8290

83-
CallExpression(node) {
91+
CallExpression(node: VAST.ESLintCallExpression) {
8492
checkCallExpression(context, node)
8593
}
8694
},
8795
{
88-
CallExpression(node) {
96+
CallExpression(node: VAST.ESLintCallExpression) {
8997
checkCallExpression(context, node)
9098
}
9199
}
92100
)
93101
}
94102

95-
module.exports = {
103+
export = {
96104
meta: {
97105
type: 'suggestion',
98106
docs: {

lib/rules/no-html-messages.js renamed to lib/rules/no-html-messages.ts

Lines changed: 33 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,45 @@
11
/**
22
* @author kazuya kawaguchi (a.k.a. kazupon)
33
*/
4-
'use strict'
4+
import { extname } from 'path'
5+
import parse5 from 'parse5'
6+
import { getLocaleMessages } from '../utils/index'
7+
import debugBuilder from 'debug'
8+
import type { AST as VAST } from 'vue-eslint-parser'
9+
import type { AST as JSONAST } from 'eslint-plugin-jsonc'
10+
import type { AST as YAMLAST } from 'yaml-eslint-parser'
11+
import type { RuleContext, RuleListener } from '../types'
512

6-
const { extname } = require('path')
7-
const parse5 = require('parse5')
8-
const { getLocaleMessages } = require('../utils/index')
9-
const debug = require('debug')('eslint-plugin-vue-i18n:no-html-messages')
13+
const debug = debugBuilder('eslint-plugin-vue-i18n:no-html-messages')
1014

11-
/**
12-
* @typedef {import('eslint-plugin-jsonc').AST.JSONLiteral} JSONLiteral
13-
* @typedef {import('yaml-eslint-parser').AST.YAMLScalar} YAMLScalar
14-
*/
15-
16-
function findHTMLNode(node) {
17-
return node.childNodes.find(child => {
18-
if (child.nodeName !== '#text' && child.tagName) {
15+
function findHTMLNode(
16+
node: parse5.DefaultTreeDocumentFragment
17+
): parse5.DefaultTreeElement | undefined {
18+
return node.childNodes.find((child): child is parse5.DefaultTreeElement => {
19+
if (
20+
child.nodeName !== '#text' &&
21+
(child as parse5.DefaultTreeElement).tagName
22+
) {
1923
return true
2024
}
25+
return false
2126
})
2227
}
2328

24-
function create(context) {
29+
function create(context: RuleContext): RuleListener {
2530
const filename = context.getFilename()
2631

2732
/**
2833
* @param {JSONLiteral} node
2934
*/
30-
function verifyJSONLiteral(node) {
31-
const parent = node.parent
35+
function verifyJSONLiteral(node: JSONAST.JSONLiteral) {
36+
const parent = node.parent!
3237
if (parent.type === 'JSONProperty' && parent.key === node) {
3338
return
3439
}
3540
const htmlNode = parse5.parseFragment(`${node.value}`, {
3641
sourceCodeLocationInfo: true
37-
})
42+
}) as parse5.DefaultTreeDocumentFragment
3843
const foundNode = findHTMLNode(htmlNode)
3944
if (!foundNode) {
4045
return
@@ -44,7 +49,7 @@ function create(context) {
4449
column:
4550
node.loc.start.column +
4651
1 /* quote */ +
47-
foundNode.sourceCodeLocation.startOffset
52+
foundNode.sourceCodeLocation!.startOffset
4853
}
4954
context.report({
5055
message: `used HTML localization message`,
@@ -55,14 +60,14 @@ function create(context) {
5560
/**
5661
* @param {YAMLScalar} node
5762
*/
58-
function verifyYAMLScalar(node) {
63+
function verifyYAMLScalar(node: YAMLAST.YAMLScalar) {
5964
const parent = node.parent
6065
if (parent.type === 'YAMLPair' && parent.key === node) {
6166
return
6267
}
6368
const htmlNode = parse5.parseFragment(`${node.value}`, {
6469
sourceCodeLocationInfo: true
65-
})
70+
}) as parse5.DefaultTreeDocumentFragment
6671
const foundNode = findHTMLNode(htmlNode)
6772
if (!foundNode) {
6873
return
@@ -72,7 +77,7 @@ function create(context) {
7277
column:
7378
node.loc.start.column +
7479
1 /* quote */ +
75-
foundNode.sourceCodeLocation.startOffset
80+
foundNode.sourceCodeLocation!.startOffset
7681
}
7782
context.report({
7883
message: `used HTML localization message`,
@@ -82,15 +87,16 @@ function create(context) {
8287

8388
if (extname(filename) === '.vue') {
8489
return {
85-
Program(node) {
90+
Program() {
8691
const documentFragment =
8792
context.parserServices.getDocumentFragment &&
8893
context.parserServices.getDocumentFragment()
8994
/** @type {VElement[]} */
9095
const i18nBlocks =
9196
(documentFragment &&
9297
documentFragment.children.filter(
93-
node => node.type === 'VElement' && node.name === 'i18n'
98+
(node): node is VAST.VElement =>
99+
node.type === 'VElement' && node.name === 'i18n'
94100
)) ||
95101
[]
96102
if (!i18nBlocks.length) {
@@ -121,7 +127,9 @@ function create(context) {
121127
verifyYAMLScalar(node)
122128
}
123129
},
124-
leaveNode() {}
130+
leaveNode() {
131+
// noop
132+
}
125133
})
126134
}
127135
}
@@ -146,7 +154,7 @@ function create(context) {
146154
}
147155
}
148156

149-
module.exports = {
157+
export = {
150158
meta: {
151159
type: 'problem',
152160
docs: {

0 commit comments

Comments
 (0)