vite-intlayer 7.3.1 → 7.3.2-canary.0

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 CHANGED
@@ -24,8 +24,6 @@
24
24
  <a href="https://github.com/aymericzip/intlayer/blob/main/LICENSE" target="_blank" rel="noopener noreferrer nofollow"><img src="https://img.shields.io/github/license/aymericzip/intlayer?style=for-the-badge&labelColor=000000&color=FFFFFF&logoColor=000000&cacheSeconds=86400" alt="license"/></a>
25
25
  <a href="https://github.com/aymericzip/intlayer/commits/main" target="_blank" rel="noopener noreferrer nofollow"><img src="https://img.shields.io/github/last-commit/aymericzip/intlayer?style=for-the-badge&labelColor=000000&color=FFFFFF&logoColor=000000&cacheSeconds=86400" alt="last commit"/>
26
26
  </a>
27
- <a href="https://bountyhub.dev/bounties?repo=intlayer" target="_blank" rel="noopener noreferrer nofollow"><img src="https://img.shields.io/badge/Bounties-on%20BountyHub-yellow?style=for-the-badge&labelColor=000000&color=FFFFFF&logoColor=000000&cacheSeconds=86400" alt="Bounties on BountyHub"/>
28
- </a>
29
27
  </p>
30
28
 
31
29
  ![Watch the video](https://github.com/aymericzip/intlayer/blob/main/docs/assets/demo_video.gif)
@@ -0,0 +1,399 @@
1
+ const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ let node_fs = require("node:fs");
3
+ let node_fs_promises = require("node:fs/promises");
4
+ let node_module = require("node:module");
5
+ let node_path = require("node:path");
6
+ let __intlayer_babel = require("@intlayer/babel");
7
+ let __intlayer_chokidar = require("@intlayer/chokidar");
8
+ let __intlayer_config = require("@intlayer/config");
9
+ let fast_glob = require("fast-glob");
10
+ fast_glob = require_rolldown_runtime.__toESM(fast_glob);
11
+
12
+ //#region src/IntlayerCompilerPlugin.ts
13
+ /**
14
+ * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer
15
+ *
16
+ * This autonomous compiler handles:
17
+ * - Configuration loading and management
18
+ * - Hot Module Replacement (HMR) for content changes
19
+ * - File transformation with content extraction
20
+ * - Dictionary persistence and building
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * // vite.config.ts
25
+ * import { defineConfig } from 'vite';
26
+ * import { intlayerCompiler } from 'vite-intlayer';
27
+ *
28
+ * export default defineConfig({
29
+ * plugins: [intlayerCompiler()],
30
+ * });
31
+ * ```
32
+ */
33
+ const intlayerCompiler = (options) => {
34
+ let config;
35
+ let logger;
36
+ let projectRoot = "";
37
+ let filesList = [];
38
+ let babel = null;
39
+ let pendingDictionaryWrite = null;
40
+ const configOptions = options?.configOptions;
41
+ const customCompilerConfig = options?.compilerConfig;
42
+ /**
43
+ * Get compiler config from intlayer config or custom options
44
+ */
45
+ const getCompilerConfig = () => {
46
+ const rawConfig = config;
47
+ return {
48
+ enabled: customCompilerConfig?.enabled ?? rawConfig.compiler?.enabled ?? true,
49
+ transformPattern: customCompilerConfig?.transformPattern ?? rawConfig.compiler?.transformPattern ?? config.build.traversePattern,
50
+ excludePattern: customCompilerConfig?.excludePattern ?? rawConfig.compiler?.excludePattern ?? ["**/node_modules/**"],
51
+ outputDir: customCompilerConfig?.outputDir ?? rawConfig.compiler?.outputDir ?? "compiler"
52
+ };
53
+ };
54
+ /**
55
+ * Get the output directory path for compiler dictionaries
56
+ */
57
+ const getOutputDir = () => {
58
+ const { baseDir } = config.content;
59
+ return (0, node_path.join)(baseDir, getCompilerConfig().outputDir);
60
+ };
61
+ /**
62
+ * Get the file path for a dictionary
63
+ */
64
+ const getDictionaryFilePath = (dictionaryKey) => {
65
+ return (0, node_path.join)(getOutputDir(), `${dictionaryKey}.content.json`);
66
+ };
67
+ /**
68
+ * Read an existing dictionary file if it exists
69
+ */
70
+ const readExistingDictionary = async (dictionaryKey) => {
71
+ const filePath = getDictionaryFilePath(dictionaryKey);
72
+ if (!(0, node_fs.existsSync)(filePath)) return null;
73
+ try {
74
+ const content = await (0, node_fs_promises.readFile)(filePath, "utf-8");
75
+ return JSON.parse(content);
76
+ } catch {
77
+ return null;
78
+ }
79
+ };
80
+ /**
81
+ * Merge extracted content with existing dictionary, preserving translations.
82
+ * - Keys in extracted but not in existing: added with default locale only
83
+ * - Keys in both: preserve existing translations, update default locale value
84
+ * - Keys in existing but not in extracted: removed (no longer in source)
85
+ */
86
+ const mergeWithExistingDictionary = (extractedContent, existingDictionary, defaultLocale) => {
87
+ const mergedContent = {};
88
+ const existingContent = existingDictionary?.content;
89
+ for (const [key, value] of Object.entries(extractedContent)) {
90
+ const existingEntry = existingContent?.[key];
91
+ if (existingEntry && existingEntry.nodeType === "translation" && existingEntry.translation) {
92
+ const oldValue = existingEntry.translation[defaultLocale];
93
+ const isUpdated = oldValue !== value;
94
+ mergedContent[key] = {
95
+ nodeType: "translation",
96
+ translation: {
97
+ ...existingEntry.translation,
98
+ [defaultLocale]: value
99
+ }
100
+ };
101
+ if (isUpdated) logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Updated "${key}" [${defaultLocale}]: "${oldValue?.slice(0, 30)}..." → "${value.slice(0, 30)}..."`, {
102
+ level: "info",
103
+ isVerbose: true
104
+ });
105
+ } else {
106
+ mergedContent[key] = {
107
+ nodeType: "translation",
108
+ translation: { [defaultLocale]: value }
109
+ };
110
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Added new key "${key}"`, {
111
+ level: "info",
112
+ isVerbose: true
113
+ });
114
+ }
115
+ }
116
+ if (existingContent) {
117
+ const removedKeys = Object.keys(existingContent).filter((key) => !(key in extractedContent));
118
+ for (const key of removedKeys) logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Removed key "${key}" (no longer in source)`, {
119
+ level: "info",
120
+ isVerbose: true
121
+ });
122
+ }
123
+ return mergedContent;
124
+ };
125
+ /**
126
+ * Build the list of files to transform based on configuration patterns
127
+ */
128
+ const buildFilesList = async () => {
129
+ const { baseDir } = config.content;
130
+ const compilerConfig = getCompilerConfig();
131
+ const patterns = Array.isArray(compilerConfig.transformPattern) ? compilerConfig.transformPattern : [compilerConfig.transformPattern];
132
+ const excludePatterns = Array.isArray(compilerConfig.excludePattern) ? compilerConfig.excludePattern : [compilerConfig.excludePattern];
133
+ filesList = fast_glob.default.sync(patterns, {
134
+ cwd: baseDir,
135
+ ignore: excludePatterns
136
+ }).map((file) => (0, node_path.join)(baseDir, file));
137
+ };
138
+ /**
139
+ * Initialize the compiler with the given mode
140
+ */
141
+ const init = async (_compilerMode) => {
142
+ config = (0, __intlayer_config.getConfiguration)(configOptions);
143
+ logger = (0, __intlayer_config.getAppLogger)(config);
144
+ try {
145
+ babel = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)("@babel/core");
146
+ } catch {
147
+ logger("Failed to load @babel/core. Transformation will be disabled.", { level: "warn" });
148
+ }
149
+ await buildFilesList();
150
+ };
151
+ /**
152
+ * Vite hook: config
153
+ * Called before Vite config is resolved - perfect time to prepare dictionaries
154
+ */
155
+ const configHook = async (_config, env) => {
156
+ config = (0, __intlayer_config.getConfiguration)(configOptions);
157
+ logger = (0, __intlayer_config.getAppLogger)(config);
158
+ const isDevCommand = env.command === "serve" && env.mode === "development";
159
+ const isBuildCommand = env.command === "build";
160
+ if (isDevCommand || isBuildCommand) await (0, __intlayer_chokidar.prepareIntlayer)(config, {
161
+ clean: isBuildCommand,
162
+ cacheTimeoutMs: isBuildCommand ? 1e3 * 30 : 1e3 * 60 * 60
163
+ });
164
+ };
165
+ /**
166
+ * Vite hook: configResolved
167
+ * Called when Vite config is resolved
168
+ */
169
+ const configResolved = async (viteConfig) => {
170
+ const compilerMode = viteConfig.env?.DEV ? "dev" : "build";
171
+ projectRoot = viteConfig.root;
172
+ await init(compilerMode);
173
+ };
174
+ /**
175
+ * Build start hook - no longer needs to prepare dictionaries
176
+ * The compiler is now autonomous and extracts content inline
177
+ */
178
+ const buildStart = async () => {
179
+ logger("Intlayer compiler initialized", { level: "info" });
180
+ };
181
+ /**
182
+ * Build end hook - wait for any pending dictionary writes
183
+ */
184
+ const buildEnd = async () => {
185
+ if (pendingDictionaryWrite) await pendingDictionaryWrite;
186
+ };
187
+ /**
188
+ * Configure the dev server
189
+ */
190
+ const configureServer = async () => {};
191
+ /**
192
+ * Vite hook: handleHotUpdate
193
+ * Handles HMR for content files - invalidates cache and triggers re-transform
194
+ */
195
+ const handleHotUpdate = async (ctx) => {
196
+ const { file, server, modules } = ctx;
197
+ if (filesList.some((f) => f === file)) {
198
+ for (const mod of modules) server.moduleGraph.invalidateModule(mod);
199
+ try {
200
+ await transformHandler(await (0, node_fs_promises.readFile)(file, "utf-8"), file);
201
+ } catch (error) {
202
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Failed to re-transform ${file}: ${error}`, { level: "error" });
203
+ }
204
+ server.ws.send({ type: "full-reload" });
205
+ return [];
206
+ }
207
+ };
208
+ /**
209
+ * Write and build a single dictionary immediately
210
+ * This is called during transform to ensure dictionaries are always up-to-date.
211
+ *
212
+ * The merge strategy:
213
+ * - New keys are added with the default locale only
214
+ * - Existing keys preserve their translations, with default locale updated
215
+ * - Keys no longer in source are removed
216
+ */
217
+ const writeAndBuildDictionary = async (result) => {
218
+ const { dictionaryKey, content, locale } = result;
219
+ const outputDir = getOutputDir();
220
+ await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
221
+ const existingDictionary = await readExistingDictionary(dictionaryKey);
222
+ const mergedContent = mergeWithExistingDictionary(content, existingDictionary, locale);
223
+ const mergedDictionary = {
224
+ ...existingDictionary && {
225
+ $schema: existingDictionary.$schema,
226
+ id: existingDictionary.id,
227
+ title: existingDictionary.title,
228
+ description: existingDictionary.description,
229
+ tags: existingDictionary.tags,
230
+ fill: existingDictionary.fill,
231
+ filled: existingDictionary.filled,
232
+ priority: existingDictionary.priority,
233
+ version: existingDictionary.version
234
+ },
235
+ key: dictionaryKey,
236
+ content: mergedContent,
237
+ filePath: (0, node_path.join)((0, node_path.relative)(config.content.baseDir, outputDir), `${dictionaryKey}.content.json`)
238
+ };
239
+ try {
240
+ const writeResult = await (0, __intlayer_chokidar.writeContentDeclaration)(mergedDictionary, config, { newDictionariesPath: (0, node_path.relative)(config.content.baseDir, outputDir) });
241
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} ${writeResult.status === "created" ? "Created" : writeResult.status === "updated" ? "Updated" : "Processed"} content declaration: ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, writeResult.path))}`, { level: "info" });
242
+ const dictionaryToBuild = {
243
+ ...mergedDictionary,
244
+ filePath: (0, node_path.relative)(config.content.baseDir, writeResult.path)
245
+ };
246
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Building dictionary ${(0, __intlayer_config.colorizeKey)(dictionaryKey)}`, { level: "info" });
247
+ await (0, __intlayer_chokidar.buildDictionary)([dictionaryToBuild], config);
248
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Dictionary ${(0, __intlayer_config.colorizeKey)(dictionaryKey)} built successfully`, { level: "info" });
249
+ } catch (error) {
250
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Failed to write/build dictionary for ${(0, __intlayer_config.colorizeKey)(dictionaryKey)}: ${error}`, { level: "error" });
251
+ }
252
+ };
253
+ /**
254
+ * Callback for when content is extracted from a file
255
+ * Immediately writes and builds the dictionary
256
+ */
257
+ const handleExtractedContent = (result) => {
258
+ const contentKeys = Object.keys(result.content);
259
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Extracted ${contentKeys.length} content keys from ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, result.filePath))}`, { level: "info" });
260
+ pendingDictionaryWrite = (pendingDictionaryWrite ?? Promise.resolve()).then(() => writeAndBuildDictionary(result)).catch((error) => {
261
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Error in dictionary write chain: ${error}`, { level: "error" });
262
+ });
263
+ };
264
+ /**
265
+ * Detect the package name to import useIntlayer from based on file extension
266
+ */
267
+ const detectPackageName = (filename) => {
268
+ if (filename.endsWith(".vue")) return "vue-intlayer";
269
+ if (filename.endsWith(".svelte")) return "svelte-intlayer";
270
+ if (filename.endsWith(".tsx") || filename.endsWith(".jsx")) return "react-intlayer";
271
+ return "intlayer";
272
+ };
273
+ /**
274
+ * Transform a Vue file using the Vue extraction plugin
275
+ */
276
+ const transformVue = async (code, filename, defaultLocale) => {
277
+ const { intlayerVueExtract } = await import("@intlayer/vue-compiler");
278
+ return intlayerVueExtract(code, filename, {
279
+ defaultLocale,
280
+ filesList,
281
+ packageName: "vue-intlayer",
282
+ onExtract: handleExtractedContent
283
+ });
284
+ };
285
+ /**
286
+ * Transform a Svelte file using the Svelte extraction plugin
287
+ */
288
+ const transformSvelte = async (code, filename, defaultLocale) => {
289
+ const { intlayerSvelteExtract } = await import("@intlayer/svelte-compiler");
290
+ return await intlayerSvelteExtract(code, filename, {
291
+ defaultLocale,
292
+ filesList,
293
+ packageName: "svelte-intlayer",
294
+ onExtract: handleExtractedContent
295
+ });
296
+ };
297
+ /**
298
+ * Transform a JSX/TSX file using the Babel extraction plugin
299
+ */
300
+ const transformJsx = (code, filename, defaultLocale) => {
301
+ if (!babel) return;
302
+ const packageName = detectPackageName(filename);
303
+ const result = babel.transformSync(code, {
304
+ filename,
305
+ plugins: [[__intlayer_babel.intlayerExtractBabelPlugin, {
306
+ defaultLocale,
307
+ filesList,
308
+ packageName,
309
+ onExtract: handleExtractedContent
310
+ }]],
311
+ parserOpts: {
312
+ sourceType: "module",
313
+ allowImportExportEverywhere: true,
314
+ plugins: [
315
+ "typescript",
316
+ "jsx",
317
+ "decorators-legacy",
318
+ "classProperties",
319
+ "objectRestSpread",
320
+ "asyncGenerators",
321
+ "functionBind",
322
+ "exportDefaultFrom",
323
+ "exportNamespaceFrom",
324
+ "dynamicImport",
325
+ "nullishCoalescingOperator",
326
+ "optionalChaining"
327
+ ]
328
+ }
329
+ });
330
+ if (result?.code) return {
331
+ code: result.code,
332
+ map: result.map,
333
+ extracted: true
334
+ };
335
+ };
336
+ /**
337
+ * Transform a file using the appropriate extraction plugin based on file type
338
+ */
339
+ const transformHandler = async (code, id, _options) => {
340
+ if (!getCompilerConfig().enabled) return;
341
+ if (id.includes("?")) return;
342
+ const { defaultLocale } = config.internationalization;
343
+ const filename = id;
344
+ if (!filesList.includes(filename)) return;
345
+ const isVue = filename.endsWith(".vue");
346
+ const isSvelte = filename.endsWith(".svelte");
347
+ if (!isVue && !isSvelte) {
348
+ try {
349
+ const result = transformJsx(code, filename, defaultLocale);
350
+ if (pendingDictionaryWrite) await pendingDictionaryWrite;
351
+ if (result?.code) return {
352
+ code: result.code,
353
+ map: result.map
354
+ };
355
+ } catch (error) {
356
+ logger(`Failed to transform ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, filename))}: ${error}`, { level: "error" });
357
+ }
358
+ return;
359
+ }
360
+ logger(`${(0, __intlayer_config.colorize)("Compiler:", __intlayer_config.ANSIColors.GREY_DARK)} Transforming ${(0, __intlayer_config.colorizePath)((0, node_path.relative)(projectRoot, filename))}`, { level: "info" });
361
+ try {
362
+ let result;
363
+ if (isVue) result = await transformVue(code, filename, defaultLocale);
364
+ else if (isSvelte) result = await transformSvelte(code, filename, defaultLocale);
365
+ if (pendingDictionaryWrite) await pendingDictionaryWrite;
366
+ if (result?.code) return {
367
+ code: result.code,
368
+ map: result.map
369
+ };
370
+ } catch (error) {
371
+ logger(`Failed to transform ${(0, node_path.relative)(projectRoot, filename)}: ${error}`, { level: "error" });
372
+ }
373
+ };
374
+ /**
375
+ * Apply hook for determining when plugin should be active
376
+ */
377
+ const apply = (_config, _env) => {
378
+ return getCompilerConfig().enabled;
379
+ };
380
+ return {
381
+ name: "vite-intlayer-compiler",
382
+ enforce: "pre",
383
+ config: configHook,
384
+ configResolved,
385
+ buildStart,
386
+ buildEnd,
387
+ configureServer,
388
+ handleHotUpdate,
389
+ transform: transformHandler,
390
+ apply: (_viteConfig, env) => {
391
+ if (!config) config = (0, __intlayer_config.getConfiguration)(configOptions);
392
+ return apply(_viteConfig, env);
393
+ }
394
+ };
395
+ };
396
+
397
+ //#endregion
398
+ exports.intlayerCompiler = intlayerCompiler;
399
+ //# sourceMappingURL=IntlayerCompilerPlugin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntlayerCompilerPlugin.cjs","names":["config: IntlayerConfig","logger: ReturnType<typeof getAppLogger>","filesList: string[]","babel: any","pendingDictionaryWrite: Promise<void> | null","mergedContent: DictionaryContentMap","ANSIColors","fg","compilerMode: CompilerMode","mergedDictionary: Dictionary","dictionaryToBuild: Dictionary","intlayerExtractBabelPlugin","result:\n | { code: string; map?: unknown; extracted?: boolean }\n | null\n | undefined"],"sources":["../../src/IntlayerCompilerPlugin.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join, relative } from 'node:path';\nimport {\n type ExtractResult,\n intlayerExtractBabelPlugin,\n} from '@intlayer/babel';\nimport {\n buildDictionary,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n colorizePath,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type {\n CompilerConfig,\n Dictionary,\n IntlayerConfig,\n} from '@intlayer/types';\nimport fg from 'fast-glob';\n\n/**\n * Translation node structure used in dictionaries\n */\ntype TranslationNode = {\n nodeType: 'translation';\n translation: Record<string, string>;\n};\n\n/**\n * Dictionary content structure - map of keys to translation nodes\n */\ntype DictionaryContentMap = Record<string, TranslationNode>;\n\n/**\n * Mode of the compiler\n * - 'dev': Development mode with HMR support\n * - 'build': Production build mode\n */\nexport type CompilerMode = 'dev' | 'build';\n\n/**\n * Options for initializing the compiler\n */\nexport type IntlayerCompilerOptions = {\n /**\n * Configuration options for getting the intlayer configuration\n */\n configOptions?: GetConfigurationOptions;\n\n /**\n * Custom compiler configuration to override defaults\n */\n compilerConfig?: Partial<CompilerConfig>;\n};\n\n/**\n * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer\n *\n * This autonomous compiler handles:\n * - Configuration loading and management\n * - Hot Module Replacement (HMR) for content changes\n * - File transformation with content extraction\n * - Dictionary persistence and building\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import { intlayerCompiler } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayerCompiler()],\n * });\n * ```\n */\nexport const intlayerCompiler = (options?: IntlayerCompilerOptions): any => {\n // Private state\n let config: IntlayerConfig;\n let logger: ReturnType<typeof getAppLogger>;\n let projectRoot = '';\n let filesList: string[] = [];\n let babel: any = null;\n\n // Promise to track dictionary writing (for synchronization)\n let pendingDictionaryWrite: Promise<void> | null = null;\n\n const configOptions = options?.configOptions;\n const customCompilerConfig = options?.compilerConfig;\n\n /**\n * Get compiler config from intlayer config or custom options\n */\n const getCompilerConfig = () => {\n // Access compiler config from the raw config (may not be in the type)\n const rawConfig = config as IntlayerConfig & {\n compiler?: Partial<CompilerConfig>;\n };\n\n return {\n enabled:\n customCompilerConfig?.enabled ?? rawConfig.compiler?.enabled ?? true,\n transformPattern:\n customCompilerConfig?.transformPattern ??\n rawConfig.compiler?.transformPattern ??\n config.build.traversePattern,\n excludePattern: customCompilerConfig?.excludePattern ??\n rawConfig.compiler?.excludePattern ?? ['**/node_modules/**'],\n outputDir:\n customCompilerConfig?.outputDir ??\n rawConfig.compiler?.outputDir ??\n 'compiler',\n };\n };\n\n /**\n * Get the output directory path for compiler dictionaries\n */\n const getOutputDir = (): string => {\n const { baseDir } = config.content;\n const compilerConfig = getCompilerConfig();\n return join(baseDir, compilerConfig.outputDir);\n };\n\n /**\n * Get the file path for a dictionary\n */\n const getDictionaryFilePath = (dictionaryKey: string): string => {\n const outputDir = getOutputDir();\n return join(outputDir, `${dictionaryKey}.content.json`);\n };\n\n /**\n * Read an existing dictionary file if it exists\n */\n const readExistingDictionary = async (\n dictionaryKey: string\n ): Promise<Dictionary | null> => {\n const filePath = getDictionaryFilePath(dictionaryKey);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as Dictionary;\n } catch {\n return null;\n }\n };\n\n /**\n * Merge extracted content with existing dictionary, preserving translations.\n * - Keys in extracted but not in existing: added with default locale only\n * - Keys in both: preserve existing translations, update default locale value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\n const mergeWithExistingDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n ): DictionaryContentMap => {\n const mergedContent: DictionaryContentMap = {};\n const existingContent = existingDictionary?.content as\n | DictionaryContentMap\n | undefined;\n\n for (const [key, value] of Object.entries(extractedContent)) {\n const existingEntry = existingContent?.[key];\n\n if (\n existingEntry &&\n existingEntry.nodeType === 'translation' &&\n existingEntry.translation\n ) {\n const oldValue = existingEntry.translation[defaultLocale];\n const isUpdated = oldValue !== value;\n\n // Key exists in both - preserve existing translations, update default locale\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n ...existingEntry.translation,\n [defaultLocale]: value,\n },\n };\n\n if (isUpdated) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Updated \"${key}\" [${defaultLocale}]: \"${oldValue?.slice(0, 30)}...\" → \"${value.slice(0, 30)}...\"`,\n { level: 'info', isVerbose: true }\n );\n }\n } else {\n // New key - add with default locale only\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n [defaultLocale]: value,\n },\n };\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Added new key \"${key}\"`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n // Log removed keys\n if (existingContent) {\n const removedKeys = Object.keys(existingContent).filter(\n (key) => !(key in extractedContent)\n );\n for (const key of removedKeys) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Removed key \"${key}\" (no longer in source)`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n return mergedContent;\n };\n\n /**\n * Build the list of files to transform based on configuration patterns\n */\n const buildFilesList = async (): Promise<void> => {\n const { baseDir } = config.content;\n const compilerConfig = getCompilerConfig();\n\n const patterns = Array.isArray(compilerConfig.transformPattern)\n ? compilerConfig.transformPattern\n : [compilerConfig.transformPattern];\n const excludePatterns = Array.isArray(compilerConfig.excludePattern)\n ? compilerConfig.excludePattern\n : [compilerConfig.excludePattern];\n\n filesList = fg\n .sync(patterns, {\n cwd: baseDir,\n ignore: excludePatterns,\n })\n .map((file) => join(baseDir, file));\n };\n\n /**\n * Initialize the compiler with the given mode\n */\n const init = async (_compilerMode: CompilerMode): Promise<void> => {\n config = getConfiguration(configOptions);\n logger = getAppLogger(config);\n\n // Load Babel dynamically\n try {\n const localRequire = createRequire(import.meta.url);\n babel = localRequire('@babel/core');\n } catch {\n logger('Failed to load @babel/core. Transformation will be disabled.', {\n level: 'warn',\n });\n }\n\n // Build files list for transformation\n await buildFilesList();\n };\n\n /**\n * Vite hook: config\n * Called before Vite config is resolved - perfect time to prepare dictionaries\n */\n const configHook = async (\n _config: unknown,\n env: { command: string; mode: string }\n ): Promise<void> => {\n // Initialize config early\n config = getConfiguration(configOptions);\n logger = getAppLogger(config);\n\n const isDevCommand = env.command === 'serve' && env.mode === 'development';\n const isBuildCommand = env.command === 'build';\n\n // Prepare all existing dictionaries (builds them to .intlayer/dictionary/)\n // This ensures built dictionaries exist before the prune plugin runs\n if (isDevCommand || isBuildCommand) {\n await prepareIntlayer(config, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build\n : 1000 * 60 * 60, // 1 hour for dev\n });\n }\n };\n\n /**\n * Vite hook: configResolved\n * Called when Vite config is resolved\n */\n const configResolved = async (viteConfig: {\n env?: { DEV?: boolean };\n root: string;\n }): Promise<void> => {\n const compilerMode: CompilerMode = viteConfig.env?.DEV ? 'dev' : 'build';\n projectRoot = viteConfig.root;\n await init(compilerMode);\n };\n\n /**\n * Build start hook - no longer needs to prepare dictionaries\n * The compiler is now autonomous and extracts content inline\n */\n const buildStart = async (): Promise<void> => {\n // Autonomous compiler - no need to prepare dictionaries\n // Content is extracted inline during transformation\n logger('Intlayer compiler initialized', {\n level: 'info',\n });\n };\n\n /**\n * Build end hook - wait for any pending dictionary writes\n */\n const buildEnd = async (): Promise<void> => {\n // Wait for any pending dictionary writes to complete\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n };\n\n /**\n * Configure the dev server\n */\n const configureServer = async (): Promise<void> => {\n // In autonomous mode, we don't need file watching for dictionaries\n // Content is extracted inline during transformation\n };\n\n /**\n * Vite hook: handleHotUpdate\n * Handles HMR for content files - invalidates cache and triggers re-transform\n */\n const handleHotUpdate = async (ctx: any): Promise<unknown[] | undefined> => {\n const { file, server, modules } = ctx;\n\n // Check if this is a file we should transform\n const isTransformableFile = filesList.some((f) => f === file);\n\n if (isTransformableFile) {\n // Invalidate all affected modules to ensure re-transform\n for (const mod of modules) {\n server.moduleGraph.invalidateModule(mod);\n }\n\n // Force re-transform by reading and processing the file\n // This ensures content extraction happens on every file change\n try {\n const code = await readFile(file, 'utf-8');\n\n // Trigger the transform manually to extract content\n await transformHandler(code, file);\n } catch (error) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to re-transform ${file}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n\n // Trigger full reload for content changes\n server.ws.send({ type: 'full-reload' });\n return [];\n }\n\n return undefined;\n };\n\n /**\n * Write and build a single dictionary immediately\n * This is called during transform to ensure dictionaries are always up-to-date.\n *\n * The merge strategy:\n * - New keys are added with the default locale only\n * - Existing keys preserve their translations, with default locale updated\n * - Keys no longer in source are removed\n */\n const writeAndBuildDictionary = async (\n result: ExtractResult\n ): Promise<void> => {\n const { dictionaryKey, content, locale } = result;\n\n const outputDir = getOutputDir();\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Read existing dictionary to preserve translations and metadata\n const existingDictionary = await readExistingDictionary(dictionaryKey);\n\n // Merge extracted content with existing translations\n const mergedContent = mergeWithExistingDictionary(\n content,\n existingDictionary,\n locale\n );\n\n // Create the merged dictionary, preserving existing metadata\n const mergedDictionary: Dictionary = {\n // Preserve existing metadata (title, description, tags, etc.)\n ...(existingDictionary && {\n $schema: existingDictionary.$schema,\n id: existingDictionary.id,\n title: existingDictionary.title,\n description: existingDictionary.description,\n tags: existingDictionary.tags,\n fill: existingDictionary.fill,\n filled: existingDictionary.filled,\n priority: existingDictionary.priority,\n version: existingDictionary.version,\n }),\n // Required fields\n key: dictionaryKey,\n content: mergedContent,\n filePath: join(\n relative(config.content.baseDir, outputDir),\n `${dictionaryKey}.content.json`\n ),\n };\n\n try {\n const writeResult = await writeContentDeclaration(\n mergedDictionary,\n config,\n {\n newDictionariesPath: relative(config.content.baseDir, outputDir),\n }\n );\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} ${writeResult.status === 'created' ? 'Created' : writeResult.status === 'updated' ? 'Updated' : 'Processed'} content declaration: ${colorizePath(relative(projectRoot, writeResult.path))}`,\n {\n level: 'info',\n }\n );\n\n // Build the dictionary immediately so it's available for the prune plugin\n const dictionaryToBuild: Dictionary = {\n ...mergedDictionary,\n filePath: relative(config.content.baseDir, writeResult.path),\n };\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Building dictionary ${colorizeKey(dictionaryKey)}`,\n {\n level: 'info',\n }\n );\n\n await buildDictionary([dictionaryToBuild], config);\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Dictionary ${colorizeKey(dictionaryKey)} built successfully`,\n {\n level: 'info',\n }\n );\n } catch (error) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to write/build dictionary for ${colorizeKey(dictionaryKey)}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n };\n\n /**\n * Callback for when content is extracted from a file\n * Immediately writes and builds the dictionary\n */\n const handleExtractedContent = (result: ExtractResult): void => {\n const contentKeys = Object.keys(result.content);\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted ${contentKeys.length} content keys from ${colorizePath(relative(projectRoot, result.filePath))}`,\n {\n level: 'info',\n }\n );\n\n // Chain the write operation to ensure sequential writes\n pendingDictionaryWrite = (pendingDictionaryWrite ?? Promise.resolve())\n .then(() => writeAndBuildDictionary(result))\n .catch((error) => {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Error in dictionary write chain: ${error}`,\n {\n level: 'error',\n }\n );\n });\n };\n\n /**\n * Detect the package name to import useIntlayer from based on file extension\n */\n const detectPackageName = (filename: string): string => {\n if (filename.endsWith('.vue')) {\n return 'vue-intlayer';\n }\n if (filename.endsWith('.svelte')) {\n return 'svelte-intlayer';\n }\n if (filename.endsWith('.tsx') || filename.endsWith('.jsx')) {\n return 'react-intlayer';\n }\n // Default to react-intlayer for JSX/TSX files\n return 'intlayer';\n };\n\n /**\n * Transform a Vue file using the Vue extraction plugin\n */\n const transformVue = async (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n const { intlayerVueExtract } = await import('@intlayer/vue-compiler');\n return intlayerVueExtract(code, filename, {\n defaultLocale,\n filesList,\n packageName: 'vue-intlayer',\n onExtract: handleExtractedContent,\n });\n };\n\n /**\n * Transform a Svelte file using the Svelte extraction plugin\n */\n const transformSvelte = async (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n const { intlayerSvelteExtract } = await import('@intlayer/svelte-compiler');\n const result = await intlayerSvelteExtract(code, filename, {\n defaultLocale,\n filesList,\n packageName: 'svelte-intlayer',\n onExtract: handleExtractedContent,\n });\n\n return result;\n };\n\n /**\n * Transform a JSX/TSX file using the Babel extraction plugin\n */\n const transformJsx = (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n if (!babel) {\n return undefined;\n }\n\n const packageName = detectPackageName(filename);\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerExtractBabelPlugin,\n {\n defaultLocale,\n filesList,\n packageName,\n onExtract: handleExtractedContent,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n extracted: true,\n };\n }\n\n return undefined;\n };\n\n /**\n * Transform a file using the appropriate extraction plugin based on file type\n */\n const transformHandler = async (\n code: string,\n id: string,\n _options?: { ssr?: boolean }\n ) => {\n const compilerConfig = getCompilerConfig();\n\n // Only transform if compiler is enabled\n if (!compilerConfig.enabled) {\n return undefined;\n }\n\n // Skip virtual modules (query strings indicate compiled/virtual modules)\n // e.g., App.svelte?svelte&type=style, Component.vue?vue&type=script\n if (id.includes('?')) {\n return undefined;\n }\n\n const { defaultLocale } = config.internationalization;\n\n const filename = id;\n\n if (!filesList.includes(filename)) {\n return undefined;\n }\n\n // Only process Vue and Svelte source files with extraction\n // JSX/TSX files are handled by Babel which has its own detection\n const isVue = filename.endsWith('.vue');\n const isSvelte = filename.endsWith('.svelte');\n\n if (!isVue && !isSvelte) {\n // For non-Vue/Svelte files, use JSX transformation via Babel\n try {\n const result = transformJsx(code, filename, defaultLocale);\n\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n } catch (error) {\n logger(\n `Failed to transform ${colorizePath(relative(projectRoot, filename))}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n return undefined;\n }\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Transforming ${colorizePath(relative(projectRoot, filename))}`,\n {\n level: 'info',\n }\n );\n\n try {\n let result:\n | { code: string; map?: unknown; extracted?: boolean }\n | null\n | undefined;\n\n // Route to appropriate transformer based on file extension\n if (isVue) {\n result = await transformVue(code, filename, defaultLocale);\n } else if (isSvelte) {\n result = await transformSvelte(code, filename, defaultLocale);\n }\n\n // Wait for the dictionary to be written before returning\n // This ensures the dictionary exists before the prune plugin runs\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n } catch (error) {\n logger(\n `Failed to transform ${relative(projectRoot, filename)}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n\n return undefined;\n };\n\n /**\n * Apply hook for determining when plugin should be active\n */\n const apply = (_config: unknown, _env: { command: string }): boolean => {\n const compilerConfig = getCompilerConfig();\n // Apply if compiler is enabled\n return compilerConfig.enabled;\n };\n\n return {\n name: 'vite-intlayer-compiler',\n enforce: 'pre',\n config: configHook,\n configResolved,\n buildStart,\n buildEnd,\n configureServer,\n handleHotUpdate,\n transform: transformHandler,\n apply: (_viteConfig: unknown, env: { command: string }) => {\n // Initialize config if not already done\n if (!config) {\n config = getConfiguration(configOptions);\n }\n return apply(_viteConfig, env);\n },\n };\n};\n"],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ const require_IntlayerCompilerPlugin = require('./IntlayerCompilerPlugin.cjs');
1
2
  const require_intlayerPrunePlugin = require('./intlayerPrunePlugin.cjs');
2
3
  const require_intlayerPlugin = require('./intlayerPlugin.cjs');
3
4
  const require_intlayerProxyPlugin = require('./intlayerProxyPlugin.cjs');
@@ -5,6 +6,7 @@ const require_intlayerProxyPlugin = require('./intlayerProxyPlugin.cjs');
5
6
  exports.intLayerMiddlewarePlugin = require_intlayerProxyPlugin.intLayerMiddlewarePlugin;
6
7
  exports.intLayerPlugin = require_intlayerPlugin.intLayerPlugin;
7
8
  exports.intlayer = require_intlayerPlugin.intlayer;
9
+ exports.intlayerCompiler = require_IntlayerCompilerPlugin.intlayerCompiler;
8
10
  exports.intlayerMiddleware = require_intlayerProxyPlugin.intlayerMiddleware;
9
11
  exports.intlayerPlugin = require_intlayerPlugin.intlayerPlugin;
10
12
  exports.intlayerProxy = require_intlayerProxyPlugin.intlayerProxy;
@@ -1,12 +1,12 @@
1
1
  const require_rolldown_runtime = require('./_virtual/rolldown_runtime.cjs');
2
+ let node_module = require("node:module");
2
3
  let node_path = require("node:path");
4
+ let __intlayer_babel = require("@intlayer/babel");
3
5
  let __intlayer_chokidar = require("@intlayer/chokidar");
4
6
  let __intlayer_config = require("@intlayer/config");
5
- let node_module = require("node:module");
6
- let __intlayer_babel = require("@intlayer/babel");
7
- let __intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
8
7
  let fast_glob = require("fast-glob");
9
8
  fast_glob = require_rolldown_runtime.__toESM(fast_glob);
9
+ let __intlayer_dictionaries_entry = require("@intlayer/dictionaries-entry");
10
10
 
11
11
  //#region src/intlayerPrunePlugin.ts
12
12
  const intlayerPrune = (intlayerConfig) => {
@@ -24,7 +24,7 @@ const intlayerPrune = (intlayerConfig) => {
24
24
  dictionariesEntryPath,
25
25
  unmergedDictionariesEntryPath
26
26
  ];
27
- const dictionaries = (0, __intlayer_dictionaries_entry.getDictionaries)();
27
+ const dictionaries = (0, __intlayer_dictionaries_entry.getDictionaries)(intlayerConfig);
28
28
  const liveSyncKeys = Object.values(dictionaries).filter((dictionary) => dictionary.live).map((dictionary) => dictionary.key);
29
29
  return {
30
30
  name: "vite-intlayer-babel-transform",
@@ -48,7 +48,8 @@ const intlayerPrune = (intlayerConfig) => {
48
48
  if (!filesList.includes(filename)) return null;
49
49
  const result = babel.transformSync(code, {
50
50
  filename,
51
- plugins: [[__intlayer_babel.intlayerBabelPlugin, {
51
+ plugins: [[__intlayer_babel.intlayerOptimizeBabelPlugin, {
52
+ optimize,
52
53
  dictionariesDir,
53
54
  dictionariesEntryPath,
54
55
  unmergedDictionariesEntryPath,
@@ -1 +1 @@
1
- {"version":3,"file":"intlayerPrunePlugin.cjs","names":["fg","intlayerBabelPlugin"],"sources":["../../src/intlayerPrunePlugin.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { intlayerBabelPlugin } from '@intlayer/babel';\nimport { runOnce } from '@intlayer/chokidar';\nimport { getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport type { PluginOption } from 'vite';\n\nexport const intlayerPrune = (intlayerConfig: IntlayerConfig): PluginOption => {\n try {\n const localeRequire = createRequire(import.meta.url);\n const babel = localeRequire('@babel/core');\n const logger = getAppLogger(intlayerConfig);\n\n const { importMode, traversePattern, optimize } = intlayerConfig.build;\n\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n unmergedDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n baseDir,\n } = intlayerConfig.content;\n\n const filesListPattern = fg\n .sync(traversePattern, {\n cwd: baseDir,\n })\n .map((file) => join(baseDir, file));\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries();\n const liveSyncKeys = Object.values(dictionaries)\n .filter((dictionary) => dictionary.live)\n .map((dictionary) => dictionary.key);\n\n return {\n name: 'vite-intlayer-babel-transform',\n enforce: 'post', // Run after other transformations as vue\n apply: (_config, env) => {\n // Only apply babel plugin if optimize is enabled\n\n const isBuild = env.command === 'build';\n const isEnabled = (optimize ?? true) && isBuild;\n\n if (isEnabled) {\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-prune-plugin-enabled.lock'\n ),\n () => logger('Build optimization enabled'),\n {\n cacheTimeoutMs: 1000 * 10, // 10 seconds\n }\n );\n }\n\n return isEnabled;\n },\n transform(code, id) {\n /**\n * Transform file as\n * .../HelloWorld.vue?vue&type=script&setup=true&lang.ts\n * Into\n * .../HelloWorld.vue\n *\n * Prevention for virtual file\n */\n const filename = id.split('?', 1)[0];\n\n if (!filesList.includes(filename)) return null;\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerBabelPlugin,\n {\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n liveSyncKeys,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n },\n };\n } catch (error) {\n console.warn('Failed to transform with Babel plugin:', error);\n\n return null;\n }\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,iBAAiB,mBAAiD;AAC7E,KAAI;EAEF,MAAM,qFAD8C,CACxB,cAAc;EAC1C,MAAM,6CAAsB,eAAe;EAE3C,MAAM,EAAE,YAAY,iBAAiB,aAAa,eAAe;EAEjE,MAAM,EACJ,iBACA,wBACA,yBACA,sBACA,SACA,YACE,eAAe;EAEnB,MAAM,mBAAmBA,kBACtB,KAAK,iBAAiB,EACrB,KAAK,SACN,CAAC,CACD,KAAK,6BAAc,SAAS,KAAK,CAAC;EAErC,MAAM,4CAA6B,SAAS,mBAAmB;EAC/D,MAAM,oDACJ,SACA,4BACD;EACD,MAAM,mDACJ,SACA,2BACD;EAED,MAAM,YAAY;GAChB,GAAG;GACH;GACA;GACD;EAED,MAAM,mEAAgC;EACtC,MAAM,eAAe,OAAO,OAAO,aAAa,CAC7C,QAAQ,eAAe,WAAW,KAAK,CACvC,KAAK,eAAe,WAAW,IAAI;AAEtC,SAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ,SAAS,QAAQ;IAGvB,MAAM,UAAU,IAAI,YAAY;IAChC,MAAM,aAAa,YAAY,SAAS;AAExC,QAAI,UACF,sDAEI,SACA,aACA,SACA,qCACD,QACK,OAAO,6BAA6B,EAC1C,EACE,gBAAgB,MAAO,IACxB,CACF;AAGH,WAAO;;GAET,UAAU,MAAM,IAAI;;;;;;;;;IASlB,MAAM,WAAW,GAAG,MAAM,KAAK,EAAE,CAAC;AAElC,QAAI,CAAC,UAAU,SAAS,SAAS,CAAE,QAAO;IAE1C,MAAM,SAAS,MAAM,cAAc,MAAM;KACvC;KACA,SAAS,CACP,CACEC,sCACA;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,wBAAwB;MACxB;MACD,CACF,CACF;KACD,YAAY;MACV,YAAY;MACZ,6BAA6B;MAC7B,SAAS;OACP;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACD;MACF;KACF,CAAC;AAEF,QAAI,QAAQ,KACV,QAAO;KACL,MAAM,OAAO;KACb,KAAK,OAAO;KACb;;GAGN;UACM,OAAO;AACd,UAAQ,KAAK,0CAA0C,MAAM;AAE7D,SAAO"}
1
+ {"version":3,"file":"intlayerPrunePlugin.cjs","names":["fg","intlayerOptimizeBabelPlugin"],"sources":["../../src/intlayerPrunePlugin.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { intlayerOptimizeBabelPlugin } from '@intlayer/babel';\nimport { runOnce } from '@intlayer/chokidar';\nimport { getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport type { PluginOption } from 'vite';\n\nexport const intlayerPrune = (intlayerConfig: IntlayerConfig): PluginOption => {\n try {\n const localeRequire = createRequire(import.meta.url);\n const babel = localeRequire('@babel/core');\n const logger = getAppLogger(intlayerConfig);\n\n const { importMode, traversePattern, optimize } = intlayerConfig.build;\n\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n unmergedDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n baseDir,\n } = intlayerConfig.content;\n\n const filesListPattern = fg\n .sync(traversePattern, {\n cwd: baseDir,\n })\n .map((file) => join(baseDir, file));\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries(intlayerConfig);\n const liveSyncKeys = Object.values(dictionaries)\n .filter((dictionary) => dictionary.live)\n .map((dictionary) => dictionary.key);\n\n return {\n name: 'vite-intlayer-babel-transform',\n enforce: 'post', // Run after other transformations as vue\n apply: (_config, env) => {\n // Only apply babel plugin if optimize is enabled\n\n const isBuild = env.command === 'build';\n const isEnabled = (optimize ?? true) && isBuild;\n\n if (isEnabled) {\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-prune-plugin-enabled.lock'\n ),\n () => logger('Build optimization enabled'),\n {\n cacheTimeoutMs: 1000 * 10, // 10 seconds\n }\n );\n }\n\n return isEnabled;\n },\n transform(code, id) {\n /**\n * Transform file as\n * .../HelloWorld.vue?vue&type=script&setup=true&lang.ts\n * Into\n * .../HelloWorld.vue\n *\n * Prevention for virtual file\n */\n const filename = id.split('?', 1)[0];\n\n if (!filesList.includes(filename)) return null;\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerOptimizeBabelPlugin,\n {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n liveSyncKeys,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n },\n };\n } catch (error) {\n console.warn('Failed to transform with Babel plugin:', error);\n\n return null;\n }\n};\n"],"mappings":";;;;;;;;;;;AAUA,MAAa,iBAAiB,mBAAiD;AAC7E,KAAI;EAEF,MAAM,qFAD8C,CACxB,cAAc;EAC1C,MAAM,6CAAsB,eAAe;EAE3C,MAAM,EAAE,YAAY,iBAAiB,aAAa,eAAe;EAEjE,MAAM,EACJ,iBACA,wBACA,yBACA,sBACA,SACA,YACE,eAAe;EAEnB,MAAM,mBAAmBA,kBACtB,KAAK,iBAAiB,EACrB,KAAK,SACN,CAAC,CACD,KAAK,6BAAc,SAAS,KAAK,CAAC;EAErC,MAAM,4CAA6B,SAAS,mBAAmB;EAC/D,MAAM,oDACJ,SACA,4BACD;EACD,MAAM,mDACJ,SACA,2BACD;EAED,MAAM,YAAY;GAChB,GAAG;GACH;GACA;GACD;EAED,MAAM,kEAA+B,eAAe;EACpD,MAAM,eAAe,OAAO,OAAO,aAAa,CAC7C,QAAQ,eAAe,WAAW,KAAK,CACvC,KAAK,eAAe,WAAW,IAAI;AAEtC,SAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ,SAAS,QAAQ;IAGvB,MAAM,UAAU,IAAI,YAAY;IAChC,MAAM,aAAa,YAAY,SAAS;AAExC,QAAI,UACF,sDAEI,SACA,aACA,SACA,qCACD,QACK,OAAO,6BAA6B,EAC1C,EACE,gBAAgB,MAAO,IACxB,CACF;AAGH,WAAO;;GAET,UAAU,MAAM,IAAI;;;;;;;;;IASlB,MAAM,WAAW,GAAG,MAAM,KAAK,EAAE,CAAC;AAElC,QAAI,CAAC,UAAU,SAAS,SAAS,CAAE,QAAO;IAE1C,MAAM,SAAS,MAAM,cAAc,MAAM;KACvC;KACA,SAAS,CACP,CACEC,8CACA;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,wBAAwB;MACxB;MACD,CACF,CACF;KACD,YAAY;MACV,YAAY;MACZ,6BAA6B;MAC7B,SAAS;OACP;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACD;MACF;KACF,CAAC;AAEF,QAAI,QAAQ,KACV,QAAO;KACL,MAAM,OAAO;KACb,KAAK,OAAO;KACb;;GAGN;UACM,OAAO;AACd,UAAQ,KAAK,0CAA0C,MAAM;AAE7D,SAAO"}
@@ -0,0 +1,397 @@
1
+ import { existsSync } from "node:fs";
2
+ import { mkdir, readFile } from "node:fs/promises";
3
+ import { createRequire } from "node:module";
4
+ import { join, relative } from "node:path";
5
+ import { intlayerExtractBabelPlugin } from "@intlayer/babel";
6
+ import { buildDictionary, prepareIntlayer, writeContentDeclaration } from "@intlayer/chokidar";
7
+ import { ANSIColors, colorize, colorizeKey, colorizePath, getAppLogger, getConfiguration } from "@intlayer/config";
8
+ import fg from "fast-glob";
9
+
10
+ //#region src/IntlayerCompilerPlugin.ts
11
+ /**
12
+ * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer
13
+ *
14
+ * This autonomous compiler handles:
15
+ * - Configuration loading and management
16
+ * - Hot Module Replacement (HMR) for content changes
17
+ * - File transformation with content extraction
18
+ * - Dictionary persistence and building
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // vite.config.ts
23
+ * import { defineConfig } from 'vite';
24
+ * import { intlayerCompiler } from 'vite-intlayer';
25
+ *
26
+ * export default defineConfig({
27
+ * plugins: [intlayerCompiler()],
28
+ * });
29
+ * ```
30
+ */
31
+ const intlayerCompiler = (options) => {
32
+ let config;
33
+ let logger;
34
+ let projectRoot = "";
35
+ let filesList = [];
36
+ let babel = null;
37
+ let pendingDictionaryWrite = null;
38
+ const configOptions = options?.configOptions;
39
+ const customCompilerConfig = options?.compilerConfig;
40
+ /**
41
+ * Get compiler config from intlayer config or custom options
42
+ */
43
+ const getCompilerConfig = () => {
44
+ const rawConfig = config;
45
+ return {
46
+ enabled: customCompilerConfig?.enabled ?? rawConfig.compiler?.enabled ?? true,
47
+ transformPattern: customCompilerConfig?.transformPattern ?? rawConfig.compiler?.transformPattern ?? config.build.traversePattern,
48
+ excludePattern: customCompilerConfig?.excludePattern ?? rawConfig.compiler?.excludePattern ?? ["**/node_modules/**"],
49
+ outputDir: customCompilerConfig?.outputDir ?? rawConfig.compiler?.outputDir ?? "compiler"
50
+ };
51
+ };
52
+ /**
53
+ * Get the output directory path for compiler dictionaries
54
+ */
55
+ const getOutputDir = () => {
56
+ const { baseDir } = config.content;
57
+ return join(baseDir, getCompilerConfig().outputDir);
58
+ };
59
+ /**
60
+ * Get the file path for a dictionary
61
+ */
62
+ const getDictionaryFilePath = (dictionaryKey) => {
63
+ return join(getOutputDir(), `${dictionaryKey}.content.json`);
64
+ };
65
+ /**
66
+ * Read an existing dictionary file if it exists
67
+ */
68
+ const readExistingDictionary = async (dictionaryKey) => {
69
+ const filePath = getDictionaryFilePath(dictionaryKey);
70
+ if (!existsSync(filePath)) return null;
71
+ try {
72
+ const content = await readFile(filePath, "utf-8");
73
+ return JSON.parse(content);
74
+ } catch {
75
+ return null;
76
+ }
77
+ };
78
+ /**
79
+ * Merge extracted content with existing dictionary, preserving translations.
80
+ * - Keys in extracted but not in existing: added with default locale only
81
+ * - Keys in both: preserve existing translations, update default locale value
82
+ * - Keys in existing but not in extracted: removed (no longer in source)
83
+ */
84
+ const mergeWithExistingDictionary = (extractedContent, existingDictionary, defaultLocale) => {
85
+ const mergedContent = {};
86
+ const existingContent = existingDictionary?.content;
87
+ for (const [key, value] of Object.entries(extractedContent)) {
88
+ const existingEntry = existingContent?.[key];
89
+ if (existingEntry && existingEntry.nodeType === "translation" && existingEntry.translation) {
90
+ const oldValue = existingEntry.translation[defaultLocale];
91
+ const isUpdated = oldValue !== value;
92
+ mergedContent[key] = {
93
+ nodeType: "translation",
94
+ translation: {
95
+ ...existingEntry.translation,
96
+ [defaultLocale]: value
97
+ }
98
+ };
99
+ if (isUpdated) logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Updated "${key}" [${defaultLocale}]: "${oldValue?.slice(0, 30)}..." → "${value.slice(0, 30)}..."`, {
100
+ level: "info",
101
+ isVerbose: true
102
+ });
103
+ } else {
104
+ mergedContent[key] = {
105
+ nodeType: "translation",
106
+ translation: { [defaultLocale]: value }
107
+ };
108
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Added new key "${key}"`, {
109
+ level: "info",
110
+ isVerbose: true
111
+ });
112
+ }
113
+ }
114
+ if (existingContent) {
115
+ const removedKeys = Object.keys(existingContent).filter((key) => !(key in extractedContent));
116
+ for (const key of removedKeys) logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Removed key "${key}" (no longer in source)`, {
117
+ level: "info",
118
+ isVerbose: true
119
+ });
120
+ }
121
+ return mergedContent;
122
+ };
123
+ /**
124
+ * Build the list of files to transform based on configuration patterns
125
+ */
126
+ const buildFilesList = async () => {
127
+ const { baseDir } = config.content;
128
+ const compilerConfig = getCompilerConfig();
129
+ const patterns = Array.isArray(compilerConfig.transformPattern) ? compilerConfig.transformPattern : [compilerConfig.transformPattern];
130
+ const excludePatterns = Array.isArray(compilerConfig.excludePattern) ? compilerConfig.excludePattern : [compilerConfig.excludePattern];
131
+ filesList = fg.sync(patterns, {
132
+ cwd: baseDir,
133
+ ignore: excludePatterns
134
+ }).map((file) => join(baseDir, file));
135
+ };
136
+ /**
137
+ * Initialize the compiler with the given mode
138
+ */
139
+ const init = async (_compilerMode) => {
140
+ config = getConfiguration(configOptions);
141
+ logger = getAppLogger(config);
142
+ try {
143
+ babel = createRequire(import.meta.url)("@babel/core");
144
+ } catch {
145
+ logger("Failed to load @babel/core. Transformation will be disabled.", { level: "warn" });
146
+ }
147
+ await buildFilesList();
148
+ };
149
+ /**
150
+ * Vite hook: config
151
+ * Called before Vite config is resolved - perfect time to prepare dictionaries
152
+ */
153
+ const configHook = async (_config, env) => {
154
+ config = getConfiguration(configOptions);
155
+ logger = getAppLogger(config);
156
+ const isDevCommand = env.command === "serve" && env.mode === "development";
157
+ const isBuildCommand = env.command === "build";
158
+ if (isDevCommand || isBuildCommand) await prepareIntlayer(config, {
159
+ clean: isBuildCommand,
160
+ cacheTimeoutMs: isBuildCommand ? 1e3 * 30 : 1e3 * 60 * 60
161
+ });
162
+ };
163
+ /**
164
+ * Vite hook: configResolved
165
+ * Called when Vite config is resolved
166
+ */
167
+ const configResolved = async (viteConfig) => {
168
+ const compilerMode = viteConfig.env?.DEV ? "dev" : "build";
169
+ projectRoot = viteConfig.root;
170
+ await init(compilerMode);
171
+ };
172
+ /**
173
+ * Build start hook - no longer needs to prepare dictionaries
174
+ * The compiler is now autonomous and extracts content inline
175
+ */
176
+ const buildStart = async () => {
177
+ logger("Intlayer compiler initialized", { level: "info" });
178
+ };
179
+ /**
180
+ * Build end hook - wait for any pending dictionary writes
181
+ */
182
+ const buildEnd = async () => {
183
+ if (pendingDictionaryWrite) await pendingDictionaryWrite;
184
+ };
185
+ /**
186
+ * Configure the dev server
187
+ */
188
+ const configureServer = async () => {};
189
+ /**
190
+ * Vite hook: handleHotUpdate
191
+ * Handles HMR for content files - invalidates cache and triggers re-transform
192
+ */
193
+ const handleHotUpdate = async (ctx) => {
194
+ const { file, server, modules } = ctx;
195
+ if (filesList.some((f) => f === file)) {
196
+ for (const mod of modules) server.moduleGraph.invalidateModule(mod);
197
+ try {
198
+ await transformHandler(await readFile(file, "utf-8"), file);
199
+ } catch (error) {
200
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Failed to re-transform ${file}: ${error}`, { level: "error" });
201
+ }
202
+ server.ws.send({ type: "full-reload" });
203
+ return [];
204
+ }
205
+ };
206
+ /**
207
+ * Write and build a single dictionary immediately
208
+ * This is called during transform to ensure dictionaries are always up-to-date.
209
+ *
210
+ * The merge strategy:
211
+ * - New keys are added with the default locale only
212
+ * - Existing keys preserve their translations, with default locale updated
213
+ * - Keys no longer in source are removed
214
+ */
215
+ const writeAndBuildDictionary = async (result) => {
216
+ const { dictionaryKey, content, locale } = result;
217
+ const outputDir = getOutputDir();
218
+ await mkdir(outputDir, { recursive: true });
219
+ const existingDictionary = await readExistingDictionary(dictionaryKey);
220
+ const mergedContent = mergeWithExistingDictionary(content, existingDictionary, locale);
221
+ const mergedDictionary = {
222
+ ...existingDictionary && {
223
+ $schema: existingDictionary.$schema,
224
+ id: existingDictionary.id,
225
+ title: existingDictionary.title,
226
+ description: existingDictionary.description,
227
+ tags: existingDictionary.tags,
228
+ fill: existingDictionary.fill,
229
+ filled: existingDictionary.filled,
230
+ priority: existingDictionary.priority,
231
+ version: existingDictionary.version
232
+ },
233
+ key: dictionaryKey,
234
+ content: mergedContent,
235
+ filePath: join(relative(config.content.baseDir, outputDir), `${dictionaryKey}.content.json`)
236
+ };
237
+ try {
238
+ const writeResult = await writeContentDeclaration(mergedDictionary, config, { newDictionariesPath: relative(config.content.baseDir, outputDir) });
239
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} ${writeResult.status === "created" ? "Created" : writeResult.status === "updated" ? "Updated" : "Processed"} content declaration: ${colorizePath(relative(projectRoot, writeResult.path))}`, { level: "info" });
240
+ const dictionaryToBuild = {
241
+ ...mergedDictionary,
242
+ filePath: relative(config.content.baseDir, writeResult.path)
243
+ };
244
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Building dictionary ${colorizeKey(dictionaryKey)}`, { level: "info" });
245
+ await buildDictionary([dictionaryToBuild], config);
246
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Dictionary ${colorizeKey(dictionaryKey)} built successfully`, { level: "info" });
247
+ } catch (error) {
248
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Failed to write/build dictionary for ${colorizeKey(dictionaryKey)}: ${error}`, { level: "error" });
249
+ }
250
+ };
251
+ /**
252
+ * Callback for when content is extracted from a file
253
+ * Immediately writes and builds the dictionary
254
+ */
255
+ const handleExtractedContent = (result) => {
256
+ const contentKeys = Object.keys(result.content);
257
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Extracted ${contentKeys.length} content keys from ${colorizePath(relative(projectRoot, result.filePath))}`, { level: "info" });
258
+ pendingDictionaryWrite = (pendingDictionaryWrite ?? Promise.resolve()).then(() => writeAndBuildDictionary(result)).catch((error) => {
259
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Error in dictionary write chain: ${error}`, { level: "error" });
260
+ });
261
+ };
262
+ /**
263
+ * Detect the package name to import useIntlayer from based on file extension
264
+ */
265
+ const detectPackageName = (filename) => {
266
+ if (filename.endsWith(".vue")) return "vue-intlayer";
267
+ if (filename.endsWith(".svelte")) return "svelte-intlayer";
268
+ if (filename.endsWith(".tsx") || filename.endsWith(".jsx")) return "react-intlayer";
269
+ return "intlayer";
270
+ };
271
+ /**
272
+ * Transform a Vue file using the Vue extraction plugin
273
+ */
274
+ const transformVue = async (code, filename, defaultLocale) => {
275
+ const { intlayerVueExtract } = await import("@intlayer/vue-compiler");
276
+ return intlayerVueExtract(code, filename, {
277
+ defaultLocale,
278
+ filesList,
279
+ packageName: "vue-intlayer",
280
+ onExtract: handleExtractedContent
281
+ });
282
+ };
283
+ /**
284
+ * Transform a Svelte file using the Svelte extraction plugin
285
+ */
286
+ const transformSvelte = async (code, filename, defaultLocale) => {
287
+ const { intlayerSvelteExtract } = await import("@intlayer/svelte-compiler");
288
+ return await intlayerSvelteExtract(code, filename, {
289
+ defaultLocale,
290
+ filesList,
291
+ packageName: "svelte-intlayer",
292
+ onExtract: handleExtractedContent
293
+ });
294
+ };
295
+ /**
296
+ * Transform a JSX/TSX file using the Babel extraction plugin
297
+ */
298
+ const transformJsx = (code, filename, defaultLocale) => {
299
+ if (!babel) return;
300
+ const packageName = detectPackageName(filename);
301
+ const result = babel.transformSync(code, {
302
+ filename,
303
+ plugins: [[intlayerExtractBabelPlugin, {
304
+ defaultLocale,
305
+ filesList,
306
+ packageName,
307
+ onExtract: handleExtractedContent
308
+ }]],
309
+ parserOpts: {
310
+ sourceType: "module",
311
+ allowImportExportEverywhere: true,
312
+ plugins: [
313
+ "typescript",
314
+ "jsx",
315
+ "decorators-legacy",
316
+ "classProperties",
317
+ "objectRestSpread",
318
+ "asyncGenerators",
319
+ "functionBind",
320
+ "exportDefaultFrom",
321
+ "exportNamespaceFrom",
322
+ "dynamicImport",
323
+ "nullishCoalescingOperator",
324
+ "optionalChaining"
325
+ ]
326
+ }
327
+ });
328
+ if (result?.code) return {
329
+ code: result.code,
330
+ map: result.map,
331
+ extracted: true
332
+ };
333
+ };
334
+ /**
335
+ * Transform a file using the appropriate extraction plugin based on file type
336
+ */
337
+ const transformHandler = async (code, id, _options) => {
338
+ if (!getCompilerConfig().enabled) return;
339
+ if (id.includes("?")) return;
340
+ const { defaultLocale } = config.internationalization;
341
+ const filename = id;
342
+ if (!filesList.includes(filename)) return;
343
+ const isVue = filename.endsWith(".vue");
344
+ const isSvelte = filename.endsWith(".svelte");
345
+ if (!isVue && !isSvelte) {
346
+ try {
347
+ const result = transformJsx(code, filename, defaultLocale);
348
+ if (pendingDictionaryWrite) await pendingDictionaryWrite;
349
+ if (result?.code) return {
350
+ code: result.code,
351
+ map: result.map
352
+ };
353
+ } catch (error) {
354
+ logger(`Failed to transform ${colorizePath(relative(projectRoot, filename))}: ${error}`, { level: "error" });
355
+ }
356
+ return;
357
+ }
358
+ logger(`${colorize("Compiler:", ANSIColors.GREY_DARK)} Transforming ${colorizePath(relative(projectRoot, filename))}`, { level: "info" });
359
+ try {
360
+ let result;
361
+ if (isVue) result = await transformVue(code, filename, defaultLocale);
362
+ else if (isSvelte) result = await transformSvelte(code, filename, defaultLocale);
363
+ if (pendingDictionaryWrite) await pendingDictionaryWrite;
364
+ if (result?.code) return {
365
+ code: result.code,
366
+ map: result.map
367
+ };
368
+ } catch (error) {
369
+ logger(`Failed to transform ${relative(projectRoot, filename)}: ${error}`, { level: "error" });
370
+ }
371
+ };
372
+ /**
373
+ * Apply hook for determining when plugin should be active
374
+ */
375
+ const apply = (_config, _env) => {
376
+ return getCompilerConfig().enabled;
377
+ };
378
+ return {
379
+ name: "vite-intlayer-compiler",
380
+ enforce: "pre",
381
+ config: configHook,
382
+ configResolved,
383
+ buildStart,
384
+ buildEnd,
385
+ configureServer,
386
+ handleHotUpdate,
387
+ transform: transformHandler,
388
+ apply: (_viteConfig, env) => {
389
+ if (!config) config = getConfiguration(configOptions);
390
+ return apply(_viteConfig, env);
391
+ }
392
+ };
393
+ };
394
+
395
+ //#endregion
396
+ export { intlayerCompiler };
397
+ //# sourceMappingURL=IntlayerCompilerPlugin.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntlayerCompilerPlugin.mjs","names":["config: IntlayerConfig","logger: ReturnType<typeof getAppLogger>","filesList: string[]","babel: any","pendingDictionaryWrite: Promise<void> | null","mergedContent: DictionaryContentMap","compilerMode: CompilerMode","mergedDictionary: Dictionary","dictionaryToBuild: Dictionary","result:\n | { code: string; map?: unknown; extracted?: boolean }\n | null\n | undefined"],"sources":["../../src/IntlayerCompilerPlugin.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join, relative } from 'node:path';\nimport {\n type ExtractResult,\n intlayerExtractBabelPlugin,\n} from '@intlayer/babel';\nimport {\n buildDictionary,\n prepareIntlayer,\n writeContentDeclaration,\n} from '@intlayer/chokidar';\nimport {\n ANSIColors,\n colorize,\n colorizeKey,\n colorizePath,\n type GetConfigurationOptions,\n getAppLogger,\n getConfiguration,\n} from '@intlayer/config';\nimport type {\n CompilerConfig,\n Dictionary,\n IntlayerConfig,\n} from '@intlayer/types';\nimport fg from 'fast-glob';\n\n/**\n * Translation node structure used in dictionaries\n */\ntype TranslationNode = {\n nodeType: 'translation';\n translation: Record<string, string>;\n};\n\n/**\n * Dictionary content structure - map of keys to translation nodes\n */\ntype DictionaryContentMap = Record<string, TranslationNode>;\n\n/**\n * Mode of the compiler\n * - 'dev': Development mode with HMR support\n * - 'build': Production build mode\n */\nexport type CompilerMode = 'dev' | 'build';\n\n/**\n * Options for initializing the compiler\n */\nexport type IntlayerCompilerOptions = {\n /**\n * Configuration options for getting the intlayer configuration\n */\n configOptions?: GetConfigurationOptions;\n\n /**\n * Custom compiler configuration to override defaults\n */\n compilerConfig?: Partial<CompilerConfig>;\n};\n\n/**\n * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer\n *\n * This autonomous compiler handles:\n * - Configuration loading and management\n * - Hot Module Replacement (HMR) for content changes\n * - File transformation with content extraction\n * - Dictionary persistence and building\n *\n * @example\n * ```ts\n * // vite.config.ts\n * import { defineConfig } from 'vite';\n * import { intlayerCompiler } from 'vite-intlayer';\n *\n * export default defineConfig({\n * plugins: [intlayerCompiler()],\n * });\n * ```\n */\nexport const intlayerCompiler = (options?: IntlayerCompilerOptions): any => {\n // Private state\n let config: IntlayerConfig;\n let logger: ReturnType<typeof getAppLogger>;\n let projectRoot = '';\n let filesList: string[] = [];\n let babel: any = null;\n\n // Promise to track dictionary writing (for synchronization)\n let pendingDictionaryWrite: Promise<void> | null = null;\n\n const configOptions = options?.configOptions;\n const customCompilerConfig = options?.compilerConfig;\n\n /**\n * Get compiler config from intlayer config or custom options\n */\n const getCompilerConfig = () => {\n // Access compiler config from the raw config (may not be in the type)\n const rawConfig = config as IntlayerConfig & {\n compiler?: Partial<CompilerConfig>;\n };\n\n return {\n enabled:\n customCompilerConfig?.enabled ?? rawConfig.compiler?.enabled ?? true,\n transformPattern:\n customCompilerConfig?.transformPattern ??\n rawConfig.compiler?.transformPattern ??\n config.build.traversePattern,\n excludePattern: customCompilerConfig?.excludePattern ??\n rawConfig.compiler?.excludePattern ?? ['**/node_modules/**'],\n outputDir:\n customCompilerConfig?.outputDir ??\n rawConfig.compiler?.outputDir ??\n 'compiler',\n };\n };\n\n /**\n * Get the output directory path for compiler dictionaries\n */\n const getOutputDir = (): string => {\n const { baseDir } = config.content;\n const compilerConfig = getCompilerConfig();\n return join(baseDir, compilerConfig.outputDir);\n };\n\n /**\n * Get the file path for a dictionary\n */\n const getDictionaryFilePath = (dictionaryKey: string): string => {\n const outputDir = getOutputDir();\n return join(outputDir, `${dictionaryKey}.content.json`);\n };\n\n /**\n * Read an existing dictionary file if it exists\n */\n const readExistingDictionary = async (\n dictionaryKey: string\n ): Promise<Dictionary | null> => {\n const filePath = getDictionaryFilePath(dictionaryKey);\n\n if (!existsSync(filePath)) {\n return null;\n }\n\n try {\n const content = await readFile(filePath, 'utf-8');\n return JSON.parse(content) as Dictionary;\n } catch {\n return null;\n }\n };\n\n /**\n * Merge extracted content with existing dictionary, preserving translations.\n * - Keys in extracted but not in existing: added with default locale only\n * - Keys in both: preserve existing translations, update default locale value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\n const mergeWithExistingDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n ): DictionaryContentMap => {\n const mergedContent: DictionaryContentMap = {};\n const existingContent = existingDictionary?.content as\n | DictionaryContentMap\n | undefined;\n\n for (const [key, value] of Object.entries(extractedContent)) {\n const existingEntry = existingContent?.[key];\n\n if (\n existingEntry &&\n existingEntry.nodeType === 'translation' &&\n existingEntry.translation\n ) {\n const oldValue = existingEntry.translation[defaultLocale];\n const isUpdated = oldValue !== value;\n\n // Key exists in both - preserve existing translations, update default locale\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n ...existingEntry.translation,\n [defaultLocale]: value,\n },\n };\n\n if (isUpdated) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Updated \"${key}\" [${defaultLocale}]: \"${oldValue?.slice(0, 30)}...\" → \"${value.slice(0, 30)}...\"`,\n { level: 'info', isVerbose: true }\n );\n }\n } else {\n // New key - add with default locale only\n mergedContent[key] = {\n nodeType: 'translation',\n translation: {\n [defaultLocale]: value,\n },\n };\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Added new key \"${key}\"`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n // Log removed keys\n if (existingContent) {\n const removedKeys = Object.keys(existingContent).filter(\n (key) => !(key in extractedContent)\n );\n for (const key of removedKeys) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Removed key \"${key}\" (no longer in source)`,\n {\n level: 'info',\n isVerbose: true,\n }\n );\n }\n }\n\n return mergedContent;\n };\n\n /**\n * Build the list of files to transform based on configuration patterns\n */\n const buildFilesList = async (): Promise<void> => {\n const { baseDir } = config.content;\n const compilerConfig = getCompilerConfig();\n\n const patterns = Array.isArray(compilerConfig.transformPattern)\n ? compilerConfig.transformPattern\n : [compilerConfig.transformPattern];\n const excludePatterns = Array.isArray(compilerConfig.excludePattern)\n ? compilerConfig.excludePattern\n : [compilerConfig.excludePattern];\n\n filesList = fg\n .sync(patterns, {\n cwd: baseDir,\n ignore: excludePatterns,\n })\n .map((file) => join(baseDir, file));\n };\n\n /**\n * Initialize the compiler with the given mode\n */\n const init = async (_compilerMode: CompilerMode): Promise<void> => {\n config = getConfiguration(configOptions);\n logger = getAppLogger(config);\n\n // Load Babel dynamically\n try {\n const localRequire = createRequire(import.meta.url);\n babel = localRequire('@babel/core');\n } catch {\n logger('Failed to load @babel/core. Transformation will be disabled.', {\n level: 'warn',\n });\n }\n\n // Build files list for transformation\n await buildFilesList();\n };\n\n /**\n * Vite hook: config\n * Called before Vite config is resolved - perfect time to prepare dictionaries\n */\n const configHook = async (\n _config: unknown,\n env: { command: string; mode: string }\n ): Promise<void> => {\n // Initialize config early\n config = getConfiguration(configOptions);\n logger = getAppLogger(config);\n\n const isDevCommand = env.command === 'serve' && env.mode === 'development';\n const isBuildCommand = env.command === 'build';\n\n // Prepare all existing dictionaries (builds them to .intlayer/dictionary/)\n // This ensures built dictionaries exist before the prune plugin runs\n if (isDevCommand || isBuildCommand) {\n await prepareIntlayer(config, {\n clean: isBuildCommand,\n cacheTimeoutMs: isBuildCommand\n ? 1000 * 30 // 30 seconds for build\n : 1000 * 60 * 60, // 1 hour for dev\n });\n }\n };\n\n /**\n * Vite hook: configResolved\n * Called when Vite config is resolved\n */\n const configResolved = async (viteConfig: {\n env?: { DEV?: boolean };\n root: string;\n }): Promise<void> => {\n const compilerMode: CompilerMode = viteConfig.env?.DEV ? 'dev' : 'build';\n projectRoot = viteConfig.root;\n await init(compilerMode);\n };\n\n /**\n * Build start hook - no longer needs to prepare dictionaries\n * The compiler is now autonomous and extracts content inline\n */\n const buildStart = async (): Promise<void> => {\n // Autonomous compiler - no need to prepare dictionaries\n // Content is extracted inline during transformation\n logger('Intlayer compiler initialized', {\n level: 'info',\n });\n };\n\n /**\n * Build end hook - wait for any pending dictionary writes\n */\n const buildEnd = async (): Promise<void> => {\n // Wait for any pending dictionary writes to complete\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n };\n\n /**\n * Configure the dev server\n */\n const configureServer = async (): Promise<void> => {\n // In autonomous mode, we don't need file watching for dictionaries\n // Content is extracted inline during transformation\n };\n\n /**\n * Vite hook: handleHotUpdate\n * Handles HMR for content files - invalidates cache and triggers re-transform\n */\n const handleHotUpdate = async (ctx: any): Promise<unknown[] | undefined> => {\n const { file, server, modules } = ctx;\n\n // Check if this is a file we should transform\n const isTransformableFile = filesList.some((f) => f === file);\n\n if (isTransformableFile) {\n // Invalidate all affected modules to ensure re-transform\n for (const mod of modules) {\n server.moduleGraph.invalidateModule(mod);\n }\n\n // Force re-transform by reading and processing the file\n // This ensures content extraction happens on every file change\n try {\n const code = await readFile(file, 'utf-8');\n\n // Trigger the transform manually to extract content\n await transformHandler(code, file);\n } catch (error) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to re-transform ${file}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n\n // Trigger full reload for content changes\n server.ws.send({ type: 'full-reload' });\n return [];\n }\n\n return undefined;\n };\n\n /**\n * Write and build a single dictionary immediately\n * This is called during transform to ensure dictionaries are always up-to-date.\n *\n * The merge strategy:\n * - New keys are added with the default locale only\n * - Existing keys preserve their translations, with default locale updated\n * - Keys no longer in source are removed\n */\n const writeAndBuildDictionary = async (\n result: ExtractResult\n ): Promise<void> => {\n const { dictionaryKey, content, locale } = result;\n\n const outputDir = getOutputDir();\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Read existing dictionary to preserve translations and metadata\n const existingDictionary = await readExistingDictionary(dictionaryKey);\n\n // Merge extracted content with existing translations\n const mergedContent = mergeWithExistingDictionary(\n content,\n existingDictionary,\n locale\n );\n\n // Create the merged dictionary, preserving existing metadata\n const mergedDictionary: Dictionary = {\n // Preserve existing metadata (title, description, tags, etc.)\n ...(existingDictionary && {\n $schema: existingDictionary.$schema,\n id: existingDictionary.id,\n title: existingDictionary.title,\n description: existingDictionary.description,\n tags: existingDictionary.tags,\n fill: existingDictionary.fill,\n filled: existingDictionary.filled,\n priority: existingDictionary.priority,\n version: existingDictionary.version,\n }),\n // Required fields\n key: dictionaryKey,\n content: mergedContent,\n filePath: join(\n relative(config.content.baseDir, outputDir),\n `${dictionaryKey}.content.json`\n ),\n };\n\n try {\n const writeResult = await writeContentDeclaration(\n mergedDictionary,\n config,\n {\n newDictionariesPath: relative(config.content.baseDir, outputDir),\n }\n );\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} ${writeResult.status === 'created' ? 'Created' : writeResult.status === 'updated' ? 'Updated' : 'Processed'} content declaration: ${colorizePath(relative(projectRoot, writeResult.path))}`,\n {\n level: 'info',\n }\n );\n\n // Build the dictionary immediately so it's available for the prune plugin\n const dictionaryToBuild: Dictionary = {\n ...mergedDictionary,\n filePath: relative(config.content.baseDir, writeResult.path),\n };\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Building dictionary ${colorizeKey(dictionaryKey)}`,\n {\n level: 'info',\n }\n );\n\n await buildDictionary([dictionaryToBuild], config);\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Dictionary ${colorizeKey(dictionaryKey)} built successfully`,\n {\n level: 'info',\n }\n );\n } catch (error) {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Failed to write/build dictionary for ${colorizeKey(dictionaryKey)}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n };\n\n /**\n * Callback for when content is extracted from a file\n * Immediately writes and builds the dictionary\n */\n const handleExtractedContent = (result: ExtractResult): void => {\n const contentKeys = Object.keys(result.content);\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Extracted ${contentKeys.length} content keys from ${colorizePath(relative(projectRoot, result.filePath))}`,\n {\n level: 'info',\n }\n );\n\n // Chain the write operation to ensure sequential writes\n pendingDictionaryWrite = (pendingDictionaryWrite ?? Promise.resolve())\n .then(() => writeAndBuildDictionary(result))\n .catch((error) => {\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Error in dictionary write chain: ${error}`,\n {\n level: 'error',\n }\n );\n });\n };\n\n /**\n * Detect the package name to import useIntlayer from based on file extension\n */\n const detectPackageName = (filename: string): string => {\n if (filename.endsWith('.vue')) {\n return 'vue-intlayer';\n }\n if (filename.endsWith('.svelte')) {\n return 'svelte-intlayer';\n }\n if (filename.endsWith('.tsx') || filename.endsWith('.jsx')) {\n return 'react-intlayer';\n }\n // Default to react-intlayer for JSX/TSX files\n return 'intlayer';\n };\n\n /**\n * Transform a Vue file using the Vue extraction plugin\n */\n const transformVue = async (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n const { intlayerVueExtract } = await import('@intlayer/vue-compiler');\n return intlayerVueExtract(code, filename, {\n defaultLocale,\n filesList,\n packageName: 'vue-intlayer',\n onExtract: handleExtractedContent,\n });\n };\n\n /**\n * Transform a Svelte file using the Svelte extraction plugin\n */\n const transformSvelte = async (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n const { intlayerSvelteExtract } = await import('@intlayer/svelte-compiler');\n const result = await intlayerSvelteExtract(code, filename, {\n defaultLocale,\n filesList,\n packageName: 'svelte-intlayer',\n onExtract: handleExtractedContent,\n });\n\n return result;\n };\n\n /**\n * Transform a JSX/TSX file using the Babel extraction plugin\n */\n const transformJsx = (\n code: string,\n filename: string,\n defaultLocale: string\n ) => {\n if (!babel) {\n return undefined;\n }\n\n const packageName = detectPackageName(filename);\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerExtractBabelPlugin,\n {\n defaultLocale,\n filesList,\n packageName,\n onExtract: handleExtractedContent,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n extracted: true,\n };\n }\n\n return undefined;\n };\n\n /**\n * Transform a file using the appropriate extraction plugin based on file type\n */\n const transformHandler = async (\n code: string,\n id: string,\n _options?: { ssr?: boolean }\n ) => {\n const compilerConfig = getCompilerConfig();\n\n // Only transform if compiler is enabled\n if (!compilerConfig.enabled) {\n return undefined;\n }\n\n // Skip virtual modules (query strings indicate compiled/virtual modules)\n // e.g., App.svelte?svelte&type=style, Component.vue?vue&type=script\n if (id.includes('?')) {\n return undefined;\n }\n\n const { defaultLocale } = config.internationalization;\n\n const filename = id;\n\n if (!filesList.includes(filename)) {\n return undefined;\n }\n\n // Only process Vue and Svelte source files with extraction\n // JSX/TSX files are handled by Babel which has its own detection\n const isVue = filename.endsWith('.vue');\n const isSvelte = filename.endsWith('.svelte');\n\n if (!isVue && !isSvelte) {\n // For non-Vue/Svelte files, use JSX transformation via Babel\n try {\n const result = transformJsx(code, filename, defaultLocale);\n\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n } catch (error) {\n logger(\n `Failed to transform ${colorizePath(relative(projectRoot, filename))}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n return undefined;\n }\n\n logger(\n `${colorize('Compiler:', ANSIColors.GREY_DARK)} Transforming ${colorizePath(relative(projectRoot, filename))}`,\n {\n level: 'info',\n }\n );\n\n try {\n let result:\n | { code: string; map?: unknown; extracted?: boolean }\n | null\n | undefined;\n\n // Route to appropriate transformer based on file extension\n if (isVue) {\n result = await transformVue(code, filename, defaultLocale);\n } else if (isSvelte) {\n result = await transformSvelte(code, filename, defaultLocale);\n }\n\n // Wait for the dictionary to be written before returning\n // This ensures the dictionary exists before the prune plugin runs\n if (pendingDictionaryWrite) {\n await pendingDictionaryWrite;\n }\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n } catch (error) {\n logger(\n `Failed to transform ${relative(projectRoot, filename)}: ${error}`,\n {\n level: 'error',\n }\n );\n }\n\n return undefined;\n };\n\n /**\n * Apply hook for determining when plugin should be active\n */\n const apply = (_config: unknown, _env: { command: string }): boolean => {\n const compilerConfig = getCompilerConfig();\n // Apply if compiler is enabled\n return compilerConfig.enabled;\n };\n\n return {\n name: 'vite-intlayer-compiler',\n enforce: 'pre',\n config: configHook,\n configResolved,\n buildStart,\n buildEnd,\n configureServer,\n handleHotUpdate,\n transform: transformHandler,\n apply: (_viteConfig: unknown, env: { command: string }) => {\n // Initialize config if not already done\n if (!config) {\n config = getConfiguration(configOptions);\n }\n return apply(_viteConfig, env);\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoFA,MAAa,oBAAoB,YAA2C;CAE1E,IAAIA;CACJ,IAAIC;CACJ,IAAI,cAAc;CAClB,IAAIC,YAAsB,EAAE;CAC5B,IAAIC,QAAa;CAGjB,IAAIC,yBAA+C;CAEnD,MAAM,gBAAgB,SAAS;CAC/B,MAAM,uBAAuB,SAAS;;;;CAKtC,MAAM,0BAA0B;EAE9B,MAAM,YAAY;AAIlB,SAAO;GACL,SACE,sBAAsB,WAAW,UAAU,UAAU,WAAW;GAClE,kBACE,sBAAsB,oBACtB,UAAU,UAAU,oBACpB,OAAO,MAAM;GACf,gBAAgB,sBAAsB,kBACpC,UAAU,UAAU,kBAAkB,CAAC,qBAAqB;GAC9D,WACE,sBAAsB,aACtB,UAAU,UAAU,aACpB;GACH;;;;;CAMH,MAAM,qBAA6B;EACjC,MAAM,EAAE,YAAY,OAAO;AAE3B,SAAO,KAAK,SADW,mBAAmB,CACN,UAAU;;;;;CAMhD,MAAM,yBAAyB,kBAAkC;AAE/D,SAAO,KADW,cAAc,EACT,GAAG,cAAc,eAAe;;;;;CAMzD,MAAM,yBAAyB,OAC7B,kBAC+B;EAC/B,MAAM,WAAW,sBAAsB,cAAc;AAErD,MAAI,CAAC,WAAW,SAAS,CACvB,QAAO;AAGT,MAAI;GACF,MAAM,UAAU,MAAM,SAAS,UAAU,QAAQ;AACjD,UAAO,KAAK,MAAM,QAAQ;UACpB;AACN,UAAO;;;;;;;;;CAUX,MAAM,+BACJ,kBACA,oBACA,kBACyB;EACzB,MAAMC,gBAAsC,EAAE;EAC9C,MAAM,kBAAkB,oBAAoB;AAI5C,OAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,iBAAiB,EAAE;GAC3D,MAAM,gBAAgB,kBAAkB;AAExC,OACE,iBACA,cAAc,aAAa,iBAC3B,cAAc,aACd;IACA,MAAM,WAAW,cAAc,YAAY;IAC3C,MAAM,YAAY,aAAa;AAG/B,kBAAc,OAAO;KACnB,UAAU;KACV,aAAa;MACX,GAAG,cAAc;OAChB,gBAAgB;MAClB;KACF;AAED,QAAI,UACF,QACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,YAAY,IAAI,KAAK,cAAc,MAAM,UAAU,MAAM,GAAG,GAAG,CAAC,UAAU,MAAM,MAAM,GAAG,GAAG,CAAC,OAC5I;KAAE,OAAO;KAAQ,WAAW;KAAM,CACnC;UAEE;AAEL,kBAAc,OAAO;KACnB,UAAU;KACV,aAAa,GACV,gBAAgB,OAClB;KACF;AACD,WACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,kBAAkB,IAAI,IACrE;KACE,OAAO;KACP,WAAW;KACZ,CACF;;;AAKL,MAAI,iBAAiB;GACnB,MAAM,cAAc,OAAO,KAAK,gBAAgB,CAAC,QAC9C,QAAQ,EAAE,OAAO,kBACnB;AACD,QAAK,MAAM,OAAO,YAChB,QACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,gBAAgB,IAAI,0BACnE;IACE,OAAO;IACP,WAAW;IACZ,CACF;;AAIL,SAAO;;;;;CAMT,MAAM,iBAAiB,YAA2B;EAChD,MAAM,EAAE,YAAY,OAAO;EAC3B,MAAM,iBAAiB,mBAAmB;EAE1C,MAAM,WAAW,MAAM,QAAQ,eAAe,iBAAiB,GAC3D,eAAe,mBACf,CAAC,eAAe,iBAAiB;EACrC,MAAM,kBAAkB,MAAM,QAAQ,eAAe,eAAe,GAChE,eAAe,iBACf,CAAC,eAAe,eAAe;AAEnC,cAAY,GACT,KAAK,UAAU;GACd,KAAK;GACL,QAAQ;GACT,CAAC,CACD,KAAK,SAAS,KAAK,SAAS,KAAK,CAAC;;;;;CAMvC,MAAM,OAAO,OAAO,kBAA+C;AACjE,WAAS,iBAAiB,cAAc;AACxC,WAAS,aAAa,OAAO;AAG7B,MAAI;AAEF,WADqB,cAAc,OAAO,KAAK,IAAI,CAC9B,cAAc;UAC7B;AACN,UAAO,gEAAgE,EACrE,OAAO,QACR,CAAC;;AAIJ,QAAM,gBAAgB;;;;;;CAOxB,MAAM,aAAa,OACjB,SACA,QACkB;AAElB,WAAS,iBAAiB,cAAc;AACxC,WAAS,aAAa,OAAO;EAE7B,MAAM,eAAe,IAAI,YAAY,WAAW,IAAI,SAAS;EAC7D,MAAM,iBAAiB,IAAI,YAAY;AAIvC,MAAI,gBAAgB,eAClB,OAAM,gBAAgB,QAAQ;GAC5B,OAAO;GACP,gBAAgB,iBACZ,MAAO,KACP,MAAO,KAAK;GACjB,CAAC;;;;;;CAQN,MAAM,iBAAiB,OAAO,eAGT;EACnB,MAAMC,eAA6B,WAAW,KAAK,MAAM,QAAQ;AACjE,gBAAc,WAAW;AACzB,QAAM,KAAK,aAAa;;;;;;CAO1B,MAAM,aAAa,YAA2B;AAG5C,SAAO,iCAAiC,EACtC,OAAO,QACR,CAAC;;;;;CAMJ,MAAM,WAAW,YAA2B;AAE1C,MAAI,uBACF,OAAM;;;;;CAOV,MAAM,kBAAkB,YAA2B;;;;;CASnD,MAAM,kBAAkB,OAAO,QAA6C;EAC1E,MAAM,EAAE,MAAM,QAAQ,YAAY;AAKlC,MAF4B,UAAU,MAAM,MAAM,MAAM,KAAK,EAEpC;AAEvB,QAAK,MAAM,OAAO,QAChB,QAAO,YAAY,iBAAiB,IAAI;AAK1C,OAAI;AAIF,UAAM,iBAHO,MAAM,SAAS,MAAM,QAAQ,EAGb,KAAK;YAC3B,OAAO;AACd,WACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,0BAA0B,KAAK,IAAI,SAClF,EACE,OAAO,SACR,CACF;;AAIH,UAAO,GAAG,KAAK,EAAE,MAAM,eAAe,CAAC;AACvC,UAAO,EAAE;;;;;;;;;;;;CAeb,MAAM,0BAA0B,OAC9B,WACkB;EAClB,MAAM,EAAE,eAAe,SAAS,WAAW;EAE3C,MAAM,YAAY,cAAc;AAGhC,QAAM,MAAM,WAAW,EAAE,WAAW,MAAM,CAAC;EAG3C,MAAM,qBAAqB,MAAM,uBAAuB,cAAc;EAGtE,MAAM,gBAAgB,4BACpB,SACA,oBACA,OACD;EAGD,MAAMC,mBAA+B;GAEnC,GAAI,sBAAsB;IACxB,SAAS,mBAAmB;IAC5B,IAAI,mBAAmB;IACvB,OAAO,mBAAmB;IAC1B,aAAa,mBAAmB;IAChC,MAAM,mBAAmB;IACzB,MAAM,mBAAmB;IACzB,QAAQ,mBAAmB;IAC3B,UAAU,mBAAmB;IAC7B,SAAS,mBAAmB;IAC7B;GAED,KAAK;GACL,SAAS;GACT,UAAU,KACR,SAAS,OAAO,QAAQ,SAAS,UAAU,EAC3C,GAAG,cAAc,eAClB;GACF;AAED,MAAI;GACF,MAAM,cAAc,MAAM,wBACxB,kBACA,QACA,EACE,qBAAqB,SAAS,OAAO,QAAQ,SAAS,UAAU,EACjE,CACF;AAED,UACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,GAAG,YAAY,WAAW,YAAY,YAAY,YAAY,WAAW,YAAY,YAAY,YAAY,wBAAwB,aAAa,SAAS,aAAa,YAAY,KAAK,CAAC,IACzO,EACE,OAAO,QACR,CACF;GAGD,MAAMC,oBAAgC;IACpC,GAAG;IACH,UAAU,SAAS,OAAO,QAAQ,SAAS,YAAY,KAAK;IAC7D;AAED,UACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,uBAAuB,YAAY,cAAc,IAChG,EACE,OAAO,QACR,CACF;AAED,SAAM,gBAAgB,CAAC,kBAAkB,EAAE,OAAO;AAElD,UACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,cAAc,YAAY,cAAc,CAAC,sBACxF,EACE,OAAO,QACR,CACF;WACM,OAAO;AACd,UACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,wCAAwC,YAAY,cAAc,CAAC,IAAI,SACtH,EACE,OAAO,SACR,CACF;;;;;;;CAQL,MAAM,0BAA0B,WAAgC;EAC9D,MAAM,cAAc,OAAO,KAAK,OAAO,QAAQ;AAE/C,SACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,aAAa,YAAY,OAAO,qBAAqB,aAAa,SAAS,aAAa,OAAO,SAAS,CAAC,IACxJ,EACE,OAAO,QACR,CACF;AAGD,4BAA0B,0BAA0B,QAAQ,SAAS,EAClE,WAAW,wBAAwB,OAAO,CAAC,CAC3C,OAAO,UAAU;AAChB,UACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,oCAAoC,SACnF,EACE,OAAO,SACR,CACF;IACD;;;;;CAMN,MAAM,qBAAqB,aAA6B;AACtD,MAAI,SAAS,SAAS,OAAO,CAC3B,QAAO;AAET,MAAI,SAAS,SAAS,UAAU,CAC9B,QAAO;AAET,MAAI,SAAS,SAAS,OAAO,IAAI,SAAS,SAAS,OAAO,CACxD,QAAO;AAGT,SAAO;;;;;CAMT,MAAM,eAAe,OACnB,MACA,UACA,kBACG;EACH,MAAM,EAAE,uBAAuB,MAAM,OAAO;AAC5C,SAAO,mBAAmB,MAAM,UAAU;GACxC;GACA;GACA,aAAa;GACb,WAAW;GACZ,CAAC;;;;;CAMJ,MAAM,kBAAkB,OACtB,MACA,UACA,kBACG;EACH,MAAM,EAAE,0BAA0B,MAAM,OAAO;AAQ/C,SAPe,MAAM,sBAAsB,MAAM,UAAU;GACzD;GACA;GACA,aAAa;GACb,WAAW;GACZ,CAAC;;;;;CAQJ,MAAM,gBACJ,MACA,UACA,kBACG;AACH,MAAI,CAAC,MACH;EAGF,MAAM,cAAc,kBAAkB,SAAS;EAE/C,MAAM,SAAS,MAAM,cAAc,MAAM;GACvC;GACA,SAAS,CACP,CACE,4BACA;IACE;IACA;IACA;IACA,WAAW;IACZ,CACF,CACF;GACD,YAAY;IACV,YAAY;IACZ,6BAA6B;IAC7B,SAAS;KACP;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD;IACF;GACF,CAAC;AAEF,MAAI,QAAQ,KACV,QAAO;GACL,MAAM,OAAO;GACb,KAAK,OAAO;GACZ,WAAW;GACZ;;;;;CASL,MAAM,mBAAmB,OACvB,MACA,IACA,aACG;AAIH,MAAI,CAHmB,mBAAmB,CAGtB,QAClB;AAKF,MAAI,GAAG,SAAS,IAAI,CAClB;EAGF,MAAM,EAAE,kBAAkB,OAAO;EAEjC,MAAM,WAAW;AAEjB,MAAI,CAAC,UAAU,SAAS,SAAS,CAC/B;EAKF,MAAM,QAAQ,SAAS,SAAS,OAAO;EACvC,MAAM,WAAW,SAAS,SAAS,UAAU;AAE7C,MAAI,CAAC,SAAS,CAAC,UAAU;AAEvB,OAAI;IACF,MAAM,SAAS,aAAa,MAAM,UAAU,cAAc;AAE1D,QAAI,uBACF,OAAM;AAGR,QAAI,QAAQ,KACV,QAAO;KACL,MAAM,OAAO;KACb,KAAK,OAAO;KACb;YAEI,OAAO;AACd,WACE,uBAAuB,aAAa,SAAS,aAAa,SAAS,CAAC,CAAC,IAAI,SACzE,EACE,OAAO,SACR,CACF;;AAEH;;AAGF,SACE,GAAG,SAAS,aAAa,WAAW,UAAU,CAAC,gBAAgB,aAAa,SAAS,aAAa,SAAS,CAAC,IAC5G,EACE,OAAO,QACR,CACF;AAED,MAAI;GACF,IAAIC;AAMJ,OAAI,MACF,UAAS,MAAM,aAAa,MAAM,UAAU,cAAc;YACjD,SACT,UAAS,MAAM,gBAAgB,MAAM,UAAU,cAAc;AAK/D,OAAI,uBACF,OAAM;AAGR,OAAI,QAAQ,KACV,QAAO;IACL,MAAM,OAAO;IACb,KAAK,OAAO;IACb;WAEI,OAAO;AACd,UACE,uBAAuB,SAAS,aAAa,SAAS,CAAC,IAAI,SAC3D,EACE,OAAO,SACR,CACF;;;;;;CASL,MAAM,SAAS,SAAkB,SAAuC;AAGtE,SAFuB,mBAAmB,CAEpB;;AAGxB,QAAO;EACL,MAAM;EACN,SAAS;EACT,QAAQ;EACR;EACA;EACA;EACA;EACA;EACA,WAAW;EACX,QAAQ,aAAsB,QAA6B;AAEzD,OAAI,CAAC,OACH,UAAS,iBAAiB,cAAc;AAE1C,UAAO,MAAM,aAAa,IAAI;;EAEjC"}
@@ -1,5 +1,6 @@
1
+ import { intlayerCompiler } from "./IntlayerCompilerPlugin.mjs";
1
2
  import { intlayerPrune } from "./intlayerPrunePlugin.mjs";
2
3
  import { intLayerPlugin, intlayer, intlayerPlugin } from "./intlayerPlugin.mjs";
3
4
  import { intLayerMiddlewarePlugin, intlayerMiddleware, intlayerProxy } from "./intlayerProxyPlugin.mjs";
4
5
 
5
- export { intLayerMiddlewarePlugin, intLayerPlugin, intlayer, intlayerMiddleware, intlayerPlugin, intlayerProxy, intlayerPrune };
6
+ export { intLayerMiddlewarePlugin, intLayerPlugin, intlayer, intlayerCompiler, intlayerMiddleware, intlayerPlugin, intlayerProxy, intlayerPrune };
@@ -1,10 +1,10 @@
1
+ import { createRequire } from "node:module";
1
2
  import { join } from "node:path";
3
+ import { intlayerOptimizeBabelPlugin } from "@intlayer/babel";
2
4
  import { runOnce } from "@intlayer/chokidar";
3
5
  import { getAppLogger } from "@intlayer/config";
4
- import { createRequire } from "node:module";
5
- import { intlayerBabelPlugin } from "@intlayer/babel";
6
- import { getDictionaries } from "@intlayer/dictionaries-entry";
7
6
  import fg from "fast-glob";
7
+ import { getDictionaries } from "@intlayer/dictionaries-entry";
8
8
 
9
9
  //#region src/intlayerPrunePlugin.ts
10
10
  const intlayerPrune = (intlayerConfig) => {
@@ -22,7 +22,7 @@ const intlayerPrune = (intlayerConfig) => {
22
22
  dictionariesEntryPath,
23
23
  unmergedDictionariesEntryPath
24
24
  ];
25
- const dictionaries = getDictionaries();
25
+ const dictionaries = getDictionaries(intlayerConfig);
26
26
  const liveSyncKeys = Object.values(dictionaries).filter((dictionary) => dictionary.live).map((dictionary) => dictionary.key);
27
27
  return {
28
28
  name: "vite-intlayer-babel-transform",
@@ -46,7 +46,8 @@ const intlayerPrune = (intlayerConfig) => {
46
46
  if (!filesList.includes(filename)) return null;
47
47
  const result = babel.transformSync(code, {
48
48
  filename,
49
- plugins: [[intlayerBabelPlugin, {
49
+ plugins: [[intlayerOptimizeBabelPlugin, {
50
+ optimize,
50
51
  dictionariesDir,
51
52
  dictionariesEntryPath,
52
53
  unmergedDictionariesEntryPath,
@@ -1 +1 @@
1
- {"version":3,"file":"intlayerPrunePlugin.mjs","names":[],"sources":["../../src/intlayerPrunePlugin.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { intlayerBabelPlugin } from '@intlayer/babel';\nimport { runOnce } from '@intlayer/chokidar';\nimport { getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport type { PluginOption } from 'vite';\n\nexport const intlayerPrune = (intlayerConfig: IntlayerConfig): PluginOption => {\n try {\n const localeRequire = createRequire(import.meta.url);\n const babel = localeRequire('@babel/core');\n const logger = getAppLogger(intlayerConfig);\n\n const { importMode, traversePattern, optimize } = intlayerConfig.build;\n\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n unmergedDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n baseDir,\n } = intlayerConfig.content;\n\n const filesListPattern = fg\n .sync(traversePattern, {\n cwd: baseDir,\n })\n .map((file) => join(baseDir, file));\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries();\n const liveSyncKeys = Object.values(dictionaries)\n .filter((dictionary) => dictionary.live)\n .map((dictionary) => dictionary.key);\n\n return {\n name: 'vite-intlayer-babel-transform',\n enforce: 'post', // Run after other transformations as vue\n apply: (_config, env) => {\n // Only apply babel plugin if optimize is enabled\n\n const isBuild = env.command === 'build';\n const isEnabled = (optimize ?? true) && isBuild;\n\n if (isEnabled) {\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-prune-plugin-enabled.lock'\n ),\n () => logger('Build optimization enabled'),\n {\n cacheTimeoutMs: 1000 * 10, // 10 seconds\n }\n );\n }\n\n return isEnabled;\n },\n transform(code, id) {\n /**\n * Transform file as\n * .../HelloWorld.vue?vue&type=script&setup=true&lang.ts\n * Into\n * .../HelloWorld.vue\n *\n * Prevention for virtual file\n */\n const filename = id.split('?', 1)[0];\n\n if (!filesList.includes(filename)) return null;\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerBabelPlugin,\n {\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n liveSyncKeys,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n },\n };\n } catch (error) {\n console.warn('Failed to transform with Babel plugin:', error);\n\n return null;\n }\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,iBAAiB,mBAAiD;AAC7E,KAAI;EAEF,MAAM,QADgB,cAAc,OAAO,KAAK,IAAI,CACxB,cAAc;EAC1C,MAAM,SAAS,aAAa,eAAe;EAE3C,MAAM,EAAE,YAAY,iBAAiB,aAAa,eAAe;EAEjE,MAAM,EACJ,iBACA,wBACA,yBACA,sBACA,SACA,YACE,eAAe;EAEnB,MAAM,mBAAmB,GACtB,KAAK,iBAAiB,EACrB,KAAK,SACN,CAAC,CACD,KAAK,SAAS,KAAK,SAAS,KAAK,CAAC;EAErC,MAAM,wBAAwB,KAAK,SAAS,mBAAmB;EAC/D,MAAM,gCAAgC,KACpC,SACA,4BACD;EACD,MAAM,+BAA+B,KACnC,SACA,2BACD;EAED,MAAM,YAAY;GAChB,GAAG;GACH;GACA;GACD;EAED,MAAM,eAAe,iBAAiB;EACtC,MAAM,eAAe,OAAO,OAAO,aAAa,CAC7C,QAAQ,eAAe,WAAW,KAAK,CACvC,KAAK,eAAe,WAAW,IAAI;AAEtC,SAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ,SAAS,QAAQ;IAGvB,MAAM,UAAU,IAAI,YAAY;IAChC,MAAM,aAAa,YAAY,SAAS;AAExC,QAAI,UACF,SACE,KACE,SACA,aACA,SACA,qCACD,QACK,OAAO,6BAA6B,EAC1C,EACE,gBAAgB,MAAO,IACxB,CACF;AAGH,WAAO;;GAET,UAAU,MAAM,IAAI;;;;;;;;;IASlB,MAAM,WAAW,GAAG,MAAM,KAAK,EAAE,CAAC;AAElC,QAAI,CAAC,UAAU,SAAS,SAAS,CAAE,QAAO;IAE1C,MAAM,SAAS,MAAM,cAAc,MAAM;KACvC;KACA,SAAS,CACP,CACE,qBACA;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,wBAAwB;MACxB;MACD,CACF,CACF;KACD,YAAY;MACV,YAAY;MACZ,6BAA6B;MAC7B,SAAS;OACP;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACD;MACF;KACF,CAAC;AAEF,QAAI,QAAQ,KACV,QAAO;KACL,MAAM,OAAO;KACb,KAAK,OAAO;KACb;;GAGN;UACM,OAAO;AACd,UAAQ,KAAK,0CAA0C,MAAM;AAE7D,SAAO"}
1
+ {"version":3,"file":"intlayerPrunePlugin.mjs","names":[],"sources":["../../src/intlayerPrunePlugin.ts"],"sourcesContent":["import { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { intlayerOptimizeBabelPlugin } from '@intlayer/babel';\nimport { runOnce } from '@intlayer/chokidar';\nimport { getAppLogger } from '@intlayer/config';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type { IntlayerConfig } from '@intlayer/types';\nimport fg from 'fast-glob';\nimport type { PluginOption } from 'vite';\n\nexport const intlayerPrune = (intlayerConfig: IntlayerConfig): PluginOption => {\n try {\n const localeRequire = createRequire(import.meta.url);\n const babel = localeRequire('@babel/core');\n const logger = getAppLogger(intlayerConfig);\n\n const { importMode, traversePattern, optimize } = intlayerConfig.build;\n\n const {\n dictionariesDir,\n dynamicDictionariesDir,\n unmergedDictionariesDir,\n fetchDictionariesDir,\n mainDir,\n baseDir,\n } = intlayerConfig.content;\n\n const filesListPattern = fg\n .sync(traversePattern, {\n cwd: baseDir,\n })\n .map((file) => join(baseDir, file));\n\n const dictionariesEntryPath = join(mainDir, 'dictionaries.mjs');\n const unmergedDictionariesEntryPath = join(\n mainDir,\n 'unmerged_dictionaries.mjs'\n );\n const dynamicDictionariesEntryPath = join(\n mainDir,\n 'dynamic_dictionaries.mjs'\n );\n\n const filesList = [\n ...filesListPattern,\n dictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n unmergedDictionariesEntryPath, // should add dictionariesEntryPath to replace it by a empty object if import made dynamic\n ];\n\n const dictionaries = getDictionaries(intlayerConfig);\n const liveSyncKeys = Object.values(dictionaries)\n .filter((dictionary) => dictionary.live)\n .map((dictionary) => dictionary.key);\n\n return {\n name: 'vite-intlayer-babel-transform',\n enforce: 'post', // Run after other transformations as vue\n apply: (_config, env) => {\n // Only apply babel plugin if optimize is enabled\n\n const isBuild = env.command === 'build';\n const isEnabled = (optimize ?? true) && isBuild;\n\n if (isEnabled) {\n runOnce(\n join(\n baseDir,\n '.intlayer',\n 'cache',\n 'intlayer-prune-plugin-enabled.lock'\n ),\n () => logger('Build optimization enabled'),\n {\n cacheTimeoutMs: 1000 * 10, // 10 seconds\n }\n );\n }\n\n return isEnabled;\n },\n transform(code, id) {\n /**\n * Transform file as\n * .../HelloWorld.vue?vue&type=script&setup=true&lang.ts\n * Into\n * .../HelloWorld.vue\n *\n * Prevention for virtual file\n */\n const filename = id.split('?', 1)[0];\n\n if (!filesList.includes(filename)) return null;\n\n const result = babel.transformSync(code, {\n filename,\n plugins: [\n [\n intlayerOptimizeBabelPlugin,\n {\n optimize,\n dictionariesDir,\n dictionariesEntryPath,\n unmergedDictionariesEntryPath,\n unmergedDictionariesDir,\n dynamicDictionariesDir,\n dynamicDictionariesEntryPath,\n fetchDictionariesDir,\n importMode,\n filesList,\n replaceDictionaryEntry: true,\n liveSyncKeys,\n },\n ],\n ],\n parserOpts: {\n sourceType: 'module',\n allowImportExportEverywhere: true,\n plugins: [\n 'typescript',\n 'jsx',\n 'decorators-legacy',\n 'classProperties',\n 'objectRestSpread',\n 'asyncGenerators',\n 'functionBind',\n 'exportDefaultFrom',\n 'exportNamespaceFrom',\n 'dynamicImport',\n 'nullishCoalescingOperator',\n 'optionalChaining',\n ],\n },\n });\n\n if (result?.code) {\n return {\n code: result.code,\n map: result.map,\n };\n }\n },\n };\n } catch (error) {\n console.warn('Failed to transform with Babel plugin:', error);\n\n return null;\n }\n};\n"],"mappings":";;;;;;;;;AAUA,MAAa,iBAAiB,mBAAiD;AAC7E,KAAI;EAEF,MAAM,QADgB,cAAc,OAAO,KAAK,IAAI,CACxB,cAAc;EAC1C,MAAM,SAAS,aAAa,eAAe;EAE3C,MAAM,EAAE,YAAY,iBAAiB,aAAa,eAAe;EAEjE,MAAM,EACJ,iBACA,wBACA,yBACA,sBACA,SACA,YACE,eAAe;EAEnB,MAAM,mBAAmB,GACtB,KAAK,iBAAiB,EACrB,KAAK,SACN,CAAC,CACD,KAAK,SAAS,KAAK,SAAS,KAAK,CAAC;EAErC,MAAM,wBAAwB,KAAK,SAAS,mBAAmB;EAC/D,MAAM,gCAAgC,KACpC,SACA,4BACD;EACD,MAAM,+BAA+B,KACnC,SACA,2BACD;EAED,MAAM,YAAY;GAChB,GAAG;GACH;GACA;GACD;EAED,MAAM,eAAe,gBAAgB,eAAe;EACpD,MAAM,eAAe,OAAO,OAAO,aAAa,CAC7C,QAAQ,eAAe,WAAW,KAAK,CACvC,KAAK,eAAe,WAAW,IAAI;AAEtC,SAAO;GACL,MAAM;GACN,SAAS;GACT,QAAQ,SAAS,QAAQ;IAGvB,MAAM,UAAU,IAAI,YAAY;IAChC,MAAM,aAAa,YAAY,SAAS;AAExC,QAAI,UACF,SACE,KACE,SACA,aACA,SACA,qCACD,QACK,OAAO,6BAA6B,EAC1C,EACE,gBAAgB,MAAO,IACxB,CACF;AAGH,WAAO;;GAET,UAAU,MAAM,IAAI;;;;;;;;;IASlB,MAAM,WAAW,GAAG,MAAM,KAAK,EAAE,CAAC;AAElC,QAAI,CAAC,UAAU,SAAS,SAAS,CAAE,QAAO;IAE1C,MAAM,SAAS,MAAM,cAAc,MAAM;KACvC;KACA,SAAS,CACP,CACE,6BACA;MACE;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA;MACA,wBAAwB;MACxB;MACD,CACF,CACF;KACD,YAAY;MACV,YAAY;MACZ,6BAA6B;MAC7B,SAAS;OACP;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACA;OACD;MACF;KACF,CAAC;AAEF,QAAI,QAAQ,KACV,QAAO;KACL,MAAM,OAAO;KACb,KAAK,OAAO;KACb;;GAGN;UACM,OAAO;AACd,UAAQ,KAAK,0CAA0C,MAAM;AAE7D,SAAO"}
@@ -0,0 +1,48 @@
1
+ import { GetConfigurationOptions } from "@intlayer/config";
2
+ import { CompilerConfig } from "@intlayer/types";
3
+
4
+ //#region src/IntlayerCompilerPlugin.d.ts
5
+
6
+ /**
7
+ * Mode of the compiler
8
+ * - 'dev': Development mode with HMR support
9
+ * - 'build': Production build mode
10
+ */
11
+ type CompilerMode = 'dev' | 'build';
12
+ /**
13
+ * Options for initializing the compiler
14
+ */
15
+ type IntlayerCompilerOptions = {
16
+ /**
17
+ * Configuration options for getting the intlayer configuration
18
+ */
19
+ configOptions?: GetConfigurationOptions;
20
+ /**
21
+ * Custom compiler configuration to override defaults
22
+ */
23
+ compilerConfig?: Partial<CompilerConfig>;
24
+ };
25
+ /**
26
+ * Create an IntlayerCompiler - A Vite-compatible compiler plugin for Intlayer
27
+ *
28
+ * This autonomous compiler handles:
29
+ * - Configuration loading and management
30
+ * - Hot Module Replacement (HMR) for content changes
31
+ * - File transformation with content extraction
32
+ * - Dictionary persistence and building
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * // vite.config.ts
37
+ * import { defineConfig } from 'vite';
38
+ * import { intlayerCompiler } from 'vite-intlayer';
39
+ *
40
+ * export default defineConfig({
41
+ * plugins: [intlayerCompiler()],
42
+ * });
43
+ * ```
44
+ */
45
+ declare const intlayerCompiler: (options?: IntlayerCompilerOptions) => any;
46
+ //#endregion
47
+ export { CompilerMode, IntlayerCompilerOptions, intlayerCompiler };
48
+ //# sourceMappingURL=IntlayerCompilerPlugin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"IntlayerCompilerPlugin.d.ts","names":[],"sources":["../../src/IntlayerCompilerPlugin.ts"],"sourcesContent":[],"mappings":";;;;;;;AA+CA;AAKA;;AAS2B,KAdf,YAAA,GAce,KAAA,GAAA,OAAA;;;AAuB3B;KAhCY,uBAAA;;;;kBAIM;;;;mBAKC,QAAQ;;;;;;;;;;;;;;;;;;;;;;cAuBd,6BAA8B"}
@@ -1,4 +1,5 @@
1
+ import { CompilerMode, IntlayerCompilerOptions, intlayerCompiler } from "./IntlayerCompilerPlugin.js";
1
2
  import { intLayerPlugin, intlayer, intlayerPlugin } from "./intlayerPlugin.js";
2
3
  import { intLayerMiddlewarePlugin, intlayerMiddleware, intlayerProxy } from "./intlayerProxyPlugin.js";
3
4
  import { intlayerPrune } from "./intlayerPrunePlugin.js";
4
- export { intLayerMiddlewarePlugin, intLayerPlugin, intlayer, intlayerMiddleware, intlayerPlugin, intlayerProxy, intlayerPrune };
5
+ export { CompilerMode, IntlayerCompilerOptions, intLayerMiddlewarePlugin, intLayerPlugin, intlayer, intlayerCompiler, intlayerMiddleware, intlayerPlugin, intlayerProxy, intlayerPrune };
@@ -1,5 +1,5 @@
1
- import { PluginOption } from "vite";
2
1
  import { IntlayerConfig } from "@intlayer/types";
2
+ import { PluginOption } from "vite";
3
3
 
4
4
  //#region src/intlayerPrunePlugin.d.ts
5
5
  declare const intlayerPrune: (intlayerConfig: IntlayerConfig) => PluginOption;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vite-intlayer",
3
- "version": "7.3.1",
3
+ "version": "7.3.2-canary.0",
4
4
  "private": false,
5
5
  "description": "A Vite plugin for seamless internationalization (i18n), providing locale detection, redirection, and environment-based configuration",
6
6
  "keywords": [
@@ -58,6 +58,7 @@
58
58
  "./package.json"
59
59
  ],
60
60
  "scripts": {
61
+ "_prepublish": "cp -f ../../README.md ./README.md",
61
62
  "build": "tsdown --config tsdown.config.ts",
62
63
  "build:ci": "tsdown --config tsdown.config.ts",
63
64
  "clean": "rimraf ./dist .turbo",
@@ -66,7 +67,7 @@
66
67
  "format:fix": "biome format --write .",
67
68
  "lint": "biome lint .",
68
69
  "lint:fix": "biome lint --write .",
69
- "prepublish": "cp -f ../../README.md ./README.md",
70
+ "prepublish": "echo prepublish temporally disabled to avoid rewrite readme",
70
71
  "publish": "bun publish || true",
71
72
  "publish:canary": "bun publish --access public --tag canary || true",
72
73
  "publish:latest": "bun publish --access public --tag latest || true",
@@ -76,14 +77,14 @@
76
77
  },
77
78
  "dependencies": {
78
79
  "@babel/core": "7.28.4",
79
- "@intlayer/babel": "7.3.1",
80
- "@intlayer/chokidar": "7.3.1",
81
- "@intlayer/config": "7.3.1",
82
- "@intlayer/core": "7.3.1",
83
- "@intlayer/dictionaries-entry": "7.3.1",
84
- "@intlayer/types": "7.3.1",
80
+ "@intlayer/babel": "7.3.2-canary.0",
81
+ "@intlayer/chokidar": "7.3.2-canary.0",
82
+ "@intlayer/config": "7.3.2-canary.0",
83
+ "@intlayer/core": "7.3.2-canary.0",
84
+ "@intlayer/dictionaries-entry": "7.3.2-canary.0",
85
+ "@intlayer/types": "7.3.2-canary.0",
85
86
  "fast-glob": "3.3.3",
86
- "intlayer": "7.3.1"
87
+ "intlayer": "7.3.2-canary.0"
87
88
  },
88
89
  "devDependencies": {
89
90
  "@types/node": "24.10.1",
@@ -97,11 +98,19 @@
97
98
  },
98
99
  "peerDependencies": {
99
100
  "@babel/core": ">=6.0.0",
101
+ "@intlayer/svelte-compiler": "7.3.2-canary.0",
102
+ "@intlayer/vue-compiler": "7.3.2-canary.0",
100
103
  "vite": ">=4.0.0"
101
104
  },
102
105
  "peerDependenciesMeta": {
103
106
  "@babel/core": {
104
107
  "optional": true
108
+ },
109
+ "@intlayer/svelte-compiler": {
110
+ "optional": true
111
+ },
112
+ "@intlayer/vue-compiler": {
113
+ "optional": true
105
114
  }
106
115
  },
107
116
  "engines": {