@intlify/unplugin-vue-i18n 5.0.0-beta.1 → 5.0.0-beta.2
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/README.md +13 -1
- package/lib/index.cjs +482 -107
- package/lib/index.mjs +480 -106
- package/lib/types.d.cts +1 -0
- package/lib/types.d.mts +1 -0
- package/lib/types.d.ts +1 -0
- package/lib/vite.cjs +10 -6
- package/lib/vite.mjs +10 -6
- package/lib/webpack.cjs +10 -6
- package/lib/webpack.mjs +10 -6
- package/package.json +11 -17
package/lib/index.mjs
CHANGED
|
@@ -1,53 +1,19 @@
|
|
|
1
1
|
import { createUnplugin } from 'unplugin';
|
|
2
|
-
import { normalize, parse } from 'pathe';
|
|
3
2
|
import createDebug from 'debug';
|
|
4
|
-
import fg from 'fast-glob';
|
|
5
|
-
import { isArray, isString, isBoolean, assign, isNumber, isEmptyObject, generateCodeFrame } from '@intlify/shared';
|
|
6
|
-
import { createFilter } from '@rollup/pluginutils';
|
|
7
|
-
import { generateJSON, generateYAML, generateJavaScript } from '@intlify/bundle-utils';
|
|
8
|
-
import { parse as parse$1 } from '@vue/compiler-sfc';
|
|
9
3
|
import fs, { promises } from 'node:fs';
|
|
10
4
|
import pc from 'picocolors';
|
|
11
5
|
import module from 'node:module';
|
|
12
6
|
import path from 'node:path';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
ret.src = params.has("src");
|
|
24
|
-
ret.raw = params.has("raw");
|
|
25
|
-
if (params.has("type")) {
|
|
26
|
-
ret.type = params.get("type");
|
|
27
|
-
}
|
|
28
|
-
if (params.has("blockType")) {
|
|
29
|
-
ret.blockType = params.get("blockType");
|
|
30
|
-
}
|
|
31
|
-
if (params.has("index")) {
|
|
32
|
-
ret.index = Number(params.get("index"));
|
|
33
|
-
}
|
|
34
|
-
if (params.has("locale")) {
|
|
35
|
-
ret.locale = params.get("locale");
|
|
36
|
-
}
|
|
37
|
-
if (langPart) {
|
|
38
|
-
const [, lang] = langPart.split(".");
|
|
39
|
-
ret.lang = lang;
|
|
40
|
-
} else if (params.has("lang")) {
|
|
41
|
-
ret.lang = params.get("lang");
|
|
42
|
-
}
|
|
43
|
-
if (params.has("issuerPath")) {
|
|
44
|
-
ret.issuerPath = params.get("issuerPath");
|
|
45
|
-
}
|
|
46
|
-
return {
|
|
47
|
-
filename,
|
|
48
|
-
query: ret
|
|
49
|
-
};
|
|
50
|
-
}
|
|
7
|
+
import { normalize, parse } from 'pathe';
|
|
8
|
+
import { isArray, isString, isBoolean, assign, isNumber, isEmptyObject, generateCodeFrame } from '@intlify/shared';
|
|
9
|
+
import fg from 'fast-glob';
|
|
10
|
+
import { createFilter } from '@rollup/pluginutils';
|
|
11
|
+
import { generateJSON, generateYAML, generateJavaScript } from '@intlify/bundle-utils';
|
|
12
|
+
import { parse as parse$1 } from 'vue/compiler-sfc';
|
|
13
|
+
import { transformVTDirective } from '@intlify/vue-i18n-extensions';
|
|
14
|
+
import { analyze } from '@typescript-eslint/scope-manager';
|
|
15
|
+
import { parse as parse$2, simpleTraverse, AST_NODE_TYPES } from '@typescript-eslint/typescript-estree';
|
|
16
|
+
import eslintUitls from '@eslint-community/eslint-utils';
|
|
51
17
|
|
|
52
18
|
const _require = module.createRequire(import.meta.url);
|
|
53
19
|
function checkInstallPackage(debug) {
|
|
@@ -74,6 +40,9 @@ function resolvePkgPath(id, debug) {
|
|
|
74
40
|
return null;
|
|
75
41
|
}
|
|
76
42
|
}
|
|
43
|
+
function resolveNamespace(name) {
|
|
44
|
+
return `unplugin-vue-i18n:${name}`;
|
|
45
|
+
}
|
|
77
46
|
function warn(...args) {
|
|
78
47
|
console.warn(pc.yellow(pc.bold(`[unplugin-vue-i18n] `)), ...args);
|
|
79
48
|
}
|
|
@@ -86,22 +55,34 @@ async function getRaw(path2) {
|
|
|
86
55
|
function raiseError(message) {
|
|
87
56
|
throw new Error(`[unplugin-vue-i18n] ${message}`);
|
|
88
57
|
}
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
58
|
+
function getVitePlugin(config, name) {
|
|
59
|
+
return config.plugins.find((p) => p.name === name);
|
|
60
|
+
}
|
|
61
|
+
function checkVuePlugin(vuePlugin) {
|
|
62
|
+
if (vuePlugin == null || !vuePlugin.api) {
|
|
63
|
+
error(
|
|
64
|
+
"`@vitejs/plugin-vue` plugin is not found or invalid version. Please install `@vitejs/plugin-vue` v4.3.4 or later version."
|
|
65
|
+
);
|
|
66
|
+
return false;
|
|
98
67
|
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
const isWindows = typeof process !== "undefined" && process.platform === "win32";
|
|
71
|
+
const windowsSlashRE = /\\/g;
|
|
72
|
+
function slash(p) {
|
|
73
|
+
return p.replace(windowsSlashRE, "/");
|
|
74
|
+
}
|
|
75
|
+
function normalizePath(id) {
|
|
76
|
+
return path.posix.normalize(isWindows ? slash(id) : id);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function resolveOptions(options, installedPkgInfo) {
|
|
99
80
|
let onlyLocales = [];
|
|
100
81
|
if (options.onlyLocales) {
|
|
101
|
-
onlyLocales =
|
|
82
|
+
onlyLocales = isArray(options.onlyLocales) ? options.onlyLocales : [options.onlyLocales];
|
|
102
83
|
}
|
|
103
84
|
let include = options.include;
|
|
104
|
-
let exclude =
|
|
85
|
+
let exclude = void 0;
|
|
105
86
|
if (include) {
|
|
106
87
|
if (isArray(include)) {
|
|
107
88
|
include = include.map((item) => normalize(item));
|
|
@@ -111,35 +92,137 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
111
92
|
} else {
|
|
112
93
|
exclude = "**/**";
|
|
113
94
|
}
|
|
114
|
-
const filter = createFilter(include, exclude);
|
|
115
95
|
const forceStringify = !!options.forceStringify;
|
|
116
96
|
const defaultSFCLang = isString(options.defaultSFCLang) ? options.defaultSFCLang : "json";
|
|
117
97
|
const globalSFCScope = !!options.globalSFCScope;
|
|
118
98
|
const runtimeOnly = isBoolean(options.runtimeOnly) ? options.runtimeOnly : true;
|
|
119
|
-
debug("runtimeOnly", runtimeOnly);
|
|
120
99
|
const dropMessageCompiler = !!options.dropMessageCompiler;
|
|
121
|
-
debug("dropMessageCompiler", dropMessageCompiler);
|
|
122
100
|
const compositionOnly = installedPkgInfo.pkg === "vue-i18n" ? isBoolean(options.compositionOnly) ? options.compositionOnly : true : true;
|
|
123
|
-
debug("compositionOnly", compositionOnly);
|
|
124
101
|
const fullInstall = installedPkgInfo.pkg === "vue-i18n" ? isBoolean(options.fullInstall) ? options.fullInstall : true : false;
|
|
125
|
-
debug("fullInstall", fullInstall);
|
|
126
102
|
const ssrBuild = !!options.ssr;
|
|
127
|
-
debug("ssr", ssrBuild);
|
|
128
|
-
const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
|
|
129
|
-
return `${installedPkgInfo.alias}/dist/${installedPkgInfo.pkg}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.mjs"}`;
|
|
130
|
-
};
|
|
131
103
|
const allowDynamic = !!options.allowDynamic;
|
|
132
|
-
debug("allowDynamic", allowDynamic);
|
|
133
104
|
const strictMessage = isBoolean(options.strictMessage) ? options.strictMessage : true;
|
|
134
|
-
debug("strictMessage", strictMessage);
|
|
135
105
|
const escapeHtml = !!options.escapeHtml;
|
|
136
|
-
|
|
106
|
+
const optimizeTranslationDirective = isString(options.optimizeTranslationDirective) || isArray(options.optimizeTranslationDirective) ? options.optimizeTranslationDirective : !!options.optimizeTranslationDirective;
|
|
107
|
+
const translationIdentifiers = /* @__PURE__ */ new Map();
|
|
108
|
+
return {
|
|
109
|
+
include,
|
|
110
|
+
exclude,
|
|
111
|
+
onlyLocales,
|
|
112
|
+
forceStringify,
|
|
113
|
+
defaultSFCLang,
|
|
114
|
+
globalSFCScope,
|
|
115
|
+
runtimeOnly,
|
|
116
|
+
dropMessageCompiler,
|
|
117
|
+
compositionOnly,
|
|
118
|
+
fullInstall,
|
|
119
|
+
ssrBuild,
|
|
120
|
+
allowDynamic,
|
|
121
|
+
strictMessage,
|
|
122
|
+
escapeHtml,
|
|
123
|
+
optimizeTranslationDirective,
|
|
124
|
+
translationIdentifiers
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function parseVueRequest(id) {
|
|
129
|
+
const [filename, rawQuery] = id.split(`?`, 2);
|
|
130
|
+
const params = new URLSearchParams(rawQuery);
|
|
131
|
+
const ret = {};
|
|
132
|
+
const langPart = Object.keys(Object.fromEntries(params)).find(
|
|
133
|
+
(key) => /lang\./i.test(key)
|
|
134
|
+
);
|
|
135
|
+
ret.vue = params.has("vue");
|
|
136
|
+
ret.global = params.has("global");
|
|
137
|
+
ret.src = params.has("src");
|
|
138
|
+
ret.raw = params.has("raw");
|
|
139
|
+
if (params.has("type")) {
|
|
140
|
+
ret.type = params.get("type");
|
|
141
|
+
}
|
|
142
|
+
if (params.has("blockType")) {
|
|
143
|
+
ret.blockType = params.get("blockType");
|
|
144
|
+
}
|
|
145
|
+
if (params.has("index")) {
|
|
146
|
+
ret.index = Number(params.get("index"));
|
|
147
|
+
}
|
|
148
|
+
if (params.has("locale")) {
|
|
149
|
+
ret.locale = params.get("locale");
|
|
150
|
+
}
|
|
151
|
+
if (langPart) {
|
|
152
|
+
const [, lang] = langPart.split(".");
|
|
153
|
+
ret.lang = lang;
|
|
154
|
+
} else if (params.has("lang")) {
|
|
155
|
+
ret.lang = params.get("lang");
|
|
156
|
+
}
|
|
157
|
+
if (params.has("issuerPath")) {
|
|
158
|
+
ret.issuerPath = params.get("issuerPath");
|
|
159
|
+
}
|
|
160
|
+
return {
|
|
161
|
+
filename,
|
|
162
|
+
query: ret
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
function getVueCompiler(vuePlugin) {
|
|
167
|
+
return vuePlugin?.api?.options.compiler;
|
|
168
|
+
}
|
|
169
|
+
function getVuePluginOptions(vuePlugin) {
|
|
170
|
+
return {
|
|
171
|
+
isProduction: vuePlugin?.api?.options.isProduction,
|
|
172
|
+
root: vuePlugin?.api?.options.root,
|
|
173
|
+
template: vuePlugin?.api?.options.template,
|
|
174
|
+
compiler: vuePlugin?.api?.options.compiler
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function createDescriptor(filename, source, { template, compiler }) {
|
|
179
|
+
const { descriptor, errors } = compiler.parse(source, {
|
|
180
|
+
filename,
|
|
181
|
+
templateParseOptions: template?.compilerOptions
|
|
182
|
+
});
|
|
183
|
+
return { descriptor, errors };
|
|
184
|
+
}
|
|
185
|
+
function getDescriptor(filename, code, options) {
|
|
186
|
+
const { descriptor, errors } = createDescriptor(filename, code, options);
|
|
187
|
+
if (errors.length) {
|
|
188
|
+
throw errors[0];
|
|
189
|
+
}
|
|
190
|
+
return descriptor;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const INTLIFY_BUNDLE_IMPORT_ID = "@intlify/unplugin-vue-i18n/messages";
|
|
194
|
+
const VIRTUAL_PREFIX = "\0";
|
|
195
|
+
const debug$2 = createDebug(resolveNamespace("resource"));
|
|
196
|
+
function resourcePlugin({
|
|
197
|
+
onlyLocales,
|
|
198
|
+
include,
|
|
199
|
+
exclude,
|
|
200
|
+
forceStringify,
|
|
201
|
+
defaultSFCLang,
|
|
202
|
+
globalSFCScope,
|
|
203
|
+
runtimeOnly,
|
|
204
|
+
dropMessageCompiler,
|
|
205
|
+
compositionOnly,
|
|
206
|
+
fullInstall,
|
|
207
|
+
ssrBuild,
|
|
208
|
+
strictMessage,
|
|
209
|
+
allowDynamic,
|
|
210
|
+
escapeHtml
|
|
211
|
+
}, meta, installedPkgInfo) {
|
|
212
|
+
const filter = createFilter(include, exclude);
|
|
213
|
+
const getVueI18nAliasPath = ({ ssr = false, runtimeOnly: runtimeOnly2 = false }) => {
|
|
214
|
+
return `${installedPkgInfo.alias}/dist/${installedPkgInfo.pkg}${runtimeOnly2 ? ".runtime" : ""}.${!ssr ? "esm-bundler.js" : "node.mjs"}`;
|
|
215
|
+
};
|
|
137
216
|
let isProduction = false;
|
|
138
217
|
let sourceMap = false;
|
|
139
218
|
const vueI18nAliasName = installedPkgInfo.alias;
|
|
140
|
-
debug(`vue-i18n alias name: ${vueI18nAliasName}`);
|
|
219
|
+
debug$2(`vue-i18n alias name: ${vueI18nAliasName}`);
|
|
220
|
+
let vuePlugin = null;
|
|
221
|
+
const getSfcParser = () => {
|
|
222
|
+
return vuePlugin ? getVueCompiler(vuePlugin).parse : parse$1;
|
|
223
|
+
};
|
|
141
224
|
return {
|
|
142
|
-
name: "
|
|
225
|
+
name: resolveNamespace("resource"),
|
|
143
226
|
/**
|
|
144
227
|
* NOTE:
|
|
145
228
|
*
|
|
@@ -159,7 +242,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
159
242
|
__VUE_I18N_PROD_DEVTOOLS__: false
|
|
160
243
|
}
|
|
161
244
|
};
|
|
162
|
-
debug("define Config:", defineConfig);
|
|
245
|
+
debug$2("define Config:", defineConfig);
|
|
163
246
|
const aliasConfig = {
|
|
164
247
|
resolve: {
|
|
165
248
|
alias: {
|
|
@@ -170,16 +253,20 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
170
253
|
}
|
|
171
254
|
}
|
|
172
255
|
};
|
|
173
|
-
debug("alias Config:", aliasConfig);
|
|
256
|
+
debug$2("alias Config:", aliasConfig);
|
|
174
257
|
return assign(defineConfig, aliasConfig);
|
|
175
258
|
},
|
|
176
259
|
configResolved(config) {
|
|
260
|
+
vuePlugin = getVitePlugin(config, "vite:vue");
|
|
261
|
+
if (!checkVuePlugin(vuePlugin)) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
177
264
|
isProduction = config.isProduction;
|
|
178
265
|
sourceMap = config.command === "build" ? !!config.build.sourcemap : false;
|
|
179
|
-
debug(
|
|
266
|
+
debug$2(
|
|
180
267
|
`configResolved: isProduction = ${isProduction}, sourceMap = ${sourceMap}`
|
|
181
268
|
);
|
|
182
|
-
const jsonPlugin = config
|
|
269
|
+
const jsonPlugin = getVitePlugin(config, "vite:json");
|
|
183
270
|
if (jsonPlugin) {
|
|
184
271
|
const orgTransform = jsonPlugin.transform;
|
|
185
272
|
jsonPlugin.transform = async function(code, id) {
|
|
@@ -190,13 +277,11 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
190
277
|
if (query.vue) {
|
|
191
278
|
return;
|
|
192
279
|
}
|
|
193
|
-
debug("org json plugin");
|
|
280
|
+
debug$2("org json plugin");
|
|
194
281
|
return orgTransform.apply(this, [code, id]);
|
|
195
282
|
};
|
|
196
283
|
}
|
|
197
|
-
const esbuildPlugin = config
|
|
198
|
-
(p) => p.name === "vite:esbuild"
|
|
199
|
-
);
|
|
284
|
+
const esbuildPlugin = getVitePlugin(config, "vite:esbuild");
|
|
200
285
|
if (esbuildPlugin) {
|
|
201
286
|
const orgTransform = esbuildPlugin.transform;
|
|
202
287
|
esbuildPlugin.transform = async function(code, id) {
|
|
@@ -229,10 +314,10 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
229
314
|
forceStringify
|
|
230
315
|
}
|
|
231
316
|
);
|
|
232
|
-
debug("parseOptions", parseOptions);
|
|
317
|
+
debug$2("parseOptions", parseOptions);
|
|
233
318
|
const { code: generatedCode, map } = generate(_code, parseOptions);
|
|
234
|
-
debug("generated code", generatedCode);
|
|
235
|
-
debug("sourcemap", map, sourceMap);
|
|
319
|
+
debug$2("generated code", generatedCode);
|
|
320
|
+
debug$2("sourcemap", map, sourceMap);
|
|
236
321
|
if (_code === generatedCode)
|
|
237
322
|
return;
|
|
238
323
|
return {
|
|
@@ -260,7 +345,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
260
345
|
webpack(compiler) {
|
|
261
346
|
isProduction = compiler.options.mode !== "development";
|
|
262
347
|
sourceMap = !!compiler.options.devtool;
|
|
263
|
-
debug(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
|
|
348
|
+
debug$2(`webpack: isProduction = ${isProduction}, sourceMap = ${sourceMap}`);
|
|
264
349
|
compiler.options.resolve = normalizeConfigResolveAlias(
|
|
265
350
|
compiler.options.resolve,
|
|
266
351
|
meta.framework
|
|
@@ -269,7 +354,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
269
354
|
ssr: ssrBuild,
|
|
270
355
|
runtimeOnly
|
|
271
356
|
});
|
|
272
|
-
debug(
|
|
357
|
+
debug$2(
|
|
273
358
|
`set ${vueI18nAliasName}: ${getVueI18nAliasPath({
|
|
274
359
|
ssr: ssrBuild,
|
|
275
360
|
runtimeOnly
|
|
@@ -284,10 +369,10 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
284
369
|
__INTLIFY_PROD_DEVTOOLS__: "false"
|
|
285
370
|
})
|
|
286
371
|
);
|
|
287
|
-
debug(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
|
|
288
|
-
debug(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
|
|
372
|
+
debug$2(`set __VUE_I18N_LEGACY_API__ is '${compositionOnly}'`);
|
|
373
|
+
debug$2(`set __VUE_I18N_FULL_INSTALL__ is '${fullInstall}'`);
|
|
289
374
|
} else {
|
|
290
|
-
debug("ignore vue-i18n feature flags with webpack.DefinePlugin");
|
|
375
|
+
debug$2("ignore vue-i18n feature flags with webpack.DefinePlugin");
|
|
291
376
|
}
|
|
292
377
|
});
|
|
293
378
|
if (compiler.options.module) {
|
|
@@ -301,15 +386,14 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
301
386
|
}
|
|
302
387
|
},
|
|
303
388
|
resolveId(id, importer) {
|
|
304
|
-
debug("resolveId", id, importer);
|
|
389
|
+
debug$2("resolveId", id, importer);
|
|
305
390
|
if (id === INTLIFY_BUNDLE_IMPORT_ID) {
|
|
306
391
|
return asVirtualId(id, meta.framework);
|
|
307
392
|
}
|
|
308
393
|
},
|
|
309
394
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
310
395
|
async load(id) {
|
|
311
|
-
debug("load", id);
|
|
312
|
-
const { query } = parseVueRequest(id);
|
|
396
|
+
debug$2("load", id);
|
|
313
397
|
if (INTLIFY_BUNDLE_IMPORT_ID === getVirtualId(id, meta.framework) && include) {
|
|
314
398
|
let resourcePaths = [];
|
|
315
399
|
const includePaths = isArray(include) ? include : [include];
|
|
@@ -321,7 +405,6 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
321
405
|
);
|
|
322
406
|
const code = await generateBundleResources(
|
|
323
407
|
resourcePaths,
|
|
324
|
-
query,
|
|
325
408
|
isProduction,
|
|
326
409
|
{
|
|
327
410
|
forceStringify,
|
|
@@ -336,7 +419,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
336
419
|
}
|
|
337
420
|
},
|
|
338
421
|
transformInclude(id) {
|
|
339
|
-
debug("transformInclude", id);
|
|
422
|
+
debug$2("transformInclude", id);
|
|
340
423
|
if (meta.framework === "vite") {
|
|
341
424
|
return true;
|
|
342
425
|
} else {
|
|
@@ -346,7 +429,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
346
429
|
},
|
|
347
430
|
async transform(code, id) {
|
|
348
431
|
const { filename, query } = parseVueRequest(id);
|
|
349
|
-
debug("transform", id, JSON.stringify(query), filename);
|
|
432
|
+
debug$2("transform", id, JSON.stringify(query), filename);
|
|
350
433
|
let langInfo = defaultSFCLang;
|
|
351
434
|
let inSourceMap;
|
|
352
435
|
if (!query.vue) {
|
|
@@ -369,10 +452,10 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
369
452
|
forceStringify
|
|
370
453
|
}
|
|
371
454
|
);
|
|
372
|
-
debug("parseOptions", parseOptions);
|
|
455
|
+
debug$2("parseOptions", parseOptions);
|
|
373
456
|
const { code: generatedCode, map } = generate(code, parseOptions);
|
|
374
|
-
debug("generated code", generatedCode);
|
|
375
|
-
debug("sourcemap", map, sourceMap);
|
|
457
|
+
debug$2("generated code", generatedCode);
|
|
458
|
+
debug$2("sourcemap", map, sourceMap);
|
|
376
459
|
if (code === generatedCode)
|
|
377
460
|
return;
|
|
378
461
|
return {
|
|
@@ -388,7 +471,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
388
471
|
} else if (defaultSFCLang) {
|
|
389
472
|
langInfo = defaultSFCLang;
|
|
390
473
|
}
|
|
391
|
-
debug("langInfo", langInfo);
|
|
474
|
+
debug$2("langInfo", langInfo);
|
|
392
475
|
const generate = /\.?json5?/.test(langInfo) ? generateJSON : generateYAML;
|
|
393
476
|
const parseOptions = getOptions(
|
|
394
477
|
filename,
|
|
@@ -405,17 +488,18 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
405
488
|
forceStringify
|
|
406
489
|
}
|
|
407
490
|
);
|
|
408
|
-
debug("parseOptions", parseOptions);
|
|
491
|
+
debug$2("parseOptions", parseOptions);
|
|
409
492
|
const source = await getCode(
|
|
410
493
|
code,
|
|
411
494
|
filename,
|
|
412
495
|
sourceMap,
|
|
413
496
|
query,
|
|
497
|
+
getSfcParser(),
|
|
414
498
|
meta.framework
|
|
415
499
|
);
|
|
416
500
|
const { code: generatedCode, map } = generate(source, parseOptions);
|
|
417
|
-
debug("generated code", generatedCode);
|
|
418
|
-
debug("sourcemap", map, sourceMap);
|
|
501
|
+
debug$2("generated code", generatedCode);
|
|
502
|
+
debug$2("sourcemap", map, sourceMap);
|
|
419
503
|
if (code === generatedCode)
|
|
420
504
|
return;
|
|
421
505
|
return {
|
|
@@ -427,7 +511,7 @@ const unplugin = createUnplugin((options = {}, meta) => {
|
|
|
427
511
|
}
|
|
428
512
|
}
|
|
429
513
|
};
|
|
430
|
-
}
|
|
514
|
+
}
|
|
431
515
|
function getGenerator(ext, defaultGen = generateJSON) {
|
|
432
516
|
return /\.?json5?$/.test(ext) ? generateJSON : /\.ya?ml$/.test(ext) ? generateYAML : /\.([c|m]?js|[c|m]?ts)$/.test(ext) ? generateJavaScript : defaultGen;
|
|
433
517
|
}
|
|
@@ -460,7 +544,7 @@ async function loadWebpack() {
|
|
|
460
544
|
}
|
|
461
545
|
return webpack;
|
|
462
546
|
}
|
|
463
|
-
async function generateBundleResources(resources,
|
|
547
|
+
async function generateBundleResources(resources, isProduction, {
|
|
464
548
|
forceStringify = false,
|
|
465
549
|
isGlobal = false,
|
|
466
550
|
onlyLocales = [],
|
|
@@ -470,7 +554,7 @@ async function generateBundleResources(resources, query, isProduction, {
|
|
|
470
554
|
}) {
|
|
471
555
|
const codes = [];
|
|
472
556
|
for (const res of resources) {
|
|
473
|
-
debug(`${res} bundle loading ...`);
|
|
557
|
+
debug$2(`${res} bundle loading ...`);
|
|
474
558
|
if (/\.(json5?|ya?ml)$/.test(res)) {
|
|
475
559
|
const { ext, name } = parse(res);
|
|
476
560
|
const source = await getRaw(res);
|
|
@@ -485,7 +569,7 @@ async function generateBundleResources(resources, query, isProduction, {
|
|
|
485
569
|
});
|
|
486
570
|
parseOptions.type = "bare";
|
|
487
571
|
const { code } = generate(source, parseOptions);
|
|
488
|
-
debug("generated code", code);
|
|
572
|
+
debug$2("generated code", code);
|
|
489
573
|
codes.push(`${JSON.stringify(name)}: ${code}`);
|
|
490
574
|
}
|
|
491
575
|
}
|
|
@@ -513,24 +597,24 @@ export default mergeDeep({},
|
|
|
513
597
|
${codes.map((code) => `{${code}}`).join(",\n")}
|
|
514
598
|
);`;
|
|
515
599
|
}
|
|
516
|
-
async function getCode(source, filename, sourceMap, query, framework = "vite") {
|
|
600
|
+
async function getCode(source, filename, sourceMap, query, parser, framework = "vite") {
|
|
517
601
|
const { index, issuerPath } = query;
|
|
518
602
|
if (!isNumber(index)) {
|
|
519
603
|
raiseError(`unexpected index: ${index}`);
|
|
520
604
|
}
|
|
521
605
|
if (framework === "webpack") {
|
|
522
606
|
if (issuerPath) {
|
|
523
|
-
debug(`getCode (webpack) ${index} via issuerPath`, issuerPath);
|
|
607
|
+
debug$2(`getCode (webpack) ${index} via issuerPath`, issuerPath);
|
|
524
608
|
return await getRaw(filename);
|
|
525
609
|
} else {
|
|
526
|
-
const result =
|
|
610
|
+
const result = parser(await getRaw(filename), {
|
|
527
611
|
sourceMap,
|
|
528
612
|
filename
|
|
529
613
|
});
|
|
530
614
|
const block = result.descriptor.customBlocks[index];
|
|
531
615
|
if (block) {
|
|
532
616
|
const code = block.src ? await getRaw(block.src) : block.content;
|
|
533
|
-
debug(`getCode (webpack) ${index} from SFC`, code);
|
|
617
|
+
debug$2(`getCode (webpack) ${index} from SFC`, code);
|
|
534
618
|
return code;
|
|
535
619
|
} else {
|
|
536
620
|
return source;
|
|
@@ -606,4 +690,294 @@ function asVirtualId(id, framework = "vite") {
|
|
|
606
690
|
return framework === "vite" ? VIRTUAL_PREFIX + id : id;
|
|
607
691
|
}
|
|
608
692
|
|
|
693
|
+
const debug$1 = createDebug(resolveNamespace("directive"));
|
|
694
|
+
function directivePlugin({
|
|
695
|
+
optimizeTranslationDirective,
|
|
696
|
+
translationIdentifiers
|
|
697
|
+
}) {
|
|
698
|
+
let vuePlugin = null;
|
|
699
|
+
let vuePluginOptions = null;
|
|
700
|
+
return {
|
|
701
|
+
name: resolveNamespace("directive"),
|
|
702
|
+
enforce: "pre",
|
|
703
|
+
vite: {
|
|
704
|
+
config(config) {
|
|
705
|
+
vuePlugin = getVitePlugin(config, "vite:vue");
|
|
706
|
+
if (!checkVuePlugin(vuePlugin)) {
|
|
707
|
+
return;
|
|
708
|
+
}
|
|
709
|
+
if (optimizeTranslationDirective) {
|
|
710
|
+
vuePlugin.api.options = resolveVueOptions(
|
|
711
|
+
vuePlugin,
|
|
712
|
+
optimizeTranslationDirective,
|
|
713
|
+
translationIdentifiers
|
|
714
|
+
);
|
|
715
|
+
debug$1(`vite:vue options['template']:`, vuePlugin.api.options);
|
|
716
|
+
}
|
|
717
|
+
},
|
|
718
|
+
configResolved(config) {
|
|
719
|
+
vuePlugin = getVitePlugin(config, "vite:vue");
|
|
720
|
+
if (!checkVuePlugin(vuePlugin)) {
|
|
721
|
+
return;
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
async transform(code, id) {
|
|
726
|
+
const { filename } = parseVueRequest(id);
|
|
727
|
+
if (vuePluginOptions == null) {
|
|
728
|
+
vuePluginOptions = getVuePluginOptions(vuePlugin);
|
|
729
|
+
}
|
|
730
|
+
if (id.endsWith(".vue")) {
|
|
731
|
+
analyzeIdentifiers(
|
|
732
|
+
getDescriptor(filename, code, vuePluginOptions),
|
|
733
|
+
vuePluginOptions,
|
|
734
|
+
translationIdentifiers
|
|
735
|
+
);
|
|
736
|
+
}
|
|
737
|
+
return code;
|
|
738
|
+
}
|
|
739
|
+
};
|
|
740
|
+
}
|
|
741
|
+
function resolveVueOptions(vuePlugin, optimizeTranslationDirective, translationIdentifiers) {
|
|
742
|
+
var _a, _b;
|
|
743
|
+
const vueOptions = vuePlugin.api.options;
|
|
744
|
+
vueOptions.template || (vueOptions.template = {});
|
|
745
|
+
(_a = vueOptions.template).compilerOptions || (_a.compilerOptions = {});
|
|
746
|
+
(_b = vueOptions.template.compilerOptions).directiveTransforms || (_b.directiveTransforms = {});
|
|
747
|
+
const translationSignatureResolver = (context, baseResolver) => {
|
|
748
|
+
const { filename } = context;
|
|
749
|
+
const vuePluginOptions = getVuePluginOptions(vuePlugin);
|
|
750
|
+
const normalizedFilename = normalizePath(
|
|
751
|
+
path.relative(vuePluginOptions.root, filename)
|
|
752
|
+
);
|
|
753
|
+
const resolveIdentifier2 = translationIdentifiers.get(normalizedFilename);
|
|
754
|
+
debug$1("resolved vue-i18n Identifier", resolveIdentifier2);
|
|
755
|
+
if (resolveIdentifier2 == null) {
|
|
756
|
+
return void 0;
|
|
757
|
+
}
|
|
758
|
+
if (resolveIdentifier2.type === "identifier") {
|
|
759
|
+
return baseResolver(context, resolveIdentifier2.key);
|
|
760
|
+
} else {
|
|
761
|
+
const resolvedSignature = baseResolver(context, resolveIdentifier2.key);
|
|
762
|
+
return resolveIdentifier2?.style === "script-setup" ? `${resolvedSignature}.t` : resolvedSignature;
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
vueOptions.template.compilerOptions.directiveTransforms.t = transformVTDirective({
|
|
766
|
+
translationSignatures: isBoolean(optimizeTranslationDirective) ? translationSignatureResolver : optimizeTranslationDirective
|
|
767
|
+
});
|
|
768
|
+
return vueOptions;
|
|
769
|
+
}
|
|
770
|
+
function analyzeIdentifiers(descriptor, { root }, translationIdentifiers) {
|
|
771
|
+
const source = descriptor.scriptSetup?.content || descriptor.script?.content;
|
|
772
|
+
debug$1("getDescriptor content", source);
|
|
773
|
+
if (!source) {
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
const ast = parse$2(source, { range: true });
|
|
777
|
+
simpleTraverse(ast, {
|
|
778
|
+
enter(node, parent) {
|
|
779
|
+
if (parent) {
|
|
780
|
+
node.parent = parent;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
});
|
|
784
|
+
const scopeManager = analyze(ast, { sourceType: "module" });
|
|
785
|
+
const scope = getScope(scopeManager, ast);
|
|
786
|
+
const importLocalName = getImportLocalName(scope, "vue-i18n", "useI18n");
|
|
787
|
+
if (importLocalName == null) {
|
|
788
|
+
return;
|
|
789
|
+
}
|
|
790
|
+
debug$1("importLocalName", importLocalName);
|
|
791
|
+
const resolvedIdentifier = getVueI18nIdentifier(scope, importLocalName);
|
|
792
|
+
if (resolvedIdentifier) {
|
|
793
|
+
const normalizedFilename = normalizePath(
|
|
794
|
+
path.relative(root, descriptor.filename)
|
|
795
|
+
);
|
|
796
|
+
debug$1("set vue-i18n resolved identifier: ", resolvedIdentifier);
|
|
797
|
+
translationIdentifiers.set(normalizedFilename, resolvedIdentifier);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
function getScope(manager, node) {
|
|
801
|
+
const scope = manager.acquire(node, true);
|
|
802
|
+
if (scope) {
|
|
803
|
+
if (scope.type === "function-expression-name") {
|
|
804
|
+
return scope.childScopes[0];
|
|
805
|
+
}
|
|
806
|
+
return scope;
|
|
807
|
+
}
|
|
808
|
+
return manager.scopes[0];
|
|
809
|
+
}
|
|
810
|
+
function getImportLocalName(scope, source, imported) {
|
|
811
|
+
const importDecl = getImportDeclaration(scope, source);
|
|
812
|
+
if (importDecl) {
|
|
813
|
+
const specifierNode = importDecl.specifiers.find(
|
|
814
|
+
(specifierNode2) => isImportedIdentifierInImportClause(specifierNode2) && specifierNode2.imported.name === imported
|
|
815
|
+
);
|
|
816
|
+
return specifierNode ? specifierNode.local.name : null;
|
|
817
|
+
}
|
|
818
|
+
return null;
|
|
819
|
+
}
|
|
820
|
+
function getImportDeclaration(scope, source) {
|
|
821
|
+
const tracker = new eslintUitls.ReferenceTracker(scope);
|
|
822
|
+
const traceMap = {
|
|
823
|
+
[source]: {
|
|
824
|
+
[eslintUitls.ReferenceTracker.ESM]: true,
|
|
825
|
+
[eslintUitls.ReferenceTracker.READ]: true
|
|
826
|
+
}
|
|
827
|
+
};
|
|
828
|
+
const refs = Array.from(tracker.iterateEsmReferences(traceMap));
|
|
829
|
+
return refs.length ? refs[0].node : null;
|
|
830
|
+
}
|
|
831
|
+
function isImportedIdentifierInImportClause(node) {
|
|
832
|
+
return "imported" in node;
|
|
833
|
+
}
|
|
834
|
+
function getVueI18nIdentifier(scope, local) {
|
|
835
|
+
const { callExpression, returnStatement } = getCallExpressionAndReturnStatement(scope, local);
|
|
836
|
+
if (callExpression == null) {
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
const id = getVariableDeclarationIdFrom(callExpression);
|
|
840
|
+
if (id == null) {
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
const variableIdPairs = parseVariableId(id);
|
|
844
|
+
debug$1("variableIdPairs:", variableIdPairs);
|
|
845
|
+
const returnVariableIdPairs = parseReturnStatement(returnStatement);
|
|
846
|
+
debug$1("returnVariableIdPairs:", returnVariableIdPairs);
|
|
847
|
+
return resolveIdentifier(variableIdPairs, returnVariableIdPairs);
|
|
848
|
+
}
|
|
849
|
+
const EMPTY_NODE_RETURN = {
|
|
850
|
+
callExpression: null,
|
|
851
|
+
returnStatement: null
|
|
852
|
+
};
|
|
853
|
+
function getCallExpressionAndReturnStatement(scope, local) {
|
|
854
|
+
const variable = eslintUitls.findVariable(scope, local);
|
|
855
|
+
if (variable == null) {
|
|
856
|
+
return EMPTY_NODE_RETURN;
|
|
857
|
+
}
|
|
858
|
+
const callExpressionRef = variable.references.find((ref) => {
|
|
859
|
+
return ref.identifier.parent?.type === AST_NODE_TYPES.CallExpression;
|
|
860
|
+
});
|
|
861
|
+
if (callExpressionRef == null) {
|
|
862
|
+
return EMPTY_NODE_RETURN;
|
|
863
|
+
}
|
|
864
|
+
let returnStatement = null;
|
|
865
|
+
if (callExpressionRef.from.type === "function" && callExpressionRef.from.block.type === AST_NODE_TYPES.FunctionExpression && callExpressionRef.from.block.parent.type === AST_NODE_TYPES.Property && callExpressionRef.from.block.parent.key.type === AST_NODE_TYPES.Identifier && callExpressionRef.from.block.parent.key.name === "setup") {
|
|
866
|
+
returnStatement = callExpressionRef.from.block.body.body.find(
|
|
867
|
+
(statement) => {
|
|
868
|
+
return statement.type === AST_NODE_TYPES.ReturnStatement;
|
|
869
|
+
}
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
return {
|
|
873
|
+
callExpression: callExpressionRef.identifier.parent,
|
|
874
|
+
returnStatement
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
function getVariableDeclarationIdFrom(node) {
|
|
878
|
+
if (node.parent?.type !== AST_NODE_TYPES.VariableDeclarator) {
|
|
879
|
+
return null;
|
|
880
|
+
}
|
|
881
|
+
return node.parent.id;
|
|
882
|
+
}
|
|
883
|
+
function parseVariableId(node) {
|
|
884
|
+
if (node.type === AST_NODE_TYPES.Identifier) {
|
|
885
|
+
return [{ key: node.name, value: null }];
|
|
886
|
+
} else {
|
|
887
|
+
const props = node.properties.filter(
|
|
888
|
+
// ignore RestElement
|
|
889
|
+
(prop) => prop.type === AST_NODE_TYPES.Property
|
|
890
|
+
);
|
|
891
|
+
const pairs = [];
|
|
892
|
+
for (const prop of props) {
|
|
893
|
+
if (prop?.key.type === AST_NODE_TYPES.Identifier && prop?.value.type === AST_NODE_TYPES.Identifier) {
|
|
894
|
+
pairs.push({ key: prop.key.name, value: prop.value.name });
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
return pairs;
|
|
898
|
+
}
|
|
899
|
+
}
|
|
900
|
+
function parseReturnStatement(node) {
|
|
901
|
+
const pairs = [];
|
|
902
|
+
if (node == null || node.argument == null) {
|
|
903
|
+
return pairs;
|
|
904
|
+
}
|
|
905
|
+
if (node.argument.type === AST_NODE_TYPES.ObjectExpression) {
|
|
906
|
+
for (const prop of node.argument.properties) {
|
|
907
|
+
if (prop.type === AST_NODE_TYPES.Property) {
|
|
908
|
+
if (prop.key.type === AST_NODE_TYPES.Identifier && prop.value.type === AST_NODE_TYPES.Identifier) {
|
|
909
|
+
pairs.push({ key: prop.key.name, value: prop.value.name });
|
|
910
|
+
} else if (prop.key.type === AST_NODE_TYPES.Identifier && prop.value.type === AST_NODE_TYPES.MemberExpression && prop.value.object.type === AST_NODE_TYPES.Identifier && prop.value.property.type === AST_NODE_TYPES.Identifier) {
|
|
911
|
+
pairs.push({
|
|
912
|
+
key: prop.key.name,
|
|
913
|
+
value: `${prop.value.object.name}.${prop.value.property.name}`
|
|
914
|
+
});
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
return pairs;
|
|
919
|
+
} else if (node.argument.type === AST_NODE_TYPES.Identifier) {
|
|
920
|
+
return pairs;
|
|
921
|
+
} else {
|
|
922
|
+
return pairs;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function resolveIdentifier(localVariables, returnVariable) {
|
|
926
|
+
if (returnVariable.length === 0) {
|
|
927
|
+
const variable = localVariables.find((pair) => pair.key === "t");
|
|
928
|
+
if (variable && variable.value) {
|
|
929
|
+
return { type: "identifier", key: variable.value };
|
|
930
|
+
}
|
|
931
|
+
const identifierOnly = localVariables.find((pair) => pair.value === null);
|
|
932
|
+
if (identifierOnly && identifierOnly.key) {
|
|
933
|
+
return { type: "object", key: identifierOnly.key, style: "script-setup" };
|
|
934
|
+
}
|
|
935
|
+
return null;
|
|
936
|
+
} else {
|
|
937
|
+
const variable = localVariables.find((pair) => pair.key === "t");
|
|
938
|
+
if (variable && variable.value) {
|
|
939
|
+
const returnVar = returnVariable.find(
|
|
940
|
+
(pair) => pair.value === variable.value
|
|
941
|
+
);
|
|
942
|
+
if (returnVar && returnVar.key) {
|
|
943
|
+
return { type: "identifier", key: returnVar.key };
|
|
944
|
+
}
|
|
945
|
+
}
|
|
946
|
+
const identifierOnly = localVariables.find((pair) => pair.value === null);
|
|
947
|
+
if (identifierOnly && identifierOnly.key) {
|
|
948
|
+
const targetKey = identifierOnly.key;
|
|
949
|
+
const returnVar = returnVariable.find(
|
|
950
|
+
(pair) => pair.value?.startsWith(targetKey)
|
|
951
|
+
);
|
|
952
|
+
if (returnVar && returnVar.key) {
|
|
953
|
+
return { type: "object", key: returnVar.key, style: "setup-hook" };
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return null;
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
const debug = createDebug(resolveNamespace("root"));
|
|
961
|
+
const installedPkgInfo = checkInstallPackage(debug);
|
|
962
|
+
const unplugin = createUnplugin((options = {}, meta) => {
|
|
963
|
+
debug("meta framework", meta.framework);
|
|
964
|
+
if (!["vite", "webpack"].includes(meta.framework)) {
|
|
965
|
+
raiseError(`This plugin is supported 'vite' and 'webpack' only`);
|
|
966
|
+
}
|
|
967
|
+
debug("plugin options (resolving):", options);
|
|
968
|
+
const resolvedOptions = resolveOptions(options, installedPkgInfo);
|
|
969
|
+
debug("plugin options (resolved):", resolvedOptions);
|
|
970
|
+
const plugins = [resourcePlugin(resolvedOptions, meta, installedPkgInfo)];
|
|
971
|
+
if (resolvedOptions.optimizeTranslationDirective) {
|
|
972
|
+
if (meta.framework === "webpack") {
|
|
973
|
+
raiseError(
|
|
974
|
+
`The 'optimizeTranslationDirective' option still is not supported for webpack.
|
|
975
|
+
We are waiting for your Pull Request \u{1F642}.`
|
|
976
|
+
);
|
|
977
|
+
}
|
|
978
|
+
plugins.push(directivePlugin(resolvedOptions));
|
|
979
|
+
}
|
|
980
|
+
return plugins;
|
|
981
|
+
});
|
|
982
|
+
|
|
609
983
|
export { unplugin as default, unplugin };
|