feima-shortcuts 0.3.0-beta.8 → 0.3.0-beta.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/feima.js +3 -1
- package/package.json +1 -1
- package/src/scripts/check-i18n-views/index.js +94 -35
package/bin/feima.js
CHANGED
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ const traverse = require('@babel/traverse').default
|
|
|
9
9
|
|
|
10
10
|
const DEFAULT_OPTIONS = {
|
|
11
11
|
cwd: process.cwd(),
|
|
12
|
-
|
|
12
|
+
scanDirs: ['src/views'],
|
|
13
13
|
silent: false,
|
|
14
14
|
}
|
|
15
15
|
|
|
@@ -42,35 +42,57 @@ function parseCode(code) {
|
|
|
42
42
|
})
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* 🔑 components 专用:
|
|
47
|
+
* 从当前文件目录开始,向上查找最近的 locale.ts
|
|
48
|
+
* 直到到达 src/components 为止
|
|
49
|
+
*/
|
|
50
|
+
function findNearestLocale(fileDir, componentsRoot) {
|
|
51
|
+
let current = fileDir
|
|
52
|
+
|
|
53
|
+
while (current.startsWith(componentsRoot)) {
|
|
54
|
+
const localePath = path.join(current, 'locale.ts')
|
|
55
|
+
if (fs.existsSync(localePath)) {
|
|
56
|
+
return localePath
|
|
57
|
+
}
|
|
58
|
+
const parent = path.dirname(current)
|
|
59
|
+
if (parent === current) break
|
|
60
|
+
current = parent
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return null
|
|
64
|
+
}
|
|
65
|
+
|
|
45
66
|
/* ---------------- core ---------------- */
|
|
46
67
|
|
|
47
68
|
function run(userOptions = {}) {
|
|
48
|
-
// ✅ 保证 options 永远有值
|
|
49
69
|
const options = { ...DEFAULT_OPTIONS, ...userOptions }
|
|
50
|
-
const { cwd,
|
|
70
|
+
const { cwd, scanDirs, silent } = options
|
|
51
71
|
|
|
52
|
-
|
|
72
|
+
let files = []
|
|
53
73
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
noLocaleUsage: [],
|
|
62
|
-
scannedFiles: 0,
|
|
74
|
+
for (const dir of scanDirs) {
|
|
75
|
+
const absDir = path.join(cwd, dir)
|
|
76
|
+
if (!fs.existsSync(absDir)) {
|
|
77
|
+
if (!silent) {
|
|
78
|
+
console.warn(`⚠️ 目录不存在:${dir}`)
|
|
79
|
+
}
|
|
80
|
+
continue
|
|
63
81
|
}
|
|
64
|
-
}
|
|
65
82
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
83
|
+
files.push(
|
|
84
|
+
...glob.sync('**/*.{vue,ts,tsx}', {
|
|
85
|
+
cwd: absDir,
|
|
86
|
+
absolute: true,
|
|
87
|
+
})
|
|
88
|
+
)
|
|
89
|
+
}
|
|
70
90
|
|
|
71
91
|
const missingKeys = []
|
|
72
92
|
const noLocaleUsage = []
|
|
73
93
|
|
|
94
|
+
const componentsRoot = path.join(cwd, 'src/components')
|
|
95
|
+
|
|
74
96
|
for (const file of files) {
|
|
75
97
|
const content = fs.readFileSync(file, 'utf-8')
|
|
76
98
|
|
|
@@ -86,15 +108,21 @@ function run(userOptions = {}) {
|
|
|
86
108
|
|
|
87
109
|
if (!scriptCode) continue
|
|
88
110
|
|
|
89
|
-
|
|
111
|
+
let ast
|
|
112
|
+
try {
|
|
113
|
+
ast = parseCode(scriptCode)
|
|
114
|
+
} catch {
|
|
115
|
+
continue
|
|
116
|
+
}
|
|
90
117
|
|
|
91
|
-
let usedLocale = false
|
|
92
118
|
const usedKeys = []
|
|
119
|
+
let usedT = false
|
|
120
|
+
let importedLocale = false
|
|
93
121
|
|
|
94
122
|
traverse(ast, {
|
|
95
123
|
ImportDeclaration(p) {
|
|
96
124
|
if (p.node.source.value === './locale') {
|
|
97
|
-
|
|
125
|
+
importedLocale = true
|
|
98
126
|
}
|
|
99
127
|
},
|
|
100
128
|
|
|
@@ -104,6 +132,7 @@ function run(userOptions = {}) {
|
|
|
104
132
|
(callee.type === 'Identifier' && callee.name === 't') ||
|
|
105
133
|
(callee.type === 'Identifier' && callee.name === '$t')
|
|
106
134
|
) {
|
|
135
|
+
usedT = true
|
|
107
136
|
const arg = p.node.arguments[0]
|
|
108
137
|
if (arg && arg.type === 'StringLiteral') {
|
|
109
138
|
usedKeys.push(arg.value)
|
|
@@ -114,23 +143,53 @@ function run(userOptions = {}) {
|
|
|
114
143
|
|
|
115
144
|
if (!usedKeys.length) continue
|
|
116
145
|
|
|
117
|
-
const
|
|
118
|
-
|
|
146
|
+
const fileDir = path.dirname(file)
|
|
147
|
+
|
|
148
|
+
/* ---------- views 逻辑 ---------- */
|
|
149
|
+
if (file.startsWith(path.join(cwd, 'src/views'))) {
|
|
150
|
+
const localePath = path.join(fileDir, 'locale.ts')
|
|
151
|
+
const localeKeys = loadLocaleKeys(localePath)
|
|
152
|
+
|
|
153
|
+
if (!importedLocale || !localeKeys) {
|
|
154
|
+
noLocaleUsage.push({
|
|
155
|
+
file: path.relative(cwd, file),
|
|
156
|
+
keys: usedKeys,
|
|
157
|
+
})
|
|
158
|
+
continue
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
for (const key of usedKeys) {
|
|
162
|
+
if (!localeKeys.includes(key)) {
|
|
163
|
+
missingKeys.push({
|
|
164
|
+
file: path.relative(cwd, file),
|
|
165
|
+
key,
|
|
166
|
+
})
|
|
167
|
+
}
|
|
168
|
+
}
|
|
119
169
|
|
|
120
|
-
if (!usedLocale || !localeKeys) {
|
|
121
|
-
noLocaleUsage.push({
|
|
122
|
-
file: path.relative(cwd, file),
|
|
123
|
-
keys: usedKeys,
|
|
124
|
-
})
|
|
125
170
|
continue
|
|
126
171
|
}
|
|
127
172
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
173
|
+
/* ---------- components 逻辑 ---------- */
|
|
174
|
+
if (file.startsWith(componentsRoot)) {
|
|
175
|
+
const localePath = findNearestLocale(fileDir, componentsRoot)
|
|
176
|
+
const localeKeys = localePath && loadLocaleKeys(localePath)
|
|
177
|
+
|
|
178
|
+
if (!localeKeys) {
|
|
179
|
+
noLocaleUsage.push({
|
|
131
180
|
file: path.relative(cwd, file),
|
|
132
|
-
|
|
181
|
+
keys: usedKeys,
|
|
133
182
|
})
|
|
183
|
+
continue
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
for (const key of usedKeys) {
|
|
187
|
+
if (!localeKeys.includes(key)) {
|
|
188
|
+
missingKeys.push({
|
|
189
|
+
file: path.relative(cwd, file),
|
|
190
|
+
key,
|
|
191
|
+
})
|
|
192
|
+
}
|
|
134
193
|
}
|
|
135
194
|
}
|
|
136
195
|
}
|
|
@@ -146,14 +205,14 @@ function run(userOptions = {}) {
|
|
|
146
205
|
}
|
|
147
206
|
|
|
148
207
|
if (noLocaleUsage.length) {
|
|
149
|
-
console.warn('\n⚠️ 使用了 t
|
|
208
|
+
console.warn('\n⚠️ 使用了 $t / t 但未找到 locale.ts:')
|
|
150
209
|
noLocaleUsage.forEach(i =>
|
|
151
210
|
console.warn(` ${i.file}`)
|
|
152
211
|
)
|
|
153
212
|
}
|
|
154
213
|
|
|
155
214
|
if (!missingKeys.length && !noLocaleUsage.length) {
|
|
156
|
-
console.log('✅ views
|
|
215
|
+
console.log('✅ 国际化检查通过(views + components)')
|
|
157
216
|
}
|
|
158
217
|
}
|
|
159
218
|
|
|
@@ -162,7 +221,7 @@ function run(userOptions = {}) {
|
|
|
162
221
|
missingKeys,
|
|
163
222
|
noLocaleUsage,
|
|
164
223
|
scannedFiles: files.length,
|
|
165
|
-
options,
|
|
224
|
+
options,
|
|
166
225
|
}
|
|
167
226
|
}
|
|
168
227
|
|