gt 2.14.35 → 2.14.36

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 (429) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/api/collectUserEditDiffs.js +112 -155
  3. package/dist/api/collectUserEditDiffs.js.map +1 -0
  4. package/dist/api/downloadFileBatch.js +164 -241
  5. package/dist/api/downloadFileBatch.js.map +1 -0
  6. package/dist/api/saveLocalEdits.js +37 -41
  7. package/dist/api/saveLocalEdits.js.map +1 -0
  8. package/dist/bin/bin-entry.js +17 -7
  9. package/dist/bin/bin-entry.js.map +1 -0
  10. package/dist/bin/bin-main.js +43 -61
  11. package/dist/bin/bin-main.js.map +1 -0
  12. package/dist/cli/base.js +382 -497
  13. package/dist/cli/base.js.map +1 -0
  14. package/dist/cli/commands/download.js +41 -49
  15. package/dist/cli/commands/download.js.map +1 -0
  16. package/dist/cli/commands/enqueue.js +26 -25
  17. package/dist/cli/commands/enqueue.js.map +1 -0
  18. package/dist/cli/commands/setupProject.js +33 -36
  19. package/dist/cli/commands/setupProject.js.map +1 -0
  20. package/dist/cli/commands/stage.js +53 -61
  21. package/dist/cli/commands/stage.js.map +1 -0
  22. package/dist/cli/commands/translate.js +75 -112
  23. package/dist/cli/commands/translate.js.map +1 -0
  24. package/dist/cli/commands/upload.js +185 -213
  25. package/dist/cli/commands/upload.js.map +1 -0
  26. package/dist/cli/commands/utils/validation.js +39 -34
  27. package/dist/cli/commands/utils/validation.js.map +1 -0
  28. package/dist/cli/flags.js +35 -62
  29. package/dist/cli/flags.js.map +1 -0
  30. package/dist/cli/inline.js +112 -137
  31. package/dist/cli/inline.js.map +1 -0
  32. package/dist/cli/next.js +17 -12
  33. package/dist/cli/next.js.map +1 -0
  34. package/dist/cli/node.js +19 -15
  35. package/dist/cli/node.js.map +1 -0
  36. package/dist/cli/python.js +13 -8
  37. package/dist/cli/python.js.map +1 -0
  38. package/dist/cli/react.js +61 -78
  39. package/dist/cli/react.js.map +1 -0
  40. package/dist/config/defaults.js +16 -11
  41. package/dist/config/defaults.js.map +1 -0
  42. package/dist/config/generateSettings.js +167 -269
  43. package/dist/config/generateSettings.js.map +1 -0
  44. package/dist/config/optionPresets.js +78 -96
  45. package/dist/config/optionPresets.js.map +1 -0
  46. package/dist/config/resolveConfig.js +27 -32
  47. package/dist/config/resolveConfig.js.map +1 -0
  48. package/dist/config/utils.js +7 -3
  49. package/dist/config/utils.js.map +1 -0
  50. package/dist/config/validateSettings.js +19 -30
  51. package/dist/config/validateSettings.js.map +1 -0
  52. package/dist/console/colors.js +18 -13
  53. package/dist/console/colors.js.map +1 -0
  54. package/dist/console/displayTranslateSummary.js +40 -37
  55. package/dist/console/displayTranslateSummary.js.map +1 -0
  56. package/dist/console/formatting.js +8 -5
  57. package/dist/console/formatting.js.map +1 -0
  58. package/dist/console/index.d.ts +11 -9
  59. package/dist/console/index.js +53 -50
  60. package/dist/console/index.js.map +1 -0
  61. package/dist/console/inkFields.d.ts +23 -0
  62. package/dist/console/inkFields.js +87 -0
  63. package/dist/console/inkFields.js.map +1 -0
  64. package/dist/console/inkLayout.d.ts +7 -0
  65. package/dist/console/inkLayout.js +139 -0
  66. package/dist/console/inkLayout.js.map +1 -0
  67. package/dist/console/inkLocaleData.d.ts +4 -0
  68. package/dist/console/inkLocaleData.js +32 -0
  69. package/dist/console/inkLocaleData.js.map +1 -0
  70. package/dist/console/inkPrompts.d.ts +8 -0
  71. package/dist/console/inkPrompts.js +496 -0
  72. package/dist/console/inkPrompts.js.map +1 -0
  73. package/dist/console/inkSession.d.ts +3 -0
  74. package/dist/console/inkSession.js +42 -0
  75. package/dist/console/inkSession.js.map +1 -0
  76. package/dist/console/inkTerminal.d.ts +4 -0
  77. package/dist/console/inkTerminal.js +15 -0
  78. package/dist/console/inkTerminal.js.map +1 -0
  79. package/dist/console/inkTypes.d.ts +66 -0
  80. package/dist/console/inkTypes.js +1 -0
  81. package/dist/console/inkUtils.d.ts +24 -0
  82. package/dist/console/inkUtils.js +87 -0
  83. package/dist/console/inkUtils.js.map +1 -0
  84. package/dist/console/logger.js +209 -249
  85. package/dist/console/logger.js.map +1 -0
  86. package/dist/console/logging.d.ts +14 -0
  87. package/dist/console/logging.js +203 -162
  88. package/dist/console/logging.js.map +1 -0
  89. package/dist/console/promptParsing.d.ts +5 -0
  90. package/dist/console/promptParsing.js +28 -0
  91. package/dist/console/promptParsing.js.map +1 -0
  92. package/dist/console/terminalSession.d.ts +5 -0
  93. package/dist/console/terminalSession.js +38 -0
  94. package/dist/console/terminalSession.js.map +1 -0
  95. package/dist/extraction/index.js +3 -2
  96. package/dist/extraction/mapToUpdates.js +19 -18
  97. package/dist/extraction/mapToUpdates.js.map +1 -0
  98. package/dist/extraction/postProcess.js +68 -86
  99. package/dist/extraction/postProcess.js.map +1 -0
  100. package/dist/formats/files/aggregateFiles.js +223 -304
  101. package/dist/formats/files/aggregateFiles.js.map +1 -0
  102. package/dist/formats/files/collectFiles.js +53 -54
  103. package/dist/formats/files/collectFiles.js.map +1 -0
  104. package/dist/formats/files/convertToFileTranslationData.js +21 -19
  105. package/dist/formats/files/convertToFileTranslationData.js.map +1 -0
  106. package/dist/formats/files/fileMapping.js +82 -119
  107. package/dist/formats/files/fileMapping.js.map +1 -0
  108. package/dist/formats/files/preprocess/mdx.js +15 -12
  109. package/dist/formats/files/preprocess/mdx.js.map +1 -0
  110. package/dist/formats/files/preprocess/mintlify.js +15 -13
  111. package/dist/formats/files/preprocess/mintlify.js.map +1 -0
  112. package/dist/formats/files/preprocessContent.js +20 -21
  113. package/dist/formats/files/preprocessContent.js.map +1 -0
  114. package/dist/formats/files/save.js +18 -15
  115. package/dist/formats/files/save.js.map +1 -0
  116. package/dist/formats/files/supportedFiles.js +27 -22
  117. package/dist/formats/files/supportedFiles.js.map +1 -0
  118. package/dist/formats/files/transformFormat.js +93 -100
  119. package/dist/formats/files/transformFormat.js.map +1 -0
  120. package/dist/formats/json/extractJson.js +83 -110
  121. package/dist/formats/json/extractJson.js.map +1 -0
  122. package/dist/formats/json/flattenJson.js +41 -48
  123. package/dist/formats/json/flattenJson.js.map +1 -0
  124. package/dist/formats/json/jsonPath.js +20 -15
  125. package/dist/formats/json/jsonPath.js.map +1 -0
  126. package/dist/formats/json/jsonPointer.js +17 -17
  127. package/dist/formats/json/jsonPointer.js.map +1 -0
  128. package/dist/formats/json/mergeJson.js +230 -371
  129. package/dist/formats/json/mergeJson.js.map +1 -0
  130. package/dist/formats/json/parseJson.js +74 -111
  131. package/dist/formats/json/parseJson.js.map +1 -0
  132. package/dist/formats/json/transformJson.js +53 -61
  133. package/dist/formats/json/transformJson.js.map +1 -0
  134. package/dist/formats/json/utils.js +158 -187
  135. package/dist/formats/json/utils.js.map +1 -0
  136. package/dist/formats/parseKeyedMetadata.js +85 -106
  137. package/dist/formats/parseKeyedMetadata.js.map +1 -0
  138. package/dist/formats/utils.js +13 -23
  139. package/dist/formats/utils.js.map +1 -0
  140. package/dist/formats/yaml/extractYaml.js +32 -31
  141. package/dist/formats/yaml/extractYaml.js.map +1 -0
  142. package/dist/formats/yaml/mergeYaml.js +43 -60
  143. package/dist/formats/yaml/mergeYaml.js.map +1 -0
  144. package/dist/formats/yaml/parseYaml.js +34 -23
  145. package/dist/formats/yaml/parseYaml.js.map +1 -0
  146. package/dist/formats/yaml/utils.js +19 -21
  147. package/dist/formats/yaml/utils.js.map +1 -0
  148. package/dist/fs/clearLocaleDirs.js +82 -114
  149. package/dist/fs/clearLocaleDirs.js.map +1 -0
  150. package/dist/fs/config/downloadedVersions.js +174 -188
  151. package/dist/fs/config/downloadedVersions.js.map +1 -0
  152. package/dist/fs/config/loadConfig.js +12 -8
  153. package/dist/fs/config/loadConfig.js.map +1 -0
  154. package/dist/fs/config/parseFilesConfig.js +166 -227
  155. package/dist/fs/config/parseFilesConfig.js.map +1 -0
  156. package/dist/fs/config/setupConfig.js +43 -52
  157. package/dist/fs/config/setupConfig.js.map +1 -0
  158. package/dist/fs/config/updateConfig.js +44 -56
  159. package/dist/fs/config/updateConfig.js.map +1 -0
  160. package/dist/fs/config/updateVersions.js +27 -28
  161. package/dist/fs/config/updateVersions.js.map +1 -0
  162. package/dist/fs/copyFile.js +33 -37
  163. package/dist/fs/copyFile.js.map +1 -0
  164. package/dist/fs/createLoadTranslationsFile.js +32 -48
  165. package/dist/fs/createLoadTranslationsFile.js.map +1 -0
  166. package/dist/fs/determineFramework/detectPythonLibrary.js +30 -34
  167. package/dist/fs/determineFramework/detectPythonLibrary.js.map +1 -0
  168. package/dist/fs/determineFramework/index.js +46 -64
  169. package/dist/fs/determineFramework/index.js.map +1 -0
  170. package/dist/fs/determineFramework/matchPyprojectDependency.js +65 -78
  171. package/dist/fs/determineFramework/matchPyprojectDependency.js.map +1 -0
  172. package/dist/fs/determineFramework/matchRequirementsTxtDependency.js +21 -19
  173. package/dist/fs/determineFramework/matchRequirementsTxtDependency.js.map +1 -0
  174. package/dist/fs/determineFramework/matchSetupPyDependency.js +60 -81
  175. package/dist/fs/determineFramework/matchSetupPyDependency.js.map +1 -0
  176. package/dist/fs/determineFramework/resolveGtDependency.js +15 -15
  177. package/dist/fs/determineFramework/resolveGtDependency.js.map +1 -0
  178. package/dist/fs/findFilepath.js +63 -78
  179. package/dist/fs/findFilepath.js.map +1 -0
  180. package/dist/fs/loadJSON.js +18 -15
  181. package/dist/fs/loadJSON.js.map +1 -0
  182. package/dist/fs/matchFiles.js +12 -7
  183. package/dist/fs/matchFiles.js.map +1 -0
  184. package/dist/fs/saveJSON.js +10 -6
  185. package/dist/fs/saveJSON.js.map +1 -0
  186. package/dist/fs/utils.js +19 -15
  187. package/dist/fs/utils.js.map +1 -0
  188. package/dist/functions.d.ts +2 -1
  189. package/dist/functions.js +3 -6
  190. package/dist/generated/version.d.ts +1 -1
  191. package/dist/generated/version.js +6 -2
  192. package/dist/generated/version.js.map +1 -0
  193. package/dist/git/branches.js +77 -83
  194. package/dist/git/branches.js.map +1 -0
  195. package/dist/hooks/postProcess.js +97 -114
  196. package/dist/hooks/postProcess.js.map +1 -0
  197. package/dist/index.js +23 -31
  198. package/dist/index.js.map +1 -0
  199. package/dist/locadex/setupFlow.js +11 -8
  200. package/dist/locadex/setupFlow.js.map +1 -0
  201. package/dist/main.js +17 -7
  202. package/dist/main.js.map +1 -0
  203. package/dist/next/config/parseNextConfig.js +32 -51
  204. package/dist/next/config/parseNextConfig.js.map +1 -0
  205. package/dist/next/jsx/utils.js +25 -37
  206. package/dist/next/jsx/utils.js.map +1 -0
  207. package/dist/next/parse/handleInitGT.js +87 -154
  208. package/dist/next/parse/handleInitGT.js.map +1 -0
  209. package/dist/next/parse/wrapContent.js +136 -158
  210. package/dist/next/parse/wrapContent.js.map +1 -0
  211. package/dist/python/parse/createPythonInlineUpdates.js +36 -33
  212. package/dist/python/parse/createPythonInlineUpdates.js.map +1 -0
  213. package/dist/react/config/createESBuildConfig.js +115 -115
  214. package/dist/react/config/createESBuildConfig.js.map +1 -0
  215. package/dist/react/jsx/evaluateJsx.js +90 -124
  216. package/dist/react/jsx/evaluateJsx.js.map +1 -0
  217. package/dist/react/jsx/utils/buildImportMap.js +24 -28
  218. package/dist/react/jsx/utils/buildImportMap.js.map +1 -0
  219. package/dist/react/jsx/utils/constants.js +79 -87
  220. package/dist/react/jsx/utils/constants.js.map +1 -0
  221. package/dist/react/jsx/utils/extractSourceCode.js +36 -37
  222. package/dist/react/jsx/utils/extractSourceCode.js.map +1 -0
  223. package/dist/react/jsx/utils/getCalleeNameFromExpression.js +30 -30
  224. package/dist/react/jsx/utils/getCalleeNameFromExpression.js.map +1 -0
  225. package/dist/react/jsx/utils/getPathsAndAliases.js +70 -105
  226. package/dist/react/jsx/utils/getPathsAndAliases.js.map +1 -0
  227. package/dist/react/jsx/utils/isNumberLiteral.js +13 -11
  228. package/dist/react/jsx/utils/isNumberLiteral.js.map +1 -0
  229. package/dist/react/jsx/utils/jsxParsing/addGTIdentifierToSyntaxTree.js +103 -148
  230. package/dist/react/jsx/utils/jsxParsing/addGTIdentifierToSyntaxTree.js.map +1 -0
  231. package/dist/react/jsx/utils/jsxParsing/autoInsertion.js +305 -389
  232. package/dist/react/jsx/utils/jsxParsing/autoInsertion.js.map +1 -0
  233. package/dist/react/jsx/utils/jsxParsing/handleChildrenWhitespace.js +122 -193
  234. package/dist/react/jsx/utils/jsxParsing/handleChildrenWhitespace.js.map +1 -0
  235. package/dist/react/jsx/utils/jsxParsing/multiplication/findMultiplicationNode.js +50 -64
  236. package/dist/react/jsx/utils/jsxParsing/multiplication/findMultiplicationNode.js.map +1 -0
  237. package/dist/react/jsx/utils/jsxParsing/multiplication/multiplyJsxTree.js +41 -68
  238. package/dist/react/jsx/utils/jsxParsing/multiplication/multiplyJsxTree.js.map +1 -0
  239. package/dist/react/jsx/utils/jsxParsing/parseJsx.js +760 -1107
  240. package/dist/react/jsx/utils/jsxParsing/parseJsx.js.map +1 -0
  241. package/dist/react/jsx/utils/jsxParsing/parseTProps.js +35 -71
  242. package/dist/react/jsx/utils/jsxParsing/parseTProps.js.map +1 -0
  243. package/dist/react/jsx/utils/jsxParsing/removeNullChildrenFields.js +39 -58
  244. package/dist/react/jsx/utils/jsxParsing/removeNullChildrenFields.js.map +1 -0
  245. package/dist/react/jsx/utils/jsxParsing/types.js +10 -24
  246. package/dist/react/jsx/utils/jsxParsing/types.js.map +1 -0
  247. package/dist/react/jsx/utils/mapAttributeName.js +13 -13
  248. package/dist/react/jsx/utils/mapAttributeName.js.map +1 -0
  249. package/dist/react/jsx/utils/parseAst.js +142 -272
  250. package/dist/react/jsx/utils/parseAst.js.map +1 -0
  251. package/dist/react/jsx/utils/parseString.js +726 -1090
  252. package/dist/react/jsx/utils/parseString.js.map +1 -0
  253. package/dist/react/jsx/utils/parseStringFunction.js +274 -401
  254. package/dist/react/jsx/utils/parseStringFunction.js.map +1 -0
  255. package/dist/react/jsx/utils/resolveImportPath.js +104 -108
  256. package/dist/react/jsx/utils/resolveImportPath.js.map +1 -0
  257. package/dist/react/jsx/utils/stringParsing/derivation/containsDeriveCall.js +18 -24
  258. package/dist/react/jsx/utils/stringParsing/derivation/containsDeriveCall.js.map +1 -0
  259. package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.js +412 -579
  260. package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.js.map +1 -0
  261. package/dist/react/jsx/utils/stringParsing/derivation/index.js +57 -67
  262. package/dist/react/jsx/utils/stringParsing/derivation/index.js.map +1 -0
  263. package/dist/react/jsx/utils/stringParsing/derivation/isDeriveCall.js +26 -36
  264. package/dist/react/jsx/utils/stringParsing/derivation/isDeriveCall.js.map +1 -0
  265. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/handleTaggedTemplateTranslationCall.js +29 -24
  266. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/handleTaggedTemplateTranslationCall.js.map +1 -0
  267. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/index.js +34 -32
  268. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/index.js.map +1 -0
  269. package/dist/react/jsx/utils/stringParsing/processTranslationCall/extractStringEntryMetadata.js +80 -117
  270. package/dist/react/jsx/utils/stringParsing/processTranslationCall/extractStringEntryMetadata.js.map +1 -0
  271. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleDeriveTranslationCall.js +24 -19
  272. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleDeriveTranslationCall.js.map +1 -0
  273. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleInvalidTranslationCall.js +18 -21
  274. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleInvalidTranslationCall.js.map +1 -0
  275. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleLiteralTranslationCall.js +45 -50
  276. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleLiteralTranslationCall.js.map +1 -0
  277. package/dist/react/jsx/utils/stringParsing/processTranslationCall/index.js +54 -59
  278. package/dist/react/jsx/utils/stringParsing/processTranslationCall/index.js.map +1 -0
  279. package/dist/react/jsx/utils/stringParsing/processTranslationCall/routeTranslationCall.js +56 -69
  280. package/dist/react/jsx/utils/stringParsing/processTranslationCall/routeTranslationCall.js.map +1 -0
  281. package/dist/react/jsx/utils/validateStringFunction.js +21 -29
  282. package/dist/react/jsx/utils/validateStringFunction.js.map +1 -0
  283. package/dist/react/jsx/wrapJsx.js +192 -375
  284. package/dist/react/jsx/wrapJsx.js.map +1 -0
  285. package/dist/react/parse/addVitePlugin/index.js +40 -34
  286. package/dist/react/parse/addVitePlugin/index.js.map +1 -0
  287. package/dist/react/parse/addVitePlugin/installCompiler.js +18 -20
  288. package/dist/react/parse/addVitePlugin/installCompiler.js.map +1 -0
  289. package/dist/react/parse/addVitePlugin/updateViteConfig.js +107 -111
  290. package/dist/react/parse/addVitePlugin/updateViteConfig.js.map +1 -0
  291. package/dist/react/parse/addVitePlugin/utils/addCompilerImport.js +23 -26
  292. package/dist/react/parse/addVitePlugin/utils/addCompilerImport.js.map +1 -0
  293. package/dist/react/parse/addVitePlugin/utils/addPluginInvocation.js +29 -43
  294. package/dist/react/parse/addVitePlugin/utils/addPluginInvocation.js.map +1 -0
  295. package/dist/react/parse/addVitePlugin/utils/checkCompilerImport.js +70 -104
  296. package/dist/react/parse/addVitePlugin/utils/checkCompilerImport.js.map +1 -0
  297. package/dist/react/parse/addVitePlugin/utils/checkPluginInvocation.js +23 -29
  298. package/dist/react/parse/addVitePlugin/utils/checkPluginInvocation.js.map +1 -0
  299. package/dist/react/parse/createDictionaryUpdates.js +121 -185
  300. package/dist/react/parse/createDictionaryUpdates.js.map +1 -0
  301. package/dist/react/parse/createInlineUpdates.js +123 -139
  302. package/dist/react/parse/createInlineUpdates.js.map +1 -0
  303. package/dist/react/parse/wrapContent.js +131 -156
  304. package/dist/react/parse/wrapContent.js.map +1 -0
  305. package/dist/react/utils/flattenDictionary.js +55 -70
  306. package/dist/react/utils/flattenDictionary.js.map +1 -0
  307. package/dist/react/utils/getEntryAndMetadata.js +14 -10
  308. package/dist/react/utils/getEntryAndMetadata.js.map +1 -0
  309. package/dist/react/utils/getVariableName.js +36 -33
  310. package/dist/react/utils/getVariableName.js.map +1 -0
  311. package/dist/setup/detectFramework.js +85 -102
  312. package/dist/setup/detectFramework.js.map +1 -0
  313. package/dist/setup/frameworkUtils.js +17 -28
  314. package/dist/setup/frameworkUtils.js.map +1 -0
  315. package/dist/setup/userInput.js +24 -31
  316. package/dist/setup/userInput.js.map +1 -0
  317. package/dist/setup/wizard.js +141 -143
  318. package/dist/setup/wizard.js.map +1 -0
  319. package/dist/state/mintlifyRefMap.js +12 -9
  320. package/dist/state/mintlifyRefMap.js.map +1 -0
  321. package/dist/state/recentDownloads.js +26 -23
  322. package/dist/state/recentDownloads.js.map +1 -0
  323. package/dist/state/translateWarnings.js +17 -8
  324. package/dist/state/translateWarnings.js.map +1 -0
  325. package/dist/translation/parse.js +77 -98
  326. package/dist/translation/parse.js.map +1 -0
  327. package/dist/translation/stage.js +28 -43
  328. package/dist/translation/stage.js.map +1 -0
  329. package/dist/translation/validate.js +68 -91
  330. package/dist/translation/validate.js.map +1 -0
  331. package/dist/types/libraries.js +93 -91
  332. package/dist/types/libraries.js.map +1 -0
  333. package/dist/types/parsing.js +19 -10
  334. package/dist/types/parsing.js.map +1 -0
  335. package/dist/utils/addExplicitAnchorIds.js +270 -389
  336. package/dist/utils/addExplicitAnchorIds.js.map +1 -0
  337. package/dist/utils/calculateTimeoutMs.js +11 -6
  338. package/dist/utils/calculateTimeoutMs.js.map +1 -0
  339. package/dist/utils/constants.js +15 -12
  340. package/dist/utils/constants.js.map +1 -0
  341. package/dist/utils/credentials.js +67 -114
  342. package/dist/utils/credentials.js.map +1 -0
  343. package/dist/utils/fetch.js +22 -20
  344. package/dist/utils/fetch.js.map +1 -0
  345. package/dist/utils/flattenJsonFiles.js +27 -34
  346. package/dist/utils/flattenJsonFiles.js.map +1 -0
  347. package/dist/utils/gitDiff.js +30 -32
  348. package/dist/utils/gitDiff.js.map +1 -0
  349. package/dist/utils/gt.js +7 -2
  350. package/dist/utils/gt.js.map +1 -0
  351. package/dist/utils/hash.js +14 -9
  352. package/dist/utils/hash.js.map +1 -0
  353. package/dist/utils/headers.js +10 -13
  354. package/dist/utils/headers.js.map +1 -0
  355. package/dist/utils/installPackage.js +70 -75
  356. package/dist/utils/installPackage.js.map +1 -0
  357. package/dist/utils/localizeRelativeAssets.js +114 -157
  358. package/dist/utils/localizeRelativeAssets.js.map +1 -0
  359. package/dist/utils/localizeStaticImports.js +229 -371
  360. package/dist/utils/localizeStaticImports.js.map +1 -0
  361. package/dist/utils/localizeStaticUrls.js +241 -424
  362. package/dist/utils/localizeStaticUrls.js.map +1 -0
  363. package/dist/utils/mintlifyTitleFallback.js +64 -72
  364. package/dist/utils/mintlifyTitleFallback.js.map +1 -0
  365. package/dist/utils/monorepoVersionCheck.js +177 -215
  366. package/dist/utils/monorepoVersionCheck.js.map +1 -0
  367. package/dist/utils/packageInfo.js +17 -16
  368. package/dist/utils/packageInfo.js.map +1 -0
  369. package/dist/utils/packageJson.js +51 -66
  370. package/dist/utils/packageJson.js.map +1 -0
  371. package/dist/utils/packageManager.js +237 -260
  372. package/dist/utils/packageManager.js.map +1 -0
  373. package/dist/utils/parse/needsCJS.js +36 -69
  374. package/dist/utils/parse/needsCJS.js.map +1 -0
  375. package/dist/utils/persistPostprocessHashes.js +30 -32
  376. package/dist/utils/persistPostprocessHashes.js.map +1 -0
  377. package/dist/utils/processAnchorIds.js +32 -54
  378. package/dist/utils/processAnchorIds.js.map +1 -0
  379. package/dist/utils/processOpenApi.js +469 -578
  380. package/dist/utils/processOpenApi.js.map +1 -0
  381. package/dist/utils/resolveMintlifyRefs.js +89 -105
  382. package/dist/utils/resolveMintlifyRefs.js.map +1 -0
  383. package/dist/utils/resolvePublish.js +46 -54
  384. package/dist/utils/resolvePublish.js.map +1 -0
  385. package/dist/utils/sanitizeFileContent.js +20 -27
  386. package/dist/utils/sanitizeFileContent.js.map +1 -0
  387. package/dist/utils/sharedStaticAssets.js +248 -366
  388. package/dist/utils/sharedStaticAssets.js.map +1 -0
  389. package/dist/utils/splitMintlifyLanguageRefs.js +208 -282
  390. package/dist/utils/splitMintlifyLanguageRefs.js.map +1 -0
  391. package/dist/utils/validateMdx.js +26 -23
  392. package/dist/utils/validateMdx.js.map +1 -0
  393. package/dist/utils/wrapPlainUrls.js +58 -70
  394. package/dist/utils/wrapPlainUrls.js.map +1 -0
  395. package/dist/workflows/download.js +92 -126
  396. package/dist/workflows/download.js.map +1 -0
  397. package/dist/workflows/enqueue.js +47 -54
  398. package/dist/workflows/enqueue.js.map +1 -0
  399. package/dist/workflows/publish.js +29 -29
  400. package/dist/workflows/publish.js.map +1 -0
  401. package/dist/workflows/setupProject.js +39 -40
  402. package/dist/workflows/setupProject.js.map +1 -0
  403. package/dist/workflows/stage.js +61 -65
  404. package/dist/workflows/stage.js.map +1 -0
  405. package/dist/workflows/steps/BranchStep.js +118 -163
  406. package/dist/workflows/steps/BranchStep.js.map +1 -0
  407. package/dist/workflows/steps/DownloadStep.js +107 -137
  408. package/dist/workflows/steps/DownloadStep.js.map +1 -0
  409. package/dist/workflows/steps/EnqueueStep.js +32 -32
  410. package/dist/workflows/steps/EnqueueStep.js.map +1 -0
  411. package/dist/workflows/steps/PollJobsStep.js +208 -292
  412. package/dist/workflows/steps/PollJobsStep.js.map +1 -0
  413. package/dist/workflows/steps/PublishStep.js +33 -38
  414. package/dist/workflows/steps/PublishStep.js.map +1 -0
  415. package/dist/workflows/steps/SetupStep.js +71 -72
  416. package/dist/workflows/steps/SetupStep.js.map +1 -0
  417. package/dist/workflows/steps/TagStep.js +39 -44
  418. package/dist/workflows/steps/TagStep.js.map +1 -0
  419. package/dist/workflows/steps/UploadSourcesStep.js +108 -140
  420. package/dist/workflows/steps/UploadSourcesStep.js.map +1 -0
  421. package/dist/workflows/steps/UploadTranslationsStep.js +61 -71
  422. package/dist/workflows/steps/UploadTranslationsStep.js.map +1 -0
  423. package/dist/workflows/steps/UserEditDiffsStep.js +32 -34
  424. package/dist/workflows/steps/UserEditDiffsStep.js.map +1 -0
  425. package/dist/workflows/steps/WorkflowStep.js +6 -2
  426. package/dist/workflows/steps/WorkflowStep.js.map +1 -0
  427. package/dist/workflows/upload.js +45 -46
  428. package/dist/workflows/upload.js.map +1 -0
  429. package/package.json +14 -7
@@ -1,1125 +1,778 @@
1
- import { randomUUID } from 'node:crypto';
2
- import generateModule from '@babel/generator';
3
- // Handle CommonJS/ESM interop
1
+ import "../../../../utils/constants.js";
2
+ import { isStaticExpression } from "../../evaluateJsx.js";
3
+ import { VARIABLE_COMPONENTS } from "../constants.js";
4
+ import { warnDataAttrOnBranch, warnDeriveDestructuringSync, warnDeriveNonConstVariableSync, warnDuplicateFunctionDefinitionSync, warnFunctionNotFoundSync, warnHasUnwrappedExpressionSync, warnInvalidDeriveInitSync, warnMissingReturnSync, warnNestedInternalTComponent, warnNestedTComponent, warnRecursiveFunctionCallSync } from "../../../../console/index.js";
5
+ import addGTIdentifierToSyntaxTree from "./addGTIdentifierToSyntaxTree.js";
6
+ import { resolveImportPath } from "../resolveImportPath.js";
7
+ import { buildImportMap } from "../buildImportMap.js";
8
+ import { getPathsAndAliases } from "../getPathsAndAliases.js";
9
+ import { parseTProps } from "./parseTProps.js";
10
+ import { isElementNode } from "./types.js";
11
+ import { handleChildrenWhitespace } from "./handleChildrenWhitespace.js";
12
+ import { multiplyJsxTree } from "./multiplication/multiplyJsxTree.js";
13
+ import { removeNullChildrenFields } from "./removeNullChildrenFields.js";
14
+ import { autoInsertJsxComponents, ensureTAndVarImported } from "./autoInsertion.js";
15
+ import { extractSourceCode } from "../extractSourceCode.js";
16
+ import { nodeToStrings, parseStringExpression } from "../parseString.js";
17
+ import { handleDerivation } from "../stringParsing/derivation/handleDerivation.js";
18
+ import { randomUUID } from "node:crypto";
19
+ import path from "node:path";
20
+ import fs from "node:fs";
21
+ import * as t from "@babel/types";
22
+ import { parse } from "@babel/parser";
23
+ import generateModule from "@babel/generator";
24
+ import { HTML_CONTENT_PROPS } from "@generaltranslation/format/types";
25
+ import { isAcceptedPluralForm } from "generaltranslation/internal";
26
+ import traverseModule from "@babel/traverse";
27
+ //#region src/react/jsx/utils/jsxParsing/parseJsx.ts
4
28
  const generate = generateModule.default || generateModule;
5
- import * as t from '@babel/types';
6
- import fs from 'node:fs';
7
- import { parse } from '@babel/parser';
8
- import addGTIdentifierToSyntaxTree from './addGTIdentifierToSyntaxTree.js';
9
- import { warnHasUnwrappedExpressionSync, warnNestedTComponent, warnFunctionNotFoundSync, warnMissingReturnSync, warnDuplicateFunctionDefinitionSync, warnInvalidDeriveInitSync, warnRecursiveFunctionCallSync, warnDataAttrOnBranch, warnNestedInternalTComponent, warnDeriveNonConstVariableSync, warnDeriveDestructuringSync, } from '../../../../console/index.js';
10
- import { isAcceptedPluralForm } from 'generaltranslation/internal';
11
- import { isStaticExpression } from '../../evaluateJsx.js';
12
- import { DATA_ATTR_PREFIX, STATIC_COMPONENT, DERIVE_COMPONENT, TRANSLATION_COMPONENT, INTERNAL_TRANSLATION_COMPONENT, VARIABLE_COMPONENTS, } from '../constants.js';
13
- import { HTML_CONTENT_PROPS, } from '@generaltranslation/format/types';
14
- import { resolveImportPath } from '../resolveImportPath.js';
15
- import traverseModule from '@babel/traverse';
16
- import { buildImportMap } from '../buildImportMap.js';
17
- import { getPathsAndAliases } from '../getPathsAndAliases.js';
18
- import { parseTProps } from './parseTProps.js';
19
- import { handleChildrenWhitespace } from './handleChildrenWhitespace.js';
20
- import { isElementNode } from './types.js';
21
- import { multiplyJsxTree } from './multiplication/multiplyJsxTree.js';
22
- import { removeNullChildrenFields } from './removeNullChildrenFields.js';
23
- import { ensureTAndVarImported, autoInsertJsxComponents, } from './autoInsertion.js';
24
- import path from 'node:path';
25
- import { extractSourceCode } from '../extractSourceCode.js';
26
- import { SURROUNDING_LINE_COUNT } from '../../../../utils/constants.js';
27
- import { handleDerivation } from '../stringParsing/derivation/handleDerivation.js';
28
- import { parseStringExpression, nodeToStrings } from '../parseString.js';
29
- // Handle CommonJS/ESM interop
30
29
  const traverse = traverseModule.default || traverseModule;
31
- // TODO: currently we cover VariableDeclaration and FunctionDeclaration nodes, but are there others we should cover as well?
32
30
  /**
33
- * Cache for resolved import paths to avoid redundant I/O operations.
34
- * Key: `${currentFile}::${importPath}`
35
- * Value: resolved absolute path or null
36
- */
37
- const resolveImportPathCache = new Map();
31
+ * Cache for resolved import paths to avoid redundant I/O operations.
32
+ * Key: `${currentFile}::${importPath}`
33
+ * Value: resolved absolute path or null
34
+ */
35
+ const resolveImportPathCache = /* @__PURE__ */ new Map();
38
36
  /**
39
- * Cache for processed functions to avoid re-parsing the same files.
40
- * Key: `${filePath}::${functionName}::${argIndex}`
41
- * Value: boolean indicating whether the function was found and processed
42
- */
43
- const processFunctionCache = new Map();
37
+ * Cache for processed functions to avoid re-parsing the same files.
38
+ * Key: `${filePath}::${functionName}::${argIndex}`
39
+ * Value: boolean indicating whether the function was found and processed
40
+ */
41
+ const processFunctionCache = /* @__PURE__ */ new Map();
44
42
  /**
45
- * Entry point for JSX parsing
46
- */
47
- export function parseTranslationComponent({ originalName, localName, path, updates, config, output, }) {
48
- // First, collect all imports in this file to track cross-file function calls
49
- const importedFunctionsMap = buildImportMap(path.scope.getProgramParent().path);
50
- const referencePaths = path.scope.bindings[localName]?.referencePaths || [];
51
- for (const refPath of referencePaths) {
52
- // Only start at opening tag
53
- if (!t.isJSXOpeningElement(refPath.parent) ||
54
- !refPath.parentPath?.parentPath) {
55
- continue;
56
- }
57
- // Get the JSX element NodePath
58
- const jsxElementPath = refPath.parentPath
59
- ?.parentPath;
60
- // Parse <T> component
61
- parseJSXElement({
62
- scopeNode: jsxElementPath,
63
- node: jsxElementPath.node,
64
- originalName,
65
- updates,
66
- config,
67
- state: {
68
- visited: null,
69
- callStack: [],
70
- derivableTracker: { isDerivable: false },
71
- importedFunctionsMap,
72
- },
73
- output,
74
- });
75
- }
43
+ * Entry point for JSX parsing
44
+ */
45
+ function parseTranslationComponent({ originalName, localName, path, updates, config, output }) {
46
+ const importedFunctionsMap = buildImportMap(path.scope.getProgramParent().path);
47
+ const referencePaths = path.scope.bindings[localName]?.referencePaths || [];
48
+ for (const refPath of referencePaths) {
49
+ if (!t.isJSXOpeningElement(refPath.parent) || !refPath.parentPath?.parentPath) continue;
50
+ const jsxElementPath = refPath.parentPath?.parentPath;
51
+ parseJSXElement({
52
+ scopeNode: jsxElementPath,
53
+ node: jsxElementPath.node,
54
+ originalName,
55
+ updates,
56
+ config,
57
+ state: {
58
+ visited: null,
59
+ callStack: [],
60
+ derivableTracker: { isDerivable: false },
61
+ importedFunctionsMap
62
+ },
63
+ output
64
+ });
65
+ }
76
66
  }
77
67
  /**
78
- * Builds a JSX tree from a given node, recursively handling children.
79
- * @param node - The node to build the tree from
80
- * @param helperPath - NodePath for AST traversal
81
- * @param scopeNode - Scope node for binding resolution
82
- * @param insideT - Whether the current node is inside a <T> component
83
- * @param inDerive - Whether we're inside a <Derive> component
84
- * @param config - Immutable configuration options
85
- * @param state - Mutable state tracking
86
- * @param output - Error/warning collectors
87
- * @returns The built JSX tree
88
- */
89
- function buildJSXTree({ node, helperPath, scopeNode, insideT, inDerive, config, state, output, }) {
90
- if (t.isJSXExpressionContainer(node)) {
91
- // Skip JSX comments
92
- if (t.isJSXEmptyExpression(node.expression)) {
93
- return null;
94
- }
95
- if (inDerive) {
96
- return processDeriveExpression({
97
- config,
98
- state,
99
- output,
100
- expressionNodePath: helperPath.get('expression'),
101
- scopeNode,
102
- });
103
- }
104
- const expr = node.expression;
105
- if (t.isJSXElement(expr) || t.isJSXFragment(expr)) {
106
- return buildJSXTree({
107
- node: expr,
108
- insideT,
109
- inDerive: inDerive,
110
- scopeNode,
111
- helperPath: helperPath.get('expression'),
112
- config,
113
- state,
114
- output,
115
- });
116
- }
117
- const staticAnalysis = isStaticExpression(expr, true);
118
- if (staticAnalysis.isStatic && staticAnalysis.value !== undefined) {
119
- // Preserve the exact whitespace for static string expressions
120
- return {
121
- nodeType: 'expression',
122
- result: staticAnalysis.value,
123
- };
124
- }
125
- // Keep existing behavior for non-static expressions
126
- const code = generate(node).code;
127
- output.unwrappedExpressions.push(code); // Keep track of unwrapped expressions for error reporting
128
- return code;
129
- }
130
- else if (t.isJSXText(node)) {
131
- // Updated JSX Text handling
132
- // JSX Text handling following React's rules
133
- const text = node.value;
134
- return text;
135
- }
136
- else if (t.isJSXElement(node)) {
137
- const element = node;
138
- const elementName = element.openingElement.name;
139
- let typeName;
140
- if (t.isJSXIdentifier(elementName)) {
141
- typeName = elementName.name;
142
- }
143
- else if (t.isJSXMemberExpression(elementName)) {
144
- typeName = generate(elementName).code;
145
- }
146
- else {
147
- typeName = null;
148
- }
149
- // Convert from alias to original name
150
- const componentType = config.importAliases[typeName ?? ''];
151
- // When enableAutoJsxInjection is on and we're inside a Derive context,
152
- // any auto-inserted T component will be stripped at runtime by
153
- // removeInjectedT. Unwrap it transparently — process the T's children
154
- // as if the T wasn't there. Check this BEFORE the nested-T warning
155
- // so we don't emit spurious errors for expected auto-inserted nesting.
156
- if (componentType === INTERNAL_TRANSLATION_COMPONENT &&
157
- inDerive &&
158
- config.enableAutoJsxInjection) {
159
- const childResults = [];
160
- const helperChildren = helperPath.get('children');
161
- for (let i = 0; i < element.children.length; i++) {
162
- const child = element.children[i];
163
- const helperChild = helperChildren[i];
164
- const result = buildJSXTree({
165
- node: child,
166
- helperPath: helperChild,
167
- scopeNode,
168
- insideT: true,
169
- inDerive: true,
170
- config,
171
- state,
172
- output,
173
- });
174
- if (result !== null) {
175
- if (Array.isArray(result)) {
176
- childResults.push(...result);
177
- }
178
- else {
179
- childResults.push(result);
180
- }
181
- }
182
- }
183
- if (childResults.length === 0)
184
- return null;
185
- if (childResults.length === 1)
186
- return childResults[0];
187
- // Return array callers flatten this into parent's children
188
- return childResults;
189
- }
190
- if ((componentType === TRANSLATION_COMPONENT ||
191
- componentType === INTERNAL_TRANSLATION_COMPONENT) &&
192
- insideT) {
193
- // Add warning: Nested <T> components are allowed, but they are advised against
194
- output.warnings.add(warnNestedTComponent(config.file, `${element.loc?.start?.line}:${element.loc?.start?.column}`));
195
- if (componentType === INTERNAL_TRANSLATION_COMPONENT) {
196
- output.errors.push(warnNestedInternalTComponent(config.file, `${element.loc?.start?.line}:${element.loc?.start?.column}`));
197
- }
198
- }
199
- // If this JSXElement is one of the recognized variable components,
200
- const elementIsVariable = VARIABLE_COMPONENTS.includes(componentType);
201
- const props = {};
202
- const elementIsPlural = componentType === 'Plural';
203
- const elementIsBranch = componentType === 'Branch';
204
- element.openingElement.attributes.forEach((attr, index) => {
205
- const helperAttribute = helperPath
206
- .get('openingElement')
207
- .get('attributes')[index];
208
- if (t.isJSXAttribute(attr)) {
209
- const attrName = typeof attr.name.name === 'string'
210
- ? attr.name.name
211
- : attr.name.name.name;
212
- let attrValue = null;
213
- if (elementIsBranch && attrName.startsWith(DATA_ATTR_PREFIX)) {
214
- const location = `${attr.loc?.start?.line}:${attr.loc?.start?.column}`;
215
- output.errors.push(warnDataAttrOnBranch(config.file, attrName, location));
216
- }
217
- if (attr.value) {
218
- if (t.isStringLiteral(attr.value)) {
219
- attrValue = attr.value.value;
220
- }
221
- else if (t.isJSXExpressionContainer(attr.value)) {
222
- const helperValue = helperAttribute.get('value');
223
- // Check if this is an HTML content prop (title, placeholder, alt, etc.)
224
- const isHtmlContentProp = Object.values(HTML_CONTENT_PROPS).includes(attrName);
225
- // If its a plural or branch prop
226
- if ((elementIsPlural && isAcceptedPluralForm(attrName)) ||
227
- (elementIsBranch &&
228
- attrName !== 'branch' &&
229
- !attrName.startsWith(DATA_ATTR_PREFIX))) {
230
- // Make sure that variable strings like {`I have ${count} book`} are invalid!
231
- if (t.isTemplateLiteral(attr.value.expression) &&
232
- !isStaticExpression(attr.value.expression, true).isStatic) {
233
- output.unwrappedExpressions.push(generate(attr.value).code);
234
- }
235
- // If it's an array, flag as an unwrapped expression
236
- if (t.isArrayExpression(attr.value.expression)) {
237
- output.unwrappedExpressions.push(generate(attr.value.expression).code);
238
- }
239
- attrValue = buildJSXTree({
240
- node: attr.value,
241
- insideT: true,
242
- inDerive: inDerive,
243
- scopeNode,
244
- helperPath: helperValue,
245
- config,
246
- state,
247
- output,
248
- });
249
- }
250
- // For HTML content props, only accept static string expressions
251
- else if (isHtmlContentProp) {
252
- const staticAnalysis = isStaticExpression(attr.value.expression, true);
253
- if (staticAnalysis.isStatic &&
254
- staticAnalysis.value !== undefined) {
255
- attrValue = staticAnalysis.value;
256
- }
257
- // Otherwise attrValue stays null and won't be included
258
- }
259
- }
260
- }
261
- props[attrName] = attrValue;
262
- }
263
- });
264
- if (elementIsVariable) {
265
- if (componentType === STATIC_COMPONENT ||
266
- componentType === DERIVE_COMPONENT) {
267
- const helperElement = helperPath.get('children');
268
- const results = {
269
- nodeType: 'element',
270
- type: componentType,
271
- props,
272
- };
273
- // Create children array if necessary
274
- const childrenArray = [];
275
- if (state.visited === null) {
276
- state.visited = new Set();
277
- }
278
- for (let index = 0; index < element.children.length; index++) {
279
- const helperChild = helperElement[index];
280
- const result = buildJSXTree({
281
- node: helperChild.node,
282
- insideT: true,
283
- inDerive: true,
284
- scopeNode,
285
- helperPath: helperChild,
286
- config,
287
- state,
288
- output,
289
- });
290
- // Flatten array results from _T transparency unwrap inside Derive
291
- if (Array.isArray(result)) {
292
- childrenArray.push(...result);
293
- }
294
- else {
295
- childrenArray.push(result);
296
- }
297
- }
298
- if (childrenArray.length) {
299
- results.props.children = childrenArray;
300
- }
301
- return results;
302
- }
303
- return {
304
- nodeType: 'element',
305
- // if componentType is undefined, use typeName
306
- // Basically, if componentType is not a GT component, use typeName such as <div>
307
- type: componentType ?? typeName ?? '',
308
- props,
309
- };
310
- }
311
- const children = element.children
312
- .flatMap((child, index) => {
313
- const result = buildJSXTree({
314
- node: child,
315
- insideT: true,
316
- inDerive: inDerive,
317
- scopeNode,
318
- helperPath: helperPath.get('children')[index],
319
- config,
320
- state,
321
- output,
322
- });
323
- // Flatten array results from _T transparency unwrap inside Derive
324
- if (Array.isArray(result))
325
- return result;
326
- return [result];
327
- })
328
- .filter((child) => child !== null && child !== '');
329
- if (children.length === 1) {
330
- props.children = children[0];
331
- }
332
- else if (children.length > 1) {
333
- props.children = children;
334
- }
335
- return {
336
- nodeType: 'element',
337
- // if componentType is undefined, use typeName
338
- // Basically, if componentType is not a GT component, use typeName such as <div>
339
- type: componentType ?? typeName,
340
- props,
341
- };
342
- }
343
- // If it's a JSX fragment
344
- else if (t.isJSXFragment(node)) {
345
- const children = node.children
346
- .flatMap((child, index) => {
347
- const result = buildJSXTree({
348
- node: child,
349
- insideT: true,
350
- inDerive: inDerive,
351
- scopeNode,
352
- helperPath: helperPath.get('children')[index],
353
- config,
354
- state,
355
- output,
356
- });
357
- // Flatten array results from _T transparency unwrap inside Derive
358
- if (Array.isArray(result))
359
- return result;
360
- return [result];
361
- })
362
- .filter((child) => child !== null && child !== '');
363
- const props = {};
364
- if (children.length === 1) {
365
- props.children = children[0];
366
- }
367
- else if (children.length > 1) {
368
- props.children = children;
369
- }
370
- return {
371
- nodeType: 'element',
372
- type: '',
373
- props,
374
- };
375
- }
376
- // If it's a string literal (standalone)
377
- else if (t.isStringLiteral(node)) {
378
- return node.value;
379
- }
380
- // If it's a template literal
381
- else if (t.isTemplateLiteral(node)) {
382
- // We've already checked that it's derivable, and and added a warning if it's not, this check is just for fallback behavior
383
- if (!isStaticExpression(node, true).isStatic ||
384
- node.quasis[0].value.cooked === undefined) {
385
- return generate(node).code;
386
- }
387
- return node.quasis[0].value.cooked;
388
- }
389
- else if (t.isNullLiteral(node)) {
390
- // If it's null, return null
391
- return null;
392
- }
393
- else if (t.isBooleanLiteral(node)) {
394
- // If it's a boolean, return the boolean
395
- return node.value;
396
- }
397
- else if (t.isNumericLiteral(node)) {
398
- // If it's a number, return the number
399
- return node.value.toString();
400
- }
401
- // Negative
402
- else if (t.isUnaryExpression(node)) {
403
- // If it's a unary expression, return the expression
404
- const staticAnalysis = isStaticExpression(node, true);
405
- if (staticAnalysis.isStatic && staticAnalysis.value !== undefined) {
406
- return staticAnalysis.value;
407
- }
408
- return generate(node).code;
409
- }
410
- else if ((t.isCallExpression(node) && t.isIdentifier(node.callee)) ||
411
- (t.isAwaitExpression(node) &&
412
- t.isCallExpression(node.argument) &&
413
- t.isIdentifier(node.argument.callee))) {
414
- if (inDerive) {
415
- const callExpression = (node.type === 'AwaitExpression' ? node.argument : node);
416
- const callee = callExpression.callee;
417
- const calleeBinding = scopeNode.scope.getBinding(callee.name);
418
- if (!calleeBinding) {
419
- output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
420
- return null;
421
- }
422
- return resolveDeriveFunctionInvocationFromBinding({
423
- calleeBinding,
424
- callee,
425
- config,
426
- state,
427
- output,
428
- });
429
- }
430
- else {
431
- output.unwrappedExpressions.push(generate(node).code);
432
- }
433
- }
434
- else if (t.isParenthesizedExpression(node)) {
435
- const child = node.expression;
436
- return buildJSXTree({
437
- node: child,
438
- insideT,
439
- inDerive: inDerive,
440
- scopeNode,
441
- helperPath: helperPath.get('expression'),
442
- config,
443
- state,
444
- output,
445
- });
446
- }
447
- // If it's some other JS expression
448
- else if (t.isIdentifier(node) ||
449
- t.isMemberExpression(node) ||
450
- t.isCallExpression(node) ||
451
- t.isBinaryExpression(node) ||
452
- t.isLogicalExpression(node) ||
453
- t.isConditionalExpression(node)) {
454
- output.unwrappedExpressions.push(generate(node).code);
455
- }
456
- else {
457
- if (node === undefined || node === null) {
458
- output.unwrappedExpressions.push(String(node));
459
- }
460
- else {
461
- output.unwrappedExpressions.push(generate(node).code);
462
- }
463
- }
464
- return null;
68
+ * Builds a JSX tree from a given node, recursively handling children.
69
+ * @param node - The node to build the tree from
70
+ * @param helperPath - NodePath for AST traversal
71
+ * @param scopeNode - Scope node for binding resolution
72
+ * @param insideT - Whether the current node is inside a <T> component
73
+ * @param inDerive - Whether we're inside a <Derive> component
74
+ * @param config - Immutable configuration options
75
+ * @param state - Mutable state tracking
76
+ * @param output - Error/warning collectors
77
+ * @returns The built JSX tree
78
+ */
79
+ function buildJSXTree({ node, helperPath, scopeNode, insideT, inDerive, config, state, output }) {
80
+ if (t.isJSXExpressionContainer(node)) {
81
+ if (t.isJSXEmptyExpression(node.expression)) return null;
82
+ if (inDerive) return processDeriveExpression({
83
+ config,
84
+ state,
85
+ output,
86
+ expressionNodePath: helperPath.get("expression"),
87
+ scopeNode
88
+ });
89
+ const expr = node.expression;
90
+ if (t.isJSXElement(expr) || t.isJSXFragment(expr)) return buildJSXTree({
91
+ node: expr,
92
+ insideT,
93
+ inDerive,
94
+ scopeNode,
95
+ helperPath: helperPath.get("expression"),
96
+ config,
97
+ state,
98
+ output
99
+ });
100
+ const staticAnalysis = isStaticExpression(expr, true);
101
+ if (staticAnalysis.isStatic && staticAnalysis.value !== void 0) return {
102
+ nodeType: "expression",
103
+ result: staticAnalysis.value
104
+ };
105
+ const code = generate(node).code;
106
+ output.unwrappedExpressions.push(code);
107
+ return code;
108
+ } else if (t.isJSXText(node)) return node.value;
109
+ else if (t.isJSXElement(node)) {
110
+ const element = node;
111
+ const elementName = element.openingElement.name;
112
+ let typeName;
113
+ if (t.isJSXIdentifier(elementName)) typeName = elementName.name;
114
+ else if (t.isJSXMemberExpression(elementName)) typeName = generate(elementName).code;
115
+ else typeName = null;
116
+ const componentType = config.importAliases[typeName ?? ""];
117
+ if (componentType === "GtInternalTranslateJsx" && inDerive && config.enableAutoJsxInjection) {
118
+ const childResults = [];
119
+ const helperChildren = helperPath.get("children");
120
+ for (let i = 0; i < element.children.length; i++) {
121
+ const child = element.children[i];
122
+ const helperChild = helperChildren[i];
123
+ const result = buildJSXTree({
124
+ node: child,
125
+ helperPath: helperChild,
126
+ scopeNode,
127
+ insideT: true,
128
+ inDerive: true,
129
+ config,
130
+ state,
131
+ output
132
+ });
133
+ if (result !== null) if (Array.isArray(result)) childResults.push(...result);
134
+ else childResults.push(result);
135
+ }
136
+ if (childResults.length === 0) return null;
137
+ if (childResults.length === 1) return childResults[0];
138
+ return childResults;
139
+ }
140
+ if ((componentType === "T" || componentType === "GtInternalTranslateJsx") && insideT) {
141
+ output.warnings.add(warnNestedTComponent(config.file, `${element.loc?.start?.line}:${element.loc?.start?.column}`));
142
+ if (componentType === "GtInternalTranslateJsx") output.errors.push(warnNestedInternalTComponent(config.file, `${element.loc?.start?.line}:${element.loc?.start?.column}`));
143
+ }
144
+ const elementIsVariable = VARIABLE_COMPONENTS.includes(componentType);
145
+ const props = {};
146
+ const elementIsPlural = componentType === "Plural";
147
+ const elementIsBranch = componentType === "Branch";
148
+ element.openingElement.attributes.forEach((attr, index) => {
149
+ const helperAttribute = helperPath.get("openingElement").get("attributes")[index];
150
+ if (t.isJSXAttribute(attr)) {
151
+ const attrName = typeof attr.name.name === "string" ? attr.name.name : attr.name.name.name;
152
+ let attrValue = null;
153
+ if (elementIsBranch && attrName.startsWith("data-")) {
154
+ const location = `${attr.loc?.start?.line}:${attr.loc?.start?.column}`;
155
+ output.errors.push(warnDataAttrOnBranch(config.file, attrName, location));
156
+ }
157
+ if (attr.value) {
158
+ if (t.isStringLiteral(attr.value)) attrValue = attr.value.value;
159
+ else if (t.isJSXExpressionContainer(attr.value)) {
160
+ const helperValue = helperAttribute.get("value");
161
+ const isHtmlContentProp = Object.values(HTML_CONTENT_PROPS).includes(attrName);
162
+ if (elementIsPlural && isAcceptedPluralForm(attrName) || elementIsBranch && attrName !== "branch" && !attrName.startsWith("data-")) {
163
+ if (t.isTemplateLiteral(attr.value.expression) && !isStaticExpression(attr.value.expression, true).isStatic) output.unwrappedExpressions.push(generate(attr.value).code);
164
+ if (t.isArrayExpression(attr.value.expression)) output.unwrappedExpressions.push(generate(attr.value.expression).code);
165
+ attrValue = buildJSXTree({
166
+ node: attr.value,
167
+ insideT: true,
168
+ inDerive,
169
+ scopeNode,
170
+ helperPath: helperValue,
171
+ config,
172
+ state,
173
+ output
174
+ });
175
+ } else if (isHtmlContentProp) {
176
+ const staticAnalysis = isStaticExpression(attr.value.expression, true);
177
+ if (staticAnalysis.isStatic && staticAnalysis.value !== void 0) attrValue = staticAnalysis.value;
178
+ }
179
+ }
180
+ }
181
+ props[attrName] = attrValue;
182
+ }
183
+ });
184
+ if (elementIsVariable) {
185
+ if (componentType === "Static" || componentType === "Derive") {
186
+ const helperElement = helperPath.get("children");
187
+ const results = {
188
+ nodeType: "element",
189
+ type: componentType,
190
+ props
191
+ };
192
+ const childrenArray = [];
193
+ if (state.visited === null) state.visited = /* @__PURE__ */ new Set();
194
+ for (let index = 0; index < element.children.length; index++) {
195
+ const helperChild = helperElement[index];
196
+ const result = buildJSXTree({
197
+ node: helperChild.node,
198
+ insideT: true,
199
+ inDerive: true,
200
+ scopeNode,
201
+ helperPath: helperChild,
202
+ config,
203
+ state,
204
+ output
205
+ });
206
+ if (Array.isArray(result)) childrenArray.push(...result);
207
+ else childrenArray.push(result);
208
+ }
209
+ if (childrenArray.length) results.props.children = childrenArray;
210
+ return results;
211
+ }
212
+ return {
213
+ nodeType: "element",
214
+ type: componentType ?? typeName ?? "",
215
+ props
216
+ };
217
+ }
218
+ const children = element.children.flatMap((child, index) => {
219
+ const result = buildJSXTree({
220
+ node: child,
221
+ insideT: true,
222
+ inDerive,
223
+ scopeNode,
224
+ helperPath: helperPath.get("children")[index],
225
+ config,
226
+ state,
227
+ output
228
+ });
229
+ if (Array.isArray(result)) return result;
230
+ return [result];
231
+ }).filter((child) => child !== null && child !== "");
232
+ if (children.length === 1) props.children = children[0];
233
+ else if (children.length > 1) props.children = children;
234
+ return {
235
+ nodeType: "element",
236
+ type: componentType ?? typeName,
237
+ props
238
+ };
239
+ } else if (t.isJSXFragment(node)) {
240
+ const children = node.children.flatMap((child, index) => {
241
+ const result = buildJSXTree({
242
+ node: child,
243
+ insideT: true,
244
+ inDerive,
245
+ scopeNode,
246
+ helperPath: helperPath.get("children")[index],
247
+ config,
248
+ state,
249
+ output
250
+ });
251
+ if (Array.isArray(result)) return result;
252
+ return [result];
253
+ }).filter((child) => child !== null && child !== "");
254
+ const props = {};
255
+ if (children.length === 1) props.children = children[0];
256
+ else if (children.length > 1) props.children = children;
257
+ return {
258
+ nodeType: "element",
259
+ type: "",
260
+ props
261
+ };
262
+ } else if (t.isStringLiteral(node)) return node.value;
263
+ else if (t.isTemplateLiteral(node)) {
264
+ if (!isStaticExpression(node, true).isStatic || node.quasis[0].value.cooked === void 0) return generate(node).code;
265
+ return node.quasis[0].value.cooked;
266
+ } else if (t.isNullLiteral(node)) return null;
267
+ else if (t.isBooleanLiteral(node)) return node.value;
268
+ else if (t.isNumericLiteral(node)) return node.value.toString();
269
+ else if (t.isUnaryExpression(node)) {
270
+ const staticAnalysis = isStaticExpression(node, true);
271
+ if (staticAnalysis.isStatic && staticAnalysis.value !== void 0) return staticAnalysis.value;
272
+ return generate(node).code;
273
+ } else if (t.isCallExpression(node) && t.isIdentifier(node.callee) || t.isAwaitExpression(node) && t.isCallExpression(node.argument) && t.isIdentifier(node.argument.callee)) if (inDerive) {
274
+ const callee = (node.type === "AwaitExpression" ? node.argument : node).callee;
275
+ const calleeBinding = scopeNode.scope.getBinding(callee.name);
276
+ if (!calleeBinding) {
277
+ output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
278
+ return null;
279
+ }
280
+ return resolveDeriveFunctionInvocationFromBinding({
281
+ calleeBinding,
282
+ callee,
283
+ config,
284
+ state,
285
+ output
286
+ });
287
+ } else output.unwrappedExpressions.push(generate(node).code);
288
+ else if (t.isParenthesizedExpression(node)) {
289
+ const child = node.expression;
290
+ return buildJSXTree({
291
+ node: child,
292
+ insideT,
293
+ inDerive,
294
+ scopeNode,
295
+ helperPath: helperPath.get("expression"),
296
+ config,
297
+ state,
298
+ output
299
+ });
300
+ } else if (t.isIdentifier(node) || t.isMemberExpression(node) || t.isCallExpression(node) || t.isBinaryExpression(node) || t.isLogicalExpression(node) || t.isConditionalExpression(node)) output.unwrappedExpressions.push(generate(node).code);
301
+ else if (node === void 0 || node === null) output.unwrappedExpressions.push(String(node));
302
+ else output.unwrappedExpressions.push(generate(node).code);
303
+ return null;
465
304
  }
466
- // end buildJSXTree
467
- // Parses a JSX element and adds it to the updates array
468
- function parseJSXElement({ node, originalName, scopeNode, updates, config, state, output, }) {
469
- const openingElement = node.openingElement;
470
- const name = openingElement.name;
471
- // Only proceed if it's <T> ...
472
- // TODO: i don't think this condition is needed anymore
473
- if (!(name.type === 'JSXIdentifier' &&
474
- (originalName === TRANSLATION_COMPONENT ||
475
- originalName === INTERNAL_TRANSLATION_COMPONENT))) {
476
- return;
477
- }
478
- const componentErrors = [];
479
- const componentWarnings = new Set();
480
- const metadata = {};
481
- const relativeFilepath = path.relative(process.cwd(), config.file);
482
- metadata.filePaths = [relativeFilepath];
483
- // Extract surrounding lines from source file
484
- const startLine = node.loc?.start?.line;
485
- const endLine = node.loc?.end?.line;
486
- if (config.includeSourceCodeContext && startLine && endLine) {
487
- const entry = extractSourceCode(config.file, startLine, endLine, SURROUNDING_LINE_COUNT);
488
- if (entry && relativeFilepath) {
489
- metadata.sourceCode = { [relativeFilepath]: [entry] };
490
- }
491
- }
492
- // We'll track this flag to know if any unwrapped {variable} is found in children
493
- const unwrappedExpressions = [];
494
- // Gather <T>'s props
495
- parseTProps({
496
- openingElement,
497
- metadata,
498
- componentErrors,
499
- file: config.file,
500
- });
501
- // Flag for if contains derivable content
502
- const derivableTracker = {
503
- isDerivable: false,
504
- };
505
- // Build the JSX tree for this component
506
- const treeResult = buildJSXTree({
507
- node,
508
- scopeNode,
509
- insideT: false,
510
- inDerive: config.autoderive ?? false,
511
- helperPath: scopeNode,
512
- config,
513
- state: {
514
- visited: null,
515
- callStack: [],
516
- derivableTracker: derivableTracker,
517
- importedFunctionsMap: state.importedFunctionsMap,
518
- },
519
- output: {
520
- unwrappedExpressions,
521
- errors: componentErrors,
522
- warnings: componentWarnings,
523
- },
524
- });
525
- // Strip the outer <T> component if necessary
526
- const jsxTree = isElementNode(treeResult) && treeResult.props?.children
527
- ? // We know this b/c the direct children of <T> will never be a multiplication node
528
- treeResult.props.children
529
- : treeResult;
530
- // Update warnings
531
- if (componentWarnings.size > 0) {
532
- componentWarnings.forEach((warning) => output.warnings.add(warning));
533
- }
534
- // Update errors
535
- if (componentErrors.length > 0) {
536
- output.errors.push(...componentErrors);
537
- return;
538
- }
539
- // Handle whitespace in children
540
- const whitespaceHandledTree = handleChildrenWhitespace(jsxTree);
541
- // Multiply the tree
542
- const multipliedTrees = multiplyJsxTree(whitespaceHandledTree);
543
- // Add GT identifiers to the tree
544
- // TODO: do this in parallel
545
- const minifiedTress = [];
546
- for (const multipliedTree of multipliedTrees) {
547
- // Build set of confirmed GT variable names from importAliases.
548
- // Only pass when enableAutoJsxInjection is on, to avoid breaking
549
- // existing behavior where importAliases may be incomplete.
550
- const gtVariableNames = config.enableAutoJsxInjection
551
- ? new Set(Object.values(config.importAliases).filter((name) => VARIABLE_COMPONENTS.includes(name) &&
552
- name !== DERIVE_COMPONENT &&
553
- name !== STATIC_COMPONENT))
554
- : undefined;
555
- const minifiedTree = addGTIdentifierToSyntaxTree(multipliedTree, 0, gtVariableNames);
556
- minifiedTress.push(Array.isArray(minifiedTree) && minifiedTree.length === 1
557
- ? minifiedTree[0]
558
- : minifiedTree);
559
- }
560
- // If we found an unwrapped expression, skip
561
- if (unwrappedExpressions.length > 0) {
562
- output.errors.push(warnHasUnwrappedExpressionSync(config.file, unwrappedExpressions, metadata.id, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
563
- return;
564
- }
565
- // Create a temporary unique flag for derivable content
566
- const temporaryDeriveId = `derive-temp-id-${randomUUID()}`;
567
- // Resolve derive context variants if present
568
- let contextVariants;
569
- if (metadata._contextDeriveExpr) {
570
- const contextExpr = metadata._contextDeriveExpr;
571
- delete metadata._contextDeriveExpr;
572
- const contextNode = handleDerivation({
573
- expr: contextExpr,
574
- tPath: scopeNode,
575
- file: config.file,
576
- parsingOptions: config.parsingOptions,
577
- errors: componentErrors,
578
- warnings: componentWarnings,
579
- });
580
- if (contextNode) {
581
- contextVariants = nodeToStrings(contextNode);
582
- }
583
- }
584
- // <T> is valid here
585
- for (const minifiedTree of minifiedTress) {
586
- // Clean the tree by removing null 'c' fields from JsxElements
587
- const cleanedTree = removeNullChildrenFields(minifiedTree);
588
- if (contextVariants) {
589
- for (const context of contextVariants) {
590
- updates.push({
591
- dataFormat: 'JSX',
592
- source: cleanedTree,
593
- metadata: {
594
- ...structuredClone(metadata),
595
- context,
596
- staticId: temporaryDeriveId,
597
- },
598
- });
599
- }
600
- }
601
- else {
602
- updates.push({
603
- dataFormat: 'JSX',
604
- source: cleanedTree,
605
- metadata: {
606
- ...structuredClone(metadata),
607
- ...(derivableTracker.isDerivable && { staticId: temporaryDeriveId }),
608
- },
609
- });
610
- }
611
- }
305
+ function parseJSXElement({ node, originalName, scopeNode, updates, config, state, output }) {
306
+ const openingElement = node.openingElement;
307
+ if (!(openingElement.name.type === "JSXIdentifier" && (originalName === "T" || originalName === "GtInternalTranslateJsx"))) return;
308
+ const componentErrors = [];
309
+ const componentWarnings = /* @__PURE__ */ new Set();
310
+ const metadata = {};
311
+ const relativeFilepath = path.relative(process.cwd(), config.file);
312
+ metadata.filePaths = [relativeFilepath];
313
+ const startLine = node.loc?.start?.line;
314
+ const endLine = node.loc?.end?.line;
315
+ if (config.includeSourceCodeContext && startLine && endLine) {
316
+ const entry = extractSourceCode(config.file, startLine, endLine, 5);
317
+ if (entry && relativeFilepath) metadata.sourceCode = { [relativeFilepath]: [entry] };
318
+ }
319
+ const unwrappedExpressions = [];
320
+ parseTProps({
321
+ openingElement,
322
+ metadata,
323
+ componentErrors,
324
+ file: config.file
325
+ });
326
+ const derivableTracker = { isDerivable: false };
327
+ const treeResult = buildJSXTree({
328
+ node,
329
+ scopeNode,
330
+ insideT: false,
331
+ inDerive: config.autoderive ?? false,
332
+ helperPath: scopeNode,
333
+ config,
334
+ state: {
335
+ visited: null,
336
+ callStack: [],
337
+ derivableTracker,
338
+ importedFunctionsMap: state.importedFunctionsMap
339
+ },
340
+ output: {
341
+ unwrappedExpressions,
342
+ errors: componentErrors,
343
+ warnings: componentWarnings
344
+ }
345
+ });
346
+ const jsxTree = isElementNode(treeResult) && treeResult.props?.children ? treeResult.props.children : treeResult;
347
+ if (componentWarnings.size > 0) componentWarnings.forEach((warning) => output.warnings.add(warning));
348
+ if (componentErrors.length > 0) {
349
+ output.errors.push(...componentErrors);
350
+ return;
351
+ }
352
+ const multipliedTrees = multiplyJsxTree(handleChildrenWhitespace(jsxTree));
353
+ const minifiedTress = [];
354
+ for (const multipliedTree of multipliedTrees) {
355
+ const minifiedTree = addGTIdentifierToSyntaxTree(multipliedTree, 0, config.enableAutoJsxInjection ? new Set(Object.values(config.importAliases).filter((name) => VARIABLE_COMPONENTS.includes(name) && name !== "Derive" && name !== "Static")) : void 0);
356
+ minifiedTress.push(Array.isArray(minifiedTree) && minifiedTree.length === 1 ? minifiedTree[0] : minifiedTree);
357
+ }
358
+ if (unwrappedExpressions.length > 0) {
359
+ output.errors.push(warnHasUnwrappedExpressionSync(config.file, unwrappedExpressions, metadata.id, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
360
+ return;
361
+ }
362
+ const temporaryDeriveId = `derive-temp-id-${randomUUID()}`;
363
+ let contextVariants;
364
+ if (metadata._contextDeriveExpr) {
365
+ const contextExpr = metadata._contextDeriveExpr;
366
+ delete metadata._contextDeriveExpr;
367
+ const contextNode = handleDerivation({
368
+ expr: contextExpr,
369
+ tPath: scopeNode,
370
+ file: config.file,
371
+ parsingOptions: config.parsingOptions,
372
+ errors: componentErrors,
373
+ warnings: componentWarnings
374
+ });
375
+ if (contextNode) contextVariants = nodeToStrings(contextNode);
376
+ }
377
+ for (const minifiedTree of minifiedTress) {
378
+ const cleanedTree = removeNullChildrenFields(minifiedTree);
379
+ if (contextVariants) for (const context of contextVariants) updates.push({
380
+ dataFormat: "JSX",
381
+ source: cleanedTree,
382
+ metadata: {
383
+ ...structuredClone(metadata),
384
+ context,
385
+ staticId: temporaryDeriveId
386
+ }
387
+ });
388
+ else updates.push({
389
+ dataFormat: "JSX",
390
+ source: cleanedTree,
391
+ metadata: {
392
+ ...structuredClone(metadata),
393
+ ...derivableTracker.isDerivable && { staticId: temporaryDeriveId }
394
+ }
395
+ });
396
+ }
612
397
  }
613
- function resolveDeriveFunctionInvocationFromBinding({ calleeBinding, callee, config, state, output, }) {
614
- function withRecusionGuard({ cb, filename, functionName, }) {
615
- const cacheKey = `${filename}::${functionName}`;
616
- if (state.callStack.includes(cacheKey)) {
617
- output.errors.push(warnRecursiveFunctionCallSync(config.file, functionName));
618
- return null;
619
- }
620
- state.callStack.push(cacheKey);
621
- const result = cb();
622
- state.callStack.pop();
623
- return result;
624
- }
625
- // check for recursive calls
626
- if (calleeBinding.path.isFunctionDeclaration()) {
627
- // Handle function declarations: function getSubject() { ... }
628
- const functionName = callee.name;
629
- const path = calleeBinding.path;
630
- return withRecusionGuard({
631
- filename: config.file,
632
- functionName,
633
- cb: () => processFunctionDeclarationNodePath({
634
- config,
635
- state,
636
- output,
637
- path,
638
- }),
639
- });
640
- }
641
- else if (calleeBinding.path.isVariableDeclarator() &&
642
- calleeBinding.path.node.init &&
643
- (t.isArrowFunctionExpression(calleeBinding.path.node.init) ||
644
- t.isFunctionExpression(calleeBinding.path.node.init))) {
645
- // Handle arrow functions assigned to variables: const getData = (t) => {...}
646
- const functionName = callee.name;
647
- const path = calleeBinding.path;
648
- return withRecusionGuard({
649
- filename: config.file,
650
- functionName,
651
- cb: () => processVariableDeclarationNodePath({
652
- config,
653
- state,
654
- output,
655
- functionName,
656
- path,
657
- }),
658
- });
659
- }
660
- else if (state.importedFunctionsMap.has(callee.name)) {
661
- // Get the original function name
662
- let originalName;
663
- if (calleeBinding.path.isImportSpecifier()) {
664
- originalName = t.isIdentifier(calleeBinding.path.node.imported)
665
- ? calleeBinding.path.node.imported.name
666
- : calleeBinding.path.node.imported.value;
667
- }
668
- else if (calleeBinding.path.isImportDefaultSpecifier()) {
669
- originalName = calleeBinding.path.node.local.name;
670
- }
671
- else if (calleeBinding.path.isImportNamespaceSpecifier()) {
672
- originalName = calleeBinding.path.node.local.name;
673
- }
674
- // Function is being imported
675
- const importPath = state.importedFunctionsMap.get(callee.name);
676
- const filePath = resolveImportPath(config.file, importPath, config.parsingOptions, resolveImportPathCache);
677
- if (filePath && originalName) {
678
- const result = withRecusionGuard({
679
- filename: filePath,
680
- functionName: originalName,
681
- cb: () => processFunctionInFile({
682
- config,
683
- state,
684
- output,
685
- filePath,
686
- functionName: originalName,
687
- }),
688
- });
689
- if (result !== null) {
690
- return result;
691
- }
692
- }
693
- }
694
- output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
695
- return null;
398
+ function resolveDeriveFunctionInvocationFromBinding({ calleeBinding, callee, config, state, output }) {
399
+ function withRecusionGuard({ cb, filename, functionName }) {
400
+ const cacheKey = `${filename}::${functionName}`;
401
+ if (state.callStack.includes(cacheKey)) {
402
+ output.errors.push(warnRecursiveFunctionCallSync(config.file, functionName));
403
+ return null;
404
+ }
405
+ state.callStack.push(cacheKey);
406
+ const result = cb();
407
+ state.callStack.pop();
408
+ return result;
409
+ }
410
+ if (calleeBinding.path.isFunctionDeclaration()) {
411
+ const functionName = callee.name;
412
+ const path = calleeBinding.path;
413
+ return withRecusionGuard({
414
+ filename: config.file,
415
+ functionName,
416
+ cb: () => processFunctionDeclarationNodePath({
417
+ config,
418
+ state,
419
+ output,
420
+ path
421
+ })
422
+ });
423
+ } else if (calleeBinding.path.isVariableDeclarator() && calleeBinding.path.node.init && (t.isArrowFunctionExpression(calleeBinding.path.node.init) || t.isFunctionExpression(calleeBinding.path.node.init))) {
424
+ const functionName = callee.name;
425
+ const path = calleeBinding.path;
426
+ return withRecusionGuard({
427
+ filename: config.file,
428
+ functionName,
429
+ cb: () => processVariableDeclarationNodePath({
430
+ config,
431
+ state,
432
+ output,
433
+ functionName,
434
+ path
435
+ })
436
+ });
437
+ } else if (state.importedFunctionsMap.has(callee.name)) {
438
+ let originalName;
439
+ if (calleeBinding.path.isImportSpecifier()) originalName = t.isIdentifier(calleeBinding.path.node.imported) ? calleeBinding.path.node.imported.name : calleeBinding.path.node.imported.value;
440
+ else if (calleeBinding.path.isImportDefaultSpecifier()) originalName = calleeBinding.path.node.local.name;
441
+ else if (calleeBinding.path.isImportNamespaceSpecifier()) originalName = calleeBinding.path.node.local.name;
442
+ const importPath = state.importedFunctionsMap.get(callee.name);
443
+ const filePath = resolveImportPath(config.file, importPath, config.parsingOptions, resolveImportPathCache);
444
+ if (filePath && originalName) {
445
+ const result = withRecusionGuard({
446
+ filename: filePath,
447
+ functionName: originalName,
448
+ cb: () => processFunctionInFile({
449
+ config,
450
+ state,
451
+ output,
452
+ filePath,
453
+ functionName: originalName
454
+ })
455
+ });
456
+ if (result !== null) return result;
457
+ }
458
+ }
459
+ output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
460
+ return null;
696
461
  }
697
462
  /**
698
- * Searches for a specific user-defined function in a file.
699
- * This is the resolution logic
700
- *
701
- * Handles multiple function declaration patterns:
702
- * - function getInfo() { ... }
703
- * - export function getInfo() { ... }
704
- * - const getInfo = () => { ... }
705
- *
706
- * If the function is not found in the file, follows re-exports (export * from './other')
707
- */
708
- function processFunctionInFile({ config, state, output, filePath, functionName, }) {
709
- // Create a custom key for the function call
710
- const cacheKey = `${filePath}::${functionName}`;
711
- // Check cache first to avoid redundant parsing
712
- if (processFunctionCache.has(cacheKey)) {
713
- return processFunctionCache.get(cacheKey) ?? null;
714
- }
715
- // Prevent infinite loops from circular re-exports
716
- if (state.visited && state.visited.has(filePath)) {
717
- return null;
718
- }
719
- if (state.visited) {
720
- state.visited.add(filePath);
721
- }
722
- let result = undefined;
723
- try {
724
- const code = fs.readFileSync(filePath, 'utf8');
725
- const ast = parse(code, {
726
- sourceType: 'module',
727
- plugins: ['jsx', 'typescript'],
728
- });
729
- const pathsResult = getPathsAndAliases(ast, config.pkgs);
730
- const importAliases = { ...pathsResult.importAliases };
731
- // Merge translation component names into importAliases so
732
- // autoInsertJsxComponents can recognize user T/Var and skip them
733
- for (const { localName, originalName, } of pathsResult.translationComponentPaths) {
734
- importAliases[localName] = originalName;
735
- }
736
- // Auto-inject T/Var into the cross-file AST when enabled,
737
- // so that Derive extraction sees the same structure as same-file
738
- if (config.enableAutoJsxInjection) {
739
- ensureTAndVarImported(ast, importAliases);
740
- autoInsertJsxComponents(ast, importAliases);
741
- }
742
- // Collect all imports in this file to track cross-file function calls
743
- let importedFunctionsMap = new Map();
744
- traverse(ast, {
745
- Program(path) {
746
- importedFunctionsMap = buildImportMap(path);
747
- },
748
- });
749
- const reExports = [];
750
- const warnDuplicateFuncDef = (path) => {
751
- output.warnings.add(warnDuplicateFunctionDefinitionSync(filePath, functionName, `${path.node.loc?.start?.line}:${path.node.loc?.start?.column}`));
752
- };
753
- traverse(ast, {
754
- // Handle function declarations: function getInfo() { ... }
755
- FunctionDeclaration(path) {
756
- if (path.node.id?.name === functionName) {
757
- if (result !== undefined)
758
- return warnDuplicateFuncDef(path);
759
- result = processFunctionDeclarationNodePath({
760
- config: {
761
- importAliases,
762
- parsingOptions: config.parsingOptions,
763
- pkgs: config.pkgs,
764
- file: filePath,
765
- enableAutoJsxInjection: config.enableAutoJsxInjection,
766
- },
767
- state: {
768
- ...state,
769
- importedFunctionsMap,
770
- },
771
- output,
772
- path,
773
- });
774
- }
775
- },
776
- // Handle variable declarations: const getInfo = () => { ... }
777
- VariableDeclarator(path) {
778
- if (t.isIdentifier(path.node.id) &&
779
- path.node.id.name === functionName &&
780
- path.node.init &&
781
- (t.isArrowFunctionExpression(path.node.init) ||
782
- t.isFunctionExpression(path.node.init))) {
783
- if (result !== undefined)
784
- return warnDuplicateFuncDef(path);
785
- result = processVariableDeclarationNodePath({
786
- config: {
787
- importAliases,
788
- parsingOptions: config.parsingOptions,
789
- pkgs: config.pkgs,
790
- file: filePath,
791
- enableAutoJsxInjection: config.enableAutoJsxInjection,
792
- },
793
- state: {
794
- ...state,
795
- importedFunctionsMap,
796
- },
797
- output,
798
- functionName,
799
- path,
800
- });
801
- }
802
- },
803
- // Collect re-exports: export * from './other'
804
- ExportAllDeclaration(path) {
805
- if (t.isStringLiteral(path.node.source)) {
806
- reExports.push(path.node.source.value);
807
- }
808
- },
809
- // Collect named re-exports: export { foo } from './other'
810
- ExportNamedDeclaration(path) {
811
- if (path.node.source && t.isStringLiteral(path.node.source)) {
812
- // Check if this export includes our function
813
- const exportsFunction = path.node.specifiers.some((spec) => {
814
- if (t.isExportSpecifier(spec)) {
815
- const exportedName = t.isIdentifier(spec.exported)
816
- ? spec.exported.name
817
- : spec.exported.value;
818
- return exportedName === functionName;
819
- }
820
- return false;
821
- });
822
- if (exportsFunction) {
823
- reExports.push(path.node.source.value);
824
- }
825
- }
826
- },
827
- });
828
- // If function not found, follow re-exports
829
- if (result === undefined && reExports.length > 0) {
830
- for (const reExportPath of reExports) {
831
- const resolvedPath = resolveImportPath(filePath, reExportPath, config.parsingOptions, resolveImportPathCache);
832
- if (resolvedPath) {
833
- const foundResult = processFunctionInFile({
834
- config: {
835
- importAliases,
836
- parsingOptions: config.parsingOptions,
837
- pkgs: config.pkgs,
838
- file: filePath,
839
- enableAutoJsxInjection: config.enableAutoJsxInjection,
840
- },
841
- state: {
842
- ...state,
843
- importedFunctionsMap,
844
- },
845
- output,
846
- filePath: resolvedPath,
847
- functionName,
848
- });
849
- if (foundResult != null) {
850
- result = foundResult;
851
- break;
852
- }
853
- }
854
- }
855
- }
856
- // Mark this function search as processed in the cache
857
- processFunctionCache.set(cacheKey, result !== undefined ? result : null);
858
- }
859
- catch {
860
- // Silently skip files that can't be parsed or accessed
861
- // Still mark as processed to avoid retrying failed parses
862
- processFunctionCache.set(cacheKey, null);
863
- }
864
- return result !== undefined ? result : null;
463
+ * Searches for a specific user-defined function in a file.
464
+ * This is the resolution logic
465
+ *
466
+ * Handles multiple function declaration patterns:
467
+ * - function getInfo() { ... }
468
+ * - export function getInfo() { ... }
469
+ * - const getInfo = () => { ... }
470
+ *
471
+ * If the function is not found in the file, follows re-exports (export * from './other')
472
+ */
473
+ function processFunctionInFile({ config, state, output, filePath, functionName }) {
474
+ const cacheKey = `${filePath}::${functionName}`;
475
+ if (processFunctionCache.has(cacheKey)) return processFunctionCache.get(cacheKey) ?? null;
476
+ if (state.visited && state.visited.has(filePath)) return null;
477
+ if (state.visited) state.visited.add(filePath);
478
+ let result = void 0;
479
+ try {
480
+ const ast = parse(fs.readFileSync(filePath, "utf8"), {
481
+ sourceType: "module",
482
+ plugins: ["jsx", "typescript"]
483
+ });
484
+ const pathsResult = getPathsAndAliases(ast, config.pkgs);
485
+ const importAliases = { ...pathsResult.importAliases };
486
+ for (const { localName, originalName } of pathsResult.translationComponentPaths) importAliases[localName] = originalName;
487
+ if (config.enableAutoJsxInjection) {
488
+ ensureTAndVarImported(ast, importAliases);
489
+ autoInsertJsxComponents(ast, importAliases);
490
+ }
491
+ let importedFunctionsMap = /* @__PURE__ */ new Map();
492
+ traverse(ast, { Program(path) {
493
+ importedFunctionsMap = buildImportMap(path);
494
+ } });
495
+ const reExports = [];
496
+ const warnDuplicateFuncDef = (path) => {
497
+ output.warnings.add(warnDuplicateFunctionDefinitionSync(filePath, functionName, `${path.node.loc?.start?.line}:${path.node.loc?.start?.column}`));
498
+ };
499
+ traverse(ast, {
500
+ FunctionDeclaration(path) {
501
+ if (path.node.id?.name === functionName) {
502
+ if (result !== void 0) return warnDuplicateFuncDef(path);
503
+ result = processFunctionDeclarationNodePath({
504
+ config: {
505
+ importAliases,
506
+ parsingOptions: config.parsingOptions,
507
+ pkgs: config.pkgs,
508
+ file: filePath,
509
+ enableAutoJsxInjection: config.enableAutoJsxInjection
510
+ },
511
+ state: {
512
+ ...state,
513
+ importedFunctionsMap
514
+ },
515
+ output,
516
+ path
517
+ });
518
+ }
519
+ },
520
+ VariableDeclarator(path) {
521
+ if (t.isIdentifier(path.node.id) && path.node.id.name === functionName && path.node.init && (t.isArrowFunctionExpression(path.node.init) || t.isFunctionExpression(path.node.init))) {
522
+ if (result !== void 0) return warnDuplicateFuncDef(path);
523
+ result = processVariableDeclarationNodePath({
524
+ config: {
525
+ importAliases,
526
+ parsingOptions: config.parsingOptions,
527
+ pkgs: config.pkgs,
528
+ file: filePath,
529
+ enableAutoJsxInjection: config.enableAutoJsxInjection
530
+ },
531
+ state: {
532
+ ...state,
533
+ importedFunctionsMap
534
+ },
535
+ output,
536
+ functionName,
537
+ path
538
+ });
539
+ }
540
+ },
541
+ ExportAllDeclaration(path) {
542
+ if (t.isStringLiteral(path.node.source)) reExports.push(path.node.source.value);
543
+ },
544
+ ExportNamedDeclaration(path) {
545
+ if (path.node.source && t.isStringLiteral(path.node.source)) {
546
+ if (path.node.specifiers.some((spec) => {
547
+ if (t.isExportSpecifier(spec)) return (t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value) === functionName;
548
+ return false;
549
+ })) reExports.push(path.node.source.value);
550
+ }
551
+ }
552
+ });
553
+ if (result === void 0 && reExports.length > 0) for (const reExportPath of reExports) {
554
+ const resolvedPath = resolveImportPath(filePath, reExportPath, config.parsingOptions, resolveImportPathCache);
555
+ if (resolvedPath) {
556
+ const foundResult = processFunctionInFile({
557
+ config: {
558
+ importAliases,
559
+ parsingOptions: config.parsingOptions,
560
+ pkgs: config.pkgs,
561
+ file: filePath,
562
+ enableAutoJsxInjection: config.enableAutoJsxInjection
563
+ },
564
+ state: {
565
+ ...state,
566
+ importedFunctionsMap
567
+ },
568
+ output,
569
+ filePath: resolvedPath,
570
+ functionName
571
+ });
572
+ if (foundResult != null) {
573
+ result = foundResult;
574
+ break;
575
+ }
576
+ }
577
+ }
578
+ processFunctionCache.set(cacheKey, result !== void 0 ? result : null);
579
+ } catch {
580
+ processFunctionCache.set(cacheKey, null);
581
+ }
582
+ return result !== void 0 ? result : null;
865
583
  }
866
584
  /**
867
- * Process a function declaration
868
- * function getInfo() { ... }
869
- */
870
- function processFunctionDeclarationNodePath({ config, state, output, path, }) {
871
- const result = {
872
- nodeType: 'multiplication',
873
- branches: [],
874
- };
875
- path.traverse({
876
- Function(path) {
877
- path.skip();
878
- },
879
- ReturnStatement(returnPath) {
880
- const returnNodePath = returnPath.get('argument');
881
- if (!returnNodePath.isExpression()) {
882
- return;
883
- }
884
- const deriveResult = processDeriveExpression({
885
- config,
886
- state,
887
- output,
888
- expressionNodePath: returnNodePath,
889
- scopeNode: returnPath,
890
- });
891
- if (Array.isArray(deriveResult)) {
892
- result.branches.push(...deriveResult);
893
- }
894
- else {
895
- result.branches.push(deriveResult);
896
- }
897
- },
898
- });
899
- if (result.branches.length === 0) {
900
- return null;
901
- }
902
- return result;
585
+ * Process a function declaration
586
+ * function getInfo() { ... }
587
+ */
588
+ function processFunctionDeclarationNodePath({ config, state, output, path }) {
589
+ const result = {
590
+ nodeType: "multiplication",
591
+ branches: []
592
+ };
593
+ path.traverse({
594
+ Function(path) {
595
+ path.skip();
596
+ },
597
+ ReturnStatement(returnPath) {
598
+ const returnNodePath = returnPath.get("argument");
599
+ if (!returnNodePath.isExpression()) return;
600
+ const deriveResult = processDeriveExpression({
601
+ config,
602
+ state,
603
+ output,
604
+ expressionNodePath: returnNodePath,
605
+ scopeNode: returnPath
606
+ });
607
+ if (Array.isArray(deriveResult)) result.branches.push(...deriveResult);
608
+ else result.branches.push(deriveResult);
609
+ }
610
+ });
611
+ if (result.branches.length === 0) return null;
612
+ return result;
903
613
  }
904
614
  /**
905
- * Process a variable declaration of a function
906
- * const getInfo = () => { ... }
907
- *
908
- * IMPORTANT: the RHand value must be the function definition, or this will fail
909
- */
910
- function processVariableDeclarationNodePath({ config, state, output, functionName, path, }) {
911
- const result = {
912
- nodeType: 'multiplication',
913
- branches: [],
914
- };
915
- // Enforce the Rhand is a function definition
916
- const arrowFunctionPath = path.get('init');
917
- if (!arrowFunctionPath.isArrowFunctionExpression()) {
918
- output.errors.push(warnInvalidDeriveInitSync(config.file, functionName, `${path.node.loc?.start?.line}:${path.node.loc?.start?.column}`));
919
- return null;
920
- }
921
- const bodyNodePath = arrowFunctionPath.get('body');
922
- if (bodyNodePath.isExpression()) {
923
- // process expression return
924
- const deriveResult = processDeriveExpression({
925
- config,
926
- state,
927
- output,
928
- expressionNodePath: bodyNodePath,
929
- scopeNode: arrowFunctionPath,
930
- });
931
- if (Array.isArray(deriveResult)) {
932
- result.branches.push(...deriveResult);
933
- }
934
- else {
935
- result.branches.push(deriveResult);
936
- }
937
- }
938
- else {
939
- // search for a return statement
940
- bodyNodePath.traverse({
941
- Function(path) {
942
- path.skip();
943
- },
944
- ReturnStatement(returnPath) {
945
- const returnNodePath = returnPath.get('argument');
946
- if (!returnNodePath.isExpression()) {
947
- return;
948
- }
949
- const deriveResult = processDeriveExpression({
950
- config,
951
- state,
952
- output,
953
- expressionNodePath: returnNodePath,
954
- scopeNode: returnPath,
955
- });
956
- if (Array.isArray(deriveResult)) {
957
- result.branches.push(...deriveResult);
958
- }
959
- else {
960
- result.branches.push(deriveResult);
961
- }
962
- },
963
- });
964
- }
965
- if (result.branches.length === 0) {
966
- output.errors.push(warnMissingReturnSync(config.file, functionName, `${path.node.loc?.start?.line}:${path.node.loc?.start?.column}`));
967
- return null;
968
- }
969
- return result;
615
+ * Process a variable declaration of a function
616
+ * const getInfo = () => { ... }
617
+ *
618
+ * IMPORTANT: the RHand value must be the function definition, or this will fail
619
+ */
620
+ function processVariableDeclarationNodePath({ config, state, output, functionName, path }) {
621
+ const result = {
622
+ nodeType: "multiplication",
623
+ branches: []
624
+ };
625
+ const arrowFunctionPath = path.get("init");
626
+ if (!arrowFunctionPath.isArrowFunctionExpression()) {
627
+ output.errors.push(warnInvalidDeriveInitSync(config.file, functionName, `${path.node.loc?.start?.line}:${path.node.loc?.start?.column}`));
628
+ return null;
629
+ }
630
+ const bodyNodePath = arrowFunctionPath.get("body");
631
+ if (bodyNodePath.isExpression()) {
632
+ const deriveResult = processDeriveExpression({
633
+ config,
634
+ state,
635
+ output,
636
+ expressionNodePath: bodyNodePath,
637
+ scopeNode: arrowFunctionPath
638
+ });
639
+ if (Array.isArray(deriveResult)) result.branches.push(...deriveResult);
640
+ else result.branches.push(deriveResult);
641
+ } else bodyNodePath.traverse({
642
+ Function(path) {
643
+ path.skip();
644
+ },
645
+ ReturnStatement(returnPath) {
646
+ const returnNodePath = returnPath.get("argument");
647
+ if (!returnNodePath.isExpression()) return;
648
+ const deriveResult = processDeriveExpression({
649
+ config,
650
+ state,
651
+ output,
652
+ expressionNodePath: returnNodePath,
653
+ scopeNode: returnPath
654
+ });
655
+ if (Array.isArray(deriveResult)) result.branches.push(...deriveResult);
656
+ else result.branches.push(deriveResult);
657
+ }
658
+ });
659
+ if (result.branches.length === 0) {
660
+ output.errors.push(warnMissingReturnSync(config.file, functionName, `${path.node.loc?.start?.line}:${path.node.loc?.start?.column}`));
661
+ return null;
662
+ }
663
+ return result;
970
664
  }
971
665
  /**
972
- * Process a <Derive> expression
973
- */
974
- function processDeriveExpression({ config, state, output, expressionNodePath, scopeNode, }) {
975
- // Mark the derivable tracker as true
976
- state.derivableTracker.isDerivable = true;
977
- // Remove parentheses if they exist
978
- if (t.isParenthesizedExpression(expressionNodePath.node)) {
979
- // ex: return (value)
980
- return processDeriveExpression({
981
- config,
982
- state,
983
- output,
984
- scopeNode,
985
- expressionNodePath: expressionNodePath.get('expression'),
986
- });
987
- }
988
- else if (t.isCallExpression(expressionNodePath.node) &&
989
- t.isIdentifier(expressionNodePath.node.callee)) {
990
- // ex: return someFunc()
991
- const callee = expressionNodePath.node.callee;
992
- const calleeBinding = scopeNode.scope.getBinding(callee.name);
993
- if (!calleeBinding) {
994
- output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
995
- return null;
996
- }
997
- // Function is found
998
- return resolveDeriveFunctionInvocationFromBinding({
999
- calleeBinding,
1000
- callee,
1001
- config,
1002
- state,
1003
- output,
1004
- });
1005
- }
1006
- else if (t.isAwaitExpression(expressionNodePath.node) &&
1007
- t.isCallExpression(expressionNodePath.node.argument) &&
1008
- t.isIdentifier(expressionNodePath.node.argument.callee)) {
1009
- // ex: return await someFunc()
1010
- const callee = expressionNodePath.node.argument.callee;
1011
- const calleeBinding = scopeNode.scope.getBinding(callee.name);
1012
- if (!calleeBinding) {
1013
- output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
1014
- return null;
1015
- }
1016
- // Function is found
1017
- return resolveDeriveFunctionInvocationFromBinding({
1018
- calleeBinding,
1019
- callee,
1020
- config,
1021
- state,
1022
- output,
1023
- });
1024
- }
1025
- else if (t.isJSXElement(expressionNodePath.node) ||
1026
- t.isJSXFragment(expressionNodePath.node)) {
1027
- // ex: return <div>Jsx content</div>
1028
- return buildJSXTree({
1029
- node: expressionNodePath.node,
1030
- helperPath: expressionNodePath,
1031
- scopeNode,
1032
- insideT: true,
1033
- inDerive: true,
1034
- config,
1035
- state,
1036
- output,
1037
- });
1038
- }
1039
- else if (t.isConditionalExpression(expressionNodePath.node)) {
1040
- // ex: return condition ? <div>Jsx content</div> : <div>Jsx content</div>
1041
- // since two options here we must construct a new multiplication node
1042
- const consequentNodePath = expressionNodePath.get('consequent');
1043
- const alternateNodePath = expressionNodePath.get('alternate');
1044
- const result = {
1045
- nodeType: 'multiplication',
1046
- branches: [consequentNodePath, alternateNodePath].flatMap((expressionNodePath) => {
1047
- const r = processDeriveExpression({
1048
- config,
1049
- state,
1050
- output,
1051
- scopeNode,
1052
- expressionNodePath,
1053
- });
1054
- return Array.isArray(r) ? r : [r];
1055
- }),
1056
- };
1057
- return result;
1058
- }
1059
- else if (t.isIdentifier(expressionNodePath.node)) {
1060
- // Resolve variable declarations: const label = cond ? "boy" : "girl"
1061
- const name = expressionNodePath.node.name;
1062
- const binding = scopeNode.scope.getBinding(name);
1063
- if (binding &&
1064
- binding.path.isVariableDeclarator() &&
1065
- binding.path.node.init) {
1066
- // Reject destructuring patterns
1067
- if (t.isObjectPattern(binding.path.node.id) ||
1068
- t.isArrayPattern(binding.path.node.id)) {
1069
- output.errors.push(warnDeriveDestructuringSync(config.file, name, `${expressionNodePath.node.loc?.start?.line}:${expressionNodePath.node.loc?.start?.column}`));
1070
- return null;
1071
- }
1072
- // Enforce const-only
1073
- const declaration = binding.path.parentPath;
1074
- if (declaration?.isVariableDeclaration() &&
1075
- declaration.node.kind !== 'const') {
1076
- output.warnings.add(warnDeriveNonConstVariableSync(config.file, name, declaration.node.kind, `${expressionNodePath.node.loc?.start?.line}:${expressionNodePath.node.loc?.start?.column}`));
1077
- return null;
1078
- }
1079
- // Resolve via parseStringExpression (handles all derivable expression types)
1080
- const errorsBefore = output.errors.length;
1081
- const stringNode = parseStringExpression(binding.path.node.init, binding.path, config.file, config.parsingOptions, output.warnings, output.errors);
1082
- if (stringNode) {
1083
- const strings = nodeToStrings(stringNode);
1084
- if (strings.length === 0) {
1085
- return null;
1086
- }
1087
- if (strings.length === 1) {
1088
- return strings[0];
1089
- }
1090
- return {
1091
- nodeType: 'multiplication',
1092
- branches: strings.map((s) => s),
1093
- };
1094
- }
1095
- // parseStringExpression returned null — if it already pushed errors,
1096
- // avoid double-reporting by skipping the buildJSXTree fallthrough.
1097
- if (output.errors.length > errorsBefore) {
1098
- return null;
1099
- }
1100
- }
1101
- // Not resolvable — fall through to existing buildJSXTree behavior
1102
- return buildJSXTree({
1103
- node: expressionNodePath.node,
1104
- helperPath: expressionNodePath,
1105
- scopeNode,
1106
- insideT: true,
1107
- inDerive: true,
1108
- config,
1109
- state,
1110
- output,
1111
- });
1112
- }
1113
- else {
1114
- return buildJSXTree({
1115
- node: expressionNodePath.node,
1116
- helperPath: expressionNodePath,
1117
- scopeNode,
1118
- insideT: true,
1119
- inDerive: true,
1120
- config,
1121
- state,
1122
- output,
1123
- });
1124
- }
666
+ * Process a <Derive> expression
667
+ */
668
+ function processDeriveExpression({ config, state, output, expressionNodePath, scopeNode }) {
669
+ state.derivableTracker.isDerivable = true;
670
+ if (t.isParenthesizedExpression(expressionNodePath.node)) return processDeriveExpression({
671
+ config,
672
+ state,
673
+ output,
674
+ scopeNode,
675
+ expressionNodePath: expressionNodePath.get("expression")
676
+ });
677
+ else if (t.isCallExpression(expressionNodePath.node) && t.isIdentifier(expressionNodePath.node.callee)) {
678
+ const callee = expressionNodePath.node.callee;
679
+ const calleeBinding = scopeNode.scope.getBinding(callee.name);
680
+ if (!calleeBinding) {
681
+ output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
682
+ return null;
683
+ }
684
+ return resolveDeriveFunctionInvocationFromBinding({
685
+ calleeBinding,
686
+ callee,
687
+ config,
688
+ state,
689
+ output
690
+ });
691
+ } else if (t.isAwaitExpression(expressionNodePath.node) && t.isCallExpression(expressionNodePath.node.argument) && t.isIdentifier(expressionNodePath.node.argument.callee)) {
692
+ const callee = expressionNodePath.node.argument.callee;
693
+ const calleeBinding = scopeNode.scope.getBinding(callee.name);
694
+ if (!calleeBinding) {
695
+ output.warnings.add(warnFunctionNotFoundSync(config.file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
696
+ return null;
697
+ }
698
+ return resolveDeriveFunctionInvocationFromBinding({
699
+ calleeBinding,
700
+ callee,
701
+ config,
702
+ state,
703
+ output
704
+ });
705
+ } else if (t.isJSXElement(expressionNodePath.node) || t.isJSXFragment(expressionNodePath.node)) return buildJSXTree({
706
+ node: expressionNodePath.node,
707
+ helperPath: expressionNodePath,
708
+ scopeNode,
709
+ insideT: true,
710
+ inDerive: true,
711
+ config,
712
+ state,
713
+ output
714
+ });
715
+ else if (t.isConditionalExpression(expressionNodePath.node)) return {
716
+ nodeType: "multiplication",
717
+ branches: [expressionNodePath.get("consequent"), expressionNodePath.get("alternate")].flatMap((expressionNodePath) => {
718
+ const r = processDeriveExpression({
719
+ config,
720
+ state,
721
+ output,
722
+ scopeNode,
723
+ expressionNodePath
724
+ });
725
+ return Array.isArray(r) ? r : [r];
726
+ })
727
+ };
728
+ else if (t.isIdentifier(expressionNodePath.node)) {
729
+ const name = expressionNodePath.node.name;
730
+ const binding = scopeNode.scope.getBinding(name);
731
+ if (binding && binding.path.isVariableDeclarator() && binding.path.node.init) {
732
+ if (t.isObjectPattern(binding.path.node.id) || t.isArrayPattern(binding.path.node.id)) {
733
+ output.errors.push(warnDeriveDestructuringSync(config.file, name, `${expressionNodePath.node.loc?.start?.line}:${expressionNodePath.node.loc?.start?.column}`));
734
+ return null;
735
+ }
736
+ const declaration = binding.path.parentPath;
737
+ if (declaration?.isVariableDeclaration() && declaration.node.kind !== "const") {
738
+ output.warnings.add(warnDeriveNonConstVariableSync(config.file, name, declaration.node.kind, `${expressionNodePath.node.loc?.start?.line}:${expressionNodePath.node.loc?.start?.column}`));
739
+ return null;
740
+ }
741
+ const errorsBefore = output.errors.length;
742
+ const stringNode = parseStringExpression(binding.path.node.init, binding.path, config.file, config.parsingOptions, output.warnings, output.errors);
743
+ if (stringNode) {
744
+ const strings = nodeToStrings(stringNode);
745
+ if (strings.length === 0) return null;
746
+ if (strings.length === 1) return strings[0];
747
+ return {
748
+ nodeType: "multiplication",
749
+ branches: strings.map((s) => s)
750
+ };
751
+ }
752
+ if (output.errors.length > errorsBefore) return null;
753
+ }
754
+ return buildJSXTree({
755
+ node: expressionNodePath.node,
756
+ helperPath: expressionNodePath,
757
+ scopeNode,
758
+ insideT: true,
759
+ inDerive: true,
760
+ config,
761
+ state,
762
+ output
763
+ });
764
+ } else return buildJSXTree({
765
+ node: expressionNodePath.node,
766
+ helperPath: expressionNodePath,
767
+ scopeNode,
768
+ insideT: true,
769
+ inDerive: true,
770
+ config,
771
+ state,
772
+ output
773
+ });
1125
774
  }
775
+ //#endregion
776
+ export { parseTranslationComponent };
777
+
778
+ //# sourceMappingURL=parseJsx.js.map