gtx-cli 2.6.31 → 2.7.0

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