@tamagui/static 1.0.1-beta.18 → 1.0.1-beta.180

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 (250) hide show
  1. package/dist/{cjs/constants.js → constants.js} +9 -1
  2. package/dist/constants.js.map +7 -0
  3. package/dist/{cjs/extractor → extractor}/accessSafe.js +14 -4
  4. package/dist/{esm/extractor → extractor}/accessSafe.js.map +2 -2
  5. package/dist/{cjs/extractor → extractor}/babelParse.js +20 -17
  6. package/dist/extractor/babelParse.js.map +7 -0
  7. package/dist/{cjs/extractor → extractor}/buildClassName.js +20 -6
  8. package/dist/extractor/buildClassName.js.map +7 -0
  9. package/dist/{cjs/extractor → extractor}/createEvaluator.js +17 -12
  10. package/dist/extractor/createEvaluator.js.map +7 -0
  11. package/dist/extractor/createExtractor.js +1560 -0
  12. package/dist/extractor/createExtractor.js.map +7 -0
  13. package/dist/{cjs/extractor → extractor}/ensureImportingConcat.js +22 -8
  14. package/dist/extractor/ensureImportingConcat.js.map +7 -0
  15. package/dist/{cjs/extractor → extractor}/evaluateAstNode.js +14 -6
  16. package/dist/{esm/extractor → extractor}/evaluateAstNode.js.map +2 -2
  17. package/dist/{cjs/extractor → extractor}/extractHelpers.js +20 -19
  18. package/dist/extractor/extractHelpers.js.map +7 -0
  19. package/dist/{cjs/extractor → extractor}/extractMediaStyle.js +38 -39
  20. package/dist/extractor/extractMediaStyle.js.map +7 -0
  21. package/dist/{cjs/extractor → extractor}/extractToClassNames.js +164 -101
  22. package/dist/extractor/extractToClassNames.js.map +7 -0
  23. package/dist/{cjs/extractor → extractor}/findTopmostFunction.js +2 -3
  24. package/dist/{esm/extractor → extractor}/findTopmostFunction.js.map +2 -2
  25. package/dist/{cjs/extractor → extractor}/generatedUid.js +9 -4
  26. package/dist/{cjs/extractor → extractor}/generatedUid.js.map +3 -3
  27. package/dist/{cjs/extractor → extractor}/getPrefixLogs.js +1 -2
  28. package/dist/extractor/getPrefixLogs.js.map +7 -0
  29. package/dist/{cjs/extractor → extractor}/getPropValueFromAttributes.js +24 -15
  30. package/dist/extractor/getPropValueFromAttributes.js.map +7 -0
  31. package/dist/{cjs/extractor → extractor}/getSourceModule.js +5 -3
  32. package/dist/{esm/extractor → extractor}/getSourceModule.js.map +2 -2
  33. package/dist/{cjs/extractor → extractor}/getStaticBindingsForScope.js +88 -38
  34. package/dist/extractor/getStaticBindingsForScope.js.map +7 -0
  35. package/dist/{cjs/extractor → extractor}/hoistClassNames.js +5 -4
  36. package/dist/{esm/extractor → extractor}/hoistClassNames.js.map +3 -3
  37. package/dist/{cjs/extractor → extractor}/literalToAst.js +26 -34
  38. package/dist/{cjs/extractor → extractor}/literalToAst.js.map +2 -2
  39. package/dist/extractor/loadFile.js +21 -0
  40. package/dist/extractor/loadFile.js.map +7 -0
  41. package/dist/extractor/loadTamagui.js +327 -0
  42. package/dist/extractor/loadTamagui.js.map +7 -0
  43. package/dist/{cjs/extractor → extractor}/logLines.js +3 -3
  44. package/dist/{cjs/extractor → extractor}/logLines.js.map +2 -2
  45. package/dist/{cjs/extractor → extractor}/normalizeTernaries.js +13 -36
  46. package/dist/extractor/normalizeTernaries.js.map +7 -0
  47. package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js +7 -5
  48. package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js.map +2 -2
  49. package/dist/{cjs/extractor → extractor}/timer.js +11 -4
  50. package/dist/extractor/timer.js.map +7 -0
  51. package/dist/{cjs/extractor → extractor}/validHTMLAttributes.js +52 -0
  52. package/dist/extractor/validHTMLAttributes.js.map +7 -0
  53. package/dist/getPragmaOptions.js +68 -0
  54. package/dist/getPragmaOptions.js.map +7 -0
  55. package/dist/{cjs/index.js → index.js} +11 -7
  56. package/dist/index.js.map +7 -0
  57. package/dist/require.js +95 -0
  58. package/dist/require.js.map +7 -0
  59. package/dist/{cjs/types.js → types.js} +1 -0
  60. package/dist/types.js.map +7 -0
  61. package/dist/webpackPlugin.js +35 -0
  62. package/dist/webpackPlugin.js.map +7 -0
  63. package/package.json +44 -35
  64. package/src/constants.ts +15 -0
  65. package/src/extractor/accessSafe.ts +18 -0
  66. package/src/extractor/babelParse.ts +27 -0
  67. package/src/extractor/buildClassName.ts +61 -0
  68. package/src/extractor/createEvaluator.ts +73 -0
  69. package/src/extractor/createExtractor.ts +2032 -0
  70. package/src/extractor/ensureImportingConcat.ts +39 -0
  71. package/src/extractor/evaluateAstNode.ts +121 -0
  72. package/src/extractor/extractHelpers.ts +120 -0
  73. package/src/extractor/extractMediaStyle.ts +192 -0
  74. package/src/extractor/extractToClassNames.ts +456 -0
  75. package/src/extractor/findTopmostFunction.ts +22 -0
  76. package/src/extractor/generatedUid.ts +43 -0
  77. package/src/extractor/getPrefixLogs.ts +6 -0
  78. package/src/extractor/getPropValueFromAttributes.ts +92 -0
  79. package/src/extractor/getSourceModule.ts +101 -0
  80. package/src/extractor/getStaticBindingsForScope.ts +227 -0
  81. package/src/extractor/hoistClassNames.ts +45 -0
  82. package/src/extractor/literalToAst.ts +84 -0
  83. package/src/extractor/loadFile.ts +17 -0
  84. package/src/extractor/loadTamagui.ts +377 -0
  85. package/src/extractor/logLines.ts +16 -0
  86. package/src/extractor/normalizeTernaries.ts +63 -0
  87. package/src/extractor/removeUnusedHooks.ts +76 -0
  88. package/src/extractor/timer.ts +29 -0
  89. package/src/extractor/validHTMLAttributes.ts +99 -0
  90. package/src/getPragmaOptions.ts +52 -0
  91. package/src/index.ts +12 -0
  92. package/src/require.ts +112 -0
  93. package/src/types.ts +91 -0
  94. package/src/webpackPlugin.ts +9 -0
  95. package/tamagui.tsconfig.json +5 -0
  96. package/types/constants.d.ts +1 -0
  97. package/types/extractor/buildClassName.d.ts +1 -1
  98. package/types/extractor/createEvaluator.d.ts +2 -2
  99. package/types/extractor/createExtractor.d.ts +25 -10
  100. package/types/extractor/extractHelpers.d.ts +2 -2
  101. package/types/extractor/extractMediaStyle.d.ts +1 -1
  102. package/types/extractor/extractToClassNames.d.ts +4 -9
  103. package/types/extractor/findTopmostFunction.d.ts +1 -1
  104. package/types/extractor/getPrefixLogs.d.ts +1 -1
  105. package/types/extractor/getPropValueFromAttributes.d.ts +16 -0
  106. package/types/extractor/getStaticBindingsForScope.d.ts +2 -1
  107. package/types/extractor/loadFile.d.ts +1 -0
  108. package/types/extractor/loadTamagui.d.ts +15 -5
  109. package/types/extractor/normalizeTernaries.d.ts +1 -1
  110. package/types/extractor/validHTMLAttributes.d.ts +49 -0
  111. package/types/getPragmaOptions.d.ts +9 -0
  112. package/types/index.d.ts +10 -7
  113. package/types/require.d.ts +4 -0
  114. package/types/types.d.ts +25 -30
  115. package/types/webpackPlugin.d.ts +4 -0
  116. package/dist/cjs/constants.js.map +0 -7
  117. package/dist/cjs/extractor/accessSafe.js.map +0 -7
  118. package/dist/cjs/extractor/babelParse.js.map +0 -7
  119. package/dist/cjs/extractor/buildClassName.js.map +0 -7
  120. package/dist/cjs/extractor/createEvaluator.js.map +0 -7
  121. package/dist/cjs/extractor/createExtractor.js +0 -1221
  122. package/dist/cjs/extractor/createExtractor.js.map +0 -7
  123. package/dist/cjs/extractor/ensureImportingConcat.js.map +0 -7
  124. package/dist/cjs/extractor/evaluateAstNode.js.map +0 -7
  125. package/dist/cjs/extractor/extractHelpers.js.map +0 -7
  126. package/dist/cjs/extractor/extractMediaStyle.js.map +0 -7
  127. package/dist/cjs/extractor/extractToClassNames.js.map +0 -7
  128. package/dist/cjs/extractor/findTopmostFunction.js.map +0 -7
  129. package/dist/cjs/extractor/getPrefixLogs.js.map +0 -7
  130. package/dist/cjs/extractor/getPropValueFromAttributes.js.map +0 -7
  131. package/dist/cjs/extractor/getSourceModule.js.map +0 -7
  132. package/dist/cjs/extractor/getStaticBindingsForScope.js.map +0 -7
  133. package/dist/cjs/extractor/hoistClassNames.js.map +0 -7
  134. package/dist/cjs/extractor/loadTamagui.js +0 -106
  135. package/dist/cjs/extractor/loadTamagui.js.map +0 -7
  136. package/dist/cjs/extractor/normalizeTernaries.js.map +0 -7
  137. package/dist/cjs/extractor/timer.js.map +0 -7
  138. package/dist/cjs/extractor/validHTMLAttributes.js.map +0 -7
  139. package/dist/cjs/index.js.map +0 -7
  140. package/dist/cjs/patchReactNativeWeb.js +0 -167
  141. package/dist/cjs/patchReactNativeWeb.js.map +0 -7
  142. package/dist/cjs/types.js.map +0 -7
  143. package/dist/esm/constants.js +0 -14
  144. package/dist/esm/constants.js.map +0 -7
  145. package/dist/esm/extractor/accessSafe.js +0 -11
  146. package/dist/esm/extractor/babelParse.js +0 -30
  147. package/dist/esm/extractor/babelParse.js.map +0 -7
  148. package/dist/esm/extractor/buildClassName.js +0 -40
  149. package/dist/esm/extractor/buildClassName.js.map +0 -7
  150. package/dist/esm/extractor/createEvaluator.js +0 -52
  151. package/dist/esm/extractor/createEvaluator.js.map +0 -7
  152. package/dist/esm/extractor/createExtractor.js +0 -1169
  153. package/dist/esm/extractor/createExtractor.js.map +0 -7
  154. package/dist/esm/extractor/ensureImportingConcat.js +0 -24
  155. package/dist/esm/extractor/ensureImportingConcat.js.map +0 -7
  156. package/dist/esm/extractor/evaluateAstNode.js +0 -94
  157. package/dist/esm/extractor/extractHelpers.js +0 -103
  158. package/dist/esm/extractor/extractHelpers.js.map +0 -7
  159. package/dist/esm/extractor/extractMediaStyle.js +0 -152
  160. package/dist/esm/extractor/extractMediaStyle.js.map +0 -7
  161. package/dist/esm/extractor/extractToClassNames.js +0 -293
  162. package/dist/esm/extractor/extractToClassNames.js.map +0 -7
  163. package/dist/esm/extractor/findTopmostFunction.js +0 -23
  164. package/dist/esm/extractor/generatedUid.js +0 -28
  165. package/dist/esm/extractor/generatedUid.js.map +0 -7
  166. package/dist/esm/extractor/getPrefixLogs.js +0 -12
  167. package/dist/esm/extractor/getPrefixLogs.js.map +0 -7
  168. package/dist/esm/extractor/getPropValueFromAttributes.js +0 -49
  169. package/dist/esm/extractor/getPropValueFromAttributes.js.map +0 -7
  170. package/dist/esm/extractor/getSourceModule.js +0 -69
  171. package/dist/esm/extractor/getStaticBindingsForScope.js +0 -137
  172. package/dist/esm/extractor/getStaticBindingsForScope.js.map +0 -7
  173. package/dist/esm/extractor/hoistClassNames.js +0 -44
  174. package/dist/esm/extractor/literalToAst.js +0 -80
  175. package/dist/esm/extractor/literalToAst.js.map +0 -7
  176. package/dist/esm/extractor/loadTamagui.js +0 -84
  177. package/dist/esm/extractor/loadTamagui.js.map +0 -7
  178. package/dist/esm/extractor/logLines.js +0 -22
  179. package/dist/esm/extractor/logLines.js.map +0 -7
  180. package/dist/esm/extractor/normalizeTernaries.js +0 -53
  181. package/dist/esm/extractor/normalizeTernaries.js.map +0 -7
  182. package/dist/esm/extractor/removeUnusedHooks.js +0 -80
  183. package/dist/esm/extractor/removeUnusedHooks.js.map +0 -7
  184. package/dist/esm/extractor/timer.js +0 -24
  185. package/dist/esm/extractor/timer.js.map +0 -7
  186. package/dist/esm/extractor/validHTMLAttributes.js +0 -52
  187. package/dist/esm/extractor/validHTMLAttributes.js.map +0 -7
  188. package/dist/esm/index.js +0 -14
  189. package/dist/esm/index.js.map +0 -7
  190. package/dist/esm/patchReactNativeWeb.js +0 -142
  191. package/dist/esm/patchReactNativeWeb.js.map +0 -7
  192. package/dist/esm/types.js +0 -1
  193. package/dist/esm/types.js.map +0 -7
  194. package/dist/jsx/constants.js +0 -13
  195. package/dist/jsx/extractor/accessSafe.js +0 -10
  196. package/dist/jsx/extractor/babelParse.js +0 -29
  197. package/dist/jsx/extractor/buildClassName.js +0 -39
  198. package/dist/jsx/extractor/createEvaluator.js +0 -51
  199. package/dist/jsx/extractor/createExtractor.js +0 -1168
  200. package/dist/jsx/extractor/ensureImportingConcat.js +0 -23
  201. package/dist/jsx/extractor/evaluateAstNode.js +0 -93
  202. package/dist/jsx/extractor/extractHelpers.js +0 -102
  203. package/dist/jsx/extractor/extractMediaStyle.js +0 -151
  204. package/dist/jsx/extractor/extractToClassNames.js +0 -292
  205. package/dist/jsx/extractor/findTopmostFunction.js +0 -22
  206. package/dist/jsx/extractor/generatedUid.js +0 -27
  207. package/dist/jsx/extractor/getPrefixLogs.js +0 -11
  208. package/dist/jsx/extractor/getPropValueFromAttributes.js +0 -48
  209. package/dist/jsx/extractor/getSourceModule.js +0 -68
  210. package/dist/jsx/extractor/getStaticBindingsForScope.js +0 -136
  211. package/dist/jsx/extractor/hoistClassNames.js +0 -43
  212. package/dist/jsx/extractor/literalToAst.js +0 -79
  213. package/dist/jsx/extractor/loadTamagui.js +0 -83
  214. package/dist/jsx/extractor/logLines.js +0 -21
  215. package/dist/jsx/extractor/normalizeTernaries.js +0 -52
  216. package/dist/jsx/extractor/removeUnusedHooks.js +0 -79
  217. package/dist/jsx/extractor/timer.js +0 -23
  218. package/dist/jsx/extractor/validHTMLAttributes.js +0 -51
  219. package/dist/jsx/index.js +0 -13
  220. package/dist/jsx/patchReactNativeWeb.js +0 -141
  221. package/dist/jsx/types.js +0 -0
  222. package/types/constants.d.ts.map +0 -1
  223. package/types/extractor/accessSafe.d.ts.map +0 -1
  224. package/types/extractor/babelParse.d.ts.map +0 -1
  225. package/types/extractor/buildClassName.d.ts.map +0 -1
  226. package/types/extractor/createEvaluator.d.ts.map +0 -1
  227. package/types/extractor/createExtractor.d.ts.map +0 -1
  228. package/types/extractor/ensureImportingConcat.d.ts.map +0 -1
  229. package/types/extractor/evaluateAstNode.d.ts.map +0 -1
  230. package/types/extractor/extractHelpers.d.ts.map +0 -1
  231. package/types/extractor/extractMediaStyle.d.ts.map +0 -1
  232. package/types/extractor/extractToClassNames.d.ts.map +0 -1
  233. package/types/extractor/findTopmostFunction.d.ts.map +0 -1
  234. package/types/extractor/generatedUid.d.ts.map +0 -1
  235. package/types/extractor/getPrefixLogs.d.ts.map +0 -1
  236. package/types/extractor/getPropValueFromAttributes.d.ts.map +0 -1
  237. package/types/extractor/getSourceModule.d.ts.map +0 -1
  238. package/types/extractor/getStaticBindingsForScope.d.ts.map +0 -1
  239. package/types/extractor/hoistClassNames.d.ts.map +0 -1
  240. package/types/extractor/literalToAst.d.ts.map +0 -1
  241. package/types/extractor/loadTamagui.d.ts.map +0 -1
  242. package/types/extractor/logLines.d.ts.map +0 -1
  243. package/types/extractor/normalizeTernaries.d.ts.map +0 -1
  244. package/types/extractor/removeUnusedHooks.d.ts.map +0 -1
  245. package/types/extractor/timer.d.ts.map +0 -1
  246. package/types/extractor/validHTMLAttributes.d.ts.map +0 -1
  247. package/types/index.d.ts.map +0 -1
  248. package/types/patchReactNativeWeb.d.ts +0 -2
  249. package/types/patchReactNativeWeb.d.ts.map +0 -1
  250. package/types/types.d.ts.map +0 -1
@@ -0,0 +1,456 @@
1
+ import * as path from 'path'
2
+ import { basename } from 'path'
3
+ import * as util from 'util'
4
+
5
+ import generate from '@babel/generator'
6
+ import * as t from '@babel/types'
7
+ import { getStylesAtomic } from '@tamagui/core-node'
8
+ import { concatClassName } from '@tamagui/helpers'
9
+ import invariant from 'invariant'
10
+ import { ViewStyle } from 'react-native'
11
+
12
+ import { CONCAT_CLASSNAME_IMPORT } from '../constants.js'
13
+ import type { ClassNameObject, StyleObject, TamaguiOptions, Ternary } from '../types.js'
14
+ import { babelParse } from './babelParse.js'
15
+ import { buildClassName } from './buildClassName.js'
16
+ import { Extractor } from './createExtractor.js'
17
+ import { ensureImportingConcat } from './ensureImportingConcat.js'
18
+ import { isSimpleSpread } from './extractHelpers.js'
19
+ import { extractMediaStyle } from './extractMediaStyle.js'
20
+ import { getPrefixLogs } from './getPrefixLogs.js'
21
+ import { hoistClassNames } from './hoistClassNames.js'
22
+ import { logLines } from './logLines.js'
23
+ import { timer } from './timer.js'
24
+
25
+ const mergeStyleGroups = {
26
+ shadowOpacity: true,
27
+ shadowRadius: true,
28
+ shadowColor: true,
29
+ shadowOffset: true,
30
+ }
31
+
32
+ export type ExtractedResponse = {
33
+ js: string | Buffer
34
+ styles: string
35
+ stylesPath?: string
36
+ ast: t.File
37
+ map: any // RawSourceMap from 'source-map'
38
+ }
39
+
40
+ export async function extractToClassNames({
41
+ extractor,
42
+ source,
43
+ sourcePath,
44
+ options,
45
+ shouldPrintDebug,
46
+ }: {
47
+ extractor: Extractor
48
+ source: string | Buffer
49
+ sourcePath: string
50
+ options: TamaguiOptions
51
+ shouldPrintDebug: boolean | 'verbose'
52
+ }): Promise<ExtractedResponse | null> {
53
+ const tm = timer()
54
+
55
+ if (typeof source !== 'string') {
56
+ throw new Error('`source` must be a string of javascript')
57
+ }
58
+ invariant(
59
+ typeof sourcePath === 'string' && path.isAbsolute(sourcePath),
60
+ '`sourcePath` must be an absolute path to a .js file'
61
+ )
62
+
63
+ // dont include loading in timing of parsing (one time cost)
64
+ await extractor.loadTamagui(options)
65
+
66
+ const shouldLogTiming = options.logTimings ?? true
67
+ const start = Date.now()
68
+ const mem = shouldLogTiming ? process.memoryUsage() : null
69
+
70
+ // Using a map for (officially supported) guaranteed insertion order
71
+ let ast: t.File
72
+
73
+ try {
74
+ ast = babelParse(source)
75
+ } catch (err) {
76
+ // eslint-disable-next-line no-console
77
+ console.error('babel parse error:', sourcePath)
78
+ throw err
79
+ }
80
+
81
+ tm.mark(`babel-parse`, shouldPrintDebug === 'verbose')
82
+
83
+ const cssMap = new Map<string, { css: string; commentTexts: string[] }>()
84
+ const existingHoists: { [key: string]: t.Identifier } = {}
85
+
86
+ let hasFlattened = false
87
+
88
+ const res = await extractor.parse(ast, {
89
+ sourcePath,
90
+ shouldPrintDebug,
91
+ ...options,
92
+ target: 'html',
93
+ extractStyledDefinitions: true,
94
+ onStyleRule(identifier, rules) {
95
+ cssMap.set(`.${identifier}`, { css: rules.join(';'), commentTexts: [] })
96
+ },
97
+ getFlattenedNode: ({ tag }) => {
98
+ hasFlattened = true
99
+ return tag
100
+ },
101
+ onExtractTag: ({
102
+ attrs,
103
+ node,
104
+ attemptEval,
105
+ jsxPath,
106
+ originalNodeName,
107
+ filePath,
108
+ lineNumbers,
109
+ programPath,
110
+ isFlattened,
111
+ completeProps,
112
+ staticConfig,
113
+ }) => {
114
+ // bail out of views that don't accept className (falls back to runtime + style={})
115
+ if (staticConfig.acceptsClassName === false) {
116
+ if (shouldPrintDebug) {
117
+ // eslint-disable-next-line no-console
118
+ console.log(`bail, acceptsClassName is false`)
119
+ }
120
+ return
121
+ }
122
+
123
+ // reset hasFlattened
124
+ const didFlattenThisTag = hasFlattened
125
+ hasFlattened = false
126
+
127
+ let finalClassNames: ClassNameObject[] = []
128
+ const finalAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
129
+ let finalStyles: StyleObject[] = []
130
+
131
+ let viewStyles = {}
132
+ for (const attr of attrs) {
133
+ if (attr.type === 'style') {
134
+ viewStyles = {
135
+ ...viewStyles,
136
+ ...attr.value,
137
+ }
138
+ }
139
+ }
140
+
141
+ const ensureNeededPrevStyle = (style: ViewStyle) => {
142
+ // ensure all group keys are merged
143
+ const keys = Object.keys(style)
144
+ if (!keys.some((key) => mergeStyleGroups[key])) {
145
+ return style
146
+ }
147
+ for (const k in mergeStyleGroups) {
148
+ if (k in viewStyles) {
149
+ style[k] = style[k] ?? viewStyles[k]
150
+ }
151
+ }
152
+ return style
153
+ }
154
+
155
+ const addStyles = (style: ViewStyle | null): StyleObject[] => {
156
+ if (!style) return []
157
+ const styleWithPrev = ensureNeededPrevStyle(style)
158
+ const res = getStylesAtomic(styleWithPrev)
159
+ if (res.length) {
160
+ finalStyles = [...finalStyles, ...res]
161
+ }
162
+ return res
163
+ }
164
+
165
+ // 1 to start above any :hover styles
166
+ let lastMediaImportance = 1
167
+ for (const attr of attrs) {
168
+ switch (attr.type) {
169
+ case 'style': {
170
+ if (!isFlattened) {
171
+ const styles = getStylesAtomic(attr.value)
172
+
173
+ finalStyles = [...finalStyles, ...styles]
174
+
175
+ for (const style of styles) {
176
+ // leave them as attributes
177
+ const prop = style.pseudo ? `${style.property}-${style.pseudo}` : style.property
178
+ finalAttrs.push(
179
+ t.jsxAttribute(t.jsxIdentifier(prop), t.stringLiteral(style.identifier))
180
+ )
181
+ }
182
+ } else {
183
+ const styles = addStyles(attr.value)
184
+ const newClassNames = concatClassName(styles.map((x) => x.identifier).join(' '))
185
+ const existing = finalClassNames.find(
186
+ (x) => x.type == 'StringLiteral'
187
+ ) as t.StringLiteral | null
188
+
189
+ if (existing) {
190
+ existing.value = `${existing.value} ${newClassNames}`
191
+ } else {
192
+ finalClassNames = [...finalClassNames, t.stringLiteral(newClassNames)]
193
+ }
194
+ }
195
+
196
+ break
197
+ }
198
+ case 'attr': {
199
+ const val = attr.value
200
+ if (t.isJSXSpreadAttribute(val)) {
201
+ if (isSimpleSpread(val)) {
202
+ finalClassNames.push(
203
+ t.logicalExpression(
204
+ '&&',
205
+ val.argument,
206
+ t.memberExpression(val.argument, t.identifier('className'))
207
+ )
208
+ )
209
+ }
210
+ } else if (val.name.name === 'className') {
211
+ const value = val.value
212
+ if (value) {
213
+ try {
214
+ const evaluatedValue = attemptEval(value)
215
+ finalClassNames.push(t.stringLiteral(evaluatedValue))
216
+ } catch (e) {
217
+ finalClassNames.push(value['expression'])
218
+ }
219
+ }
220
+ continue
221
+ }
222
+ finalAttrs.push(val)
223
+ break
224
+ }
225
+ case 'ternary': {
226
+ const mediaExtraction = extractMediaStyle(
227
+ attr.value,
228
+ jsxPath,
229
+ extractor.getTamagui()!,
230
+ sourcePath,
231
+ lastMediaImportance,
232
+ shouldPrintDebug
233
+ )
234
+ if (shouldPrintDebug) {
235
+ if (mediaExtraction) {
236
+ // eslint-disable-next-line no-console
237
+ console.log(
238
+ 'ternary (mediaStyles)',
239
+ mediaExtraction.ternaryWithoutMedia?.inlineMediaQuery ?? '',
240
+ mediaExtraction.mediaStyles.map((x) => x.identifier).join('.')
241
+ )
242
+ }
243
+ }
244
+ if (!mediaExtraction) {
245
+ addTernaryStyle(
246
+ attr.value,
247
+ addStyles(attr.value.consequent),
248
+ addStyles(attr.value.alternate)
249
+ )
250
+ continue
251
+ }
252
+ lastMediaImportance++
253
+ if (mediaExtraction.mediaStyles) {
254
+ finalStyles = [...finalStyles, ...mediaExtraction.mediaStyles]
255
+ }
256
+ if (mediaExtraction.ternaryWithoutMedia) {
257
+ addTernaryStyle(mediaExtraction.ternaryWithoutMedia, mediaExtraction.mediaStyles, [])
258
+ } else {
259
+ finalClassNames = [
260
+ ...finalClassNames,
261
+ ...mediaExtraction.mediaStyles.map((x) => t.stringLiteral(x.identifier)),
262
+ ]
263
+ }
264
+ break
265
+ }
266
+ }
267
+ }
268
+
269
+ function addTernaryStyle(ternary: Ternary, a: any, b: any) {
270
+ const cCN = a.map((x) => x.identifier).join(' ')
271
+ const aCN = b.map((x) => x.identifier).join(' ')
272
+ if (a.length && b.length) {
273
+ finalClassNames.push(
274
+ t.conditionalExpression(ternary.test, t.stringLiteral(cCN), t.stringLiteral(aCN))
275
+ )
276
+ } else {
277
+ finalClassNames.push(
278
+ t.conditionalExpression(
279
+ ternary.test,
280
+ t.stringLiteral(' ' + cCN),
281
+ t.stringLiteral(' ' + aCN)
282
+ )
283
+ )
284
+ }
285
+ }
286
+
287
+ if (shouldPrintDebug) {
288
+ // eslint-disable-next-line no-console
289
+ console.log(
290
+ ' finalClassNames\n',
291
+ logLines(finalClassNames.map((x) => x['value']).join(' '))
292
+ )
293
+ }
294
+
295
+ node.attributes = finalAttrs
296
+
297
+ if (finalClassNames.length) {
298
+ const extraClassNames = (() => {
299
+ let value = ''
300
+ if (!isFlattened) {
301
+ return value
302
+ }
303
+
304
+ // helper to see how many get flattened
305
+ if (process.env.TAMAGUI_DEBUG_OPTIMIZATIONS) {
306
+ value += `is_tamagui_flattened`
307
+ }
308
+
309
+ // add is_Component className
310
+ if (staticConfig.componentName) {
311
+ value += ` is_${staticConfig.componentName}`
312
+ }
313
+
314
+ if (staticConfig.isText) {
315
+ let family = completeProps.fontFamily
316
+ if (family[0] === '$') {
317
+ family = family.slice(1)
318
+ }
319
+ value += ` font_${family}`
320
+ }
321
+
322
+ return value
323
+ })()
324
+
325
+ // inserts the _cn variable and uses it for className
326
+ let names = buildClassName(finalClassNames)
327
+
328
+ if (names) {
329
+ if (t.isStringLiteral(names)) {
330
+ names.value = concatClassName(names.value)
331
+ names.value = `${extraClassNames} ${names.value}`
332
+ } else {
333
+ names = t.binaryExpression('+', t.stringLiteral(extraClassNames), names)
334
+ }
335
+ }
336
+
337
+ const nameExpr = names ? hoistClassNames(jsxPath, existingHoists, names) : null
338
+ let expr = nameExpr
339
+
340
+ // if has some spreads, use concat helper
341
+ if (nameExpr && !t.isIdentifier(nameExpr)) {
342
+ if (!didFlattenThisTag) {
343
+ // not flat
344
+ } else {
345
+ ensureImportingConcat(programPath)
346
+ const simpleSpreads = attrs.filter(
347
+ (x) => t.isJSXSpreadAttribute(x.value) && isSimpleSpread(x.value)
348
+ )
349
+ expr = t.callExpression(t.identifier(CONCAT_CLASSNAME_IMPORT), [
350
+ expr,
351
+ ...simpleSpreads.map((val) => val.value['argument']),
352
+ ])
353
+ }
354
+ }
355
+
356
+ node.attributes.push(
357
+ t.jsxAttribute(t.jsxIdentifier('className'), t.jsxExpressionContainer(expr))
358
+ )
359
+ }
360
+
361
+ const comment = util.format('/* %s:%s (%s) */', filePath, lineNumbers, originalNodeName)
362
+
363
+ for (const { identifier, rules } of finalStyles) {
364
+ const className = `.${identifier}`
365
+ if (cssMap.has(className)) {
366
+ if (comment) {
367
+ const val = cssMap.get(className)!
368
+ val.commentTexts.push(comment)
369
+ cssMap.set(className, val)
370
+ }
371
+ } else if (rules.length) {
372
+ if (rules.length > 1) {
373
+ // eslint-disable-next-line no-console
374
+ console.log(' rules error', { rules })
375
+ throw new Error(`Shouldn't have more than one rule`)
376
+ }
377
+ cssMap.set(className, {
378
+ css: rules[0],
379
+ commentTexts: [comment],
380
+ })
381
+ }
382
+ }
383
+ },
384
+ })
385
+
386
+ if (!res || (!res.modified && !res.optimized && !res.flattened && !res.styled)) {
387
+ if (shouldPrintDebug) {
388
+ // eslint-disable-next-line no-console
389
+ console.log('no res or none modified', res)
390
+ }
391
+ return null
392
+ }
393
+
394
+ const styles = Array.from(cssMap.values())
395
+ .map((x) => x.css)
396
+ .join('\n')
397
+ .trim()
398
+
399
+ const result = generate(
400
+ ast,
401
+ {
402
+ concise: false,
403
+ filename: sourcePath,
404
+ // this makes the debug output terrible, and i think sourcemap works already
405
+ retainLines: false,
406
+ sourceFileName: sourcePath,
407
+ sourceMaps: true,
408
+ },
409
+ source
410
+ )
411
+
412
+ if (shouldPrintDebug) {
413
+ // eslint-disable-next-line no-console
414
+ console.log(
415
+ '\n -------- output code ------- \n\n',
416
+ result.code
417
+ .split('\n')
418
+ .filter((x) => !x.startsWith('//'))
419
+ .join('\n')
420
+ )
421
+ // eslint-disable-next-line no-console
422
+ console.log('\n -------- output style -------- \n\n', styles)
423
+ }
424
+
425
+ if (shouldLogTiming) {
426
+ const memUsed = mem
427
+ ? Math.round(((process.memoryUsage().heapUsed - mem.heapUsed) / 1024 / 1204) * 10) / 10
428
+ : 0
429
+ const path = basename(sourcePath)
430
+ .replace(/\.[jt]sx?$/, '')
431
+ .slice(0, 22)
432
+ .trim()
433
+ .padStart(24)
434
+
435
+ const numStyled = `${res.styled}`.padStart(3)
436
+ const numOptimized = `${res.optimized}`.padStart(3)
437
+ const numFound = `${res.found}`.padStart(3)
438
+ const numFlattened = `${res.flattened}`.padStart(3)
439
+ const memory = process.env.DEBUG && memUsed > 10 ? ` ${memUsed}MB` : ''
440
+ const timing = Date.now() - start
441
+ const timingStr = `${timing}ms`.padStart(6)
442
+ const pre = getPrefixLogs(options)
443
+ const memStr = memory ? `(${memory})` : ''
444
+ // eslint-disable-next-line no-console
445
+ console.log(
446
+ `${pre} ${path} ${numFound} · ${numOptimized} · ${numFlattened} · ${numStyled} ${timingStr} ${memStr}`
447
+ )
448
+ }
449
+
450
+ return {
451
+ ast,
452
+ styles,
453
+ js: result.code,
454
+ map: result.map,
455
+ }
456
+ }
@@ -0,0 +1,22 @@
1
+ import { NodePath } from '@babel/traverse'
2
+ import * as t from '@babel/types'
3
+
4
+ export function findTopmostFunction(jsxPath: NodePath<t.JSXElement>) {
5
+ // get topmost fn
6
+ const isFunction = (path: NodePath<any>) =>
7
+ path.isArrowFunctionExpression() || path.isFunctionDeclaration() || path.isFunctionExpression()
8
+ let compFn: NodePath<any> | null = jsxPath.findParent(isFunction)
9
+ while (compFn) {
10
+ const parent = compFn.findParent(isFunction)
11
+ if (parent) {
12
+ compFn = parent
13
+ } else {
14
+ break
15
+ }
16
+ }
17
+ if (!compFn) {
18
+ // console.error(`Couldn't find a topmost function for media query extraction`)
19
+ return null
20
+ }
21
+ return compFn
22
+ }
@@ -0,0 +1,43 @@
1
+ import * as t from '@babel/types'
2
+ import invariant from 'invariant'
3
+
4
+ // TODO: open a PR upstream
5
+ declare module '@babel/types' {
6
+ export function toIdentifier(input: string): string
7
+ }
8
+
9
+ // A clone of path.scope.generateUid that doesn't prepend underscores
10
+ export function generateUid(scope: any, name: string): string {
11
+ invariant(typeof scope === 'object', 'generateUid expects a scope object as its first parameter')
12
+ invariant(
13
+ typeof name === 'string' && name !== '',
14
+ 'generateUid expects a valid name as its second parameter'
15
+ )
16
+
17
+ name = t
18
+ .toIdentifier(name)
19
+ .replace(/^_+/, '')
20
+ .replace(/[0-9]+$/g, '')
21
+
22
+ let uid
23
+ let i = 0
24
+ do {
25
+ if (i > 1) {
26
+ uid = name + i
27
+ } else {
28
+ uid = name
29
+ }
30
+ i++
31
+ } while (
32
+ scope.hasLabel(uid) ||
33
+ scope.hasBinding(uid) ||
34
+ scope.hasGlobal(uid) ||
35
+ scope.hasReference(uid)
36
+ )
37
+
38
+ const program = scope.getProgramParent()
39
+ program.references[uid] = true
40
+ program.uids[uid] = true
41
+
42
+ return uid
43
+ }
@@ -0,0 +1,6 @@
1
+ import { TamaguiOptions } from '../types.js'
2
+
3
+ export function getPrefixLogs(options?: TamaguiOptions) {
4
+ const { TAMAGUI_TARGET } = process.env
5
+ return options?.prefixLogs ?? ` ${TAMAGUI_TARGET} | `
6
+ }
@@ -0,0 +1,92 @@
1
+ import generate from '@babel/generator'
2
+ import * as t from '@babel/types'
3
+
4
+ import { accessSafe } from './accessSafe.js'
5
+
6
+ /**
7
+ * getPropValueFromAttributes gets a prop by name from a list of attributes and accounts for potential spread operators.
8
+ * Here's an example. Given this component:
9
+ * ```
10
+ * <Block coolProp="wow" {...spread1} neatProp="ok" {...spread2} />```
11
+ * getPropValueFromAttributes will return the following:
12
+ * - for propName `coolProp`:
13
+ * ```
14
+ * accessSafe(spread1, 'coolProp') || accessSafe(spread2, 'coolProp') || 'wow'```
15
+ * - for propName `neatProp`:
16
+ * ```
17
+ * accessSafe(spread2, 'neatProp') || 'ok'```
18
+ * - for propName `notPresent`: `null`
19
+ *
20
+ * The returned value should (obviously) be placed after spread operators.
21
+ */
22
+ export function getPropValueFromAttributes(
23
+ propName: string,
24
+ attrs: (t.JSXAttribute | t.JSXSpreadAttribute)[]
25
+ ): t.Expression | null {
26
+ let propIndex = -1
27
+ let jsxAttr: t.JSXAttribute | null = null
28
+ for (let idx = -1, len = attrs.length; ++idx < len; ) {
29
+ const attr = attrs[idx]
30
+ if (t.isJSXAttribute(attr) && attr.name && attr.name.name === propName) {
31
+ propIndex = idx
32
+ jsxAttr = attr
33
+ break
34
+ }
35
+ }
36
+
37
+ if (!jsxAttr || jsxAttr.value == null) {
38
+ return null
39
+ }
40
+
41
+ let propValue:
42
+ | t.JSXElement
43
+ | t.JSXFragment
44
+ | t.StringLiteral
45
+ | t.JSXExpressionContainer
46
+ | t.JSXEmptyExpression
47
+ | t.Expression = jsxAttr.value
48
+
49
+ if (t.isJSXExpressionContainer(propValue)) {
50
+ propValue = propValue.expression
51
+ }
52
+
53
+ // TODO how to handle this??
54
+ if (t.isJSXEmptyExpression(propValue)) {
55
+ console.error('encountered JSXEmptyExpression')
56
+ return null
57
+ }
58
+
59
+ // filter out spread props that occur before propValue
60
+ const applicableSpreads = attrs
61
+ .filter(
62
+ // 1. idx is greater than propValue prop index
63
+ // 2. attr is a spread operator
64
+ (attr, idx): attr is t.JSXSpreadAttribute => {
65
+ if (t.isJSXSpreadAttribute(attr)) {
66
+ if (t.isIdentifier(attr.argument) || t.isMemberExpression(attr.argument)) {
67
+ return idx > propIndex
68
+ }
69
+ if (t.isLogicalExpression(attr.argument)) {
70
+ return false
71
+ }
72
+ throw new Error(
73
+ `unsupported spread of type "${attr.argument.type}": ${generate(attr).code}`
74
+ )
75
+ }
76
+ return false
77
+ }
78
+ )
79
+ .map((attr) => attr.argument)
80
+
81
+ // if spread operators occur after propValue, create a binary expression for each operator
82
+ // i.e. before1.propValue || before2.propValue || propValue
83
+ // TODO: figure out how to do this without all the extra parens
84
+ if (applicableSpreads.length > 0) {
85
+ propValue = applicableSpreads.reduce<t.Expression>(
86
+ (acc, val) => t.logicalExpression('||', accessSafe(val, propName), acc),
87
+ propValue
88
+ )
89
+ }
90
+
91
+ return propValue
92
+ }