@hanzogui/static 8.3.0 → 8.3.2

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 (377) hide show
  1. package/dist/cjs/check-dep-versions.js +438 -0
  2. package/dist/cjs/check-dep-versions.js.map +1 -0
  3. package/dist/cjs/checkDeps.js +343 -0
  4. package/dist/cjs/checkDeps.js.map +1 -0
  5. package/dist/cjs/constants.js +13 -0
  6. package/dist/cjs/constants.js.map +1 -0
  7. package/dist/cjs/exports.js +27 -0
  8. package/dist/cjs/exports.js.map +1 -0
  9. package/dist/cjs/extractor/accessSafe.js +17 -0
  10. package/dist/cjs/extractor/accessSafe.js.map +1 -0
  11. package/dist/cjs/extractor/babelParse.js +27 -0
  12. package/dist/cjs/extractor/babelParse.js.map +1 -0
  13. package/dist/cjs/extractor/buildClassName.js +65 -0
  14. package/dist/cjs/extractor/buildClassName.js.map +1 -0
  15. package/dist/cjs/extractor/bundle.js +257 -0
  16. package/dist/cjs/extractor/bundle.js.map +1 -0
  17. package/dist/cjs/extractor/bundleConfig.js +794 -0
  18. package/dist/cjs/extractor/bundleConfig.js.map +1 -0
  19. package/dist/cjs/extractor/concatClassName.js +101 -0
  20. package/dist/cjs/extractor/concatClassName.js.map +1 -0
  21. package/dist/cjs/extractor/createEvaluator.js +56 -0
  22. package/dist/cjs/extractor/createEvaluator.js.map +1 -0
  23. package/dist/cjs/extractor/createExtractor.js +2285 -0
  24. package/dist/cjs/extractor/createExtractor.js.map +1 -0
  25. package/dist/cjs/extractor/createLogger.js +34 -0
  26. package/dist/cjs/extractor/createLogger.js.map +1 -0
  27. package/dist/cjs/extractor/detectModuleFormat.js +41 -0
  28. package/dist/cjs/extractor/detectModuleFormat.js.map +1 -0
  29. package/dist/cjs/extractor/ensureImportingConcat.js +23 -0
  30. package/dist/cjs/extractor/ensureImportingConcat.js.map +1 -0
  31. package/dist/cjs/extractor/errors.js +7 -0
  32. package/dist/cjs/extractor/errors.js.map +1 -0
  33. package/dist/cjs/extractor/esbuildAliasPlugin.js +43 -0
  34. package/dist/cjs/extractor/esbuildAliasPlugin.js.map +1 -0
  35. package/dist/cjs/extractor/esbuildTsconfigPaths.js +68 -0
  36. package/dist/cjs/extractor/esbuildTsconfigPaths.js.map +1 -0
  37. package/dist/cjs/extractor/evaluateAstNode.js +107 -0
  38. package/dist/cjs/extractor/evaluateAstNode.js.map +1 -0
  39. package/dist/cjs/extractor/extractHelpers.js +183 -0
  40. package/dist/cjs/extractor/extractHelpers.js.map +1 -0
  41. package/dist/cjs/extractor/extractMediaStyle.js +143 -0
  42. package/dist/cjs/extractor/extractMediaStyle.js.map +1 -0
  43. package/dist/cjs/extractor/extractToClassNames.js +541 -0
  44. package/dist/cjs/extractor/extractToClassNames.js.map +1 -0
  45. package/dist/cjs/extractor/extractToNative.js +404 -0
  46. package/dist/cjs/extractor/extractToNative.js.map +1 -0
  47. package/dist/cjs/extractor/extractablePath.js +89 -0
  48. package/dist/cjs/extractor/extractablePath.js.map +1 -0
  49. package/dist/cjs/extractor/findTopmostFunction.js +17 -0
  50. package/dist/cjs/extractor/findTopmostFunction.js.map +1 -0
  51. package/dist/cjs/extractor/generatedUid.js +35 -0
  52. package/dist/cjs/extractor/generatedUid.js.map +1 -0
  53. package/dist/cjs/extractor/getGuiConfigPathFromOptionsConfig.js +21 -0
  54. package/dist/cjs/extractor/getGuiConfigPathFromOptionsConfig.js.map +1 -0
  55. package/dist/cjs/extractor/getPrefixLogs.js +9 -0
  56. package/dist/cjs/extractor/getPrefixLogs.js.map +1 -0
  57. package/dist/cjs/extractor/getPropValueFromAttributes.js +75 -0
  58. package/dist/cjs/extractor/getPropValueFromAttributes.js.map +1 -0
  59. package/dist/cjs/extractor/getSourceModule.js +81 -0
  60. package/dist/cjs/extractor/getSourceModule.js.map +1 -0
  61. package/dist/cjs/extractor/getStaticBindingsForScope.js +212 -0
  62. package/dist/cjs/extractor/getStaticBindingsForScope.js.map +1 -0
  63. package/dist/cjs/extractor/hasTopLevelAwait.js +29 -0
  64. package/dist/cjs/extractor/hasTopLevelAwait.js.map +1 -0
  65. package/dist/cjs/extractor/hoistClassNames.js +47 -0
  66. package/dist/cjs/extractor/hoistClassNames.js.map +1 -0
  67. package/dist/cjs/extractor/literalToAst.js +83 -0
  68. package/dist/cjs/extractor/literalToAst.js.map +1 -0
  69. package/dist/cjs/extractor/loadFile.js +24 -0
  70. package/dist/cjs/extractor/loadFile.js.map +1 -0
  71. package/dist/cjs/extractor/loadGui.js +414 -0
  72. package/dist/cjs/extractor/loadGui.js.map +1 -0
  73. package/dist/cjs/extractor/logLines.js +20 -0
  74. package/dist/cjs/extractor/logLines.js.map +1 -0
  75. package/dist/cjs/extractor/normalizeTernaries.js +60 -0
  76. package/dist/cjs/extractor/normalizeTernaries.js.map +1 -0
  77. package/dist/cjs/extractor/propsToFontFamilyCache.js +20 -0
  78. package/dist/cjs/extractor/propsToFontFamilyCache.js.map +1 -0
  79. package/dist/cjs/extractor/regenerateConfig.js +151 -0
  80. package/dist/cjs/extractor/regenerateConfig.js.map +1 -0
  81. package/dist/cjs/extractor/removeUnusedHooks.js +84 -0
  82. package/dist/cjs/extractor/removeUnusedHooks.js.map +1 -0
  83. package/dist/cjs/extractor/timer.js +30 -0
  84. package/dist/cjs/extractor/timer.js.map +1 -0
  85. package/dist/cjs/extractor/validHTMLAttributes.js +56 -0
  86. package/dist/cjs/extractor/validHTMLAttributes.js.map +1 -0
  87. package/dist/cjs/extractor/watchGuiConfig.js +56 -0
  88. package/dist/cjs/extractor/watchGuiConfig.js.map +1 -0
  89. package/dist/cjs/getPragmaOptions.js +52 -0
  90. package/dist/cjs/getPragmaOptions.js.map +1 -0
  91. package/dist/cjs/helpers/memoize.js +24 -0
  92. package/dist/cjs/helpers/memoize.js.map +1 -0
  93. package/dist/cjs/helpers/nativeEntry.js +87 -0
  94. package/dist/cjs/helpers/nativeEntry.js.map +1 -0
  95. package/dist/cjs/helpers/requireGuiCore.js +25 -0
  96. package/dist/cjs/helpers/requireGuiCore.js.map +1 -0
  97. package/dist/cjs/here.js +8 -0
  98. package/dist/cjs/here.js.map +1 -0
  99. package/dist/cjs/index.js +8 -0
  100. package/dist/cjs/index.js.map +1 -0
  101. package/dist/cjs/package.json +1 -0
  102. package/dist/cjs/registerRequire.js +263 -0
  103. package/dist/cjs/registerRequire.js.map +1 -0
  104. package/dist/cjs/server.js +41 -0
  105. package/dist/cjs/server.js.map +1 -0
  106. package/dist/cjs/setup.js +2 -0
  107. package/dist/cjs/setup.js.map +1 -0
  108. package/dist/cjs/types.js +3 -0
  109. package/dist/cjs/types.js.map +1 -0
  110. package/dist/cjs/worker.js +95 -0
  111. package/dist/cjs/worker.js.map +1 -0
  112. package/dist/esm/check-dep-versions.js +433 -0
  113. package/dist/esm/check-dep-versions.js.map +1 -0
  114. package/dist/esm/checkDeps.js +339 -0
  115. package/dist/esm/checkDeps.js.map +1 -0
  116. package/dist/esm/constants.js +9 -0
  117. package/dist/esm/constants.js.map +1 -0
  118. package/dist/esm/exports.js +18 -0
  119. package/dist/esm/exports.js.map +1 -0
  120. package/dist/esm/extractor/accessSafe.js +13 -0
  121. package/dist/esm/extractor/accessSafe.js.map +1 -0
  122. package/dist/esm/extractor/babelParse.js +22 -0
  123. package/dist/esm/extractor/babelParse.js.map +1 -0
  124. package/dist/esm/extractor/buildClassName.js +59 -0
  125. package/dist/esm/extractor/buildClassName.js.map +1 -0
  126. package/dist/esm/extractor/bundle.js +252 -0
  127. package/dist/esm/extractor/bundle.js.map +1 -0
  128. package/dist/esm/extractor/bundleConfig.js +781 -0
  129. package/dist/esm/extractor/bundleConfig.js.map +1 -0
  130. package/dist/esm/extractor/concatClassName.js +98 -0
  131. package/dist/esm/extractor/concatClassName.js.map +1 -0
  132. package/dist/esm/extractor/createEvaluator.js +51 -0
  133. package/dist/esm/extractor/createEvaluator.js.map +1 -0
  134. package/dist/esm/extractor/createExtractor.js +2281 -0
  135. package/dist/esm/extractor/createExtractor.js.map +1 -0
  136. package/dist/esm/extractor/createLogger.js +31 -0
  137. package/dist/esm/extractor/createLogger.js.map +1 -0
  138. package/dist/esm/extractor/detectModuleFormat.js +37 -0
  139. package/dist/esm/extractor/detectModuleFormat.js.map +1 -0
  140. package/dist/esm/extractor/ensureImportingConcat.js +19 -0
  141. package/dist/esm/extractor/ensureImportingConcat.js.map +1 -0
  142. package/dist/esm/extractor/errors.js +3 -0
  143. package/dist/esm/extractor/errors.js.map +1 -0
  144. package/dist/esm/extractor/esbuildAliasPlugin.js +39 -0
  145. package/dist/esm/extractor/esbuildAliasPlugin.js.map +1 -0
  146. package/dist/esm/extractor/esbuildTsconfigPaths.js +63 -0
  147. package/dist/esm/extractor/esbuildTsconfigPaths.js.map +1 -0
  148. package/dist/esm/extractor/evaluateAstNode.js +103 -0
  149. package/dist/esm/extractor/evaluateAstNode.js.map +1 -0
  150. package/dist/esm/extractor/extractHelpers.js +166 -0
  151. package/dist/esm/extractor/extractHelpers.js.map +1 -0
  152. package/dist/esm/extractor/extractMediaStyle.js +138 -0
  153. package/dist/esm/extractor/extractMediaStyle.js.map +1 -0
  154. package/dist/esm/extractor/extractToClassNames.js +537 -0
  155. package/dist/esm/extractor/extractToClassNames.js.map +1 -0
  156. package/dist/esm/extractor/extractToNative.js +398 -0
  157. package/dist/esm/extractor/extractToNative.js.map +1 -0
  158. package/dist/esm/extractor/extractablePath.js +84 -0
  159. package/dist/esm/extractor/extractablePath.js.map +1 -0
  160. package/dist/esm/extractor/findTopmostFunction.js +14 -0
  161. package/dist/esm/extractor/findTopmostFunction.js.map +1 -0
  162. package/dist/esm/extractor/generatedUid.js +31 -0
  163. package/dist/esm/extractor/generatedUid.js.map +1 -0
  164. package/dist/esm/extractor/getGuiConfigPathFromOptionsConfig.js +18 -0
  165. package/dist/esm/extractor/getGuiConfigPathFromOptionsConfig.js.map +1 -0
  166. package/dist/esm/extractor/getPrefixLogs.js +6 -0
  167. package/dist/esm/extractor/getPrefixLogs.js.map +1 -0
  168. package/dist/esm/extractor/getPropValueFromAttributes.js +71 -0
  169. package/dist/esm/extractor/getPropValueFromAttributes.js.map +1 -0
  170. package/dist/esm/extractor/getSourceModule.js +77 -0
  171. package/dist/esm/extractor/getSourceModule.js.map +1 -0
  172. package/dist/esm/extractor/getStaticBindingsForScope.js +207 -0
  173. package/dist/esm/extractor/getStaticBindingsForScope.js.map +1 -0
  174. package/dist/esm/extractor/hasTopLevelAwait.js +25 -0
  175. package/dist/esm/extractor/hasTopLevelAwait.js.map +1 -0
  176. package/dist/esm/extractor/hoistClassNames.js +43 -0
  177. package/dist/esm/extractor/hoistClassNames.js.map +1 -0
  178. package/dist/esm/extractor/literalToAst.js +78 -0
  179. package/dist/esm/extractor/literalToAst.js.map +1 -0
  180. package/dist/esm/extractor/loadFile.js +22 -0
  181. package/dist/esm/extractor/loadFile.js.map +1 -0
  182. package/dist/esm/extractor/loadGui.js +402 -0
  183. package/dist/esm/extractor/loadGui.js.map +1 -0
  184. package/dist/esm/extractor/logLines.js +16 -0
  185. package/dist/esm/extractor/logLines.js.map +1 -0
  186. package/dist/esm/extractor/normalizeTernaries.js +56 -0
  187. package/dist/esm/extractor/normalizeTernaries.js.map +1 -0
  188. package/dist/esm/extractor/propsToFontFamilyCache.js +15 -0
  189. package/dist/esm/extractor/propsToFontFamilyCache.js.map +1 -0
  190. package/dist/esm/extractor/regenerateConfig.js +145 -0
  191. package/dist/esm/extractor/regenerateConfig.js.map +1 -0
  192. package/dist/esm/extractor/removeUnusedHooks.js +80 -0
  193. package/dist/esm/extractor/removeUnusedHooks.js.map +1 -0
  194. package/dist/esm/extractor/timer.js +26 -0
  195. package/dist/esm/extractor/timer.js.map +1 -0
  196. package/dist/esm/extractor/validHTMLAttributes.js +53 -0
  197. package/dist/esm/extractor/validHTMLAttributes.js.map +1 -0
  198. package/dist/esm/extractor/watchGuiConfig.js +53 -0
  199. package/dist/esm/extractor/watchGuiConfig.js.map +1 -0
  200. package/dist/esm/getPragmaOptions.js +49 -0
  201. package/dist/esm/getPragmaOptions.js.map +1 -0
  202. package/dist/esm/helpers/memoize.js +21 -0
  203. package/dist/esm/helpers/memoize.js.map +1 -0
  204. package/dist/esm/helpers/nativeEntry.js +82 -0
  205. package/dist/esm/helpers/nativeEntry.js.map +1 -0
  206. package/dist/esm/helpers/requireGuiCore.js +22 -0
  207. package/dist/esm/helpers/requireGuiCore.js.map +1 -0
  208. package/dist/esm/here.js +7 -0
  209. package/dist/esm/here.js.map +1 -0
  210. package/dist/esm/index.js +5 -0
  211. package/dist/esm/index.js.map +1 -0
  212. package/dist/esm/registerRequire.js +256 -0
  213. package/dist/esm/registerRequire.js.map +1 -0
  214. package/dist/esm/server.js +37 -0
  215. package/dist/esm/server.js.map +1 -0
  216. package/dist/esm/setup.js +2 -0
  217. package/dist/esm/setup.js.map +1 -0
  218. package/dist/esm/types.js +2 -0
  219. package/dist/esm/types.js.map +1 -0
  220. package/dist/esm/worker.js +92 -0
  221. package/dist/esm/worker.js.map +1 -0
  222. package/package.json +77 -56
  223. package/src/check-dep-versions.ts +2 -1
  224. package/src/checkDeps.ts +1 -1
  225. package/src/exports.ts +17 -17
  226. package/src/extractor/babelParse.ts +2 -11
  227. package/src/extractor/buildClassName.ts +1 -1
  228. package/src/extractor/bundle.ts +13 -9
  229. package/src/extractor/bundleConfig.ts +25 -21
  230. package/src/extractor/createEvaluator.ts +3 -3
  231. package/src/extractor/createExtractor.ts +59 -77
  232. package/src/extractor/createLogger.ts +2 -2
  233. package/src/extractor/esbuildTsconfigPaths.ts +55 -120
  234. package/src/extractor/evaluateAstNode.ts +2 -2
  235. package/src/extractor/extractHelpers.ts +3 -3
  236. package/src/extractor/extractMediaStyle.ts +3 -3
  237. package/src/extractor/extractToClassNames.ts +12 -12
  238. package/src/extractor/extractToNative.ts +20 -22
  239. package/src/extractor/findTopmostFunction.ts +5 -13
  240. package/src/extractor/getGuiConfigPathFromOptionsConfig.ts +1 -1
  241. package/src/extractor/getPrefixLogs.ts +1 -1
  242. package/src/extractor/getPropValueFromAttributes.ts +2 -2
  243. package/src/extractor/getStaticBindingsForScope.ts +6 -6
  244. package/src/extractor/hasTopLevelAwait.ts +1 -1
  245. package/src/extractor/literalToAst.ts +2 -2
  246. package/src/extractor/loadFile.ts +6 -1
  247. package/src/extractor/loadGui.ts +16 -12
  248. package/src/extractor/normalizeTernaries.ts +3 -3
  249. package/src/extractor/regenerateConfig.ts +10 -6
  250. package/src/extractor/watchGuiConfig.ts +7 -3
  251. package/src/helpers/nativeEntry.ts +92 -0
  252. package/src/helpers/requireGuiCore.ts +8 -3
  253. package/src/here.cjs.ts +6 -0
  254. package/src/here.ts +8 -0
  255. package/src/index.ts +2 -2
  256. package/src/registerRequire.ts +30 -14
  257. package/src/server.ts +1 -1
  258. package/src/types.ts +1 -1
  259. package/src/worker.ts +7 -7
  260. package/types/check-dep-versions.d.ts.map +1 -1
  261. package/types/constants.d.ts +1 -1
  262. package/types/constants.d.ts.map +1 -1
  263. package/types/exports.d.ts +17 -17
  264. package/types/exports.d.ts.map +1 -1
  265. package/types/extractor/babelParse.d.ts.map +1 -1
  266. package/types/extractor/buildClassName.d.ts +1 -1
  267. package/types/extractor/buildClassName.d.ts.map +1 -1
  268. package/types/extractor/bundle.d.ts +66 -66
  269. package/types/extractor/bundle.d.ts.map +1 -1
  270. package/types/extractor/bundleConfig.d.ts +2 -2
  271. package/types/extractor/bundleConfig.d.ts.map +1 -1
  272. package/types/extractor/createEvaluator.d.ts +1 -1
  273. package/types/extractor/createEvaluator.d.ts.map +1 -1
  274. package/types/extractor/createExtractor.d.ts +4 -4
  275. package/types/extractor/createExtractor.d.ts.map +1 -1
  276. package/types/extractor/createLogger.d.ts +1 -1
  277. package/types/extractor/createLogger.d.ts.map +1 -1
  278. package/types/extractor/esbuildAliasPlugin.d.ts.map +1 -1
  279. package/types/extractor/esbuildTsconfigPaths.d.ts +4 -9
  280. package/types/extractor/esbuildTsconfigPaths.d.ts.map +1 -1
  281. package/types/extractor/extractHelpers.d.ts +1 -1
  282. package/types/extractor/extractHelpers.d.ts.map +1 -1
  283. package/types/extractor/extractMediaStyle.d.ts +2 -3
  284. package/types/extractor/extractMediaStyle.d.ts.map +1 -1
  285. package/types/extractor/extractToClassNames.d.ts +2 -2
  286. package/types/extractor/extractToClassNames.d.ts.map +1 -1
  287. package/types/extractor/extractToNative.d.ts +4 -4
  288. package/types/extractor/extractToNative.d.ts.map +1 -1
  289. package/types/extractor/findTopmostFunction.d.ts +1 -1
  290. package/types/extractor/findTopmostFunction.d.ts.map +1 -1
  291. package/types/extractor/getGuiConfigPathFromOptionsConfig.d.ts +1 -1
  292. package/types/extractor/getGuiConfigPathFromOptionsConfig.d.ts.map +1 -1
  293. package/types/extractor/getPrefixLogs.d.ts +1 -1
  294. package/types/extractor/getPrefixLogs.d.ts.map +1 -1
  295. package/types/extractor/loadFile.d.ts +1 -0
  296. package/types/extractor/loadGui.d.ts +1 -1
  297. package/types/extractor/loadGui.d.ts.map +1 -1
  298. package/types/extractor/logLines.d.ts.map +1 -1
  299. package/types/extractor/normalizeTernaries.d.ts +1 -1
  300. package/types/extractor/normalizeTernaries.d.ts.map +1 -1
  301. package/types/extractor/regenerateConfig.d.ts +1 -1
  302. package/types/extractor/regenerateConfig.d.ts.map +1 -1
  303. package/types/extractor/timer.d.ts.map +1 -1
  304. package/types/extractor/validHTMLAttributes.d.ts.map +1 -1
  305. package/types/extractor/watchGuiConfig.d.ts.map +1 -1
  306. package/types/getPragmaOptions.d.ts +1 -1
  307. package/types/helpers/memoize.d.ts +1 -1
  308. package/types/helpers/memoize.d.ts.map +1 -1
  309. package/types/helpers/nativeEntry.d.ts +16 -0
  310. package/types/helpers/nativeEntry.d.ts.map +1 -0
  311. package/types/helpers/requireGuiCore.d.ts +1 -1
  312. package/types/helpers/requireGuiCore.d.ts.map +1 -1
  313. package/types/here.d.ts +3 -0
  314. package/types/here.d.ts.map +1 -0
  315. package/types/index.d.ts +2 -2
  316. package/types/index.d.ts.map +1 -1
  317. package/types/registerRequire.d.ts +1 -1
  318. package/types/registerRequire.d.ts.map +1 -1
  319. package/types/server.d.ts +1 -1
  320. package/types/server.d.ts.map +1 -1
  321. package/types/types.d.ts +1 -1
  322. package/types/types.d.ts.map +1 -1
  323. package/types/worker.d.ts +4 -4
  324. package/types/worker.d.ts.map +1 -1
  325. package/dist/check-dep-versions.cjs +0 -372
  326. package/dist/checkDeps.cjs +0 -271
  327. package/dist/constants.cjs +0 -51
  328. package/dist/exports.cjs +0 -49
  329. package/dist/extractor/accessSafe.cjs +0 -48
  330. package/dist/extractor/babelParse.cjs +0 -56
  331. package/dist/extractor/buildClassName.cjs +0 -86
  332. package/dist/extractor/bundle.cjs +0 -234
  333. package/dist/extractor/bundleConfig.cjs +0 -729
  334. package/dist/extractor/concatClassName.cjs +0 -121
  335. package/dist/extractor/createEvaluator.cjs +0 -88
  336. package/dist/extractor/createExtractor.cjs +0 -1935
  337. package/dist/extractor/createLogger.cjs +0 -50
  338. package/dist/extractor/detectModuleFormat.cjs +0 -55
  339. package/dist/extractor/ensureImportingConcat.cjs +0 -54
  340. package/dist/extractor/errors.cjs +0 -28
  341. package/dist/extractor/esbuildAliasPlugin.cjs +0 -56
  342. package/dist/extractor/esbuildTsconfigPaths.cjs +0 -126
  343. package/dist/extractor/evaluateAstNode.cjs +0 -128
  344. package/dist/extractor/extractHelpers.cjs +0 -182
  345. package/dist/extractor/extractMediaStyle.cjs +0 -169
  346. package/dist/extractor/extractToClassNames.cjs +0 -476
  347. package/dist/extractor/extractToNative.cjs +0 -369
  348. package/dist/extractor/extractablePath.cjs +0 -51
  349. package/dist/extractor/findTopmostFunction.cjs +0 -43
  350. package/dist/extractor/generatedUid.cjs +0 -58
  351. package/dist/extractor/getGuiConfigPathFromOptionsConfig.cjs +0 -41
  352. package/dist/extractor/getPrefixLogs.cjs +0 -31
  353. package/dist/extractor/getPropValueFromAttributes.cjs +0 -85
  354. package/dist/extractor/getSourceModule.cjs +0 -100
  355. package/dist/extractor/getStaticBindingsForScope.cjs +0 -213
  356. package/dist/extractor/hasTopLevelAwait.cjs +0 -62
  357. package/dist/extractor/hoistClassNames.cjs +0 -76
  358. package/dist/extractor/literalToAst.cjs +0 -109
  359. package/dist/extractor/loadFile.cjs +0 -17
  360. package/dist/extractor/loadGui.cjs +0 -373
  361. package/dist/extractor/logLines.cjs +0 -43
  362. package/dist/extractor/normalizeTernaries.cjs +0 -95
  363. package/dist/extractor/propsToFontFamilyCache.cjs +0 -42
  364. package/dist/extractor/regenerateConfig.cjs +0 -178
  365. package/dist/extractor/removeUnusedHooks.cjs +0 -108
  366. package/dist/extractor/timer.cjs +0 -52
  367. package/dist/extractor/validHTMLAttributes.cjs +0 -79
  368. package/dist/extractor/watchGuiConfig.cjs +0 -70
  369. package/dist/getPragmaOptions.cjs +0 -73
  370. package/dist/helpers/memoize.cjs +0 -45
  371. package/dist/helpers/requireGuiCore.cjs +0 -40
  372. package/dist/index.cjs +0 -42
  373. package/dist/registerRequire.cjs +0 -209
  374. package/dist/server.cjs +0 -82
  375. package/dist/setup.cjs +0 -0
  376. package/dist/types.cjs +0 -18
  377. package/dist/worker.cjs +0 -111
@@ -0,0 +1,2281 @@
1
+ import traverse from '@babel/traverse';
2
+ import * as t from '@babel/types';
3
+ import { Color, colorLog } from '@hanzogui/cli-color';
4
+ import * as reactNativeWebInternals from '@hanzogui/react-native-web-internals';
5
+ import { StyleObjectIdentifier, StyleObjectRules, } from '@hanzogui/web';
6
+ import { readFileSync } from 'node:fs';
7
+ import { basename, dirname, resolve, relative } from 'node:path';
8
+ import { FAILED_EVAL } from '../constants.js';
9
+ import { requireGuiCore } from '../helpers/requireGuiCore.js';
10
+ import { registerRequire } from '../registerRequire.js';
11
+ import { createEvaluator, createSafeEvaluator } from './createEvaluator.js';
12
+ import { installedPackageOf } from './extractablePath.js';
13
+ import { evaluateAstNode } from './evaluateAstNode.js';
14
+ import { attrStr, findComponentName, getValidComponent, getValidComponentsPaths, getValidImport, isPresent, isValidImport, objToStr, } from './extractHelpers.js';
15
+ import { findTopmostFunction } from './findTopmostFunction.js';
16
+ import { cleanupBeforeExit, getStaticBindingsForScope, } from './getStaticBindingsForScope.js';
17
+ import { literalToAst } from './literalToAst.js';
18
+ import { loadGui, loadGuiSync } from './loadGui.js';
19
+ import { logLines } from './logLines.js';
20
+ import { normalizeTernaries } from './normalizeTernaries.js';
21
+ import { setPropsToFontFamily } from './propsToFontFamilyCache.js';
22
+ import { timer } from './timer.js';
23
+ import { validHTMLAttributes } from './validHTMLAttributes.js';
24
+ import { BailOptimizationError } from './errors.js';
25
+ import { probe, resolveAlias } from './esbuildTsconfigPaths.js';
26
+ // The core of a platform, loaded with the extractor's own require in place so
27
+ // the react-native its native emit asks for is the one this process can run.
28
+ const loadGuiCore = (platform) => {
29
+ const { unregister } = registerRequire(platform);
30
+ try {
31
+ return requireGuiCore(platform);
32
+ }
33
+ finally {
34
+ unregister();
35
+ }
36
+ };
37
+ const UNTOUCHED_PROPS = {
38
+ key: true,
39
+ style: true,
40
+ className: true,
41
+ };
42
+ // Platform variants that can't be resolved at compile time on native builds.
43
+ // Defined at module level (not inside the loop) to avoid repeated Set allocations during compilation.
44
+ // (requires runtime Platform.OS + Platform.isTV checks via react-native-tvos)
45
+ const nativeOnlyPlatforms = new Set(['android', 'ios', 'tv', 'androidtv', 'tvos']);
46
+ const createTernary = (x) => x;
47
+ let hasLoggedBaseInfo = false;
48
+ function isFullyDisabled(props) {
49
+ return props.disableExtraction && props.disableDebugAttr;
50
+ }
51
+ // Walk up JSX ancestors looking for one that declares `group="<groupName>"` together
52
+ // with the `untilMeasured` prop. Used to deopt children whose styles depend on a
53
+ // parent that the runtime measures before emitting child styles (can't be modeled
54
+ // in static CSS).
55
+ function hasUntilMeasuredAncestor(path, groupName) {
56
+ let current = path.parentPath;
57
+ while (current) {
58
+ if (current.isJSXElement()) {
59
+ const opening = current.node.openingElement;
60
+ let foundGroup = false;
61
+ let foundUntilMeasured = false;
62
+ for (const attr of opening.attributes) {
63
+ if (!t.isJSXAttribute(attr))
64
+ continue;
65
+ if (!t.isJSXIdentifier(attr.name))
66
+ continue;
67
+ const aName = attr.name.name;
68
+ if (aName === 'group') {
69
+ // only literal string equality counts — dynamic group= is left to runtime
70
+ if (t.isStringLiteral(attr.value) && attr.value.value === groupName) {
71
+ foundGroup = true;
72
+ }
73
+ else if (t.isJSXExpressionContainer(attr.value) &&
74
+ t.isStringLiteral(attr.value.expression) &&
75
+ attr.value.expression.value === groupName) {
76
+ foundGroup = true;
77
+ }
78
+ }
79
+ else if (aName === 'untilMeasured') {
80
+ foundUntilMeasured = true;
81
+ }
82
+ }
83
+ if (foundGroup && foundUntilMeasured)
84
+ return true;
85
+ }
86
+ current = current.parentPath;
87
+ }
88
+ return false;
89
+ }
90
+ export function createExtractor({ logger = console, platform = 'web' } = { logger: console }) {
91
+ const INLINE_EXTRACTABLE = {
92
+ ref: 'ref',
93
+ key: 'key',
94
+ ...(platform === 'web' && {
95
+ onPress: 'onClick',
96
+ onHoverIn: 'onMouseEnter',
97
+ onHoverOut: 'onMouseLeave',
98
+ onPressIn: 'onMouseDown',
99
+ onPressOut: 'onMouseUp',
100
+ }),
101
+ ...(platform === 'native' && {
102
+ // native view props that should pass through without preventing flattening
103
+ testID: 'testID',
104
+ nativeID: 'nativeID',
105
+ accessibilityLabel: 'accessibilityLabel',
106
+ accessibilityHint: 'accessibilityHint',
107
+ accessibilityRole: 'accessibilityRole',
108
+ accessibilityState: 'accessibilityState',
109
+ accessibilityValue: 'accessibilityValue',
110
+ accessibilityActions: 'accessibilityActions',
111
+ accessibilityLabelledBy: 'accessibilityLabelledBy',
112
+ accessibilityLiveRegion: 'accessibilityLiveRegion',
113
+ accessibilityElementsHidden: 'accessibilityElementsHidden',
114
+ accessibilityViewIsModal: 'accessibilityViewIsModal',
115
+ importantForAccessibility: 'importantForAccessibility',
116
+ collapsable: 'collapsable',
117
+ needsOffscreenAlphaCompositing: 'needsOffscreenAlphaCompositing',
118
+ removeClippedSubviews: 'removeClippedSubviews',
119
+ renderToHardwareTextureAndroid: 'renderToHardwareTextureAndroid',
120
+ shouldRasterizeIOS: 'shouldRasterizeIOS',
121
+ hitSlop: 'hitSlop',
122
+ pointerEvents: 'pointerEvents',
123
+ }),
124
+ };
125
+ const componentState = {
126
+ focus: false,
127
+ focusVisible: false,
128
+ focusWithin: false,
129
+ hover: false,
130
+ unmounted: true,
131
+ press: false,
132
+ pressIn: false,
133
+ disabled: false,
134
+ };
135
+ const styleProps = {
136
+ resolveValues: platform === 'native' ? 'value' : 'variable',
137
+ noClass: false,
138
+ isAnimated: false,
139
+ };
140
+ const shouldAddDebugProp =
141
+ // really basic disable this for next.js because it messes with ssr
142
+ !process.env.npm_package_dependencies_next &&
143
+ platform !== 'native' &&
144
+ process.env.IDENTIFY_TAGS !== 'false' &&
145
+ (process.env.NODE_ENV === 'development' || process.env.IDENTIFY_TAGS);
146
+ let projectInfo = null;
147
+ // cache of dynamically discovered styled components, keyed by absolute file path
148
+ // persists across files within the same worker/extractor instance
149
+ const dynamicComponentCache = new Map();
150
+ const dynamicLoadingInProgress = new Set();
151
+ function resolveImportPath(fromFile, importPath) {
152
+ const dir = dirname(fromFile);
153
+ if (importPath.startsWith('.')) {
154
+ return probe(resolve(dir, importPath));
155
+ }
156
+ // tsconfig path alias (e.g. ~/foo, @/bar) into project source, never into node_modules
157
+ const file = resolveAlias(importPath, dir);
158
+ return file && !file.includes('node_modules') ? file : null;
159
+ }
160
+ const styledCheckCache = new Map();
161
+ function mightHaveStyledComponents(filePath) {
162
+ const cached = styledCheckCache.get(filePath);
163
+ if (cached !== undefined)
164
+ return cached;
165
+ try {
166
+ const content = readFileSync(filePath, 'utf-8');
167
+ const result = content.includes('styled(');
168
+ styledCheckCache.set(filePath, result);
169
+ return result;
170
+ }
171
+ catch {
172
+ styledCheckCache.set(filePath, false);
173
+ return false;
174
+ }
175
+ }
176
+ // we load hanzogui delayed because we need to set some global/env stuff before importing
177
+ // otherwise we'd import `rnw` and cause it to evaluate react-native-web which causes errors
178
+ function loadSync(props) {
179
+ if (isFullyDisabled(props)) {
180
+ return null;
181
+ }
182
+ return (projectInfo || (projectInfo = loadGuiSync(props)));
183
+ }
184
+ async function load(props) {
185
+ if (isFullyDisabled(props)) {
186
+ return null;
187
+ }
188
+ return (projectInfo || (projectInfo = await loadGui(props)));
189
+ }
190
+ return {
191
+ options: {
192
+ logger,
193
+ },
194
+ cleanupBeforeExit,
195
+ loadGui: load,
196
+ loadGuiSync: loadSync,
197
+ getGui() {
198
+ return projectInfo?.hanzoguiConfig;
199
+ },
200
+ parseSync: (f, props) => {
201
+ globalThis.expo || (globalThis.expo = {}); // expo-modules-core checks this and avoids loading "native" modules if exists
202
+ const projectInfo = loadSync(props);
203
+ return parseWithConfig(projectInfo || {}, f, props);
204
+ },
205
+ parse: async (f, props) => {
206
+ globalThis.expo || (globalThis.expo = {}); // expo-modules-core checks this and avoids loading "native" modules if exists
207
+ const projectInfo = await load(props);
208
+ return parseWithConfig(projectInfo || {}, f, props);
209
+ },
210
+ };
211
+ function parseWithConfig({ components, hanzoguiConfig }, fileOrPath, options) {
212
+ const { config = 'hanzogui.config.ts', importsWhitelist = ['constants.js'], evaluateVars = true, sourcePath = '', onExtractTag, onStyledDefinitionRule, getFlattenedNode, disable, disableExtraction, disableExtractVariables, disableDebugAttr, enableDynamicEvaluation = false, includeExtensions = ['.ts', '.tsx', '.jsx'], extractStyledDefinitions = false, prefixLogs, excludeProps, platform, ...restProps } = options;
213
+ // invalidate dynamic cache for this file on re-parse (HMR)
214
+ if (sourcePath && dynamicComponentCache.has(sourcePath)) {
215
+ dynamicComponentCache.delete(sourcePath);
216
+ styledCheckCache.delete(sourcePath);
217
+ }
218
+ if (sourcePath.includes('.hanzogui-dynamic-eval')) {
219
+ return null;
220
+ }
221
+ const { normalizeStyle, getSplitStyles, mediaQueryConfig, propMapper, proxyThemeVariables, getDefaultProps, pseudoDescriptors, } = loadGuiCore(platform);
222
+ let shouldPrintDebug = options.shouldPrintDebug || false;
223
+ if (disable === true || (Array.isArray(disable) && disable.includes(sourcePath))) {
224
+ return null;
225
+ }
226
+ if (!isFullyDisabled(options)) {
227
+ if (!components) {
228
+ throw new Error(`Must provide components`);
229
+ }
230
+ }
231
+ // includeExtensions describes the app's OWN source, where the author picks
232
+ // the extension. An installed package ships whatever its build emits —
233
+ // .mjs, .js — and it already passed the package allowlist to get here, so
234
+ // holding it to ['.ts', '.tsx', '.jsx'] rejected every design-system file
235
+ // the allowlist had just admitted.
236
+ if (sourcePath &&
237
+ includeExtensions &&
238
+ !installedPackageOf(sourcePath) &&
239
+ !includeExtensions.some((ext) => sourcePath.endsWith(ext))) {
240
+ if (shouldPrintDebug) {
241
+ logger.info(`Ignoring file due to includeExtensions: ${sourcePath}, includeExtensions: ${includeExtensions.join(', ')}`);
242
+ }
243
+ return null;
244
+ }
245
+ function isValidStyleKey(name, staticConfig) {
246
+ if (!projectInfo) {
247
+ throw new Error(`Gui extractor not loaded yet`);
248
+ }
249
+ if (platform === 'native' && name[0] === '$' && mediaQueryConfig[name.slice(1)]) {
250
+ return false;
251
+ }
252
+ // Check for $theme-, $platform-, $group- prefixed keys
253
+ if (name[0] === '$') {
254
+ const mediaName = name.slice(1);
255
+ if (mediaName.startsWith('theme-') ||
256
+ mediaName.startsWith('platform-') ||
257
+ mediaName.startsWith('group-')) {
258
+ return true;
259
+ }
260
+ if (mediaQueryConfig[mediaName]) {
261
+ return true;
262
+ }
263
+ }
264
+ return !!(staticConfig.validStyles?.[name] ||
265
+ pseudoDescriptors[name] ||
266
+ // don't disable variants or else you lose many things flattening
267
+ staticConfig.variants?.[name] ||
268
+ projectInfo?.hanzoguiConfig?.shorthands[name]);
269
+ }
270
+ function getGroupPseudo(name) {
271
+ const [_, groupName, a, b, c] = name.split('-');
272
+ if (!groupName)
273
+ return;
274
+ const m2 = a && b ? `${a}-${b}` : '';
275
+ const media = (m2 && mediaQueryConfig[m2] && m2) || (a && mediaQueryConfig[a] && a);
276
+ return media
277
+ ? media === m2
278
+ ? c
279
+ : b
280
+ ? `${b}${c ? `-${c}` : ''}`
281
+ : undefined
282
+ : a
283
+ ? `${a}${b ? `-${b}` : ''}${c ? `-${c}` : ''}`
284
+ : undefined;
285
+ }
286
+ /**
287
+ * Step 1: Determine if importing any statically extractable components
288
+ */
289
+ const isTargetingHTML = platform === 'web';
290
+ const ogDebug = shouldPrintDebug;
291
+ const tm = timer();
292
+ const propsWithFileInfo = {
293
+ ...options,
294
+ sourcePath,
295
+ allLoadedComponents: components ? [...components] : [],
296
+ };
297
+ if (!hasLoggedBaseInfo) {
298
+ hasLoggedBaseInfo = true;
299
+ if (shouldPrintDebug) {
300
+ logger.info([
301
+ 'loaded components:',
302
+ propsWithFileInfo.allLoadedComponents
303
+ .map((comp) => Object.keys(comp.nameToInfo).join(', '))
304
+ .join(', '),
305
+ ].join(' '));
306
+ }
307
+ if (process.env.DEBUG?.startsWith('hanzogui')) {
308
+ logger.info([
309
+ 'loaded:',
310
+ propsWithFileInfo.allLoadedComponents.map((x) => x.moduleName),
311
+ ].join('\n'));
312
+ }
313
+ }
314
+ tm.mark('load-hanzogui', !!shouldPrintDebug);
315
+ if (!isFullyDisabled(options)) {
316
+ if (!hanzoguiConfig?.themes) {
317
+ console.error(`⛔️ Error: Missing "themes" in your hanzogui.config file:
318
+
319
+ You may not need the compiler! Remember you can run Gui with no configuration at all.
320
+
321
+ You may have not "export default" your config (you can also "export const config").
322
+
323
+ Or this may be due to duplicated dependency versions:
324
+ - try out https://github.com/bmish/check-dependency-version-consistency to see if there are mis-matches.
325
+ - or search your lockfile for mis-matches.
326
+ `);
327
+ console.info(` Got config:`, hanzoguiConfig);
328
+ process.exit(0);
329
+ }
330
+ }
331
+ const firstThemeName = Object.keys(hanzoguiConfig?.themes || {})[0];
332
+ const firstTheme = hanzoguiConfig?.themes[firstThemeName] || {};
333
+ if (!firstTheme || typeof firstTheme !== 'object') {
334
+ const err = `Missing theme ${firstThemeName}, an error occurred when importing your config`;
335
+ console.info(err, `Got config:`, hanzoguiConfig);
336
+ console.info(`Looking for theme:`, firstThemeName);
337
+ throw new Error(err);
338
+ }
339
+ const proxiedTheme = proxyThemeVariables(firstTheme);
340
+ const themeAccessListeners = new Set();
341
+ const defaultTheme = new Proxy(proxiedTheme, {
342
+ get(target, key) {
343
+ if (Reflect.has(target, key)) {
344
+ themeAccessListeners.forEach((cb) => cb(String(key)));
345
+ }
346
+ return Reflect.get(target, key);
347
+ },
348
+ });
349
+ const body = fileOrPath.type === 'Program' ? fileOrPath.get('body') : fileOrPath.program.body;
350
+ if (!isFullyDisabled(options)) {
351
+ if (Object.keys(components || []).length === 0) {
352
+ console.warn(`Warning: Gui didn't find any valid components (DEBUG=hanzogui for more)`);
353
+ if (process.env.DEBUG === 'hanzogui') {
354
+ console.info(`components`, Object.keys(components || []), components);
355
+ }
356
+ }
357
+ }
358
+ if (shouldPrintDebug === 'verbose') {
359
+ logger.info(`allLoadedComponent modules ${propsWithFileInfo.allLoadedComponents
360
+ .map((k) => k.moduleName)
361
+ .join(', ')}`);
362
+ logger.info(`valid import paths: ${JSON.stringify(getValidComponentsPaths(propsWithFileInfo))}`);
363
+ }
364
+ let doesUseValidImport = false;
365
+ let hasImportedTheme = false;
366
+ const importDeclarations = [];
367
+ for (const bodyPath of body) {
368
+ if (bodyPath.type !== 'ImportDeclaration')
369
+ continue;
370
+ const node = ('node' in bodyPath ? bodyPath.node : bodyPath);
371
+ const moduleName = node.source.value;
372
+ // if importing valid module
373
+ const valid = isValidImport(propsWithFileInfo, moduleName);
374
+ if (valid) {
375
+ importDeclarations.push(node);
376
+ }
377
+ if (shouldPrintDebug === 'verbose') {
378
+ logger.info(` - import via ${moduleName} ${valid}`);
379
+ }
380
+ if (extractStyledDefinitions && enableDynamicEvaluation) {
381
+ // check all imports for `styled`, not just valid packages
382
+ // styled( is basically guaranteed to be hanzogui regardless of source
383
+ if (node.specifiers.some((specifier) => specifier.local.name === 'styled')) {
384
+ doesUseValidImport = true;
385
+ // don't break - need to collect all import declarations for the styled() handler
386
+ }
387
+ }
388
+ if (valid) {
389
+ const names = node.specifiers.map((specifier) => specifier.local.name);
390
+ const isValidComponent = names.some((name) => Boolean(isValidImport(propsWithFileInfo, moduleName, name)));
391
+ if (shouldPrintDebug === 'verbose') {
392
+ logger.info(` - import ${isValidComponent ? '✅' : '⇣'} - ${names.join(', ')} via package '${moduleName}' - (valid: ${JSON.stringify(getValidComponentsPaths(propsWithFileInfo))})`);
393
+ }
394
+ if (isValidComponent) {
395
+ doesUseValidImport = true;
396
+ if (!(extractStyledDefinitions && enableDynamicEvaluation))
397
+ break;
398
+ }
399
+ }
400
+ }
401
+ if (shouldPrintDebug) {
402
+ logger.info(`${JSON.stringify({ doesUseValidImport, hasImportedTheme }, null, 2)}\n`);
403
+ }
404
+ if (!doesUseValidImport &&
405
+ extractStyledDefinitions &&
406
+ enableDynamicEvaluation &&
407
+ sourcePath) {
408
+ // check if any local import is in the dynamic cache or has styled components
409
+ for (const bodyPath of body) {
410
+ if (bodyPath.type !== 'ImportDeclaration')
411
+ continue;
412
+ const node = ('node' in bodyPath ? bodyPath.node : bodyPath);
413
+ const moduleName = node.source.value;
414
+ const resolved = resolveImportPath(sourcePath, moduleName);
415
+ if (!resolved)
416
+ continue;
417
+ if (dynamicComponentCache.has(resolved)) {
418
+ doesUseValidImport = true;
419
+ break;
420
+ }
421
+ if (mightHaveStyledComponents(resolved)) {
422
+ doesUseValidImport = true;
423
+ break;
424
+ }
425
+ }
426
+ }
427
+ if (!doesUseValidImport) {
428
+ return null;
429
+ }
430
+ function getValidImportedComponent(componentName) {
431
+ const importDeclaration = importDeclarations.find((dec) => dec.specifiers.some((spec) => spec.local.name === componentName));
432
+ if (!importDeclaration) {
433
+ return null;
434
+ }
435
+ return getValidImport(propsWithFileInfo, importDeclaration.source.value, componentName);
436
+ }
437
+ tm.mark('import-check', !!shouldPrintDebug);
438
+ let couldntParse = false;
439
+ const modifiedComponents = new Set();
440
+ // only keeping a cache around per-file, reset it if it changes
441
+ const bindingCache = {};
442
+ const callTraverse = (a) => {
443
+ return fileOrPath.type === 'File' ? traverse(fileOrPath, a) : fileOrPath.traverse(a);
444
+ };
445
+ const shouldDisableExtraction = disableExtraction === true ||
446
+ (Array.isArray(disableExtraction) && disableExtraction.includes(sourcePath));
447
+ /**
448
+ * Step 2: Statically extract from JSX < /> nodes
449
+ */
450
+ let programPath = null;
451
+ const res = {
452
+ styled: 0,
453
+ flattened: 0,
454
+ optimized: 0,
455
+ modified: 0,
456
+ found: 0,
457
+ };
458
+ const version = `${Math.random()}`;
459
+ callTraverse({
460
+ Program: {
461
+ enter(path) {
462
+ programPath = path;
463
+ },
464
+ },
465
+ // styled() calls
466
+ CallExpression(path) {
467
+ if (disable || shouldDisableExtraction || extractStyledDefinitions === false) {
468
+ return;
469
+ }
470
+ if (!t.isIdentifier(path.node.callee) || path.node.callee.name !== 'styled') {
471
+ return;
472
+ }
473
+ const variableName = t.isVariableDeclarator(path.parent) && t.isIdentifier(path.parent.id)
474
+ ? path.parent.id.name
475
+ : 'unknown';
476
+ if (shouldPrintDebug) {
477
+ logger.info(` [styled] Found styled(${variableName})`);
478
+ }
479
+ const parentNode = path.node.arguments[0];
480
+ if (!t.isIdentifier(parentNode)) {
481
+ return;
482
+ }
483
+ const parentName = parentNode.name;
484
+ const definition = path.node.arguments[1];
485
+ if (!parentName || !definition || !t.isObjectExpression(definition)) {
486
+ return;
487
+ }
488
+ // look up by parent first (e.g. View in `styled(View, {...})`), then by self
489
+ let Component = getValidImportedComponent(parentName) || getValidImportedComponent(variableName);
490
+ if (!Component) {
491
+ if (!enableDynamicEvaluation) {
492
+ return;
493
+ }
494
+ try {
495
+ if (shouldPrintDebug) {
496
+ logger.info(`Unknown component: ${variableName} = styled(${parentName}) attempting dynamic load: ${sourcePath}`);
497
+ }
498
+ const out = loadGuiSync({
499
+ forceExports: true,
500
+ components: [sourcePath],
501
+ cacheKey: version,
502
+ });
503
+ if (!out?.components) {
504
+ if (shouldPrintDebug) {
505
+ logger.info(`Couldn't load, got ${out}`);
506
+ }
507
+ return;
508
+ }
509
+ propsWithFileInfo.allLoadedComponents = [
510
+ ...propsWithFileInfo.allLoadedComponents,
511
+ ...out.components,
512
+ ];
513
+ Component = out.components.flatMap((x) => x.nameToInfo[variableName] ?? [])[0];
514
+ if (!out.cached) {
515
+ const foundNames = out.components
516
+ ?.map((x) => Object.keys(x.nameToInfo).join(', '))
517
+ .join(', ')
518
+ .trim();
519
+ if (foundNames) {
520
+ colorLog(Color.FgYellow, ` | Gui found dynamic components: ${foundNames}`);
521
+ }
522
+ }
523
+ }
524
+ catch (err) {
525
+ if (shouldPrintDebug) {
526
+ logger.info(`skip optimize styled(${variableName}), unable to pre-process (DEBUG=hanzogui for more)`);
527
+ }
528
+ }
529
+ }
530
+ if (!Component) {
531
+ if (shouldPrintDebug) {
532
+ logger.info(` No component found`);
533
+ }
534
+ /**
535
+ * We could/should still extract CSS just limited to validStyleProps
536
+ */
537
+ return;
538
+ }
539
+ const componentSkipProps = new Set([
540
+ ...(Component.staticConfig.inlineWhenUnflattened || []),
541
+ ...(Component.staticConfig.inlineProps || []),
542
+ // for now skip variants, will return to them
543
+ 'variants',
544
+ 'defaultVariants',
545
+ // skip fontFamily its basically a "variant", important for theme use to be value always
546
+ 'fontFamily',
547
+ 'name',
548
+ 'focusStyle',
549
+ 'focusVisibleStyle',
550
+ 'focusWithinStyle',
551
+ 'disabledStyle',
552
+ 'hoverStyle',
553
+ 'pressStyle',
554
+ ]);
555
+ // for now dont parse variants, spreads, etc
556
+ const skipped = new Set();
557
+ const styles = {};
558
+ const staticDefaultProps = {};
559
+ // Generate scope object at this level
560
+ const staticNamespace = getStaticBindingsForScope(path.scope, importsWhitelist, sourcePath, bindingCache, shouldPrintDebug);
561
+ const attemptEval = !evaluateVars
562
+ ? evaluateAstNode
563
+ : createEvaluator({
564
+ props: propsWithFileInfo,
565
+ staticNamespace,
566
+ sourcePath,
567
+ shouldPrintDebug,
568
+ });
569
+ const attemptEvalSafe = createSafeEvaluator(attemptEval);
570
+ for (const property of definition.properties) {
571
+ if (t.isObjectProperty(property) &&
572
+ (t.isIdentifier(property.key) || t.isStringLiteral(property.key))) {
573
+ const key = t.isIdentifier(property.key)
574
+ ? property.key.name
575
+ : property.key.value;
576
+ const defaultPropValue = attemptEvalSafe(property.value);
577
+ if (defaultPropValue !== FAILED_EVAL) {
578
+ staticDefaultProps[key] = defaultPropValue;
579
+ }
580
+ }
581
+ if (!t.isObjectProperty(property) ||
582
+ !t.isIdentifier(property.key) ||
583
+ !isValidStyleKey(property.key.name, Component.staticConfig) ||
584
+ // TODO make pseudos and variants work
585
+ // skip pseudos
586
+ pseudoDescriptors[property.key.name] ||
587
+ // skip variants
588
+ Component.staticConfig.variants?.[property.key.name] ||
589
+ componentSkipProps.has(property.key.name)) {
590
+ skipped.add(property);
591
+ continue;
592
+ }
593
+ // attempt eval
594
+ const out = attemptEvalSafe(property.value);
595
+ if (out === FAILED_EVAL) {
596
+ skipped.add(property);
597
+ }
598
+ else {
599
+ styles[property.key.name] = out;
600
+ }
601
+ }
602
+ const out = getSplitStyles(styles, Component.staticConfig, defaultTheme, '', componentState, styleProps, undefined, undefined, undefined, undefined, false, shouldPrintDebug);
603
+ const classNames = {
604
+ ...out.classNames,
605
+ };
606
+ // // add in the style object as classnames
607
+ // const atomics = getPropsAtomic(out.style)
608
+ // for (const atomic of atomics) {
609
+ // out.rulesToInsert = out.rulesToInsert || []
610
+ // out.rulesToInsert.push(atomic)
611
+ // classNames[atomic.property] = atomic.identifier
612
+ // }
613
+ if (shouldPrintDebug) {
614
+ logger.info([
615
+ `Extracted styled(${variableName})\n`,
616
+ JSON.stringify(styles, null, 2),
617
+ '\n classNames:',
618
+ JSON.stringify(classNames, null, 2),
619
+ '\n rulesToInsert:',
620
+ out.rulesToInsert,
621
+ ].join(' '));
622
+ }
623
+ // don't replace definition values with class name strings -
624
+ // the runtime needs real values for animations, context, and group styles.
625
+ // we only emit the CSS rules so they're available if the runtime uses classNames.
626
+ if (out.rulesToInsert) {
627
+ for (const key in out.rulesToInsert) {
628
+ const styleObject = out.rulesToInsert[key];
629
+ onStyledDefinitionRule?.(styleObject[StyleObjectIdentifier], styleObject[StyleObjectRules]);
630
+ }
631
+ }
632
+ res.styled++;
633
+ // register so JSX handler can find this component (same-file and cross-file)
634
+ if (extractStyledDefinitions && enableDynamicEvaluation && Component) {
635
+ const dynamicStaticConfig = {
636
+ ...Component.staticConfig,
637
+ defaultProps: {
638
+ ...Component.staticConfig.defaultProps,
639
+ ...staticDefaultProps,
640
+ },
641
+ };
642
+ // add to allLoadedComponents with '' so getValidComponent matches when moduleName is ''
643
+ // (same-file styled components have '' as moduleName in JSX handler)
644
+ propsWithFileInfo.allLoadedComponents.push({
645
+ moduleName: '',
646
+ nameToInfo: { [variableName]: { staticConfig: dynamicStaticConfig } },
647
+ });
648
+ // also cache by file path so other files importing from this path can find it
649
+ if (sourcePath) {
650
+ let existing = dynamicComponentCache.get(sourcePath);
651
+ if (!existing) {
652
+ existing = { moduleName: sourcePath, nameToInfo: {} };
653
+ dynamicComponentCache.set(sourcePath, existing);
654
+ }
655
+ existing.nameToInfo[variableName] = { staticConfig: dynamicStaticConfig };
656
+ }
657
+ }
658
+ if (shouldPrintDebug) {
659
+ logger.info(`Extracted styled(${variableName})`);
660
+ }
661
+ },
662
+ JSXElement(traversePath) {
663
+ tm.mark('jsx-element', !!shouldPrintDebug);
664
+ const node = traversePath.node.openingElement;
665
+ const ogAttributes = node.attributes.map((attr) => ({ ...attr }));
666
+ const componentName = findComponentName(traversePath.scope);
667
+ const closingElement = traversePath.node.closingElement;
668
+ // skip non-identifier opening elements (member expressions, etc.)
669
+ if ((closingElement && t.isJSXMemberExpression(closingElement?.name)) ||
670
+ !t.isJSXIdentifier(node.name)) {
671
+ if (shouldPrintDebug) {
672
+ logger.info(` skip non-identifier element`);
673
+ }
674
+ return;
675
+ }
676
+ // validate its a proper import from hanzogui (or internally inside hanzogui)
677
+ const binding = traversePath.scope.getBinding(node.name.name);
678
+ let moduleName = '';
679
+ let dynamicComponent = null;
680
+ if (binding) {
681
+ if (t.isImportDeclaration(binding.path.parent)) {
682
+ moduleName = binding.path.parent.source.value;
683
+ if (!isValidImport(propsWithFileInfo, moduleName, binding.identifier.name)) {
684
+ // fallback: try dynamic component cache for local imports (relative or tsconfig alias)
685
+ if (enableDynamicEvaluation && sourcePath) {
686
+ const resolved = resolveImportPath(sourcePath, moduleName);
687
+ if (resolved) {
688
+ // check cache first
689
+ const cached = dynamicComponentCache.get(resolved);
690
+ if (cached?.nameToInfo[binding.identifier.name]) {
691
+ dynamicComponent = cached.nameToInfo[binding.identifier.name];
692
+ }
693
+ else if (!dynamicLoadingInProgress.has(resolved) &&
694
+ mightHaveStyledComponents(resolved)) {
695
+ // proactively load the file
696
+ dynamicLoadingInProgress.add(resolved);
697
+ try {
698
+ const out = loadGuiSync({
699
+ forceExports: true,
700
+ components: [resolved],
701
+ });
702
+ if (out?.components) {
703
+ for (const comp of out.components) {
704
+ // merge into cache
705
+ let existing = dynamicComponentCache.get(resolved);
706
+ if (!existing) {
707
+ existing = { moduleName: resolved, nameToInfo: {} };
708
+ dynamicComponentCache.set(resolved, existing);
709
+ }
710
+ Object.assign(existing.nameToInfo, comp.nameToInfo);
711
+ // also add to allLoadedComponents so getValidComponent works
712
+ propsWithFileInfo.allLoadedComponents.push({
713
+ moduleName: resolved,
714
+ nameToInfo: comp.nameToInfo,
715
+ });
716
+ }
717
+ const cachedNow = dynamicComponentCache.get(resolved);
718
+ if (cachedNow?.nameToInfo[binding.identifier.name]) {
719
+ dynamicComponent = cachedNow.nameToInfo[binding.identifier.name];
720
+ }
721
+ }
722
+ }
723
+ catch (err) {
724
+ if (shouldPrintDebug) {
725
+ logger.info(` - Failed to dynamically load ${resolved}: ${err}`);
726
+ }
727
+ }
728
+ finally {
729
+ dynamicLoadingInProgress.delete(resolved);
730
+ }
731
+ }
732
+ }
733
+ }
734
+ if (!dynamicComponent) {
735
+ if (shouldPrintDebug) {
736
+ logger.info(` - Binding in component ${componentName} not valid import: "${binding.identifier.name}" isn't in ${moduleName}\n`);
737
+ }
738
+ return;
739
+ }
740
+ }
741
+ }
742
+ }
743
+ const component = dynamicComponent ||
744
+ getValidComponent(propsWithFileInfo, moduleName, node.name.name);
745
+ if (!component || !component.staticConfig) {
746
+ if (shouldPrintDebug) {
747
+ logger.info(`\n - No Gui conf for: ${node.name.name}\n`);
748
+ }
749
+ return;
750
+ }
751
+ const originalNodeName = node.name.name;
752
+ // found a valid tag
753
+ res.found++;
754
+ const filePath = `./${relative(process.cwd(), sourcePath)}`;
755
+ const lineNumbers = node.loc
756
+ ? node.loc.start.line +
757
+ (node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
758
+ : '';
759
+ const codePosition = `${filePath}:${lineNumbers}`;
760
+ // debug just one
761
+ const debugPropValue = node.attributes
762
+ .filter((n) => t.isJSXAttribute(n) && t.isJSXIdentifier(n.name) && n.name.name === 'debug')
763
+ // @ts-ignore
764
+ .map((n) => {
765
+ if (n.value === null)
766
+ return true;
767
+ if (t.isStringLiteral(n.value))
768
+ return n.value.value;
769
+ return false;
770
+ })[0];
771
+ if (debugPropValue) {
772
+ shouldPrintDebug = debugPropValue;
773
+ }
774
+ if (shouldPrintDebug) {
775
+ logger.info(`\x1b[33m\x1b[0m ` + `${componentName} | ${codePosition} -------------------`);
776
+ // prettier-ignore
777
+ logger.info([
778
+ '\x1b[1m',
779
+ '\x1b[32m',
780
+ `<${originalNodeName} />`,
781
+ disableDebugAttr ? '' : '🐛',
782
+ ].join(' '));
783
+ }
784
+ // add data-* debug attributes
785
+ if (platform !== 'native') {
786
+ if (shouldAddDebugProp && !disableDebugAttr) {
787
+ res.modified++;
788
+ node.attributes.unshift(t.jsxAttribute(t.jsxIdentifier('data-is'), t.stringLiteral(node.name.name)));
789
+ if (componentName) {
790
+ node.attributes.unshift(t.jsxAttribute(t.jsxIdentifier('data-in'), t.stringLiteral(componentName)));
791
+ }
792
+ node.attributes.unshift(t.jsxAttribute(t.jsxIdentifier('data-at'), t.stringLiteral(`${basename(filePath)}:${lineNumbers}`)));
793
+ }
794
+ }
795
+ if (shouldDisableExtraction) {
796
+ if (shouldPrintDebug === 'verbose') {
797
+ logger.info(` ❌ Extraction disabled: ${JSON.stringify(disableExtraction)}\n`);
798
+ }
799
+ return;
800
+ }
801
+ try {
802
+ const { staticConfig } = component;
803
+ const defaultProps = {
804
+ ...getDefaultProps(staticConfig),
805
+ };
806
+ const variants = staticConfig.variants || {};
807
+ const isTextView = staticConfig.isText || false;
808
+ const validStyles = staticConfig?.validStyles ?? {};
809
+ // find render="a" render="main" etc dom indicators
810
+ let tagName = defaultProps.render ?? (isTextView ? 'span' : 'div');
811
+ traversePath
812
+ .get('openingElement')
813
+ .get('attributes')
814
+ .forEach((path) => {
815
+ const attr = path.node;
816
+ if (t.isJSXSpreadAttribute(attr))
817
+ return;
818
+ if (attr.name.name !== 'render')
819
+ return;
820
+ const val = attr.value;
821
+ if (!t.isStringLiteral(val))
822
+ return;
823
+ tagName = val.value;
824
+ });
825
+ if (shouldPrintDebug === 'verbose') {
826
+ console.info(` Start tag ${tagName}`);
827
+ }
828
+ const flatNodeName = getFlattenedNode?.({ isTextView, tag: tagName });
829
+ const inlineProps = new Set([
830
+ // adding some always inline props
831
+ ...(restProps.inlineProps || []),
832
+ ...(staticConfig.inlineProps || []),
833
+ ]);
834
+ const canFlattenTransition = isTargetingHTML &&
835
+ hanzoguiConfig?.animations.outputStyle === 'css' &&
836
+ !hanzoguiConfig.animationDrivers;
837
+ const deoptProps = new Set([
838
+ // css-only transitions lower to ordinary css; every runtime driver
839
+ // needs the component preserved so it can respond to prop changes.
840
+ 'animation',
841
+ ...(canFlattenTransition ? [] : ['transition']),
842
+ 'animateOnly',
843
+ 'animatePresence',
844
+ 'disableOptimization',
845
+ ...(!isTargetingHTML
846
+ ? [
847
+ // native has no css pseudo selectors; these are runtime-only on
848
+ // rn (event listeners + style merge in createComponent), and if
849
+ // we let them flatten into the stylesheet they get written
850
+ // under a literal key that rn treats as an unknown style prop.
851
+ // hover is intentionally excluded: it is no-op on native and
852
+ // should be dropped rather than preserved as runtime work.
853
+ 'pressStyle',
854
+ 'focusStyle',
855
+ 'focusVisibleStyle',
856
+ 'focusWithinStyle',
857
+ 'disabledStyle',
858
+ ]
859
+ : []),
860
+ // when using a non-CSS driver, de-opt on enterStyle/exitStyle
861
+ ...(hanzoguiConfig?.animations.isReactNative
862
+ ? ['enterStyle', 'exitStyle']
863
+ : []),
864
+ ]);
865
+ const inlineWhenUnflattened = new Set(staticConfig.inlineWhenUnflattened || []);
866
+ // Generate scope object at this level
867
+ const staticNamespace = getStaticBindingsForScope(traversePath.scope, importsWhitelist, sourcePath, bindingCache, shouldPrintDebug);
868
+ const attemptEval = !evaluateVars
869
+ ? evaluateAstNode
870
+ : createEvaluator({
871
+ props: propsWithFileInfo,
872
+ staticNamespace,
873
+ sourcePath,
874
+ traversePath,
875
+ shouldPrintDebug,
876
+ });
877
+ const attemptEvalSafe = createSafeEvaluator(attemptEval);
878
+ if (shouldPrintDebug) {
879
+ logger.info(` staticNamespace ${Object.keys(staticNamespace).join(', ')}`);
880
+ }
881
+ //
882
+ // SPREADS SETUP
883
+ //
884
+ if (couldntParse) {
885
+ return;
886
+ }
887
+ tm.mark('jsx-element-flattened', !!shouldPrintDebug);
888
+ let attrs = [];
889
+ let shouldDeopt = false;
890
+ const inlined = new Map();
891
+ const variantValues = new Map();
892
+ let hasSetOptimized = false;
893
+ const inlineWhenUnflattenedOGVals = {};
894
+ // RUN first pass
895
+ // normalize all conditionals so we can evaluate away easier later
896
+ // at the same time lets normalize shorthand media queries into spreads:
897
+ // that way we can parse them with the same logic later on
898
+ //
899
+ // {...media.sm && { color: x ? 'red' : 'blue' }}
900
+ // => {...media.sm && x && { color: 'red' }}
901
+ // => {...media.sm && !x && { color: 'blue' }}
902
+ //
903
+ // $sm={{ color: 'red' }}
904
+ // => {...media.sm && { color: 'red' }}
905
+ //
906
+ // $sm={{ color: x ? 'red' : 'blue' }}
907
+ // => {...media.sm && x && { color: 'red' }}
908
+ // => {...media.sm && !x && { color: 'blue' }}
909
+ const propMapperStyleState = {
910
+ staticConfig,
911
+ usedKeys: {},
912
+ classNames: {},
913
+ style: {},
914
+ theme: defaultTheme,
915
+ viewProps: defaultProps,
916
+ conf: hanzoguiConfig,
917
+ props: defaultProps,
918
+ componentState,
919
+ styleProps: {
920
+ ...styleProps,
921
+ resolveValues: 'auto',
922
+ },
923
+ debug: shouldPrintDebug,
924
+ };
925
+ attrs = traversePath
926
+ .get('openingElement')
927
+ .get('attributes')
928
+ .flatMap((path) => {
929
+ // avoid work
930
+ if (shouldDeopt) {
931
+ return;
932
+ }
933
+ try {
934
+ const res = evaluateAttribute(path);
935
+ if (!res) {
936
+ path.remove();
937
+ }
938
+ return res;
939
+ }
940
+ catch (err) {
941
+ if (shouldPrintDebug) {
942
+ logger.info([
943
+ 'Recoverable error extracting attribute',
944
+ err.message,
945
+ shouldPrintDebug === 'verbose' ? err.stack : '',
946
+ ].join(' '));
947
+ if (shouldPrintDebug === 'verbose') {
948
+ logger.info(`node ${path.node?.type}`);
949
+ }
950
+ }
951
+ // dont flatten if we run into error
952
+ inlined.set(`${Math.random()}`, 'spread');
953
+ return {
954
+ type: 'attr',
955
+ value: path.node,
956
+ };
957
+ }
958
+ })
959
+ .flat(4)
960
+ .filter(isPresent);
961
+ if (shouldPrintDebug) {
962
+ logger.info([' - attrs (before):\n', logLines(attrs.map(attrStr).join(', '))].join(' '));
963
+ }
964
+ // START function evaluateAttribute
965
+ function evaluateAttribute(path) {
966
+ const attribute = path.node;
967
+ const attr = { type: 'attr', value: attribute };
968
+ // ...spreads
969
+ if (t.isJSXSpreadAttribute(attribute)) {
970
+ const arg = attribute.argument;
971
+ const conditional = t.isConditionalExpression(arg)
972
+ ? // <YStack {...isSmall ? { color: 'red } : { color: 'blue }}
973
+ [arg.test, arg.consequent, arg.alternate]
974
+ : t.isLogicalExpression(arg) && arg.operator === '&&'
975
+ ? // <YStack {...isSmall && { color: 'red }}
976
+ [arg.left, arg.right, null]
977
+ : null;
978
+ if (conditional) {
979
+ const [test, alt, cons] = conditional;
980
+ if (!test)
981
+ throw new Error(`no test`);
982
+ if ([alt, cons].some((side) => side && !isStaticObject(side))) {
983
+ if (shouldPrintDebug) {
984
+ logger.info(`not extractable ${alt} ${cons}`);
985
+ }
986
+ return attr;
987
+ }
988
+ // split into individual ternaries per object property
989
+ return [
990
+ ...(flattenNestedTernaries(test, alt) || []),
991
+ ...((cons &&
992
+ flattenNestedTernaries(t.unaryExpression('!', test), cons)) ||
993
+ []),
994
+ ].map((ternary) => ({
995
+ type: 'ternary',
996
+ value: ternary,
997
+ }));
998
+ }
999
+ }
1000
+ // END ...spreads
1001
+ // directly keep these
1002
+ // couldn't evaluate spread, undefined name, or name is not string
1003
+ if (t.isJSXSpreadAttribute(attribute) ||
1004
+ !attribute.name ||
1005
+ typeof attribute.name.name !== 'string') {
1006
+ if (shouldPrintDebug) {
1007
+ logger.info(' ! inlining, spread attr');
1008
+ }
1009
+ inlined.set(`${Math.random()}`, 'spread');
1010
+ return attr;
1011
+ }
1012
+ const name = attribute.name.name;
1013
+ // in hanzogui style is handled at the end of the style loop so its not as simple as just
1014
+ // adding this as a "style" property
1015
+ // its not used often when using hanzogui so not optimizing it for now
1016
+ if (name === 'style') {
1017
+ shouldDeopt = true;
1018
+ return null;
1019
+ }
1020
+ if (excludeProps?.has(name)) {
1021
+ if (shouldPrintDebug) {
1022
+ logger.info([' excluding prop', name].join(' '));
1023
+ }
1024
+ return null;
1025
+ }
1026
+ if (inlineProps.has(name)) {
1027
+ inlined.set(name, name);
1028
+ if (shouldPrintDebug) {
1029
+ logger.info([' ! inlining, inline prop', name].join(' '));
1030
+ }
1031
+ return attr;
1032
+ }
1033
+ // pass className, key, and style props through untouched
1034
+ if (UNTOUCHED_PROPS[name]) {
1035
+ return attr;
1036
+ }
1037
+ if (INLINE_EXTRACTABLE[name]) {
1038
+ inlined.set(name, INLINE_EXTRACTABLE[name]);
1039
+ return attr;
1040
+ }
1041
+ if (name.startsWith('data-') ||
1042
+ name.startsWith('aria-') ||
1043
+ validHTMLAttributes[name]) {
1044
+ return attr;
1045
+ }
1046
+ // de-opt on enterStyle={expression}
1047
+ if ((name === 'enterStyle' || name === 'exitStyle') &&
1048
+ t.isJSXExpressionContainer(attribute?.value)) {
1049
+ shouldDeopt = true;
1050
+ return attr;
1051
+ }
1052
+ // shorthand media queries
1053
+ if (name[0] === '$' && t.isJSXExpressionContainer(attribute?.value)) {
1054
+ const shortname = name.slice(1);
1055
+ if (mediaQueryConfig[shortname]) {
1056
+ const expression = attribute.value.expression;
1057
+ if (!t.isJSXEmptyExpression(expression)) {
1058
+ const ternaries = flattenNestedTernaries(t.stringLiteral(shortname), expression, {
1059
+ inlineMediaQuery: shortname,
1060
+ });
1061
+ if (ternaries) {
1062
+ return ternaries.map((value) => ({
1063
+ type: 'ternary',
1064
+ value,
1065
+ }));
1066
+ }
1067
+ }
1068
+ }
1069
+ }
1070
+ const [value, valuePath] = (() => {
1071
+ if (t.isJSXExpressionContainer(attribute?.value)) {
1072
+ return [attribute.value.expression, path.get('value')];
1073
+ }
1074
+ return [attribute.value, path.get('value')];
1075
+ })();
1076
+ // these props have runtime-only meaning on native. decide from the
1077
+ // original jsx attr, before getSplitStyles has a chance to drop
1078
+ // native-dead work like hoverStyle from its static output.
1079
+ if (deoptProps.has(name) ||
1080
+ (platform === 'native' &&
1081
+ name[0] === '$' &&
1082
+ (name.startsWith('$theme-') ||
1083
+ (name.startsWith('$group-') && getGroupPseudo(name) !== 'hover')))) {
1084
+ inlined.set(name, true);
1085
+ return attr;
1086
+ }
1087
+ const remove = () => {
1088
+ Array.isArray(valuePath)
1089
+ ? valuePath.map((p) => p.remove())
1090
+ : valuePath.remove();
1091
+ };
1092
+ if (name === 'ref') {
1093
+ if (shouldPrintDebug) {
1094
+ logger.info([' ! inlining, ref', name].join(' '));
1095
+ }
1096
+ inlined.set('ref', 'ref');
1097
+ return attr;
1098
+ }
1099
+ if (name === 'render') {
1100
+ // Only optimize string literal render props
1101
+ // JSX elements and functions should deopt
1102
+ if (!value || value.type !== 'StringLiteral') {
1103
+ if (shouldPrintDebug) {
1104
+ logger.info(` ! deopt on render prop (not a string literal)`);
1105
+ }
1106
+ shouldDeopt = true;
1107
+ }
1108
+ return {
1109
+ type: 'attr',
1110
+ value: path.node,
1111
+ };
1112
+ }
1113
+ // native shouldn't extract variables
1114
+ if (disableExtractVariables === true) {
1115
+ if (value) {
1116
+ if (value.type === 'StringLiteral' && value.value[0] === '$') {
1117
+ if (shouldPrintDebug) {
1118
+ logger.info([
1119
+ ` ! inlining, native disable extract: ${name} =`,
1120
+ value.value,
1121
+ ].join(' '));
1122
+ }
1123
+ inlined.set(name, true);
1124
+ return attr;
1125
+ }
1126
+ }
1127
+ }
1128
+ if (name === 'theme') {
1129
+ inlined.set('theme', attr.value);
1130
+ return attr;
1131
+ }
1132
+ // static `group="<literal>"` is handled at compile-time in
1133
+ // extractToClassNames (emits container CSS + adds `t_group_<name>`
1134
+ // className), so we drop the JSX attribute here without bailing
1135
+ // flattening. dynamic `group={expr}` falls through to runtime.
1136
+ if (isTargetingHTML && name === 'group' && t.isStringLiteral(value)) {
1137
+ return [];
1138
+ }
1139
+ // if value can be evaluated, extract it and filter it out
1140
+ const styleValue = attemptEvalSafe(value);
1141
+ // media-like blocks with nested $-keys (eg $theme-dark={{ $sm: {…} }})
1142
+ // can't resolve to static CSS in one pass — keep them on the runtime path
1143
+ if (name[0] === '$' &&
1144
+ (name.startsWith('$theme-') || name.startsWith('$group-')) &&
1145
+ styleValue &&
1146
+ typeof styleValue === 'object' &&
1147
+ Object.keys(styleValue).some((k) => k[0] === '$')) {
1148
+ if (shouldPrintDebug) {
1149
+ logger.info(` ! nested media-like key inside ${name}, deopt to runtime`);
1150
+ }
1151
+ inlined.set(name, true);
1152
+ return attr;
1153
+ }
1154
+ // never flatten if a prop isn't a valid static attribute
1155
+ // only post prop-mapping
1156
+ if (!variants[name] && !isValidStyleKey(name, staticConfig)) {
1157
+ let out = null;
1158
+ // for now passing empty props {}, a bit odd, need to at least document
1159
+ // for now we don't expose custom components so just noting behavior
1160
+ propMapper(name, styleValue, propMapperStyleState, false, (key, val) => {
1161
+ out || (out = {});
1162
+ out[key] = val;
1163
+ });
1164
+ if (out) {
1165
+ if (isTargetingHTML) {
1166
+ // translate to DOM-compat
1167
+ out = reactNativeWebInternals.createDOMProps(isTextView ? 'span' : 'div', out);
1168
+ // remove className - we dont use rnw styling
1169
+ delete out.className;
1170
+ // remove style - rnw createDOMProps unconditionally emits a
1171
+ // (possibly empty) style key, but we passed it a single
1172
+ // non-style prop. Leaving it in causes Object.keys(out) to
1173
+ // iterate twice and emit the original JSXAttribute twice
1174
+ // (e.g. duplicate testID), breaking the DOM output.
1175
+ delete out.style;
1176
+ }
1177
+ }
1178
+ let didInline = false;
1179
+ const attributes = Object.keys(out).map((key) => {
1180
+ const val = out[key];
1181
+ const isStyle = isValidStyleKey(key, staticConfig);
1182
+ if (isStyle) {
1183
+ return {
1184
+ type: 'style',
1185
+ value: { [key]: styleValue },
1186
+ name: key,
1187
+ attr: path.node,
1188
+ };
1189
+ }
1190
+ if (validHTMLAttributes[key] ||
1191
+ key.startsWith('aria-') ||
1192
+ key.startsWith('data-') ||
1193
+ // this is debug stuff added by vite / new jsx transform
1194
+ key === '__source' ||
1195
+ key === '__self') {
1196
+ if (styleValue === FAILED_EVAL &&
1197
+ key !== name &&
1198
+ t.isJSXAttribute(attr.value)) {
1199
+ // createDOMProps renamed the prop (e.g. testID -> data-testid).
1200
+ // preserve the original expression value but use the new
1201
+ // attribute name. restricted to FAILED_EVAL because the
1202
+ // later `case 'attr'` rename pass only runs on
1203
+ // statically-evaluable values; for static values that pass
1204
+ // intentionally preserves some prop names (e.g. focusable
1205
+ // in v2) instead of doing the createDOMProps rename.
1206
+ return {
1207
+ type: 'attr',
1208
+ value: t.jsxAttribute(t.jsxIdentifier(key), attr.value.value),
1209
+ };
1210
+ }
1211
+ return attr;
1212
+ }
1213
+ if (shouldPrintDebug) {
1214
+ logger.info(' ! inlining, non-static ' + key);
1215
+ }
1216
+ didInline = true;
1217
+ inlined.set(key, val);
1218
+ return val;
1219
+ });
1220
+ // weird logic whats going on here
1221
+ if (didInline) {
1222
+ if (shouldPrintDebug) {
1223
+ logger.info(` bailing flattening due to attributes ${attributes.map((x) => x.toString())}`);
1224
+ }
1225
+ // bail
1226
+ return attr;
1227
+ }
1228
+ // return evaluated attributes
1229
+ return attributes;
1230
+ }
1231
+ // FAILED = dynamic or ternary, keep going
1232
+ if (styleValue !== FAILED_EVAL) {
1233
+ if (inlineWhenUnflattened.has(name)) {
1234
+ // preserve original value for restoration
1235
+ inlineWhenUnflattenedOGVals[name] = { styleValue, attr };
1236
+ }
1237
+ if (isValidStyleKey(name, staticConfig)) {
1238
+ // $theme- / $group- styles extract through the atomic-CSS pipeline
1239
+ // (extractToClassNames → createMediaStyle), so they fall through to
1240
+ // the normal style return below. The one case we still bail is
1241
+ // $group-<name>-* when an ancestor element declares `group="<name>"`
1242
+ // together with `untilMeasured` — the runtime measures the parent
1243
+ // and only then emits child styles, which can't be modeled in CSS.
1244
+ // $platform- can be flattened if the platform matches.
1245
+ if (name[0] === '$') {
1246
+ if (name.startsWith('$group-')) {
1247
+ const groupName = name.slice('$group-'.length).split('-')[0];
1248
+ if (groupName && hasUntilMeasuredAncestor(path, groupName)) {
1249
+ if (shouldPrintDebug) {
1250
+ logger.info(` ! group="${groupName}" ancestor has untilMeasured, not flattening: ${name}`);
1251
+ }
1252
+ inlined.set(name, true);
1253
+ return attr;
1254
+ }
1255
+ }
1256
+ // $platform-web, $platform-native, $platform-ios, $platform-android, $platform-tv, $platform-androidtv, $platform-tvos
1257
+ if (name.startsWith('$platform-')) {
1258
+ const platformName = name.slice(10); // remove '$platform-'
1259
+ const isMatchingPlatform = platformName === platform ||
1260
+ (platformName === 'native' && platform === 'native') ||
1261
+ (platformName === 'web' && platform === 'web');
1262
+ if (isMatchingPlatform && typeof styleValue === 'object') {
1263
+ // Flatten the inner styles directly
1264
+ if (shouldPrintDebug) {
1265
+ logger.info(` flattening $platform-${platformName}: ${JSON.stringify(styleValue)}`);
1266
+ }
1267
+ return Object.entries(styleValue).map(([key, val]) => ({
1268
+ type: 'style',
1269
+ value: { [key]: val },
1270
+ name: key,
1271
+ attr: path.node,
1272
+ }));
1273
+ }
1274
+ else {
1275
+ // On native builds, sub-platform variants (android, ios, tv, androidtv, tvos)
1276
+ // can't be resolved at compile time - leave for runtime evaluation
1277
+ if (platform === 'native' &&
1278
+ nativeOnlyPlatforms.has(platformName)) {
1279
+ if (shouldPrintDebug) {
1280
+ logger.info(` ! keeping platform-specific style for runtime evaluation: ${name}`);
1281
+ }
1282
+ inlined.set(name, true);
1283
+ return attr;
1284
+ }
1285
+ // Platform doesn't match, skip these styles entirely
1286
+ if (shouldPrintDebug) {
1287
+ logger.info(` ! skipping non-matching platform style: ${name}`);
1288
+ }
1289
+ return [];
1290
+ }
1291
+ }
1292
+ }
1293
+ if (shouldPrintDebug) {
1294
+ logger.info(` style: ${name} = ${JSON.stringify(styleValue)}`);
1295
+ }
1296
+ if (!(name in defaultProps)) {
1297
+ if (!hasSetOptimized) {
1298
+ res.optimized++;
1299
+ hasSetOptimized = true;
1300
+ }
1301
+ }
1302
+ return {
1303
+ type: 'style',
1304
+ value: { [name]: styleValue },
1305
+ name,
1306
+ attr: path.node,
1307
+ };
1308
+ }
1309
+ if (variants[name]) {
1310
+ variantValues.set(name, styleValue);
1311
+ }
1312
+ inlined.set(name, true);
1313
+ return attr;
1314
+ }
1315
+ // ternaries!
1316
+ // binary ternary, we can eventually make this smarter but step 1
1317
+ // basically for the common use case of:
1318
+ // opacity={(conditional ? 0 : 1) * scale}
1319
+ if (t.isBinaryExpression(value)) {
1320
+ if (shouldPrintDebug) {
1321
+ logger.info(` binary expression ${name} = ${value}`);
1322
+ }
1323
+ const { operator, left, right } = value;
1324
+ // if one side is a ternary, and the other side is evaluatable, we can maybe extract
1325
+ const lVal = attemptEvalSafe(left);
1326
+ const rVal = attemptEvalSafe(right);
1327
+ if (shouldPrintDebug) {
1328
+ logger.info(` evalBinaryExpression lVal ${String(lVal)}, rVal ${String(rVal)}`);
1329
+ }
1330
+ if (lVal !== FAILED_EVAL && t.isConditionalExpression(right)) {
1331
+ const ternary = addBinaryConditional(operator, left, right);
1332
+ if (ternary)
1333
+ return ternary;
1334
+ }
1335
+ if (rVal !== FAILED_EVAL && t.isConditionalExpression(left)) {
1336
+ const ternary = addBinaryConditional(operator, right, left);
1337
+ if (ternary)
1338
+ return ternary;
1339
+ }
1340
+ if (shouldPrintDebug) {
1341
+ logger.info(` evalBinaryExpression cant extract`);
1342
+ }
1343
+ inlined.set(name, true);
1344
+ return attr;
1345
+ }
1346
+ const staticConditional = getStaticConditional(value);
1347
+ if (staticConditional) {
1348
+ if (shouldPrintDebug === 'verbose') {
1349
+ logger.info(` static conditional ${name} ${value}`);
1350
+ }
1351
+ return { type: 'ternary', value: staticConditional };
1352
+ }
1353
+ const staticLogical = getStaticLogical(value);
1354
+ if (staticLogical) {
1355
+ if (shouldPrintDebug === 'verbose') {
1356
+ logger.info(` static ternary ${name} = ${value}`);
1357
+ }
1358
+ return { type: 'ternary', value: staticLogical };
1359
+ }
1360
+ // if we've made it this far, the prop stays inline
1361
+ inlined.set(name, true);
1362
+ if (shouldPrintDebug) {
1363
+ logger.info(` ! inline no match ${name} ${value}`);
1364
+ }
1365
+ //
1366
+ // RETURN ATTR
1367
+ //
1368
+ return attr;
1369
+ // attr helpers:
1370
+ function addBinaryConditional(operator, staticExpr, cond) {
1371
+ if (getStaticConditional(cond)) {
1372
+ const alt = attemptEval(t.binaryExpression(operator, staticExpr, cond.alternate));
1373
+ const cons = attemptEval(t.binaryExpression(operator, staticExpr, cond.consequent));
1374
+ if (shouldPrintDebug) {
1375
+ logger.info([' binaryConditional', cond.test, cons, alt].join(' '));
1376
+ }
1377
+ return {
1378
+ type: 'ternary',
1379
+ value: {
1380
+ test: cond.test,
1381
+ remove,
1382
+ alternate: { [name]: alt },
1383
+ consequent: { [name]: cons },
1384
+ },
1385
+ };
1386
+ }
1387
+ return null;
1388
+ }
1389
+ function getStaticConditional(value) {
1390
+ if (t.isConditionalExpression(value)) {
1391
+ try {
1392
+ const aVal = attemptEval(value.alternate);
1393
+ const cVal = attemptEval(value.consequent);
1394
+ if (shouldPrintDebug) {
1395
+ const type = value.test.type;
1396
+ logger.info([' static ternary', type, cVal, aVal].join(' '));
1397
+ }
1398
+ return {
1399
+ test: value.test,
1400
+ remove,
1401
+ consequent: { [name]: cVal },
1402
+ alternate: { [name]: aVal },
1403
+ };
1404
+ }
1405
+ catch (err) {
1406
+ if (shouldPrintDebug) {
1407
+ logger.info([' cant eval ternary', err.message].join(' '));
1408
+ }
1409
+ }
1410
+ }
1411
+ return null;
1412
+ }
1413
+ function getStaticLogical(value) {
1414
+ if (t.isLogicalExpression(value)) {
1415
+ if (value.operator === '&&') {
1416
+ try {
1417
+ const val = attemptEval(value.right);
1418
+ if (shouldPrintDebug) {
1419
+ logger.info([' staticLogical', value.left, name, val].join(' '));
1420
+ }
1421
+ return {
1422
+ test: value.left,
1423
+ remove,
1424
+ consequent: { [name]: val },
1425
+ alternate: null,
1426
+ };
1427
+ }
1428
+ catch (err) {
1429
+ if (shouldPrintDebug) {
1430
+ logger.info([' cant static eval logical', err].join(' '));
1431
+ }
1432
+ }
1433
+ }
1434
+ }
1435
+ return null;
1436
+ }
1437
+ } // END function evaluateAttribute
1438
+ function isStaticObject(obj) {
1439
+ return (t.isObjectExpression(obj) &&
1440
+ obj.properties.every((prop) => {
1441
+ if (!t.isObjectProperty(prop)) {
1442
+ // console.warn('not an object prop?', prop)
1443
+ return false;
1444
+ }
1445
+ const propName = prop.key['name'];
1446
+ if (!isValidStyleKey(propName, staticConfig) && propName !== 'render') {
1447
+ if (shouldPrintDebug) {
1448
+ logger.info([' not a valid style prop!', propName].join(' '));
1449
+ }
1450
+ return false;
1451
+ }
1452
+ return true;
1453
+ }));
1454
+ }
1455
+ // side = {
1456
+ // color: 'red',
1457
+ // background: x ? 'red' : 'green',
1458
+ // $gtSm: { color: 'green' }
1459
+ // }
1460
+ // => Ternary<test, { color: 'red' }, null>
1461
+ // => Ternary<test && x, { background: 'red' }, null>
1462
+ // => Ternary<test && !x, { background: 'green' }, null>
1463
+ // => Ternary<test && '$gtSm', { color: 'green' }, null>
1464
+ function flattenNestedTernaries(test, side, ternaryPartial = {}) {
1465
+ if (!side) {
1466
+ return null;
1467
+ }
1468
+ if (!isStaticObject(side)) {
1469
+ throw new Error('not extractable');
1470
+ }
1471
+ return side.properties.flatMap((property) => {
1472
+ if (!t.isObjectProperty(property)) {
1473
+ throw new Error('expected object property');
1474
+ }
1475
+ // this could be a recurse here if we want to get fancy
1476
+ if (t.isConditionalExpression(property.value)) {
1477
+ // merge up into the parent conditional, split into two
1478
+ const [truthy, falsy] = [
1479
+ t.objectExpression([
1480
+ t.objectProperty(property.key, property.value.consequent),
1481
+ ]),
1482
+ t.objectExpression([
1483
+ t.objectProperty(property.key, property.value.alternate),
1484
+ ]),
1485
+ ].map((x) => attemptEval(x));
1486
+ return [
1487
+ createTernary({
1488
+ remove() { },
1489
+ ...ternaryPartial,
1490
+ test: t.logicalExpression('&&', test, property.value.test),
1491
+ consequent: truthy,
1492
+ alternate: null,
1493
+ }),
1494
+ createTernary({
1495
+ ...ternaryPartial,
1496
+ test: t.logicalExpression('&&', test, t.unaryExpression('!', property.value.test)),
1497
+ consequent: falsy,
1498
+ alternate: null,
1499
+ remove() { },
1500
+ }),
1501
+ ];
1502
+ }
1503
+ const obj = t.objectExpression([
1504
+ t.objectProperty(property.key, property.value),
1505
+ ]);
1506
+ const consequent = attemptEval(obj);
1507
+ return createTernary({
1508
+ remove() { },
1509
+ ...ternaryPartial,
1510
+ test,
1511
+ consequent,
1512
+ alternate: null,
1513
+ });
1514
+ });
1515
+ }
1516
+ if (couldntParse || shouldDeopt) {
1517
+ if (shouldPrintDebug) {
1518
+ logger.info([` avoid optimizing:`, { couldntParse, shouldDeopt }].join(' '));
1519
+ }
1520
+ node.attributes = ogAttributes;
1521
+ return;
1522
+ }
1523
+ // before deopt, can still optimize
1524
+ const parentFn = findTopmostFunction(traversePath);
1525
+ if (parentFn) {
1526
+ modifiedComponents.add(parentFn);
1527
+ }
1528
+ // flatten logic!
1529
+ // fairly simple check to see if all children are text
1530
+ const hasSpread = attrs.some((x) => x.type === 'attr' && t.isJSXSpreadAttribute(x.value));
1531
+ const hasOnlyStringChildren = !hasSpread &&
1532
+ (node.selfClosing ||
1533
+ (traversePath.node.children &&
1534
+ traversePath.node.children.every((x) => x.type === 'JSXText')));
1535
+ let themeVal = inlined.get('theme');
1536
+ // on native we can't flatten when theme prop is set
1537
+ if (platform !== 'native') {
1538
+ inlined.delete('theme');
1539
+ }
1540
+ for (const [key] of inlined) {
1541
+ const isStaticObjectVariant = staticConfig.variants?.[key] && variantValues.has(key);
1542
+ if (INLINE_EXTRACTABLE[key] || isStaticObjectVariant) {
1543
+ inlined.delete(key);
1544
+ }
1545
+ }
1546
+ const canFlattenProps = inlined.size === 0;
1547
+ let shouldFlatten = Boolean(flatNodeName &&
1548
+ !shouldDeopt &&
1549
+ canFlattenProps &&
1550
+ !hasSpread &&
1551
+ !staticConfig.isStyledHOC &&
1552
+ !staticConfig.isHOC &&
1553
+ !staticConfig.isReactNative &&
1554
+ staticConfig.neverFlatten !== true &&
1555
+ (staticConfig.neverFlatten === 'jsx' ? hasOnlyStringChildren : true));
1556
+ if (shouldPrintDebug === 'verbose') {
1557
+ logger.info(` flatten? ${originalNodeName} -> ${flatNodeName} ${JSON.stringify({
1558
+ shouldFlatten,
1559
+ shouldDeopt,
1560
+ canFlattenProps,
1561
+ hasSpread,
1562
+ isStyledHOC: staticConfig.isStyledHOC,
1563
+ isHOC: staticConfig.isHOC,
1564
+ isReactNative: staticConfig.isReactNative,
1565
+ neverFlatten: staticConfig.neverFlatten,
1566
+ })}`);
1567
+ }
1568
+ const usedThemeKeys = new Set();
1569
+ // if it accesses any theme values during evaluation
1570
+ themeAccessListeners.add((key) => {
1571
+ if (disableExtractVariables) {
1572
+ usedThemeKeys.add(key);
1573
+ shouldFlatten = false;
1574
+ if (shouldPrintDebug === 'verbose') {
1575
+ logger.info([' ! accessing theme key, avoid flatten', key].join(' '));
1576
+ }
1577
+ }
1578
+ });
1579
+ if (!shouldFlatten) {
1580
+ if (shouldPrintDebug) {
1581
+ logger.info(`Deopting ${JSON.stringify({
1582
+ shouldFlatten,
1583
+ shouldDeopt,
1584
+ canFlattenProps,
1585
+ hasSpread,
1586
+ neverFlatten: staticConfig.neverFlatten,
1587
+ })}`);
1588
+ }
1589
+ node.attributes = ogAttributes;
1590
+ return;
1591
+ }
1592
+ // ensure the default styles are there
1593
+ let skipMap = false;
1594
+ const defaultStyleAttrs = Object.keys(defaultProps).flatMap((key) => {
1595
+ if (skipMap)
1596
+ return [];
1597
+ const value = defaultProps[key];
1598
+ if (key === 'theme' && !themeVal) {
1599
+ if (platform === 'native') {
1600
+ shouldFlatten = false;
1601
+ skipMap = true;
1602
+ inlined.set('theme', { value: t.stringLiteral(value) });
1603
+ }
1604
+ themeVal = { value: t.stringLiteral(value) };
1605
+ return [];
1606
+ }
1607
+ if (!isValidStyleKey(key, staticConfig)) {
1608
+ return [];
1609
+ }
1610
+ const name = hanzoguiConfig?.shorthands[key] || key;
1611
+ if (value === undefined) {
1612
+ logger.warn(`⚠️ Error evaluating default style for component, prop ${key} ${value}`);
1613
+ shouldDeopt = true;
1614
+ return;
1615
+ }
1616
+ if (name[0] === '$' && mediaQueryConfig[name.slice(1)]) {
1617
+ defaultProps[key] = undefined;
1618
+ return evaluateAttribute({
1619
+ node: t.jsxAttribute(t.jsxIdentifier(name), t.jsxExpressionContainer(t.objectExpression(Object.keys(value)
1620
+ .filter((k) => {
1621
+ return typeof value[k] !== 'undefined';
1622
+ })
1623
+ .map((k) => {
1624
+ return t.objectProperty(t.identifier(k), literalToAst(value[k]));
1625
+ })))),
1626
+ });
1627
+ }
1628
+ const attr = {
1629
+ type: 'style',
1630
+ name,
1631
+ value: { [name]: value },
1632
+ };
1633
+ return attr;
1634
+ });
1635
+ if (!skipMap) {
1636
+ if (defaultStyleAttrs.length) {
1637
+ attrs = [...defaultStyleAttrs, ...attrs];
1638
+ }
1639
+ }
1640
+ // combine ternaries
1641
+ let ternaries = [];
1642
+ attrs = attrs
1643
+ .reduce((out, cur) => {
1644
+ const next = attrs[attrs.indexOf(cur) + 1];
1645
+ if (cur.type === 'ternary') {
1646
+ ternaries.push(cur.value);
1647
+ }
1648
+ if ((!next || next.type !== 'ternary') && ternaries.length) {
1649
+ // finish, process
1650
+ const normalized = normalizeTernaries(ternaries).map(({ alternate, consequent, ...rest }) => {
1651
+ return {
1652
+ type: 'ternary',
1653
+ value: {
1654
+ ...rest,
1655
+ alternate: alternate || null,
1656
+ consequent: consequent || null,
1657
+ },
1658
+ };
1659
+ });
1660
+ try {
1661
+ return [...out, ...normalized];
1662
+ }
1663
+ finally {
1664
+ if (shouldPrintDebug) {
1665
+ logger.info(` normalizeTernaries (${ternaries.length} => ${normalized.length})`);
1666
+ }
1667
+ ternaries = [];
1668
+ }
1669
+ }
1670
+ if (cur.type === 'ternary') {
1671
+ return out;
1672
+ }
1673
+ out.push(cur);
1674
+ return out;
1675
+ }, [])
1676
+ .flat();
1677
+ // wrap theme around children on flatten
1678
+ // account for shouldFlatten could change w the above block "if (disableExtractVariables)"
1679
+ if (themeVal) {
1680
+ if (!programPath) {
1681
+ console.warn(`No program path found, avoiding importing flattening / importing theme in ${sourcePath}`);
1682
+ }
1683
+ else {
1684
+ if (shouldPrintDebug) {
1685
+ logger.info([' - wrapping theme', themeVal].join(' '));
1686
+ }
1687
+ // remove theme attribute from flattened node
1688
+ attrs = attrs.filter((x) => !(x.type === 'attr' &&
1689
+ t.isJSXAttribute(x.value) &&
1690
+ x.value.name.name === 'theme'));
1691
+ // add import
1692
+ if (!hasImportedTheme) {
1693
+ hasImportedTheme = true;
1694
+ programPath.node.body.push(t.importDeclaration([t.importSpecifier(t.identifier('_GuiTheme'), t.identifier('Theme'))], t.stringLiteral('@hanzogui/web')));
1695
+ }
1696
+ traversePath.replaceWith(t.jsxElement(t.jsxOpeningElement(t.jsxIdentifier('_GuiTheme'), [
1697
+ t.jsxAttribute(t.jsxIdentifier('name'), themeVal.value),
1698
+ ]), t.jsxClosingElement(t.jsxIdentifier('_GuiTheme')), [traversePath.node]));
1699
+ }
1700
+ }
1701
+ if (shouldPrintDebug) {
1702
+ logger.info([' - attrs (flattened): \n', logLines(attrs.map(attrStr).join(', '))].join(' '));
1703
+ }
1704
+ function mergeToEnd(obj, key, val) {
1705
+ if (key in obj) {
1706
+ delete obj[key];
1707
+ }
1708
+ obj[key] = val;
1709
+ }
1710
+ // preserves order
1711
+ function normalizeStyleWithoutVariants(style) {
1712
+ let res = {};
1713
+ for (const key in style) {
1714
+ if (staticConfig.variants && key in staticConfig.variants) {
1715
+ mergeToEnd(res, key, style[key]);
1716
+ }
1717
+ else {
1718
+ const expanded = normalizeStyle({ [key]: style[key] }, true);
1719
+ for (const key in expanded) {
1720
+ mergeToEnd(res, key, expanded[key]);
1721
+ }
1722
+ }
1723
+ }
1724
+ return res;
1725
+ }
1726
+ // evaluates all static attributes into a simple object
1727
+ let foundStaticProps = {};
1728
+ for (const key in attrs) {
1729
+ const cur = attrs[key];
1730
+ if (cur.type === 'style') {
1731
+ // remove variants because they are processed later, and can lead to invalid values here
1732
+ // see <Spacer flex /> where flex looks like a valid style, but is a variant
1733
+ const expanded = normalizeStyleWithoutVariants(cur.value);
1734
+ // preserve order
1735
+ for (const key in expanded) {
1736
+ mergeToEnd(foundStaticProps, key, expanded[key]);
1737
+ }
1738
+ continue;
1739
+ }
1740
+ if (cur.type === 'attr') {
1741
+ if (t.isJSXSpreadAttribute(cur.value)) {
1742
+ continue;
1743
+ }
1744
+ if (!t.isJSXIdentifier(cur.value.name)) {
1745
+ continue;
1746
+ }
1747
+ const key = cur.value.name.name;
1748
+ // undefined = boolean true
1749
+ const value = attemptEvalSafe(cur.value.value || t.booleanLiteral(true));
1750
+ if (value !== FAILED_EVAL) {
1751
+ mergeToEnd(foundStaticProps, key, value);
1752
+ }
1753
+ }
1754
+ }
1755
+ // must preserve exact order
1756
+ const completeProps = {};
1757
+ for (const key in defaultProps) {
1758
+ if (!(key in foundStaticProps)) {
1759
+ completeProps[key] = defaultProps[key];
1760
+ }
1761
+ }
1762
+ for (const key in foundStaticProps) {
1763
+ completeProps[key] = foundStaticProps[key];
1764
+ }
1765
+ // expand shorthands, de-opt variables
1766
+ attrs = attrs.reduce((acc, cur) => {
1767
+ if (!cur)
1768
+ return acc;
1769
+ if (cur.type === 'attr' && !t.isJSXSpreadAttribute(cur.value)) {
1770
+ if (shouldFlatten) {
1771
+ const name = cur.value.name.name;
1772
+ if (typeof name === 'string') {
1773
+ if (name === 'render') {
1774
+ // remove render=""
1775
+ return acc;
1776
+ }
1777
+ // if flattening, expand variants
1778
+ if (variants[name] && variantValues.has(name)) {
1779
+ const styleState = {
1780
+ ...propMapperStyleState,
1781
+ props: completeProps,
1782
+ };
1783
+ let out = {};
1784
+ propMapper(name, variantValues.get(name), styleState, false, (key, val) => {
1785
+ out[key] = val;
1786
+ });
1787
+ if (out && isTargetingHTML) {
1788
+ const cn = out.className;
1789
+ // translate to DOM-compat
1790
+ out = reactNativeWebInternals.createDOMProps(isTextView ? 'span' : 'div', out);
1791
+ // remove rnw className use ours
1792
+ out.className = cn;
1793
+ // see note in single-prop branch above; createDOMProps
1794
+ // also emits a stray style key here that would duplicate
1795
+ // emitted JSXAttributes downstream.
1796
+ delete out.style;
1797
+ }
1798
+ if (shouldPrintDebug) {
1799
+ logger.info([' - expanded variant', name, out].join(' '));
1800
+ }
1801
+ for (const key in out) {
1802
+ const value = out[key];
1803
+ if (isValidStyleKey(key, staticConfig)) {
1804
+ acc.push({
1805
+ type: 'style',
1806
+ value: { [key]: value },
1807
+ name: key,
1808
+ attr: cur.value,
1809
+ });
1810
+ }
1811
+ else {
1812
+ acc.push({
1813
+ type: 'attr',
1814
+ value: t.jsxAttribute(t.jsxIdentifier(key), t.jsxExpressionContainer(typeof value === 'string'
1815
+ ? t.stringLiteral(value)
1816
+ : literalToAst(value))),
1817
+ });
1818
+ }
1819
+ }
1820
+ }
1821
+ }
1822
+ }
1823
+ }
1824
+ if (cur.type !== 'style') {
1825
+ acc.push(cur);
1826
+ return acc;
1827
+ }
1828
+ let key = Object.keys(cur.value)[0];
1829
+ const value = cur.value[key];
1830
+ const fullKey = hanzoguiConfig?.shorthands[key];
1831
+ // expand shorthands
1832
+ if (fullKey) {
1833
+ cur.value = { [fullKey]: value };
1834
+ key = fullKey;
1835
+ }
1836
+ // finally we have all styles + expansions, lets see if we need to skip
1837
+ // any and keep them as attrs
1838
+ if (disableExtractVariables) {
1839
+ if (value[0] === '$' &&
1840
+ (usedThemeKeys.has(key) || usedThemeKeys.has(fullKey))) {
1841
+ if (shouldPrintDebug) {
1842
+ logger.info([` keeping variable inline: ${key} =`, value].join(' '));
1843
+ }
1844
+ acc.push({
1845
+ type: 'attr',
1846
+ value: t.jsxAttribute(t.jsxIdentifier(key), t.jsxExpressionContainer(t.stringLiteral(value))),
1847
+ });
1848
+ return acc;
1849
+ }
1850
+ }
1851
+ acc.push(cur);
1852
+ return acc;
1853
+ }, []);
1854
+ tm.mark('jsx-element-expanded', !!shouldPrintDebug);
1855
+ if (shouldPrintDebug) {
1856
+ logger.info([' - attrs (expanded): \n', logLines(attrs.map(attrStr).join(', '))].join(' '));
1857
+ }
1858
+ // merge styles, leave undefined values
1859
+ let prev = null;
1860
+ function mergeStyles(prev, next) {
1861
+ for (const key in next) {
1862
+ // merge pseudos
1863
+ if (pseudoDescriptors[key]) {
1864
+ prev[key] = prev[key] || {};
1865
+ Object.assign(prev[key], next[key]);
1866
+ }
1867
+ else {
1868
+ mergeToEnd(prev, key, next[key]);
1869
+ }
1870
+ }
1871
+ }
1872
+ // post process
1873
+ const getProps = (props, includeProps = false, debugName = '') => {
1874
+ if (!props) {
1875
+ if (shouldPrintDebug)
1876
+ logger.info([' getProps() no props'].join(' '));
1877
+ return {};
1878
+ }
1879
+ if (excludeProps?.size) {
1880
+ for (const key in props) {
1881
+ if (excludeProps.has(key)) {
1882
+ if (shouldPrintDebug)
1883
+ logger.info([' delete excluded', key].join(' '));
1884
+ delete props[key];
1885
+ }
1886
+ }
1887
+ }
1888
+ const before = process.env.IS_STATIC;
1889
+ process.env.IS_STATIC = 'is_static';
1890
+ try {
1891
+ // $group-* / $theme-* keys carry block-form style objects that
1892
+ // getSplitStyles drops in static mode (no parent group context,
1893
+ // no theme value to read). Pluck them out so the atomic-CSS
1894
+ // pipeline in extractToClassNames can emit @container / theme
1895
+ // rules for them directly.
1896
+ let extractedMediaLikeProps = null;
1897
+ let propsForSplit = props;
1898
+ for (const k in props) {
1899
+ if (k[0] === '$' &&
1900
+ (k.startsWith('$group-') || k.startsWith('$theme-'))) {
1901
+ if (propsForSplit === props) {
1902
+ propsForSplit = { ...props };
1903
+ }
1904
+ if (platform === 'native' &&
1905
+ k.startsWith('$group-') &&
1906
+ getGroupPseudo(k) === 'hover') {
1907
+ delete propsForSplit[k];
1908
+ continue;
1909
+ }
1910
+ extractedMediaLikeProps || (extractedMediaLikeProps = {});
1911
+ extractedMediaLikeProps[k] = propsForSplit[k];
1912
+ delete propsForSplit[k];
1913
+ }
1914
+ }
1915
+ const out = getSplitStyles(propsForSplit, staticConfig, defaultTheme, '', componentState, {
1916
+ ...styleProps,
1917
+ noClass: true,
1918
+ fallbackProps: completeProps,
1919
+ ...(platform === 'native' && {
1920
+ resolveValues: 'except-theme',
1921
+ }),
1922
+ }, undefined, undefined, undefined, undefined, false, debugPropValue || shouldPrintDebug);
1923
+ // resolve tokens inside the plucked blocks: they skipped the main
1924
+ // split, so values like "$color5" would flow raw into the emitted
1925
+ // CSS where browsers reject the declaration. run each block through
1926
+ // its own static split so tokens become var(--x) references.
1927
+ // (native never extracts these — it deopts below — so web only.)
1928
+ if (extractedMediaLikeProps && platform !== 'native') {
1929
+ for (const k in extractedMediaLikeProps) {
1930
+ const block = extractedMediaLikeProps[k];
1931
+ if (!block || typeof block !== 'object')
1932
+ continue;
1933
+ const blockOut = getSplitStyles(block, staticConfig, defaultTheme, '', componentState, {
1934
+ ...styleProps,
1935
+ noClass: true,
1936
+ fallbackProps: completeProps,
1937
+ }, undefined, undefined, undefined, undefined, false, debugPropValue || shouldPrintDebug);
1938
+ if (blockOut) {
1939
+ extractedMediaLikeProps[k] = {
1940
+ ...blockOut.style,
1941
+ ...blockOut.pseudos,
1942
+ };
1943
+ }
1944
+ }
1945
+ }
1946
+ let outProps = {
1947
+ ...(includeProps ? out.viewProps : {}),
1948
+ ...out.style,
1949
+ ...out.pseudos,
1950
+ ...extractedMediaLikeProps,
1951
+ };
1952
+ // check de-opt props again
1953
+ for (const key in outProps) {
1954
+ if (deoptProps.has(key)) {
1955
+ shouldFlatten = false;
1956
+ }
1957
+ // native has no atomic-CSS sink for theme- / group- pseudo
1958
+ // blocks; if they flatten they get serialized under the literal
1959
+ // `$theme-…` / `$group-…` key into the RN StyleSheet, where the
1960
+ // runtime's @container / theme-name matching never runs. de-opt
1961
+ // → preserve as inline prop so getSplitStyles handles them at
1962
+ // render time.
1963
+ if (platform === 'native' &&
1964
+ key[0] === '$' &&
1965
+ (key.startsWith('$theme-') ||
1966
+ (key.startsWith('$group-') && getGroupPseudo(key) !== 'hover'))) {
1967
+ shouldFlatten = false;
1968
+ }
1969
+ }
1970
+ if (shouldPrintDebug) {
1971
+ logger.info(`(${debugName})`);
1972
+ // prettier-ignore
1973
+ logger.info(`\n getProps (props in): ${logLines(objToStr(props))}`);
1974
+ // prettier-ignore
1975
+ logger.info(`\n getProps (outProps): ${logLines(objToStr(outProps))}`);
1976
+ }
1977
+ if (out.fontFamily) {
1978
+ setPropsToFontFamily(outProps, out.fontFamily);
1979
+ if (shouldPrintDebug) {
1980
+ logger.info(`\n 💬 new font fam: ${out.fontFamily}`);
1981
+ }
1982
+ }
1983
+ return outProps;
1984
+ }
1985
+ catch (err) {
1986
+ logger.info(['error', err.message, err.stack].join(' '));
1987
+ return {};
1988
+ }
1989
+ finally {
1990
+ process.env.IS_STATIC = before;
1991
+ }
1992
+ };
1993
+ // add default props
1994
+ attrs.unshift({
1995
+ type: 'style',
1996
+ value: defaultProps,
1997
+ });
1998
+ attrs = attrs.reduce((acc, cur) => {
1999
+ if (cur.type === 'style') {
2000
+ const keys = Object.keys(cur.value || {});
2001
+ if (!keys.length) {
2002
+ return acc;
2003
+ }
2004
+ const key = keys[0];
2005
+ const value = cur.value[key];
2006
+ // Check if this is a media-like key ($theme-, $platform-, $group-, or $mediaQuery)
2007
+ const isMediaLikeKey = key[0] === '$' &&
2008
+ (key.startsWith('$theme-') ||
2009
+ key.startsWith('$platform-') ||
2010
+ key.startsWith('$group-') ||
2011
+ mediaQueryConfig[key.slice(1)]);
2012
+ const shouldKeepOriginalAttr =
2013
+ // !isStyleAndAttr[key] &&
2014
+ !shouldFlatten &&
2015
+ // de-opt if non-style
2016
+ !validStyles[key] &&
2017
+ !pseudoDescriptors[key] &&
2018
+ !isMediaLikeKey &&
2019
+ !(key.startsWith('data-') || key.startsWith('aria-'));
2020
+ if (shouldKeepOriginalAttr) {
2021
+ if (shouldPrintDebug) {
2022
+ logger.info([' - keeping as non-style', key].join(' '));
2023
+ }
2024
+ prev = cur;
2025
+ acc.push({
2026
+ type: 'attr',
2027
+ value: t.jsxAttribute(t.jsxIdentifier(key), t.jsxExpressionContainer(typeof value === 'string'
2028
+ ? t.stringLiteral(value)
2029
+ : literalToAst(value))),
2030
+ });
2031
+ acc.push(cur);
2032
+ return acc;
2033
+ }
2034
+ if (prev?.type === 'style') {
2035
+ mergeStyles(prev.value, cur.value);
2036
+ return acc;
2037
+ }
2038
+ }
2039
+ if (cur.type === 'style') {
2040
+ prev = cur;
2041
+ }
2042
+ acc.push(cur);
2043
+ return acc;
2044
+ }, []);
2045
+ if (shouldPrintDebug) {
2046
+ logger.info([
2047
+ ' - attrs (combined 🔀): \n',
2048
+ logLines(attrs.map(attrStr).join(', ')),
2049
+ ].join(' '));
2050
+ }
2051
+ let getStyleError = null;
2052
+ // fix up ternaries, combine final style values
2053
+ for (const attr of attrs) {
2054
+ try {
2055
+ if (shouldPrintDebug) {
2056
+ console.info(` Processing ${attr.type}:`);
2057
+ }
2058
+ switch (attr.type) {
2059
+ case 'ternary': {
2060
+ const a = getProps(attr.value.alternate, false, 'ternary.alternate');
2061
+ const c = getProps(attr.value.consequent, false, 'ternary.consequent');
2062
+ if (a)
2063
+ attr.value.alternate = a;
2064
+ if (c)
2065
+ attr.value.consequent = c;
2066
+ if (shouldPrintDebug)
2067
+ logger.info([' => tern ', attrStr(attr)].join(' '));
2068
+ continue;
2069
+ }
2070
+ case 'style': {
2071
+ // expand variants and such
2072
+ const styles = getProps(attr.value, false, 'style');
2073
+ if (styles) {
2074
+ // @ts-ignore
2075
+ attr.value = styles;
2076
+ }
2077
+ // prettier-ignore
2078
+ if (shouldPrintDebug)
2079
+ logger.info([' * styles (in)', logLines(objToStr(attr.value))].join(' '));
2080
+ // prettier-ignore
2081
+ if (shouldPrintDebug)
2082
+ logger.info([' * styles (out)', logLines(objToStr(styles))].join(' '));
2083
+ continue;
2084
+ }
2085
+ case 'attr': {
2086
+ if (shouldFlatten && t.isJSXAttribute(attr.value)) {
2087
+ // we know all attributes are static
2088
+ // this only does one at a time but it should really do the whole group together...
2089
+ // also awkward to be doing it using jsxAttributes...
2090
+ const key = attr.value.name.name;
2091
+ // dont process style/className can just stay attrs
2092
+ if (key === 'style' || key === 'className' || key === 'render') {
2093
+ continue;
2094
+ }
2095
+ // undefined = boolean true
2096
+ const value = attemptEvalSafe(attr.value.value || t.booleanLiteral(true));
2097
+ if (value !== FAILED_EVAL) {
2098
+ const outProps = getProps({ [key]: value }, true, `attr.${key}`);
2099
+ const outKey = Object.keys(outProps)[0];
2100
+ if (outKey) {
2101
+ const outVal = outProps[outKey];
2102
+ attr.value = t.jsxAttribute(t.jsxIdentifier(outKey), t.jsxExpressionContainer(typeof outVal === 'string'
2103
+ ? t.stringLiteral(outVal)
2104
+ : literalToAst(outVal)));
2105
+ }
2106
+ }
2107
+ }
2108
+ }
2109
+ }
2110
+ }
2111
+ catch (err) {
2112
+ // any error de-opt
2113
+ getStyleError = err;
2114
+ }
2115
+ }
2116
+ if (shouldPrintDebug) {
2117
+ // prettier-ignore
2118
+ logger.info([
2119
+ ' - attrs (ternaries/combined):\n',
2120
+ logLines(attrs.map(attrStr).join(', ')),
2121
+ ].join(' '));
2122
+ }
2123
+ tm.mark('jsx-element-styles', !!shouldPrintDebug);
2124
+ if (getStyleError) {
2125
+ logger.info([' ⚠️ postprocessing error, deopt', getStyleError].join(' '));
2126
+ node.attributes = ogAttributes;
2127
+ return null;
2128
+ }
2129
+ // final lazy extra loop:
2130
+ const existingStyleKeys = new Set();
2131
+ for (let i = attrs.length - 1; i >= 0; i--) {
2132
+ const attr = attrs[i];
2133
+ // if flattening map inline props to proper flattened names
2134
+ if (shouldFlatten) {
2135
+ if (attr.type === 'attr') {
2136
+ if (t.isJSXAttribute(attr.value)) {
2137
+ if (t.isJSXIdentifier(attr.value.name)) {
2138
+ const name = attr.value.name.name;
2139
+ if (INLINE_EXTRACTABLE[name]) {
2140
+ // map to HTML only name
2141
+ attr.value.name.name = INLINE_EXTRACTABLE[name];
2142
+ }
2143
+ }
2144
+ }
2145
+ }
2146
+ }
2147
+ // remove duplicate styles
2148
+ // so if you have:
2149
+ // style({ color: 'red' }), ...someProps, style({ color: 'green' })
2150
+ // this will mutate:
2151
+ // style({}), ...someProps, style({ color: 'green' })
2152
+ if (attr.type === 'style') {
2153
+ for (const key in attr.value) {
2154
+ if (existingStyleKeys.has(key)) {
2155
+ if (shouldPrintDebug) {
2156
+ logger.info([` >> delete existing ${key}`].join(' '));
2157
+ }
2158
+ delete attr.value[key];
2159
+ }
2160
+ else {
2161
+ existingStyleKeys.add(key);
2162
+ }
2163
+ }
2164
+ }
2165
+ }
2166
+ attrs = attrs.filter(Boolean);
2167
+ // inlineWhenUnflattened
2168
+ if (!shouldFlatten) {
2169
+ if (inlineWhenUnflattened.size) {
2170
+ for (const [index, attr] of attrs.entries()) {
2171
+ if (attr.type === 'style') {
2172
+ for (const key in attr.value) {
2173
+ if (!inlineWhenUnflattened.has(key))
2174
+ continue;
2175
+ const val = inlineWhenUnflattenedOGVals[key];
2176
+ if (val) {
2177
+ // delete the style
2178
+ delete attr.value[key];
2179
+ // and insert it before
2180
+ attrs.splice(index - 1, 0, val.attr);
2181
+ }
2182
+ else {
2183
+ // just delete it, it was added during expansion but should be left inline
2184
+ delete attr.value[key];
2185
+ }
2186
+ }
2187
+ }
2188
+ }
2189
+ }
2190
+ }
2191
+ // delete empty styles:
2192
+ attrs = attrs.filter((x) => {
2193
+ if (x.type === 'style' && Object.keys(x.value).length === 0) {
2194
+ return false;
2195
+ }
2196
+ return true;
2197
+ });
2198
+ const isNativeNotFlat = !shouldFlatten && platform === 'native';
2199
+ if (isNativeNotFlat) {
2200
+ if (shouldPrintDebug) {
2201
+ logger.info(`Disabled flattening except for simple cases on native for now: ${JSON.stringify({
2202
+ flatNode: flatNodeName,
2203
+ shouldDeopt,
2204
+ canFlattenProps,
2205
+ hasSpread,
2206
+ 'staticConfig.isStyledHOC': staticConfig.isStyledHOC,
2207
+ '!staticConfig.isHOC': !staticConfig.isHOC,
2208
+ 'staticConfig.isReactNative': staticConfig.isReactNative,
2209
+ 'staticConfig.neverFlatten': staticConfig.neverFlatten,
2210
+ }, null, 2)}`);
2211
+ }
2212
+ node.attributes = ogAttributes;
2213
+ return null;
2214
+ }
2215
+ if (shouldPrintDebug) {
2216
+ // prettier-ignore
2217
+ logger.info([
2218
+ ` - inlined props (${inlined.size}):`,
2219
+ shouldDeopt ? ' deopted' : '',
2220
+ hasSpread ? ' has spread' : '',
2221
+ staticConfig.neverFlatten ? 'neverFlatten' : '',
2222
+ ].join(' '));
2223
+ logger.info(` - attrs (end):\n ${logLines(attrs.map(attrStr).join(', '))}`);
2224
+ }
2225
+ onExtractTag({
2226
+ parserProps: propsWithFileInfo,
2227
+ attrs,
2228
+ node,
2229
+ lineNumbers,
2230
+ filePath,
2231
+ config: hanzoguiConfig,
2232
+ flatNodeName,
2233
+ attemptEval,
2234
+ jsxPath: traversePath,
2235
+ originalNodeName,
2236
+ programPath: programPath,
2237
+ completeProps,
2238
+ staticConfig,
2239
+ });
2240
+ if (shouldFlatten) {
2241
+ if (shouldPrintDebug) {
2242
+ logger.info([' [✅] flattened', originalNodeName, flatNodeName].join(' '));
2243
+ }
2244
+ // Only rename if onExtractTag hasn't already renamed to a custom wrapper
2245
+ // @ts-ignore - check if already renamed by callback (e.g., to a styled wrapper)
2246
+ const currentName = node.name?.name;
2247
+ if (!currentName ||
2248
+ currentName === originalNodeName ||
2249
+ currentName.startsWith('__ReactNative')) {
2250
+ // @ts-ignore
2251
+ node.name.name = flatNodeName;
2252
+ if (closingElement) {
2253
+ // @ts-ignore
2254
+ closingElement.name.name = flatNodeName;
2255
+ }
2256
+ }
2257
+ res.flattened++;
2258
+ }
2259
+ }
2260
+ catch (err) {
2261
+ node.attributes = ogAttributes;
2262
+ if (!(err instanceof BailOptimizationError)) {
2263
+ console.error(`@hanzogui/static error, reverting optimization. In ${filePath} ${lineNumbers} on ${originalNodeName}: ${err.message}. For stack trace set environment GUI_DEBUG=1`);
2264
+ if (process.env.GUI_DEBUG === '1') {
2265
+ console.error(err.stack);
2266
+ }
2267
+ }
2268
+ }
2269
+ finally {
2270
+ if (debugPropValue) {
2271
+ shouldPrintDebug = ogDebug;
2272
+ }
2273
+ }
2274
+ },
2275
+ });
2276
+ tm.mark('jsx-done', !!shouldPrintDebug);
2277
+ tm.done(shouldPrintDebug === 'verbose');
2278
+ return res;
2279
+ }
2280
+ }
2281
+ //# sourceMappingURL=createExtractor.js.map