@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,393 @@
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'
13
+ import { ClassNameObject, StyleObject, TamaguiOptions, Ternary } from '../types'
14
+ import { babelParse } from './babelParse'
15
+ import { buildClassName } from './buildClassName'
16
+ import { Extractor } from './createExtractor'
17
+ import { ensureImportingConcat } from './ensureImportingConcat'
18
+ import { isSimpleSpread } from './extractHelpers'
19
+ import { extractMediaStyle } from './extractMediaStyle'
20
+ import { getPrefixLogs } from './getPrefixLogs'
21
+ import { hoistClassNames } from './hoistClassNames'
22
+ import { logLines } from './logLines'
23
+ import { timer } from './timer'
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 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
+ }): 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
+ const shouldLogTiming = options.logTimings ?? true
64
+ const start = Date.now()
65
+ const mem = shouldLogTiming ? process.memoryUsage() : null
66
+
67
+ // Using a map for (officially supported) guaranteed insertion order
68
+ let ast: t.File
69
+
70
+ try {
71
+ ast = babelParse(source)
72
+ } catch (err) {
73
+ console.error('babel parse error:', sourcePath)
74
+ throw err
75
+ }
76
+
77
+ tm.mark(`babel-parse`, shouldPrintDebug === 'verbose')
78
+
79
+ const cssMap = new Map<string, { css: string; commentTexts: string[] }>()
80
+ const existingHoists: { [key: string]: t.Identifier } = {}
81
+
82
+ let hasFlattened = false
83
+
84
+ const res = extractor.parse(ast, {
85
+ sourcePath,
86
+ shouldPrintDebug,
87
+ ...options,
88
+ target: 'html',
89
+ extractStyledDefinitions: true,
90
+ onStyleRule(identifier, rules) {
91
+ cssMap.set(`.${identifier}`, { css: rules.join(';'), commentTexts: [] })
92
+ },
93
+ getFlattenedNode: ({ tag }) => {
94
+ hasFlattened = true
95
+ return tag
96
+ },
97
+ onExtractTag: ({
98
+ attrs,
99
+ node,
100
+ attemptEval,
101
+ jsxPath,
102
+ originalNodeName,
103
+ filePath,
104
+ lineNumbers,
105
+ programPath,
106
+ isFlattened,
107
+ }) => {
108
+ // reset hasFlattened
109
+ const didFlattenThisTag = hasFlattened
110
+ hasFlattened = false
111
+
112
+ let finalClassNames: ClassNameObject[] = []
113
+ let finalAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
114
+ let finalStyles: StyleObject[] = []
115
+
116
+ let viewStyles = {}
117
+ for (const attr of attrs) {
118
+ if (attr.type === 'style') {
119
+ viewStyles = {
120
+ ...viewStyles,
121
+ ...attr.value,
122
+ }
123
+ }
124
+ }
125
+
126
+ const ensureNeededPrevStyle = (style: ViewStyle) => {
127
+ // ensure all group keys are merged
128
+ const keys = Object.keys(style)
129
+ if (!keys.some((key) => mergeStyleGroups[key])) {
130
+ return style
131
+ }
132
+ for (const k in mergeStyleGroups) {
133
+ if (k in viewStyles) {
134
+ style[k] = style[k] ?? viewStyles[k]
135
+ }
136
+ }
137
+ return style
138
+ }
139
+
140
+ const addStyles = (style: ViewStyle | null): StyleObject[] => {
141
+ if (!style) return []
142
+ const styleWithPrev = ensureNeededPrevStyle(style)
143
+ const res = getStylesAtomic(styleWithPrev)
144
+ if (res.length) {
145
+ finalStyles = [...finalStyles, ...res]
146
+ }
147
+ return res
148
+ }
149
+
150
+ // 1 to start above any :hover styles
151
+ let lastMediaImportance = 1
152
+ for (const attr of attrs) {
153
+ switch (attr.type) {
154
+ case 'style':
155
+ if (!isFlattened) {
156
+ const styles = getStylesAtomic(attr.value)
157
+
158
+ finalStyles = [...finalStyles, ...styles]
159
+
160
+ for (const style of styles) {
161
+ // leave them as attributes
162
+ const prop = style.pseudo ? `${style.property}-${style.pseudo}` : style.property
163
+ finalAttrs.push(
164
+ t.jsxAttribute(t.jsxIdentifier(prop), t.stringLiteral(style.identifier))
165
+ )
166
+ }
167
+ } else {
168
+ const styles = addStyles(attr.value)
169
+ const newClassNames = concatClassName(styles.map((x) => x.identifier).join(' '))
170
+ const existing = finalClassNames.find(
171
+ (x) => x.type == 'StringLiteral'
172
+ ) as t.StringLiteral | null
173
+
174
+ if (existing) {
175
+ existing.value = `${existing.value} ${newClassNames}`
176
+ } else {
177
+ finalClassNames = [...finalClassNames, t.stringLiteral(newClassNames)]
178
+ }
179
+ }
180
+
181
+ break
182
+ case 'attr':
183
+ const val = attr.value
184
+ if (t.isJSXSpreadAttribute(val)) {
185
+ if (isSimpleSpread(val)) {
186
+ finalClassNames.push(
187
+ t.logicalExpression(
188
+ '&&',
189
+ val.argument,
190
+ t.memberExpression(val.argument, t.identifier('className'))
191
+ )
192
+ )
193
+ }
194
+ } else if (val.name.name === 'className') {
195
+ const value = val.value
196
+ if (value) {
197
+ try {
198
+ const evaluatedValue = attemptEval(value)
199
+ finalClassNames.push(t.stringLiteral(evaluatedValue))
200
+ } catch (e) {
201
+ finalClassNames.push(value['expression'])
202
+ }
203
+ }
204
+ continue
205
+ }
206
+ finalAttrs.push(val)
207
+ break
208
+ case 'ternary':
209
+ const mediaExtraction = extractMediaStyle(
210
+ attr.value,
211
+ jsxPath,
212
+ extractor.getTamagui(),
213
+ sourcePath,
214
+ lastMediaImportance,
215
+ shouldPrintDebug
216
+ )
217
+ if (shouldPrintDebug) {
218
+ if (mediaExtraction) {
219
+ // prettier-ignore
220
+ console.log('ternary (mediaStyles)', mediaExtraction.ternaryWithoutMedia?.inlineMediaQuery ?? '', mediaExtraction.mediaStyles.map((x) => x.identifier).join('.'))
221
+ }
222
+ }
223
+ if (!mediaExtraction) {
224
+ addTernaryStyle(
225
+ attr.value,
226
+ addStyles(attr.value.consequent),
227
+ addStyles(attr.value.alternate)
228
+ )
229
+ continue
230
+ }
231
+ lastMediaImportance++
232
+ if (mediaExtraction.mediaStyles) {
233
+ finalStyles = [...finalStyles, ...mediaExtraction.mediaStyles]
234
+ }
235
+ if (mediaExtraction.ternaryWithoutMedia) {
236
+ addTernaryStyle(mediaExtraction.ternaryWithoutMedia, mediaExtraction.mediaStyles, [])
237
+ } else {
238
+ finalClassNames = [
239
+ ...finalClassNames,
240
+ ...mediaExtraction.mediaStyles.map((x) => t.stringLiteral(x.identifier)),
241
+ ]
242
+ }
243
+ break
244
+ }
245
+ }
246
+
247
+ function addTernaryStyle(ternary: Ternary, a: any, b: any) {
248
+ const cCN = a.map((x) => x.identifier).join(' ')
249
+ const aCN = b.map((x) => x.identifier).join(' ')
250
+ if (a.length && b.length) {
251
+ finalClassNames.push(
252
+ t.conditionalExpression(ternary.test, t.stringLiteral(cCN), t.stringLiteral(aCN))
253
+ )
254
+ } else {
255
+ finalClassNames.push(
256
+ t.conditionalExpression(
257
+ ternary.test,
258
+ t.stringLiteral(' ' + cCN),
259
+ t.stringLiteral(' ' + aCN)
260
+ )
261
+ )
262
+ }
263
+ }
264
+
265
+ if (shouldPrintDebug) {
266
+ // prettier-ignore
267
+ console.log(' finalClassNames\n', logLines(finalClassNames.map(x => x['value']).join(' ')))
268
+ }
269
+
270
+ node.attributes = finalAttrs
271
+
272
+ if (finalClassNames.length) {
273
+ // inserts the _cn variable and uses it for className
274
+ let names = buildClassName(finalClassNames)
275
+ if (t.isStringLiteral(names)) {
276
+ names.value = concatClassName(names.value)
277
+ }
278
+ const nameExpr = names ? hoistClassNames(jsxPath, existingHoists, names) : null
279
+ let expr = nameExpr
280
+
281
+ // if has some spreads, use concat helper
282
+ if (nameExpr && !t.isIdentifier(nameExpr)) {
283
+ if (!didFlattenThisTag) {
284
+ // not flat
285
+ } else {
286
+ ensureImportingConcat(programPath)
287
+ const simpleSpreads = attrs.filter(
288
+ (x) => t.isJSXSpreadAttribute(x.value) && isSimpleSpread(x.value)
289
+ )
290
+ expr = t.callExpression(t.identifier(CONCAT_CLASSNAME_IMPORT), [
291
+ expr,
292
+ ...simpleSpreads.map((val) => val.value['argument']),
293
+ ])
294
+ }
295
+ }
296
+
297
+ node.attributes.push(
298
+ t.jsxAttribute(t.jsxIdentifier('className'), t.jsxExpressionContainer(expr))
299
+ )
300
+ }
301
+
302
+ const comment = util.format('/* %s:%s (%s) */', filePath, lineNumbers, originalNodeName)
303
+
304
+ for (const { identifier, rules } of finalStyles) {
305
+ const className = `.${identifier}`
306
+ if (cssMap.has(className)) {
307
+ if (comment) {
308
+ const val = cssMap.get(className)!
309
+ val.commentTexts.push(comment)
310
+ cssMap.set(className, val)
311
+ }
312
+ } else if (rules.length) {
313
+ if (rules.length > 1) {
314
+ console.log(' rules error', { rules })
315
+ throw new Error(`Shouldn't have more than one rule`)
316
+ }
317
+ cssMap.set(className, {
318
+ css: rules[0],
319
+ commentTexts: [comment],
320
+ })
321
+ }
322
+ }
323
+ },
324
+ })
325
+
326
+ if (!res || (!res.modified && !res.optimized && !res.flattened && !res.styled)) {
327
+ if (shouldPrintDebug) {
328
+ console.log('no res or none modified', res)
329
+ }
330
+ return null
331
+ }
332
+
333
+ const styles = Array.from(cssMap.values())
334
+ .map((x) => x.css)
335
+ .join('\n')
336
+ .trim()
337
+
338
+ const result = generate(
339
+ ast,
340
+ {
341
+ concise: false,
342
+ filename: sourcePath,
343
+ // this makes the debug output terrible, and i think sourcemap works already
344
+ retainLines: false,
345
+ sourceFileName: sourcePath,
346
+ sourceMaps: true,
347
+ },
348
+ source
349
+ )
350
+
351
+ if (shouldPrintDebug) {
352
+ console.log(
353
+ '\n -------- output code ------- \n\n',
354
+ result.code
355
+ .split('\n')
356
+ .filter((x) => !x.startsWith('//'))
357
+ .join('\n')
358
+ )
359
+ console.log('\n -------- output style -------- \n\n', styles)
360
+ }
361
+
362
+ if (shouldLogTiming) {
363
+ const memUsed = mem
364
+ ? Math.round(((process.memoryUsage().heapUsed - mem.heapUsed) / 1024 / 1204) * 10) / 10
365
+ : 0
366
+ const path = basename(sourcePath)
367
+ .replace(/\.[jt]sx?$/, '')
368
+ .slice(0, 22)
369
+ .trim()
370
+ .padStart(24)
371
+
372
+ const numStyled = `${res.styled}`.padStart(3)
373
+ const numOptimized = `${res.optimized}`.padStart(3)
374
+ const numFound = `${res.found}`.padStart(3)
375
+ const numFlattened = `${res.flattened}`.padStart(3)
376
+ const memory = process.env.DEBUG && memUsed > 10 ? ` ${memUsed}MB` : ''
377
+ const timing = Date.now() - start
378
+ const timingWarning = timing > 150 ? '⚠️' : timing > 150 ? '☢️' : ''
379
+ const timingStr = `${timing}ms ${timingWarning}`.padStart(6)
380
+ const pre = getPrefixLogs(options)
381
+ const memStr = memory ? `(${memory})` : ''
382
+ console.log(
383
+ `${pre} ${path} ${numFound} · ${numOptimized} · ${numFlattened} · ${numStyled} ${timingStr} ${memStr}`
384
+ )
385
+ }
386
+
387
+ return {
388
+ ast,
389
+ styles,
390
+ js: result.code,
391
+ map: result.map,
392
+ }
393
+ }
@@ -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'
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'
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: number = -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
+ }
@@ -0,0 +1,101 @@
1
+ import * as t from '@babel/types'
2
+
3
+ export interface SourceModule {
4
+ sourceModule?: string
5
+ imported?: string
6
+ local?: string
7
+ destructured?: boolean
8
+ usesImportSyntax: boolean
9
+ }
10
+
11
+ export function getSourceModule(
12
+ itemName: string,
13
+ itemBinding: {
14
+ constant?: boolean
15
+ path: { node: t.Node; parent: any }
16
+ }
17
+ ): SourceModule | null {
18
+ // TODO: deal with reassignment
19
+ if (!itemBinding.constant) {
20
+ return null
21
+ }
22
+
23
+ let sourceModule: string | undefined
24
+ let imported: string | undefined
25
+ let local: string | undefined
26
+ let destructured: boolean | undefined
27
+ let usesImportSyntax = false
28
+
29
+ const itemNode = itemBinding.path.node
30
+
31
+ if (
32
+ // import x from 'y';
33
+ t.isImportDefaultSpecifier(itemNode) ||
34
+ // import {x} from 'y';
35
+ t.isImportSpecifier(itemNode)
36
+ ) {
37
+ if (t.isImportDeclaration(itemBinding.path.parent)) {
38
+ sourceModule = itemBinding.path.parent.source.value
39
+ local = itemNode.local.name
40
+ usesImportSyntax = true
41
+ if (t.isImportSpecifier(itemNode)) {
42
+ imported = itemNode.imported['name']
43
+ destructured = true
44
+ } else {
45
+ imported = itemNode.local.name
46
+ destructured = false
47
+ }
48
+ }
49
+ } else if (
50
+ t.isVariableDeclarator(itemNode) &&
51
+ itemNode.init != null &&
52
+ t.isCallExpression(itemNode.init) &&
53
+ t.isIdentifier(itemNode.init.callee) &&
54
+ itemNode.init.callee.name === 'require' &&
55
+ itemNode.init.arguments.length === 1
56
+ ) {
57
+ const firstArg = itemNode.init.arguments[0]
58
+ if (!t.isStringLiteral(firstArg)) {
59
+ return null
60
+ }
61
+ sourceModule = firstArg.value
62
+
63
+ if (t.isIdentifier(itemNode.id)) {
64
+ local = itemNode.id.name
65
+ imported = itemNode.id.name
66
+ destructured = false
67
+ } else if (t.isObjectPattern(itemNode.id)) {
68
+ for (const objProp of itemNode.id.properties) {
69
+ if (
70
+ t.isObjectProperty(objProp) &&
71
+ t.isIdentifier(objProp.value) &&
72
+ objProp.value.name === itemName
73
+ ) {
74
+ local = objProp.value.name
75
+ // @ts-ignore TODO remove this is only an issue on CI
76
+ imported = objProp.key.name
77
+ destructured = true
78
+ break
79
+ }
80
+ }
81
+
82
+ if (!local || !imported) {
83
+ console.error('could not find prop with value `%s`', itemName)
84
+ return null
85
+ }
86
+ } else {
87
+ console.error('Unhandled id type: %s', itemNode.id.type)
88
+ return null
89
+ }
90
+ } else {
91
+ return null
92
+ }
93
+
94
+ return {
95
+ destructured,
96
+ imported,
97
+ local,
98
+ sourceModule,
99
+ usesImportSyntax,
100
+ }
101
+ }