@tamagui/static 1.0.0-alpha.6 → 1.0.0-alpha.60

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 (209) hide show
  1. package/dist/cjs/constants.js +43 -0
  2. package/dist/cjs/constants.js.map +7 -0
  3. package/dist/cjs/extractor/accessSafe.js +39 -0
  4. package/dist/cjs/extractor/accessSafe.js.map +7 -0
  5. package/dist/cjs/extractor/babelParse.js +58 -0
  6. package/dist/cjs/extractor/babelParse.js.map +7 -0
  7. package/dist/cjs/extractor/buildClassName.js +68 -0
  8. package/dist/cjs/extractor/buildClassName.js.map +7 -0
  9. package/dist/cjs/extractor/createEvaluator.js +79 -0
  10. package/dist/cjs/extractor/createEvaluator.js.map +7 -0
  11. package/dist/cjs/extractor/createExtractor.js +952 -0
  12. package/dist/cjs/extractor/createExtractor.js.map +7 -0
  13. package/dist/cjs/extractor/ensureImportingConcat.js +52 -0
  14. package/dist/cjs/extractor/ensureImportingConcat.js.map +7 -0
  15. package/dist/cjs/extractor/evaluateAstNode.js +122 -0
  16. package/dist/cjs/extractor/evaluateAstNode.js.map +7 -0
  17. package/dist/cjs/extractor/extractHelpers.js +124 -0
  18. package/dist/cjs/extractor/extractHelpers.js.map +7 -0
  19. package/dist/cjs/extractor/extractMediaStyle.js +193 -0
  20. package/dist/cjs/extractor/extractMediaStyle.js.map +7 -0
  21. package/dist/cjs/extractor/extractToClassNames.js +291 -0
  22. package/dist/cjs/extractor/extractToClassNames.js.map +7 -0
  23. package/dist/cjs/extractor/findTopmostFunction.js +46 -0
  24. package/dist/cjs/extractor/findTopmostFunction.js.map +7 -0
  25. package/dist/cjs/extractor/generatedUid.js +56 -0
  26. package/dist/cjs/extractor/generatedUid.js.map +7 -0
  27. package/dist/cjs/extractor/getPropValueFromAttributes.js +77 -0
  28. package/dist/cjs/extractor/getPropValueFromAttributes.js.map +7 -0
  29. package/dist/cjs/extractor/getSourceModule.js +97 -0
  30. package/dist/cjs/extractor/getSourceModule.js.map +7 -0
  31. package/dist/cjs/extractor/getStaticBindingsForScope.js +156 -0
  32. package/dist/cjs/extractor/getStaticBindingsForScope.js.map +7 -0
  33. package/dist/cjs/extractor/hoistClassNames.js +72 -0
  34. package/dist/cjs/extractor/hoistClassNames.js.map +7 -0
  35. package/dist/cjs/extractor/literalToAst.js +62 -0
  36. package/dist/cjs/extractor/literalToAst.js.map +7 -0
  37. package/dist/cjs/extractor/loadTamagui.js +70 -0
  38. package/dist/cjs/extractor/loadTamagui.js.map +7 -0
  39. package/dist/cjs/extractor/logLines.js +40 -0
  40. package/dist/cjs/extractor/logLines.js.map +7 -0
  41. package/dist/cjs/extractor/normalizeTernaries.js +108 -0
  42. package/dist/cjs/extractor/normalizeTernaries.js.map +7 -0
  43. package/dist/cjs/extractor/removeUnusedHooks.js +107 -0
  44. package/dist/cjs/extractor/removeUnusedHooks.js.map +7 -0
  45. package/dist/cjs/index.js +38 -0
  46. package/dist/cjs/index.js.map +7 -0
  47. package/dist/cjs/patchReactNativeWeb.js +157 -0
  48. package/dist/cjs/patchReactNativeWeb.js.map +7 -0
  49. package/dist/cjs/types.js +21 -0
  50. package/dist/cjs/types.js.map +7 -0
  51. package/dist/{constants.js → esm/constants.js} +4 -0
  52. package/dist/{constants.js.map → esm/constants.js.map} +3 -3
  53. package/dist/{extractor → esm/extractor}/accessSafe.js +0 -0
  54. package/dist/{extractor → esm/extractor}/accessSafe.js.map +1 -1
  55. package/dist/{extractor → esm/extractor}/babelParse.js +0 -0
  56. package/dist/{extractor → esm/extractor}/babelParse.js.map +1 -1
  57. package/dist/{extractor → esm/extractor}/buildClassName.js +0 -0
  58. package/dist/{extractor → esm/extractor}/buildClassName.js.map +1 -1
  59. package/dist/{extractor → esm/extractor}/createEvaluator.js +1 -1
  60. package/dist/esm/extractor/createEvaluator.js.map +7 -0
  61. package/dist/{extractor → esm/extractor}/createExtractor.js +151 -79
  62. package/dist/esm/extractor/createExtractor.js.map +7 -0
  63. package/dist/{extractor → esm/extractor}/ensureImportingConcat.js +1 -1
  64. package/dist/esm/extractor/ensureImportingConcat.js.map +7 -0
  65. package/dist/{extractor → esm/extractor}/evaluateAstNode.js +0 -0
  66. package/dist/{extractor → esm/extractor}/evaluateAstNode.js.map +1 -1
  67. package/dist/{extractor → esm/extractor}/extractHelpers.js +6 -4
  68. package/dist/{extractor → esm/extractor}/extractHelpers.js.map +3 -3
  69. package/dist/{extractor → esm/extractor}/extractMediaStyle.js +3 -2
  70. package/dist/{extractor → esm/extractor}/extractMediaStyle.js.map +2 -2
  71. package/dist/{extractor → esm/extractor}/extractToClassNames.js +35 -22
  72. package/dist/esm/extractor/extractToClassNames.js.map +7 -0
  73. package/dist/{extractor → esm/extractor}/findTopmostFunction.js +0 -0
  74. package/dist/{extractor → esm/extractor}/findTopmostFunction.js.map +1 -1
  75. package/dist/{extractor → esm/extractor}/generatedUid.js +0 -0
  76. package/dist/{extractor → esm/extractor}/generatedUid.js.map +1 -1
  77. package/dist/{extractor → esm/extractor}/getPropValueFromAttributes.js +0 -0
  78. package/dist/{extractor → esm/extractor}/getPropValueFromAttributes.js.map +1 -1
  79. package/dist/{extractor → esm/extractor}/getSourceModule.js +0 -0
  80. package/dist/{extractor → esm/extractor}/getSourceModule.js.map +1 -1
  81. package/dist/{extractor → esm/extractor}/getStaticBindingsForScope.js +0 -0
  82. package/dist/{extractor → esm/extractor}/getStaticBindingsForScope.js.map +1 -1
  83. package/dist/{extractor → esm/extractor}/hoistClassNames.js +0 -0
  84. package/dist/{extractor → esm/extractor}/hoistClassNames.js.map +1 -1
  85. package/dist/{extractor → esm/extractor}/literalToAst.js +0 -0
  86. package/dist/{extractor → esm/extractor}/literalToAst.js.map +1 -1
  87. package/dist/{extractor → esm/extractor}/loadTamagui.js +8 -2
  88. package/dist/esm/extractor/loadTamagui.js.map +7 -0
  89. package/dist/esm/extractor/logLines.js +17 -0
  90. package/dist/esm/extractor/logLines.js.map +7 -0
  91. package/dist/{extractor → esm/extractor}/normalizeTernaries.js +3 -2
  92. package/dist/{extractor → esm/extractor}/normalizeTernaries.js.map +2 -2
  93. package/dist/{extractor → esm/extractor}/removeUnusedHooks.js +5 -3
  94. package/dist/{extractor → esm/extractor}/removeUnusedHooks.js.map +2 -2
  95. package/dist/{index.js → esm/index.js} +0 -0
  96. package/dist/{index.js.map → esm/index.js.map} +1 -1
  97. package/dist/{patchReactNativeWeb.js → esm/patchReactNativeWeb.js} +22 -0
  98. package/dist/esm/patchReactNativeWeb.js.map +7 -0
  99. package/dist/{types.js → esm/types.js} +0 -0
  100. package/dist/{types.js.map → esm/types.js.map} +0 -0
  101. package/dist/jsx/constants.js +13 -0
  102. package/dist/jsx/extractor/accessSafe.js +10 -0
  103. package/dist/jsx/extractor/babelParse.js +29 -0
  104. package/dist/jsx/extractor/buildClassName.js +39 -0
  105. package/dist/jsx/extractor/createEvaluator.js +50 -0
  106. package/dist/jsx/extractor/createExtractor.js +890 -0
  107. package/dist/jsx/extractor/ensureImportingConcat.js +23 -0
  108. package/dist/jsx/extractor/evaluateAstNode.js +93 -0
  109. package/dist/jsx/extractor/extractHelpers.js +95 -0
  110. package/dist/jsx/extractor/extractMediaStyle.js +151 -0
  111. package/dist/jsx/extractor/extractToClassNames.js +247 -0
  112. package/dist/jsx/extractor/findTopmostFunction.js +22 -0
  113. package/dist/jsx/extractor/generatedUid.js +27 -0
  114. package/dist/jsx/extractor/getPropValueFromAttributes.js +48 -0
  115. package/dist/jsx/extractor/getSourceModule.js +68 -0
  116. package/dist/jsx/extractor/getStaticBindingsForScope.js +127 -0
  117. package/dist/jsx/extractor/hoistClassNames.js +43 -0
  118. package/dist/jsx/extractor/literalToAst.js +33 -0
  119. package/dist/jsx/extractor/loadTamagui.js +46 -0
  120. package/dist/jsx/extractor/logLines.js +16 -0
  121. package/dist/jsx/extractor/normalizeTernaries.js +52 -0
  122. package/dist/jsx/extractor/removeUnusedHooks.js +79 -0
  123. package/dist/jsx/index.js +13 -0
  124. package/dist/jsx/patchReactNativeWeb.js +128 -0
  125. package/dist/jsx/types.js +0 -0
  126. package/package.json +27 -19
  127. package/types/constants.d.ts +6 -0
  128. package/types/constants.d.ts.map +1 -0
  129. package/types/extractor/accessSafe.d.ts +3 -0
  130. package/types/extractor/accessSafe.d.ts.map +1 -0
  131. package/types/extractor/babelParse.d.ts +5 -0
  132. package/types/extractor/babelParse.d.ts.map +1 -0
  133. package/types/extractor/buildClassName.d.ts +4 -0
  134. package/types/extractor/buildClassName.d.ts.map +1 -0
  135. package/types/extractor/createEvaluator.d.ts +12 -0
  136. package/types/extractor/createEvaluator.d.ts.map +1 -0
  137. package/types/extractor/createExtractor.d.ts +33 -0
  138. package/types/extractor/createExtractor.d.ts.map +1 -0
  139. package/types/extractor/ensureImportingConcat.d.ts +4 -0
  140. package/types/extractor/ensureImportingConcat.d.ts.map +1 -0
  141. package/types/extractor/evaluateAstNode.d.ts +3 -0
  142. package/types/extractor/evaluateAstNode.d.ts.map +1 -0
  143. package/types/extractor/extractHelpers.d.ts +12 -0
  144. package/types/extractor/extractHelpers.d.ts.map +1 -0
  145. package/types/extractor/extractMediaStyle.d.ts +10 -0
  146. package/types/extractor/extractMediaStyle.d.ts.map +1 -0
  147. package/types/extractor/extractToClassNames.d.ts +21 -0
  148. package/types/extractor/extractToClassNames.d.ts.map +1 -0
  149. package/types/extractor/findTopmostFunction.d.ts +4 -0
  150. package/types/extractor/findTopmostFunction.d.ts.map +1 -0
  151. package/types/extractor/generatedUid.d.ts +5 -0
  152. package/types/extractor/generatedUid.d.ts.map +1 -0
  153. package/types/extractor/getPropValueFromAttributes.d.ts +3 -0
  154. package/types/extractor/getPropValueFromAttributes.d.ts.map +1 -0
  155. package/types/extractor/getSourceModule.d.ts +16 -0
  156. package/types/extractor/getSourceModule.d.ts.map +1 -0
  157. package/types/extractor/getStaticBindingsForScope.d.ts +4 -0
  158. package/types/extractor/getStaticBindingsForScope.d.ts.map +1 -0
  159. package/types/extractor/hoistClassNames.d.ts +6 -0
  160. package/types/extractor/hoistClassNames.d.ts.map +1 -0
  161. package/types/extractor/literalToAst.d.ts +3 -0
  162. package/types/extractor/literalToAst.d.ts.map +1 -0
  163. package/types/extractor/loadTamagui.d.ts +9 -0
  164. package/types/extractor/loadTamagui.d.ts.map +1 -0
  165. package/types/extractor/logLines.d.ts +2 -0
  166. package/types/extractor/logLines.d.ts.map +1 -0
  167. package/types/extractor/normalizeTernaries.d.ts +3 -0
  168. package/types/extractor/normalizeTernaries.d.ts.map +1 -0
  169. package/types/extractor/removeUnusedHooks.d.ts +3 -0
  170. package/types/extractor/removeUnusedHooks.d.ts.map +1 -0
  171. package/types/index.d.ts +8 -0
  172. package/types/index.d.ts.map +1 -0
  173. package/types/patchReactNativeWeb.d.ts +2 -0
  174. package/types/patchReactNativeWeb.d.ts.map +1 -0
  175. package/types/types.d.ts +79 -0
  176. package/types/types.d.ts.map +1 -0
  177. package/dist/extractor/createEvaluator.js.map +0 -7
  178. package/dist/extractor/createExtractor.js.map +0 -7
  179. package/dist/extractor/ensureImportingConcat.js.map +0 -7
  180. package/dist/extractor/extractToClassNames.js.map +0 -7
  181. package/dist/extractor/loadTamagui.js.map +0 -7
  182. package/dist/index.cjs +0 -2107
  183. package/dist/index.cjs.map +0 -7
  184. package/dist/patchReactNativeWeb.js.map +0 -7
  185. package/src/constants.ts +0 -10
  186. package/src/extractor/accessSafe.ts +0 -18
  187. package/src/extractor/babelParse.ts +0 -27
  188. package/src/extractor/buildClassName.ts +0 -61
  189. package/src/extractor/createEvaluator.ts +0 -68
  190. package/src/extractor/createExtractor.ts +0 -1132
  191. package/src/extractor/ensureImportingConcat.ts +0 -33
  192. package/src/extractor/evaluateAstNode.ts +0 -121
  193. package/src/extractor/extractHelpers.ts +0 -102
  194. package/src/extractor/extractMediaStyle.ts +0 -191
  195. package/src/extractor/extractToClassNames.ts +0 -326
  196. package/src/extractor/findTopmostFunction.ts +0 -22
  197. package/src/extractor/generatedUid.ts +0 -43
  198. package/src/extractor/getPropValueFromAttributes.ts +0 -92
  199. package/src/extractor/getSourceModule.ts +0 -101
  200. package/src/extractor/getStaticBindingsForScope.ts +0 -173
  201. package/src/extractor/hoistClassNames.ts +0 -45
  202. package/src/extractor/literalToAst.ts +0 -32
  203. package/src/extractor/loadTamagui.ts +0 -61
  204. package/src/extractor/normalizeTernaries.ts +0 -60
  205. package/src/extractor/removeUnusedHooks.ts +0 -76
  206. package/src/index.ts +0 -9
  207. package/src/patchReactNativeWeb.ts +0 -123
  208. package/src/types.ts +0 -83
  209. package/types.d.ts +0 -215
@@ -1,1132 +0,0 @@
1
- import traverse, { NodePath, Visitor } from '@babel/traverse'
2
- import * as t from '@babel/types'
3
- import type { StaticConfigParsed, TamaguiInternalConfig } from '@tamagui/core'
4
- import * as CoreNode from '@tamagui/core-node'
5
- import { stylePropsTransform } from '@tamagui/helpers'
6
- import { difference, pick } from 'lodash'
7
-
8
- import { ExtractedAttr, ExtractedAttrAttr, ExtractorParseProps, Ternary } from '../types'
9
- import { createEvaluator, createSafeEvaluator } from './createEvaluator'
10
- import { evaluateAstNode } from './evaluateAstNode'
11
- import { attrStr, findComponentName, isInsideTamagui, isPresent, objToStr } from './extractHelpers'
12
- import { findTopmostFunction } from './findTopmostFunction'
13
- import { getStaticBindingsForScope } from './getStaticBindingsForScope'
14
- import { literalToAst } from './literalToAst'
15
- import { loadTamagui } from './loadTamagui'
16
- import { normalizeTernaries } from './normalizeTernaries'
17
- import { removeUnusedHooks } from './removeUnusedHooks'
18
-
19
- const { mediaQueryConfig, postProcessStyles, pseudos } = CoreNode
20
-
21
- export const FAILED_EVAL = Symbol('failed_style_eval')
22
- const UNTOUCHED_PROPS = {
23
- key: true,
24
- style: true,
25
- className: true,
26
- }
27
-
28
- const isAttr = (x: ExtractedAttr): x is ExtractedAttrAttr => x.type === 'attr'
29
-
30
- const validHooks = {
31
- useMedia: true,
32
- useTheme: true,
33
- }
34
-
35
- export type Extractor = ReturnType<typeof createExtractor>
36
-
37
- const createTernary = (x: Ternary) => x
38
-
39
- export function createExtractor() {
40
- const shouldAddDebugProp =
41
- // really basic disable this for next.js because it messes with ssr
42
- !process.env.npm_package_dependencies_next &&
43
- process.env.TAMAGUI_TARGET !== 'native' &&
44
- process.env.IDENTIFY_TAGS !== 'false' &&
45
- (process.env.NODE_ENV === 'development' || process.env.DEBUG || process.env.IDENTIFY_TAGS)
46
-
47
- // ts imports
48
- require('esbuild-register/dist/node').register({
49
- target: 'es2019',
50
- format: 'cjs',
51
- })
52
-
53
- let loadedTamaguiConfig: TamaguiInternalConfig
54
- let hasLogged = false
55
-
56
- return {
57
- getTamaguiConfig() {
58
- return loadedTamaguiConfig
59
- },
60
- parse: (
61
- fileOrPath: NodePath<t.Program> | t.File,
62
- {
63
- config = 'tamagui.config.ts',
64
- importsWhitelist = ['constants.js'],
65
- evaluateVars = true,
66
- shouldPrintDebug = false,
67
- sourcePath = '',
68
- onExtractTag,
69
- getFlattenedNode,
70
- disableExtraction,
71
- disableDebugAttr,
72
- ...props
73
- }: ExtractorParseProps
74
- ) => {
75
- if (sourcePath === '') {
76
- throw new Error(`Must provide a source file name`)
77
- }
78
- if (!Array.isArray(props.components)) {
79
- throw new Error(`Must provide components array with list of Tamagui component modules`)
80
- }
81
-
82
- // we require it after parse because we need to set some global/env stuff before importing
83
- // otherwise we'd import `rnw` and cause it to evaluate react-native-web which causes errors
84
- const { components, tamaguiConfig } = loadTamagui({
85
- config,
86
- components: props.components || ['tamagui'],
87
- })
88
-
89
- loadedTamaguiConfig = tamaguiConfig
90
-
91
- const defaultTheme = tamaguiConfig.themes[Object.keys(tamaguiConfig.themes)[0]]
92
- const body = fileOrPath.type === 'Program' ? fileOrPath.get('body') : fileOrPath.program.body
93
-
94
- /**
95
- * Step 1: Determine if importing any statically extractable components
96
- */
97
- const isInternalImport = (importStr: string) =>
98
- isInsideTamagui(sourcePath) && importStr[0] === '.'
99
-
100
- const validComponents: { [key: string]: any } = Object.keys(components)
101
- .filter((key) => !!components[key]?.staticConfig)
102
- .reduce((obj, name) => {
103
- obj[name] = components[name]
104
- return obj
105
- }, {})
106
-
107
- let doesUseValidImport = false
108
-
109
- for (const bodyPath of body) {
110
- if (bodyPath.type !== 'ImportDeclaration') continue
111
- const node = ('node' in bodyPath ? bodyPath.node : bodyPath) as any
112
- const from = node.source.value
113
- if (props.components.includes(from) || isInternalImport(from)) {
114
- if (
115
- node.specifiers.some((specifier) => {
116
- const name = specifier.local.name
117
- return validComponents[name] || validHooks[name]
118
- })
119
- ) {
120
- doesUseValidImport = true
121
- break
122
- }
123
- }
124
- }
125
-
126
- if (shouldPrintDebug) {
127
- console.log(sourcePath, { doesUseValidImport })
128
- }
129
-
130
- if (!doesUseValidImport) {
131
- return null
132
- }
133
-
134
- let couldntParse = false
135
- const modifiedComponents = new Set<NodePath<any>>()
136
-
137
- // only keeping a cache around per-file, reset it if it changes
138
- const bindingCache: Record<string, string | null> = {}
139
-
140
- const callTraverse = (a: Visitor<{}>) => {
141
- return fileOrPath.type === 'File' ? traverse(fileOrPath, a) : fileOrPath.traverse(a)
142
- }
143
-
144
- /**
145
- * Step 2: Statically extract from JSX < /> nodes
146
- */
147
- let programPath: NodePath<t.Program>
148
-
149
- const res = {
150
- flattened: 0,
151
- optimized: 0,
152
- modified: 0,
153
- }
154
-
155
- callTraverse({
156
- Program: {
157
- enter(path) {
158
- programPath = path
159
- },
160
- },
161
- JSXElement(traversePath) {
162
- const node = traversePath.node.openingElement
163
- const ogAttributes = node.attributes
164
- const componentName = findComponentName(traversePath.scope)
165
- const closingElement = traversePath.node.closingElement
166
-
167
- // skip non-identifier opening elements (member expressions, etc.)
168
- if (t.isJSXMemberExpression(closingElement?.name) || !t.isJSXIdentifier(node.name)) {
169
- return
170
- }
171
-
172
- // validate its a proper import from tamagui (or internally inside tamagui)
173
- const binding = traversePath.scope.getBinding(node.name.name)
174
-
175
- if (binding) {
176
- if (!t.isImportDeclaration(binding.path.parent)) {
177
- return
178
- }
179
- const source = binding.path.parent.source
180
- if (!props.components.includes(source.value) && !isInternalImport(source.value)) {
181
- return
182
- }
183
- if (!validComponents[binding.identifier.name]) {
184
- return
185
- }
186
- }
187
-
188
- const component = validComponents[node.name.name] as { staticConfig?: StaticConfigParsed }
189
- if (!component || !component.staticConfig) {
190
- return
191
- }
192
-
193
- const originalNodeName = node.name.name
194
-
195
- if (shouldPrintDebug) {
196
- console.log(`\n<${originalNodeName} />`)
197
- }
198
-
199
- const filePath = sourcePath.replace(process.cwd(), '.')
200
- const lineNumbers = node.loc
201
- ? node.loc.start.line +
202
- (node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
203
- : ''
204
-
205
- // add data-is
206
- if (shouldAddDebugProp && !disableDebugAttr) {
207
- const preName = componentName ? `${componentName}:` : ''
208
- res.modified++
209
- node.attributes.unshift(
210
- t.jsxAttribute(
211
- t.jsxIdentifier('data-is'),
212
- t.stringLiteral(
213
- ` ${preName}${node.name.name} ${filePath.replace('./', '')}:${lineNumbers} `
214
- )
215
- )
216
- )
217
- }
218
-
219
- if (disableExtraction) {
220
- if (!hasLogged) {
221
- console.log('🥚 Tamagui disableExtraction set: no CSS or optimizations will be run')
222
- hasLogged = true
223
- }
224
- return
225
- }
226
-
227
- const { staticConfig } = component
228
- const isTextView = staticConfig.isText || false
229
- const validStyles = staticConfig?.validStyles ?? {}
230
-
231
- // find tag="a" tag="main" etc dom indicators
232
- let tagName = staticConfig.defaultProps?.tag ?? (isTextView ? 'span' : 'div')
233
- traversePath
234
- .get('openingElement')
235
- .get('attributes')
236
- .forEach((path) => {
237
- const attr = path.node
238
- if (t.isJSXSpreadAttribute(attr)) return
239
- if (attr.name.name !== 'tag') return
240
- const val = attr.value
241
- if (!t.isStringLiteral(val)) return
242
- tagName = val.value
243
- })
244
-
245
- const flatNode = getFlattenedNode({ isTextView, tag: tagName })
246
-
247
- const deoptProps = new Set([
248
- ...(props.deoptProps ?? []),
249
- ...(staticConfig.deoptProps ?? []),
250
- ])
251
- const excludeProps = new Set(props.excludeProps ?? [])
252
- const isExcludedProp = (name: string) => {
253
- const res = excludeProps.has(name)
254
- if (res && shouldPrintDebug) console.log(` excluding ${name}`)
255
- return res
256
- }
257
-
258
- const isDeoptedProp = (name: string) => {
259
- const res = deoptProps.has(name)
260
- if (res && shouldPrintDebug) console.log(` deopting ${name}`)
261
- return res
262
- }
263
-
264
- // Generate scope object at this level
265
- const staticNamespace = getStaticBindingsForScope(
266
- traversePath.scope,
267
- importsWhitelist,
268
- sourcePath,
269
- bindingCache,
270
- shouldPrintDebug
271
- )
272
-
273
- const attemptEval = !evaluateVars
274
- ? evaluateAstNode
275
- : createEvaluator({
276
- tamaguiConfig,
277
- staticNamespace,
278
- sourcePath,
279
- traversePath,
280
- shouldPrintDebug,
281
- })
282
- const attemptEvalSafe = createSafeEvaluator(attemptEval)
283
-
284
- if (shouldPrintDebug) {
285
- console.log(' staticNamespace', Object.keys(staticNamespace).join(', '))
286
- }
287
-
288
- //
289
- // SPREADS SETUP
290
- //
291
-
292
- // TODO restore
293
- const hasDeopt = (obj: Object) => {
294
- return Object.keys(obj).some(isDeoptedProp)
295
- }
296
-
297
- // flatten any easily evaluatable spreads
298
- const flattenedAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
299
- traversePath
300
- .get('openingElement')
301
- .get('attributes')
302
- .forEach((path) => {
303
- const attr = path.node
304
- if (!t.isJSXSpreadAttribute(attr)) {
305
- flattenedAttrs.push(attr)
306
- return
307
- }
308
- let arg: any
309
- try {
310
- arg = attemptEval(attr.argument)
311
- } catch (e: any) {
312
- if (shouldPrintDebug) {
313
- console.log(' couldnt parse spread', e.message)
314
- }
315
- flattenedAttrs.push(attr)
316
- return
317
- }
318
- if (typeof arg !== 'undefined') {
319
- try {
320
- if (typeof arg !== 'object' || arg == null) {
321
- if (shouldPrintDebug) {
322
- console.log(' non object or null arg', arg)
323
- }
324
- flattenedAttrs.push(attr)
325
- } else {
326
- for (const k in arg) {
327
- const value = arg[k]
328
- // this is a null prop:
329
- if (!value && typeof value === 'object') {
330
- console.log('shouldnt we handle this?', k, value, arg)
331
- continue
332
- }
333
- flattenedAttrs.push(
334
- t.jsxAttribute(
335
- t.jsxIdentifier(k),
336
- t.jsxExpressionContainer(literalToAst(value))
337
- )
338
- )
339
- }
340
- }
341
- } catch (err) {
342
- console.warn('cant parse spread, caught err', err)
343
- couldntParse = true
344
- }
345
- }
346
- })
347
-
348
- if (couldntParse) {
349
- return
350
- }
351
-
352
- // set flattened
353
- node.attributes = flattenedAttrs
354
-
355
- // add in default props
356
- if (staticConfig.defaultProps) {
357
- for (const key in staticConfig.defaultProps) {
358
- const serialize = require('babel-literal-to-ast')
359
- const val = staticConfig.defaultProps[key]
360
- node.attributes.unshift(
361
- t.jsxAttribute(
362
- t.jsxIdentifier(key),
363
- typeof val === 'string'
364
- ? t.stringLiteral(val)
365
- : t.jsxExpressionContainer(serialize(val))
366
- )
367
- )
368
- }
369
- }
370
-
371
- let attrs: ExtractedAttr[] = []
372
- let shouldDeopt = false
373
- let inlinePropCount = 0
374
- let isFlattened = false
375
-
376
- // RUN first pass
377
-
378
- // normalize all conditionals so we can evaluate away easier later
379
- // at the same time lets normalize shorthand media queries into spreads:
380
- // that way we can parse them with the same logic later on
381
- //
382
- // {...media.sm && { color: x ? 'red' : 'blue' }}
383
- // => {...media.sm && x && { color: 'red' }}
384
- // => {...media.sm && !x && { color: 'blue' }}
385
- //
386
- // $sm={{ color: 'red' }}
387
- // => {...media.sm && { color: 'red' }}
388
- //
389
- // $sm={{ color: x ? 'red' : 'blue' }}
390
- // => {...media.sm && x && { color: 'red' }}
391
- // => {...media.sm && !x && { color: 'blue' }}
392
-
393
- attrs = traversePath
394
- .get('openingElement')
395
- .get('attributes')
396
- .flatMap((path) => {
397
- try {
398
- const res = evaluateAttribute(path)
399
- if (!res) {
400
- path.remove()
401
- }
402
- return res
403
- } catch (err: any) {
404
- console.log('Error extracting attribute', err.message, err.stack)
405
- console.log('node', path.node)
406
- return {
407
- type: 'attr',
408
- value: path.node,
409
- } as const
410
- }
411
- })
412
- .flat(4)
413
- .filter(isPresent)
414
-
415
- function isStaticAttributeName(name: string) {
416
- return !!(
417
- !!validStyles[name] ||
418
- staticConfig.validPropsExtra?.[name] ||
419
- !!pseudos[name] ||
420
- staticConfig.variants?.[name] ||
421
- tamaguiConfig.shorthands[name] ||
422
- (name[0] === '$' ? !!mediaQueryConfig[name.slice(1)] : false)
423
- )
424
- }
425
-
426
- function isExtractable(obj: t.Node): obj is t.ObjectExpression {
427
- return (
428
- t.isObjectExpression(obj) &&
429
- obj.properties.every((prop) => {
430
- if (!t.isObjectProperty(prop)) {
431
- console.log('not object prop', prop)
432
- return false
433
- }
434
- const propName = prop.key['name']
435
- if (!isStaticAttributeName(propName) && propName !== 'tag') {
436
- if (shouldPrintDebug) {
437
- console.log(' not a valid style prop!', propName)
438
- }
439
- return false
440
- }
441
- return true
442
- })
443
- )
444
- }
445
-
446
- // side <= { color: 'red', background: x ? 'red' : 'green' }
447
- // | => Ternary<test, { color: 'red' }, null>
448
- // | => Ternary<test && x, { background: 'red' }, null>
449
- // | => Ternary<test && !x, { background: 'green' }, null>
450
- function createTernariesFromObjectProperties(
451
- test: t.Expression,
452
- side: t.Expression | null,
453
- ternaryPartial: Partial<Ternary> = {}
454
- ): null | Ternary[] {
455
- if (!side) {
456
- return null
457
- }
458
- if (!isExtractable(side)) {
459
- throw new Error('not extractable')
460
- }
461
- return side.properties.flatMap((property) => {
462
- if (!t.isObjectProperty(property)) {
463
- throw new Error('expected object property')
464
- }
465
- // this could be a recurse here if we want to get fancy
466
- if (t.isConditionalExpression(property.value)) {
467
- // merge up into the parent conditional, split into two
468
- const [truthy, falsy] = [
469
- t.objectExpression([t.objectProperty(property.key, property.value.consequent)]),
470
- t.objectExpression([t.objectProperty(property.key, property.value.alternate)]),
471
- ].map((x) => attemptEval(x))
472
- return [
473
- createTernary({
474
- remove() {},
475
- ...ternaryPartial,
476
- test: t.logicalExpression('&&', test, property.value.test),
477
- consequent: truthy,
478
- alternate: null,
479
- }),
480
- createTernary({
481
- ...ternaryPartial,
482
- test: t.logicalExpression(
483
- '&&',
484
- test,
485
- t.unaryExpression('!', property.value.test)
486
- ),
487
- consequent: falsy,
488
- alternate: null,
489
- remove() {},
490
- }),
491
- ]
492
- }
493
- const obj = t.objectExpression([t.objectProperty(property.key, property.value)])
494
- const consequent = attemptEval(obj)
495
- return createTernary({
496
- remove() {},
497
- ...ternaryPartial,
498
- test,
499
- consequent,
500
- alternate: null,
501
- })
502
- })
503
- }
504
-
505
- // START function evaluateAttribute
506
- function evaluateAttribute(
507
- path: NodePath<t.JSXAttribute | t.JSXSpreadAttribute>
508
- ): ExtractedAttr | ExtractedAttr[] | null {
509
- const attribute = path.node
510
- const attr: ExtractedAttr = { type: 'attr', value: attribute }
511
- // ...spreads
512
- if (t.isJSXSpreadAttribute(attribute)) {
513
- const arg = attribute.argument
514
- const conditional = t.isConditionalExpression(arg)
515
- ? // <YStack {...isSmall ? { color: 'red } : { color: 'blue }}
516
- ([arg.test, arg.consequent, arg.alternate] as const)
517
- : t.isLogicalExpression(arg) && arg.operator === '&&'
518
- ? // <YStack {...isSmall && { color: 'red }}
519
- ([arg.left, arg.right, null] as const)
520
- : null
521
-
522
- if (conditional) {
523
- const [test, alt, cons] = conditional
524
- if (!test) throw new Error(`no test`)
525
- if ([alt, cons].some((side) => side && !isExtractable(side))) {
526
- if (shouldPrintDebug) {
527
- console.log('not extractable', alt, cons)
528
- }
529
- return attr
530
- }
531
- // split into individual ternaries per object property
532
- return [
533
- ...(createTernariesFromObjectProperties(test, alt) || []),
534
- ...((cons &&
535
- createTernariesFromObjectProperties(t.unaryExpression('!', test), cons)) ||
536
- []),
537
- ].map((ternary) => ({
538
- type: 'ternary',
539
- value: ternary,
540
- }))
541
- }
542
- }
543
- // END ...spreads
544
-
545
- // directly keep these
546
- // couldn't evaluate spread, undefined name, or name is not string
547
- if (
548
- t.isJSXSpreadAttribute(attribute) ||
549
- !attribute.name ||
550
- typeof attribute.name.name !== 'string'
551
- ) {
552
- inlinePropCount++
553
- return attr
554
- }
555
-
556
- const name = attribute.name.name
557
-
558
- if (isExcludedProp(name)) {
559
- return null
560
- }
561
-
562
- // can still optimize the object... see hoverStyle on native
563
- if (isDeoptedProp(name)) {
564
- if (shouldPrintDebug) {
565
- console.log(' ! inlining, deopt prop', name)
566
- }
567
- inlinePropCount++
568
- return attr
569
- }
570
-
571
- // pass className, key, and style props through untouched
572
- if (UNTOUCHED_PROPS[name]) {
573
- return attr
574
- }
575
-
576
- // shorthand media queries
577
- if (name[0] === '$' && t.isJSXExpressionContainer(attribute?.value)) {
578
- const shortname = name.slice(1)
579
- if (mediaQueryConfig[shortname]) {
580
- const expression = attribute.value.expression
581
- if (!t.isJSXEmptyExpression(expression)) {
582
- const ternaries = createTernariesFromObjectProperties(
583
- t.stringLiteral(shortname),
584
- expression,
585
- {
586
- inlineMediaQuery: shortname,
587
- }
588
- )
589
- if (ternaries) {
590
- return ternaries.map((value) => ({
591
- type: 'ternary',
592
- value,
593
- }))
594
- }
595
- }
596
- }
597
- }
598
-
599
- const [value, valuePath] = (() => {
600
- if (t.isJSXExpressionContainer(attribute?.value)) {
601
- return [attribute.value.expression!, path.get('value')!] as const
602
- } else {
603
- return [attribute.value!, path.get('value')!] as const
604
- }
605
- })()
606
-
607
- const remove = () => {
608
- Array.isArray(valuePath) ? valuePath.map((p) => p.remove()) : valuePath.remove()
609
- }
610
-
611
- if (name === 'ref') {
612
- if (shouldPrintDebug) {
613
- console.log(' ! inlining, ref', name)
614
- }
615
- inlinePropCount++
616
- return attr
617
- }
618
-
619
- if (name === 'tag') {
620
- return {
621
- type: 'attr',
622
- value: path.node,
623
- }
624
- }
625
-
626
- // if value can be evaluated, extract it and filter it out
627
- const styleValue = attemptEvalSafe(value)
628
-
629
- // we never flatten if a prop isn't a valid static attribute
630
- // but we need to make sure its post-prop mapping
631
- if (!isStaticAttributeName(name)) {
632
- let keys = [name]
633
- if (staticConfig.propMapper) {
634
- // for now passing empty props {}, a bit odd, need to at least document
635
- // for now we don't expose custom components so just noting behavior
636
- const out = staticConfig.propMapper(
637
- name,
638
- styleValue,
639
- defaultTheme,
640
- staticConfig.defaultProps
641
- )
642
- if (out) {
643
- keys = Object.keys(out)
644
- }
645
- }
646
- if (keys.some((k) => !isStaticAttributeName(k) && k !== 'tag')) {
647
- if (shouldPrintDebug) {
648
- console.log(' ! inlining, not static attribute name', name)
649
- }
650
- inlinePropCount++
651
- return attr
652
- }
653
- }
654
-
655
- // FAILED = dynamic or ternary, keep going
656
- if (styleValue !== FAILED_EVAL) {
657
- return {
658
- type: 'style',
659
- value: { [name]: styleValue },
660
- }
661
- }
662
-
663
- // ternaries!
664
-
665
- // binary ternary, we can eventually make this smarter but step 1
666
- // basically for the common use case of:
667
- // opacity={(conditional ? 0 : 1) * scale}
668
- if (t.isBinaryExpression(value)) {
669
- const { operator, left, right } = value
670
- // if one side is a ternary, and the other side is evaluatable, we can maybe extract
671
- const lVal = attemptEvalSafe(left)
672
- const rVal = attemptEvalSafe(right)
673
- if (shouldPrintDebug) {
674
- console.log(` evalBinaryExpression lVal ${String(lVal)}, rVal ${String(rVal)}`)
675
- }
676
- if (lVal !== FAILED_EVAL && t.isConditionalExpression(right)) {
677
- const ternary = addBinaryConditional(operator, left, right)
678
- if (ternary) return ternary
679
- }
680
- if (rVal !== FAILED_EVAL && t.isConditionalExpression(left)) {
681
- const ternary = addBinaryConditional(operator, right, left)
682
- if (ternary) return ternary
683
- }
684
- if (shouldPrintDebug) {
685
- console.log(` evalBinaryExpression cant extract`)
686
- }
687
- inlinePropCount++
688
- return attr
689
- }
690
-
691
- const staticConditional = getStaticConditional(value)
692
- if (staticConditional) {
693
- return { type: 'ternary', value: staticConditional }
694
- }
695
-
696
- const staticLogical = getStaticLogical(value)
697
- if (staticLogical) {
698
- return { type: 'ternary', value: staticLogical }
699
- }
700
-
701
- if (shouldPrintDebug) {
702
- console.log(' ! inline prop via no match', name, value.type)
703
- }
704
- // if we've made it this far, the prop stays inline
705
- inlinePropCount++
706
-
707
- //
708
- // RETURN ATTR
709
- //
710
- return attr
711
-
712
- // attr helpers:
713
- function addBinaryConditional(
714
- operator: any,
715
- staticExpr: any,
716
- cond: t.ConditionalExpression
717
- ): ExtractedAttr | null {
718
- if (getStaticConditional(cond)) {
719
- const alt = attemptEval(t.binaryExpression(operator, staticExpr, cond.alternate))
720
- const cons = attemptEval(t.binaryExpression(operator, staticExpr, cond.consequent))
721
- if (shouldPrintDebug) {
722
- console.log(' binaryConditional', cond.test, cons, alt)
723
- }
724
- return {
725
- type: 'ternary',
726
- value: {
727
- test: cond.test,
728
- remove,
729
- alternate: { [name]: alt },
730
- consequent: { [name]: cons },
731
- },
732
- }
733
- }
734
- return null
735
- }
736
-
737
- function getStaticConditional(value: t.Node): Ternary | null {
738
- if (t.isConditionalExpression(value)) {
739
- try {
740
- if (shouldPrintDebug) {
741
- console.log('attempt', value.alternate, value.consequent)
742
- }
743
- const aVal = attemptEval(value.alternate)
744
- const cVal = attemptEval(value.consequent)
745
- if (shouldPrintDebug) {
746
- const type = value.test.type
747
- console.log(' static ternary', type, cVal, aVal)
748
- }
749
- return {
750
- test: value.test,
751
- remove,
752
- consequent: { [name]: cVal },
753
- alternate: { [name]: aVal },
754
- }
755
- } catch (err: any) {
756
- if (shouldPrintDebug) {
757
- console.log(' cant eval ternary', err.message)
758
- }
759
- }
760
- }
761
- return null
762
- }
763
-
764
- function getStaticLogical(value: t.Node): Ternary | null {
765
- if (t.isLogicalExpression(value)) {
766
- if (value.operator === '&&') {
767
- try {
768
- const val = attemptEval(value.right)
769
- if (shouldPrintDebug) {
770
- console.log(' staticLogical', value.left, name, val)
771
- }
772
- return {
773
- test: value.left,
774
- remove,
775
- consequent: { [name]: val },
776
- alternate: null,
777
- }
778
- } catch (err) {
779
- if (shouldPrintDebug) {
780
- console.log(' cant static eval logical', err)
781
- }
782
- }
783
- }
784
- }
785
- return null
786
- }
787
- } // END function evaluateAttribute
788
-
789
- // see if we can filter them
790
- if (shouldPrintDebug) {
791
- console.log(' - attrs (before): ', attrs.map(attrStr).join(', '))
792
- }
793
-
794
- // now update to new values
795
- node.attributes = attrs.filter(isAttr).map((x) => x.value)
796
-
797
- if (couldntParse) {
798
- if (shouldPrintDebug) {
799
- console.log(` cancel:`, { couldntParse, shouldDeopt })
800
- }
801
- node.attributes = ogAttributes
802
- return
803
- }
804
-
805
- // before deopt, can still optimize
806
- const parentFn = findTopmostFunction(traversePath)
807
- if (parentFn) {
808
- modifiedComponents.add(parentFn)
809
- }
810
-
811
- // combine ternaries
812
- let ternaries: Ternary[] = []
813
- attrs = attrs
814
- .reduce<(ExtractedAttr | ExtractedAttr[])[]>((out, cur) => {
815
- const next = attrs[attrs.indexOf(cur) + 1]
816
- if (cur.type === 'ternary') {
817
- ternaries.push(cur.value)
818
- }
819
- if ((!next || next.type !== 'ternary') && ternaries.length) {
820
- // finish, process
821
- const normalized = normalizeTernaries(ternaries).map(
822
- ({ alternate, consequent, ...rest }) => {
823
- return {
824
- type: 'ternary' as const,
825
- value: {
826
- ...rest,
827
- alternate: alternate || null,
828
- consequent: consequent || null,
829
- },
830
- }
831
- }
832
- )
833
- try {
834
- return [...out, ...normalized]
835
- } finally {
836
- if (shouldPrintDebug) {
837
- console.log(
838
- ` normalizeTernaries (${ternaries.length} => ${normalized.length})`
839
- )
840
- }
841
- ternaries = []
842
- }
843
- }
844
- if (cur.type === 'ternary') {
845
- return out
846
- }
847
- out.push(cur)
848
- return out
849
- }, [])
850
- .flat()
851
-
852
- // evaluates all static attributes into a simple object
853
- const completeStaticProps = {
854
- ...Object.keys(attrs).reduce((acc, index) => {
855
- const cur = attrs[index] as ExtractedAttr
856
- if (cur.type === 'style') {
857
- Object.assign(acc, cur.value)
858
- }
859
- if (cur.type === 'attr') {
860
- if (t.isJSXSpreadAttribute(cur.value)) {
861
- return acc
862
- }
863
- if (!t.isJSXIdentifier(cur.value.name)) {
864
- return acc
865
- }
866
- const key = cur.value.name.name
867
- // undefined = boolean true
868
- const value = attemptEvalSafe(cur.value.value || t.booleanLiteral(true))
869
- if (value === FAILED_EVAL) {
870
- return acc
871
- }
872
- acc[key] = value
873
- }
874
- return acc
875
- }, {}),
876
- }
877
-
878
- // flatten logic!
879
- // fairly simple check to see if all children are text
880
- const hasSpread = node.attributes.some((x) => t.isJSXSpreadAttribute(x))
881
- const hasOnlyStringChildren =
882
- !hasSpread &&
883
- (node.selfClosing ||
884
- (traversePath.node.children &&
885
- traversePath.node.children.every((x) => x.type === 'JSXText')))
886
- const shouldFlatten =
887
- !shouldDeopt &&
888
- inlinePropCount === 0 &&
889
- !hasSpread &&
890
- staticConfig.neverFlatten !== true &&
891
- (staticConfig.neverFlatten === 'jsx' ? hasOnlyStringChildren : true)
892
-
893
- // insert overrides - this inserts null props for things that are set in classNames
894
- // only when not flattening, so the downstream component can skip applying those styles
895
- if (!shouldFlatten) {
896
- attrs = attrs.reduce<ExtractedAttr[]>((acc, cur) => {
897
- if (cur.type === 'style') {
898
- // TODO need to loop over initial props not just style props
899
- for (const key in cur.value) {
900
- const shouldInsertNull =
901
- !!(
902
- staticConfig.ensureOverriddenProp?.[key] // || staticConfig.defaultProps?.[key]
903
- )
904
- const isSetInAttrsAlready = attrs.some(
905
- (x) =>
906
- x.type === 'attr' &&
907
- x.value.type === 'JSXAttribute' &&
908
- x.value.name.name === key
909
- )
910
- const shouldInsertNullOverride = shouldInsertNull && !isSetInAttrsAlready
911
- // if (shouldPrintDebug) {
912
- // // prettier-ignore
913
- // console.log('what is', key, { shouldInsertNullOverride, shouldInsertNull, isSetInAttrsAlready })
914
- // }
915
- if (shouldInsertNullOverride) {
916
- acc.push({
917
- type: 'attr',
918
- value: t.jsxAttribute(
919
- t.jsxIdentifier(key),
920
- t.jsxExpressionContainer(t.nullLiteral())
921
- ),
922
- })
923
- }
924
- }
925
- }
926
- acc.push(cur)
927
- return acc
928
- }, [])
929
- }
930
-
931
- if (shouldPrintDebug) {
932
- console.log(' - attrs (flattened): ', attrs.map(attrStr).join(', '))
933
- }
934
-
935
- // evaluate away purely style props
936
- attrs = attrs.reduce<ExtractedAttr[]>((acc, cur) => {
937
- if (
938
- cur.type !== 'attr' ||
939
- !t.isJSXAttribute(cur.value) ||
940
- typeof cur.value.name.name !== 'string'
941
- ) {
942
- if (cur.type === 'style') {
943
- const key = Object.keys(cur.value)[0]
944
- if (!validStyles[key] && !pseudos[key]) {
945
- if (shouldPrintDebug) {
946
- console.log(' ❌ excluding', key)
947
- }
948
- // we've already expanded shorthands, now we can remove them
949
- return acc
950
- }
951
- }
952
- }
953
- acc.push(cur)
954
- return acc
955
- }, [])
956
-
957
- if (shouldPrintDebug) {
958
- console.log(' - attrs (evaluated styles): ', attrs.map(attrStr).join(', '))
959
- }
960
-
961
- // combine styles, leave undefined values
962
- let prev: ExtractedAttr | null = null
963
- attrs = attrs.reduce<ExtractedAttr[]>((acc, cur) => {
964
- if (cur.type === 'style') {
965
- if (prev?.type === 'style') {
966
- Object.assign(prev.value, cur.value)
967
- return acc
968
- }
969
- }
970
- acc.push(cur)
971
- prev = cur
972
- return acc
973
- }, [])
974
-
975
- if (shouldPrintDebug) {
976
- console.log(' - attrs (combined 🔀): ', attrs.map(attrStr).join(', '))
977
- }
978
-
979
- // post process
980
- const getStyles = (props: Object | null) => {
981
- if (!props) return
982
- if (!!excludeProps.size) {
983
- for (const key in props) {
984
- if (isExcludedProp(key)) delete props[key]
985
- }
986
- }
987
-
988
- const out = postProcessStyles(props, staticConfig, defaultTheme)
989
- const next = out?.style ?? props
990
- if (shouldPrintDebug) {
991
- console.log(' >> getStyles: ', objToStr(props), '==>>', objToStr(next))
992
- console.log(' >> style: ', objToStr(out.style))
993
- console.log(' >> viewp: ', objToStr(out.viewProps))
994
- }
995
- if (staticConfig.validStyles) {
996
- for (const key in next) {
997
- if (!staticConfig.validStyles[key] && !pseudos[key]) {
998
- delete next[key]
999
- }
1000
- }
1001
- }
1002
- return next
1003
- }
1004
-
1005
- if (shouldPrintDebug) {
1006
- console.log(' staticConfig.defaultProps', staticConfig.defaultProps)
1007
- }
1008
-
1009
- // used to ensure we pass the entire prop bundle to getStyles
1010
- const completeStylesProcessed = getStyles({
1011
- ...staticConfig.defaultProps,
1012
- ...completeStaticProps,
1013
- })
1014
-
1015
- // any extra styles added in postprocess should be added to first group as they wont be overriden
1016
- const stylesToAddToInitialGroup = difference(
1017
- Object.keys(completeStylesProcessed),
1018
- Object.keys(completeStaticProps)
1019
- )
1020
-
1021
- if (stylesToAddToInitialGroup.length) {
1022
- const toAdd = pick(completeStylesProcessed, ...stylesToAddToInitialGroup)
1023
- const firstGroup = attrs.find((x) => x.type === 'style')
1024
- if (shouldPrintDebug) {
1025
- console.log(' stylesToAddToInitialGroup', stylesToAddToInitialGroup.join(', '))
1026
- console.log(' toAdd', objToStr(toAdd))
1027
- }
1028
- if (!firstGroup) {
1029
- attrs.unshift({ type: 'style', value: toAdd })
1030
- } else {
1031
- Object.assign(firstGroup.value, toAdd)
1032
- }
1033
- }
1034
-
1035
- if (shouldPrintDebug) {
1036
- // prettier-ignore
1037
- console.log(' completeStaticProps', objToStr(completeStaticProps))
1038
- // prettier-ignore
1039
- console.log(' completeStylesProcessed', objToStr(completeStylesProcessed))
1040
- }
1041
-
1042
- for (const attr of attrs) {
1043
- try {
1044
- switch (attr.type) {
1045
- case 'ternary':
1046
- const a = getStyles(attr.value.alternate)
1047
- const c = getStyles(attr.value.consequent)
1048
- attr.value.alternate = a
1049
- attr.value.consequent = c
1050
- if (shouldPrintDebug) {
1051
- console.log(' => tern ', attrStr(attr))
1052
- }
1053
- break
1054
- case 'style':
1055
- const next = {}
1056
- for (const key in attr.value) {
1057
- if (key in stylePropsTransform) {
1058
- // TODO this logic needs to be a bit more right, because could have spread in between transforms...
1059
- next['transform'] = completeStylesProcessed['transform']
1060
- } else {
1061
- next[key] = completeStylesProcessed[key] ?? attr.value[key]
1062
- }
1063
- }
1064
- attr.value = next
1065
- break
1066
- }
1067
- } catch (err) {
1068
- // any error de-opt
1069
- if (shouldPrintDebug) {
1070
- console.log(' postprocessing error, deopt', err)
1071
- node.attributes = ogAttributes
1072
- return node
1073
- }
1074
- }
1075
- }
1076
-
1077
- if (shouldPrintDebug) {
1078
- console.log(' - attrs (after): ', attrs.map(attrStr).join(', '))
1079
- }
1080
-
1081
- if (shouldFlatten) {
1082
- // DO FLATTEN
1083
- if (shouldPrintDebug) {
1084
- console.log(' [✅] flattening', originalNodeName, flatNode)
1085
- }
1086
- isFlattened = true
1087
- node.name.name = flatNode
1088
- res.flattened++
1089
- if (closingElement) {
1090
- closingElement.name.name = flatNode
1091
- }
1092
- }
1093
-
1094
- if (shouldPrintDebug) {
1095
- // prettier-ignore
1096
- console.log(' [❊] inline props ', inlinePropCount, shouldDeopt ? ' deopted' : '', hasSpread ? ' spread' : '', '!flatten', staticConfig.neverFlatten)
1097
- console.log(' - attrs (end): ', attrs.map(attrStr).join(', '))
1098
- }
1099
-
1100
- res.optimized++
1101
-
1102
- onExtractTag({
1103
- attrs,
1104
- node,
1105
- lineNumbers,
1106
- filePath,
1107
- attemptEval,
1108
- jsxPath: traversePath,
1109
- originalNodeName,
1110
- isFlattened,
1111
- programPath,
1112
- })
1113
- },
1114
- })
1115
-
1116
- /**
1117
- * Step 3: Remove dead code from removed media query / theme hooks
1118
- */
1119
- if (modifiedComponents.size) {
1120
- const all = Array.from(modifiedComponents)
1121
- if (shouldPrintDebug) {
1122
- console.log(' [🪝] hook check', all.length)
1123
- }
1124
- for (const comp of all) {
1125
- removeUnusedHooks(comp, shouldPrintDebug)
1126
- }
1127
- }
1128
-
1129
- return res
1130
- },
1131
- }
1132
- }