gt 2.14.35 → 2.14.37

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 (430) hide show
  1. package/CHANGELOG.md +22 -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.d.ts +1 -1
  256. package/dist/react/jsx/utils/resolveImportPath.js +125 -108
  257. package/dist/react/jsx/utils/resolveImportPath.js.map +1 -0
  258. package/dist/react/jsx/utils/stringParsing/derivation/containsDeriveCall.js +18 -24
  259. package/dist/react/jsx/utils/stringParsing/derivation/containsDeriveCall.js.map +1 -0
  260. package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.js +412 -579
  261. package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.js.map +1 -0
  262. package/dist/react/jsx/utils/stringParsing/derivation/index.js +57 -67
  263. package/dist/react/jsx/utils/stringParsing/derivation/index.js.map +1 -0
  264. package/dist/react/jsx/utils/stringParsing/derivation/isDeriveCall.js +26 -36
  265. package/dist/react/jsx/utils/stringParsing/derivation/isDeriveCall.js.map +1 -0
  266. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/handleTaggedTemplateTranslationCall.js +29 -24
  267. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/handleTaggedTemplateTranslationCall.js.map +1 -0
  268. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/index.js +34 -32
  269. package/dist/react/jsx/utils/stringParsing/processTaggedTemplateCall/index.js.map +1 -0
  270. package/dist/react/jsx/utils/stringParsing/processTranslationCall/extractStringEntryMetadata.js +80 -117
  271. package/dist/react/jsx/utils/stringParsing/processTranslationCall/extractStringEntryMetadata.js.map +1 -0
  272. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleDeriveTranslationCall.js +24 -19
  273. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleDeriveTranslationCall.js.map +1 -0
  274. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleInvalidTranslationCall.js +18 -21
  275. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleInvalidTranslationCall.js.map +1 -0
  276. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleLiteralTranslationCall.js +45 -50
  277. package/dist/react/jsx/utils/stringParsing/processTranslationCall/handleLiteralTranslationCall.js.map +1 -0
  278. package/dist/react/jsx/utils/stringParsing/processTranslationCall/index.js +54 -59
  279. package/dist/react/jsx/utils/stringParsing/processTranslationCall/index.js.map +1 -0
  280. package/dist/react/jsx/utils/stringParsing/processTranslationCall/routeTranslationCall.js +56 -69
  281. package/dist/react/jsx/utils/stringParsing/processTranslationCall/routeTranslationCall.js.map +1 -0
  282. package/dist/react/jsx/utils/validateStringFunction.js +21 -29
  283. package/dist/react/jsx/utils/validateStringFunction.js.map +1 -0
  284. package/dist/react/jsx/wrapJsx.js +192 -375
  285. package/dist/react/jsx/wrapJsx.js.map +1 -0
  286. package/dist/react/parse/addVitePlugin/index.js +40 -34
  287. package/dist/react/parse/addVitePlugin/index.js.map +1 -0
  288. package/dist/react/parse/addVitePlugin/installCompiler.js +18 -20
  289. package/dist/react/parse/addVitePlugin/installCompiler.js.map +1 -0
  290. package/dist/react/parse/addVitePlugin/updateViteConfig.js +107 -111
  291. package/dist/react/parse/addVitePlugin/updateViteConfig.js.map +1 -0
  292. package/dist/react/parse/addVitePlugin/utils/addCompilerImport.js +23 -26
  293. package/dist/react/parse/addVitePlugin/utils/addCompilerImport.js.map +1 -0
  294. package/dist/react/parse/addVitePlugin/utils/addPluginInvocation.js +29 -43
  295. package/dist/react/parse/addVitePlugin/utils/addPluginInvocation.js.map +1 -0
  296. package/dist/react/parse/addVitePlugin/utils/checkCompilerImport.js +70 -104
  297. package/dist/react/parse/addVitePlugin/utils/checkCompilerImport.js.map +1 -0
  298. package/dist/react/parse/addVitePlugin/utils/checkPluginInvocation.js +23 -29
  299. package/dist/react/parse/addVitePlugin/utils/checkPluginInvocation.js.map +1 -0
  300. package/dist/react/parse/createDictionaryUpdates.js +121 -185
  301. package/dist/react/parse/createDictionaryUpdates.js.map +1 -0
  302. package/dist/react/parse/createInlineUpdates.js +123 -139
  303. package/dist/react/parse/createInlineUpdates.js.map +1 -0
  304. package/dist/react/parse/wrapContent.js +131 -156
  305. package/dist/react/parse/wrapContent.js.map +1 -0
  306. package/dist/react/utils/flattenDictionary.js +55 -70
  307. package/dist/react/utils/flattenDictionary.js.map +1 -0
  308. package/dist/react/utils/getEntryAndMetadata.js +14 -10
  309. package/dist/react/utils/getEntryAndMetadata.js.map +1 -0
  310. package/dist/react/utils/getVariableName.js +36 -33
  311. package/dist/react/utils/getVariableName.js.map +1 -0
  312. package/dist/setup/detectFramework.js +85 -102
  313. package/dist/setup/detectFramework.js.map +1 -0
  314. package/dist/setup/frameworkUtils.js +17 -28
  315. package/dist/setup/frameworkUtils.js.map +1 -0
  316. package/dist/setup/userInput.js +24 -31
  317. package/dist/setup/userInput.js.map +1 -0
  318. package/dist/setup/wizard.js +141 -143
  319. package/dist/setup/wizard.js.map +1 -0
  320. package/dist/state/mintlifyRefMap.js +12 -9
  321. package/dist/state/mintlifyRefMap.js.map +1 -0
  322. package/dist/state/recentDownloads.js +26 -23
  323. package/dist/state/recentDownloads.js.map +1 -0
  324. package/dist/state/translateWarnings.js +17 -8
  325. package/dist/state/translateWarnings.js.map +1 -0
  326. package/dist/translation/parse.js +77 -98
  327. package/dist/translation/parse.js.map +1 -0
  328. package/dist/translation/stage.js +28 -43
  329. package/dist/translation/stage.js.map +1 -0
  330. package/dist/translation/validate.js +68 -91
  331. package/dist/translation/validate.js.map +1 -0
  332. package/dist/types/libraries.js +93 -91
  333. package/dist/types/libraries.js.map +1 -0
  334. package/dist/types/parsing.js +19 -10
  335. package/dist/types/parsing.js.map +1 -0
  336. package/dist/utils/addExplicitAnchorIds.js +270 -389
  337. package/dist/utils/addExplicitAnchorIds.js.map +1 -0
  338. package/dist/utils/calculateTimeoutMs.js +11 -6
  339. package/dist/utils/calculateTimeoutMs.js.map +1 -0
  340. package/dist/utils/constants.js +15 -12
  341. package/dist/utils/constants.js.map +1 -0
  342. package/dist/utils/credentials.js +67 -114
  343. package/dist/utils/credentials.js.map +1 -0
  344. package/dist/utils/fetch.js +22 -20
  345. package/dist/utils/fetch.js.map +1 -0
  346. package/dist/utils/flattenJsonFiles.js +27 -34
  347. package/dist/utils/flattenJsonFiles.js.map +1 -0
  348. package/dist/utils/gitDiff.js +30 -32
  349. package/dist/utils/gitDiff.js.map +1 -0
  350. package/dist/utils/gt.js +7 -2
  351. package/dist/utils/gt.js.map +1 -0
  352. package/dist/utils/hash.js +14 -9
  353. package/dist/utils/hash.js.map +1 -0
  354. package/dist/utils/headers.js +10 -13
  355. package/dist/utils/headers.js.map +1 -0
  356. package/dist/utils/installPackage.js +70 -75
  357. package/dist/utils/installPackage.js.map +1 -0
  358. package/dist/utils/localizeRelativeAssets.js +114 -157
  359. package/dist/utils/localizeRelativeAssets.js.map +1 -0
  360. package/dist/utils/localizeStaticImports.js +229 -371
  361. package/dist/utils/localizeStaticImports.js.map +1 -0
  362. package/dist/utils/localizeStaticUrls.js +241 -424
  363. package/dist/utils/localizeStaticUrls.js.map +1 -0
  364. package/dist/utils/mintlifyTitleFallback.js +64 -72
  365. package/dist/utils/mintlifyTitleFallback.js.map +1 -0
  366. package/dist/utils/monorepoVersionCheck.js +177 -215
  367. package/dist/utils/monorepoVersionCheck.js.map +1 -0
  368. package/dist/utils/packageInfo.js +17 -16
  369. package/dist/utils/packageInfo.js.map +1 -0
  370. package/dist/utils/packageJson.js +51 -66
  371. package/dist/utils/packageJson.js.map +1 -0
  372. package/dist/utils/packageManager.js +237 -260
  373. package/dist/utils/packageManager.js.map +1 -0
  374. package/dist/utils/parse/needsCJS.js +36 -69
  375. package/dist/utils/parse/needsCJS.js.map +1 -0
  376. package/dist/utils/persistPostprocessHashes.js +30 -32
  377. package/dist/utils/persistPostprocessHashes.js.map +1 -0
  378. package/dist/utils/processAnchorIds.js +32 -54
  379. package/dist/utils/processAnchorIds.js.map +1 -0
  380. package/dist/utils/processOpenApi.js +469 -578
  381. package/dist/utils/processOpenApi.js.map +1 -0
  382. package/dist/utils/resolveMintlifyRefs.js +89 -105
  383. package/dist/utils/resolveMintlifyRefs.js.map +1 -0
  384. package/dist/utils/resolvePublish.js +46 -54
  385. package/dist/utils/resolvePublish.js.map +1 -0
  386. package/dist/utils/sanitizeFileContent.js +20 -27
  387. package/dist/utils/sanitizeFileContent.js.map +1 -0
  388. package/dist/utils/sharedStaticAssets.js +248 -366
  389. package/dist/utils/sharedStaticAssets.js.map +1 -0
  390. package/dist/utils/splitMintlifyLanguageRefs.js +208 -282
  391. package/dist/utils/splitMintlifyLanguageRefs.js.map +1 -0
  392. package/dist/utils/validateMdx.js +26 -23
  393. package/dist/utils/validateMdx.js.map +1 -0
  394. package/dist/utils/wrapPlainUrls.js +58 -70
  395. package/dist/utils/wrapPlainUrls.js.map +1 -0
  396. package/dist/workflows/download.js +92 -126
  397. package/dist/workflows/download.js.map +1 -0
  398. package/dist/workflows/enqueue.js +47 -54
  399. package/dist/workflows/enqueue.js.map +1 -0
  400. package/dist/workflows/publish.js +29 -29
  401. package/dist/workflows/publish.js.map +1 -0
  402. package/dist/workflows/setupProject.js +39 -40
  403. package/dist/workflows/setupProject.js.map +1 -0
  404. package/dist/workflows/stage.js +61 -65
  405. package/dist/workflows/stage.js.map +1 -0
  406. package/dist/workflows/steps/BranchStep.js +118 -163
  407. package/dist/workflows/steps/BranchStep.js.map +1 -0
  408. package/dist/workflows/steps/DownloadStep.js +107 -137
  409. package/dist/workflows/steps/DownloadStep.js.map +1 -0
  410. package/dist/workflows/steps/EnqueueStep.js +32 -32
  411. package/dist/workflows/steps/EnqueueStep.js.map +1 -0
  412. package/dist/workflows/steps/PollJobsStep.js +208 -292
  413. package/dist/workflows/steps/PollJobsStep.js.map +1 -0
  414. package/dist/workflows/steps/PublishStep.js +33 -38
  415. package/dist/workflows/steps/PublishStep.js.map +1 -0
  416. package/dist/workflows/steps/SetupStep.js +71 -72
  417. package/dist/workflows/steps/SetupStep.js.map +1 -0
  418. package/dist/workflows/steps/TagStep.js +39 -44
  419. package/dist/workflows/steps/TagStep.js.map +1 -0
  420. package/dist/workflows/steps/UploadSourcesStep.js +108 -140
  421. package/dist/workflows/steps/UploadSourcesStep.js.map +1 -0
  422. package/dist/workflows/steps/UploadTranslationsStep.js +61 -71
  423. package/dist/workflows/steps/UploadTranslationsStep.js.map +1 -0
  424. package/dist/workflows/steps/UserEditDiffsStep.js +32 -34
  425. package/dist/workflows/steps/UserEditDiffsStep.js.map +1 -0
  426. package/dist/workflows/steps/WorkflowStep.js +6 -2
  427. package/dist/workflows/steps/WorkflowStep.js.map +1 -0
  428. package/dist/workflows/upload.js +45 -46
  429. package/dist/workflows/upload.js.map +1 -0
  430. package/package.json +14 -7
@@ -1,1124 +1,760 @@
1
- import * as t from '@babel/types';
2
- import { buildImportMap } from './buildImportMap.js';
3
- import { resolveImportPath } from './resolveImportPath.js';
4
- import { parse } from '@babel/parser';
5
- import fs from 'node:fs';
6
- import { warnDeriveFunctionNoResultsSync, warnFunctionNotFoundSync, warnInvalidDeclareVarNameSync, warnDeriveNonConstVariableSync, warnDeriveUnresolvableValueSync, warnDeriveOptionalChainingSync, warnDeriveDestructuringSync, warnDeriveCircularSpreadSync, } from '../../../console/index.js';
7
- import traverseModule from '@babel/traverse';
8
- import { DECLARE_VAR_FUNCTION } from '../../jsx/utils/constants.js';
9
- import { GT_LIBRARIES } from '../../../types/libraries.js';
10
- import { declareVar } from 'generaltranslation/internal';
11
- import { isStaticExpression } from '../evaluateJsx.js';
12
- import generateModule from '@babel/generator';
13
- // Handle CommonJS/ESM interop
1
+ import { isStaticExpression } from "../evaluateJsx.js";
2
+ import "./constants.js";
3
+ import { warnDeriveCircularSpreadSync, warnDeriveDestructuringSync, warnDeriveFunctionNoResultsSync, warnDeriveNonConstVariableSync, warnDeriveOptionalChainingSync, warnDeriveUnresolvableValueSync, warnFunctionNotFoundSync, warnInvalidDeclareVarNameSync } from "../../../console/index.js";
4
+ import { resolveImportPath } from "./resolveImportPath.js";
5
+ import { buildImportMap } from "./buildImportMap.js";
6
+ import { GT_LIBRARIES } from "../../../types/libraries.js";
7
+ import fs from "node:fs";
8
+ import * as t from "@babel/types";
9
+ import { parse } from "@babel/parser";
10
+ import generateModule from "@babel/generator";
11
+ import { declareVar } from "generaltranslation/internal";
12
+ import traverseModule from "@babel/traverse";
13
+ //#region src/react/jsx/utils/parseString.ts
14
14
  const traverse = traverseModule.default || traverseModule;
15
15
  const generate = generateModule.default || generateModule;
16
16
  /**
17
- * Cache for resolved import paths to avoid redundant I/O operations.
18
- */
19
- const resolveImportPathCache = new Map();
17
+ * Cache for resolved import paths to avoid redundant I/O operations.
18
+ */
19
+ const resolveImportPathCache = /* @__PURE__ */ new Map();
20
20
  /**
21
- * Cache for processed functions to avoid re-parsing the same files.
22
- */
23
- const processFunctionCache = new Map();
21
+ * Cache for processed functions to avoid re-parsing the same files.
22
+ */
23
+ const processFunctionCache = /* @__PURE__ */ new Map();
24
24
  /**
25
- * Cache for resolved object nodes to avoid re-parsing the same files.
26
- */
27
- const resolveObjectNodeCache = new Map();
25
+ * Cache for resolved object nodes to avoid re-parsing the same files.
26
+ */
27
+ const resolveObjectNodeCache = /* @__PURE__ */ new Map();
28
28
  /**
29
- * Guard against infinite recursion when resolving identifier chains.
30
- * Tracks AST nodes currently being resolved to detect circular references.
31
- */
32
- const resolvingIdentifiers = new Set();
29
+ * Guard against infinite recursion when resolving identifier chains.
30
+ * Tracks AST nodes currently being resolved to detect circular references.
31
+ */
32
+ const resolvingIdentifiers = /* @__PURE__ */ new Set();
33
33
  /**
34
- * Unwraps TypeScript type annotations to get the underlying expression.
35
- * Handles: as, satisfies, non-null assertion (!), and angle-bracket assertions.
36
- */
34
+ * Unwraps TypeScript type annotations to get the underlying expression.
35
+ * Handles: as, satisfies, non-null assertion (!), and angle-bracket assertions.
36
+ */
37
37
  function unwrapTypeAnnotation(node) {
38
- if (t.isTSAsExpression(node))
39
- return node.expression;
40
- if (t.isTSSatisfiesExpression(node))
41
- return node.expression;
42
- if (t.isTSNonNullExpression(node))
43
- return node.expression;
44
- if (t.isTSTypeAssertion(node))
45
- return node.expression;
46
- return node;
38
+ if (t.isTSAsExpression(node)) return node.expression;
39
+ if (t.isTSSatisfiesExpression(node)) return node.expression;
40
+ if (t.isTSNonNullExpression(node)) return node.expression;
41
+ if (t.isTSTypeAssertion(node)) return node.expression;
42
+ return node;
47
43
  }
48
44
  /**
49
- * Collects all resolvable property entries from an ObjectExpression,
50
- * including entries from spread sources.
51
- */
45
+ * Collects all resolvable property entries from an ObjectExpression,
46
+ * including entries from spread sources.
47
+ */
52
48
  function collectObjectProperties(objExpr, tPath, file, parsingOptions, errors = []) {
53
- const entries = [];
54
- for (const prop of objExpr.properties) {
55
- if (t.isObjectProperty(prop)) {
56
- const key = !prop.computed && t.isIdentifier(prop.key)
57
- ? prop.key.name
58
- : t.isStringLiteral(prop.key)
59
- ? prop.key.value
60
- : t.isNumericLiteral(prop.key)
61
- ? String(prop.key.value)
62
- : null;
63
- if (t.isExpression(prop.value)) {
64
- entries.push({ key, value: prop.value });
65
- }
66
- }
67
- else if (t.isSpreadElement(prop)) {
68
- // Handle inline ObjectExpression spread: { ...({ a: 'x' }) }
69
- const spreadArg = unwrapTypeAnnotation(prop.argument);
70
- if (t.isObjectExpression(spreadArg)) {
71
- entries.push(...collectObjectProperties(spreadArg, tPath, file, parsingOptions, errors));
72
- continue;
73
- }
74
- if (!t.isIdentifier(prop.argument))
75
- continue;
76
- const spreadBinding = tPath.scope.getBinding(prop.argument.name);
77
- if (!spreadBinding)
78
- continue;
79
- // Same-file: VariableDeclarator
80
- if (spreadBinding.path.isVariableDeclarator()) {
81
- const spreadDecl = spreadBinding.path.parentPath;
82
- if (spreadDecl?.isVariableDeclaration() &&
83
- spreadDecl.node.kind !== 'const')
84
- continue;
85
- const spreadInit = spreadBinding.path.node.init;
86
- if (!spreadInit)
87
- continue;
88
- // Guard against circular spreads
89
- if (resolvingIdentifiers.has(spreadInit)) {
90
- errors.push(warnDeriveCircularSpreadSync(file, prop.argument.name, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
91
- continue;
92
- }
93
- resolvingIdentifiers.add(spreadInit);
94
- const spreadObj = unwrapTypeAnnotation(spreadInit);
95
- if (!t.isObjectExpression(spreadObj)) {
96
- resolvingIdentifiers.delete(spreadInit);
97
- continue;
98
- }
99
- entries.push(...collectObjectProperties(spreadObj, spreadBinding.path, file, parsingOptions, errors));
100
- resolvingIdentifiers.delete(spreadInit);
101
- }
102
- // Cross-file: ImportSpecifier or ImportDefaultSpecifier
103
- else if (spreadBinding.path.isImportSpecifier() ||
104
- spreadBinding.path.isImportDefaultSpecifier()) {
105
- const programPath = tPath.scope.getProgramParent().path;
106
- const importMap = buildImportMap(programPath);
107
- const importPath = importMap.get(prop.argument.name);
108
- if (!importPath)
109
- continue;
110
- let originalName = prop.argument.name;
111
- if (spreadBinding.path.isImportSpecifier()) {
112
- const imported = spreadBinding.path.node.imported;
113
- originalName = t.isIdentifier(imported)
114
- ? imported.name
115
- : imported.value;
116
- }
117
- const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
118
- if (!resolvedFilePath)
119
- continue;
120
- const crossFileObjects = resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions);
121
- for (const crossObj of crossFileObjects) {
122
- const crossEntries = t.isArrayExpression(crossObj.objExpr)
123
- ? collectArrayElements(crossObj.objExpr, crossObj.tPath, crossObj.file, parsingOptions)
124
- : collectObjectProperties(crossObj.objExpr, crossObj.tPath, crossObj.file, parsingOptions, errors);
125
- entries.push(...crossEntries);
126
- }
127
- }
128
- }
129
- // Skip ObjectMethod (getters, setters, methods)
130
- }
131
- return entries;
49
+ const entries = [];
50
+ for (const prop of objExpr.properties) if (t.isObjectProperty(prop)) {
51
+ const key = !prop.computed && t.isIdentifier(prop.key) ? prop.key.name : t.isStringLiteral(prop.key) ? prop.key.value : t.isNumericLiteral(prop.key) ? String(prop.key.value) : null;
52
+ if (t.isExpression(prop.value)) entries.push({
53
+ key,
54
+ value: prop.value
55
+ });
56
+ } else if (t.isSpreadElement(prop)) {
57
+ const spreadArg = unwrapTypeAnnotation(prop.argument);
58
+ if (t.isObjectExpression(spreadArg)) {
59
+ entries.push(...collectObjectProperties(spreadArg, tPath, file, parsingOptions, errors));
60
+ continue;
61
+ }
62
+ if (!t.isIdentifier(prop.argument)) continue;
63
+ const spreadBinding = tPath.scope.getBinding(prop.argument.name);
64
+ if (!spreadBinding) continue;
65
+ if (spreadBinding.path.isVariableDeclarator()) {
66
+ const spreadDecl = spreadBinding.path.parentPath;
67
+ if (spreadDecl?.isVariableDeclaration() && spreadDecl.node.kind !== "const") continue;
68
+ const spreadInit = spreadBinding.path.node.init;
69
+ if (!spreadInit) continue;
70
+ if (resolvingIdentifiers.has(spreadInit)) {
71
+ errors.push(warnDeriveCircularSpreadSync(file, prop.argument.name, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
72
+ continue;
73
+ }
74
+ resolvingIdentifiers.add(spreadInit);
75
+ const spreadObj = unwrapTypeAnnotation(spreadInit);
76
+ if (!t.isObjectExpression(spreadObj)) {
77
+ resolvingIdentifiers.delete(spreadInit);
78
+ continue;
79
+ }
80
+ entries.push(...collectObjectProperties(spreadObj, spreadBinding.path, file, parsingOptions, errors));
81
+ resolvingIdentifiers.delete(spreadInit);
82
+ } else if (spreadBinding.path.isImportSpecifier() || spreadBinding.path.isImportDefaultSpecifier()) {
83
+ const programPath = tPath.scope.getProgramParent().path;
84
+ const importPath = buildImportMap(programPath).get(prop.argument.name);
85
+ if (!importPath) continue;
86
+ let originalName = prop.argument.name;
87
+ if (spreadBinding.path.isImportSpecifier()) {
88
+ const imported = spreadBinding.path.node.imported;
89
+ originalName = t.isIdentifier(imported) ? imported.name : imported.value;
90
+ }
91
+ const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
92
+ if (!resolvedFilePath) continue;
93
+ const crossFileObjects = resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions);
94
+ for (const crossObj of crossFileObjects) {
95
+ const crossEntries = t.isArrayExpression(crossObj.objExpr) ? collectArrayElements(crossObj.objExpr, crossObj.tPath, crossObj.file, parsingOptions) : collectObjectProperties(crossObj.objExpr, crossObj.tPath, crossObj.file, parsingOptions, errors);
96
+ entries.push(...crossEntries);
97
+ }
98
+ }
99
+ }
100
+ return entries;
132
101
  }
133
102
  /**
134
- * Collects elements from an ArrayExpression as ObjectEntry[] with index as key.
135
- * Handles spread elements by resolving the source array.
136
- */
103
+ * Collects elements from an ArrayExpression as ObjectEntry[] with index as key.
104
+ * Handles spread elements by resolving the source array.
105
+ */
137
106
  function collectArrayElements(arrExpr, tPath, file, parsingOptions, errors = []) {
138
- const entries = [];
139
- let index = 0;
140
- for (const el of arrExpr.elements) {
141
- if (!el) {
142
- index++;
143
- continue;
144
- } // sparse hole
145
- if (t.isSpreadElement(el)) {
146
- if (!t.isIdentifier(el.argument)) {
147
- continue;
148
- }
149
- const spreadBinding = tPath.scope.getBinding(el.argument.name);
150
- if (!spreadBinding)
151
- continue;
152
- // Same-file spread
153
- if (spreadBinding.path.isVariableDeclarator()) {
154
- const spreadDecl = spreadBinding.path.parentPath;
155
- if (spreadDecl?.isVariableDeclaration() &&
156
- spreadDecl.node.kind !== 'const') {
157
- errors.push(warnDeriveNonConstVariableSync(file, el.argument.name, spreadDecl.node.kind, `${el.loc?.start?.line}:${el.loc?.start?.column}`));
158
- continue;
159
- }
160
- const spreadInit = spreadBinding.path.node.init;
161
- if (!spreadInit)
162
- continue;
163
- const spreadUnwrapped = unwrapTypeAnnotation(spreadInit);
164
- if (t.isArrayExpression(spreadUnwrapped)) {
165
- const spreadEntries = collectArrayElements(spreadUnwrapped, spreadBinding.path, file, parsingOptions);
166
- for (const e of spreadEntries) {
167
- entries.push({ key: String(index++), value: e.value });
168
- }
169
- continue;
170
- }
171
- }
172
- // Cross-file spread
173
- else if (spreadBinding.path.isImportSpecifier() ||
174
- spreadBinding.path.isImportDefaultSpecifier()) {
175
- const programPath = tPath.scope.getProgramParent().path;
176
- const importMap = buildImportMap(programPath);
177
- const importPath = importMap.get(el.argument.name);
178
- if (!importPath)
179
- continue;
180
- let originalName = el.argument.name;
181
- if (spreadBinding.path.isImportSpecifier()) {
182
- const imported = spreadBinding.path.node.imported;
183
- originalName = t.isIdentifier(imported)
184
- ? imported.name
185
- : imported.value;
186
- }
187
- const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
188
- if (!resolvedFilePath)
189
- continue;
190
- const crossFileNodes = resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions);
191
- for (const crossNode of crossFileNodes) {
192
- if (t.isArrayExpression(crossNode.objExpr)) {
193
- const spreadEntries = collectArrayElements(crossNode.objExpr, crossNode.tPath, crossNode.file, parsingOptions);
194
- for (const e of spreadEntries) {
195
- entries.push({ key: String(index++), value: e.value });
196
- }
197
- }
198
- }
199
- }
200
- continue;
201
- }
202
- if (t.isExpression(el)) {
203
- entries.push({ key: String(index), value: unwrapTypeAnnotation(el) });
204
- }
205
- index++;
206
- }
207
- return entries;
107
+ const entries = [];
108
+ let index = 0;
109
+ for (const el of arrExpr.elements) {
110
+ if (!el) {
111
+ index++;
112
+ continue;
113
+ }
114
+ if (t.isSpreadElement(el)) {
115
+ if (!t.isIdentifier(el.argument)) continue;
116
+ const spreadBinding = tPath.scope.getBinding(el.argument.name);
117
+ if (!spreadBinding) continue;
118
+ if (spreadBinding.path.isVariableDeclarator()) {
119
+ const spreadDecl = spreadBinding.path.parentPath;
120
+ if (spreadDecl?.isVariableDeclaration() && spreadDecl.node.kind !== "const") {
121
+ errors.push(warnDeriveNonConstVariableSync(file, el.argument.name, spreadDecl.node.kind, `${el.loc?.start?.line}:${el.loc?.start?.column}`));
122
+ continue;
123
+ }
124
+ const spreadInit = spreadBinding.path.node.init;
125
+ if (!spreadInit) continue;
126
+ const spreadUnwrapped = unwrapTypeAnnotation(spreadInit);
127
+ if (t.isArrayExpression(spreadUnwrapped)) {
128
+ const spreadEntries = collectArrayElements(spreadUnwrapped, spreadBinding.path, file, parsingOptions);
129
+ for (const e of spreadEntries) entries.push({
130
+ key: String(index++),
131
+ value: e.value
132
+ });
133
+ continue;
134
+ }
135
+ } else if (spreadBinding.path.isImportSpecifier() || spreadBinding.path.isImportDefaultSpecifier()) {
136
+ const programPath = tPath.scope.getProgramParent().path;
137
+ const importPath = buildImportMap(programPath).get(el.argument.name);
138
+ if (!importPath) continue;
139
+ let originalName = el.argument.name;
140
+ if (spreadBinding.path.isImportSpecifier()) {
141
+ const imported = spreadBinding.path.node.imported;
142
+ originalName = t.isIdentifier(imported) ? imported.name : imported.value;
143
+ }
144
+ const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
145
+ if (!resolvedFilePath) continue;
146
+ const crossFileNodes = resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions);
147
+ for (const crossNode of crossFileNodes) if (t.isArrayExpression(crossNode.objExpr)) {
148
+ const spreadEntries = collectArrayElements(crossNode.objExpr, crossNode.tPath, crossNode.file, parsingOptions);
149
+ for (const e of spreadEntries) entries.push({
150
+ key: String(index++),
151
+ value: e.value
152
+ });
153
+ }
154
+ }
155
+ continue;
156
+ }
157
+ if (t.isExpression(el)) entries.push({
158
+ key: String(index),
159
+ value: unwrapTypeAnnotation(el)
160
+ });
161
+ index++;
162
+ }
163
+ return entries;
208
164
  }
209
165
  /**
210
- * Resolves an expression to ObjectExpression or ArrayExpression AST node(s).
211
- * Handles Identifier (local + imported) and MemberExpression (nested access chains).
212
- */
166
+ * Resolves an expression to ObjectExpression or ArrayExpression AST node(s).
167
+ * Handles Identifier (local + imported) and MemberExpression (nested access chains).
168
+ */
213
169
  function resolveToObjectNodes(node, tPath, file, parsingOptions, warnings, errors = []) {
214
- // Case 1: Identifier — base case
215
- if (t.isIdentifier(node)) {
216
- const binding = tPath.scope.getBinding(node.name);
217
- if (!binding)
218
- return [];
219
- // Local variable
220
- if (binding.path.isVariableDeclarator()) {
221
- const declaration = binding.path.parentPath;
222
- if (declaration?.isVariableDeclaration() &&
223
- declaration.node.kind !== 'const') {
224
- warnings.add(warnDeriveNonConstVariableSync(file, node.name, declaration.node.kind, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
225
- return [];
226
- }
227
- const init = binding.path.node.init;
228
- if (!init)
229
- return [];
230
- const unwrapped = unwrapTypeAnnotation(init);
231
- if (t.isObjectExpression(unwrapped) || t.isArrayExpression(unwrapped)) {
232
- return [{ objExpr: unwrapped, tPath: binding.path, file }];
233
- }
234
- // Handle identifier chain: const A = B; const B = { ... }
235
- if (t.isIdentifier(unwrapped)) {
236
- return resolveToObjectNodes(unwrapped, binding.path, file, parsingOptions, warnings, errors);
237
- }
238
- // Handle conditional: cond ? { ... } : { ... } (including nested ternaries)
239
- if (t.isConditionalExpression(unwrapped)) {
240
- const collectConditionalLeaves = (expr) => {
241
- const inner = unwrapTypeAnnotation(expr);
242
- if (t.isConditionalExpression(inner)) {
243
- return [
244
- ...collectConditionalLeaves(inner.consequent),
245
- ...collectConditionalLeaves(inner.alternate),
246
- ];
247
- }
248
- if (t.isObjectExpression(inner) || t.isArrayExpression(inner)) {
249
- return [{ objExpr: inner, tPath: binding.path, file }];
250
- }
251
- return [];
252
- };
253
- return [
254
- ...collectConditionalLeaves(unwrapped.consequent),
255
- ...collectConditionalLeaves(unwrapped.alternate),
256
- ];
257
- }
258
- return [];
259
- }
260
- // Imported
261
- if (binding.path.isImportSpecifier() ||
262
- binding.path.isImportDefaultSpecifier()) {
263
- const programPath = tPath.scope.getProgramParent().path;
264
- const importMap = buildImportMap(programPath);
265
- const importPath = importMap.get(node.name);
266
- if (!importPath)
267
- return [];
268
- let originalName = node.name;
269
- if (binding.path.isImportSpecifier()) {
270
- const imported = binding.path.node.imported;
271
- originalName = t.isIdentifier(imported)
272
- ? imported.name
273
- : imported.value;
274
- }
275
- const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
276
- if (!resolvedFilePath)
277
- return [];
278
- return resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions);
279
- }
280
- return [];
281
- }
282
- // Case 2: MemberExpression recursive
283
- if (t.isMemberExpression(node)) {
284
- if (!t.isExpression(node.object))
285
- return [];
286
- const parentObjects = resolveToObjectNodes(node.object, tPath, file, parsingOptions, warnings, errors);
287
- if (parentObjects.length === 0)
288
- return [];
289
- const results = [];
290
- for (const parent of parentObjects) {
291
- const entries = t.isArrayExpression(parent.objExpr)
292
- ? collectArrayElements(parent.objExpr, parent.tPath, parent.file, parsingOptions)
293
- : collectObjectProperties(parent.objExpr, parent.tPath, parent.file, parsingOptions, errors);
294
- // Determine if this is a static access (known key)
295
- let staticKey = null;
296
- if (!node.computed && t.isIdentifier(node.property)) {
297
- staticKey = node.property.name;
298
- }
299
- else if (node.computed && t.isStringLiteral(node.property)) {
300
- staticKey = node.property.value;
301
- }
302
- else if (node.computed && t.isNumericLiteral(node.property)) {
303
- staticKey = String(node.property.value);
304
- }
305
- if (staticKey !== null) {
306
- // Static: narrow to matching key(s) — don't break, spreads may duplicate keys
307
- for (const entry of entries) {
308
- if (entry.key === staticKey) {
309
- const unwrapped = unwrapTypeAnnotation(entry.value);
310
- if (t.isObjectExpression(unwrapped) ||
311
- t.isArrayExpression(unwrapped)) {
312
- results.push({
313
- objExpr: unwrapped,
314
- tPath: parent.tPath,
315
- file: parent.file,
316
- });
317
- }
318
- }
319
- }
320
- }
321
- else {
322
- // Dynamic: collect ALL entries whose values are ObjectExpressions or ArrayExpressions
323
- for (const entry of entries) {
324
- const unwrapped = unwrapTypeAnnotation(entry.value);
325
- if (t.isObjectExpression(unwrapped) ||
326
- t.isArrayExpression(unwrapped)) {
327
- results.push({
328
- objExpr: unwrapped,
329
- tPath: parent.tPath,
330
- file: parent.file,
331
- });
332
- }
333
- }
334
- }
335
- }
336
- return results;
337
- }
338
- return [];
170
+ if (t.isIdentifier(node)) {
171
+ const binding = tPath.scope.getBinding(node.name);
172
+ if (!binding) return [];
173
+ if (binding.path.isVariableDeclarator()) {
174
+ const declaration = binding.path.parentPath;
175
+ if (declaration?.isVariableDeclaration() && declaration.node.kind !== "const") {
176
+ warnings.add(warnDeriveNonConstVariableSync(file, node.name, declaration.node.kind, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
177
+ return [];
178
+ }
179
+ const init = binding.path.node.init;
180
+ if (!init) return [];
181
+ const unwrapped = unwrapTypeAnnotation(init);
182
+ if (t.isObjectExpression(unwrapped) || t.isArrayExpression(unwrapped)) return [{
183
+ objExpr: unwrapped,
184
+ tPath: binding.path,
185
+ file
186
+ }];
187
+ if (t.isIdentifier(unwrapped)) return resolveToObjectNodes(unwrapped, binding.path, file, parsingOptions, warnings, errors);
188
+ if (t.isConditionalExpression(unwrapped)) {
189
+ const collectConditionalLeaves = (expr) => {
190
+ const inner = unwrapTypeAnnotation(expr);
191
+ if (t.isConditionalExpression(inner)) return [...collectConditionalLeaves(inner.consequent), ...collectConditionalLeaves(inner.alternate)];
192
+ if (t.isObjectExpression(inner) || t.isArrayExpression(inner)) return [{
193
+ objExpr: inner,
194
+ tPath: binding.path,
195
+ file
196
+ }];
197
+ return [];
198
+ };
199
+ return [...collectConditionalLeaves(unwrapped.consequent), ...collectConditionalLeaves(unwrapped.alternate)];
200
+ }
201
+ return [];
202
+ }
203
+ if (binding.path.isImportSpecifier() || binding.path.isImportDefaultSpecifier()) {
204
+ const programPath = tPath.scope.getProgramParent().path;
205
+ const importPath = buildImportMap(programPath).get(node.name);
206
+ if (!importPath) return [];
207
+ let originalName = node.name;
208
+ if (binding.path.isImportSpecifier()) {
209
+ const imported = binding.path.node.imported;
210
+ originalName = t.isIdentifier(imported) ? imported.name : imported.value;
211
+ }
212
+ const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
213
+ if (!resolvedFilePath) return [];
214
+ return resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions);
215
+ }
216
+ return [];
217
+ }
218
+ if (t.isMemberExpression(node)) {
219
+ if (!t.isExpression(node.object)) return [];
220
+ const parentObjects = resolveToObjectNodes(node.object, tPath, file, parsingOptions, warnings, errors);
221
+ if (parentObjects.length === 0) return [];
222
+ const results = [];
223
+ for (const parent of parentObjects) {
224
+ const entries = t.isArrayExpression(parent.objExpr) ? collectArrayElements(parent.objExpr, parent.tPath, parent.file, parsingOptions) : collectObjectProperties(parent.objExpr, parent.tPath, parent.file, parsingOptions, errors);
225
+ let staticKey = null;
226
+ if (!node.computed && t.isIdentifier(node.property)) staticKey = node.property.name;
227
+ else if (node.computed && t.isStringLiteral(node.property)) staticKey = node.property.value;
228
+ else if (node.computed && t.isNumericLiteral(node.property)) staticKey = String(node.property.value);
229
+ if (staticKey !== null) {
230
+ for (const entry of entries) if (entry.key === staticKey) {
231
+ const unwrapped = unwrapTypeAnnotation(entry.value);
232
+ if (t.isObjectExpression(unwrapped) || t.isArrayExpression(unwrapped)) results.push({
233
+ objExpr: unwrapped,
234
+ tPath: parent.tPath,
235
+ file: parent.file
236
+ });
237
+ }
238
+ } else for (const entry of entries) {
239
+ const unwrapped = unwrapTypeAnnotation(entry.value);
240
+ if (t.isObjectExpression(unwrapped) || t.isArrayExpression(unwrapped)) results.push({
241
+ objExpr: unwrapped,
242
+ tPath: parent.tPath,
243
+ file: parent.file
244
+ });
245
+ }
246
+ }
247
+ return results;
248
+ }
249
+ return [];
339
250
  }
340
251
  /**
341
- * Resolves an object declaration from an external file.
342
- * Finds a const VariableDeclarator with ObjectExpression init.
343
- * Follows re-export chains.
344
- */
252
+ * Resolves an object declaration from an external file.
253
+ * Finds a const VariableDeclarator with ObjectExpression init.
254
+ * Follows re-export chains.
255
+ */
345
256
  function resolveObjectNodesInFile(filePath, name, parsingOptions) {
346
- const cacheKey = `${filePath}::${name}`;
347
- if (resolveObjectNodeCache.has(cacheKey)) {
348
- return resolveObjectNodeCache.get(cacheKey);
349
- }
350
- try {
351
- const code = fs.readFileSync(filePath, 'utf8');
352
- const ast = parse(code, {
353
- sourceType: 'module',
354
- plugins: ['jsx', 'typescript'],
355
- });
356
- const results = [];
357
- traverse(ast, {
358
- VariableDeclarator(path) {
359
- if (t.isIdentifier(path.node.id) &&
360
- path.node.id.name === name &&
361
- results.length === 0) {
362
- const init = path.node.init;
363
- if (!init)
364
- return;
365
- const declaration = path.parentPath;
366
- if (declaration?.isVariableDeclaration() &&
367
- declaration.node.kind !== 'const')
368
- return;
369
- const unwrapped = unwrapTypeAnnotation(init);
370
- if (t.isObjectExpression(unwrapped) ||
371
- t.isArrayExpression(unwrapped)) {
372
- results.push({
373
- objExpr: unwrapped,
374
- tPath: path,
375
- file: filePath,
376
- });
377
- }
378
- }
379
- },
380
- ExportAllDeclaration(path) {
381
- if (results.length > 0)
382
- return;
383
- if (t.isStringLiteral(path.node.source)) {
384
- const reexportPath = path.node.source.value;
385
- const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
386
- if (resolvedPath) {
387
- results.push(...resolveObjectNodesInFile(resolvedPath, name, parsingOptions));
388
- }
389
- }
390
- },
391
- ExportNamedDeclaration(path) {
392
- if (results.length > 0)
393
- return;
394
- if (path.node.source && t.isStringLiteral(path.node.source)) {
395
- const hasMatch = path.node.specifiers.some((spec) => {
396
- if (t.isExportSpecifier(spec)) {
397
- const exportedName = t.isIdentifier(spec.exported)
398
- ? spec.exported.name
399
- : spec.exported.value;
400
- return exportedName === name;
401
- }
402
- return false;
403
- });
404
- if (hasMatch) {
405
- const reexportPath = path.node.source.value;
406
- const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
407
- if (resolvedPath) {
408
- const specifier = path.node.specifiers.find((spec) => {
409
- if (t.isExportSpecifier(spec)) {
410
- const exportedName = t.isIdentifier(spec.exported)
411
- ? spec.exported.name
412
- : spec.exported.value;
413
- return exportedName === name;
414
- }
415
- return false;
416
- });
417
- let originalName = name;
418
- if (specifier &&
419
- t.isExportSpecifier(specifier) &&
420
- t.isIdentifier(specifier.local)) {
421
- originalName = specifier.local.name;
422
- }
423
- results.push(...resolveObjectNodesInFile(resolvedPath, originalName, parsingOptions));
424
- }
425
- }
426
- }
427
- },
428
- });
429
- resolveObjectNodeCache.set(cacheKey, results);
430
- return results;
431
- }
432
- catch {
433
- resolveObjectNodeCache.set(cacheKey, []);
434
- return [];
435
- }
257
+ const cacheKey = `${filePath}::${name}`;
258
+ if (resolveObjectNodeCache.has(cacheKey)) return resolveObjectNodeCache.get(cacheKey);
259
+ try {
260
+ const ast = parse(fs.readFileSync(filePath, "utf8"), {
261
+ sourceType: "module",
262
+ plugins: ["jsx", "typescript"]
263
+ });
264
+ const results = [];
265
+ traverse(ast, {
266
+ VariableDeclarator(path) {
267
+ if (t.isIdentifier(path.node.id) && path.node.id.name === name && results.length === 0) {
268
+ const init = path.node.init;
269
+ if (!init) return;
270
+ const declaration = path.parentPath;
271
+ if (declaration?.isVariableDeclaration() && declaration.node.kind !== "const") return;
272
+ const unwrapped = unwrapTypeAnnotation(init);
273
+ if (t.isObjectExpression(unwrapped) || t.isArrayExpression(unwrapped)) results.push({
274
+ objExpr: unwrapped,
275
+ tPath: path,
276
+ file: filePath
277
+ });
278
+ }
279
+ },
280
+ ExportAllDeclaration(path) {
281
+ if (results.length > 0) return;
282
+ if (t.isStringLiteral(path.node.source)) {
283
+ const reexportPath = path.node.source.value;
284
+ const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
285
+ if (resolvedPath) results.push(...resolveObjectNodesInFile(resolvedPath, name, parsingOptions));
286
+ }
287
+ },
288
+ ExportNamedDeclaration(path) {
289
+ if (results.length > 0) return;
290
+ if (path.node.source && t.isStringLiteral(path.node.source)) {
291
+ if (path.node.specifiers.some((spec) => {
292
+ if (t.isExportSpecifier(spec)) return (t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value) === name;
293
+ return false;
294
+ })) {
295
+ const reexportPath = path.node.source.value;
296
+ const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
297
+ if (resolvedPath) {
298
+ const specifier = path.node.specifiers.find((spec) => {
299
+ if (t.isExportSpecifier(spec)) return (t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value) === name;
300
+ return false;
301
+ });
302
+ let originalName = name;
303
+ if (specifier && t.isExportSpecifier(specifier) && t.isIdentifier(specifier.local)) originalName = specifier.local.name;
304
+ results.push(...resolveObjectNodesInFile(resolvedPath, originalName, parsingOptions));
305
+ }
306
+ }
307
+ }
308
+ }
309
+ });
310
+ resolveObjectNodeCache.set(cacheKey, results);
311
+ return results;
312
+ } catch {
313
+ resolveObjectNodeCache.set(cacheKey, []);
314
+ return [];
315
+ }
436
316
  }
437
317
  /**
438
- * Processes a string expression node and resolves any function calls within it
439
- * This handles cases like:
440
- * - "hello" (string literal)
441
- * - "hello" + world() (binary expression with function call)
442
- * - Math.random() > 0.5 ? "day" : "night" (conditional expression)
443
- * - greeting() (function call that returns string or conditional)
444
- *
445
- * @param node - The AST node to process
446
- * @param tPath - NodePath for scope resolution
447
- * @param file - Current file path
448
- * @param parsingOptions - Parsing configuration
449
- * @param warnings - Set to collect warning messages
450
- * @returns Node | null
451
- */
452
- export function parseStringExpression(node, tPath, file, parsingOptions, warnings, errors) {
453
- // Unwrap TypeScript type annotations (as, satisfies, !, <Type>)
454
- if (t.isTSAsExpression(node) ||
455
- t.isTSSatisfiesExpression(node) ||
456
- t.isTSNonNullExpression(node) ||
457
- t.isTSTypeAssertion(node)) {
458
- return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings, errors);
459
- }
460
- // Handle string literals
461
- if (t.isStringLiteral(node)) {
462
- return { type: 'text', text: node.value };
463
- }
464
- // Handle numeric literals
465
- if (t.isNumericLiteral(node)) {
466
- return { type: 'text', text: String(node.value) };
467
- }
468
- // Handle boolean literals
469
- if (t.isBooleanLiteral(node)) {
470
- return { type: 'text', text: String(node.value) };
471
- }
472
- // Handle null literal
473
- if (t.isNullLiteral(node)) {
474
- return { type: 'text', text: 'null' };
475
- }
476
- // Handle template literals
477
- if (t.isTemplateLiteral(node)) {
478
- const parts = [];
479
- for (let index = 0; index < node.quasis.length; index++) {
480
- const quasi = node.quasis[index];
481
- const text = quasi.value.cooked ?? quasi.value.raw ?? '';
482
- if (text) {
483
- parts.push({ type: 'text', text });
484
- }
485
- const exprNode = node.expressions[index];
486
- if (exprNode && t.isExpression(exprNode)) {
487
- const result = parseStringExpression(exprNode, tPath, file, parsingOptions, warnings, errors);
488
- if (result === null) {
489
- return null;
490
- }
491
- parts.push(result);
492
- }
493
- }
494
- if (parts.length === 0) {
495
- return { type: 'text', text: '' };
496
- }
497
- if (parts.length === 1) {
498
- return parts[0];
499
- }
500
- return { type: 'sequence', nodes: parts };
501
- }
502
- // Handle binary expressions (e.g., "hello" + world())
503
- if (t.isBinaryExpression(node) && node.operator === '+') {
504
- if (!t.isExpression(node.left) || !t.isExpression(node.right)) {
505
- return null;
506
- }
507
- const leftResult = parseStringExpression(node.left, tPath, file, parsingOptions, warnings, errors);
508
- const rightResult = parseStringExpression(node.right, tPath, file, parsingOptions, warnings, errors);
509
- if (leftResult === null || rightResult === null) {
510
- return null;
511
- }
512
- return { type: 'sequence', nodes: [leftResult, rightResult] };
513
- }
514
- // Handle conditional expressions (e.g., cond ? "day" : "night")
515
- if (t.isConditionalExpression(node)) {
516
- if (!t.isExpression(node.consequent) || !t.isExpression(node.alternate)) {
517
- return null;
518
- }
519
- const consequentResult = parseStringExpression(node.consequent, tPath, file, parsingOptions, warnings, errors);
520
- const alternateResult = parseStringExpression(node.alternate, tPath, file, parsingOptions, warnings, errors);
521
- if (consequentResult === null || alternateResult === null) {
522
- return null;
523
- }
524
- // Create a choice node with both branches
525
- return {
526
- type: 'choice',
527
- nodes: [consequentResult, alternateResult],
528
- };
529
- }
530
- // Handle variable references (e.g., result)
531
- if (t.isIdentifier(node)) {
532
- const binding = tPath.scope.getBinding(node.name);
533
- if (!binding) {
534
- // Variable not found in scope
535
- return null;
536
- }
537
- // Check if it's a const/let/var with an initializer
538
- if (binding.path.isVariableDeclarator() && binding.path.node.init) {
539
- // Check for destructuring patterns (not yet supported)
540
- if (t.isObjectPattern(binding.path.node.id) ||
541
- t.isArrayPattern(binding.path.node.id)) {
542
- errors.push(warnDeriveDestructuringSync(file, node.name, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
543
- return null;
544
- }
545
- // Guard against circular references (e.g., const A = B; const B = A)
546
- const init = binding.path.node.init;
547
- if (resolvingIdentifiers.has(init)) {
548
- return null;
549
- }
550
- // Enforce const-only
551
- const declaration = binding.path.parentPath;
552
- if (declaration?.isVariableDeclaration() &&
553
- declaration.node.kind !== 'const') {
554
- warnings.add(warnDeriveNonConstVariableSync(file, node.name, declaration.node.kind, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
555
- return null;
556
- }
557
- // Unwrap TSAsExpression (for `as const`)
558
- const unwrapped = unwrapTypeAnnotation(init);
559
- if (t.isExpression(unwrapped)) {
560
- // Recursively resolve the initializer with recursion guard
561
- resolvingIdentifiers.add(init);
562
- try {
563
- return parseStringExpression(unwrapped, binding.path, file, parsingOptions, warnings, errors);
564
- }
565
- finally {
566
- resolvingIdentifiers.delete(init);
567
- }
568
- }
569
- }
570
- // Check for destructuring patterns (not yet supported)
571
- if (binding.path.isObjectProperty() ||
572
- binding.path.isArrayPattern() ||
573
- binding.path.isRestElement()) {
574
- errors.push(warnDeriveDestructuringSync(file, node.name, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
575
- return null;
576
- }
577
- // Not a resolvable variable
578
- return null;
579
- }
580
- // Handle optional chaining — not supported, emit error
581
- if (t.isOptionalMemberExpression(node)) {
582
- errors.push(warnDeriveOptionalChainingSync(file, generate(node).code, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
583
- return null;
584
- }
585
- // Handle member expressions: obj[key], obj.prop, and nested obj.a.b / obj[a][b]
586
- if (t.isMemberExpression(node)) {
587
- if (!t.isExpression(node.object))
588
- return null;
589
- // Resolve the object part to ObjectExpression node(s)
590
- const objectNodes = resolveToObjectNodes(node.object, tPath, file, parsingOptions, warnings, errors);
591
- if (objectNodes.length === 0)
592
- return null;
593
- // Apply the final access to each resolved object
594
- const branches = [];
595
- for (const { objExpr, tPath: objPath, file: objFile } of objectNodes) {
596
- const entries = t.isArrayExpression(objExpr)
597
- ? collectArrayElements(objExpr, objPath, objFile, parsingOptions, errors)
598
- : collectObjectProperties(objExpr, objPath, objFile, parsingOptions, errors);
599
- // Check for static literal subscripts: obj['key'] or obj[0]
600
- let staticLiteralKey = null;
601
- if (node.computed && t.isStringLiteral(node.property)) {
602
- staticLiteralKey = node.property.value;
603
- }
604
- else if (node.computed && t.isNumericLiteral(node.property)) {
605
- staticLiteralKey = String(node.property.value);
606
- }
607
- // Determine the access key (if statically known)
608
- const propName = staticLiteralKey ??
609
- (!node.computed && t.isIdentifier(node.property)
610
- ? node.property.name
611
- : null);
612
- // Check if we can narrow: need a known access key AND all object keys must be resolvable
613
- const hasUnresolvableKeys = entries.some((e) => e.key === null);
614
- const canNarrow = propName !== null && !hasUnresolvableKeys;
615
- if (canNarrow) {
616
- // STATIC: extract ONE specific property
617
- for (const entry of entries) {
618
- if (entry.key === propName) {
619
- const resolved = parseStringExpression(entry.value, objPath, objFile, parsingOptions, warnings, errors);
620
- if (resolved) {
621
- branches.push(resolved);
622
- }
623
- else {
624
- errors.push(warnDeriveUnresolvableValueSync(objFile, propName, `${entry.value.loc?.start?.line}:${entry.value.loc?.start?.column}`));
625
- }
626
- // Don't break — spreads may introduce duplicate keys
627
- }
628
- }
629
- }
630
- else {
631
- // DYNAMIC: extract ALL values (can't determine which key matches)
632
- for (const entry of entries) {
633
- const resolved = parseStringExpression(entry.value, objPath, objFile, parsingOptions, warnings, errors);
634
- if (resolved) {
635
- branches.push(resolved);
636
- }
637
- else if (entry.key !== null) {
638
- errors.push(warnDeriveUnresolvableValueSync(objFile, entry.key, `${entry.value.loc?.start?.line}:${entry.value.loc?.start?.column}`));
639
- }
640
- }
641
- }
642
- }
643
- if (branches.length === 0)
644
- return null;
645
- if (branches.length === 1)
646
- return branches[0];
647
- return { type: 'choice', nodes: branches };
648
- }
649
- // Handle function calls (e.g., getName())
650
- if (t.isCallExpression(node) && t.isIdentifier(node.callee)) {
651
- const functionName = node.callee.name;
652
- const calleeBinding = tPath.scope.getBinding(functionName);
653
- if (!calleeBinding) {
654
- // Function not found in scope
655
- warnings.add(warnFunctionNotFoundSync(file, functionName, `${node.callee.loc?.start?.line}:${node.callee.loc?.start?.column}`));
656
- return null;
657
- }
658
- // Check if this is an imported function
659
- const programPath = tPath.scope.getProgramParent().path;
660
- const importedFunctionsMap = buildImportMap(programPath);
661
- if (importedFunctionsMap.has(functionName)) {
662
- // Function is imported - resolve cross-file
663
- let originalName;
664
- if (calleeBinding.path.isImportSpecifier()) {
665
- originalName = t.isIdentifier(calleeBinding.path.node.imported)
666
- ? calleeBinding.path.node.imported.name
667
- : calleeBinding.path.node.imported.value;
668
- }
669
- else if (calleeBinding.path.isImportDefaultSpecifier()) {
670
- originalName = calleeBinding.path.node.local.name;
671
- }
672
- else if (calleeBinding.path.isImportNamespaceSpecifier()) {
673
- originalName = calleeBinding.path.node.local.name;
674
- }
675
- const importPath = importedFunctionsMap.get(functionName);
676
- // Handle declareVar function
677
- if (originalName === DECLARE_VAR_FUNCTION &&
678
- GT_LIBRARIES.includes(importPath)) {
679
- // check for name field eg declareVar('test', { $name: 'test' })
680
- if (node.arguments.length > 1 &&
681
- t.isObjectExpression(node.arguments[1])) {
682
- const name = node.arguments[1].properties
683
- .filter((prop) => t.isObjectProperty(prop))
684
- .find((prop) => t.isIdentifier(prop.key) && prop.key.name === '$name')?.value;
685
- if (name) {
686
- if (!t.isExpression(name)) {
687
- warnings.add(warnInvalidDeclareVarNameSync(file, generate(name).code, `${node.arguments[1].loc?.start?.line}:${node.arguments[1].loc?.start?.column}`));
688
- return null;
689
- }
690
- const staticResult = isStaticExpression(name);
691
- if (!staticResult.isStatic) {
692
- warnings.add(warnInvalidDeclareVarNameSync(file, generate(name).code, `${node.arguments[1].loc?.start?.line}:${node.arguments[1].loc?.start?.column}`));
693
- return null;
694
- }
695
- return {
696
- type: 'text',
697
- text: declareVar('', { $name: staticResult.value }),
698
- };
699
- }
700
- }
701
- return {
702
- type: 'text',
703
- text: declareVar(''),
704
- };
705
- }
706
- const filePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
707
- if (filePath && originalName) {
708
- return resolveFunctionInFile(filePath, originalName, parsingOptions, warnings, errors);
709
- }
710
- return null;
711
- }
712
- // Resolve the function locally and get its return values
713
- return resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings, errors);
714
- }
715
- // Handle parenthesized expressions
716
- if (t.isParenthesizedExpression(node)) {
717
- return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings, errors);
718
- }
719
- // Handle unary expressions (e.g., -123)
720
- if (t.isUnaryExpression(node)) {
721
- let operator = '';
722
- if (node.operator === '-') {
723
- operator = node.operator;
724
- }
725
- if (t.isNumericLiteral(node.argument)) {
726
- if (node.argument.value === 0) {
727
- return { type: 'text', text: '0' };
728
- }
729
- else {
730
- return {
731
- type: 'text',
732
- text: operator + node.argument.value.toString(),
733
- };
734
- }
735
- }
736
- return null;
737
- }
738
- // Unsupported expression type
739
- return null;
318
+ * Processes a string expression node and resolves any function calls within it
319
+ * This handles cases like:
320
+ * - "hello" (string literal)
321
+ * - "hello" + world() (binary expression with function call)
322
+ * - Math.random() > 0.5 ? "day" : "night" (conditional expression)
323
+ * - greeting() (function call that returns string or conditional)
324
+ *
325
+ * @param node - The AST node to process
326
+ * @param tPath - NodePath for scope resolution
327
+ * @param file - Current file path
328
+ * @param parsingOptions - Parsing configuration
329
+ * @param warnings - Set to collect warning messages
330
+ * @returns Node | null
331
+ */
332
+ function parseStringExpression(node, tPath, file, parsingOptions, warnings, errors) {
333
+ if (t.isTSAsExpression(node) || t.isTSSatisfiesExpression(node) || t.isTSNonNullExpression(node) || t.isTSTypeAssertion(node)) return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings, errors);
334
+ if (t.isStringLiteral(node)) return {
335
+ type: "text",
336
+ text: node.value
337
+ };
338
+ if (t.isNumericLiteral(node)) return {
339
+ type: "text",
340
+ text: String(node.value)
341
+ };
342
+ if (t.isBooleanLiteral(node)) return {
343
+ type: "text",
344
+ text: String(node.value)
345
+ };
346
+ if (t.isNullLiteral(node)) return {
347
+ type: "text",
348
+ text: "null"
349
+ };
350
+ if (t.isTemplateLiteral(node)) {
351
+ const parts = [];
352
+ for (let index = 0; index < node.quasis.length; index++) {
353
+ const quasi = node.quasis[index];
354
+ const text = quasi.value.cooked ?? quasi.value.raw ?? "";
355
+ if (text) parts.push({
356
+ type: "text",
357
+ text
358
+ });
359
+ const exprNode = node.expressions[index];
360
+ if (exprNode && t.isExpression(exprNode)) {
361
+ const result = parseStringExpression(exprNode, tPath, file, parsingOptions, warnings, errors);
362
+ if (result === null) return null;
363
+ parts.push(result);
364
+ }
365
+ }
366
+ if (parts.length === 0) return {
367
+ type: "text",
368
+ text: ""
369
+ };
370
+ if (parts.length === 1) return parts[0];
371
+ return {
372
+ type: "sequence",
373
+ nodes: parts
374
+ };
375
+ }
376
+ if (t.isBinaryExpression(node) && node.operator === "+") {
377
+ if (!t.isExpression(node.left) || !t.isExpression(node.right)) return null;
378
+ const leftResult = parseStringExpression(node.left, tPath, file, parsingOptions, warnings, errors);
379
+ const rightResult = parseStringExpression(node.right, tPath, file, parsingOptions, warnings, errors);
380
+ if (leftResult === null || rightResult === null) return null;
381
+ return {
382
+ type: "sequence",
383
+ nodes: [leftResult, rightResult]
384
+ };
385
+ }
386
+ if (t.isConditionalExpression(node)) {
387
+ if (!t.isExpression(node.consequent) || !t.isExpression(node.alternate)) return null;
388
+ const consequentResult = parseStringExpression(node.consequent, tPath, file, parsingOptions, warnings, errors);
389
+ const alternateResult = parseStringExpression(node.alternate, tPath, file, parsingOptions, warnings, errors);
390
+ if (consequentResult === null || alternateResult === null) return null;
391
+ return {
392
+ type: "choice",
393
+ nodes: [consequentResult, alternateResult]
394
+ };
395
+ }
396
+ if (t.isIdentifier(node)) {
397
+ const binding = tPath.scope.getBinding(node.name);
398
+ if (!binding) return null;
399
+ if (binding.path.isVariableDeclarator() && binding.path.node.init) {
400
+ if (t.isObjectPattern(binding.path.node.id) || t.isArrayPattern(binding.path.node.id)) {
401
+ errors.push(warnDeriveDestructuringSync(file, node.name, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
402
+ return null;
403
+ }
404
+ const init = binding.path.node.init;
405
+ if (resolvingIdentifiers.has(init)) return null;
406
+ const declaration = binding.path.parentPath;
407
+ if (declaration?.isVariableDeclaration() && declaration.node.kind !== "const") {
408
+ warnings.add(warnDeriveNonConstVariableSync(file, node.name, declaration.node.kind, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
409
+ return null;
410
+ }
411
+ const unwrapped = unwrapTypeAnnotation(init);
412
+ if (t.isExpression(unwrapped)) {
413
+ resolvingIdentifiers.add(init);
414
+ try {
415
+ return parseStringExpression(unwrapped, binding.path, file, parsingOptions, warnings, errors);
416
+ } finally {
417
+ resolvingIdentifiers.delete(init);
418
+ }
419
+ }
420
+ }
421
+ if (binding.path.isObjectProperty() || binding.path.isArrayPattern() || binding.path.isRestElement()) {
422
+ errors.push(warnDeriveDestructuringSync(file, node.name, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
423
+ return null;
424
+ }
425
+ return null;
426
+ }
427
+ if (t.isOptionalMemberExpression(node)) {
428
+ errors.push(warnDeriveOptionalChainingSync(file, generate(node).code, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
429
+ return null;
430
+ }
431
+ if (t.isMemberExpression(node)) {
432
+ if (!t.isExpression(node.object)) return null;
433
+ const objectNodes = resolveToObjectNodes(node.object, tPath, file, parsingOptions, warnings, errors);
434
+ if (objectNodes.length === 0) return null;
435
+ const branches = [];
436
+ for (const { objExpr, tPath: objPath, file: objFile } of objectNodes) {
437
+ const entries = t.isArrayExpression(objExpr) ? collectArrayElements(objExpr, objPath, objFile, parsingOptions, errors) : collectObjectProperties(objExpr, objPath, objFile, parsingOptions, errors);
438
+ let staticLiteralKey = null;
439
+ if (node.computed && t.isStringLiteral(node.property)) staticLiteralKey = node.property.value;
440
+ else if (node.computed && t.isNumericLiteral(node.property)) staticLiteralKey = String(node.property.value);
441
+ const propName = staticLiteralKey ?? (!node.computed && t.isIdentifier(node.property) ? node.property.name : null);
442
+ const hasUnresolvableKeys = entries.some((e) => e.key === null);
443
+ if (propName !== null && !hasUnresolvableKeys) {
444
+ for (const entry of entries) if (entry.key === propName) {
445
+ const resolved = parseStringExpression(entry.value, objPath, objFile, parsingOptions, warnings, errors);
446
+ if (resolved) branches.push(resolved);
447
+ else errors.push(warnDeriveUnresolvableValueSync(objFile, propName, `${entry.value.loc?.start?.line}:${entry.value.loc?.start?.column}`));
448
+ }
449
+ } else for (const entry of entries) {
450
+ const resolved = parseStringExpression(entry.value, objPath, objFile, parsingOptions, warnings, errors);
451
+ if (resolved) branches.push(resolved);
452
+ else if (entry.key !== null) errors.push(warnDeriveUnresolvableValueSync(objFile, entry.key, `${entry.value.loc?.start?.line}:${entry.value.loc?.start?.column}`));
453
+ }
454
+ }
455
+ if (branches.length === 0) return null;
456
+ if (branches.length === 1) return branches[0];
457
+ return {
458
+ type: "choice",
459
+ nodes: branches
460
+ };
461
+ }
462
+ if (t.isCallExpression(node) && t.isIdentifier(node.callee)) {
463
+ const functionName = node.callee.name;
464
+ const calleeBinding = tPath.scope.getBinding(functionName);
465
+ if (!calleeBinding) {
466
+ warnings.add(warnFunctionNotFoundSync(file, functionName, `${node.callee.loc?.start?.line}:${node.callee.loc?.start?.column}`));
467
+ return null;
468
+ }
469
+ const programPath = tPath.scope.getProgramParent().path;
470
+ const importedFunctionsMap = buildImportMap(programPath);
471
+ if (importedFunctionsMap.has(functionName)) {
472
+ let originalName;
473
+ if (calleeBinding.path.isImportSpecifier()) originalName = t.isIdentifier(calleeBinding.path.node.imported) ? calleeBinding.path.node.imported.name : calleeBinding.path.node.imported.value;
474
+ else if (calleeBinding.path.isImportDefaultSpecifier()) originalName = calleeBinding.path.node.local.name;
475
+ else if (calleeBinding.path.isImportNamespaceSpecifier()) originalName = calleeBinding.path.node.local.name;
476
+ const importPath = importedFunctionsMap.get(functionName);
477
+ if (originalName === "declareVar" && GT_LIBRARIES.includes(importPath)) {
478
+ if (node.arguments.length > 1 && t.isObjectExpression(node.arguments[1])) {
479
+ const name = node.arguments[1].properties.filter((prop) => t.isObjectProperty(prop)).find((prop) => t.isIdentifier(prop.key) && prop.key.name === "$name")?.value;
480
+ if (name) {
481
+ if (!t.isExpression(name)) {
482
+ warnings.add(warnInvalidDeclareVarNameSync(file, generate(name).code, `${node.arguments[1].loc?.start?.line}:${node.arguments[1].loc?.start?.column}`));
483
+ return null;
484
+ }
485
+ const staticResult = isStaticExpression(name);
486
+ if (!staticResult.isStatic) {
487
+ warnings.add(warnInvalidDeclareVarNameSync(file, generate(name).code, `${node.arguments[1].loc?.start?.line}:${node.arguments[1].loc?.start?.column}`));
488
+ return null;
489
+ }
490
+ return {
491
+ type: "text",
492
+ text: declareVar("", { $name: staticResult.value })
493
+ };
494
+ }
495
+ }
496
+ return {
497
+ type: "text",
498
+ text: declareVar("")
499
+ };
500
+ }
501
+ const filePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
502
+ if (filePath && originalName) return resolveFunctionInFile(filePath, originalName, parsingOptions, warnings, errors);
503
+ return null;
504
+ }
505
+ return resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings, errors);
506
+ }
507
+ if (t.isParenthesizedExpression(node)) return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings, errors);
508
+ if (t.isUnaryExpression(node)) {
509
+ let operator = "";
510
+ if (node.operator === "-") operator = node.operator;
511
+ if (t.isNumericLiteral(node.argument)) if (node.argument.value === 0) return {
512
+ type: "text",
513
+ text: "0"
514
+ };
515
+ else return {
516
+ type: "text",
517
+ text: operator + node.argument.value.toString()
518
+ };
519
+ return null;
520
+ }
521
+ return null;
740
522
  }
741
523
  /**
742
- * Resolves a function call by traversing its body and collecting return values
743
- */
524
+ * Resolves a function call by traversing its body and collecting return values
525
+ */
744
526
  function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings, errors) {
745
- if (!calleeBinding) {
746
- return null;
747
- }
748
- const bindingPath = calleeBinding.path;
749
- const branches = [];
750
- // Handle function declarations: function time() { return "day"; }
751
- if (bindingPath.isFunctionDeclaration()) {
752
- bindingPath.traverse({
753
- // Don't skip nested functions - let parseStringExpression handle function calls
754
- ReturnStatement(returnPath) {
755
- // Only process return statements that are direct children of this function
756
- // Skip return statements from nested functions (they'll be handled when those functions are called)
757
- const parentFunction = returnPath.getFunctionParent();
758
- if (parentFunction?.node !== bindingPath.node) {
759
- // This return belongs to a nested function, skip it
760
- return;
761
- }
762
- const returnArg = returnPath.node.argument;
763
- if (!returnArg || !t.isExpression(returnArg)) {
764
- return;
765
- }
766
- const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
767
- if (returnResult !== null) {
768
- branches.push(returnResult);
769
- }
770
- },
771
- });
772
- }
773
- // Handle arrow functions: const time = () => "day"
774
- else if (bindingPath.isVariableDeclarator()) {
775
- const init = bindingPath.get('init');
776
- if (!init.isArrowFunctionExpression()) {
777
- return null;
778
- }
779
- const body = init.get('body');
780
- // Handle expression body: () => "day"
781
- if (body.isExpression()) {
782
- const bodyResult = parseStringExpression(body.node, body, file, parsingOptions, warnings, errors);
783
- if (bodyResult !== null) {
784
- branches.push(bodyResult);
785
- }
786
- }
787
- // Handle block body: () => { return "day"; }
788
- else if (body.isBlockStatement()) {
789
- const arrowFunction = init.node;
790
- body.traverse({
791
- // Don't skip nested functions - let parseStringExpression handle function calls
792
- ReturnStatement(returnPath) {
793
- // Only process return statements that are direct children of this function
794
- // Skip return statements from nested functions (they'll be handled when those functions are called)
795
- const parentFunction = returnPath.getFunctionParent();
796
- if (parentFunction?.node !== arrowFunction) {
797
- // This return belongs to a nested function, skip it
798
- return;
799
- }
800
- const returnArg = returnPath.node.argument;
801
- if (!returnArg || !t.isExpression(returnArg)) {
802
- return;
803
- }
804
- const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
805
- if (returnResult !== null) {
806
- branches.push(returnResult);
807
- }
808
- },
809
- });
810
- }
811
- }
812
- if (branches.length === 0) {
813
- return null;
814
- }
815
- if (branches.length === 1) {
816
- return branches[0];
817
- }
818
- return { type: 'choice', nodes: branches };
527
+ if (!calleeBinding) return null;
528
+ const bindingPath = calleeBinding.path;
529
+ const branches = [];
530
+ if (bindingPath.isFunctionDeclaration()) bindingPath.traverse({ ReturnStatement(returnPath) {
531
+ if (returnPath.getFunctionParent()?.node !== bindingPath.node) return;
532
+ const returnArg = returnPath.node.argument;
533
+ if (!returnArg || !t.isExpression(returnArg)) return;
534
+ const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
535
+ if (returnResult !== null) branches.push(returnResult);
536
+ } });
537
+ else if (bindingPath.isVariableDeclarator()) {
538
+ const init = bindingPath.get("init");
539
+ if (!init.isArrowFunctionExpression()) return null;
540
+ const body = init.get("body");
541
+ if (body.isExpression()) {
542
+ const bodyResult = parseStringExpression(body.node, body, file, parsingOptions, warnings, errors);
543
+ if (bodyResult !== null) branches.push(bodyResult);
544
+ } else if (body.isBlockStatement()) {
545
+ const arrowFunction = init.node;
546
+ body.traverse({ ReturnStatement(returnPath) {
547
+ if (returnPath.getFunctionParent()?.node !== arrowFunction) return;
548
+ const returnArg = returnPath.node.argument;
549
+ if (!returnArg || !t.isExpression(returnArg)) return;
550
+ const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
551
+ if (returnResult !== null) branches.push(returnResult);
552
+ } });
553
+ }
554
+ }
555
+ if (branches.length === 0) return null;
556
+ if (branches.length === 1) return branches[0];
557
+ return {
558
+ type: "choice",
559
+ nodes: branches
560
+ };
819
561
  }
820
562
  /**
821
- * Resolves a function definition in an external file
822
- */
563
+ * Resolves a function definition in an external file
564
+ */
823
565
  function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings, errors) {
824
- // Check cache first
825
- const cacheKey = `${filePath}::${functionName}`;
826
- if (processFunctionCache.has(cacheKey)) {
827
- return processFunctionCache.get(cacheKey) ?? null;
828
- }
829
- let result = null;
830
- try {
831
- const code = fs.readFileSync(filePath, 'utf8');
832
- const ast = parse(code, {
833
- sourceType: 'module',
834
- plugins: ['jsx', 'typescript'],
835
- });
836
- traverse(ast, {
837
- // Handle re-exports: export * from './utils1'
838
- ExportAllDeclaration(path) {
839
- // Only follow re-exports if we haven't found the function yet
840
- if (result !== null)
841
- return;
842
- if (t.isStringLiteral(path.node.source)) {
843
- const reexportPath = path.node.source.value;
844
- const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
845
- if (resolvedPath) {
846
- // Recursively resolve in the re-exported file
847
- const reexportResult = resolveFunctionInFile(resolvedPath, functionName, parsingOptions, warnings, errors);
848
- if (reexportResult) {
849
- result = reexportResult;
850
- }
851
- }
852
- }
853
- },
854
- // Handle named re-exports: export { fn1 } from './utils'
855
- ExportNamedDeclaration(path) {
856
- // Only follow re-exports if we haven't found the function yet
857
- if (result !== null)
858
- return;
859
- // Check if this is a re-export with a source
860
- if (path.node.source && t.isStringLiteral(path.node.source)) {
861
- // Check if any of the exported specifiers match our function name
862
- const hasMatchingExport = path.node.specifiers.some((spec) => {
863
- if (t.isExportSpecifier(spec)) {
864
- const exportedName = t.isIdentifier(spec.exported)
865
- ? spec.exported.name
866
- : spec.exported.value;
867
- return exportedName === functionName;
868
- }
869
- return false;
870
- });
871
- if (hasMatchingExport) {
872
- const reexportPath = path.node.source.value;
873
- const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
874
- if (resolvedPath) {
875
- // Find the original name in case it was renamed
876
- const specifier = path.node.specifiers.find((spec) => {
877
- if (t.isExportSpecifier(spec)) {
878
- const exportedName = t.isIdentifier(spec.exported)
879
- ? spec.exported.name
880
- : spec.exported.value;
881
- return exportedName === functionName;
882
- }
883
- return false;
884
- });
885
- let originalName = functionName;
886
- if (specifier &&
887
- t.isExportSpecifier(specifier) &&
888
- t.isIdentifier(specifier.local)) {
889
- originalName = specifier.local.name;
890
- }
891
- // Recursively resolve in the re-exported file
892
- const reexportResult = resolveFunctionInFile(resolvedPath, originalName, parsingOptions, warnings, errors);
893
- if (reexportResult) {
894
- result = reexportResult;
895
- }
896
- }
897
- }
898
- }
899
- },
900
- // Handle function declarations: function interjection() { ... }
901
- FunctionDeclaration(path) {
902
- if (path.node.id?.name === functionName && result === null) {
903
- const branches = [];
904
- path.traverse({
905
- Function(innerPath) {
906
- // Skip nested functions
907
- innerPath.skip();
908
- },
909
- ReturnStatement(returnPath) {
910
- if (!t.isReturnStatement(returnPath.node)) {
911
- return;
912
- }
913
- const returnArg = returnPath.node.argument;
914
- if (!returnArg || !t.isExpression(returnArg)) {
915
- return;
916
- }
917
- const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
918
- if (returnResult !== null) {
919
- branches.push(returnResult);
920
- }
921
- },
922
- });
923
- if (branches.length === 1) {
924
- result = branches[0];
925
- }
926
- else if (branches.length > 1) {
927
- result = { type: 'choice', nodes: branches };
928
- }
929
- }
930
- },
931
- // Handle variable declarations: const interjection = () => { ... }
932
- VariableDeclarator(path) {
933
- if (t.isIdentifier(path.node.id) &&
934
- path.node.id.name === functionName &&
935
- result === null) {
936
- const init = path.node.init;
937
- if (!init)
938
- return;
939
- // Handle arrow/function expressions
940
- if (t.isArrowFunctionExpression(init) ||
941
- t.isFunctionExpression(init)) {
942
- const initPath = path.get('init');
943
- if (!initPath.isArrowFunctionExpression() &&
944
- !initPath.isFunctionExpression()) {
945
- return;
946
- }
947
- const bodyPath = initPath.get('body');
948
- const branches = [];
949
- // Handle expression body: () => "day"
950
- if (!Array.isArray(bodyPath) && t.isExpression(bodyPath.node)) {
951
- const bodyResult = parseStringExpression(bodyPath.node, bodyPath, filePath, parsingOptions, warnings, errors);
952
- if (bodyResult !== null) {
953
- branches.push(bodyResult);
954
- }
955
- }
956
- // Handle block body: () => { return "day"; }
957
- else if (!Array.isArray(bodyPath) &&
958
- t.isBlockStatement(bodyPath.node)) {
959
- const arrowFunction = initPath.node;
960
- bodyPath.traverse({
961
- Function(innerPath) {
962
- // Skip nested functions
963
- innerPath.skip();
964
- },
965
- ReturnStatement(returnPath) {
966
- // Only process return statements that are direct children of this function
967
- const parentFunction = returnPath.getFunctionParent();
968
- if (parentFunction?.node !== arrowFunction) {
969
- return;
970
- }
971
- if (!t.isReturnStatement(returnPath.node)) {
972
- return;
973
- }
974
- const returnArg = returnPath.node.argument;
975
- if (!returnArg || !t.isExpression(returnArg)) {
976
- return;
977
- }
978
- const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
979
- if (returnResult !== null) {
980
- branches.push(returnResult);
981
- }
982
- },
983
- });
984
- }
985
- if (branches.length === 1) {
986
- result = branches[0];
987
- }
988
- else if (branches.length > 1) {
989
- result = { type: 'choice', nodes: branches };
990
- }
991
- }
992
- // Handle string/numeric/boolean/null constants
993
- else if (t.isStringLiteral(init)) {
994
- result = { type: 'text', text: init.value };
995
- }
996
- else if (t.isNumericLiteral(init)) {
997
- result = { type: 'text', text: String(init.value) };
998
- }
999
- else if (t.isBooleanLiteral(init)) {
1000
- result = { type: 'text', text: String(init.value) };
1001
- }
1002
- // Handle template literals
1003
- else if (t.isTemplateLiteral(init)) {
1004
- const parts = [];
1005
- let failed = false;
1006
- for (let index = 0; index < init.quasis.length; index++) {
1007
- const quasi = init.quasis[index];
1008
- const text = quasi.value.cooked ?? quasi.value.raw ?? '';
1009
- if (text) {
1010
- parts.push({ type: 'text', text });
1011
- }
1012
- const exprNode = init.expressions[index];
1013
- if (exprNode && t.isExpression(exprNode)) {
1014
- const exprResult = parseStringExpression(exprNode, path, filePath, parsingOptions, warnings, errors);
1015
- if (exprResult === null) {
1016
- failed = true;
1017
- break;
1018
- }
1019
- parts.push(exprResult);
1020
- }
1021
- }
1022
- if (!failed) {
1023
- if (parts.length === 0) {
1024
- result = { type: 'text', text: '' };
1025
- }
1026
- else if (parts.length === 1) {
1027
- result = parts[0];
1028
- }
1029
- else {
1030
- result = { type: 'sequence', nodes: parts };
1031
- }
1032
- }
1033
- }
1034
- // Handle object expressions (and `as const` / `satisfies`)
1035
- else if (t.isObjectExpression(init) ||
1036
- t.isObjectExpression(unwrapTypeAnnotation(init))) {
1037
- const objExpr = unwrapTypeAnnotation(init);
1038
- const branches = [];
1039
- for (const prop of objExpr.properties) {
1040
- if (!t.isObjectProperty(prop) || !t.isExpression(prop.value))
1041
- continue;
1042
- const resolved = parseStringExpression(prop.value, path, filePath, parsingOptions, warnings, errors);
1043
- if (resolved)
1044
- branches.push(resolved);
1045
- }
1046
- if (branches.length === 1)
1047
- result = branches[0];
1048
- else if (branches.length > 1)
1049
- result = { type: 'choice', nodes: branches };
1050
- }
1051
- }
1052
- },
1053
- });
1054
- }
1055
- catch (error) {
1056
- // File read or parse error - return null
1057
- warnings.add(warnDeriveFunctionNoResultsSync(filePath, functionName, 'file read/parse error: ' + error));
1058
- result = null;
1059
- }
1060
- // Cache the result
1061
- processFunctionCache.set(cacheKey, result);
1062
- return result;
566
+ const cacheKey = `${filePath}::${functionName}`;
567
+ if (processFunctionCache.has(cacheKey)) return processFunctionCache.get(cacheKey) ?? null;
568
+ let result = null;
569
+ try {
570
+ traverse(parse(fs.readFileSync(filePath, "utf8"), {
571
+ sourceType: "module",
572
+ plugins: ["jsx", "typescript"]
573
+ }), {
574
+ ExportAllDeclaration(path) {
575
+ if (result !== null) return;
576
+ if (t.isStringLiteral(path.node.source)) {
577
+ const reexportPath = path.node.source.value;
578
+ const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
579
+ if (resolvedPath) {
580
+ const reexportResult = resolveFunctionInFile(resolvedPath, functionName, parsingOptions, warnings, errors);
581
+ if (reexportResult) result = reexportResult;
582
+ }
583
+ }
584
+ },
585
+ ExportNamedDeclaration(path) {
586
+ if (result !== null) return;
587
+ if (path.node.source && t.isStringLiteral(path.node.source)) {
588
+ if (path.node.specifiers.some((spec) => {
589
+ if (t.isExportSpecifier(spec)) return (t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value) === functionName;
590
+ return false;
591
+ })) {
592
+ const reexportPath = path.node.source.value;
593
+ const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
594
+ if (resolvedPath) {
595
+ const specifier = path.node.specifiers.find((spec) => {
596
+ if (t.isExportSpecifier(spec)) return (t.isIdentifier(spec.exported) ? spec.exported.name : spec.exported.value) === functionName;
597
+ return false;
598
+ });
599
+ let originalName = functionName;
600
+ if (specifier && t.isExportSpecifier(specifier) && t.isIdentifier(specifier.local)) originalName = specifier.local.name;
601
+ const reexportResult = resolveFunctionInFile(resolvedPath, originalName, parsingOptions, warnings, errors);
602
+ if (reexportResult) result = reexportResult;
603
+ }
604
+ }
605
+ }
606
+ },
607
+ FunctionDeclaration(path) {
608
+ if (path.node.id?.name === functionName && result === null) {
609
+ const branches = [];
610
+ path.traverse({
611
+ Function(innerPath) {
612
+ innerPath.skip();
613
+ },
614
+ ReturnStatement(returnPath) {
615
+ if (!t.isReturnStatement(returnPath.node)) return;
616
+ const returnArg = returnPath.node.argument;
617
+ if (!returnArg || !t.isExpression(returnArg)) return;
618
+ const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
619
+ if (returnResult !== null) branches.push(returnResult);
620
+ }
621
+ });
622
+ if (branches.length === 1) result = branches[0];
623
+ else if (branches.length > 1) result = {
624
+ type: "choice",
625
+ nodes: branches
626
+ };
627
+ }
628
+ },
629
+ VariableDeclarator(path) {
630
+ if (t.isIdentifier(path.node.id) && path.node.id.name === functionName && result === null) {
631
+ const init = path.node.init;
632
+ if (!init) return;
633
+ if (t.isArrowFunctionExpression(init) || t.isFunctionExpression(init)) {
634
+ const initPath = path.get("init");
635
+ if (!initPath.isArrowFunctionExpression() && !initPath.isFunctionExpression()) return;
636
+ const bodyPath = initPath.get("body");
637
+ const branches = [];
638
+ if (!Array.isArray(bodyPath) && t.isExpression(bodyPath.node)) {
639
+ const bodyResult = parseStringExpression(bodyPath.node, bodyPath, filePath, parsingOptions, warnings, errors);
640
+ if (bodyResult !== null) branches.push(bodyResult);
641
+ } else if (!Array.isArray(bodyPath) && t.isBlockStatement(bodyPath.node)) {
642
+ const arrowFunction = initPath.node;
643
+ bodyPath.traverse({
644
+ Function(innerPath) {
645
+ innerPath.skip();
646
+ },
647
+ ReturnStatement(returnPath) {
648
+ if (returnPath.getFunctionParent()?.node !== arrowFunction) return;
649
+ if (!t.isReturnStatement(returnPath.node)) return;
650
+ const returnArg = returnPath.node.argument;
651
+ if (!returnArg || !t.isExpression(returnArg)) return;
652
+ const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
653
+ if (returnResult !== null) branches.push(returnResult);
654
+ }
655
+ });
656
+ }
657
+ if (branches.length === 1) result = branches[0];
658
+ else if (branches.length > 1) result = {
659
+ type: "choice",
660
+ nodes: branches
661
+ };
662
+ } else if (t.isStringLiteral(init)) result = {
663
+ type: "text",
664
+ text: init.value
665
+ };
666
+ else if (t.isNumericLiteral(init)) result = {
667
+ type: "text",
668
+ text: String(init.value)
669
+ };
670
+ else if (t.isBooleanLiteral(init)) result = {
671
+ type: "text",
672
+ text: String(init.value)
673
+ };
674
+ else if (t.isTemplateLiteral(init)) {
675
+ const parts = [];
676
+ let failed = false;
677
+ for (let index = 0; index < init.quasis.length; index++) {
678
+ const quasi = init.quasis[index];
679
+ const text = quasi.value.cooked ?? quasi.value.raw ?? "";
680
+ if (text) parts.push({
681
+ type: "text",
682
+ text
683
+ });
684
+ const exprNode = init.expressions[index];
685
+ if (exprNode && t.isExpression(exprNode)) {
686
+ const exprResult = parseStringExpression(exprNode, path, filePath, parsingOptions, warnings, errors);
687
+ if (exprResult === null) {
688
+ failed = true;
689
+ break;
690
+ }
691
+ parts.push(exprResult);
692
+ }
693
+ }
694
+ if (!failed) if (parts.length === 0) result = {
695
+ type: "text",
696
+ text: ""
697
+ };
698
+ else if (parts.length === 1) result = parts[0];
699
+ else result = {
700
+ type: "sequence",
701
+ nodes: parts
702
+ };
703
+ } else if (t.isObjectExpression(init) || t.isObjectExpression(unwrapTypeAnnotation(init))) {
704
+ const objExpr = unwrapTypeAnnotation(init);
705
+ const branches = [];
706
+ for (const prop of objExpr.properties) {
707
+ if (!t.isObjectProperty(prop) || !t.isExpression(prop.value)) continue;
708
+ const resolved = parseStringExpression(prop.value, path, filePath, parsingOptions, warnings, errors);
709
+ if (resolved) branches.push(resolved);
710
+ }
711
+ if (branches.length === 1) result = branches[0];
712
+ else if (branches.length > 1) result = {
713
+ type: "choice",
714
+ nodes: branches
715
+ };
716
+ }
717
+ }
718
+ }
719
+ });
720
+ } catch (error) {
721
+ warnings.add(warnDeriveFunctionNoResultsSync(filePath, functionName, "file read/parse error: " + error));
722
+ result = null;
723
+ }
724
+ processFunctionCache.set(cacheKey, result);
725
+ return result;
1063
726
  }
1064
727
  /**
1065
- * Converts a Node tree to an array of all possible string combinations
1066
- * This is a helper function for compatibility with existing code
1067
- */
1068
- export function nodeToStrings(node) {
1069
- if (node === null) {
1070
- return [];
1071
- }
1072
- // Handle TextNode
1073
- if (typeof node === 'object' &&
1074
- node !== null &&
1075
- 'type' in node &&
1076
- node.type === 'text') {
1077
- return [node.text];
1078
- }
1079
- // Handle SequenceNode - concatenate all parts
1080
- if (typeof node === 'object' &&
1081
- node !== null &&
1082
- 'type' in node &&
1083
- node.type === 'sequence') {
1084
- const partResults = node.nodes.map((n) => nodeToStrings(n));
1085
- return cartesianProduct(partResults);
1086
- }
1087
- // Handle ChoiceNode - flatten all branches
1088
- if (typeof node === 'object' &&
1089
- node !== null &&
1090
- 'type' in node &&
1091
- node.type === 'choice') {
1092
- const allStrings = [];
1093
- for (const branch of node.nodes) {
1094
- allStrings.push(...nodeToStrings(branch));
1095
- }
1096
- return [...new Set(allStrings)]; // Deduplicate
1097
- }
1098
- return [];
728
+ * Converts a Node tree to an array of all possible string combinations
729
+ * This is a helper function for compatibility with existing code
730
+ */
731
+ function nodeToStrings(node) {
732
+ if (node === null) return [];
733
+ if (typeof node === "object" && node !== null && "type" in node && node.type === "text") return [node.text];
734
+ if (typeof node === "object" && node !== null && "type" in node && node.type === "sequence") return cartesianProduct(node.nodes.map((n) => nodeToStrings(n)));
735
+ if (typeof node === "object" && node !== null && "type" in node && node.type === "choice") {
736
+ const allStrings = [];
737
+ for (const branch of node.nodes) allStrings.push(...nodeToStrings(branch));
738
+ return [...new Set(allStrings)];
739
+ }
740
+ return [];
1099
741
  }
1100
742
  /**
1101
- * Creates cartesian product of string arrays and concatenates them
1102
- * @example cartesianProduct([["Hello "], ["day", "night"]]) → ["Hello day", "Hello night"]
1103
- */
743
+ * Creates cartesian product of string arrays and concatenates them
744
+ * @example cartesianProduct([["Hello "], ["day", "night"]]) → ["Hello day", "Hello night"]
745
+ */
1104
746
  function cartesianProduct(arrays) {
1105
- if (arrays.length === 0) {
1106
- return [];
1107
- }
1108
- if (arrays.length === 1) {
1109
- return arrays[0];
1110
- }
1111
- // Start with first array
1112
- let result = arrays[0];
1113
- // Combine with each subsequent array
1114
- for (let i = 1; i < arrays.length; i++) {
1115
- const newResult = [];
1116
- for (const prev of result) {
1117
- for (const curr of arrays[i]) {
1118
- newResult.push(prev + curr);
1119
- }
1120
- }
1121
- result = newResult;
1122
- }
1123
- return result;
747
+ if (arrays.length === 0) return [];
748
+ if (arrays.length === 1) return arrays[0];
749
+ let result = arrays[0];
750
+ for (let i = 1; i < arrays.length; i++) {
751
+ const newResult = [];
752
+ for (const prev of result) for (const curr of arrays[i]) newResult.push(prev + curr);
753
+ result = newResult;
754
+ }
755
+ return result;
1124
756
  }
757
+ //#endregion
758
+ export { nodeToStrings, parseStringExpression };
759
+
760
+ //# sourceMappingURL=parseString.js.map