@intlayer/babel 5.5.3 → 5.5.5
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/dist/cjs/babel-plugin-intlayer.cjs +94 -17
- package/dist/cjs/babel-plugin-intlayer.cjs.map +1 -1
- package/dist/esm/babel-plugin-intlayer.mjs +94 -17
- package/dist/esm/babel-plugin-intlayer.mjs.map +1 -1
- package/dist/types/babel-plugin-intlayer.d.ts +64 -11
- package/dist/types/babel-plugin-intlayer.d.ts.map +1 -1
- package/package.json +8 -8
|
@@ -50,12 +50,27 @@ const PACKAGE_LIST = [
|
|
|
50
50
|
"solid-intlayer"
|
|
51
51
|
];
|
|
52
52
|
const CALLER_LIST = ["useIntlayer", "getIntlayer"];
|
|
53
|
+
const PACKAGE_LIST_DYNAMIC = [
|
|
54
|
+
"react-intlayer",
|
|
55
|
+
"react-intlayer/client",
|
|
56
|
+
"react-intlayer/server",
|
|
57
|
+
"next-intlayer",
|
|
58
|
+
"next-intlayer/client",
|
|
59
|
+
"next-intlayer/server"
|
|
60
|
+
];
|
|
61
|
+
const STATIC_IMPORT_FUNCTION = {
|
|
62
|
+
getIntlayer: "getDictionary",
|
|
63
|
+
useIntlayer: "useDictionary"
|
|
64
|
+
};
|
|
65
|
+
const DYNAMIC_IMPORT_FUNCTION = {
|
|
66
|
+
useIntlayer: "useDictionaryDynamic"
|
|
67
|
+
};
|
|
53
68
|
const makeIdent = (key) => {
|
|
54
69
|
const hash = (0, import_chokidar.getFileHash)(key);
|
|
55
70
|
return t.identifier(`_${hash}`);
|
|
56
71
|
};
|
|
57
|
-
const computeRelativeImport = (fromFile,
|
|
58
|
-
const jsonPath = (0, import_node_path.join)(
|
|
72
|
+
const computeRelativeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, key, isDynamic = false) => {
|
|
73
|
+
const jsonPath = isDynamic ? (0, import_node_path.join)(dynamicDictionariesDir, `${key}.mjs`) : (0, import_node_path.join)(dictionariesDir, `${key}.json`);
|
|
59
74
|
let rel = (0, import_node_path.relative)((0, import_node_path.dirname)(fromFile), jsonPath).replace(/\\/g, "/");
|
|
60
75
|
if (!rel.startsWith("./") && !rel.startsWith("../")) rel = `./${rel}`;
|
|
61
76
|
return rel;
|
|
@@ -64,9 +79,20 @@ const intlayerBabelPlugin = () => {
|
|
|
64
79
|
return {
|
|
65
80
|
name: "babel-plugin-intlayer-transform",
|
|
66
81
|
pre() {
|
|
67
|
-
this.
|
|
82
|
+
this._newStaticImports = /* @__PURE__ */ new Map();
|
|
83
|
+
this._newDynamicImports = /* @__PURE__ */ new Map();
|
|
84
|
+
this._isIncluded = true;
|
|
68
85
|
this._hasValidImport = false;
|
|
69
86
|
this._isDictEntry = false;
|
|
87
|
+
this._useDynamicHelpers = false;
|
|
88
|
+
const filename = this.file.opts.filename;
|
|
89
|
+
if (this.opts.filesList && filename) {
|
|
90
|
+
const isIncluded = this.opts.filesList.includes(filename);
|
|
91
|
+
if (!isIncluded) {
|
|
92
|
+
this._isIncluded = false;
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
70
96
|
},
|
|
71
97
|
visitor: {
|
|
72
98
|
/* 0. If this file *is* the dictionaries entry, short-circuit: export {} */
|
|
@@ -85,11 +111,36 @@ const intlayerBabelPlugin = () => {
|
|
|
85
111
|
exit(programPath, state) {
|
|
86
112
|
if (state._isDictEntry) return;
|
|
87
113
|
if (!state._hasValidImport) return;
|
|
114
|
+
if (!state._isIncluded) return;
|
|
88
115
|
const file = state.file.opts.filename;
|
|
89
|
-
const
|
|
116
|
+
const dictionariesDir = state.opts.dictionariesDir;
|
|
117
|
+
const dynamicDictionariesDir = state.opts.dynamicDictionariesDir;
|
|
90
118
|
const imports = [];
|
|
91
|
-
for (const [key, ident] of state.
|
|
92
|
-
const rel = computeRelativeImport(
|
|
119
|
+
for (const [key, ident] of state._newStaticImports) {
|
|
120
|
+
const rel = computeRelativeImport(
|
|
121
|
+
file,
|
|
122
|
+
dictionariesDir,
|
|
123
|
+
dynamicDictionariesDir,
|
|
124
|
+
key,
|
|
125
|
+
false
|
|
126
|
+
// Always static
|
|
127
|
+
);
|
|
128
|
+
imports.push(
|
|
129
|
+
t.importDeclaration(
|
|
130
|
+
[t.importDefaultSpecifier(t.identifier(ident.name))],
|
|
131
|
+
t.stringLiteral(rel)
|
|
132
|
+
)
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
for (const [key, ident] of state._newDynamicImports) {
|
|
136
|
+
const rel = computeRelativeImport(
|
|
137
|
+
file,
|
|
138
|
+
dictionariesDir,
|
|
139
|
+
dynamicDictionariesDir,
|
|
140
|
+
key,
|
|
141
|
+
true
|
|
142
|
+
// Always dynamic
|
|
143
|
+
);
|
|
93
144
|
imports.push(
|
|
94
145
|
t.importDeclaration(
|
|
95
146
|
[t.importDefaultSpecifier(t.identifier(ident.name))],
|
|
@@ -102,7 +153,7 @@ const intlayerBabelPlugin = () => {
|
|
|
102
153
|
let insertPos = 0;
|
|
103
154
|
for (const stmtPath of bodyPaths) {
|
|
104
155
|
const stmt = stmtPath.node;
|
|
105
|
-
if (t.isExpressionStatement(stmt) && t.isStringLiteral(stmt.expression) &&
|
|
156
|
+
if (t.isExpressionStatement(stmt) && t.isStringLiteral(stmt.expression) && !stmt.expression.value.startsWith("import") && !stmt.expression.value.startsWith("require")) {
|
|
106
157
|
insertPos += 1;
|
|
107
158
|
} else {
|
|
108
159
|
break;
|
|
@@ -120,14 +171,22 @@ const intlayerBabelPlugin = () => {
|
|
|
120
171
|
for (const spec of path.node.specifiers) {
|
|
121
172
|
if (!t.isImportSpecifier(spec)) continue;
|
|
122
173
|
const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
174
|
+
const activateDynamicImport = state.opts.activateDynamicImport;
|
|
175
|
+
const shouldUseDynamicHelpers = activateDynamicImport && PACKAGE_LIST_DYNAMIC.includes(src);
|
|
176
|
+
if (shouldUseDynamicHelpers) {
|
|
177
|
+
state._useDynamicHelpers = true;
|
|
178
|
+
}
|
|
179
|
+
const helperMap = shouldUseDynamicHelpers ? {
|
|
180
|
+
...STATIC_IMPORT_FUNCTION,
|
|
181
|
+
...DYNAMIC_IMPORT_FUNCTION
|
|
182
|
+
} : STATIC_IMPORT_FUNCTION;
|
|
183
|
+
const newIdentifier = helperMap[importedName];
|
|
184
|
+
if (newIdentifier) {
|
|
185
|
+
spec.imported = t.identifier(newIdentifier);
|
|
127
186
|
}
|
|
128
187
|
}
|
|
129
188
|
},
|
|
130
|
-
/* 2. Replace calls: useIntlayer("foo") → useDictionary(_hash) */
|
|
189
|
+
/* 2. Replace calls: useIntlayer("foo") → useDictionary(_hash) or useDictionaryDynamic(_hash, "foo") */
|
|
131
190
|
CallExpression(path, state) {
|
|
132
191
|
if (state._isDictEntry) return;
|
|
133
192
|
const callee = path.node.callee;
|
|
@@ -137,12 +196,30 @@ const intlayerBabelPlugin = () => {
|
|
|
137
196
|
const arg = path.node.arguments[0];
|
|
138
197
|
if (!arg || !t.isStringLiteral(arg)) return;
|
|
139
198
|
const key = arg.value;
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
199
|
+
const useDynamic = Boolean(state._useDynamicHelpers);
|
|
200
|
+
const shouldUseDynamicForThisCall = callee.name === "useIntlayer" && useDynamic;
|
|
201
|
+
let ident;
|
|
202
|
+
if (shouldUseDynamicForThisCall) {
|
|
203
|
+
let dynamicIdent = state._newDynamicImports.get(key);
|
|
204
|
+
if (!dynamicIdent) {
|
|
205
|
+
const hash = (0, import_chokidar.getFileHash)(key);
|
|
206
|
+
dynamicIdent = t.identifier(`_${hash}_dyn`);
|
|
207
|
+
state._newDynamicImports.set(key, dynamicIdent);
|
|
208
|
+
}
|
|
209
|
+
ident = dynamicIdent;
|
|
210
|
+
path.node.arguments = [
|
|
211
|
+
t.identifier(ident.name),
|
|
212
|
+
...path.node.arguments
|
|
213
|
+
];
|
|
214
|
+
} else {
|
|
215
|
+
let staticIdent = state._newStaticImports.get(key);
|
|
216
|
+
if (!staticIdent) {
|
|
217
|
+
staticIdent = makeIdent(key);
|
|
218
|
+
state._newStaticImports.set(key, staticIdent);
|
|
219
|
+
}
|
|
220
|
+
ident = staticIdent;
|
|
221
|
+
path.node.arguments[0] = t.identifier(ident.name);
|
|
144
222
|
}
|
|
145
|
-
path.node.arguments[0] = t.identifier(ident.name);
|
|
146
223
|
}
|
|
147
224
|
}
|
|
148
225
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/babel-plugin-intlayer.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from '@babel/core';\nimport * as t from '@babel/types';\nimport { getFileHash } from '@intlayer/chokidar';\nimport { dirname, join, relative } from 'node:path';\n\n/* ────────────────────────────────────────── constants ───────────────────── */\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer'] as const;\n\n/* ────────────────────────────────────────── types ───────────────────────── */\n\ntype State = PluginPass & {\n opts: { dictionariesDir: string; dictionariesEntryPath: string };\n /** map key → generated ident (per-file) */\n _newImports?: Map<string, t.Identifier>;\n /** whether the current file imported *any* intlayer package */\n _hasValidImport?: boolean;\n /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\n/**\n * Replicates the xxHash64 → Base-62 algorithm used by the SWC version\n * and prefixes an underscore so the generated identifiers never collide\n * with user-defined ones.\n */\nconst makeIdent = (key: string): t.Identifier => {\n const hash = getFileHash(key);\n return t.identifier(`_${hash}`);\n};\n\nconst computeRelativeImport = (\n fromFile: string,\n dictDir: string,\n key: string\n): string => {\n const jsonPath = join(dictDir, `${key}.json`);\n let rel = relative(dirname(fromFile), jsonPath).replace(/\\\\/g, '/'); // win →\n if (!rel.startsWith('./') && !rel.startsWith('../')) rel = `./${rel}`;\n return rel;\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\n/**\n * Babel plugin that transforms `useIntlayer/getIntlayer` calls into\n * `useDictionary/getDictionary` and auto-imports the required JSON dictionaries.\n *\n * **New behaviour**: if the currently processed file matches `dictionariesEntryPath`,\n * its entire contents are replaced with a simple `export default {}` so that it\n * never contains stale or circular references.\n *\n * The **critical detail** (bug-fix) is that we still **only rewrite** an import\n * specifier when its *imported* name is `useIntlayer`/`getIntlayer`.\n *\n * This means cases like:\n * ```ts\n * import { useDictionary as useIntlayer } from 'react-intlayer';\n * ```\n * —where `useIntlayer` is merely an *alias* or re-export—are left untouched\n * because `imported.name` is `useDictionary`.\n */\nexport const intlayerBabelPlugin = (): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._newImports = new Map();\n this._hasValidImport = false;\n this._isDictEntry = false;\n },\n\n visitor: {\n /* 0. If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n const filename = state.file.opts.filename!;\n if (filename === state.opts.dictionariesEntryPath) {\n state._isDictEntry = true;\n // Replace all existing statements with: export default {}\n programPath.node.body = [\n t.exportDefaultDeclaration(t.objectExpression([])),\n ];\n // Stop further traversal for this plugin – nothing else to transform\n programPath.stop();\n }\n },\n\n /* 3. After full traversal, inject the JSON dictionary imports. */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n if (!state._hasValidImport) return; // early-out if we touched nothing\n\n const file = state.file.opts.filename!;\n const dictDir = state.opts.dictionariesDir;\n const imports: t.ImportDeclaration[] = [];\n\n for (const [key, ident] of state._newImports!) {\n const rel = computeRelativeImport(file, dictDir, key);\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n if (!imports.length) return;\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n const bodyPaths = programPath.get('body') as NodePath<t.Statement>[];\n let insertPos = 0;\n for (const stmtPath of bodyPaths) {\n const stmt = stmtPath.node;\n if (\n t.isExpressionStatement(stmt) &&\n t.isStringLiteral(stmt.expression) &&\n (stmt.expression.value === 'use client' ||\n stmt.expression.value === 'use server')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n programPath.node.body.splice(insertPos, 0, ...imports);\n },\n },\n\n /* 1. Inspect *every* intlayer import. */\n ImportDeclaration(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const src = path.node.source.value;\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Mark that we do import from an intlayer package in this file; this is\n // enough to know that we *might* need to inject runtime helpers later.\n state._hasValidImport = true;\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n // ⚠️ We now key off *imported* name, *not* local name.\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as t.StringLiteral).value;\n\n if (importedName === 'useIntlayer') {\n spec.imported = t.identifier('useDictionary');\n } else if (importedName === 'getIntlayer') {\n spec.imported = t.identifier('getDictionary');\n }\n }\n },\n\n /* 2. Replace calls: useIntlayer(\"foo\") → useDictionary(_hash) */\n CallExpression(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee)) return;\n if (!CALLER_LIST.includes(callee.name as any)) return;\n\n // Ensure we ultimately emit helper imports for files that *invoke*\n // the hooks, even if they didn’t import them directly (edge cases with\n // re-exports).\n state._hasValidImport = true;\n\n const arg = path.node.arguments[0];\n if (!arg || !t.isStringLiteral(arg)) return; // must be literal\n\n const key = arg.value;\n // per-file cache\n let ident = state._newImports!.get(key);\n if (!ident) {\n ident = makeIdent(key);\n state._newImports!.set(key, ident);\n }\n\n // replace first arg with ident\n path.node.arguments[0] = t.identifier(ident.name);\n },\n },\n };\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/babel-plugin-intlayer.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from '@babel/core';\nimport * as t from '@babel/types';\nimport { getFileHash } from '@intlayer/chokidar';\nimport { dirname, join, relative } from 'node:path';\n\n/* ────────────────────────────────────────── constants ───────────────────── */\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer'] as const;\n\n/**\n * Packages that support dynamic import\n */\nconst PACKAGE_LIST_DYNAMIC = [\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n] as const;\n\nconst STATIC_IMPORT_FUNCTION = {\n getIntlayer: 'getDictionary',\n useIntlayer: 'useDictionary',\n} as const;\n\nconst DYNAMIC_IMPORT_FUNCTION = {\n useIntlayer: 'useDictionaryDynamic',\n} as const;\n\n/* ────────────────────────────────────────── types ───────────────────────── */\n\ntype State = PluginPass & {\n opts: {\n /**\n * The path to the dictionaries directory.\n */\n dictionariesDir: string;\n /**\n * The path to the dictionaries entry file.\n */\n dictionariesEntryPath: string;\n /**\n * The path to the dictionaries directory.\n */\n dynamicDictionariesDir: string;\n /**\n * The path to the dynamic dictionaries entry file.\n */\n dynamicDictionariesEntryPath: string;\n /**\n * If true, the plugin will activate the dynamic import of the dictionaries.\n */\n activateDynamicImport?: boolean;\n /**\n * Files list to traverse.\n */\n filesList?: string[];\n };\n /** map key → generated ident (per-file) for static imports */\n _newStaticImports?: Map<string, t.Identifier>;\n /** map key → generated ident (per-file) for dynamic imports */\n _newDynamicImports?: Map<string, t.Identifier>;\n /** whether the current file imported *any* intlayer package */\n _hasValidImport?: boolean;\n /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n /** whether dynamic helpers are active for this file */\n _useDynamicHelpers?: boolean;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\n/**\n * Replicates the xxHash64 → Base-62 algorithm used by the SWC version\n * and prefixes an underscore so the generated identifiers never collide\n * with user-defined ones.\n */\nconst makeIdent = (key: string): t.Identifier => {\n const hash = getFileHash(key);\n return t.identifier(`_${hash}`);\n};\n\nconst computeRelativeImport = (\n fromFile: string,\n dictionariesDir: string,\n dynamicDictionariesDir: string,\n key: string,\n isDynamic = false\n): string => {\n const jsonPath = isDynamic\n ? join(dynamicDictionariesDir, `${key}.mjs`)\n : join(dictionariesDir, `${key}.json`);\n\n let rel = relative(dirname(fromFile), jsonPath).replace(/\\\\/g, '/'); // win →\n if (!rel.startsWith('./') && !rel.startsWith('../')) rel = `./${rel}`;\n return rel;\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\n/**\n * Babel plugin that transforms `useIntlayer/getIntlayer` calls into\n * `useDictionary/getDictionary` and auto-imports the required JSON dictionaries.\n *\n *\n * This means cases like:\n *\n * ```ts\n * import { getIntlayer } from 'intlayer';\n * import { useIntlayer } from 'react-intlayer';\n *\n * // ...\n *\n * const content1 = getIntlayer('app');\n * const content2 = useIntlayer('app');\n * ```\n *\n * will be transformed into:\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.mjs';\n * import { getDictionary as getIntlayer } from 'intlayer';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n *\n * // ...\n *\n * const content1 = getIntlayer(_dicHash);\n * const content2 = useIntlayer(_dicHash)\n * ```\n *\n * Or if the `activateDynamicImport` option is enabled:\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import _dicHash_dyn from '../../.intlayer/dictionaries/app.mjs';\n *\n * import { useDictionary as getIntlayer } from 'intlayer';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n *\n * // ...\n *\n * const content1 = getIntlayer(_dicHash);\n * const content2 = useIntlayer(_dicHash_dyn, 'app');\n * ```\n */\nexport const intlayerBabelPlugin = (): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._newStaticImports = new Map();\n this._newDynamicImports = new Map();\n this._isIncluded = true;\n this._hasValidImport = false;\n this._isDictEntry = false;\n this._useDynamicHelpers = false;\n\n // If filesList is provided, check if current file is included\n const filename = this.file.opts.filename;\n if (this.opts.filesList && filename) {\n const isIncluded = this.opts.filesList.includes(filename);\n\n if (!isIncluded) {\n // Force _isIncluded to false to skip processing\n this._isIncluded = false;\n return;\n }\n }\n },\n\n visitor: {\n /* 0. If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n const filename = state.file.opts.filename!;\n if (filename === state.opts.dictionariesEntryPath) {\n state._isDictEntry = true;\n // Replace all existing statements with: export default {}\n programPath.node.body = [\n t.exportDefaultDeclaration(t.objectExpression([])),\n ];\n // Stop further traversal for this plugin – nothing else to transform\n programPath.stop();\n }\n },\n\n /* 3. After full traversal, inject the JSON dictionary imports. */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n if (!state._hasValidImport) return; // early-out if we touched nothing\n if (!state._isIncluded) return; // early-out if file is not included\n\n const file = state.file.opts.filename!;\n const dictionariesDir = state.opts.dictionariesDir;\n const dynamicDictionariesDir = state.opts.dynamicDictionariesDir;\n const imports: t.ImportDeclaration[] = [];\n\n // Generate static imports (for getIntlayer and useIntlayer when not using dynamic)\n for (const [key, ident] of state._newStaticImports!) {\n const rel = computeRelativeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n key,\n false // Always static\n );\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n // Generate dynamic imports (for useIntlayer when using dynamic helpers)\n for (const [key, ident] of state._newDynamicImports!) {\n const rel = computeRelativeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n key,\n true // Always dynamic\n );\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n if (!imports.length) return;\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n const bodyPaths = programPath.get('body') as NodePath<t.Statement>[];\n let insertPos = 0;\n for (const stmtPath of bodyPaths) {\n const stmt = stmtPath.node;\n if (\n t.isExpressionStatement(stmt) &&\n t.isStringLiteral(stmt.expression) &&\n !stmt.expression.value.startsWith('import') &&\n !stmt.expression.value.startsWith('require')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n programPath.node.body.splice(insertPos, 0, ...imports);\n },\n },\n\n /* 1. Inspect *every* intlayer import. */\n ImportDeclaration(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const src = path.node.source.value;\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Mark that we do import from an intlayer package in this file; this is\n // enough to know that we *might* need to inject runtime helpers later.\n state._hasValidImport = true;\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n // ⚠️ We now key off *imported* name, *not* local name.\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as t.StringLiteral).value;\n\n const activateDynamicImport = state.opts.activateDynamicImport;\n // Determine whether this import should use the dynamic helpers. We\n // only switch to the dynamic helpers when (1) the option is turned\n // on AND (2) the package we are importing from supports the dynamic\n // helpers.\n const shouldUseDynamicHelpers =\n activateDynamicImport && PACKAGE_LIST_DYNAMIC.includes(src as any);\n\n // Remember for later (CallExpression) whether we are using the dynamic helpers\n if (shouldUseDynamicHelpers) {\n state._useDynamicHelpers = true;\n }\n\n const helperMap = shouldUseDynamicHelpers\n ? ({\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n } as Record<string, string>)\n : (STATIC_IMPORT_FUNCTION as Record<string, string>);\n\n const newIdentifier = helperMap[importedName];\n\n // Only rewrite when we actually have a mapping for the imported\n // specifier (ignore unrelated named imports).\n if (newIdentifier) {\n // Keep the local alias intact (so calls remain `useIntlayer` /\n // `getIntlayer`), but rewrite the imported identifier so it\n // points to our helper implementation.\n spec.imported = t.identifier(newIdentifier);\n }\n }\n },\n\n /* 2. Replace calls: useIntlayer(\"foo\") → useDictionary(_hash) or useDictionaryDynamic(_hash, \"foo\") */\n CallExpression(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee)) return;\n if (!CALLER_LIST.includes(callee.name as any)) return;\n\n // Ensure we ultimately emit helper imports for files that *invoke*\n // the hooks, even if they didn't import them directly (edge cases with\n // re-exports).\n state._hasValidImport = true;\n\n const arg = path.node.arguments[0];\n if (!arg || !t.isStringLiteral(arg)) return; // must be literal\n\n const key = arg.value;\n const useDynamic = Boolean(state._useDynamicHelpers);\n\n // Determine if this specific call should use dynamic imports\n const shouldUseDynamicForThisCall =\n callee.name === 'useIntlayer' && useDynamic;\n\n let ident: t.Identifier;\n\n if (shouldUseDynamicForThisCall) {\n // Use dynamic imports for useIntlayer when dynamic helpers are enabled\n let dynamicIdent = state._newDynamicImports!.get(key);\n if (!dynamicIdent) {\n // Create a unique identifier for dynamic imports by appending a suffix\n const hash = getFileHash(key);\n dynamicIdent = t.identifier(`_${hash}_dyn`);\n state._newDynamicImports!.set(key, dynamicIdent);\n }\n ident = dynamicIdent;\n\n // Dynamic helper: first argument is the dictionary, second is the key.\n path.node.arguments = [\n t.identifier(ident.name),\n ...path.node.arguments,\n ];\n } else {\n // Use static imports for getIntlayer or useIntlayer when not using dynamic helpers\n let staticIdent = state._newStaticImports!.get(key);\n if (!staticIdent) {\n staticIdent = makeIdent(key);\n state._newStaticImports!.set(key, staticIdent);\n }\n ident = staticIdent;\n\n // Static helper (useDictionary / getDictionary): replace key with ident.\n path.node.arguments[0] = t.identifier(ident.name);\n }\n },\n },\n };\n};\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,QAAmB;AACnB,sBAA4B;AAC5B,uBAAwC;AAIxC,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,cAAc,CAAC,eAAe,aAAa;AAKjD,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,yBAAyB;AAAA,EAC7B,aAAa;AAAA,EACb,aAAa;AACf;AAEA,MAAM,0BAA0B;AAAA,EAC9B,aAAa;AACf;AAkDA,MAAM,YAAY,CAAC,QAA8B;AAC/C,QAAM,WAAO,6BAAY,GAAG;AAC5B,SAAO,EAAE,WAAW,IAAI,IAAI,EAAE;AAChC;AAEA,MAAM,wBAAwB,CAC5B,UACA,iBACA,wBACA,KACA,YAAY,UACD;AACX,QAAM,WAAW,gBACb,uBAAK,wBAAwB,GAAG,GAAG,MAAM,QACzC,uBAAK,iBAAiB,GAAG,GAAG,OAAO;AAEvC,MAAI,UAAM,+BAAS,0BAAQ,QAAQ,GAAG,QAAQ,EAAE,QAAQ,OAAO,GAAG;AAClE,MAAI,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,EAAG,OAAM,KAAK,GAAG;AACnE,SAAO;AACT;AAiDO,MAAM,sBAAsB,MAAwB;AACzD,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,MAAM;AACJ,WAAK,oBAAoB,oBAAI,IAAI;AACjC,WAAK,qBAAqB,oBAAI,IAAI;AAClC,WAAK,cAAc;AACnB,WAAK,kBAAkB;AACvB,WAAK,eAAe;AACpB,WAAK,qBAAqB;AAG1B,YAAM,WAAW,KAAK,KAAK,KAAK;AAChC,UAAI,KAAK,KAAK,aAAa,UAAU;AACnC,cAAM,aAAa,KAAK,KAAK,UAAU,SAAS,QAAQ;AAExD,YAAI,CAAC,YAAY;AAEf,eAAK,cAAc;AACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,SAAS;AAAA;AAAA,MAEP,SAAS;AAAA,QACP,MAAM,aAAa,OAAO;AACxB,gBAAM,WAAW,MAAM,KAAK,KAAK;AACjC,cAAI,aAAa,MAAM,KAAK,uBAAuB;AACjD,kBAAM,eAAe;AAErB,wBAAY,KAAK,OAAO;AAAA,cACtB,EAAE,yBAAyB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAAA,YACnD;AAEA,wBAAY,KAAK;AAAA,UACnB;AAAA,QACF;AAAA;AAAA,QAGA,KAAK,aAAa,OAAO;AACvB,cAAI,MAAM,aAAc;AACxB,cAAI,CAAC,MAAM,gBAAiB;AAC5B,cAAI,CAAC,MAAM,YAAa;AAExB,gBAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,gBAAM,kBAAkB,MAAM,KAAK;AACnC,gBAAM,yBAAyB,MAAM,KAAK;AAC1C,gBAAM,UAAiC,CAAC;AAGxC,qBAAW,CAAC,KAAK,KAAK,KAAK,MAAM,mBAAoB;AACnD,kBAAM,MAAM;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,YACF;AACA,oBAAQ;AAAA,cACN,EAAE;AAAA,gBACA,CAAC,EAAE,uBAAuB,EAAE,WAAW,MAAM,IAAI,CAAC,CAAC;AAAA,gBACnD,EAAE,cAAc,GAAG;AAAA,cACrB;AAAA,YACF;AAAA,UACF;AAGA,qBAAW,CAAC,KAAK,KAAK,KAAK,MAAM,oBAAqB;AACpD,kBAAM,MAAM;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,YACF;AACA,oBAAQ;AAAA,cACN,EAAE;AAAA,gBACA,CAAC,EAAE,uBAAuB,EAAE,WAAW,MAAM,IAAI,CAAC,CAAC;AAAA,gBACnD,EAAE,cAAc,GAAG;AAAA,cACrB;AAAA,YACF;AAAA,UACF;AAEA,cAAI,CAAC,QAAQ,OAAQ;AAGrB,gBAAM,YAAY,YAAY,IAAI,MAAM;AACxC,cAAI,YAAY;AAChB,qBAAW,YAAY,WAAW;AAChC,kBAAM,OAAO,SAAS;AACtB,gBACE,EAAE,sBAAsB,IAAI,KAC5B,EAAE,gBAAgB,KAAK,UAAU,KACjC,CAAC,KAAK,WAAW,MAAM,WAAW,QAAQ,KAC1C,CAAC,KAAK,WAAW,MAAM,WAAW,SAAS,GAC3C;AACA,2BAAa;AAAA,YACf,OAAO;AACL;AAAA,YACF;AAAA,UACF;AAEA,sBAAY,KAAK,KAAK,OAAO,WAAW,GAAG,GAAG,OAAO;AAAA,QACvD;AAAA,MACF;AAAA;AAAA,MAGA,kBAAkB,MAAM,OAAO;AAC7B,YAAI,MAAM,aAAc;AAExB,cAAM,MAAM,KAAK,KAAK,OAAO;AAC7B,YAAI,CAAC,aAAa,SAAS,GAAG,EAAG;AAIjC,cAAM,kBAAkB;AAExB,mBAAW,QAAQ,KAAK,KAAK,YAAY;AACvC,cAAI,CAAC,EAAE,kBAAkB,IAAI,EAAG;AAGhC,gBAAM,eAAe,EAAE,aAAa,KAAK,QAAQ,IAC7C,KAAK,SAAS,OACb,KAAK,SAA6B;AAEvC,gBAAM,wBAAwB,MAAM,KAAK;AAKzC,gBAAM,0BACJ,yBAAyB,qBAAqB,SAAS,GAAU;AAGnE,cAAI,yBAAyB;AAC3B,kBAAM,qBAAqB;AAAA,UAC7B;AAEA,gBAAM,YAAY,0BACb;AAAA,YACC,GAAG;AAAA,YACH,GAAG;AAAA,UACL,IACC;AAEL,gBAAM,gBAAgB,UAAU,YAAY;AAI5C,cAAI,eAAe;AAIjB,iBAAK,WAAW,EAAE,WAAW,aAAa;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,eAAe,MAAM,OAAO;AAC1B,YAAI,MAAM,aAAc;AAExB,cAAM,SAAS,KAAK,KAAK;AACzB,YAAI,CAAC,EAAE,aAAa,MAAM,EAAG;AAC7B,YAAI,CAAC,YAAY,SAAS,OAAO,IAAW,EAAG;AAK/C,cAAM,kBAAkB;AAExB,cAAM,MAAM,KAAK,KAAK,UAAU,CAAC;AACjC,YAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,EAAG;AAErC,cAAM,MAAM,IAAI;AAChB,cAAM,aAAa,QAAQ,MAAM,kBAAkB;AAGnD,cAAM,8BACJ,OAAO,SAAS,iBAAiB;AAEnC,YAAI;AAEJ,YAAI,6BAA6B;AAE/B,cAAI,eAAe,MAAM,mBAAoB,IAAI,GAAG;AACpD,cAAI,CAAC,cAAc;AAEjB,kBAAM,WAAO,6BAAY,GAAG;AAC5B,2BAAe,EAAE,WAAW,IAAI,IAAI,MAAM;AAC1C,kBAAM,mBAAoB,IAAI,KAAK,YAAY;AAAA,UACjD;AACA,kBAAQ;AAGR,eAAK,KAAK,YAAY;AAAA,YACpB,EAAE,WAAW,MAAM,IAAI;AAAA,YACvB,GAAG,KAAK,KAAK;AAAA,UACf;AAAA,QACF,OAAO;AAEL,cAAI,cAAc,MAAM,kBAAmB,IAAI,GAAG;AAClD,cAAI,CAAC,aAAa;AAChB,0BAAc,UAAU,GAAG;AAC3B,kBAAM,kBAAmB,IAAI,KAAK,WAAW;AAAA,UAC/C;AACA,kBAAQ;AAGR,eAAK,KAAK,UAAU,CAAC,IAAI,EAAE,WAAW,MAAM,IAAI;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -17,12 +17,27 @@ const PACKAGE_LIST = [
|
|
|
17
17
|
"solid-intlayer"
|
|
18
18
|
];
|
|
19
19
|
const CALLER_LIST = ["useIntlayer", "getIntlayer"];
|
|
20
|
+
const PACKAGE_LIST_DYNAMIC = [
|
|
21
|
+
"react-intlayer",
|
|
22
|
+
"react-intlayer/client",
|
|
23
|
+
"react-intlayer/server",
|
|
24
|
+
"next-intlayer",
|
|
25
|
+
"next-intlayer/client",
|
|
26
|
+
"next-intlayer/server"
|
|
27
|
+
];
|
|
28
|
+
const STATIC_IMPORT_FUNCTION = {
|
|
29
|
+
getIntlayer: "getDictionary",
|
|
30
|
+
useIntlayer: "useDictionary"
|
|
31
|
+
};
|
|
32
|
+
const DYNAMIC_IMPORT_FUNCTION = {
|
|
33
|
+
useIntlayer: "useDictionaryDynamic"
|
|
34
|
+
};
|
|
20
35
|
const makeIdent = (key) => {
|
|
21
36
|
const hash = getFileHash(key);
|
|
22
37
|
return t.identifier(`_${hash}`);
|
|
23
38
|
};
|
|
24
|
-
const computeRelativeImport = (fromFile,
|
|
25
|
-
const jsonPath = join(
|
|
39
|
+
const computeRelativeImport = (fromFile, dictionariesDir, dynamicDictionariesDir, key, isDynamic = false) => {
|
|
40
|
+
const jsonPath = isDynamic ? join(dynamicDictionariesDir, `${key}.mjs`) : join(dictionariesDir, `${key}.json`);
|
|
26
41
|
let rel = relative(dirname(fromFile), jsonPath).replace(/\\/g, "/");
|
|
27
42
|
if (!rel.startsWith("./") && !rel.startsWith("../")) rel = `./${rel}`;
|
|
28
43
|
return rel;
|
|
@@ -31,9 +46,20 @@ const intlayerBabelPlugin = () => {
|
|
|
31
46
|
return {
|
|
32
47
|
name: "babel-plugin-intlayer-transform",
|
|
33
48
|
pre() {
|
|
34
|
-
this.
|
|
49
|
+
this._newStaticImports = /* @__PURE__ */ new Map();
|
|
50
|
+
this._newDynamicImports = /* @__PURE__ */ new Map();
|
|
51
|
+
this._isIncluded = true;
|
|
35
52
|
this._hasValidImport = false;
|
|
36
53
|
this._isDictEntry = false;
|
|
54
|
+
this._useDynamicHelpers = false;
|
|
55
|
+
const filename = this.file.opts.filename;
|
|
56
|
+
if (this.opts.filesList && filename) {
|
|
57
|
+
const isIncluded = this.opts.filesList.includes(filename);
|
|
58
|
+
if (!isIncluded) {
|
|
59
|
+
this._isIncluded = false;
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
37
63
|
},
|
|
38
64
|
visitor: {
|
|
39
65
|
/* 0. If this file *is* the dictionaries entry, short-circuit: export {} */
|
|
@@ -52,11 +78,36 @@ const intlayerBabelPlugin = () => {
|
|
|
52
78
|
exit(programPath, state) {
|
|
53
79
|
if (state._isDictEntry) return;
|
|
54
80
|
if (!state._hasValidImport) return;
|
|
81
|
+
if (!state._isIncluded) return;
|
|
55
82
|
const file = state.file.opts.filename;
|
|
56
|
-
const
|
|
83
|
+
const dictionariesDir = state.opts.dictionariesDir;
|
|
84
|
+
const dynamicDictionariesDir = state.opts.dynamicDictionariesDir;
|
|
57
85
|
const imports = [];
|
|
58
|
-
for (const [key, ident] of state.
|
|
59
|
-
const rel = computeRelativeImport(
|
|
86
|
+
for (const [key, ident] of state._newStaticImports) {
|
|
87
|
+
const rel = computeRelativeImport(
|
|
88
|
+
file,
|
|
89
|
+
dictionariesDir,
|
|
90
|
+
dynamicDictionariesDir,
|
|
91
|
+
key,
|
|
92
|
+
false
|
|
93
|
+
// Always static
|
|
94
|
+
);
|
|
95
|
+
imports.push(
|
|
96
|
+
t.importDeclaration(
|
|
97
|
+
[t.importDefaultSpecifier(t.identifier(ident.name))],
|
|
98
|
+
t.stringLiteral(rel)
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
for (const [key, ident] of state._newDynamicImports) {
|
|
103
|
+
const rel = computeRelativeImport(
|
|
104
|
+
file,
|
|
105
|
+
dictionariesDir,
|
|
106
|
+
dynamicDictionariesDir,
|
|
107
|
+
key,
|
|
108
|
+
true
|
|
109
|
+
// Always dynamic
|
|
110
|
+
);
|
|
60
111
|
imports.push(
|
|
61
112
|
t.importDeclaration(
|
|
62
113
|
[t.importDefaultSpecifier(t.identifier(ident.name))],
|
|
@@ -69,7 +120,7 @@ const intlayerBabelPlugin = () => {
|
|
|
69
120
|
let insertPos = 0;
|
|
70
121
|
for (const stmtPath of bodyPaths) {
|
|
71
122
|
const stmt = stmtPath.node;
|
|
72
|
-
if (t.isExpressionStatement(stmt) && t.isStringLiteral(stmt.expression) &&
|
|
123
|
+
if (t.isExpressionStatement(stmt) && t.isStringLiteral(stmt.expression) && !stmt.expression.value.startsWith("import") && !stmt.expression.value.startsWith("require")) {
|
|
73
124
|
insertPos += 1;
|
|
74
125
|
} else {
|
|
75
126
|
break;
|
|
@@ -87,14 +138,22 @@ const intlayerBabelPlugin = () => {
|
|
|
87
138
|
for (const spec of path.node.specifiers) {
|
|
88
139
|
if (!t.isImportSpecifier(spec)) continue;
|
|
89
140
|
const importedName = t.isIdentifier(spec.imported) ? spec.imported.name : spec.imported.value;
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
141
|
+
const activateDynamicImport = state.opts.activateDynamicImport;
|
|
142
|
+
const shouldUseDynamicHelpers = activateDynamicImport && PACKAGE_LIST_DYNAMIC.includes(src);
|
|
143
|
+
if (shouldUseDynamicHelpers) {
|
|
144
|
+
state._useDynamicHelpers = true;
|
|
145
|
+
}
|
|
146
|
+
const helperMap = shouldUseDynamicHelpers ? {
|
|
147
|
+
...STATIC_IMPORT_FUNCTION,
|
|
148
|
+
...DYNAMIC_IMPORT_FUNCTION
|
|
149
|
+
} : STATIC_IMPORT_FUNCTION;
|
|
150
|
+
const newIdentifier = helperMap[importedName];
|
|
151
|
+
if (newIdentifier) {
|
|
152
|
+
spec.imported = t.identifier(newIdentifier);
|
|
94
153
|
}
|
|
95
154
|
}
|
|
96
155
|
},
|
|
97
|
-
/* 2. Replace calls: useIntlayer("foo") → useDictionary(_hash) */
|
|
156
|
+
/* 2. Replace calls: useIntlayer("foo") → useDictionary(_hash) or useDictionaryDynamic(_hash, "foo") */
|
|
98
157
|
CallExpression(path, state) {
|
|
99
158
|
if (state._isDictEntry) return;
|
|
100
159
|
const callee = path.node.callee;
|
|
@@ -104,12 +163,30 @@ const intlayerBabelPlugin = () => {
|
|
|
104
163
|
const arg = path.node.arguments[0];
|
|
105
164
|
if (!arg || !t.isStringLiteral(arg)) return;
|
|
106
165
|
const key = arg.value;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
166
|
+
const useDynamic = Boolean(state._useDynamicHelpers);
|
|
167
|
+
const shouldUseDynamicForThisCall = callee.name === "useIntlayer" && useDynamic;
|
|
168
|
+
let ident;
|
|
169
|
+
if (shouldUseDynamicForThisCall) {
|
|
170
|
+
let dynamicIdent = state._newDynamicImports.get(key);
|
|
171
|
+
if (!dynamicIdent) {
|
|
172
|
+
const hash = getFileHash(key);
|
|
173
|
+
dynamicIdent = t.identifier(`_${hash}_dyn`);
|
|
174
|
+
state._newDynamicImports.set(key, dynamicIdent);
|
|
175
|
+
}
|
|
176
|
+
ident = dynamicIdent;
|
|
177
|
+
path.node.arguments = [
|
|
178
|
+
t.identifier(ident.name),
|
|
179
|
+
...path.node.arguments
|
|
180
|
+
];
|
|
181
|
+
} else {
|
|
182
|
+
let staticIdent = state._newStaticImports.get(key);
|
|
183
|
+
if (!staticIdent) {
|
|
184
|
+
staticIdent = makeIdent(key);
|
|
185
|
+
state._newStaticImports.set(key, staticIdent);
|
|
186
|
+
}
|
|
187
|
+
ident = staticIdent;
|
|
188
|
+
path.node.arguments[0] = t.identifier(ident.name);
|
|
111
189
|
}
|
|
112
|
-
path.node.arguments[0] = t.identifier(ident.name);
|
|
113
190
|
}
|
|
114
191
|
}
|
|
115
192
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/babel-plugin-intlayer.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from '@babel/core';\nimport * as t from '@babel/types';\nimport { getFileHash } from '@intlayer/chokidar';\nimport { dirname, join, relative } from 'node:path';\n\n/* ────────────────────────────────────────── constants ───────────────────── */\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer'] as const;\n\n/* ────────────────────────────────────────── types ───────────────────────── */\n\ntype State = PluginPass & {\n opts: { dictionariesDir: string; dictionariesEntryPath: string };\n /** map key → generated ident (per-file) */\n _newImports?: Map<string, t.Identifier>;\n /** whether the current file imported *any* intlayer package */\n _hasValidImport?: boolean;\n /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\n/**\n * Replicates the xxHash64 → Base-62 algorithm used by the SWC version\n * and prefixes an underscore so the generated identifiers never collide\n * with user-defined ones.\n */\nconst makeIdent = (key: string): t.Identifier => {\n const hash = getFileHash(key);\n return t.identifier(`_${hash}`);\n};\n\nconst computeRelativeImport = (\n fromFile: string,\n dictDir: string,\n key: string\n): string => {\n const jsonPath = join(dictDir, `${key}.json`);\n let rel = relative(dirname(fromFile), jsonPath).replace(/\\\\/g, '/'); // win →\n if (!rel.startsWith('./') && !rel.startsWith('../')) rel = `./${rel}`;\n return rel;\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\n/**\n * Babel plugin that transforms `useIntlayer/getIntlayer` calls into\n * `useDictionary/getDictionary` and auto-imports the required JSON dictionaries.\n *\n * **New behaviour**: if the currently processed file matches `dictionariesEntryPath`,\n * its entire contents are replaced with a simple `export default {}` so that it\n * never contains stale or circular references.\n *\n * The **critical detail** (bug-fix) is that we still **only rewrite** an import\n * specifier when its *imported* name is `useIntlayer`/`getIntlayer`.\n *\n * This means cases like:\n * ```ts\n * import { useDictionary as useIntlayer } from 'react-intlayer';\n * ```\n * —where `useIntlayer` is merely an *alias* or re-export—are left untouched\n * because `imported.name` is `useDictionary`.\n */\nexport const intlayerBabelPlugin = (): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._newImports = new Map();\n this._hasValidImport = false;\n this._isDictEntry = false;\n },\n\n visitor: {\n /* 0. If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n const filename = state.file.opts.filename!;\n if (filename === state.opts.dictionariesEntryPath) {\n state._isDictEntry = true;\n // Replace all existing statements with: export default {}\n programPath.node.body = [\n t.exportDefaultDeclaration(t.objectExpression([])),\n ];\n // Stop further traversal for this plugin – nothing else to transform\n programPath.stop();\n }\n },\n\n /* 3. After full traversal, inject the JSON dictionary imports. */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n if (!state._hasValidImport) return; // early-out if we touched nothing\n\n const file = state.file.opts.filename!;\n const dictDir = state.opts.dictionariesDir;\n const imports: t.ImportDeclaration[] = [];\n\n for (const [key, ident] of state._newImports!) {\n const rel = computeRelativeImport(file, dictDir, key);\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n if (!imports.length) return;\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n const bodyPaths = programPath.get('body') as NodePath<t.Statement>[];\n let insertPos = 0;\n for (const stmtPath of bodyPaths) {\n const stmt = stmtPath.node;\n if (\n t.isExpressionStatement(stmt) &&\n t.isStringLiteral(stmt.expression) &&\n (stmt.expression.value === 'use client' ||\n stmt.expression.value === 'use server')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n programPath.node.body.splice(insertPos, 0, ...imports);\n },\n },\n\n /* 1. Inspect *every* intlayer import. */\n ImportDeclaration(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const src = path.node.source.value;\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Mark that we do import from an intlayer package in this file; this is\n // enough to know that we *might* need to inject runtime helpers later.\n state._hasValidImport = true;\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n // ⚠️ We now key off *imported* name, *not* local name.\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as t.StringLiteral).value;\n\n if (importedName === 'useIntlayer') {\n spec.imported = t.identifier('useDictionary');\n } else if (importedName === 'getIntlayer') {\n spec.imported = t.identifier('getDictionary');\n }\n }\n },\n\n /* 2. Replace calls: useIntlayer(\"foo\") → useDictionary(_hash) */\n CallExpression(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee)) return;\n if (!CALLER_LIST.includes(callee.name as any)) return;\n\n // Ensure we ultimately emit helper imports for files that *invoke*\n // the hooks, even if they didn’t import them directly (edge cases with\n // re-exports).\n state._hasValidImport = true;\n\n const arg = path.node.arguments[0];\n if (!arg || !t.isStringLiteral(arg)) return; // must be literal\n\n const key = arg.value;\n // per-file cache\n let ident = state._newImports!.get(key);\n if (!ident) {\n ident = makeIdent(key);\n state._newImports!.set(key, ident);\n }\n\n // replace first arg with ident\n path.node.arguments[0] = t.identifier(ident.name);\n },\n },\n };\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/babel-plugin-intlayer.ts"],"sourcesContent":["import type { NodePath, PluginObj, PluginPass } from '@babel/core';\nimport * as t from '@babel/types';\nimport { getFileHash } from '@intlayer/chokidar';\nimport { dirname, join, relative } from 'node:path';\n\n/* ────────────────────────────────────────── constants ───────────────────── */\n\nconst PACKAGE_LIST = [\n 'intlayer',\n '@intlayer/core',\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n 'svelte-intlayer',\n 'vue-intlayer',\n 'angular-intlayer',\n 'preact-intlayer',\n 'solid-intlayer',\n];\n\nconst CALLER_LIST = ['useIntlayer', 'getIntlayer'] as const;\n\n/**\n * Packages that support dynamic import\n */\nconst PACKAGE_LIST_DYNAMIC = [\n 'react-intlayer',\n 'react-intlayer/client',\n 'react-intlayer/server',\n 'next-intlayer',\n 'next-intlayer/client',\n 'next-intlayer/server',\n] as const;\n\nconst STATIC_IMPORT_FUNCTION = {\n getIntlayer: 'getDictionary',\n useIntlayer: 'useDictionary',\n} as const;\n\nconst DYNAMIC_IMPORT_FUNCTION = {\n useIntlayer: 'useDictionaryDynamic',\n} as const;\n\n/* ────────────────────────────────────────── types ───────────────────────── */\n\ntype State = PluginPass & {\n opts: {\n /**\n * The path to the dictionaries directory.\n */\n dictionariesDir: string;\n /**\n * The path to the dictionaries entry file.\n */\n dictionariesEntryPath: string;\n /**\n * The path to the dictionaries directory.\n */\n dynamicDictionariesDir: string;\n /**\n * The path to the dynamic dictionaries entry file.\n */\n dynamicDictionariesEntryPath: string;\n /**\n * If true, the plugin will activate the dynamic import of the dictionaries.\n */\n activateDynamicImport?: boolean;\n /**\n * Files list to traverse.\n */\n filesList?: string[];\n };\n /** map key → generated ident (per-file) for static imports */\n _newStaticImports?: Map<string, t.Identifier>;\n /** map key → generated ident (per-file) for dynamic imports */\n _newDynamicImports?: Map<string, t.Identifier>;\n /** whether the current file imported *any* intlayer package */\n _hasValidImport?: boolean;\n /** whether the current file *is* the dictionaries entry file */\n _isDictEntry?: boolean;\n /** whether dynamic helpers are active for this file */\n _useDynamicHelpers?: boolean;\n};\n\n/* ────────────────────────────────────────── helpers ─────────────────────── */\n\n/**\n * Replicates the xxHash64 → Base-62 algorithm used by the SWC version\n * and prefixes an underscore so the generated identifiers never collide\n * with user-defined ones.\n */\nconst makeIdent = (key: string): t.Identifier => {\n const hash = getFileHash(key);\n return t.identifier(`_${hash}`);\n};\n\nconst computeRelativeImport = (\n fromFile: string,\n dictionariesDir: string,\n dynamicDictionariesDir: string,\n key: string,\n isDynamic = false\n): string => {\n const jsonPath = isDynamic\n ? join(dynamicDictionariesDir, `${key}.mjs`)\n : join(dictionariesDir, `${key}.json`);\n\n let rel = relative(dirname(fromFile), jsonPath).replace(/\\\\/g, '/'); // win →\n if (!rel.startsWith('./') && !rel.startsWith('../')) rel = `./${rel}`;\n return rel;\n};\n\n/* ────────────────────────────────────────── plugin ──────────────────────── */\n\n/**\n * Babel plugin that transforms `useIntlayer/getIntlayer` calls into\n * `useDictionary/getDictionary` and auto-imports the required JSON dictionaries.\n *\n *\n * This means cases like:\n *\n * ```ts\n * import { getIntlayer } from 'intlayer';\n * import { useIntlayer } from 'react-intlayer';\n *\n * // ...\n *\n * const content1 = getIntlayer('app');\n * const content2 = useIntlayer('app');\n * ```\n *\n * will be transformed into:\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dictionaries/app.mjs';\n * import { getDictionary as getIntlayer } from 'intlayer';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n *\n * // ...\n *\n * const content1 = getIntlayer(_dicHash);\n * const content2 = useIntlayer(_dicHash)\n * ```\n *\n * Or if the `activateDynamicImport` option is enabled:\n *\n * ```ts\n * import _dicHash from '../../.intlayer/dynamic_dictionaries/app.mjs';\n * import _dicHash_dyn from '../../.intlayer/dictionaries/app.mjs';\n *\n * import { useDictionary as getIntlayer } from 'intlayer';\n * import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';\n *\n * // ...\n *\n * const content1 = getIntlayer(_dicHash);\n * const content2 = useIntlayer(_dicHash_dyn, 'app');\n * ```\n */\nexport const intlayerBabelPlugin = (): PluginObj<State> => {\n return {\n name: 'babel-plugin-intlayer-transform',\n\n pre() {\n this._newStaticImports = new Map();\n this._newDynamicImports = new Map();\n this._isIncluded = true;\n this._hasValidImport = false;\n this._isDictEntry = false;\n this._useDynamicHelpers = false;\n\n // If filesList is provided, check if current file is included\n const filename = this.file.opts.filename;\n if (this.opts.filesList && filename) {\n const isIncluded = this.opts.filesList.includes(filename);\n\n if (!isIncluded) {\n // Force _isIncluded to false to skip processing\n this._isIncluded = false;\n return;\n }\n }\n },\n\n visitor: {\n /* 0. If this file *is* the dictionaries entry, short-circuit: export {} */\n Program: {\n enter(programPath, state) {\n const filename = state.file.opts.filename!;\n if (filename === state.opts.dictionariesEntryPath) {\n state._isDictEntry = true;\n // Replace all existing statements with: export default {}\n programPath.node.body = [\n t.exportDefaultDeclaration(t.objectExpression([])),\n ];\n // Stop further traversal for this plugin – nothing else to transform\n programPath.stop();\n }\n },\n\n /* 3. After full traversal, inject the JSON dictionary imports. */\n exit(programPath, state) {\n if (state._isDictEntry) return; // nothing else to do – already replaced\n if (!state._hasValidImport) return; // early-out if we touched nothing\n if (!state._isIncluded) return; // early-out if file is not included\n\n const file = state.file.opts.filename!;\n const dictionariesDir = state.opts.dictionariesDir;\n const dynamicDictionariesDir = state.opts.dynamicDictionariesDir;\n const imports: t.ImportDeclaration[] = [];\n\n // Generate static imports (for getIntlayer and useIntlayer when not using dynamic)\n for (const [key, ident] of state._newStaticImports!) {\n const rel = computeRelativeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n key,\n false // Always static\n );\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n // Generate dynamic imports (for useIntlayer when using dynamic helpers)\n for (const [key, ident] of state._newDynamicImports!) {\n const rel = computeRelativeImport(\n file,\n dictionariesDir,\n dynamicDictionariesDir,\n key,\n true // Always dynamic\n );\n imports.push(\n t.importDeclaration(\n [t.importDefaultSpecifier(t.identifier(ident.name))],\n t.stringLiteral(rel)\n )\n );\n }\n\n if (!imports.length) return;\n\n /* Keep \"use client\" / \"use server\" directives at the very top. */\n const bodyPaths = programPath.get('body') as NodePath<t.Statement>[];\n let insertPos = 0;\n for (const stmtPath of bodyPaths) {\n const stmt = stmtPath.node;\n if (\n t.isExpressionStatement(stmt) &&\n t.isStringLiteral(stmt.expression) &&\n !stmt.expression.value.startsWith('import') &&\n !stmt.expression.value.startsWith('require')\n ) {\n insertPos += 1;\n } else {\n break;\n }\n }\n\n programPath.node.body.splice(insertPos, 0, ...imports);\n },\n },\n\n /* 1. Inspect *every* intlayer import. */\n ImportDeclaration(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const src = path.node.source.value;\n if (!PACKAGE_LIST.includes(src)) return;\n\n // Mark that we do import from an intlayer package in this file; this is\n // enough to know that we *might* need to inject runtime helpers later.\n state._hasValidImport = true;\n\n for (const spec of path.node.specifiers) {\n if (!t.isImportSpecifier(spec)) continue;\n\n // ⚠️ We now key off *imported* name, *not* local name.\n const importedName = t.isIdentifier(spec.imported)\n ? spec.imported.name\n : (spec.imported as t.StringLiteral).value;\n\n const activateDynamicImport = state.opts.activateDynamicImport;\n // Determine whether this import should use the dynamic helpers. We\n // only switch to the dynamic helpers when (1) the option is turned\n // on AND (2) the package we are importing from supports the dynamic\n // helpers.\n const shouldUseDynamicHelpers =\n activateDynamicImport && PACKAGE_LIST_DYNAMIC.includes(src as any);\n\n // Remember for later (CallExpression) whether we are using the dynamic helpers\n if (shouldUseDynamicHelpers) {\n state._useDynamicHelpers = true;\n }\n\n const helperMap = shouldUseDynamicHelpers\n ? ({\n ...STATIC_IMPORT_FUNCTION,\n ...DYNAMIC_IMPORT_FUNCTION,\n } as Record<string, string>)\n : (STATIC_IMPORT_FUNCTION as Record<string, string>);\n\n const newIdentifier = helperMap[importedName];\n\n // Only rewrite when we actually have a mapping for the imported\n // specifier (ignore unrelated named imports).\n if (newIdentifier) {\n // Keep the local alias intact (so calls remain `useIntlayer` /\n // `getIntlayer`), but rewrite the imported identifier so it\n // points to our helper implementation.\n spec.imported = t.identifier(newIdentifier);\n }\n }\n },\n\n /* 2. Replace calls: useIntlayer(\"foo\") → useDictionary(_hash) or useDictionaryDynamic(_hash, \"foo\") */\n CallExpression(path, state) {\n if (state._isDictEntry) return; // skip if entry file – already handled\n\n const callee = path.node.callee;\n if (!t.isIdentifier(callee)) return;\n if (!CALLER_LIST.includes(callee.name as any)) return;\n\n // Ensure we ultimately emit helper imports for files that *invoke*\n // the hooks, even if they didn't import them directly (edge cases with\n // re-exports).\n state._hasValidImport = true;\n\n const arg = path.node.arguments[0];\n if (!arg || !t.isStringLiteral(arg)) return; // must be literal\n\n const key = arg.value;\n const useDynamic = Boolean(state._useDynamicHelpers);\n\n // Determine if this specific call should use dynamic imports\n const shouldUseDynamicForThisCall =\n callee.name === 'useIntlayer' && useDynamic;\n\n let ident: t.Identifier;\n\n if (shouldUseDynamicForThisCall) {\n // Use dynamic imports for useIntlayer when dynamic helpers are enabled\n let dynamicIdent = state._newDynamicImports!.get(key);\n if (!dynamicIdent) {\n // Create a unique identifier for dynamic imports by appending a suffix\n const hash = getFileHash(key);\n dynamicIdent = t.identifier(`_${hash}_dyn`);\n state._newDynamicImports!.set(key, dynamicIdent);\n }\n ident = dynamicIdent;\n\n // Dynamic helper: first argument is the dictionary, second is the key.\n path.node.arguments = [\n t.identifier(ident.name),\n ...path.node.arguments,\n ];\n } else {\n // Use static imports for getIntlayer or useIntlayer when not using dynamic helpers\n let staticIdent = state._newStaticImports!.get(key);\n if (!staticIdent) {\n staticIdent = makeIdent(key);\n state._newStaticImports!.set(key, staticIdent);\n }\n ident = staticIdent;\n\n // Static helper (useDictionary / getDictionary): replace key with ident.\n path.node.arguments[0] = t.identifier(ident.name);\n }\n },\n },\n };\n};\n"],"mappings":"AACA,YAAY,OAAO;AACnB,SAAS,mBAAmB;AAC5B,SAAS,SAAS,MAAM,gBAAgB;AAIxC,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,cAAc,CAAC,eAAe,aAAa;AAKjD,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,MAAM,yBAAyB;AAAA,EAC7B,aAAa;AAAA,EACb,aAAa;AACf;AAEA,MAAM,0BAA0B;AAAA,EAC9B,aAAa;AACf;AAkDA,MAAM,YAAY,CAAC,QAA8B;AAC/C,QAAM,OAAO,YAAY,GAAG;AAC5B,SAAO,EAAE,WAAW,IAAI,IAAI,EAAE;AAChC;AAEA,MAAM,wBAAwB,CAC5B,UACA,iBACA,wBACA,KACA,YAAY,UACD;AACX,QAAM,WAAW,YACb,KAAK,wBAAwB,GAAG,GAAG,MAAM,IACzC,KAAK,iBAAiB,GAAG,GAAG,OAAO;AAEvC,MAAI,MAAM,SAAS,QAAQ,QAAQ,GAAG,QAAQ,EAAE,QAAQ,OAAO,GAAG;AAClE,MAAI,CAAC,IAAI,WAAW,IAAI,KAAK,CAAC,IAAI,WAAW,KAAK,EAAG,OAAM,KAAK,GAAG;AACnE,SAAO;AACT;AAiDO,MAAM,sBAAsB,MAAwB;AACzD,SAAO;AAAA,IACL,MAAM;AAAA,IAEN,MAAM;AACJ,WAAK,oBAAoB,oBAAI,IAAI;AACjC,WAAK,qBAAqB,oBAAI,IAAI;AAClC,WAAK,cAAc;AACnB,WAAK,kBAAkB;AACvB,WAAK,eAAe;AACpB,WAAK,qBAAqB;AAG1B,YAAM,WAAW,KAAK,KAAK,KAAK;AAChC,UAAI,KAAK,KAAK,aAAa,UAAU;AACnC,cAAM,aAAa,KAAK,KAAK,UAAU,SAAS,QAAQ;AAExD,YAAI,CAAC,YAAY;AAEf,eAAK,cAAc;AACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,IAEA,SAAS;AAAA;AAAA,MAEP,SAAS;AAAA,QACP,MAAM,aAAa,OAAO;AACxB,gBAAM,WAAW,MAAM,KAAK,KAAK;AACjC,cAAI,aAAa,MAAM,KAAK,uBAAuB;AACjD,kBAAM,eAAe;AAErB,wBAAY,KAAK,OAAO;AAAA,cACtB,EAAE,yBAAyB,EAAE,iBAAiB,CAAC,CAAC,CAAC;AAAA,YACnD;AAEA,wBAAY,KAAK;AAAA,UACnB;AAAA,QACF;AAAA;AAAA,QAGA,KAAK,aAAa,OAAO;AACvB,cAAI,MAAM,aAAc;AACxB,cAAI,CAAC,MAAM,gBAAiB;AAC5B,cAAI,CAAC,MAAM,YAAa;AAExB,gBAAM,OAAO,MAAM,KAAK,KAAK;AAC7B,gBAAM,kBAAkB,MAAM,KAAK;AACnC,gBAAM,yBAAyB,MAAM,KAAK;AAC1C,gBAAM,UAAiC,CAAC;AAGxC,qBAAW,CAAC,KAAK,KAAK,KAAK,MAAM,mBAAoB;AACnD,kBAAM,MAAM;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,YACF;AACA,oBAAQ;AAAA,cACN,EAAE;AAAA,gBACA,CAAC,EAAE,uBAAuB,EAAE,WAAW,MAAM,IAAI,CAAC,CAAC;AAAA,gBACnD,EAAE,cAAc,GAAG;AAAA,cACrB;AAAA,YACF;AAAA,UACF;AAGA,qBAAW,CAAC,KAAK,KAAK,KAAK,MAAM,oBAAqB;AACpD,kBAAM,MAAM;AAAA,cACV;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA,cACA;AAAA;AAAA,YACF;AACA,oBAAQ;AAAA,cACN,EAAE;AAAA,gBACA,CAAC,EAAE,uBAAuB,EAAE,WAAW,MAAM,IAAI,CAAC,CAAC;AAAA,gBACnD,EAAE,cAAc,GAAG;AAAA,cACrB;AAAA,YACF;AAAA,UACF;AAEA,cAAI,CAAC,QAAQ,OAAQ;AAGrB,gBAAM,YAAY,YAAY,IAAI,MAAM;AACxC,cAAI,YAAY;AAChB,qBAAW,YAAY,WAAW;AAChC,kBAAM,OAAO,SAAS;AACtB,gBACE,EAAE,sBAAsB,IAAI,KAC5B,EAAE,gBAAgB,KAAK,UAAU,KACjC,CAAC,KAAK,WAAW,MAAM,WAAW,QAAQ,KAC1C,CAAC,KAAK,WAAW,MAAM,WAAW,SAAS,GAC3C;AACA,2BAAa;AAAA,YACf,OAAO;AACL;AAAA,YACF;AAAA,UACF;AAEA,sBAAY,KAAK,KAAK,OAAO,WAAW,GAAG,GAAG,OAAO;AAAA,QACvD;AAAA,MACF;AAAA;AAAA,MAGA,kBAAkB,MAAM,OAAO;AAC7B,YAAI,MAAM,aAAc;AAExB,cAAM,MAAM,KAAK,KAAK,OAAO;AAC7B,YAAI,CAAC,aAAa,SAAS,GAAG,EAAG;AAIjC,cAAM,kBAAkB;AAExB,mBAAW,QAAQ,KAAK,KAAK,YAAY;AACvC,cAAI,CAAC,EAAE,kBAAkB,IAAI,EAAG;AAGhC,gBAAM,eAAe,EAAE,aAAa,KAAK,QAAQ,IAC7C,KAAK,SAAS,OACb,KAAK,SAA6B;AAEvC,gBAAM,wBAAwB,MAAM,KAAK;AAKzC,gBAAM,0BACJ,yBAAyB,qBAAqB,SAAS,GAAU;AAGnE,cAAI,yBAAyB;AAC3B,kBAAM,qBAAqB;AAAA,UAC7B;AAEA,gBAAM,YAAY,0BACb;AAAA,YACC,GAAG;AAAA,YACH,GAAG;AAAA,UACL,IACC;AAEL,gBAAM,gBAAgB,UAAU,YAAY;AAI5C,cAAI,eAAe;AAIjB,iBAAK,WAAW,EAAE,WAAW,aAAa;AAAA,UAC5C;AAAA,QACF;AAAA,MACF;AAAA;AAAA,MAGA,eAAe,MAAM,OAAO;AAC1B,YAAI,MAAM,aAAc;AAExB,cAAM,SAAS,KAAK,KAAK;AACzB,YAAI,CAAC,EAAE,aAAa,MAAM,EAAG;AAC7B,YAAI,CAAC,YAAY,SAAS,OAAO,IAAW,EAAG;AAK/C,cAAM,kBAAkB;AAExB,cAAM,MAAM,KAAK,KAAK,UAAU,CAAC;AACjC,YAAI,CAAC,OAAO,CAAC,EAAE,gBAAgB,GAAG,EAAG;AAErC,cAAM,MAAM,IAAI;AAChB,cAAM,aAAa,QAAQ,MAAM,kBAAkB;AAGnD,cAAM,8BACJ,OAAO,SAAS,iBAAiB;AAEnC,YAAI;AAEJ,YAAI,6BAA6B;AAE/B,cAAI,eAAe,MAAM,mBAAoB,IAAI,GAAG;AACpD,cAAI,CAAC,cAAc;AAEjB,kBAAM,OAAO,YAAY,GAAG;AAC5B,2BAAe,EAAE,WAAW,IAAI,IAAI,MAAM;AAC1C,kBAAM,mBAAoB,IAAI,KAAK,YAAY;AAAA,UACjD;AACA,kBAAQ;AAGR,eAAK,KAAK,YAAY;AAAA,YACpB,EAAE,WAAW,MAAM,IAAI;AAAA,YACvB,GAAG,KAAK,KAAK;AAAA,UACf;AAAA,QACF,OAAO;AAEL,cAAI,cAAc,MAAM,kBAAmB,IAAI,GAAG;AAClD,cAAI,CAAC,aAAa;AAChB,0BAAc,UAAU,GAAG;AAC3B,kBAAM,kBAAmB,IAAI,KAAK,WAAW;AAAA,UAC/C;AACA,kBAAQ;AAGR,eAAK,KAAK,UAAU,CAAC,IAAI,EAAE,WAAW,MAAM,IAAI;AAAA,QAClD;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
|
|
@@ -2,33 +2,86 @@ import type { PluginObj, PluginPass } from '@babel/core';
|
|
|
2
2
|
import * as t from '@babel/types';
|
|
3
3
|
type State = PluginPass & {
|
|
4
4
|
opts: {
|
|
5
|
+
/**
|
|
6
|
+
* The path to the dictionaries directory.
|
|
7
|
+
*/
|
|
5
8
|
dictionariesDir: string;
|
|
9
|
+
/**
|
|
10
|
+
* The path to the dictionaries entry file.
|
|
11
|
+
*/
|
|
6
12
|
dictionariesEntryPath: string;
|
|
13
|
+
/**
|
|
14
|
+
* The path to the dictionaries directory.
|
|
15
|
+
*/
|
|
16
|
+
dynamicDictionariesDir: string;
|
|
17
|
+
/**
|
|
18
|
+
* The path to the dynamic dictionaries entry file.
|
|
19
|
+
*/
|
|
20
|
+
dynamicDictionariesEntryPath: string;
|
|
21
|
+
/**
|
|
22
|
+
* If true, the plugin will activate the dynamic import of the dictionaries.
|
|
23
|
+
*/
|
|
24
|
+
activateDynamicImport?: boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Files list to traverse.
|
|
27
|
+
*/
|
|
28
|
+
filesList?: string[];
|
|
7
29
|
};
|
|
8
|
-
/** map key → generated ident (per-file) */
|
|
9
|
-
|
|
30
|
+
/** map key → generated ident (per-file) for static imports */
|
|
31
|
+
_newStaticImports?: Map<string, t.Identifier>;
|
|
32
|
+
/** map key → generated ident (per-file) for dynamic imports */
|
|
33
|
+
_newDynamicImports?: Map<string, t.Identifier>;
|
|
10
34
|
/** whether the current file imported *any* intlayer package */
|
|
11
35
|
_hasValidImport?: boolean;
|
|
12
36
|
/** whether the current file *is* the dictionaries entry file */
|
|
13
37
|
_isDictEntry?: boolean;
|
|
38
|
+
/** whether dynamic helpers are active for this file */
|
|
39
|
+
_useDynamicHelpers?: boolean;
|
|
14
40
|
};
|
|
15
41
|
/**
|
|
16
42
|
* Babel plugin that transforms `useIntlayer/getIntlayer` calls into
|
|
17
43
|
* `useDictionary/getDictionary` and auto-imports the required JSON dictionaries.
|
|
18
44
|
*
|
|
19
|
-
* **New behaviour**: if the currently processed file matches `dictionariesEntryPath`,
|
|
20
|
-
* its entire contents are replaced with a simple `export default {}` so that it
|
|
21
|
-
* never contains stale or circular references.
|
|
22
|
-
*
|
|
23
|
-
* The **critical detail** (bug-fix) is that we still **only rewrite** an import
|
|
24
|
-
* specifier when its *imported* name is `useIntlayer`/`getIntlayer`.
|
|
25
45
|
*
|
|
26
46
|
* This means cases like:
|
|
47
|
+
*
|
|
27
48
|
* ```ts
|
|
28
|
-
* import {
|
|
49
|
+
* import { getIntlayer } from 'intlayer';
|
|
50
|
+
* import { useIntlayer } from 'react-intlayer';
|
|
51
|
+
*
|
|
52
|
+
* // ...
|
|
53
|
+
*
|
|
54
|
+
* const content1 = getIntlayer('app');
|
|
55
|
+
* const content2 = useIntlayer('app');
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* will be transformed into:
|
|
59
|
+
*
|
|
60
|
+
* ```ts
|
|
61
|
+
* import _dicHash from '../../.intlayer/dictionaries/app.mjs';
|
|
62
|
+
* import { getDictionary as getIntlayer } from 'intlayer';
|
|
63
|
+
* import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';
|
|
64
|
+
*
|
|
65
|
+
* // ...
|
|
66
|
+
*
|
|
67
|
+
* const content1 = getIntlayer(_dicHash);
|
|
68
|
+
* const content2 = useIntlayer(_dicHash)
|
|
69
|
+
* ```
|
|
70
|
+
*
|
|
71
|
+
* Or if the `activateDynamicImport` option is enabled:
|
|
72
|
+
*
|
|
73
|
+
* ```ts
|
|
74
|
+
* import _dicHash from '../../.intlayer/dynamic_dictionaries/app.mjs';
|
|
75
|
+
* import _dicHash_dyn from '../../.intlayer/dictionaries/app.mjs';
|
|
76
|
+
*
|
|
77
|
+
* import { useDictionary as getIntlayer } from 'intlayer';
|
|
78
|
+
* import { useDictionaryDynamic as useIntlayer } from 'react-intlayer';
|
|
79
|
+
*
|
|
80
|
+
* // ...
|
|
81
|
+
*
|
|
82
|
+
* const content1 = getIntlayer(_dicHash);
|
|
83
|
+
* const content2 = useIntlayer(_dicHash_dyn, 'app');
|
|
29
84
|
* ```
|
|
30
|
-
* —where `useIntlayer` is merely an *alias* or re-export—are left untouched
|
|
31
|
-
* because `imported.name` is `useDictionary`.
|
|
32
85
|
*/
|
|
33
86
|
export declare const intlayerBabelPlugin: () => PluginObj<State>;
|
|
34
87
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"babel-plugin-intlayer.d.ts","sourceRoot":"","sources":["../../src/babel-plugin-intlayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"babel-plugin-intlayer.d.ts","sourceRoot":"","sources":["../../src/babel-plugin-intlayer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAY,SAAS,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,KAAK,CAAC,MAAM,cAAc,CAAC;AA+ClC,KAAK,KAAK,GAAG,UAAU,GAAG;IACxB,IAAI,EAAE;QACJ;;WAEG;QACH,eAAe,EAAE,MAAM,CAAC;QACxB;;WAEG;QACH,qBAAqB,EAAE,MAAM,CAAC;QAC9B;;WAEG;QACH,sBAAsB,EAAE,MAAM,CAAC;QAC/B;;WAEG;QACH,4BAA4B,EAAE,MAAM,CAAC;QACrC;;WAEG;QACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;QAChC;;WAEG;QACH,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;KACtB,CAAC;IACF,8DAA8D;IAC9D,iBAAiB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IAC9C,+DAA+D;IAC/D,kBAAkB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC;IAC/C,+DAA+D;IAC/D,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gEAAgE;IAChE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,uDAAuD;IACvD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAgCF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,eAAO,MAAM,mBAAmB,QAAO,SAAS,CAAC,KAAK,CAyNrD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/babel",
|
|
3
|
-
"version": "5.5.
|
|
3
|
+
"version": "5.5.5",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A Babel plugin for Intlayer that transforms declaration files and provides internationalization features during the build process according to the Intlayer configuration.",
|
|
6
6
|
"keywords": [
|
|
@@ -62,8 +62,8 @@
|
|
|
62
62
|
"@babel/generator": "^7.27.1",
|
|
63
63
|
"@babel/parser": "^7.27.2",
|
|
64
64
|
"@babel/traverse": "^7.27.1",
|
|
65
|
-
"@intlayer/
|
|
66
|
-
"@intlayer/
|
|
65
|
+
"@intlayer/config": "5.5.5",
|
|
66
|
+
"@intlayer/chokidar": "5.5.5"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
69
|
"@babel/types": "^7.27.1",
|
|
@@ -82,14 +82,14 @@
|
|
|
82
82
|
"tsc-alias": "^1.8.11",
|
|
83
83
|
"tsup": "^8.4.0",
|
|
84
84
|
"typescript": "^5.8.2",
|
|
85
|
-
"@utils/ts-config-types": "1.0.4",
|
|
86
|
-
"@utils/tsup-config": "1.0.4",
|
|
87
85
|
"@utils/ts-config": "1.0.4",
|
|
88
|
-
"@utils/
|
|
86
|
+
"@utils/ts-config-types": "1.0.4",
|
|
87
|
+
"@utils/eslint-config": "1.0.4",
|
|
88
|
+
"@utils/tsup-config": "1.0.4"
|
|
89
89
|
},
|
|
90
90
|
"peerDependencies": {
|
|
91
|
-
"@intlayer/chokidar": "5.5.
|
|
92
|
-
"@intlayer/config": "5.5.
|
|
91
|
+
"@intlayer/chokidar": "5.5.5",
|
|
92
|
+
"@intlayer/config": "5.5.5"
|
|
93
93
|
},
|
|
94
94
|
"engines": {
|
|
95
95
|
"node": ">=14.18"
|