@intlayer/babel 9.0.0-canary.2 → 9.0.0-canary.21

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.
Files changed (152) hide show
  1. package/dist/cjs/babel-plugin-intlayer-extract.cjs +3 -2
  2. package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
  3. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs +160 -99
  4. package/dist/cjs/babel-plugin-intlayer-field-rename.cjs.map +1 -1
  5. package/dist/cjs/babel-plugin-intlayer-minify.cjs +11 -28
  6. package/dist/cjs/babel-plugin-intlayer-minify.cjs.map +1 -1
  7. package/dist/cjs/babel-plugin-intlayer-optimize.cjs +143 -13
  8. package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
  9. package/dist/cjs/babel-plugin-intlayer-purge.cjs +38 -96
  10. package/dist/cjs/babel-plugin-intlayer-purge.cjs.map +1 -1
  11. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs +151 -52
  12. package/dist/cjs/babel-plugin-intlayer-usage-analyzer.cjs.map +1 -1
  13. package/dist/cjs/babelParser.cjs +62 -0
  14. package/dist/cjs/babelParser.cjs.map +1 -0
  15. package/dist/cjs/extractContent/babelProcessor.cjs +144 -71
  16. package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
  17. package/dist/cjs/extractContent/contentWriter.cjs +10 -14
  18. package/dist/cjs/extractContent/contentWriter.cjs.map +1 -1
  19. package/dist/cjs/extractContent/extractContent.cjs +3 -3
  20. package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
  21. package/dist/cjs/extractContent/processTsxFile.cjs +4 -7
  22. package/dist/cjs/extractContent/processTsxFile.cjs.map +1 -1
  23. package/dist/cjs/extractContent/utils/constants.cjs +2 -2
  24. package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
  25. package/dist/cjs/extractContent/utils/detectPackageName.cjs +0 -1
  26. package/dist/cjs/extractContent/utils/detectPackageName.cjs.map +1 -1
  27. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +4 -4
  28. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs.map +1 -1
  29. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs +2 -3
  30. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs.map +1 -1
  31. package/dist/cjs/extractContent/utils/generateKey.cjs.map +1 -1
  32. package/dist/cjs/extractContent/utils/getComponentName.cjs.map +1 -1
  33. package/dist/cjs/extractContent/utils/getExistingIntlayerInfo.cjs.map +1 -1
  34. package/dist/cjs/extractContent/utils/getOrGenerateKey.cjs.map +1 -1
  35. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs +0 -1
  36. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs.map +1 -1
  37. package/dist/cjs/extractContent/utils/shouldExtract.cjs +2 -0
  38. package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +1 -1
  39. package/dist/cjs/extractScriptBlocks.cjs +0 -1
  40. package/dist/cjs/extractScriptBlocks.cjs.map +1 -1
  41. package/dist/cjs/getExtractPluginOptions.cjs +2 -2
  42. package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
  43. package/dist/cjs/getOptimizePluginOptions.cjs +2 -3
  44. package/dist/cjs/getOptimizePluginOptions.cjs.map +1 -1
  45. package/dist/cjs/getPurgePluginOptions.cjs +2 -3
  46. package/dist/cjs/getPurgePluginOptions.cjs.map +1 -1
  47. package/dist/cjs/index.cjs +3 -0
  48. package/dist/cjs/normalizedFilesList.cjs +30 -0
  49. package/dist/cjs/normalizedFilesList.cjs.map +1 -0
  50. package/dist/cjs/transformers.cjs +20 -2
  51. package/dist/cjs/transformers.cjs.map +1 -1
  52. package/dist/esm/babel-plugin-intlayer-extract.mjs +3 -2
  53. package/dist/esm/babel-plugin-intlayer-extract.mjs.map +1 -1
  54. package/dist/esm/babel-plugin-intlayer-field-rename.mjs +159 -100
  55. package/dist/esm/babel-plugin-intlayer-field-rename.mjs.map +1 -1
  56. package/dist/esm/babel-plugin-intlayer-minify.mjs +12 -29
  57. package/dist/esm/babel-plugin-intlayer-minify.mjs.map +1 -1
  58. package/dist/esm/babel-plugin-intlayer-optimize.mjs +140 -9
  59. package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
  60. package/dist/esm/babel-plugin-intlayer-purge.mjs +40 -97
  61. package/dist/esm/babel-plugin-intlayer-purge.mjs.map +1 -1
  62. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs +151 -52
  63. package/dist/esm/babel-plugin-intlayer-usage-analyzer.mjs.map +1 -1
  64. package/dist/esm/babelParser.mjs +60 -0
  65. package/dist/esm/babelParser.mjs.map +1 -0
  66. package/dist/esm/extractContent/babelProcessor.mjs +144 -71
  67. package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
  68. package/dist/esm/extractContent/contentWriter.mjs +6 -10
  69. package/dist/esm/extractContent/contentWriter.mjs.map +1 -1
  70. package/dist/esm/extractContent/extractContent.mjs +1 -1
  71. package/dist/esm/extractContent/extractContent.mjs.map +1 -1
  72. package/dist/esm/extractContent/processTsxFile.mjs +3 -6
  73. package/dist/esm/extractContent/processTsxFile.mjs.map +1 -1
  74. package/dist/esm/extractContent/utils/constants.mjs +2 -2
  75. package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
  76. package/dist/esm/extractContent/utils/detectPackageName.mjs.map +1 -1
  77. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +1 -1
  78. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs.map +1 -1
  79. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs +1 -1
  80. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs.map +1 -1
  81. package/dist/esm/extractContent/utils/generateKey.mjs.map +1 -1
  82. package/dist/esm/extractContent/utils/getComponentName.mjs.map +1 -1
  83. package/dist/esm/extractContent/utils/getExistingIntlayerInfo.mjs.map +1 -1
  84. package/dist/esm/extractContent/utils/getOrGenerateKey.mjs.map +1 -1
  85. package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs.map +1 -1
  86. package/dist/esm/extractContent/utils/shouldExtract.mjs +2 -0
  87. package/dist/esm/extractContent/utils/shouldExtract.mjs.map +1 -1
  88. package/dist/esm/extractScriptBlocks.mjs.map +1 -1
  89. package/dist/esm/getExtractPluginOptions.mjs +1 -1
  90. package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
  91. package/dist/esm/getOptimizePluginOptions.mjs +1 -1
  92. package/dist/esm/getOptimizePluginOptions.mjs.map +1 -1
  93. package/dist/esm/getPurgePluginOptions.mjs +1 -1
  94. package/dist/esm/getPurgePluginOptions.mjs.map +1 -1
  95. package/dist/esm/index.mjs +3 -3
  96. package/dist/esm/normalizedFilesList.mjs +29 -0
  97. package/dist/esm/normalizedFilesList.mjs.map +1 -0
  98. package/dist/esm/transformers.mjs +20 -2
  99. package/dist/esm/transformers.mjs.map +1 -1
  100. package/dist/types/babel-plugin-intlayer-extract.d.ts +2 -3
  101. package/dist/types/babel-plugin-intlayer-extract.d.ts.map +1 -1
  102. package/dist/types/babel-plugin-intlayer-field-rename.d.ts +29 -11
  103. package/dist/types/babel-plugin-intlayer-field-rename.d.ts.map +1 -1
  104. package/dist/types/babel-plugin-intlayer-minify.d.ts +2 -3
  105. package/dist/types/babel-plugin-intlayer-minify.d.ts.map +1 -1
  106. package/dist/types/babel-plugin-intlayer-optimize.d.ts +34 -11
  107. package/dist/types/babel-plugin-intlayer-optimize.d.ts.map +1 -1
  108. package/dist/types/babel-plugin-intlayer-purge.d.ts +2 -3
  109. package/dist/types/babel-plugin-intlayer-purge.d.ts.map +1 -1
  110. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts +35 -113
  111. package/dist/types/babel-plugin-intlayer-usage-analyzer.d.ts.map +1 -1
  112. package/dist/types/babelParser.d.ts +12 -0
  113. package/dist/types/babelParser.d.ts.map +1 -0
  114. package/dist/types/extractContent/babelProcessor.d.ts +5 -2
  115. package/dist/types/extractContent/babelProcessor.d.ts.map +1 -1
  116. package/dist/types/extractContent/contentWriter.d.ts +0 -1
  117. package/dist/types/extractContent/contentWriter.d.ts.map +1 -1
  118. package/dist/types/extractContent/extractContent.d.ts +1 -1
  119. package/dist/types/extractContent/extractContent.d.ts.map +1 -1
  120. package/dist/types/extractContent/index.d.ts +1 -1
  121. package/dist/types/extractContent/processTsxFile.d.ts +1 -1
  122. package/dist/types/extractContent/processTsxFile.d.ts.map +1 -1
  123. package/dist/types/extractContent/utils/constants.d.ts +3 -3
  124. package/dist/types/extractContent/utils/constants.d.ts.map +1 -1
  125. package/dist/types/extractContent/utils/detectPackageName.d.ts +0 -1
  126. package/dist/types/extractContent/utils/detectPackageName.d.ts.map +1 -1
  127. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts +0 -1
  128. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts.map +1 -1
  129. package/dist/types/extractContent/utils/extractDictionaryKey.d.ts.map +1 -1
  130. package/dist/types/extractContent/utils/generateKey.d.ts.map +1 -1
  131. package/dist/types/extractContent/utils/getComponentName.d.ts +0 -1
  132. package/dist/types/extractContent/utils/getComponentName.d.ts.map +1 -1
  133. package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts +8 -5
  134. package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts.map +1 -1
  135. package/dist/types/extractContent/utils/getOrGenerateKey.d.ts.map +1 -1
  136. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts +0 -1
  137. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts.map +1 -1
  138. package/dist/types/extractContent/utils/shouldExtract.d.ts +1 -0
  139. package/dist/types/extractContent/utils/shouldExtract.d.ts.map +1 -1
  140. package/dist/types/extractScriptBlocks.d.ts.map +1 -1
  141. package/dist/types/getExtractPluginOptions.d.ts +0 -1
  142. package/dist/types/getExtractPluginOptions.d.ts.map +1 -1
  143. package/dist/types/getOptimizePluginOptions.d.ts +0 -1
  144. package/dist/types/getOptimizePluginOptions.d.ts.map +1 -1
  145. package/dist/types/getPurgePluginOptions.d.ts +0 -1
  146. package/dist/types/getPurgePluginOptions.d.ts.map +1 -1
  147. package/dist/types/index.d.ts +6 -5
  148. package/dist/types/normalizedFilesList.d.ts +12 -0
  149. package/dist/types/normalizedFilesList.d.ts.map +1 -0
  150. package/dist/types/transformers.d.ts +7 -2
  151. package/dist/types/transformers.d.ts.map +1 -1
  152. package/package.json +31 -23
@@ -14,6 +14,123 @@ _babel_types = require_runtime.__toESM(_babel_types);
14
14
  //#region src/extractContent/babelProcessor.ts
15
15
  const traverse = typeof _babel_traverse.default === "function" ? _babel_traverse.default : _babel_traverse.default.default;
16
16
  /**
17
+ * Method names whose string arguments are technical operands — lookups,
18
+ * comparisons, DOM queries, storage keys, event names — rather than translatable
19
+ * display text. A string literal passed to one of these (e.g.
20
+ * `message.includes('Loading chunk')`) is code, not content, and is skipped.
21
+ */
22
+ /**
23
+ * Binary operators whose string operands are code constants / enum values
24
+ * (e.g. `msg.step === 'ERROR'`) rather than translatable display text.
25
+ */
26
+ const COMPARISON_OPERATORS = /* @__PURE__ */ new Set([
27
+ "===",
28
+ "!==",
29
+ "==",
30
+ "!="
31
+ ]);
32
+ /**
33
+ * Object property names whose string values are technical/non-translatable
34
+ * (e.g. `icon: 'Globe'`, `variant: 'primary'`). String values under other
35
+ * property names (e.g. `label: 'Language'`) are still extracted.
36
+ */
37
+ const TECHNICAL_KEYS = /* @__PURE__ */ new Set([
38
+ "icon",
39
+ "className",
40
+ "class",
41
+ "id",
42
+ "type",
43
+ "variant",
44
+ "color",
45
+ "theme",
46
+ "size",
47
+ "align",
48
+ "placement",
49
+ "target",
50
+ "rel",
51
+ "method",
52
+ "mode",
53
+ "direction",
54
+ "orientation",
55
+ "scope",
56
+ "role",
57
+ "lang",
58
+ "locale",
59
+ "href",
60
+ "src",
61
+ "width",
62
+ "height",
63
+ "as",
64
+ "to",
65
+ "key",
66
+ "value",
67
+ "defaultValue",
68
+ "prop",
69
+ "property",
70
+ "state",
71
+ "action",
72
+ "event",
73
+ "handler",
74
+ "callback",
75
+ "url",
76
+ "uri",
77
+ "path",
78
+ "route",
79
+ "slug",
80
+ "endpoint",
81
+ "headers",
82
+ "contentType"
83
+ ]);
84
+ const NON_TRANSLATABLE_CALL_METHODS = /* @__PURE__ */ new Set([
85
+ "includes",
86
+ "startsWith",
87
+ "endsWith",
88
+ "indexOf",
89
+ "lastIndexOf",
90
+ "match",
91
+ "matchAll",
92
+ "search",
93
+ "localeCompare",
94
+ "split",
95
+ "getAttribute",
96
+ "setAttribute",
97
+ "hasAttribute",
98
+ "removeAttribute",
99
+ "querySelector",
100
+ "querySelectorAll",
101
+ "getElementById",
102
+ "getElementsByClassName",
103
+ "getElementsByTagName",
104
+ "addEventListener",
105
+ "removeEventListener",
106
+ "dispatchEvent",
107
+ "matchMedia",
108
+ "getItem",
109
+ "setItem",
110
+ "removeItem",
111
+ "getPropertyValue",
112
+ "setProperty"
113
+ ]);
114
+ /**
115
+ * When `path` is a string-literal argument of a member/optional-member call
116
+ * expression (e.g. `foo.includes('bar')` or `foo?.bar?.includes('baz')`),
117
+ * returns the called method name and whether the call targets the `console`
118
+ * object. Returns `undefined` when the parent is not such a call, or the string
119
+ * is not one of its arguments.
120
+ */
121
+ const getEnclosingMethodCallInfo = (path) => {
122
+ const parent = path.parentPath;
123
+ if (!parent.isCallExpression() && !parent.isOptionalCallExpression()) return;
124
+ const callNode = parent.node;
125
+ if (!callNode.arguments.includes(path.node)) return void 0;
126
+ const callee = callNode.callee;
127
+ if (!_babel_types.isMemberExpression(callee) && !_babel_types.isOptionalMemberExpression(callee)) return;
128
+ return {
129
+ methodName: _babel_types.isIdentifier(callee.property) ? callee.property.name : void 0,
130
+ isConsoleCall: _babel_types.isIdentifier(callee.object) && callee.object.name === "console"
131
+ };
132
+ };
133
+ /**
17
134
  * Handles JSX insertions (elements with multiple children, including expressions).
18
135
  * Replaces complex JSX structures with variable-based translations.
19
136
  */
@@ -140,13 +257,19 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
140
257
  componentPaths.push(path);
141
258
  }
142
259
  });
260
+ const existingInfoByNode = /* @__PURE__ */ new Map();
261
+ const componentNodeToPath = /* @__PURE__ */ new Map();
262
+ for (const path of componentPaths) {
263
+ existingInfoByNode.set(path.node, require_extractContent_utils_getExistingIntlayerInfo.getExistingIntlayerInfo(path));
264
+ componentNodeToPath.set(path.node, path);
265
+ }
143
266
  for (const path of componentPaths) {
144
267
  if (path.isProgram()) continue;
145
- const existingInfo = require_extractContent_utils_getExistingIntlayerInfo.getExistingIntlayerInfo(path);
268
+ const existingInfo = existingInfoByNode.get(path.node);
146
269
  if (existingInfo) usedKeysInFile.add(existingInfo.key);
147
270
  }
148
271
  for (const path of componentPaths) {
149
- const existingInfo = require_extractContent_utils_getExistingIntlayerInfo.getExistingIntlayerInfo(path);
272
+ const existingInfo = existingInfoByNode.get(path.node);
150
273
  if (existingInfo) {
151
274
  componentKeyMap.set(path.node, existingInfo.key);
152
275
  usedKeysInFile.add(existingInfo.key);
@@ -240,57 +363,11 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
240
363
  const parent = path.parentPath;
241
364
  if (parent.isImportDeclaration() || parent.isImportSpecifier() || parent.isExportDeclaration()) return;
242
365
  if (parent.isJSXAttribute()) return;
243
- if (parent.isCallExpression() && _babel_types.isMemberExpression(parent.node.callee)) {
244
- if (_babel_types.isIdentifier(parent.node.callee.object) && parent.node.callee.object.name === "console" && _babel_types.isIdentifier(parent.node.callee.property) && parent.node.callee.property.name === "log") return;
245
- }
366
+ if (parent.isBinaryExpression() && COMPARISON_OPERATORS.has(parent.node.operator)) return;
367
+ if (parent.isSwitchCase() && parent.node.test === path.node) return;
368
+ const methodCallInfo = getEnclosingMethodCallInfo(path);
369
+ if (methodCallInfo && (methodCallInfo.isConsoleCall || methodCallInfo.methodName !== void 0 && NON_TRANSLATABLE_CALL_METHODS.has(methodCallInfo.methodName))) return;
246
370
  if (parent.isObjectProperty() && parent.node.key === path.node) return;
247
- const TECHNICAL_KEYS = new Set([
248
- "icon",
249
- "className",
250
- "class",
251
- "id",
252
- "type",
253
- "variant",
254
- "color",
255
- "theme",
256
- "size",
257
- "align",
258
- "placement",
259
- "target",
260
- "rel",
261
- "method",
262
- "mode",
263
- "direction",
264
- "orientation",
265
- "scope",
266
- "role",
267
- "lang",
268
- "locale",
269
- "href",
270
- "src",
271
- "width",
272
- "height",
273
- "as",
274
- "to",
275
- "key",
276
- "value",
277
- "defaultValue",
278
- "prop",
279
- "property",
280
- "state",
281
- "action",
282
- "event",
283
- "handler",
284
- "callback",
285
- "url",
286
- "uri",
287
- "path",
288
- "route",
289
- "slug",
290
- "endpoint",
291
- "headers",
292
- "contentType"
293
- ]);
294
371
  if (parent.isObjectProperty() && _babel_types.isIdentifier(parent.node.key) && TECHNICAL_KEYS.has(parent.node.key.name)) return;
295
372
  if (parent.isMemberExpression() && parent.node.property === path.node) return;
296
373
  const componentKey = getComponentKeyForPath(path);
@@ -340,6 +417,15 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
340
417
  });
341
418
  }
342
419
  });
420
+ /** Returns true when `componentNode` encloses the replacement's path. */
421
+ const replacementIsInside = (replacement, componentNode) => {
422
+ let current = replacement.path;
423
+ while (current) {
424
+ if (current.node === componentNode) return true;
425
+ current = current.parentPath;
426
+ }
427
+ return false;
428
+ };
343
429
  const componentsNeedingHooks = /* @__PURE__ */ new Set();
344
430
  for (const componentPath of componentPaths) {
345
431
  if (componentPath.isProgram()) {
@@ -347,37 +433,23 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
347
433
  let current = replacement.path;
348
434
  while (current) {
349
435
  if (current.node === componentPath.node) return true;
350
- if (componentPaths.some((p) => p !== componentPath && p.node === current?.node)) return false;
436
+ if (componentNodeToPath.has(current.node)) return false;
351
437
  current = current.parentPath;
352
438
  }
353
439
  return false;
354
440
  })) componentsNeedingHooks.add(componentPath);
355
441
  continue;
356
442
  }
357
- if (replacements.some((replacement) => {
358
- let current = replacement.path;
359
- while (current) {
360
- if (current.node === componentPath.node) return true;
361
- current = current.parentPath;
362
- }
363
- return false;
364
- })) {
443
+ if (replacements.some((replacement) => replacementIsInside(replacement, componentPath.node))) {
365
444
  const key = componentKeyMap.get(componentPath.node);
366
445
  let ancestorProvidesKey = false;
367
446
  let currentPath = componentPath.parentPath;
368
447
  while (currentPath) {
369
- const ancestorPath = componentPaths.find((path) => path.node === currentPath?.node);
448
+ const ancestorPath = componentNodeToPath.get(currentPath.node);
370
449
  if (ancestorPath && !ancestorPath.isProgram()) {
371
450
  if (componentKeyMap.get(ancestorPath.node) === key) {
372
- const ancestorHasReplacements = replacements.some((replacement) => {
373
- let rPath = replacement.path;
374
- while (rPath) {
375
- if (rPath.node === ancestorPath.node) return true;
376
- rPath = rPath.parentPath;
377
- }
378
- return false;
379
- });
380
- const existingInfo = require_extractContent_utils_getExistingIntlayerInfo.getExistingIntlayerInfo(ancestorPath);
451
+ const ancestorHasReplacements = replacements.some((replacement) => replacementIsInside(replacement, ancestorPath.node));
452
+ const existingInfo = existingInfoByNode.get(ancestorPath.node);
381
453
  if (ancestorHasReplacements || existingInfo) {
382
454
  ancestorProvidesKey = true;
383
455
  break;
@@ -396,6 +468,7 @@ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKe
396
468
  componentKeyMap,
397
469
  componentPaths,
398
470
  hookMap,
471
+ existingInfoByNode,
399
472
  isSolid: false
400
473
  };
401
474
  };
@@ -1 +1 @@
1
- {"version":3,"file":"babelProcessor.cjs","names":["_traverse","t","shouldExtract","getOrGenerateKey","getExistingIntlayerInfo","resolveDictionaryKey","getComponentName","ATTRIBUTES_TO_EXTRACT"],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined'\n | 'template-literal';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else if (t.isTemplateLiteral(expr)) {\n for (let i = 0; i < expr.quasis.length; i++) {\n parts.push({\n type: 'text',\n value: expr.quasis[i]?.value.raw ?? '',\n });\n if (i < expr.expressions.length) {\n const subExpr = expr.expressions[i];\n if (t.isIdentifier(subExpr)) {\n parts.push({\n type: 'var',\n value: subExpr.name,\n originalExpr: subExpr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(subExpr)) {\n const code = fileCode.substring(subExpr.start!, subExpr.end!);\n const varName = t.isIdentifier(subExpr.property)\n ? subExpr.property.name\n : 'var';\n parts.push({ type: 'var', value: varName, originalExpr: code });\n hasVariables = true;\n } else {\n return false;\n }\n }\n }\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n Program(path) {\n componentPaths.push(path);\n },\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n // Pre-scan non-Program paths to collect their existing dictionary keys before the\n // Program scope is assigned. Without this, Program is processed first (depth-first\n // traversal) and creates a new file-path-derived key even when a child component\n // already declares a specific dictionary (e.g. useIntlayer('dashboard-sidebar')).\n for (const path of componentPaths) {\n if (path.isProgram()) continue;\n const existingInfo = getExistingIntlayerInfo(path);\n if (existingInfo) {\n usedKeysInFile.add(existingInfo.key);\n }\n }\n\n for (const path of componentPaths) {\n const existingInfo = getExistingIntlayerInfo(path);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (path.isProgram()) {\n if (!globalFileKey) {\n // Reuse the dominant existing key from child components so that\n // module-level strings join the same dictionary rather than\n // creating a new file-path-derived one (e.g. 'route').\n const dominantKey =\n usedKeysInFile.size > 0 ? [...usedKeysInFile][0] : undefined;\n if (dominantKey) {\n globalFileKey = dominantKey;\n } else {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n }\n componentKeyMap.set(path.node, globalFileKey);\n hookMap.set(path.node, 'getIntlayer');\n } else {\n let inheritedKey: string | undefined;\n let parent: NodePath | null = path.parentPath;\n while (parent) {\n if (componentKeyMap.has(parent.node)) {\n inheritedKey = componentKeyMap.get(parent.node);\n break;\n }\n parent = parent.parentPath;\n }\n\n if (!inheritedKey) {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n inheritedKey = globalFileKey;\n }\n\n componentKeyMap.set(path.node, inheritedKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n const isHook = compName ? /^use[A-Z]/.test(compName) : false;\n hookMap.set(\n path.node,\n isComponent || isHook ? 'useIntlayer' : 'getIntlayer'\n );\n }\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n if (\n parent.isCallExpression() &&\n t.isMemberExpression(parent.node.callee)\n ) {\n if (\n t.isIdentifier(parent.node.callee.object) &&\n parent.node.callee.object.name === 'console' &&\n t.isIdentifier(parent.node.callee.property) &&\n parent.node.callee.property.name === 'log'\n ) {\n return;\n }\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n // Skip string values in known technical/non-translatable object properties (e.g. `icon: 'Globe'`).\n // String values in translatable object properties (e.g. `label: 'Language'`) are still extracted.\n const TECHNICAL_KEYS = new Set([\n 'icon',\n 'className',\n 'class',\n 'id',\n 'type',\n 'variant',\n 'color',\n 'theme',\n 'size',\n 'align',\n 'placement',\n 'target',\n 'rel',\n 'method',\n 'mode',\n 'direction',\n 'orientation',\n 'scope',\n 'role',\n 'lang',\n 'locale',\n 'href',\n 'src',\n 'width',\n 'height',\n 'as',\n 'to',\n 'key',\n 'value',\n 'defaultValue',\n 'prop',\n 'property',\n 'state',\n 'action',\n 'event',\n 'handler',\n 'callback',\n 'url',\n 'uri',\n 'path',\n 'route',\n 'slug',\n 'endpoint',\n 'headers',\n 'contentType',\n ]);\n if (\n parent.isObjectProperty() &&\n t.isIdentifier(parent.node.key) &&\n TECHNICAL_KEYS.has(parent.node.key.name)\n ) {\n return;\n }\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n TemplateLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const { quasis, expressions } = path.node;\n\n // Build the combined string with placeholders\n let combinedString = '';\n const variables: string[] = [];\n let hasSignificantText = false;\n\n for (let i = 0; i < quasis.length; i++) {\n const text = quasis[i]?.value.raw ?? '';\n combinedString += text;\n if (text.trim().length > 0) hasSignificantText = true;\n\n if (i < expressions.length) {\n const expr = expressions[i];\n if (t.isIdentifier(expr)) {\n combinedString += `{{${expr.name}}}`;\n variables.push(`${expr.name}: ${expr.name}`);\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n combinedString += `{{${varName}}}`;\n variables.push(`${varName}: ${code}`);\n } else {\n // Complex expression in template literal, skip\n return;\n }\n }\n }\n\n if (!hasSignificantText) return;\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (!shouldExtract(cleanString)) return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const uniqueVars = Array.from(new Set(variables));\n\n replacements.push({\n path,\n key,\n type: 'template-literal',\n componentKey,\n variables: uniqueVars,\n });\n },\n });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n if (componentPath.isProgram()) {\n const hasDirectReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) {\n return true;\n }\n const isOtherComponent = componentPaths.some(\n (p) => p !== componentPath && p.node === current?.node\n );\n if (isOtherComponent) {\n return false;\n }\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasDirectReplacements) {\n componentsNeedingHooks.add(componentPath);\n }\n continue;\n }\n\n const hasReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) return true;\n\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentPaths.find(\n (path) => path.node === currentPath?.node\n );\n\n if (ancestorPath && !ancestorPath.isProgram()) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) => {\n let rPath: NodePath | null = replacement.path;\n while (rPath) {\n if (rPath.node === ancestorPath.node) return true;\n\n rPath = rPath.parentPath;\n }\n return false;\n });\n const existingInfo = getExistingIntlayerInfo(ancestorPath);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"babelProcessor.cjs","names":["_traverse","t","shouldExtract","getOrGenerateKey","getExistingIntlayerInfo","resolveDictionaryKey","getComponentName","ATTRIBUTES_TO_EXTRACT"],"sources":["../../../src/extractContent/babelProcessor.ts"],"sourcesContent":["import _traverse, { type NodePath } from '@babel/traverse';\nimport * as t from '@babel/types';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport { resolveDictionaryKey } from '../extractContent/utils';\nimport {\n ATTRIBUTES_TO_EXTRACT,\n type ExistingIntlayerInfo,\n getComponentName,\n getExistingIntlayerInfo,\n getOrGenerateKey,\n shouldExtract,\n} from './utils';\n\nexport type BabelReplacement = {\n path: NodePath;\n key: string;\n type:\n | 'jsx-text'\n | 'jsx-attribute'\n | 'string-literal'\n | 'jsx-insertion'\n | 'jsx-text-combined'\n | 'template-literal';\n componentKey: string;\n childrenToReplace?: t.Node[];\n variables?: string[];\n};\n\n// CJS/ESM interop: @babel/traverse exports its function as `.default` in CJS bundles\nconst traverse = (\n typeof _traverse === 'function' ? _traverse : (_traverse as any).default\n) as typeof _traverse;\n\n/**\n * Method names whose string arguments are technical operands — lookups,\n * comparisons, DOM queries, storage keys, event names — rather than translatable\n * display text. A string literal passed to one of these (e.g.\n * `message.includes('Loading chunk')`) is code, not content, and is skipped.\n */\n/**\n * Binary operators whose string operands are code constants / enum values\n * (e.g. `msg.step === 'ERROR'`) rather than translatable display text.\n */\nconst COMPARISON_OPERATORS = new Set(['===', '!==', '==', '!=']);\n\n/**\n * Object property names whose string values are technical/non-translatable\n * (e.g. `icon: 'Globe'`, `variant: 'primary'`). String values under other\n * property names (e.g. `label: 'Language'`) are still extracted.\n */\nconst TECHNICAL_KEYS = new Set<string>([\n 'icon',\n 'className',\n 'class',\n 'id',\n 'type',\n 'variant',\n 'color',\n 'theme',\n 'size',\n 'align',\n 'placement',\n 'target',\n 'rel',\n 'method',\n 'mode',\n 'direction',\n 'orientation',\n 'scope',\n 'role',\n 'lang',\n 'locale',\n 'href',\n 'src',\n 'width',\n 'height',\n 'as',\n 'to',\n 'key',\n 'value',\n 'defaultValue',\n 'prop',\n 'property',\n 'state',\n 'action',\n 'event',\n 'handler',\n 'callback',\n 'url',\n 'uri',\n 'path',\n 'route',\n 'slug',\n 'endpoint',\n 'headers',\n 'contentType',\n]);\n\nconst NON_TRANSLATABLE_CALL_METHODS = new Set<string>([\n 'includes',\n 'startsWith',\n 'endsWith',\n 'indexOf',\n 'lastIndexOf',\n 'match',\n 'matchAll',\n 'search',\n 'localeCompare',\n 'split',\n 'getAttribute',\n 'setAttribute',\n 'hasAttribute',\n 'removeAttribute',\n 'querySelector',\n 'querySelectorAll',\n 'getElementById',\n 'getElementsByClassName',\n 'getElementsByTagName',\n 'addEventListener',\n 'removeEventListener',\n 'dispatchEvent',\n 'matchMedia',\n 'getItem',\n 'setItem',\n 'removeItem',\n 'getPropertyValue',\n 'setProperty',\n]);\n\n/**\n * When `path` is a string-literal argument of a member/optional-member call\n * expression (e.g. `foo.includes('bar')` or `foo?.bar?.includes('baz')`),\n * returns the called method name and whether the call targets the `console`\n * object. Returns `undefined` when the parent is not such a call, or the string\n * is not one of its arguments.\n */\nconst getEnclosingMethodCallInfo = (\n path: NodePath<t.StringLiteral>\n): { methodName: string | undefined; isConsoleCall: boolean } | undefined => {\n const parent = path.parentPath;\n if (!parent.isCallExpression() && !parent.isOptionalCallExpression()) {\n return undefined;\n }\n\n const callNode = parent.node as t.CallExpression | t.OptionalCallExpression;\n if (!callNode.arguments.includes(path.node)) return undefined;\n\n const callee = callNode.callee;\n if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {\n return undefined;\n }\n\n const methodName = t.isIdentifier(callee.property)\n ? callee.property.name\n : undefined;\n const isConsoleCall =\n t.isIdentifier(callee.object) && callee.object.name === 'console';\n\n return { methodName, isConsoleCall };\n};\n\n/**\n * Handles JSX insertions (elements with multiple children, including expressions).\n * Replaces complex JSX structures with variable-based translations.\n */\nexport const handleJsxInsertionBabel = (\n path: NodePath<t.JSXElement | t.JSXFragment>,\n fileCode: string,\n existingKeys: Set<string>,\n getComponentKeyForPath: (path: NodePath) => string,\n extractedContent: Record<string, Record<string, string>>,\n replacements: BabelReplacement[],\n handledNodes: Set<t.Node>\n): boolean => {\n const children = path.node.children;\n\n if (children.length <= 1) return false;\n\n const parts: {\n type: 'text' | 'var';\n value: string;\n originalExpr?: string;\n }[] = [];\n let hasSignificantText = false;\n let hasVariables = false;\n\n for (const child of children) {\n if (t.isJSXText(child)) {\n const text = child.value;\n\n if (text.trim().length > 0) hasSignificantText = true;\n\n parts.push({ type: 'text', value: text });\n } else if (t.isJSXExpressionContainer(child)) {\n if (t.isJSXEmptyExpression(child.expression)) {\n parts.push({ type: 'text', value: '' });\n } else {\n const expr = child.expression;\n\n if (t.isIdentifier(expr)) {\n parts.push({\n type: 'var',\n value: expr.name,\n originalExpr: expr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n\n parts.push({ type: 'var', value: varName, originalExpr: code });\n\n hasVariables = true;\n } else if (t.isTemplateLiteral(expr)) {\n for (let i = 0; i < expr.quasis.length; i++) {\n parts.push({\n type: 'text',\n value: expr.quasis[i]?.value.raw ?? '',\n });\n if (i < expr.expressions.length) {\n const subExpr = expr.expressions[i];\n if (t.isIdentifier(subExpr)) {\n parts.push({\n type: 'var',\n value: subExpr.name,\n originalExpr: subExpr.name,\n });\n hasVariables = true;\n } else if (t.isMemberExpression(subExpr)) {\n const code = fileCode.substring(subExpr.start!, subExpr.end!);\n const varName = t.isIdentifier(subExpr.property)\n ? subExpr.property.name\n : 'var';\n parts.push({ type: 'var', value: varName, originalExpr: code });\n hasVariables = true;\n } else {\n return false;\n }\n }\n }\n } else {\n return false;\n }\n }\n } else {\n return false;\n }\n }\n\n if (!hasSignificantText) return false;\n\n let combinedString = '';\n for (const part of parts) {\n if (part.type === 'var') combinedString += `{{${part.value}}}`;\n else combinedString += part.value;\n }\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (shouldExtract(cleanString)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const varMap = parts\n .filter((part) => part.type === 'var')\n .map((part) => `${part.value}: ${part.originalExpr}`);\n const uniqueVars = Array.from(new Set(varMap));\n\n if (hasVariables) {\n replacements.push({\n path,\n key,\n type: 'jsx-insertion',\n componentKey,\n childrenToReplace: children,\n variables: uniqueVars,\n });\n } else {\n replacements.push({\n path,\n key,\n type: 'jsx-text-combined',\n componentKey,\n childrenToReplace: children,\n });\n }\n\n children.forEach((child) => {\n handledNodes.add(child);\n });\n return true;\n }\n\n return false;\n};\n\n/**\n * Traverses the AST to identify components and extract content.\n * Returns extraction results and metadata about which components need Intlayer hooks.\n */\nexport const extractBabelContentForComponents = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n defaultKey: string = 'default',\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, Record<string, string>>;\n replacements: BabelReplacement[];\n componentsNeedingHooks: Set<NodePath>;\n componentKeyMap: Map<t.Node, string>;\n componentPaths: NodePath[];\n hookMap: Map<t.Node, 'useIntlayer' | 'getIntlayer'>;\n /** Cached `getExistingIntlayerInfo` result per component node, so callers do not re-traverse. */\n existingInfoByNode: Map<t.Node, ExistingIntlayerInfo | undefined>;\n isSolid: boolean;\n} => {\n const extractedContent: Record<string, Record<string, string>> = {};\n const replacements: BabelReplacement[] = [];\n const handledNodes = new Set<t.Node>();\n const componentKeyMap = new Map<t.Node, string>();\n const hookMap = new Map<t.Node, 'useIntlayer' | 'getIntlayer'>();\n const usedKeysInFile = new Set<string>();\n let globalFileKey: string | undefined;\n\n const componentPaths: NodePath[] = [];\n\n traverse(ast, {\n Program(path) {\n componentPaths.push(path);\n },\n FunctionDeclaration(path) {\n componentPaths.push(path);\n },\n ArrowFunctionExpression(path) {\n componentPaths.push(path);\n },\n FunctionExpression(path) {\n componentPaths.push(path);\n },\n });\n\n // `getExistingIntlayerInfo` traverses the component body, so resolve it a\n // single time per component and share the cache with every later phase\n // (including the caller, via the returned `existingInfoByNode`).\n const existingInfoByNode = new Map<\n t.Node,\n ExistingIntlayerInfo | undefined\n >();\n const componentNodeToPath = new Map<t.Node, NodePath>();\n for (const path of componentPaths) {\n existingInfoByNode.set(path.node, getExistingIntlayerInfo(path));\n componentNodeToPath.set(path.node, path);\n }\n\n // Pre-scan non-Program paths to collect their existing dictionary keys before the\n // Program scope is assigned. Without this, Program is processed first (depth-first\n // traversal) and creates a new file-path-derived key even when a child component\n // already declares a specific dictionary (e.g. useIntlayer('dashboard-sidebar')).\n for (const path of componentPaths) {\n if (path.isProgram()) continue;\n const existingInfo = existingInfoByNode.get(path.node);\n if (existingInfo) {\n usedKeysInFile.add(existingInfo.key);\n }\n }\n\n for (const path of componentPaths) {\n const existingInfo = existingInfoByNode.get(path.node);\n\n if (existingInfo) {\n componentKeyMap.set(path.node, existingInfo.key);\n usedKeysInFile.add(existingInfo.key);\n hookMap.set(path.node, existingInfo.hook);\n } else {\n if (path.isProgram()) {\n if (!globalFileKey) {\n // Reuse the dominant existing key from child components so that\n // module-level strings join the same dictionary rather than\n // creating a new file-path-derived one (e.g. 'route').\n const dominantKey =\n usedKeysInFile.size > 0 ? [...usedKeysInFile][0] : undefined;\n if (dominantKey) {\n globalFileKey = dominantKey;\n } else {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n }\n componentKeyMap.set(path.node, globalFileKey);\n hookMap.set(path.node, 'getIntlayer');\n } else {\n let inheritedKey: string | undefined;\n let parent: NodePath | null = path.parentPath;\n while (parent) {\n if (componentKeyMap.has(parent.node)) {\n inheritedKey = componentKeyMap.get(parent.node);\n break;\n }\n parent = parent.parentPath;\n }\n\n if (!inheritedKey) {\n if (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n inheritedKey = globalFileKey;\n }\n\n componentKeyMap.set(path.node, inheritedKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n const isHook = compName ? /^use[A-Z]/.test(compName) : false;\n hookMap.set(\n path.node,\n isComponent || isHook ? 'useIntlayer' : 'getIntlayer'\n );\n }\n }\n }\n\n const getComponentKeyForPath = (path: NodePath): string => {\n let current: NodePath | null = path;\n while (current) {\n if (componentKeyMap.has(current.node)) {\n return componentKeyMap.get(current.node)!;\n }\n current = current.parentPath;\n }\n return globalFileKey || defaultKey;\n };\n\n traverse(ast, {\n JSXElement(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXFragment(path) {\n if (handledNodes.has(path.node)) return;\n\n handleJsxInsertionBabel(\n path,\n fileCode,\n existingKeys,\n getComponentKeyForPath,\n extractedContent,\n replacements,\n handledNodes\n );\n },\n JSXText(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (shouldExtract(text)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.replace(/\\s+/g, ' ').trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-text', componentKey });\n }\n },\n JSXAttribute(path) {\n if (handledNodes.has(path.node)) return;\n\n const name = path.node.name.name;\n\n if (\n typeof name !== 'string' ||\n !ATTRIBUTES_TO_EXTRACT.includes(name as any)\n )\n return;\n const value = path.node.value;\n\n if (t.isStringLiteral(value) && shouldExtract(value.value)) {\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n value.value.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'jsx-attribute', componentKey });\n }\n },\n StringLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const text = path.node.value;\n\n if (!shouldExtract(text)) return;\n\n const parent = path.parentPath;\n\n if (\n parent.isImportDeclaration() ||\n parent.isImportSpecifier() ||\n parent.isExportDeclaration()\n )\n return;\n\n if (parent.isJSXAttribute()) return;\n\n // Skip string literals used as comparison operands (e.g. `msg.step === 'ERROR'`).\n // These are code constants / enum values, not translatable display text.\n if (\n parent.isBinaryExpression() &&\n COMPARISON_OPERATORS.has(parent.node.operator)\n ) {\n return;\n }\n\n // Skip string literals used as `switch` case tests (e.g. `case 'ERROR':`).\n // Like comparisons, these are code constants, not display text.\n if (parent.isSwitchCase() && parent.node.test === path.node) return;\n\n // Skip string literals passed to technical method calls, e.g.\n // `message.includes('Loading chunk')`, `el.getAttribute('data-id')`, or\n // `console.log('...')`. These are code operands, not display text.\n const methodCallInfo = getEnclosingMethodCallInfo(path);\n if (\n methodCallInfo &&\n (methodCallInfo.isConsoleCall ||\n (methodCallInfo.methodName !== undefined &&\n NON_TRANSLATABLE_CALL_METHODS.has(methodCallInfo.methodName)))\n ) {\n return;\n }\n\n if (parent.isObjectProperty() && parent.node.key === path.node) return;\n\n // Skip string values in known technical/non-translatable object properties (e.g. `icon: 'Globe'`).\n // String values in translatable object properties (e.g. `label: 'Language'`) are still extracted.\n if (\n parent.isObjectProperty() &&\n t.isIdentifier(parent.node.key) &&\n TECHNICAL_KEYS.has(parent.node.key.name)\n ) {\n return;\n }\n\n if (parent.isMemberExpression() && parent.node.property === path.node)\n return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n text.trim(),\n componentKey,\n existingKeys,\n extractedContent\n );\n replacements.push({ path, key, type: 'string-literal', componentKey });\n },\n TemplateLiteral(path) {\n if (handledNodes.has(path.node)) return;\n\n const { quasis, expressions } = path.node;\n\n // Build the combined string with placeholders\n let combinedString = '';\n const variables: string[] = [];\n let hasSignificantText = false;\n\n for (let i = 0; i < quasis.length; i++) {\n const text = quasis[i]?.value.raw ?? '';\n combinedString += text;\n if (text.trim().length > 0) hasSignificantText = true;\n\n if (i < expressions.length) {\n const expr = expressions[i];\n if (t.isIdentifier(expr)) {\n combinedString += `{{${expr.name}}}`;\n variables.push(`${expr.name}: ${expr.name}`);\n } else if (t.isMemberExpression(expr)) {\n const code = fileCode.substring(expr.start!, expr.end!);\n const varName = t.isIdentifier(expr.property)\n ? expr.property.name\n : 'var';\n combinedString += `{{${varName}}}`;\n variables.push(`${varName}: ${code}`);\n } else {\n // Complex expression in template literal, skip\n return;\n }\n }\n }\n\n if (!hasSignificantText) return;\n\n const cleanString = combinedString.replace(/\\s+/g, ' ').trim();\n\n if (!shouldExtract(cleanString)) return;\n\n const componentKey = getComponentKeyForPath(path);\n const key = getOrGenerateKey(\n cleanString,\n componentKey,\n existingKeys,\n extractedContent\n );\n\n const uniqueVars = Array.from(new Set(variables));\n\n replacements.push({\n path,\n key,\n type: 'template-literal',\n componentKey,\n variables: uniqueVars,\n });\n },\n });\n\n /** Returns true when `componentNode` encloses the replacement's path. */\n const replacementIsInside = (\n replacement: BabelReplacement,\n componentNode: t.Node\n ): boolean => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentNode) return true;\n current = current.parentPath;\n }\n return false;\n };\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\n if (componentPath.isProgram()) {\n // Only count replacements that belong to the Program scope itself, not\n // to a nested component (which provides its own hook).\n const hasDirectReplacements = replacements.some((replacement) => {\n let current: NodePath | null = replacement.path;\n while (current) {\n if (current.node === componentPath.node) {\n return true;\n }\n if (componentNodeToPath.has(current.node)) {\n return false; // reached an enclosing component first\n }\n current = current.parentPath;\n }\n return false;\n });\n\n if (hasDirectReplacements) {\n componentsNeedingHooks.add(componentPath);\n }\n continue;\n }\n\n const hasReplacements = replacements.some((replacement) =>\n replacementIsInside(replacement, componentPath.node)\n );\n\n if (hasReplacements) {\n const key = componentKeyMap.get(componentPath.node)!;\n let ancestorProvidesKey = false;\n let currentPath: NodePath | null = componentPath.parentPath;\n while (currentPath) {\n const ancestorPath = componentNodeToPath.get(currentPath.node);\n\n if (ancestorPath && !ancestorPath.isProgram()) {\n const ancestorKey = componentKeyMap.get(ancestorPath.node);\n\n if (ancestorKey === key) {\n const ancestorHasReplacements = replacements.some((replacement) =>\n replacementIsInside(replacement, ancestorPath.node)\n );\n const existingInfo = existingInfoByNode.get(ancestorPath.node);\n\n if (ancestorHasReplacements || existingInfo) {\n ancestorProvidesKey = true;\n break;\n }\n }\n }\n currentPath = currentPath.parentPath;\n }\n\n if (!ancestorProvidesKey) {\n componentsNeedingHooks.add(componentPath);\n }\n }\n }\n\n return {\n extractedContent,\n replacements,\n componentsNeedingHooks,\n componentKeyMap,\n componentPaths,\n hookMap,\n existingInfoByNode,\n isSolid: false,\n };\n};\n\n/**\n * High-level function to extract content from TS/JS/JSX/TSX AST.\n */\nexport const extractTsContent = (\n ast: t.File,\n fileCode: string,\n existingKeys: Set<string>,\n configuration: IntlayerConfig,\n filePath: string,\n unmergedDictionaries: Record<string, unknown> = {}\n): {\n extractedContent: Record<string, string>;\n replacements: BabelReplacement[];\n} => {\n const { extractedContent, replacements } = extractBabelContentForComponents(\n ast,\n fileCode,\n existingKeys,\n 'default',\n configuration,\n filePath,\n unmergedDictionaries\n );\n\n const flatContent: Record<string, string> = {};\n for (const group of Object.values(extractedContent)) {\n Object.assign(flatContent, group);\n }\n\n return { extractedContent: flatContent, replacements };\n};\n"],"mappings":"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"}
@@ -4,25 +4,21 @@ const require_extractContent_utils_extractDictionaryInfo = require('./utils/extr
4
4
  let node_path = require("node:path");
5
5
  let node_fs = require("node:fs");
6
6
  let node_fs_promises = require("node:fs/promises");
7
- let _intlayer_chokidar_build = require("@intlayer/chokidar/build");
8
7
  let _intlayer_core_plugins = require("@intlayer/core/plugins");
8
+ let _intlayer_engine_build = require("@intlayer/engine/build");
9
9
  let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
10
10
  _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
11
11
 
12
12
  //#region src/extractContent/contentWriter.ts
13
13
  const hasInsertionVars = (str) => /\{\{[^}]+\}\}/.test(str);
14
14
  const getInsertionFields = (template) => {
15
- const fields = [];
15
+ const fields = /* @__PURE__ */ new Set();
16
16
  const regex = /\{\{([^}]+)\}\}/g;
17
- let match;
18
- for (let result = regex.exec(template); result !== null; result = regex.exec(template)) {
19
- match = result;
20
- const fieldMatch = match[1];
21
- if (!fieldMatch) continue;
22
- const field = fieldMatch.trim();
23
- if (!fields.includes(field)) fields.push(field);
17
+ for (let match = regex.exec(template); match !== null; match = regex.exec(template)) {
18
+ const field = match[1]?.trim();
19
+ if (field) fields.add(field);
24
20
  }
25
- return fields;
21
+ return [...fields];
26
22
  };
27
23
  /**
28
24
  * Cached bundle file path to optimize performance
@@ -95,12 +91,12 @@ const writeContentHelper = async (extractedContent, dictionaryKey, filePath, con
95
91
  const { absolutePath, isPerLocale } = await require_extractContent_utils_extractDictionaryInfo.resolveContentFilePaths(filePath, dictionaryKey, configuration);
96
92
  const { defaultLocale } = configuration.internationalization;
97
93
  const { baseDir } = configuration.system;
98
- if (!cachedBundleFilePath) cachedBundleFilePath = await (0, _intlayer_chokidar_build.ensureIntlayerBundle)(configuration);
94
+ if (!cachedBundleFilePath) cachedBundleFilePath = await (0, _intlayer_engine_build.ensureIntlayerBundle)(configuration);
99
95
  const outputDir = (0, node_path.dirname)(absolutePath);
100
96
  await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
101
97
  let existingDictionary = null;
102
98
  if ((0, node_fs.existsSync)(absolutePath)) try {
103
- existingDictionary = await (0, _intlayer_chokidar_build.loadContentDeclaration)(absolutePath, configuration, cachedBundleFilePath) ?? null;
99
+ existingDictionary = await (0, _intlayer_engine_build.loadContentDeclaration)(absolutePath, configuration, cachedBundleFilePath) ?? null;
104
100
  } catch (error) {
105
101
  console.error(error);
106
102
  }
@@ -125,11 +121,11 @@ const writeContentHelper = async (extractedContent, dictionaryKey, filePath, con
125
121
  };
126
122
  }
127
123
  const relativeDir = (0, node_path.relative)(baseDir, outputDir);
128
- const writeResult = await (0, _intlayer_chokidar_build.writeContentDeclaration)(mergedDictionary, configuration, {
124
+ const writeResult = await (0, _intlayer_engine_build.writeContentDeclaration)(mergedDictionary, configuration, {
129
125
  newDictionariesPath: relativeDir,
130
126
  localeList: [defaultLocale]
131
127
  });
132
- await (0, _intlayer_chokidar_build.buildDictionary)([{
128
+ await (0, _intlayer_engine_build.buildDictionary)([{
133
129
  ...mergedDictionary,
134
130
  filePath: (0, node_path.relative)(baseDir, writeResult?.path ?? absolutePath)
135
131
  }], configuration);
@@ -1 +1 @@
1
- {"version":3,"file":"contentWriter.cjs","names":["NodeTypes","resolveContentFilePaths"],"sources":["../../../src/extractContent/contentWriter.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { dirname, relative } from 'node:path';\nimport {\n buildDictionary,\n ensureIntlayerBundle,\n loadContentDeclaration,\n writeContentDeclaration,\n} from '@intlayer/chokidar/build';\nimport { insertContentInDictionary } from '@intlayer/core/plugins';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, DictionaryKey } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { resolveContentFilePaths } from './utils/extractDictionaryInfo';\n\nconst hasInsertionVars = (str: string): boolean => /\\{\\{[^}]+\\}\\}/.test(str);\n\nconst getInsertionFields = (template: string): string[] => {\n const fields: string[] = [];\n const regex = /\\{\\{([^}]+)\\}\\}/g;\n let match: RegExpExecArray | null;\n for (\n let result = regex.exec(template);\n result !== null;\n result = regex.exec(template)\n ) {\n match = result;\n const fieldMatch = match[1];\n if (!fieldMatch) continue;\n const field = fieldMatch.trim();\n if (!fields.includes(field)) fields.push(field);\n }\n return fields;\n};\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 * Cached bundle file path to optimize performance\n */\nlet cachedBundleFilePath: string | undefined;\n\n/**\n * Merge extracted content with existing dictionary for multilingual format.\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 */\nexport const mergeWithExistingMultilingualDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n): DictionaryContentMap => {\n const dictionary: Dictionary =\n existingDictionary ??\n ({\n key: '',\n content: {},\n filePath: '',\n } as Dictionary);\n\n const mergedDictionary = insertContentInDictionary(\n dictionary,\n extractedContent,\n defaultLocale as Locale\n );\n\n const mergedContent = mergedDictionary.content as DictionaryContentMap;\n\n // Pruning: remove keys not in extractedContent\n const finalContent: DictionaryContentMap = {};\n for (const key in extractedContent) {\n const contentNode = mergedContent[key];\n if (contentNode) {\n finalContent[key] = contentNode;\n }\n }\n\n // Promote any key whose source text contains {{vars}} to an insertion node\n for (const key in extractedContent) {\n const rawValue = extractedContent[key];\n if (typeof rawValue === 'string' && hasInsertionVars(rawValue)) {\n const node = finalContent[key] as any;\n if (node && node.nodeType === NodeTypes.TRANSLATION) {\n (finalContent as any)[key] = {\n nodeType: NodeTypes.INSERTION,\n [NodeTypes.INSERTION]: node,\n fields: getInsertionFields(rawValue),\n };\n }\n }\n }\n\n return finalContent;\n};\n\n/**\n * Merge extracted content with existing dictionary for per-locale format.\n * - Keys in extracted but not in existing: added\n * - Keys in both: update value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\nexport const mergeWithExistingPerLocaleDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null\n): Record<string, string> => {\n const dictionary: Dictionary =\n existingDictionary ??\n ({\n key: '',\n content: {},\n filePath: '',\n } as Dictionary);\n\n const mergedDictionary = insertContentInDictionary(\n dictionary,\n extractedContent\n );\n\n const mergedContent = mergedDictionary.content as Record<string, string>;\n\n // Pruning: remove keys not in extractedContent\n const finalContent: Record<string, string> = {};\n for (const key in extractedContent) {\n const contentStr = mergedContent[key];\n if (contentStr) {\n finalContent[key] = contentStr;\n }\n }\n\n // Promote any key whose source text contains {{vars}} to an insertion node\n for (const key in extractedContent) {\n const rawValue = extractedContent[key];\n if (typeof rawValue === 'string' && hasInsertionVars(rawValue)) {\n const currentVal = finalContent[key];\n if (typeof currentVal === 'string') {\n (finalContent as any)[key] = {\n nodeType: NodeTypes.INSERTION,\n [NodeTypes.INSERTION]: currentVal,\n fields: getInsertionFields(rawValue),\n };\n }\n }\n }\n\n return finalContent;\n};\n\n/**\n * Helper to write extracted content to dictionary file(s).\n */\nexport const writeContentHelper = async (\n extractedContent: Record<string, string>,\n dictionaryKey: DictionaryKey,\n filePath: string,\n configuration: IntlayerConfig\n): Promise<string> => {\n const { absolutePath, isPerLocale } = await resolveContentFilePaths(\n filePath,\n dictionaryKey,\n configuration\n );\n\n const { defaultLocale } = configuration.internationalization;\n const { baseDir } = configuration.system;\n\n if (!cachedBundleFilePath) {\n cachedBundleFilePath = await ensureIntlayerBundle(configuration);\n }\n\n const outputDir = dirname(absolutePath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Read existing dictionary to preserve translations and metadata\n let existingDictionary: Dictionary | null = null;\n\n if (existsSync(absolutePath)) {\n try {\n const dictionary = await loadContentDeclaration(\n absolutePath,\n configuration,\n cachedBundleFilePath\n );\n\n existingDictionary = dictionary ?? null;\n } catch (error) {\n console.error(error);\n }\n }\n\n const relativeContentFilePath = relative(baseDir, absolutePath);\n\n let mergedDictionary: Dictionary;\n\n if (isPerLocale) {\n // Per-locale format: simple string content for a single locale\n const mergedContent = mergeWithExistingPerLocaleDictionary(\n extractedContent,\n existingDictionary\n );\n\n mergedDictionary = {\n // Preserve existing metadata\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n locale: defaultLocale,\n filePath: relativeContentFilePath,\n };\n } else {\n // Multilingual format: content wrapped in translation nodes for multiple locales\n const mergedContent = mergeWithExistingMultilingualDictionary(\n extractedContent,\n existingDictionary,\n defaultLocale\n );\n\n mergedDictionary = {\n // Preserve existing metadata\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n filePath: relativeContentFilePath,\n };\n }\n\n const relativeDir = relative(baseDir, outputDir);\n\n const writeResult = await writeContentDeclaration(\n mergedDictionary,\n configuration,\n {\n newDictionariesPath: relativeDir,\n localeList: [defaultLocale],\n }\n );\n\n // Build the dictionary immediately\n const dictionaryToBuild: Dictionary = {\n ...mergedDictionary,\n filePath: relative(baseDir, writeResult?.path ?? absolutePath),\n };\n\n await buildDictionary([dictionaryToBuild], configuration);\n\n return absolutePath;\n};\n"],"mappings":";;;;;;;;;;;;AAgBA,MAAM,oBAAoB,QAAyB,gBAAgB,KAAK,IAAI;AAE5E,MAAM,sBAAsB,aAA+B;CACzD,MAAM,SAAmB,EAAE;CAC3B,MAAM,QAAQ;CACd,IAAI;AACJ,MACE,IAAI,SAAS,MAAM,KAAK,SAAS,EACjC,WAAW,MACX,SAAS,MAAM,KAAK,SAAS,EAC7B;AACA,UAAQ;EACR,MAAM,aAAa,MAAM;AACzB,MAAI,CAAC,WAAY;EACjB,MAAM,QAAQ,WAAW,MAAM;AAC/B,MAAI,CAAC,OAAO,SAAS,MAAM,CAAE,QAAO,KAAK,MAAM;;AAEjD,QAAO;;;;;AAmBT,IAAI;;;;;;;AAQJ,MAAa,2CACX,kBACA,oBACA,kBACyB;CAezB,MAAM,sEAbJ,sBACC;EACC,KAAK;EACL,SAAS,EAAE;EACX,UAAU;EACX,EAID,kBACA,cAGoC,CAAC;CAGvC,MAAM,eAAqC,EAAE;AAC7C,MAAK,MAAM,OAAO,kBAAkB;EAClC,MAAM,cAAc,cAAc;AAClC,MAAI,YACF,cAAa,OAAO;;AAKxB,MAAK,MAAM,OAAO,kBAAkB;EAClC,MAAM,WAAW,iBAAiB;AAClC,MAAI,OAAO,aAAa,YAAY,iBAAiB,SAAS,EAAE;GAC9D,MAAM,OAAO,aAAa;AAC1B,OAAI,QAAQ,KAAK,aAAaA,yBAAU,YACtC,CAAC,aAAqB,OAAO;IAC3B,UAAUA,yBAAU;KACnBA,yBAAU,YAAY;IACvB,QAAQ,mBAAmB,SAAS;IACrC;;;AAKP,QAAO;;;;;;;;AAST,MAAa,wCACX,kBACA,uBAC2B;CAc3B,MAAM,sEAZJ,sBACC;EACC,KAAK;EACL,SAAS,EAAE;EACX,UAAU;EACX,EAID,iBAGoC,CAAC;CAGvC,MAAM,eAAuC,EAAE;AAC/C,MAAK,MAAM,OAAO,kBAAkB;EAClC,MAAM,aAAa,cAAc;AACjC,MAAI,WACF,cAAa,OAAO;;AAKxB,MAAK,MAAM,OAAO,kBAAkB;EAClC,MAAM,WAAW,iBAAiB;AAClC,MAAI,OAAO,aAAa,YAAY,iBAAiB,SAAS,EAAE;GAC9D,MAAM,aAAa,aAAa;AAChC,OAAI,OAAO,eAAe,SACxB,CAAC,aAAqB,OAAO;IAC3B,UAAUA,yBAAU;KACnBA,yBAAU,YAAY;IACvB,QAAQ,mBAAmB,SAAS;IACrC;;;AAKP,QAAO;;;;;AAMT,MAAa,qBAAqB,OAChC,kBACA,eACA,UACA,kBACoB;CACpB,MAAM,EAAE,cAAc,gBAAgB,MAAMC,2EAC1C,UACA,eACA,cACD;CAED,MAAM,EAAE,kBAAkB,cAAc;CACxC,MAAM,EAAE,YAAY,cAAc;AAElC,KAAI,CAAC,qBACH,wBAAuB,yDAA2B,cAAc;CAGlE,MAAM,mCAAoB,aAAa;AAGvC,mCAAY,WAAW,EAAE,WAAW,MAAM,CAAC;CAG3C,IAAI,qBAAwC;AAE5C,6BAAe,aAAa,CAC1B,KAAI;AAOF,uBAAqB,2DALnB,cACA,eACA,qBACD,IAEkC;UAC5B,OAAO;AACd,UAAQ,MAAM,MAAM;;CAIxB,MAAM,kDAAmC,SAAS,aAAa;CAE/D,IAAI;AAEJ,KAAI,aAAa;EAEf,MAAM,gBAAgB,qCACpB,kBACA,mBACD;AAED,qBAAmB;GAEjB,GAAG;GACH,KAAK;GACL,SAAS;GACT,QAAQ;GACR,UAAU;GACX;QACI;EAEL,MAAM,gBAAgB,wCACpB,kBACA,oBACA,cACD;AAED,qBAAmB;GAEjB,GAAG;GACH,KAAK;GACL,SAAS;GACT,UAAU;GACX;;CAGH,MAAM,sCAAuB,SAAS,UAAU;CAEhD,MAAM,cAAc,4DAClB,kBACA,eACA;EACE,qBAAqB;EACrB,YAAY,CAAC,cAAc;EAC5B,CACF;AAQD,qDAAsB,CAAC;EAJrB,GAAG;EACH,kCAAmB,SAAS,aAAa,QAAQ,aAAa;EAGxB,CAAC,EAAE,cAAc;AAEzD,QAAO"}
1
+ {"version":3,"file":"contentWriter.cjs","names":["NodeTypes","resolveContentFilePaths"],"sources":["../../../src/extractContent/contentWriter.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { dirname, relative } from 'node:path';\nimport { insertContentInDictionary } from '@intlayer/core/plugins';\nimport {\n buildDictionary,\n ensureIntlayerBundle,\n loadContentDeclaration,\n writeContentDeclaration,\n} from '@intlayer/engine/build';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary, DictionaryKey } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport { resolveContentFilePaths } from './utils/extractDictionaryInfo';\n\nconst hasInsertionVars = (str: string): boolean => /\\{\\{[^}]+\\}\\}/.test(str);\n\nconst getInsertionFields = (template: string): string[] => {\n const fields = new Set<string>();\n const regex = /\\{\\{([^}]+)\\}\\}/g;\n for (\n let match = regex.exec(template);\n match !== null;\n match = regex.exec(template)\n ) {\n const field = match[1]?.trim();\n if (field) fields.add(field);\n }\n return [...fields];\n};\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 * Cached bundle file path to optimize performance\n */\nlet cachedBundleFilePath: string | undefined;\n\n/**\n * Merge extracted content with existing dictionary for multilingual format.\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 */\nexport const mergeWithExistingMultilingualDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null,\n defaultLocale: string\n): DictionaryContentMap => {\n const dictionary: Dictionary =\n existingDictionary ??\n ({\n key: '',\n content: {},\n filePath: '',\n } as Dictionary);\n\n const mergedDictionary = insertContentInDictionary(\n dictionary,\n extractedContent,\n defaultLocale as Locale\n );\n\n const mergedContent = mergedDictionary.content as DictionaryContentMap;\n\n // Pruning: remove keys not in extractedContent\n const finalContent: DictionaryContentMap = {};\n for (const key in extractedContent) {\n const contentNode = mergedContent[key];\n if (contentNode) {\n finalContent[key] = contentNode;\n }\n }\n\n // Promote any key whose source text contains {{vars}} to an insertion node\n for (const key in extractedContent) {\n const rawValue = extractedContent[key];\n if (typeof rawValue === 'string' && hasInsertionVars(rawValue)) {\n const node = finalContent[key] as any;\n if (node && node.nodeType === NodeTypes.TRANSLATION) {\n (finalContent as any)[key] = {\n nodeType: NodeTypes.INSERTION,\n [NodeTypes.INSERTION]: node,\n fields: getInsertionFields(rawValue),\n };\n }\n }\n }\n\n return finalContent;\n};\n\n/**\n * Merge extracted content with existing dictionary for per-locale format.\n * - Keys in extracted but not in existing: added\n * - Keys in both: update value\n * - Keys in existing but not in extracted: removed (no longer in source)\n */\nexport const mergeWithExistingPerLocaleDictionary = (\n extractedContent: Record<string, string>,\n existingDictionary: Dictionary | null\n): Record<string, string> => {\n const dictionary: Dictionary =\n existingDictionary ??\n ({\n key: '',\n content: {},\n filePath: '',\n } as Dictionary);\n\n const mergedDictionary = insertContentInDictionary(\n dictionary,\n extractedContent\n );\n\n const mergedContent = mergedDictionary.content as Record<string, string>;\n\n // Pruning: remove keys not in extractedContent\n const finalContent: Record<string, string> = {};\n for (const key in extractedContent) {\n const contentStr = mergedContent[key];\n if (contentStr) {\n finalContent[key] = contentStr;\n }\n }\n\n // Promote any key whose source text contains {{vars}} to an insertion node\n for (const key in extractedContent) {\n const rawValue = extractedContent[key];\n if (typeof rawValue === 'string' && hasInsertionVars(rawValue)) {\n const currentVal = finalContent[key];\n if (typeof currentVal === 'string') {\n (finalContent as any)[key] = {\n nodeType: NodeTypes.INSERTION,\n [NodeTypes.INSERTION]: currentVal,\n fields: getInsertionFields(rawValue),\n };\n }\n }\n }\n\n return finalContent;\n};\n\n/**\n * Helper to write extracted content to dictionary file(s).\n */\nexport const writeContentHelper = async (\n extractedContent: Record<string, string>,\n dictionaryKey: DictionaryKey,\n filePath: string,\n configuration: IntlayerConfig\n): Promise<string> => {\n const { absolutePath, isPerLocale } = await resolveContentFilePaths(\n filePath,\n dictionaryKey,\n configuration\n );\n\n const { defaultLocale } = configuration.internationalization;\n const { baseDir } = configuration.system;\n\n if (!cachedBundleFilePath) {\n cachedBundleFilePath = await ensureIntlayerBundle(configuration);\n }\n\n const outputDir = dirname(absolutePath);\n\n // Ensure output directory exists\n await mkdir(outputDir, { recursive: true });\n\n // Read existing dictionary to preserve translations and metadata\n let existingDictionary: Dictionary | null = null;\n\n if (existsSync(absolutePath)) {\n try {\n const dictionary = await loadContentDeclaration(\n absolutePath,\n configuration,\n cachedBundleFilePath\n );\n\n existingDictionary = dictionary ?? null;\n } catch (error) {\n console.error(error);\n }\n }\n\n const relativeContentFilePath = relative(baseDir, absolutePath);\n\n let mergedDictionary: Dictionary;\n\n if (isPerLocale) {\n // Per-locale format: simple string content for a single locale\n const mergedContent = mergeWithExistingPerLocaleDictionary(\n extractedContent,\n existingDictionary\n );\n\n mergedDictionary = {\n // Preserve existing metadata\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n locale: defaultLocale,\n filePath: relativeContentFilePath,\n };\n } else {\n // Multilingual format: content wrapped in translation nodes for multiple locales\n const mergedContent = mergeWithExistingMultilingualDictionary(\n extractedContent,\n existingDictionary,\n defaultLocale\n );\n\n mergedDictionary = {\n // Preserve existing metadata\n ...existingDictionary,\n key: dictionaryKey,\n content: mergedContent,\n filePath: relativeContentFilePath,\n };\n }\n\n const relativeDir = relative(baseDir, outputDir);\n\n const writeResult = await writeContentDeclaration(\n mergedDictionary,\n configuration,\n {\n newDictionariesPath: relativeDir,\n localeList: [defaultLocale],\n }\n );\n\n // Build the dictionary immediately\n const dictionaryToBuild: Dictionary = {\n ...mergedDictionary,\n filePath: relative(baseDir, writeResult?.path ?? absolutePath),\n };\n\n await buildDictionary([dictionaryToBuild], configuration);\n\n return absolutePath;\n};\n"],"mappings":"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"}
@@ -15,7 +15,7 @@ let _intlayer_config_node = require("@intlayer/config/node");
15
15
  let node_fs = require("node:fs");
16
16
  let _intlayer_config_utils = require("@intlayer/config/utils");
17
17
  let _intlayer_unmerged_dictionaries_entry = require("@intlayer/unmerged-dictionaries-entry");
18
- let _intlayer_chokidar_cli = require("@intlayer/chokidar/cli");
18
+ let _intlayer_engine_cli = require("@intlayer/engine/cli");
19
19
  let node_child_process = require("node:child_process");
20
20
 
21
21
  //#region src/extractContent/extractContent.ts
@@ -69,7 +69,7 @@ const processFileInternal = (filePath, packageName, options, dependencies, saveC
69
69
  if (!hasFrontmatter) modifiedFullCode = modifiedFullCode.replace(/\n;\n---\n/, "\n---\n");
70
70
  if (saveComponent) {
71
71
  (0, node_fs.writeFileSync)(filePath, modifiedFullCode);
72
- const formatCommand = (0, _intlayer_chokidar_cli.detectFormatCommand)(configuration);
72
+ const formatCommand = (0, _intlayer_engine_cli.detectFormatCommand)(configuration);
73
73
  if (formatCommand) try {
74
74
  (0, node_child_process.execSync)(formatCommand.replace("{{file}}", filePath), {
75
75
  stdio: "inherit",
@@ -110,7 +110,7 @@ const handleExtractionSideEffects = async (extractedContentMap, filePath, option
110
110
  appLogger(`${(0, _intlayer_config_logger.colorize)("Compiler:", _intlayer_config_colors.GREY_DARK)} Created content file: ${(0, _intlayer_config_logger.colorizePath)(relativeContentFilePath)}`);
111
111
  }
112
112
  if (saveComponent) {
113
- const formatCommand = (0, _intlayer_chokidar_cli.detectFormatCommand)(configuration);
113
+ const formatCommand = (0, _intlayer_engine_cli.detectFormatCommand)(configuration);
114
114
  if (formatCommand) try {
115
115
  (0, node_child_process.execSync)(formatCommand.replace("{{file}}", filePath), {
116
116
  stdio: "inherit",