@@ -8,24 +8,73 @@ const jsonAstParse = require('json-to-ast')
8
8
const jsonDiffPatch = require ( 'jsondiffpatch' ) . create ( { } )
9
9
const flatten = require ( 'flat' )
10
10
const collectKeys = require ( '../utils/collect-keys' )
11
- const { loadLocaleMessages } = require ( '../utils/index' )
11
+ const { UNEXPETECD_ERROR_LOCATION , loadLocaleMessages } = require ( '../utils/index' )
12
12
const debug = require ( 'debug' ) ( 'eslint-plugin-vue-i18n:no-unused-keys' )
13
13
14
14
let usedLocaleMessageKeys = null // used locale message keys
15
15
let localeMessages = null // used locale messages
16
+ let localeDir = null
16
17
17
18
function findExistLocaleMessage ( fullpath , localeMessages ) {
18
19
return localeMessages . find ( message => message . fullpath === fullpath )
19
20
}
20
21
21
- function getUnusedKeys ( diffLocaleMessage ) {
22
- const unusedKeys = [ ]
23
- Object . keys ( diffLocaleMessage ) . forEach ( key => {
24
- const value = diffLocaleMessage [ key ]
25
- if ( value && Array . isArray ( value ) && value . length === 1 ) {
26
- unusedKeys . push ( key )
27
- }
28
- } )
22
+ function extractJsonInfo ( context , node ) {
23
+ try {
24
+ const [ str , filename ] = node . comments
25
+ return [
26
+ Buffer . from ( str . value , 'base64' ) . toString ( ) ,
27
+ Buffer . from ( filename . value , 'base64' ) . toString ( )
28
+ ]
29
+ } catch ( e ) {
30
+ context . report ( {
31
+ loc : UNEXPETECD_ERROR_LOCATION ,
32
+ message : e . message
33
+ } )
34
+ return [ ]
35
+ }
36
+ }
37
+
38
+ function generateJsonAst ( context , json , filename ) {
39
+ let ast = null
40
+
41
+ try {
42
+ ast = jsonAstParse ( json , { loc : true , source : filename } )
43
+ } catch ( e ) {
44
+ const { message, line, column } = e
45
+ context . report ( {
46
+ message,
47
+ loc : { line, column }
48
+ } )
49
+ }
50
+
51
+ return ast
52
+ }
53
+
54
+ function getUnusedKeys ( context , json , usedkeys ) {
55
+ let unusedKeys = [ ]
56
+
57
+ try {
58
+ const jsonValue = JSON . parse ( json )
59
+ const diffValue = jsonDiffPatch . diff (
60
+ flatten ( usedkeys , { safe : true } ) ,
61
+ flatten ( jsonValue , { safe : true } )
62
+ )
63
+ const diffLocaleMessage = flatten ( diffValue , { safe : true } )
64
+ Object . keys ( diffLocaleMessage ) . forEach ( key => {
65
+ const value = diffLocaleMessage [ key ]
66
+ if ( value && Array . isArray ( value ) && value . length === 1 ) {
67
+ unusedKeys . push ( key )
68
+ }
69
+ } )
70
+ } catch ( e ) {
71
+ context . report ( {
72
+ loc : UNEXPETECD_ERROR_LOCATION ,
73
+ message : e . message
74
+ } )
75
+ unusedKeys = null
76
+ }
77
+
29
78
return unusedKeys
30
79
}
31
80
@@ -65,53 +114,53 @@ function create (context) {
65
114
66
115
const { settings } = context
67
116
if ( ! settings [ 'vue-i18n' ] || ! settings [ 'vue-i18n' ] . localeDir ) {
68
- // TODO: should be error
117
+ context . report ( {
118
+ loc : UNEXPETECD_ERROR_LOCATION ,
119
+ message : `You need to 'localeDir' at 'settings. See the 'eslint-plugin-vue-i18n documentation`
120
+ } )
69
121
return { }
70
122
}
71
- localeMessages = localeMessages || loadLocaleMessages ( settings [ 'vue-i18n' ] . localeDir )
123
+
124
+ if ( localeDir !== settings [ 'vue-i18n' ] . localeDir ) {
125
+ debug ( `change localeDir: ${ localeDir } -> ${ settings [ 'vue-i18n' ] . localeDir } ` )
126
+ localeDir = settings [ 'vue-i18n' ] . localeDir
127
+ localeMessages = loadLocaleMessages ( localeDir )
128
+ } else {
129
+ localeMessages = localeMessages || loadLocaleMessages ( settings [ 'vue-i18n' ] . localeDir )
130
+ }
72
131
73
132
const targetLocaleMessage = findExistLocaleMessage ( filename , localeMessages )
74
133
if ( ! targetLocaleMessage ) {
75
134
debug ( `ignore ${ filename } in no-unused-keys` )
76
135
return { }
77
136
}
78
137
79
- const { extensions } = ( context . options && context . options [ 0 ] ) || { extensions : [ '.js' , '.vue' ] }
80
- const src = [ process . cwd ( ) ] || [ '.' ]
138
+ const options = ( context . options && context . options [ 0 ] ) || { }
139
+ const src = options . src || process . cwd ( )
140
+ const extensions = options . extensions || [ '.js' , '.vue' ]
81
141
82
142
if ( ! usedLocaleMessageKeys ) {
83
- usedLocaleMessageKeys = collectKeys ( src , extensions )
143
+ usedLocaleMessageKeys = collectKeys ( [ src ] , extensions )
84
144
}
85
145
86
146
return {
87
147
Program ( node ) {
88
- const [ stringNode , filenameNode ] = node . comments
89
- const jsonString = Buffer . from ( stringNode . value , 'base64' ) . toString ( )
90
- const jsonFilename = Buffer . from ( filenameNode . value , 'base64' ) . toString ( )
91
- const jsonValue = JSON . parse ( jsonString )
92
- try {
93
- const diffValue = jsonDiffPatch . diff (
94
- flatten ( usedLocaleMessageKeys , { safe : true } ) ,
95
- flatten ( jsonValue , { safe : true } )
96
- )
97
- const diffLocaleMessage = flatten ( diffValue , { safe : true } )
98
- const unusedKeys = getUnusedKeys ( diffLocaleMessage )
99
-
100
- const jsonAstSettings = { loc : true , source : jsonFilename }
101
- const ast = jsonAstParse ( jsonString , jsonAstSettings )
102
- traverseJsonAstWithUnusedKeys ( unusedKeys , ast , ( fullpath , node ) => {
103
- const { line, column } = node . loc . start
104
- context . report ( {
105
- message : `unused '${ fullpath } ' key in '${ targetLocaleMessage . path } '` ,
106
- loc : { line, column }
107
- } )
108
- } )
109
- } catch ( { message, line, column } ) {
148
+ const [ jsonString , jsonFilename ] = extractJsonInfo ( context , node )
149
+ if ( ! jsonString || ! jsonFilename ) { return }
150
+
151
+ const ast = generateJsonAst ( context , jsonString , jsonFilename )
152
+ if ( ! ast ) { return }
153
+
154
+ const unusedKeys = getUnusedKeys ( context , jsonString , usedLocaleMessageKeys )
155
+ if ( ! unusedKeys ) { return }
156
+
157
+ traverseJsonAstWithUnusedKeys ( unusedKeys , ast , ( fullpath , node ) => {
158
+ const { line, column } = node . loc . start
110
159
context . report ( {
111
- message,
160
+ message : `unused ' ${ fullpath } ' key in ' ${ targetLocaleMessage . path } '` ,
112
161
loc : { line, column }
113
162
} )
114
- }
163
+ } )
115
164
}
116
165
}
117
166
}
@@ -128,6 +177,9 @@ module.exports = {
128
177
schema : [ {
129
178
type : 'object' ,
130
179
properties : {
180
+ src : {
181
+ type : 'string'
182
+ } ,
131
183
extensions : {
132
184
type : 'array' ,
133
185
items : { type : 'string' } ,
0 commit comments