@tamagui/static 1.0.0-beta.8 → 1.0.1-beta.100

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 (244) hide show
  1. package/dist/cjs/extractor/accessSafe.js +0 -2
  2. package/dist/cjs/extractor/accessSafe.js.map +1 -1
  3. package/dist/cjs/extractor/babelParse.js +15 -16
  4. package/dist/cjs/extractor/babelParse.js.map +2 -2
  5. package/dist/cjs/extractor/buildClassName.js +0 -2
  6. package/dist/cjs/extractor/buildClassName.js.map +1 -1
  7. package/dist/cjs/extractor/createEvaluator.js +9 -7
  8. package/dist/cjs/extractor/createEvaluator.js.map +2 -2
  9. package/dist/cjs/extractor/createExtractor.js +318 -145
  10. package/dist/cjs/extractor/createExtractor.js.map +2 -2
  11. package/dist/cjs/extractor/ensureImportingConcat.js +0 -2
  12. package/dist/cjs/extractor/ensureImportingConcat.js.map +1 -1
  13. package/dist/cjs/extractor/evaluateAstNode.js +0 -2
  14. package/dist/cjs/extractor/evaluateAstNode.js.map +1 -1
  15. package/dist/cjs/extractor/extractHelpers.js +11 -16
  16. package/dist/cjs/extractor/extractHelpers.js.map +1 -1
  17. package/dist/cjs/extractor/extractMediaStyle.js +3 -8
  18. package/dist/cjs/extractor/extractMediaStyle.js.map +2 -2
  19. package/dist/cjs/extractor/extractToClassNames.js +27 -42
  20. package/dist/cjs/extractor/extractToClassNames.js.map +2 -2
  21. package/dist/cjs/extractor/findTopmostFunction.js +1 -3
  22. package/dist/cjs/extractor/findTopmostFunction.js.map +1 -1
  23. package/dist/cjs/extractor/generatedUid.js +0 -2
  24. package/dist/cjs/extractor/generatedUid.js.map +1 -1
  25. package/dist/cjs/extractor/getPrefixLogs.js +0 -2
  26. package/dist/cjs/extractor/getPrefixLogs.js.map +1 -1
  27. package/dist/cjs/extractor/getPropValueFromAttributes.js +0 -2
  28. package/dist/cjs/extractor/getPropValueFromAttributes.js.map +1 -1
  29. package/dist/cjs/extractor/getSourceModule.js +0 -2
  30. package/dist/cjs/extractor/getSourceModule.js.map +1 -1
  31. package/dist/cjs/extractor/getStaticBindingsForScope.js +1 -5
  32. package/dist/cjs/extractor/getStaticBindingsForScope.js.map +1 -1
  33. package/dist/cjs/extractor/hoistClassNames.js +0 -3
  34. package/dist/cjs/extractor/hoistClassNames.js.map +1 -1
  35. package/dist/cjs/extractor/literalToAst.js +0 -4
  36. package/dist/cjs/extractor/literalToAst.js.map +1 -1
  37. package/dist/cjs/extractor/loadTamagui.js +43 -10
  38. package/dist/cjs/extractor/loadTamagui.js.map +2 -2
  39. package/dist/cjs/extractor/logLines.js +2 -3
  40. package/dist/cjs/extractor/logLines.js.map +1 -1
  41. package/dist/cjs/extractor/normalizeTernaries.js +0 -2
  42. package/dist/cjs/extractor/normalizeTernaries.js.map +1 -1
  43. package/dist/cjs/extractor/removeUnusedHooks.js +2 -4
  44. package/dist/cjs/extractor/removeUnusedHooks.js.map +1 -1
  45. package/dist/cjs/extractor/timer.js +2 -3
  46. package/dist/cjs/extractor/timer.js.map +1 -1
  47. package/dist/cjs/extractor/validHTMLAttributes.js +51 -0
  48. package/dist/cjs/extractor/validHTMLAttributes.js.map +2 -2
  49. package/dist/cjs/index.js +2 -1
  50. package/dist/cjs/index.js.map +2 -2
  51. package/dist/cjs/types.js.map +1 -1
  52. package/dist/esm/extractor/accessSafe.js +0 -3
  53. package/dist/esm/extractor/accessSafe.js.map +1 -1
  54. package/dist/esm/extractor/babelParse.js +15 -17
  55. package/dist/esm/extractor/babelParse.js.map +2 -2
  56. package/dist/esm/extractor/buildClassName.js +0 -3
  57. package/dist/esm/extractor/buildClassName.js.map +1 -1
  58. package/dist/esm/extractor/createEvaluator.js +9 -8
  59. package/dist/esm/extractor/createEvaluator.js.map +2 -2
  60. package/dist/esm/extractor/createExtractor.js +405 -195
  61. package/dist/esm/extractor/createExtractor.js.map +2 -2
  62. package/dist/esm/extractor/ensureImportingConcat.js +0 -3
  63. package/dist/esm/extractor/ensureImportingConcat.js.map +1 -1
  64. package/dist/esm/extractor/evaluateAstNode.js +0 -3
  65. package/dist/esm/extractor/evaluateAstNode.js.map +1 -1
  66. package/dist/esm/extractor/extractHelpers.js +11 -17
  67. package/dist/esm/extractor/extractHelpers.js.map +1 -1
  68. package/dist/esm/extractor/extractMediaStyle.js +29 -20
  69. package/dist/esm/extractor/extractMediaStyle.js.map +2 -2
  70. package/dist/esm/extractor/extractToClassNames.js +53 -52
  71. package/dist/esm/extractor/extractToClassNames.js.map +2 -2
  72. package/dist/esm/extractor/findTopmostFunction.js +1 -4
  73. package/dist/esm/extractor/findTopmostFunction.js.map +1 -1
  74. package/dist/esm/extractor/generatedUid.js +0 -3
  75. package/dist/esm/extractor/generatedUid.js.map +1 -1
  76. package/dist/esm/extractor/getPrefixLogs.js +1 -5
  77. package/dist/esm/extractor/getPrefixLogs.js.map +1 -1
  78. package/dist/esm/extractor/getPropValueFromAttributes.js +0 -3
  79. package/dist/esm/extractor/getPropValueFromAttributes.js.map +1 -1
  80. package/dist/esm/extractor/getSourceModule.js +0 -3
  81. package/dist/esm/extractor/getSourceModule.js.map +1 -1
  82. package/dist/esm/extractor/getStaticBindingsForScope.js +1 -6
  83. package/dist/esm/extractor/getStaticBindingsForScope.js.map +1 -1
  84. package/dist/esm/extractor/hoistClassNames.js +0 -4
  85. package/dist/esm/extractor/hoistClassNames.js.map +1 -1
  86. package/dist/esm/extractor/literalToAst.js +21 -11
  87. package/dist/esm/extractor/literalToAst.js.map +1 -1
  88. package/dist/esm/extractor/loadTamagui.js +44 -11
  89. package/dist/esm/extractor/loadTamagui.js.map +2 -2
  90. package/dist/esm/extractor/logLines.js +2 -4
  91. package/dist/esm/extractor/logLines.js.map +1 -1
  92. package/dist/esm/extractor/normalizeTernaries.js +35 -9
  93. package/dist/esm/extractor/normalizeTernaries.js.map +1 -1
  94. package/dist/esm/extractor/removeUnusedHooks.js +5 -9
  95. package/dist/esm/extractor/removeUnusedHooks.js.map +1 -1
  96. package/dist/esm/extractor/timer.js +2 -4
  97. package/dist/esm/extractor/timer.js.map +1 -1
  98. package/dist/esm/extractor/validHTMLAttributes.js +50 -0
  99. package/dist/esm/extractor/validHTMLAttributes.js.map +2 -2
  100. package/dist/esm/index.js +2 -1
  101. package/dist/esm/index.js.map +2 -2
  102. package/dist/jsx/constants.js +1 -0
  103. package/dist/jsx/constants.js.map +7 -0
  104. package/dist/jsx/extractor/accessSafe.js +1 -3
  105. package/dist/jsx/extractor/accessSafe.js.map +7 -0
  106. package/dist/jsx/extractor/babelParse.js +16 -17
  107. package/dist/jsx/extractor/babelParse.js.map +7 -0
  108. package/dist/jsx/extractor/buildClassName.js +1 -3
  109. package/dist/jsx/extractor/buildClassName.js.map +7 -0
  110. package/dist/jsx/extractor/createEvaluator.js +10 -8
  111. package/dist/jsx/extractor/createEvaluator.js.map +7 -0
  112. package/dist/jsx/extractor/createExtractor.js +325 -150
  113. package/dist/jsx/extractor/createExtractor.js.map +7 -0
  114. package/dist/jsx/extractor/ensureImportingConcat.js +1 -3
  115. package/dist/jsx/extractor/ensureImportingConcat.js.map +7 -0
  116. package/dist/jsx/extractor/evaluateAstNode.js +1 -3
  117. package/dist/jsx/extractor/evaluateAstNode.js.map +7 -0
  118. package/dist/jsx/extractor/extractHelpers.js +12 -17
  119. package/dist/jsx/extractor/extractHelpers.js.map +7 -0
  120. package/dist/jsx/extractor/extractMediaStyle.js +4 -9
  121. package/dist/jsx/extractor/extractMediaStyle.js.map +7 -0
  122. package/dist/jsx/extractor/extractToClassNames.js +31 -43
  123. package/dist/jsx/extractor/extractToClassNames.js.map +7 -0
  124. package/dist/jsx/extractor/findTopmostFunction.js +2 -4
  125. package/dist/jsx/extractor/findTopmostFunction.js.map +7 -0
  126. package/dist/jsx/extractor/generatedUid.js +1 -3
  127. package/dist/jsx/extractor/generatedUid.js.map +7 -0
  128. package/dist/jsx/extractor/getPrefixLogs.js +1 -3
  129. package/dist/jsx/extractor/getPrefixLogs.js.map +7 -0
  130. package/dist/jsx/extractor/getPropValueFromAttributes.js +1 -3
  131. package/dist/jsx/extractor/getPropValueFromAttributes.js.map +7 -0
  132. package/dist/jsx/extractor/getSourceModule.js +1 -3
  133. package/dist/jsx/extractor/getSourceModule.js.map +7 -0
  134. package/dist/jsx/extractor/getStaticBindingsForScope.js +2 -6
  135. package/dist/jsx/extractor/getStaticBindingsForScope.js.map +7 -0
  136. package/dist/jsx/extractor/hoistClassNames.js +1 -4
  137. package/dist/jsx/extractor/hoistClassNames.js.map +7 -0
  138. package/dist/jsx/extractor/literalToAst.js +1 -5
  139. package/dist/jsx/extractor/literalToAst.js.map +7 -0
  140. package/dist/jsx/extractor/loadTamagui.js +30 -11
  141. package/dist/jsx/extractor/loadTamagui.js.map +7 -0
  142. package/dist/jsx/extractor/logLines.js +3 -4
  143. package/dist/jsx/extractor/logLines.js.map +7 -0
  144. package/dist/jsx/extractor/normalizeTernaries.js +1 -3
  145. package/dist/jsx/extractor/normalizeTernaries.js.map +7 -0
  146. package/dist/jsx/extractor/removeUnusedHooks.js +3 -5
  147. package/dist/jsx/extractor/removeUnusedHooks.js.map +7 -0
  148. package/dist/jsx/extractor/timer.js +3 -4
  149. package/dist/jsx/extractor/timer.js.map +7 -0
  150. package/dist/jsx/extractor/validHTMLAttributes.js +51 -0
  151. package/dist/jsx/extractor/validHTMLAttributes.js.map +7 -0
  152. package/dist/jsx/index.js +3 -1
  153. package/dist/jsx/index.js.map +7 -0
  154. package/dist/jsx/types.js +1 -0
  155. package/dist/jsx/types.js.map +7 -0
  156. package/package.json +27 -19
  157. package/src/constants.ts +13 -0
  158. package/src/extractor/accessSafe.ts +18 -0
  159. package/src/extractor/babelParse.ts +27 -0
  160. package/src/extractor/buildClassName.ts +61 -0
  161. package/src/extractor/createEvaluator.ts +75 -0
  162. package/src/extractor/createExtractor.ts +1928 -0
  163. package/src/extractor/ensureImportingConcat.ts +39 -0
  164. package/src/extractor/evaluateAstNode.ts +121 -0
  165. package/src/extractor/extractHelpers.ts +119 -0
  166. package/src/extractor/extractMediaStyle.ts +192 -0
  167. package/src/extractor/extractToClassNames.ts +393 -0
  168. package/src/extractor/findTopmostFunction.ts +22 -0
  169. package/src/extractor/generatedUid.ts +43 -0
  170. package/src/extractor/getPrefixLogs.ts +6 -0
  171. package/src/extractor/getPropValueFromAttributes.ts +92 -0
  172. package/src/extractor/getSourceModule.ts +101 -0
  173. package/src/extractor/getStaticBindingsForScope.ts +183 -0
  174. package/src/extractor/hoistClassNames.ts +45 -0
  175. package/src/extractor/literalToAst.ts +84 -0
  176. package/src/extractor/loadTamagui.ts +145 -0
  177. package/src/extractor/logLines.ts +16 -0
  178. package/src/extractor/normalizeTernaries.ts +63 -0
  179. package/src/extractor/removeUnusedHooks.ts +76 -0
  180. package/src/extractor/timer.ts +18 -0
  181. package/src/extractor/validHTMLAttributes.ts +99 -0
  182. package/src/index.ts +10 -0
  183. package/src/types.ts +96 -0
  184. package/types/extractor/buildClassName.d.ts +0 -0
  185. package/types/extractor/buildClassName.d.ts.map +0 -0
  186. package/types/extractor/createEvaluator.d.ts +1 -1
  187. package/types/extractor/createEvaluator.d.ts.map +1 -1
  188. package/types/extractor/createExtractor.d.ts +3 -4
  189. package/types/extractor/createExtractor.d.ts.map +1 -1
  190. package/types/extractor/extractHelpers.d.ts +1 -1
  191. package/types/extractor/extractHelpers.d.ts.map +1 -1
  192. package/types/extractor/extractMediaStyle.d.ts +0 -0
  193. package/types/extractor/extractMediaStyle.d.ts.map +1 -1
  194. package/types/extractor/extractToClassNames.d.ts +1 -6
  195. package/types/extractor/extractToClassNames.d.ts.map +1 -1
  196. package/types/extractor/getPrefixLogs.d.ts +0 -0
  197. package/types/extractor/getPrefixLogs.d.ts.map +0 -0
  198. package/types/extractor/loadTamagui.d.ts +10 -4
  199. package/types/extractor/loadTamagui.d.ts.map +1 -1
  200. package/types/extractor/normalizeTernaries.d.ts +0 -0
  201. package/types/extractor/normalizeTernaries.d.ts.map +0 -0
  202. package/types/index.d.ts +2 -1
  203. package/types/index.d.ts.map +1 -1
  204. package/types/types.d.ts +6 -7
  205. package/types/types.d.ts.map +1 -1
  206. package/dist/cjs/patchReactNativeWeb.js +0 -167
  207. package/dist/cjs/patchReactNativeWeb.js.map +0 -7
  208. package/dist/esm/patchReactNativeWeb.js +0 -142
  209. package/dist/esm/patchReactNativeWeb.js.map +0 -7
  210. package/dist/jsx/patchReactNativeWeb.js +0 -141
  211. package/types/constants.d.ts +0 -6
  212. package/types/constants.d.ts.map +0 -1
  213. package/types/extractor/accessSafe.d.ts +0 -3
  214. package/types/extractor/accessSafe.d.ts.map +0 -1
  215. package/types/extractor/babelParse.d.ts +0 -5
  216. package/types/extractor/babelParse.d.ts.map +0 -1
  217. package/types/extractor/ensureImportingConcat.d.ts +0 -4
  218. package/types/extractor/ensureImportingConcat.d.ts.map +0 -1
  219. package/types/extractor/evaluateAstNode.d.ts +0 -3
  220. package/types/extractor/evaluateAstNode.d.ts.map +0 -1
  221. package/types/extractor/findTopmostFunction.d.ts +0 -4
  222. package/types/extractor/findTopmostFunction.d.ts.map +0 -1
  223. package/types/extractor/generatedUid.d.ts +0 -5
  224. package/types/extractor/generatedUid.d.ts.map +0 -1
  225. package/types/extractor/getPropValueFromAttributes.d.ts +0 -3
  226. package/types/extractor/getPropValueFromAttributes.d.ts.map +0 -1
  227. package/types/extractor/getSourceModule.d.ts +0 -16
  228. package/types/extractor/getSourceModule.d.ts.map +0 -1
  229. package/types/extractor/getStaticBindingsForScope.d.ts +0 -4
  230. package/types/extractor/getStaticBindingsForScope.d.ts.map +0 -1
  231. package/types/extractor/hoistClassNames.d.ts +0 -6
  232. package/types/extractor/hoistClassNames.d.ts.map +0 -1
  233. package/types/extractor/literalToAst.d.ts +0 -4
  234. package/types/extractor/literalToAst.d.ts.map +0 -1
  235. package/types/extractor/logLines.d.ts +0 -2
  236. package/types/extractor/logLines.d.ts.map +0 -1
  237. package/types/extractor/removeUnusedHooks.d.ts +0 -3
  238. package/types/extractor/removeUnusedHooks.d.ts.map +0 -1
  239. package/types/extractor/timer.d.ts +0 -5
  240. package/types/extractor/timer.d.ts.map +0 -1
  241. package/types/extractor/validHTMLAttributes.d.ts +0 -49
  242. package/types/extractor/validHTMLAttributes.d.ts.map +0 -1
  243. package/types/patchReactNativeWeb.d.ts +0 -2
  244. package/types/patchReactNativeWeb.d.ts.map +0 -1
@@ -0,0 +1,183 @@
1
+ import { dirname, extname, resolve } from 'path'
2
+
3
+ import { Binding, NodePath } from '@babel/traverse'
4
+ import * as t from '@babel/types'
5
+ import { existsSync } from 'fs-extra'
6
+
7
+ import { evaluateAstNode } from './evaluateAstNode'
8
+ import { getSourceModule } from './getSourceModule'
9
+
10
+ const isLocalImport = (path: string) => path.startsWith('.') || path.startsWith('/')
11
+
12
+ function resolveImportPath(sourcePath: string, path: string) {
13
+ const sourceDir = dirname(sourcePath)
14
+ if (isLocalImport(path)) {
15
+ if (extname(path) === '') {
16
+ path += '.js'
17
+ }
18
+ return resolve(sourceDir, path)
19
+ }
20
+ return path
21
+ }
22
+
23
+ function importModule(path: string) {
24
+ const filenames = [path.replace('.js', '.tsx'), path.replace('.js', '.ts'), path]
25
+ for (const file of filenames) {
26
+ if (existsSync(file)) {
27
+ const { unregister } = require('esbuild-register/dist/node').register({
28
+ target: 'es2019',
29
+ format: 'cjs',
30
+ })
31
+ try {
32
+ // TODO we can clear this when we see updates on it later on
33
+ return require(file)
34
+ } catch {
35
+ // doesn't exists
36
+ } finally {
37
+ unregister()
38
+ }
39
+ }
40
+ }
41
+ return null
42
+ }
43
+
44
+ export function getStaticBindingsForScope(
45
+ scope: NodePath<t.JSXElement>['scope'],
46
+ whitelist: string[] = [],
47
+ sourcePath: string,
48
+ bindingCache: Record<string, string | null>,
49
+ shouldPrintDebug: boolean | 'verbose'
50
+ ): Record<string, any> {
51
+ const bindings: Record<string, Binding> = scope.getAllBindings() as any
52
+ const ret: Record<string, any> = {}
53
+
54
+ if (shouldPrintDebug) {
55
+ // prettier-ignore
56
+ console.log(' ', Object.keys(bindings).length, 'variables in scope')
57
+ // .map(x => bindings[x].identifier?.name).join(', ')
58
+ }
59
+
60
+ // on react native at least it doesnt find some bindings? not sure why
61
+ // lets add in whitelisted imports if they exist
62
+ const program = scope.getProgramParent().block as t.Program
63
+ for (const node of program.body) {
64
+ if (t.isImportDeclaration(node)) {
65
+ const importPath = node.source.value
66
+ if (!node.specifiers.length) continue
67
+ if (!isLocalImport(importPath)) {
68
+ continue
69
+ }
70
+ const moduleName = resolveImportPath(sourcePath, importPath)
71
+ const isOnWhitelist = whitelist.some((test) => moduleName.endsWith(test))
72
+ if (!isOnWhitelist) continue
73
+ const src = importModule(moduleName)
74
+ if (!src) continue
75
+ for (const specifier of node.specifiers) {
76
+ if (t.isImportSpecifier(specifier) && t.isIdentifier(specifier.imported)) {
77
+ if (typeof src[specifier.imported.name] !== 'undefined') {
78
+ const val = src[specifier.local.name]
79
+ ret[specifier.local.name] = val
80
+ }
81
+ }
82
+ }
83
+ }
84
+ }
85
+
86
+ if (!bindingCache) {
87
+ throw new Error('bindingCache is a required param')
88
+ }
89
+
90
+ for (const k in bindings) {
91
+ const binding = bindings[k]
92
+
93
+ // check to see if the item is a module
94
+ const sourceModule = getSourceModule(k, binding)
95
+ if (sourceModule) {
96
+ if (!sourceModule.sourceModule) {
97
+ continue
98
+ }
99
+
100
+ const moduleName = resolveImportPath(sourcePath, sourceModule.sourceModule)
101
+ const isOnWhitelist = whitelist.some((test) => moduleName.endsWith(test))
102
+
103
+ // TODO we could cache this at the file level.. and check if its been touched since
104
+
105
+ if (isOnWhitelist) {
106
+ const src = importModule(moduleName)
107
+ if (!src) {
108
+ console.log(
109
+ `⚠️ missing file ${moduleName} via ${sourcePath} import ${sourceModule.sourceModule}?`
110
+ )
111
+ return {}
112
+ }
113
+ if (sourceModule.destructured) {
114
+ if (sourceModule.imported) {
115
+ ret[k] = src[sourceModule.imported]
116
+ }
117
+ } else {
118
+ // crude esmodule check
119
+ // TODO: make sure this actually works
120
+ // if (src && src.__esModule) {
121
+ // ret[k] = src.default
122
+ // } else {
123
+ ret[k] = src
124
+ // }
125
+ }
126
+ }
127
+ continue
128
+ }
129
+
130
+ const { parent, parentPath } = binding.path
131
+
132
+ if (!t.isVariableDeclaration(parent) || parent.kind !== 'const') {
133
+ continue
134
+ }
135
+
136
+ // pick out the right variable declarator
137
+ const dec = parent.declarations.find((d) => t.isIdentifier(d.id) && d.id.name === k)
138
+
139
+ // if init is not set, there's nothing to evaluate
140
+ // TODO: handle spread syntax
141
+ if (!dec || !dec.init) {
142
+ continue
143
+ }
144
+
145
+ // missing start/end will break caching
146
+ if (typeof dec.id.start !== 'number' || typeof dec.id.end !== 'number') {
147
+ console.error('dec.id.start/end is not a number')
148
+ continue
149
+ }
150
+
151
+ if (!t.isIdentifier(dec.id)) {
152
+ console.error('dec is not an identifier')
153
+ continue
154
+ }
155
+
156
+ const cacheKey = `${dec.id.name}_${dec.id.start}-${dec.id.end}`
157
+
158
+ // retrieve value from cache
159
+ if (bindingCache.hasOwnProperty(cacheKey)) {
160
+ ret[k] = bindingCache[cacheKey]
161
+ continue
162
+ }
163
+ // retrieve value from cache
164
+ if (bindingCache.hasOwnProperty(cacheKey)) {
165
+ ret[k] = bindingCache[cacheKey]
166
+ continue
167
+ }
168
+
169
+ // evaluate
170
+ try {
171
+ ret[k] = evaluateAstNode(dec.init, undefined, shouldPrintDebug)
172
+ bindingCache[cacheKey] = ret[k]
173
+ continue
174
+ } catch (e) {
175
+ // skip
176
+ // if (shouldPrintDebug) {
177
+ // console.error('[🐇] cant eval, skipping', cacheKey) //, e.message)
178
+ // }
179
+ }
180
+ }
181
+
182
+ return ret
183
+ }
@@ -0,0 +1,45 @@
1
+ import { NodePath } from '@babel/traverse'
2
+ import * as t from '@babel/types'
3
+
4
+ export function hoistClassNames(
5
+ path: NodePath<t.JSXElement>,
6
+ existing: { [key: string]: t.Identifier },
7
+ expr: t.Expression
8
+ ) {
9
+ const hoist = hoistClassNames.bind(null, path, existing)
10
+ if (t.isStringLiteral(expr)) {
11
+ if (expr.value.trim() === '') {
12
+ return expr
13
+ }
14
+ if (existing[expr.value]) {
15
+ return existing[expr.value]
16
+ }
17
+ const identifier = replaceStringWithVariable(expr)
18
+ existing[expr.value] = identifier
19
+ return identifier
20
+ }
21
+ if (t.isBinaryExpression(expr)) {
22
+ return t.binaryExpression(expr.operator, hoist(expr.left), hoist(expr.right))
23
+ }
24
+ if (t.isLogicalExpression(expr)) {
25
+ return t.logicalExpression(expr.operator, hoist(expr.left), hoist(expr.right))
26
+ }
27
+ if (t.isConditionalExpression(expr)) {
28
+ return t.conditionalExpression(expr.test, hoist(expr.consequent), hoist(expr.alternate))
29
+ }
30
+ return expr
31
+
32
+ function replaceStringWithVariable(str: t.StringLiteral): t.Identifier {
33
+ // hoist outside fn!
34
+ const uid = path.scope.generateUidIdentifier('cn')
35
+ const parent = path.findParent((path) => path.isProgram())
36
+ if (!parent) throw new Error(`no program?`)
37
+ const variable = t.variableDeclaration('const', [
38
+ // adding a space for extra safety
39
+ t.variableDeclarator(uid, t.stringLiteral(` ${str.value}`)),
40
+ ])
41
+ // @ts-ignore
42
+ parent.unshiftContainer('body', variable)
43
+ return uid
44
+ }
45
+ }
@@ -0,0 +1,84 @@
1
+ import * as t from '@babel/types'
2
+
3
+ export function literalToAst(literal: any): t.Expression {
4
+ if (literal === null) {
5
+ return t.nullLiteral()
6
+ }
7
+ switch (typeof literal) {
8
+ case 'function':
9
+ throw new Error('Unsupported')
10
+ case 'number':
11
+ return t.numericLiteral(literal)
12
+ case 'string':
13
+ return t.stringLiteral(literal)
14
+ case 'boolean':
15
+ return t.booleanLiteral(literal)
16
+ case 'undefined':
17
+ return t.unaryExpression('void', t.numericLiteral(0), true)
18
+ default:
19
+ if (Array.isArray(literal)) {
20
+ return t.arrayExpression(literal.map(literalToAst))
21
+ }
22
+ return t.objectExpression(
23
+ Object.keys(literal)
24
+ .filter((k) => {
25
+ return typeof literal[k] !== 'undefined'
26
+ })
27
+ .map((k) => {
28
+ return t.objectProperty(t.stringLiteral(k), literalToAst(literal[k]))
29
+ })
30
+ )
31
+ }
32
+ }
33
+
34
+ const easyPeasies = ['BooleanLiteral', 'StringLiteral', 'NumericLiteral']
35
+
36
+ export function astToLiteral(node: any) {
37
+ if (!node) {
38
+ return
39
+ }
40
+ if (easyPeasies.includes(node.type)) {
41
+ return node.value
42
+ }
43
+ if (node.name === 'undefined' && !node.value) {
44
+ return undefined
45
+ }
46
+ if (t.isNullLiteral(node)) {
47
+ return null
48
+ }
49
+ if (t.isObjectExpression(node)) {
50
+ return computeProps(node.properties)
51
+ }
52
+ if (t.isArrayExpression(node)) {
53
+ return node.elements.reduce(
54
+ // @ts-ignore
55
+ (acc, element) => [
56
+ ...acc,
57
+ ...(element?.type === 'SpreadElement'
58
+ ? astToLiteral(element.argument)
59
+ : [astToLiteral(element)]),
60
+ ],
61
+ []
62
+ )
63
+ }
64
+ }
65
+
66
+ function computeProps(props) {
67
+ return props.reduce((acc, prop) => {
68
+ if (prop.type === 'SpreadElement') {
69
+ return {
70
+ ...acc,
71
+ ...astToLiteral(prop.argument),
72
+ }
73
+ } else if (prop.type !== 'ObjectMethod') {
74
+ const val = astToLiteral(prop.value)
75
+ if (val !== undefined) {
76
+ return {
77
+ ...acc,
78
+ [prop.key.name]: val,
79
+ }
80
+ }
81
+ }
82
+ return acc
83
+ }, {})
84
+ }
@@ -0,0 +1,145 @@
1
+ import { join } from 'path'
2
+
3
+ import type { StaticConfig, TamaguiComponent, TamaguiInternalConfig } from '@tamagui/core'
4
+ import { createTamagui } from '@tamagui/core-node'
5
+
6
+ let loadedTamagui: any = null
7
+
8
+ type NameToPaths = {
9
+ [key: string]: Set<string>
10
+ }
11
+
12
+ export type TamaguiProjectInfo = {
13
+ components: Record<string, TamaguiComponent>
14
+ tamaguiConfig: TamaguiInternalConfig
15
+ nameToPaths: NameToPaths
16
+ }
17
+
18
+ export function loadTamagui(props: { components: string[]; config: string }): TamaguiProjectInfo {
19
+ if (loadedTamagui) {
20
+ return loadedTamagui
21
+ }
22
+
23
+ const configPath = join(process.cwd(), props.config)
24
+
25
+ const { unregister } = require('esbuild-register/dist/node').register({
26
+ target: 'es2019',
27
+ format: 'cjs',
28
+ })
29
+
30
+ try {
31
+ // lets shim require and avoid importing react-native + react-native-web
32
+ // we just need to read the config around them
33
+ process.env.IS_STATIC = 'is_static'
34
+ // @ts-ignore
35
+ if (typeof globalThis['__DEV__'] === 'undefined') {
36
+ // @ts-ignore
37
+ globalThis['__DEV__'] = process.env.NODE_ENV === 'development'
38
+ }
39
+
40
+ const proxyWorm = require('@tamagui/proxy-worm')
41
+ const rnw = require('react-native-web')
42
+ const Mod = require('module')
43
+ const og = Mod.prototype.require
44
+ const nameToPaths: NameToPaths = {}
45
+
46
+ Mod.prototype.require = function (path: string) {
47
+ if (path.endsWith('.css')) {
48
+ return {}
49
+ }
50
+ if (
51
+ path === '@gorhom/bottom-sheet' ||
52
+ path.startsWith('react-native-reanimated') ||
53
+ path === 'expo-linear-gradient'
54
+ ) {
55
+ return proxyWorm
56
+ }
57
+ if (
58
+ path.startsWith('react-native') &&
59
+ // allow our rnw.tsx imports through
60
+ !path.startsWith('react-native-web/dist/cjs/exports')
61
+ ) {
62
+ return rnw
63
+ }
64
+ try {
65
+ const out = og.apply(this, arguments)
66
+ if (!nameToPaths[path]) {
67
+ if (out && typeof out === 'object') {
68
+ for (const key in out) {
69
+ try {
70
+ const conf = out[key]?.staticConfig as StaticConfig
71
+ if (conf) {
72
+ if (conf.componentName) {
73
+ nameToPaths[conf.componentName] ??= new Set()
74
+ const fullName = path.startsWith('.')
75
+ ? join(`${this.path.replace(/dist(\/cjs)?/, 'src')}`, path)
76
+ : path
77
+ nameToPaths[conf.componentName].add(fullName)
78
+ } else {
79
+ // console.log('no name component', path)
80
+ }
81
+ }
82
+ } catch {
83
+ // ok
84
+ }
85
+ }
86
+ }
87
+ }
88
+ return out
89
+ } catch (err: any) {
90
+ console.error('Tamagui error loading file:\n', path, err.message, '\n', err.stack)
91
+ // avoid infinite loops
92
+ process.exit(1)
93
+ }
94
+ }
95
+
96
+ // import config
97
+ const exp = require(configPath)
98
+ const tamaguiConfig = (exp['default'] || exp) as TamaguiInternalConfig
99
+
100
+ if (!tamaguiConfig || !tamaguiConfig.parsed) {
101
+ try {
102
+ const confPath = require.resolve(configPath)
103
+ console.log(`Received:`, tamaguiConfig)
104
+ throw new Error(`Can't find valid config in ${confPath}`)
105
+ } catch (err) {
106
+ throw err
107
+ }
108
+ }
109
+
110
+ // import components
111
+ const components = {}
112
+ for (const moduleName of props.components) {
113
+ const exported = require(moduleName)
114
+ for (const Name in exported) {
115
+ const val = exported[Name]
116
+ const staticConfig = val?.staticConfig as StaticConfig | undefined
117
+ if (staticConfig) {
118
+ // remove non-stringifyable
119
+ const { Component, reactNativeWebComponent, ...sc } = staticConfig
120
+ Object.assign(components, { [Name]: { staticConfig: sc } })
121
+ }
122
+ }
123
+ }
124
+
125
+ // undo shims
126
+ process.env.IS_STATIC = undefined
127
+ Mod.prototype.require = og
128
+
129
+ // set up core-node
130
+ createTamagui(tamaguiConfig as any)
131
+
132
+ loadedTamagui = {
133
+ components,
134
+ tamaguiConfig,
135
+ nameToPaths,
136
+ }
137
+
138
+ return loadedTamagui
139
+ } catch (err) {
140
+ console.log('Error loading Tamagui', err)
141
+ throw err
142
+ } finally {
143
+ unregister()
144
+ }
145
+ }
@@ -0,0 +1,16 @@
1
+ const prefix = ' '
2
+
3
+ export const logLines = (str: string, singleLine = false) => {
4
+ if (singleLine) {
5
+ return prefix + str.split(' ').join(`\n${prefix}`)
6
+ }
7
+ let lines: string[] = ['']
8
+ const items = str.split(' ')
9
+ for (const item of items) {
10
+ if (item.length + lines[lines.length - 1].length > 85) {
11
+ lines.push('')
12
+ }
13
+ lines[lines.length - 1] += item + ' '
14
+ }
15
+ return lines.map((line, i) => prefix + (i == 0 ? '' : ' ') + line.trim()).join('\n')
16
+ }
@@ -0,0 +1,63 @@
1
+ import generate from '@babel/generator'
2
+ import * as t from '@babel/types'
3
+ import invariant from 'invariant'
4
+
5
+ import { Ternary } from '../types'
6
+
7
+ export function normalizeTernaries(ternaries: Ternary[]) {
8
+ invariant(
9
+ Array.isArray(ternaries),
10
+ 'extractStaticTernaries expects param 1 to be an array of ternaries'
11
+ )
12
+
13
+ if (ternaries.length === 0) {
14
+ return []
15
+ }
16
+
17
+ const ternariesByKey: { [key: string]: Ternary } = {}
18
+
19
+ for (let idx = -1, len = ternaries.length; ++idx < len; ) {
20
+ const { test, consequent, alternate, remove, ...rest } = ternaries[idx]
21
+
22
+ let ternaryTest = test
23
+
24
+ // strip parens
25
+ if (t.isExpressionStatement(test)) {
26
+ ternaryTest = (test as any).expression
27
+ }
28
+
29
+ // convert `!thing` to `thing` with swapped consequent and alternate
30
+ let shouldSwap = false
31
+ if (t.isUnaryExpression(test) && test.operator === '!') {
32
+ ternaryTest = test.argument
33
+ shouldSwap = true
34
+ } else if (t.isBinaryExpression(test)) {
35
+ if (test.operator === '!==' || test.operator === '!=') {
36
+ ternaryTest = t.binaryExpression(test.operator, test.left, test.right)
37
+ shouldSwap = true
38
+ }
39
+ }
40
+
41
+ const key = generate(ternaryTest).code
42
+
43
+ if (!ternariesByKey[key]) {
44
+ ternariesByKey[key] = {
45
+ ...rest,
46
+ alternate: {},
47
+ consequent: {},
48
+ test: ternaryTest,
49
+ remove,
50
+ }
51
+ }
52
+ const altStyle = (shouldSwap ? consequent : alternate) ?? {}
53
+ const consStyle = (shouldSwap ? alternate : consequent) ?? {}
54
+ Object.assign(ternariesByKey[key].alternate!, altStyle)
55
+ Object.assign(ternariesByKey[key].consequent!, consStyle)
56
+ }
57
+
58
+ const ternaryExpression = Object.keys(ternariesByKey).map((key) => {
59
+ return ternariesByKey[key]
60
+ })
61
+
62
+ return ternaryExpression
63
+ }
@@ -0,0 +1,76 @@
1
+ import { NodePath } from '@babel/traverse'
2
+ import * as t from '@babel/types'
3
+
4
+ const hooks = {
5
+ useMedia: true,
6
+ useTheme: true,
7
+ }
8
+
9
+ export function removeUnusedHooks(compFn: NodePath<any>, shouldPrintDebug: boolean | 'verbose') {
10
+ compFn.scope.crawl()
11
+ // check the top level statements
12
+ let bodyStatements = compFn?.get('body')
13
+ if (!bodyStatements) {
14
+ console.log('no body statemnts?', compFn)
15
+ return
16
+ }
17
+ if (!Array.isArray(bodyStatements)) {
18
+ if (bodyStatements.isFunctionExpression()) {
19
+ bodyStatements = bodyStatements.scope.path.get('body')
20
+ } else {
21
+ bodyStatements = bodyStatements.get('body')
22
+ }
23
+ }
24
+ if (!bodyStatements || !Array.isArray(bodyStatements)) {
25
+ return
26
+ }
27
+ const statements = bodyStatements as NodePath<any>[]
28
+ for (const statement of statements) {
29
+ if (!statement.isVariableDeclaration()) {
30
+ continue
31
+ }
32
+ const declarations = statement.get('declarations')
33
+ if (!Array.isArray(declarations)) {
34
+ continue
35
+ }
36
+ const isBindingReferenced = (name: string) => {
37
+ return !!statement.scope.getBinding(name)?.referenced
38
+ }
39
+ for (const declarator of declarations) {
40
+ const id = declarator.get('id')
41
+ const init = declarator.node.init
42
+ if (Array.isArray(id) || Array.isArray(init)) {
43
+ continue
44
+ }
45
+ const shouldRemove = (() => {
46
+ const isHook =
47
+ t.isCallExpression(init) && t.isIdentifier(init.callee) && hooks[init.callee.name]
48
+ if (!isHook) {
49
+ return false
50
+ }
51
+ if (t.isIdentifier(id.node)) {
52
+ // remove "const media = useMedia()"
53
+ const name = id.node.name
54
+ return !isBindingReferenced(name)
55
+ } else if (t.isObjectPattern(id.node)) {
56
+ // remove "const { sm } = useMedia()"
57
+ const propPaths = id.get('properties') as NodePath<any>[]
58
+ return propPaths.every((prop) => {
59
+ if (!prop.isObjectProperty()) return false
60
+ const value = prop.get('value')
61
+ if (Array.isArray(value) || !value.isIdentifier()) return false
62
+ const name = value.node.name
63
+ return !isBindingReferenced(name)
64
+ })
65
+ }
66
+ return false
67
+ })()
68
+ if (shouldRemove) {
69
+ declarator.remove()
70
+ if (shouldPrintDebug) {
71
+ console.log(` [🪝] removed ${id.node['name'] ?? ''}`)
72
+ }
73
+ }
74
+ }
75
+ }
76
+ }
@@ -0,0 +1,18 @@
1
+ export const timer = () => {
2
+ const start = Date.now()
3
+ let last = start
4
+ return {
5
+ mark: (name: string, print = false) => {
6
+ if (print) {
7
+ const took = Date.now() - last
8
+ last = Date.now()
9
+ console.log(`Time ${name}: ${took}ms`)
10
+ }
11
+ },
12
+ done: (print = false) => {
13
+ if (print) {
14
+ console.log(`Total time: ${Date.now() - start}ms`)
15
+ }
16
+ },
17
+ }
18
+ }