@intlayer/babel 8.4.4 → 8.4.6

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 (139) hide show
  1. package/dist/cjs/_virtual/_rolldown/runtime.cjs +29 -0
  2. package/dist/cjs/babel-plugin-intlayer-extract.cjs +75 -1
  3. package/dist/cjs/babel-plugin-intlayer-extract.cjs.map +1 -1
  4. package/dist/cjs/babel-plugin-intlayer-optimize.cjs +306 -1
  5. package/dist/cjs/babel-plugin-intlayer-optimize.cjs.map +1 -1
  6. package/dist/cjs/extractContent/babelProcessor.cjs +261 -1
  7. package/dist/cjs/extractContent/babelProcessor.cjs.map +1 -1
  8. package/dist/cjs/extractContent/contentWriter.cjs +134 -1
  9. package/dist/cjs/extractContent/contentWriter.cjs.map +1 -1
  10. package/dist/cjs/extractContent/extractContent.cjs +184 -1
  11. package/dist/cjs/extractContent/extractContent.cjs.map +1 -1
  12. package/dist/cjs/extractContent/index.cjs +26 -1
  13. package/dist/cjs/extractContent/processTsxFile.cjs +263 -5
  14. package/dist/cjs/extractContent/processTsxFile.cjs.map +1 -1
  15. package/dist/cjs/extractContent/utils/constants.cjs +42 -1
  16. package/dist/cjs/extractContent/utils/constants.cjs.map +1 -1
  17. package/dist/cjs/extractContent/utils/detectPackageName.cjs +26 -1
  18. package/dist/cjs/extractContent/utils/detectPackageName.cjs.map +1 -1
  19. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs +103 -1
  20. package/dist/cjs/extractContent/utils/extractDictionaryInfo.cjs.map +1 -1
  21. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs +29 -1
  22. package/dist/cjs/extractContent/utils/extractDictionaryKey.cjs.map +1 -1
  23. package/dist/cjs/extractContent/utils/generateKey.cjs +16 -1
  24. package/dist/cjs/extractContent/utils/generateKey.cjs.map +1 -1
  25. package/dist/cjs/extractContent/utils/getComponentName.cjs +18 -1
  26. package/dist/cjs/extractContent/utils/getComponentName.cjs.map +1 -1
  27. package/dist/cjs/extractContent/utils/getExistingIntlayerInfo.cjs +50 -1
  28. package/dist/cjs/extractContent/utils/getExistingIntlayerInfo.cjs.map +1 -1
  29. package/dist/cjs/extractContent/utils/getOrGenerateKey.cjs +19 -1
  30. package/dist/cjs/extractContent/utils/getOrGenerateKey.cjs.map +1 -1
  31. package/dist/cjs/extractContent/utils/index.cjs +27 -1
  32. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs +34 -1
  33. package/dist/cjs/extractContent/utils/resolveDictionaryKey.cjs.map +1 -1
  34. package/dist/cjs/extractContent/utils/shouldExtract.cjs +23 -1
  35. package/dist/cjs/extractContent/utils/shouldExtract.cjs.map +1 -1
  36. package/dist/cjs/getExtractPluginOptions.cjs +41 -1
  37. package/dist/cjs/getExtractPluginOptions.cjs.map +1 -1
  38. package/dist/cjs/getOptimizePluginOptions.cjs +63 -1
  39. package/dist/cjs/getOptimizePluginOptions.cjs.map +1 -1
  40. package/dist/cjs/index.cjs +34 -1
  41. package/dist/esm/_virtual/_rolldown/runtime.mjs +8 -0
  42. package/dist/esm/babel-plugin-intlayer-extract.mjs +72 -1
  43. package/dist/esm/babel-plugin-intlayer-extract.mjs.map +1 -1
  44. package/dist/esm/babel-plugin-intlayer-optimize.mjs +304 -1
  45. package/dist/esm/babel-plugin-intlayer-optimize.mjs.map +1 -1
  46. package/dist/esm/extractContent/babelProcessor.mjs +255 -1
  47. package/dist/esm/extractContent/babelProcessor.mjs.map +1 -1
  48. package/dist/esm/extractContent/contentWriter.mjs +129 -1
  49. package/dist/esm/extractContent/contentWriter.mjs.map +1 -1
  50. package/dist/esm/extractContent/extractContent.mjs +180 -1
  51. package/dist/esm/extractContent/extractContent.mjs.map +1 -1
  52. package/dist/esm/extractContent/index.mjs +10 -1
  53. package/dist/esm/extractContent/processTsxFile.mjs +259 -5
  54. package/dist/esm/extractContent/processTsxFile.mjs.map +1 -1
  55. package/dist/esm/extractContent/utils/constants.mjs +38 -1
  56. package/dist/esm/extractContent/utils/constants.mjs.map +1 -1
  57. package/dist/esm/extractContent/utils/detectPackageName.mjs +24 -1
  58. package/dist/esm/extractContent/utils/detectPackageName.mjs.map +1 -1
  59. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs +98 -1
  60. package/dist/esm/extractContent/utils/extractDictionaryInfo.mjs.map +1 -1
  61. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs +26 -1
  62. package/dist/esm/extractContent/utils/extractDictionaryKey.mjs.map +1 -1
  63. package/dist/esm/extractContent/utils/generateKey.mjs +14 -1
  64. package/dist/esm/extractContent/utils/generateKey.mjs.map +1 -1
  65. package/dist/esm/extractContent/utils/getComponentName.mjs +15 -1
  66. package/dist/esm/extractContent/utils/getComponentName.mjs.map +1 -1
  67. package/dist/esm/extractContent/utils/getExistingIntlayerInfo.mjs +47 -1
  68. package/dist/esm/extractContent/utils/getExistingIntlayerInfo.mjs.map +1 -1
  69. package/dist/esm/extractContent/utils/getOrGenerateKey.mjs +18 -1
  70. package/dist/esm/extractContent/utils/getOrGenerateKey.mjs.map +1 -1
  71. package/dist/esm/extractContent/utils/index.mjs +12 -1
  72. package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs +32 -1
  73. package/dist/esm/extractContent/utils/resolveDictionaryKey.mjs.map +1 -1
  74. package/dist/esm/extractContent/utils/shouldExtract.mjs +21 -1
  75. package/dist/esm/extractContent/utils/shouldExtract.mjs.map +1 -1
  76. package/dist/esm/getExtractPluginOptions.mjs +38 -1
  77. package/dist/esm/getExtractPluginOptions.mjs.map +1 -1
  78. package/dist/esm/getOptimizePluginOptions.mjs +63 -1
  79. package/dist/esm/getOptimizePluginOptions.mjs.map +1 -0
  80. package/dist/esm/index.mjs +14 -1
  81. package/dist/types/babel-plugin-intlayer-extract.d.ts +1 -1
  82. package/dist/types/extractContent/contentWriter.d.ts +36 -2
  83. package/dist/types/extractContent/contentWriter.d.ts.map +1 -0
  84. package/dist/types/extractContent/extractContent.d.ts +37 -2
  85. package/dist/types/extractContent/extractContent.d.ts.map +1 -0
  86. package/dist/types/extractContent/index.d.ts +8 -8
  87. package/dist/types/extractContent/processTsxFile.d.ts +1 -1
  88. package/dist/types/extractContent/processTsxFile.d.ts.map +1 -1
  89. package/dist/types/extractContent/utils/constants.d.ts +20 -2
  90. package/dist/types/extractContent/utils/constants.d.ts.map +1 -0
  91. package/dist/types/extractContent/utils/detectPackageName.d.ts +10 -2
  92. package/dist/types/extractContent/utils/detectPackageName.d.ts.map +1 -0
  93. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts +28 -2
  94. package/dist/types/extractContent/utils/extractDictionaryInfo.d.ts.map +1 -0
  95. package/dist/types/extractContent/utils/extractDictionaryKey.d.ts +11 -2
  96. package/dist/types/extractContent/utils/extractDictionaryKey.d.ts.map +1 -0
  97. package/dist/types/extractContent/utils/generateKey.d.ts +5 -2
  98. package/dist/types/extractContent/utils/generateKey.d.ts.map +1 -0
  99. package/dist/types/extractContent/utils/getComponentName.d.ts +10 -2
  100. package/dist/types/extractContent/utils/getComponentName.d.ts.map +1 -0
  101. package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts +19 -2
  102. package/dist/types/extractContent/utils/getExistingIntlayerInfo.d.ts.map +1 -0
  103. package/dist/types/extractContent/utils/getOrGenerateKey.d.ts +8 -2
  104. package/dist/types/extractContent/utils/getOrGenerateKey.d.ts.map +1 -0
  105. package/dist/types/extractContent/utils/index.d.ts +10 -10
  106. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts +12 -2
  107. package/dist/types/extractContent/utils/resolveDictionaryKey.d.ts.map +1 -0
  108. package/dist/types/extractContent/utils/shouldExtract.d.ts +14 -2
  109. package/dist/types/extractContent/utils/shouldExtract.d.ts.map +1 -0
  110. package/dist/types/index.d.ts +8 -8
  111. package/package.json +9 -9
  112. package/dist/cjs/chunk-Bmb41Sf3.cjs +0 -1
  113. package/dist/esm/getOptimizePluginOptions-BAFPfVq5.mjs +0 -2
  114. package/dist/esm/getOptimizePluginOptions-BAFPfVq5.mjs.map +0 -1
  115. package/dist/types/constants-BLArAqsA.d.ts +0 -20
  116. package/dist/types/constants-BLArAqsA.d.ts.map +0 -1
  117. package/dist/types/contentWriter-I2Ch5yQY.d.ts +0 -36
  118. package/dist/types/contentWriter-I2Ch5yQY.d.ts.map +0 -1
  119. package/dist/types/detectPackageName-C0TfbHa3.d.ts +0 -10
  120. package/dist/types/detectPackageName-C0TfbHa3.d.ts.map +0 -1
  121. package/dist/types/extractContent-AFk68B7L.d.ts +0 -37
  122. package/dist/types/extractContent-AFk68B7L.d.ts.map +0 -1
  123. package/dist/types/extractDictionaryInfo-5GLZsA_I.d.ts +0 -28
  124. package/dist/types/extractDictionaryInfo-5GLZsA_I.d.ts.map +0 -1
  125. package/dist/types/extractDictionaryKey-CHgfwRo6.d.ts +0 -11
  126. package/dist/types/extractDictionaryKey-CHgfwRo6.d.ts.map +0 -1
  127. package/dist/types/generateKey-Cgdh6seq.d.ts +0 -5
  128. package/dist/types/generateKey-Cgdh6seq.d.ts.map +0 -1
  129. package/dist/types/getComponentName-DGlmJa-F.d.ts +0 -10
  130. package/dist/types/getComponentName-DGlmJa-F.d.ts.map +0 -1
  131. package/dist/types/getExistingIntlayerInfo-Cy6Vpcfb.d.ts +0 -19
  132. package/dist/types/getExistingIntlayerInfo-Cy6Vpcfb.d.ts.map +0 -1
  133. package/dist/types/getOrGenerateKey-DtIR0WeU.d.ts +0 -8
  134. package/dist/types/getOrGenerateKey-DtIR0WeU.d.ts.map +0 -1
  135. package/dist/types/index-DK_kKFOF.d.ts +0 -1
  136. package/dist/types/resolveDictionaryKey-CcbieIfX.d.ts +0 -12
  137. package/dist/types/resolveDictionaryKey-CcbieIfX.d.ts.map +0 -1
  138. package/dist/types/shouldExtract-BRaeB9eg.d.ts +0 -14
  139. package/dist/types/shouldExtract-BRaeB9eg.d.ts.map +0 -1
@@ -1,2 +1,262 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require(`../chunk-Bmb41Sf3.cjs`),t=require(`./utils/constants.cjs`),n=require(`./utils/getComponentName.cjs`),r=require(`./utils/getExistingIntlayerInfo.cjs`),i=require(`./utils/getOrGenerateKey.cjs`),a=require(`./utils/resolveDictionaryKey.cjs`),o=require(`./utils/shouldExtract.cjs`);let s=require(`@babel/traverse`);s=e.t(s);let c=require(`@babel/types`);c=e.t(c);const l=typeof s.default==`function`?s.default:s.default.default,u=(e,t,n,r,a,s,l)=>{let u=e.node.children;if(u.length<=1)return!1;let d=[],f=!1,p=!1;for(let e of u)if(c.isJSXText(e)){let t=e.value;t.trim().length>0&&(f=!0),d.push({type:`text`,value:t})}else if(c.isJSXExpressionContainer(e))if(c.isJSXEmptyExpression(e.expression))d.push({type:`text`,value:``});else{let n=e.expression;if(c.isIdentifier(n))d.push({type:`var`,value:n.name,originalExpr:n.name}),p=!0;else if(c.isMemberExpression(n)){let e=t.substring(n.start,n.end),r=c.isIdentifier(n.property)?n.property.name:`var`;d.push({type:`var`,value:r,originalExpr:e}),p=!0}else return!1}else return!1;if(!f)return!1;let m=``;for(let e of d)e.type===`var`?m+=`{{${e.value}}}`:m+=e.value;let h=m.replace(/\s+/g,` `).trim();if(o.shouldExtract(h)){let t=r(e),o=i.getOrGenerateKey(h,t,n,a),c=d.filter(e=>e.type===`var`).map(e=>`${e.value}: ${e.originalExpr}`),f=Array.from(new Set(c));return p?s.push({path:e,key:o,type:`jsx-insertion`,componentKey:t,childrenToReplace:u,variables:f}):s.push({path:e,key:o,type:`jsx-text-combined`,componentKey:t,childrenToReplace:u}),u.forEach(e=>{l.add(e)}),!0}return!1},d=(e,s,d,f=`default`,p,m,h={})=>{let g={},_=[],v=new Set,y=new Map,b=new Map,x=new Set,S,C=[];l(e,{FunctionDeclaration(e){C.push(e)},ArrowFunctionExpression(e){C.push(e)},FunctionExpression(e){C.push(e)}});for(let e of C){let t=r.getExistingIntlayerInfo(e);if(t)y.set(e.node,t.key),x.add(t.key),b.set(e.node,t.hook);else{S||(S=a.resolveDictionaryKey(f,m,p,h,x),x.add(S)),y.set(e.node,S);let t=n.getComponentName(e),r=t?/^[A-Z]/.test(t):!1;b.set(e.node,r?`useIntlayer`:`getIntlayer`)}}let w=e=>{let t=e;for(;t;){if(y.has(t.node))return y.get(t.node);t=t.parentPath}return S||f};l(e,{JSXElement(e){v.has(e.node)||u(e,s,d,w,g,_,v)},JSXFragment(e){v.has(e.node)||u(e,s,d,w,g,_,v)},JSXText(e){if(v.has(e.node))return;let t=e.node.value;if(o.shouldExtract(t)){let n=w(e),r=i.getOrGenerateKey(t.replace(/\s+/g,` `).trim(),n,d,g);_.push({path:e,key:r,type:`jsx-text`,componentKey:n})}},JSXAttribute(e){if(v.has(e.node))return;let n=e.node.name.name;if(typeof n!=`string`||!t.ATTRIBUTES_TO_EXTRACT.includes(n))return;let r=e.node.value;if(c.isStringLiteral(r)&&o.shouldExtract(r.value)){let t=w(e),n=i.getOrGenerateKey(r.value.trim(),t,d,g);_.push({path:e,key:n,type:`jsx-attribute`,componentKey:t})}},StringLiteral(e){if(v.has(e.node))return;let t=e.node.value;if(!o.shouldExtract(t))return;let n=e.parentPath;if(n.isImportDeclaration()||n.isImportSpecifier()||n.isExportDeclaration()||n.isJSXAttribute()||n.isCallExpression()&&c.isMemberExpression(n.node.callee)&&c.isIdentifier(n.node.callee.object)&&n.node.callee.object.name===`console`&&c.isIdentifier(n.node.callee.property)&&n.node.callee.property.name===`log`||n.isObjectProperty()&&n.node.key===e.node||n.isMemberExpression()&&n.node.property===e.node)return;let r=w(e),a=i.getOrGenerateKey(t.trim(),r,d,g);_.push({path:e,key:a,type:`string-literal`,componentKey:r})}});let T=new Set;for(let e of C)if(_.some(t=>{let n=t.path;for(;n;){if(n.node===e.node)return!0;n=n.parentPath}return!1})){let t=y.get(e.node),n=!1,i=e.parentPath;for(;i;){let e=C.find(e=>e.node===i?.node);if(e&&y.get(e.node)===t){let t=_.some(t=>{let n=t.path;for(;n;){if(n.node===e.node)return!0;n=n.parentPath}return!1}),i=r.getExistingIntlayerInfo(e);if(t||i){n=!0;break}}i=i.parentPath}n||T.add(e)}return{extractedContent:g,replacements:_,componentsNeedingHooks:T,componentKeyMap:y,componentPaths:C,hookMap:b,isSolid:!1}},f=(e,t,n,r,i,a={})=>{let{extractedContent:o,replacements:s}=d(e,t,n,`default`,r,i,a),c={};for(let e of Object.values(o))Object.assign(c,e);return{extractedContent:c,replacements:s}};exports.extractBabelContentForComponents=d,exports.extractTsContent=f,exports.handleJsxInsertionBabel=u;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ const require_extractContent_utils_constants = require('./utils/constants.cjs');
4
+ const require_extractContent_utils_getComponentName = require('./utils/getComponentName.cjs');
5
+ const require_extractContent_utils_getExistingIntlayerInfo = require('./utils/getExistingIntlayerInfo.cjs');
6
+ const require_extractContent_utils_getOrGenerateKey = require('./utils/getOrGenerateKey.cjs');
7
+ const require_extractContent_utils_resolveDictionaryKey = require('./utils/resolveDictionaryKey.cjs');
8
+ const require_extractContent_utils_shouldExtract = require('./utils/shouldExtract.cjs');
9
+ let _babel_traverse = require("@babel/traverse");
10
+ _babel_traverse = require_runtime.__toESM(_babel_traverse);
11
+ let _babel_types = require("@babel/types");
12
+ _babel_types = require_runtime.__toESM(_babel_types);
13
+
14
+ //#region src/extractContent/babelProcessor.ts
15
+ const traverse = typeof _babel_traverse.default === "function" ? _babel_traverse.default : _babel_traverse.default.default;
16
+ /**
17
+ * Handles JSX insertions (elements with multiple children, including expressions).
18
+ * Replaces complex JSX structures with variable-based translations.
19
+ */
20
+ const handleJsxInsertionBabel = (path, fileCode, existingKeys, getComponentKeyForPath, extractedContent, replacements, handledNodes) => {
21
+ const children = path.node.children;
22
+ if (children.length <= 1) return false;
23
+ const parts = [];
24
+ let hasSignificantText = false;
25
+ let hasVariables = false;
26
+ for (const child of children) if (_babel_types.isJSXText(child)) {
27
+ const text = child.value;
28
+ if (text.trim().length > 0) hasSignificantText = true;
29
+ parts.push({
30
+ type: "text",
31
+ value: text
32
+ });
33
+ } else if (_babel_types.isJSXExpressionContainer(child)) if (_babel_types.isJSXEmptyExpression(child.expression)) parts.push({
34
+ type: "text",
35
+ value: ""
36
+ });
37
+ else {
38
+ const expr = child.expression;
39
+ if (_babel_types.isIdentifier(expr)) {
40
+ parts.push({
41
+ type: "var",
42
+ value: expr.name,
43
+ originalExpr: expr.name
44
+ });
45
+ hasVariables = true;
46
+ } else if (_babel_types.isMemberExpression(expr)) {
47
+ const code = fileCode.substring(expr.start, expr.end);
48
+ const varName = _babel_types.isIdentifier(expr.property) ? expr.property.name : "var";
49
+ parts.push({
50
+ type: "var",
51
+ value: varName,
52
+ originalExpr: code
53
+ });
54
+ hasVariables = true;
55
+ } else return false;
56
+ }
57
+ else return false;
58
+ if (!hasSignificantText) return false;
59
+ let combinedString = "";
60
+ for (const part of parts) if (part.type === "var") combinedString += `{{${part.value}}}`;
61
+ else combinedString += part.value;
62
+ const cleanString = combinedString.replace(/\s+/g, " ").trim();
63
+ if (require_extractContent_utils_shouldExtract.shouldExtract(cleanString)) {
64
+ const componentKey = getComponentKeyForPath(path);
65
+ const key = require_extractContent_utils_getOrGenerateKey.getOrGenerateKey(cleanString, componentKey, existingKeys, extractedContent);
66
+ const varMap = parts.filter((part) => part.type === "var").map((part) => `${part.value}: ${part.originalExpr}`);
67
+ const uniqueVars = Array.from(new Set(varMap));
68
+ if (hasVariables) replacements.push({
69
+ path,
70
+ key,
71
+ type: "jsx-insertion",
72
+ componentKey,
73
+ childrenToReplace: children,
74
+ variables: uniqueVars
75
+ });
76
+ else replacements.push({
77
+ path,
78
+ key,
79
+ type: "jsx-text-combined",
80
+ componentKey,
81
+ childrenToReplace: children
82
+ });
83
+ children.forEach((child) => {
84
+ handledNodes.add(child);
85
+ });
86
+ return true;
87
+ }
88
+ return false;
89
+ };
90
+ /**
91
+ * Traverses the AST to identify components and extract content.
92
+ * Returns extraction results and metadata about which components need Intlayer hooks.
93
+ */
94
+ const extractBabelContentForComponents = (ast, fileCode, existingKeys, defaultKey = "default", configuration, filePath, unmergedDictionaries = {}) => {
95
+ const extractedContent = {};
96
+ const replacements = [];
97
+ const handledNodes = /* @__PURE__ */ new Set();
98
+ const componentKeyMap = /* @__PURE__ */ new Map();
99
+ const hookMap = /* @__PURE__ */ new Map();
100
+ const usedKeysInFile = /* @__PURE__ */ new Set();
101
+ let globalFileKey;
102
+ const componentPaths = [];
103
+ traverse(ast, {
104
+ FunctionDeclaration(path) {
105
+ componentPaths.push(path);
106
+ },
107
+ ArrowFunctionExpression(path) {
108
+ componentPaths.push(path);
109
+ },
110
+ FunctionExpression(path) {
111
+ componentPaths.push(path);
112
+ }
113
+ });
114
+ for (const path of componentPaths) {
115
+ const existingInfo = require_extractContent_utils_getExistingIntlayerInfo.getExistingIntlayerInfo(path);
116
+ if (existingInfo) {
117
+ componentKeyMap.set(path.node, existingInfo.key);
118
+ usedKeysInFile.add(existingInfo.key);
119
+ hookMap.set(path.node, existingInfo.hook);
120
+ } else {
121
+ if (!globalFileKey) {
122
+ globalFileKey = require_extractContent_utils_resolveDictionaryKey.resolveDictionaryKey(defaultKey, filePath, configuration, unmergedDictionaries, usedKeysInFile);
123
+ usedKeysInFile.add(globalFileKey);
124
+ }
125
+ componentKeyMap.set(path.node, globalFileKey);
126
+ const compName = require_extractContent_utils_getComponentName.getComponentName(path);
127
+ const isComponent = compName ? /^[A-Z]/.test(compName) : false;
128
+ hookMap.set(path.node, isComponent ? "useIntlayer" : "getIntlayer");
129
+ }
130
+ }
131
+ const getComponentKeyForPath = (path) => {
132
+ let current = path;
133
+ while (current) {
134
+ if (componentKeyMap.has(current.node)) return componentKeyMap.get(current.node);
135
+ current = current.parentPath;
136
+ }
137
+ return globalFileKey || defaultKey;
138
+ };
139
+ traverse(ast, {
140
+ JSXElement(path) {
141
+ if (handledNodes.has(path.node)) return;
142
+ handleJsxInsertionBabel(path, fileCode, existingKeys, getComponentKeyForPath, extractedContent, replacements, handledNodes);
143
+ },
144
+ JSXFragment(path) {
145
+ if (handledNodes.has(path.node)) return;
146
+ handleJsxInsertionBabel(path, fileCode, existingKeys, getComponentKeyForPath, extractedContent, replacements, handledNodes);
147
+ },
148
+ JSXText(path) {
149
+ if (handledNodes.has(path.node)) return;
150
+ const text = path.node.value;
151
+ if (require_extractContent_utils_shouldExtract.shouldExtract(text)) {
152
+ const componentKey = getComponentKeyForPath(path);
153
+ const key = require_extractContent_utils_getOrGenerateKey.getOrGenerateKey(text.replace(/\s+/g, " ").trim(), componentKey, existingKeys, extractedContent);
154
+ replacements.push({
155
+ path,
156
+ key,
157
+ type: "jsx-text",
158
+ componentKey
159
+ });
160
+ }
161
+ },
162
+ JSXAttribute(path) {
163
+ if (handledNodes.has(path.node)) return;
164
+ const name = path.node.name.name;
165
+ if (typeof name !== "string" || !require_extractContent_utils_constants.ATTRIBUTES_TO_EXTRACT.includes(name)) return;
166
+ const value = path.node.value;
167
+ if (_babel_types.isStringLiteral(value) && require_extractContent_utils_shouldExtract.shouldExtract(value.value)) {
168
+ const componentKey = getComponentKeyForPath(path);
169
+ const key = require_extractContent_utils_getOrGenerateKey.getOrGenerateKey(value.value.trim(), componentKey, existingKeys, extractedContent);
170
+ replacements.push({
171
+ path,
172
+ key,
173
+ type: "jsx-attribute",
174
+ componentKey
175
+ });
176
+ }
177
+ },
178
+ StringLiteral(path) {
179
+ if (handledNodes.has(path.node)) return;
180
+ const text = path.node.value;
181
+ if (!require_extractContent_utils_shouldExtract.shouldExtract(text)) return;
182
+ const parent = path.parentPath;
183
+ if (parent.isImportDeclaration() || parent.isImportSpecifier() || parent.isExportDeclaration()) return;
184
+ if (parent.isJSXAttribute()) return;
185
+ if (parent.isCallExpression() && _babel_types.isMemberExpression(parent.node.callee)) {
186
+ 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;
187
+ }
188
+ if (parent.isObjectProperty() && parent.node.key === path.node) return;
189
+ if (parent.isMemberExpression() && parent.node.property === path.node) return;
190
+ const componentKey = getComponentKeyForPath(path);
191
+ const key = require_extractContent_utils_getOrGenerateKey.getOrGenerateKey(text.trim(), componentKey, existingKeys, extractedContent);
192
+ replacements.push({
193
+ path,
194
+ key,
195
+ type: "string-literal",
196
+ componentKey
197
+ });
198
+ }
199
+ });
200
+ const componentsNeedingHooks = /* @__PURE__ */ new Set();
201
+ for (const componentPath of componentPaths) if (replacements.some((replacement) => {
202
+ let current = replacement.path;
203
+ while (current) {
204
+ if (current.node === componentPath.node) return true;
205
+ current = current.parentPath;
206
+ }
207
+ return false;
208
+ })) {
209
+ const key = componentKeyMap.get(componentPath.node);
210
+ let ancestorProvidesKey = false;
211
+ let currentPath = componentPath.parentPath;
212
+ while (currentPath) {
213
+ const ancestorPath = componentPaths.find((path) => path.node === currentPath?.node);
214
+ if (ancestorPath) {
215
+ if (componentKeyMap.get(ancestorPath.node) === key) {
216
+ const ancestorHasReplacements = replacements.some((replacement) => {
217
+ let rPath = replacement.path;
218
+ while (rPath) {
219
+ if (rPath.node === ancestorPath.node) return true;
220
+ rPath = rPath.parentPath;
221
+ }
222
+ return false;
223
+ });
224
+ const existingInfo = require_extractContent_utils_getExistingIntlayerInfo.getExistingIntlayerInfo(ancestorPath);
225
+ if (ancestorHasReplacements || existingInfo) {
226
+ ancestorProvidesKey = true;
227
+ break;
228
+ }
229
+ }
230
+ }
231
+ currentPath = currentPath.parentPath;
232
+ }
233
+ if (!ancestorProvidesKey) componentsNeedingHooks.add(componentPath);
234
+ }
235
+ return {
236
+ extractedContent,
237
+ replacements,
238
+ componentsNeedingHooks,
239
+ componentKeyMap,
240
+ componentPaths,
241
+ hookMap,
242
+ isSolid: false
243
+ };
244
+ };
245
+ /**
246
+ * High-level function to extract content from TS/JS/JSX/TSX AST.
247
+ */
248
+ const extractTsContent = (ast, fileCode, existingKeys, configuration, filePath, unmergedDictionaries = {}) => {
249
+ const { extractedContent, replacements } = extractBabelContentForComponents(ast, fileCode, existingKeys, "default", configuration, filePath, unmergedDictionaries);
250
+ const flatContent = {};
251
+ for (const group of Object.values(extractedContent)) Object.assign(flatContent, group);
252
+ return {
253
+ extractedContent: flatContent,
254
+ replacements
255
+ };
256
+ };
257
+
258
+ //#endregion
259
+ exports.extractBabelContentForComponents = extractBabelContentForComponents;
260
+ exports.extractTsContent = extractTsContent;
261
+ exports.handleJsxInsertionBabel = handleJsxInsertionBabel;
2
262
  //# sourceMappingURL=babelProcessor.cjs.map
@@ -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 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 {\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 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 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 (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n componentKeyMap.set(path.node, globalFileKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n hookMap.set(path.node, isComponent ? 'useIntlayer' : 'getIntlayer');\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 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 });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\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) {\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 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 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 {\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 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 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 (!globalFileKey) {\n globalFileKey = resolveDictionaryKey(\n defaultKey,\n filePath,\n configuration,\n unmergedDictionaries,\n usedKeysInFile\n );\n usedKeysInFile.add(globalFileKey);\n }\n componentKeyMap.set(path.node, globalFileKey);\n\n const compName = getComponentName(path);\n const isComponent = compName ? /^[A-Z]/.test(compName) : false;\n hookMap.set(path.node, isComponent ? 'useIntlayer' : 'getIntlayer');\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 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 });\n\n const componentsNeedingHooks = new Set<NodePath>();\n for (const componentPath of componentPaths) {\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) {\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,2 +1,135 @@
1
- Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`}),require(`../chunk-Bmb41Sf3.cjs`);const e=require(`./utils/extractDictionaryInfo.cjs`);let t=require(`node:fs`),n=require(`node:fs/promises`),r=require(`node:path`),i=require(`@intlayer/chokidar/build`),a=require(`@intlayer/core/plugins`),o=require(`@intlayer/types/nodeType`);const s=e=>/\{\{[^}]+\}\}/.test(e),c=e=>{let t=[],n=/\{\{([^}]+)\}\}/g,r;for(let i=n.exec(e);i!==null;i=n.exec(e)){r=i;let e=r[1].trim();t.includes(e)||t.push(e)}return t};let l;const u=(e,t,n)=>{let r=(0,a.insertContentInDictionary)(t??{key:``,content:{},filePath:``},e,n).content,i={};for(let t in e)i[t]=r[t];for(let t in e){let n=e[t];if(typeof n==`string`&&s(n)){let e=i[t];e&&e.nodeType===o.NodeType.Translation&&(i[t]={nodeType:o.NodeType.Insertion,[o.NodeType.Insertion]:e,fields:c(n)})}}return i},d=(e,t)=>{let n=(0,a.insertContentInDictionary)(t??{key:``,content:{},filePath:``},e).content,r={};for(let t in e)r[t]=n[t];for(let t in e){let n=e[t];if(typeof n==`string`&&s(n)){let e=r[t];typeof e==`string`&&(r[t]={nodeType:o.NodeType.Insertion,[o.NodeType.Insertion]:e,fields:c(n)})}}return r},f=async(a,o,s,c)=>{let{absolutePath:f,isPerLocale:p}=await e.resolveContentFilePaths(s,o,c),{defaultLocale:m}=c.internationalization,{baseDir:h}=c.system;l||=await(0,i.ensureIntlayerBundle)(c);let g=(0,r.dirname)(f);await(0,n.mkdir)(g,{recursive:!0});let _=null;if((0,t.existsSync)(f))try{_=await(0,i.loadContentDeclaration)(f,c,l)??null}catch(e){console.error(e)}let v=(0,r.relative)(h,f),y;if(p){let e=d(a,_);y={..._,key:o,content:e,locale:m,filePath:v}}else{let e=u(a,_,m);y={..._,key:o,content:e,filePath:v}}let b=(0,r.relative)(h,g),x=await(0,i.writeContentDeclaration)(y,c,{newDictionariesPath:b,localeList:[m]});return await(0,i.buildDictionary)([{...y,filePath:(0,r.relative)(h,x?.path??f)}],c),f};exports.mergeWithExistingMultilingualDictionary=u,exports.mergeWithExistingPerLocaleDictionary=d,exports.writeContentHelper=f;
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
+ const require_extractContent_utils_extractDictionaryInfo = require('./utils/extractDictionaryInfo.cjs');
4
+ let node_fs = require("node:fs");
5
+ let node_fs_promises = require("node:fs/promises");
6
+ let node_path = require("node:path");
7
+ let _intlayer_chokidar_build = require("@intlayer/chokidar/build");
8
+ let _intlayer_core_plugins = require("@intlayer/core/plugins");
9
+ let _intlayer_types_nodeType = require("@intlayer/types/nodeType");
10
+ _intlayer_types_nodeType = require_runtime.__toESM(_intlayer_types_nodeType);
11
+
12
+ //#region src/extractContent/contentWriter.ts
13
+ const hasInsertionVars = (str) => /\{\{[^}]+\}\}/.test(str);
14
+ const getInsertionFields = (template) => {
15
+ const fields = [];
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 field = match[1].trim();
21
+ if (!fields.includes(field)) fields.push(field);
22
+ }
23
+ return fields;
24
+ };
25
+ /**
26
+ * Cached bundle file path to optimize performance
27
+ */
28
+ let cachedBundleFilePath;
29
+ /**
30
+ * Merge extracted content with existing dictionary for multilingual format.
31
+ * - Keys in extracted but not in existing: added with default locale only
32
+ * - Keys in both: preserve existing translations, update default locale value
33
+ * - Keys in existing but not in extracted: removed (no longer in source)
34
+ */
35
+ const mergeWithExistingMultilingualDictionary = (extractedContent, existingDictionary, defaultLocale) => {
36
+ const mergedContent = (0, _intlayer_core_plugins.insertContentInDictionary)(existingDictionary ?? {
37
+ key: "",
38
+ content: {},
39
+ filePath: ""
40
+ }, extractedContent, defaultLocale).content;
41
+ const finalContent = {};
42
+ for (const key in extractedContent) finalContent[key] = mergedContent[key];
43
+ for (const key in extractedContent) {
44
+ const rawValue = extractedContent[key];
45
+ if (typeof rawValue === "string" && hasInsertionVars(rawValue)) {
46
+ const node = finalContent[key];
47
+ if (node && node.nodeType === _intlayer_types_nodeType.TRANSLATION) finalContent[key] = {
48
+ nodeType: _intlayer_types_nodeType.INSERTION,
49
+ [_intlayer_types_nodeType.INSERTION]: node,
50
+ fields: getInsertionFields(rawValue)
51
+ };
52
+ }
53
+ }
54
+ return finalContent;
55
+ };
56
+ /**
57
+ * Merge extracted content with existing dictionary for per-locale format.
58
+ * - Keys in extracted but not in existing: added
59
+ * - Keys in both: update value
60
+ * - Keys in existing but not in extracted: removed (no longer in source)
61
+ */
62
+ const mergeWithExistingPerLocaleDictionary = (extractedContent, existingDictionary) => {
63
+ const mergedContent = (0, _intlayer_core_plugins.insertContentInDictionary)(existingDictionary ?? {
64
+ key: "",
65
+ content: {},
66
+ filePath: ""
67
+ }, extractedContent).content;
68
+ const finalContent = {};
69
+ for (const key in extractedContent) finalContent[key] = mergedContent[key];
70
+ for (const key in extractedContent) {
71
+ const rawValue = extractedContent[key];
72
+ if (typeof rawValue === "string" && hasInsertionVars(rawValue)) {
73
+ const currentVal = finalContent[key];
74
+ if (typeof currentVal === "string") finalContent[key] = {
75
+ nodeType: _intlayer_types_nodeType.INSERTION,
76
+ [_intlayer_types_nodeType.INSERTION]: currentVal,
77
+ fields: getInsertionFields(rawValue)
78
+ };
79
+ }
80
+ }
81
+ return finalContent;
82
+ };
83
+ /**
84
+ * Helper to write extracted content to dictionary file(s).
85
+ */
86
+ const writeContentHelper = async (extractedContent, dictionaryKey, filePath, configuration) => {
87
+ const { absolutePath, isPerLocale } = await require_extractContent_utils_extractDictionaryInfo.resolveContentFilePaths(filePath, dictionaryKey, configuration);
88
+ const { defaultLocale } = configuration.internationalization;
89
+ const { baseDir } = configuration.system;
90
+ if (!cachedBundleFilePath) cachedBundleFilePath = await (0, _intlayer_chokidar_build.ensureIntlayerBundle)(configuration);
91
+ const outputDir = (0, node_path.dirname)(absolutePath);
92
+ await (0, node_fs_promises.mkdir)(outputDir, { recursive: true });
93
+ let existingDictionary = null;
94
+ if ((0, node_fs.existsSync)(absolutePath)) try {
95
+ existingDictionary = await (0, _intlayer_chokidar_build.loadContentDeclaration)(absolutePath, configuration, cachedBundleFilePath) ?? null;
96
+ } catch (error) {
97
+ console.error(error);
98
+ }
99
+ const relativeContentFilePath = (0, node_path.relative)(baseDir, absolutePath);
100
+ let mergedDictionary;
101
+ if (isPerLocale) {
102
+ const mergedContent = mergeWithExistingPerLocaleDictionary(extractedContent, existingDictionary);
103
+ mergedDictionary = {
104
+ ...existingDictionary,
105
+ key: dictionaryKey,
106
+ content: mergedContent,
107
+ locale: defaultLocale,
108
+ filePath: relativeContentFilePath
109
+ };
110
+ } else {
111
+ const mergedContent = mergeWithExistingMultilingualDictionary(extractedContent, existingDictionary, defaultLocale);
112
+ mergedDictionary = {
113
+ ...existingDictionary,
114
+ key: dictionaryKey,
115
+ content: mergedContent,
116
+ filePath: relativeContentFilePath
117
+ };
118
+ }
119
+ const relativeDir = (0, node_path.relative)(baseDir, outputDir);
120
+ const writeResult = await (0, _intlayer_chokidar_build.writeContentDeclaration)(mergedDictionary, configuration, {
121
+ newDictionariesPath: relativeDir,
122
+ localeList: [defaultLocale]
123
+ });
124
+ await (0, _intlayer_chokidar_build.buildDictionary)([{
125
+ ...mergedDictionary,
126
+ filePath: (0, node_path.relative)(baseDir, writeResult?.path ?? absolutePath)
127
+ }], configuration);
128
+ return absolutePath;
129
+ };
130
+
131
+ //#endregion
132
+ exports.mergeWithExistingMultilingualDictionary = mergeWithExistingMultilingualDictionary;
133
+ exports.mergeWithExistingPerLocaleDictionary = mergeWithExistingPerLocaleDictionary;
134
+ exports.writeContentHelper = writeContentHelper;
2
135
  //# sourceMappingURL=contentWriter.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"contentWriter.cjs","names":["NodeType","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 { NodeType } 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 field = match[1].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 finalContent[key] = mergedContent[key];\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 === NodeType.Translation) {\n (finalContent as any)[key] = {\n nodeType: NodeType.Insertion,\n [NodeType.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 finalContent[key] = mergedContent[key];\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: NodeType.Insertion,\n [NodeType.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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"}
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 field = match[1].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 finalContent[key] = mergedContent[key];\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 finalContent[key] = mergedContent[key];\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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"}