@tamagui/static 1.0.1-beta.99 → 1.0.1-rc.0
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.
- package/dist/{cjs/constants.js → constants.js} +9 -4
- package/dist/constants.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/accessSafe.js +14 -2
- package/dist/{esm/extractor → extractor}/accessSafe.js.map +2 -2
- package/dist/{cjs/extractor → extractor}/babelParse.js +5 -1
- package/dist/extractor/babelParse.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/buildClassName.js +40 -9
- package/dist/extractor/buildClassName.js.map +7 -0
- package/dist/extractor/bundle.js +117 -0
- package/dist/extractor/bundle.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/createEvaluator.js +11 -8
- package/dist/extractor/createEvaluator.js.map +7 -0
- package/dist/extractor/createExtractor.js +1623 -0
- package/dist/extractor/createExtractor.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/ensureImportingConcat.js +18 -6
- package/dist/extractor/ensureImportingConcat.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/evaluateAstNode.js +14 -4
- package/dist/extractor/evaluateAstNode.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/extractHelpers.js +83 -12
- package/dist/extractor/extractHelpers.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/extractMediaStyle.js +46 -42
- package/dist/extractor/extractMediaStyle.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/extractToClassNames.js +144 -73
- package/dist/extractor/extractToClassNames.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/findTopmostFunction.js +1 -0
- package/dist/{cjs/extractor → extractor}/findTopmostFunction.js.map +2 -2
- package/dist/{cjs/extractor → extractor}/generatedUid.js +9 -2
- package/dist/{cjs/extractor → extractor}/generatedUid.js.map +3 -3
- package/dist/{cjs/extractor → extractor}/getPrefixLogs.js +1 -0
- package/dist/extractor/getPrefixLogs.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/getPropValueFromAttributes.js +24 -13
- package/dist/extractor/getPropValueFromAttributes.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/getSourceModule.js +5 -1
- package/dist/{esm/extractor → extractor}/getSourceModule.js.map +3 -3
- package/dist/{cjs/extractor → extractor}/getStaticBindingsForScope.js +89 -35
- package/dist/extractor/getStaticBindingsForScope.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/hoistClassNames.js +5 -1
- package/dist/{jsx/extractor → extractor}/hoistClassNames.js.map +3 -3
- package/dist/{cjs/extractor → extractor}/literalToAst.js +26 -30
- package/dist/{jsx/extractor → extractor}/literalToAst.js.map +2 -2
- package/dist/extractor/loadFile.js +21 -0
- package/dist/extractor/loadFile.js.map +7 -0
- package/dist/extractor/loadTamagui.js +427 -0
- package/dist/extractor/loadTamagui.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/logLines.js +2 -1
- package/dist/extractor/logLines.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/normalizeTernaries.js +13 -34
- package/dist/extractor/normalizeTernaries.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/removeUnusedHooks.js +5 -1
- package/dist/extractor/removeUnusedHooks.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/timer.js +9 -1
- package/dist/extractor/timer.js.map +7 -0
- package/dist/{cjs/extractor → extractor}/validHTMLAttributes.js +1 -0
- package/dist/{jsx/extractor → extractor}/validHTMLAttributes.js.map +2 -2
- package/dist/getPragmaOptions.js +68 -0
- package/dist/getPragmaOptions.js.map +7 -0
- package/dist/helpers/memoize.js +46 -0
- package/dist/helpers/memoize.js.map +7 -0
- package/dist/{cjs/index.js → index.js} +10 -8
- package/dist/index.js.map +7 -0
- package/dist/require.js +86 -0
- package/dist/require.js.map +7 -0
- package/dist/{cjs/types.js → types.js} +1 -0
- package/dist/types.js.map +7 -0
- package/dist/webpackPlugin.js +35 -0
- package/dist/webpackPlugin.js.map +7 -0
- package/package.json +40 -36
- package/src/constants.ts +2 -1
- package/src/extractor/babelParse.ts +3 -2
- package/src/extractor/buildClassName.ts +21 -5
- package/src/extractor/bundle.ts +110 -0
- package/src/extractor/createEvaluator.ts +10 -12
- package/src/extractor/createExtractor.ts +1702 -1523
- package/src/extractor/ensureImportingConcat.ts +4 -11
- package/src/extractor/evaluateAstNode.ts +1 -1
- package/src/extractor/extractHelpers.ts +93 -10
- package/src/extractor/extractMediaStyle.ts +18 -11
- package/src/extractor/extractToClassNames.ts +104 -47
- package/src/extractor/getPrefixLogs.ts +1 -1
- package/src/extractor/getPropValueFromAttributes.ts +4 -3
- package/src/extractor/getSourceModule.ts +2 -0
- package/src/extractor/getStaticBindingsForScope.ts +90 -46
- package/src/extractor/loadFile.ts +17 -0
- package/src/extractor/loadTamagui.ts +448 -103
- package/src/extractor/logLines.ts +1 -1
- package/src/extractor/normalizeTernaries.ts +2 -2
- package/src/extractor/removeUnusedHooks.ts +2 -0
- package/src/extractor/timer.ts +12 -1
- package/src/getPragmaOptions.ts +53 -0
- package/src/helpers/memoize.ts +21 -0
- package/src/index.ts +9 -8
- package/src/require.ts +103 -0
- package/src/types.ts +33 -31
- package/src/webpackPlugin.ts +9 -0
- package/tamagui.tsconfig.json +5 -0
- package/types/constants.d.ts +6 -0
- package/types/extractor/accessSafe.d.ts +3 -0
- package/types/extractor/babelParse.d.ts +6 -0
- package/types/extractor/buildClassName.d.ts +5 -2
- package/types/extractor/bundle.d.ts +13 -0
- package/types/extractor/createEvaluator.d.ts +3 -3
- package/types/extractor/createExtractor.d.ts +25 -9
- package/types/extractor/ensureImportingConcat.d.ts +4 -0
- package/types/extractor/evaluateAstNode.d.ts +3 -0
- package/types/extractor/extractHelpers.d.ts +15 -3
- package/types/extractor/extractMediaStyle.d.ts +3 -3
- package/types/extractor/extractToClassNames.d.ts +5 -4
- package/types/extractor/findTopmostFunction.d.ts +4 -0
- package/types/extractor/generatedUid.d.ts +5 -0
- package/types/extractor/getPrefixLogs.d.ts +1 -1
- package/types/extractor/getPropValueFromAttributes.d.ts +19 -0
- package/types/extractor/getSourceModule.d.ts +16 -0
- package/types/extractor/getStaticBindingsForScope.d.ts +5 -0
- package/types/extractor/hoistClassNames.d.ts +6 -0
- package/types/extractor/literalToAst.d.ts +4 -0
- package/types/extractor/loadFile.d.ts +1 -0
- package/types/extractor/loadTamagui.d.ts +15 -5
- package/types/extractor/logLines.d.ts +2 -0
- package/types/extractor/normalizeTernaries.d.ts +1 -1
- package/types/extractor/removeUnusedHooks.d.ts +3 -0
- package/types/extractor/timer.d.ts +5 -0
- package/types/extractor/validHTMLAttributes.d.ts +98 -0
- package/types/getPragmaOptions.d.ts +9 -0
- package/types/helpers/memoize.d.ts +8 -0
- package/types/index.d.ts +9 -8
- package/types/require.d.ts +4 -0
- package/types/types.d.ts +28 -27
- package/types/webpackPlugin.d.ts +4 -0
- package/dist/cjs/constants.js.map +0 -7
- package/dist/cjs/extractor/accessSafe.js.map +0 -7
- package/dist/cjs/extractor/babelParse.js.map +0 -7
- package/dist/cjs/extractor/buildClassName.js.map +0 -7
- package/dist/cjs/extractor/createEvaluator.js.map +0 -7
- package/dist/cjs/extractor/createExtractor.js +0 -1394
- package/dist/cjs/extractor/createExtractor.js.map +0 -7
- package/dist/cjs/extractor/ensureImportingConcat.js.map +0 -7
- package/dist/cjs/extractor/evaluateAstNode.js.map +0 -7
- package/dist/cjs/extractor/extractHelpers.js.map +0 -7
- package/dist/cjs/extractor/extractMediaStyle.js.map +0 -7
- package/dist/cjs/extractor/extractToClassNames.js.map +0 -7
- package/dist/cjs/extractor/getPrefixLogs.js.map +0 -7
- package/dist/cjs/extractor/getPropValueFromAttributes.js.map +0 -7
- package/dist/cjs/extractor/getSourceModule.js.map +0 -7
- package/dist/cjs/extractor/getStaticBindingsForScope.js.map +0 -7
- package/dist/cjs/extractor/hoistClassNames.js.map +0 -7
- package/dist/cjs/extractor/literalToAst.js.map +0 -7
- package/dist/cjs/extractor/loadTamagui.js +0 -139
- package/dist/cjs/extractor/loadTamagui.js.map +0 -7
- package/dist/cjs/extractor/logLines.js.map +0 -7
- package/dist/cjs/extractor/normalizeTernaries.js.map +0 -7
- package/dist/cjs/extractor/removeUnusedHooks.js.map +0 -7
- package/dist/cjs/extractor/timer.js.map +0 -7
- package/dist/cjs/extractor/validHTMLAttributes.js.map +0 -7
- package/dist/cjs/index.js.map +0 -7
- package/dist/cjs/types.js.map +0 -7
- package/dist/esm/constants.js +0 -14
- package/dist/esm/constants.js.map +0 -7
- package/dist/esm/extractor/accessSafe.js +0 -8
- package/dist/esm/extractor/babelParse.js +0 -28
- package/dist/esm/extractor/babelParse.js.map +0 -7
- package/dist/esm/extractor/buildClassName.js +0 -37
- package/dist/esm/extractor/buildClassName.js.map +0 -7
- package/dist/esm/extractor/createEvaluator.js +0 -53
- package/dist/esm/extractor/createEvaluator.js.map +0 -7
- package/dist/esm/extractor/createExtractor.js +0 -1379
- package/dist/esm/extractor/createExtractor.js.map +0 -7
- package/dist/esm/extractor/ensureImportingConcat.js +0 -21
- package/dist/esm/extractor/ensureImportingConcat.js.map +0 -7
- package/dist/esm/extractor/evaluateAstNode.js +0 -91
- package/dist/esm/extractor/evaluateAstNode.js.map +0 -7
- package/dist/esm/extractor/extractHelpers.js +0 -97
- package/dist/esm/extractor/extractHelpers.js.map +0 -7
- package/dist/esm/extractor/extractMediaStyle.js +0 -161
- package/dist/esm/extractor/extractMediaStyle.js.map +0 -7
- package/dist/esm/extractor/extractToClassNames.js +0 -294
- package/dist/esm/extractor/extractToClassNames.js.map +0 -7
- package/dist/esm/extractor/findTopmostFunction.js +0 -20
- package/dist/esm/extractor/findTopmostFunction.js.map +0 -7
- package/dist/esm/extractor/generatedUid.js +0 -25
- package/dist/esm/extractor/generatedUid.js.map +0 -7
- package/dist/esm/extractor/getPrefixLogs.js +0 -8
- package/dist/esm/extractor/getPrefixLogs.js.map +0 -7
- package/dist/esm/extractor/getPropValueFromAttributes.js +0 -46
- package/dist/esm/extractor/getPropValueFromAttributes.js.map +0 -7
- package/dist/esm/extractor/getSourceModule.js +0 -66
- package/dist/esm/extractor/getStaticBindingsForScope.js +0 -132
- package/dist/esm/extractor/getStaticBindingsForScope.js.map +0 -7
- package/dist/esm/extractor/hoistClassNames.js +0 -40
- package/dist/esm/extractor/hoistClassNames.js.map +0 -7
- package/dist/esm/extractor/literalToAst.js +0 -90
- package/dist/esm/extractor/literalToAst.js.map +0 -7
- package/dist/esm/extractor/loadTamagui.js +0 -117
- package/dist/esm/extractor/loadTamagui.js.map +0 -7
- package/dist/esm/extractor/logLines.js +0 -20
- package/dist/esm/extractor/logLines.js.map +0 -7
- package/dist/esm/extractor/normalizeTernaries.js +0 -79
- package/dist/esm/extractor/normalizeTernaries.js.map +0 -7
- package/dist/esm/extractor/removeUnusedHooks.js +0 -76
- package/dist/esm/extractor/removeUnusedHooks.js.map +0 -7
- package/dist/esm/extractor/timer.js +0 -22
- package/dist/esm/extractor/timer.js.map +0 -7
- package/dist/esm/extractor/validHTMLAttributes.js +0 -102
- package/dist/esm/extractor/validHTMLAttributes.js.map +0 -7
- package/dist/esm/index.js +0 -15
- package/dist/esm/index.js.map +0 -7
- package/dist/esm/types.js +0 -1
- package/dist/esm/types.js.map +0 -7
- package/dist/jsx/constants.js +0 -14
- package/dist/jsx/constants.js.map +0 -7
- package/dist/jsx/extractor/accessSafe.js +0 -8
- package/dist/jsx/extractor/accessSafe.js.map +0 -7
- package/dist/jsx/extractor/babelParse.js +0 -28
- package/dist/jsx/extractor/babelParse.js.map +0 -7
- package/dist/jsx/extractor/buildClassName.js +0 -37
- package/dist/jsx/extractor/buildClassName.js.map +0 -7
- package/dist/jsx/extractor/createEvaluator.js +0 -53
- package/dist/jsx/extractor/createEvaluator.js.map +0 -7
- package/dist/jsx/extractor/createExtractor.js +0 -1343
- package/dist/jsx/extractor/createExtractor.js.map +0 -7
- package/dist/jsx/extractor/ensureImportingConcat.js +0 -21
- package/dist/jsx/extractor/ensureImportingConcat.js.map +0 -7
- package/dist/jsx/extractor/evaluateAstNode.js +0 -91
- package/dist/jsx/extractor/evaluateAstNode.js.map +0 -7
- package/dist/jsx/extractor/extractHelpers.js +0 -97
- package/dist/jsx/extractor/extractHelpers.js.map +0 -7
- package/dist/jsx/extractor/extractMediaStyle.js +0 -146
- package/dist/jsx/extractor/extractMediaStyle.js.map +0 -7
- package/dist/jsx/extractor/extractToClassNames.js +0 -280
- package/dist/jsx/extractor/extractToClassNames.js.map +0 -7
- package/dist/jsx/extractor/findTopmostFunction.js +0 -20
- package/dist/jsx/extractor/findTopmostFunction.js.map +0 -7
- package/dist/jsx/extractor/generatedUid.js +0 -25
- package/dist/jsx/extractor/generatedUid.js.map +0 -7
- package/dist/jsx/extractor/getPrefixLogs.js +0 -9
- package/dist/jsx/extractor/getPrefixLogs.js.map +0 -7
- package/dist/jsx/extractor/getPropValueFromAttributes.js +0 -46
- package/dist/jsx/extractor/getPropValueFromAttributes.js.map +0 -7
- package/dist/jsx/extractor/getSourceModule.js +0 -66
- package/dist/jsx/extractor/getSourceModule.js.map +0 -7
- package/dist/jsx/extractor/getStaticBindingsForScope.js +0 -132
- package/dist/jsx/extractor/getStaticBindingsForScope.js.map +0 -7
- package/dist/jsx/extractor/hoistClassNames.js +0 -40
- package/dist/jsx/extractor/literalToAst.js +0 -75
- package/dist/jsx/extractor/loadTamagui.js +0 -102
- package/dist/jsx/extractor/loadTamagui.js.map +0 -7
- package/dist/jsx/extractor/logLines.js +0 -20
- package/dist/jsx/extractor/logLines.js.map +0 -7
- package/dist/jsx/extractor/normalizeTernaries.js +0 -50
- package/dist/jsx/extractor/normalizeTernaries.js.map +0 -7
- package/dist/jsx/extractor/removeUnusedHooks.js +0 -77
- package/dist/jsx/extractor/removeUnusedHooks.js.map +0 -7
- package/dist/jsx/extractor/timer.js +0 -22
- package/dist/jsx/extractor/timer.js.map +0 -7
- package/dist/jsx/extractor/validHTMLAttributes.js +0 -102
- package/dist/jsx/index.js +0 -15
- package/dist/jsx/index.js.map +0 -7
- package/dist/jsx/types.js +0 -1
- package/dist/jsx/types.js.map +0 -7
- package/types/extractor/buildClassName.d.ts.map +0 -1
- package/types/extractor/createEvaluator.d.ts.map +0 -1
- package/types/extractor/createExtractor.d.ts.map +0 -1
- package/types/extractor/extractHelpers.d.ts.map +0 -1
- package/types/extractor/extractMediaStyle.d.ts.map +0 -1
- package/types/extractor/extractToClassNames.d.ts.map +0 -1
- package/types/extractor/getPrefixLogs.d.ts.map +0 -1
- package/types/extractor/loadTamagui.d.ts.map +0 -1
- package/types/extractor/normalizeTernaries.d.ts.map +0 -1
- package/types/index.d.ts.map +0 -1
- package/types/types.d.ts.map +0 -1
|
@@ -1,43 +1,53 @@
|
|
|
1
|
-
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
import { basename, relative } from 'path'
|
|
2
3
|
|
|
3
|
-
import traverse, { NodePath,
|
|
4
|
+
import traverse, { NodePath, TraverseOptions } from '@babel/traverse'
|
|
4
5
|
import * as t from '@babel/types'
|
|
5
6
|
import {
|
|
6
7
|
PseudoStyles,
|
|
7
8
|
StaticConfigParsed,
|
|
8
|
-
TamaguiInternalConfig,
|
|
9
|
-
createDOMProps,
|
|
10
9
|
expandStyles,
|
|
11
10
|
getSplitStyles,
|
|
12
11
|
getStylesAtomic,
|
|
13
12
|
mediaQueryConfig,
|
|
14
13
|
proxyThemeVariables,
|
|
15
14
|
pseudoDescriptors,
|
|
16
|
-
stylePropsTransform,
|
|
17
15
|
} from '@tamagui/core-node'
|
|
18
|
-
import { difference, pick } from 'lodash'
|
|
19
16
|
import type { ViewStyle } from 'react-native'
|
|
17
|
+
import { createDOMProps } from 'react-native-web-internals'
|
|
20
18
|
|
|
21
|
-
import { FAILED_EVAL } from '../constants'
|
|
22
|
-
import {
|
|
19
|
+
import { FAILED_EVAL } from '../constants.js'
|
|
20
|
+
import type {
|
|
23
21
|
ExtractedAttr,
|
|
24
22
|
ExtractedAttrAttr,
|
|
25
23
|
ExtractedAttrStyle,
|
|
24
|
+
ExtractorOptions,
|
|
26
25
|
ExtractorParseProps,
|
|
26
|
+
TamaguiOptions,
|
|
27
|
+
TamaguiOptionsWithFileInfo,
|
|
27
28
|
Ternary,
|
|
28
|
-
} from '../types'
|
|
29
|
-
import { createEvaluator, createSafeEvaluator } from './createEvaluator'
|
|
30
|
-
import { evaluateAstNode } from './evaluateAstNode'
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
import {
|
|
29
|
+
} from '../types.js'
|
|
30
|
+
import { createEvaluator, createSafeEvaluator } from './createEvaluator.js'
|
|
31
|
+
import { evaluateAstNode } from './evaluateAstNode.js'
|
|
32
|
+
import {
|
|
33
|
+
attrStr,
|
|
34
|
+
findComponentName,
|
|
35
|
+
getValidComponent,
|
|
36
|
+
getValidImport,
|
|
37
|
+
isPresent,
|
|
38
|
+
isValidImport,
|
|
39
|
+
objToStr,
|
|
40
|
+
} from './extractHelpers.js'
|
|
41
|
+
import { findTopmostFunction } from './findTopmostFunction.js'
|
|
42
|
+
import { getPrefixLogs } from './getPrefixLogs.js'
|
|
43
|
+
import { cleanupBeforeExit, getStaticBindingsForScope } from './getStaticBindingsForScope.js'
|
|
44
|
+
import { literalToAst } from './literalToAst.js'
|
|
45
|
+
import { TamaguiProjectInfo, loadTamagui, loadTamaguiSync } from './loadTamagui.js'
|
|
46
|
+
import { logLines } from './logLines.js'
|
|
47
|
+
import { normalizeTernaries } from './normalizeTernaries.js'
|
|
48
|
+
import { removeUnusedHooks } from './removeUnusedHooks.js'
|
|
49
|
+
import { timer } from './timer.js'
|
|
50
|
+
import { validHTMLAttributes } from './validHTMLAttributes.js'
|
|
41
51
|
|
|
42
52
|
const UNTOUCHED_PROPS = {
|
|
43
53
|
key: true,
|
|
@@ -48,25 +58,30 @@ const UNTOUCHED_PROPS = {
|
|
|
48
58
|
const INLINE_EXTRACTABLE = {
|
|
49
59
|
ref: 'ref',
|
|
50
60
|
key: 'key',
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
61
|
+
...(process.env.TAMAGUI_TARGET === 'web' && {
|
|
62
|
+
onPress: 'onClick',
|
|
63
|
+
onHoverIn: 'onMouseEnter',
|
|
64
|
+
onHoverOut: 'onMouseLeave',
|
|
65
|
+
onPressIn: 'onMouseDown',
|
|
66
|
+
onPressOut: 'onMouseUp',
|
|
67
|
+
}),
|
|
56
68
|
}
|
|
57
69
|
|
|
58
|
-
const isAttr = (x: ExtractedAttr): x is ExtractedAttrAttr => x.type === 'attr'
|
|
59
|
-
|
|
60
70
|
const validHooks = {
|
|
61
71
|
useMedia: true,
|
|
62
72
|
useTheme: true,
|
|
63
73
|
}
|
|
64
74
|
|
|
75
|
+
const isAttr = (x: ExtractedAttr): x is ExtractedAttrAttr => x.type === 'attr'
|
|
76
|
+
const createTernary = (x: Ternary) => x
|
|
77
|
+
|
|
65
78
|
export type Extractor = ReturnType<typeof createExtractor>
|
|
66
79
|
|
|
67
|
-
|
|
80
|
+
type FileOrPath = NodePath<t.Program> | t.File
|
|
68
81
|
|
|
69
|
-
|
|
82
|
+
let hasLoggedBaseInfo = false
|
|
83
|
+
|
|
84
|
+
export function createExtractor({ logger = console }: ExtractorOptions = { logger: console }) {
|
|
70
85
|
if (!process.env.TAMAGUI_TARGET) {
|
|
71
86
|
console.log('⚠️ Please set process.env.TAMAGUI_TARGET to either "web" or "native"')
|
|
72
87
|
process.exit(1)
|
|
@@ -79,1248 +94,1451 @@ export function createExtractor() {
|
|
|
79
94
|
process.env.IDENTIFY_TAGS !== 'false' &&
|
|
80
95
|
(process.env.NODE_ENV === 'development' || process.env.DEBUG || process.env.IDENTIFY_TAGS)
|
|
81
96
|
|
|
82
|
-
let
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
97
|
+
let projectInfo: TamaguiProjectInfo | null = null
|
|
98
|
+
|
|
99
|
+
// we load tamagui delayed because we need to set some global/env stuff before importing
|
|
100
|
+
// otherwise we'd import `rnw` and cause it to evaluate react-native-web which causes errors
|
|
101
|
+
|
|
102
|
+
function loadSync(props: TamaguiOptions) {
|
|
103
|
+
return (projectInfo ||= loadTamaguiSync({
|
|
104
|
+
config: props.config || 'tamagui.config.ts',
|
|
105
|
+
components: props.components || ['tamagui'],
|
|
106
|
+
}))
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function load(props: TamaguiOptions) {
|
|
110
|
+
return (projectInfo ||= await loadTamagui({
|
|
111
|
+
config: props.config || 'tamagui.config.ts',
|
|
112
|
+
components: props.components || ['tamagui'],
|
|
113
|
+
}))
|
|
94
114
|
}
|
|
95
115
|
|
|
96
116
|
return {
|
|
117
|
+
options: {
|
|
118
|
+
logger,
|
|
119
|
+
},
|
|
120
|
+
cleanupBeforeExit,
|
|
121
|
+
loadTamagui: load,
|
|
122
|
+
loadTamaguiSync: loadSync,
|
|
97
123
|
getTamagui() {
|
|
98
|
-
return
|
|
124
|
+
return projectInfo?.tamaguiConfig
|
|
99
125
|
},
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
126
|
+
parseSync: (f: FileOrPath, props: ExtractorParseProps) => {
|
|
127
|
+
const projectInfo = loadSync(props)
|
|
128
|
+
return parseWithConfig(projectInfo, f, props)
|
|
129
|
+
},
|
|
130
|
+
parse: async (f: FileOrPath, props: ExtractorParseProps) => {
|
|
131
|
+
const projectInfo = await load(props)
|
|
132
|
+
return parseWithConfig(projectInfo, f, props)
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function parseWithConfig(
|
|
137
|
+
{ components, tamaguiConfig }: TamaguiProjectInfo,
|
|
138
|
+
fileOrPath: FileOrPath,
|
|
139
|
+
options: ExtractorParseProps
|
|
140
|
+
) {
|
|
141
|
+
const {
|
|
142
|
+
config = 'tamagui.config.ts',
|
|
143
|
+
importsWhitelist = ['constants.js'],
|
|
144
|
+
evaluateVars = true,
|
|
145
|
+
sourcePath = '',
|
|
146
|
+
onExtractTag,
|
|
147
|
+
onStyleRule,
|
|
148
|
+
getFlattenedNode,
|
|
149
|
+
disable,
|
|
150
|
+
disableExtraction,
|
|
151
|
+
disableExtractInlineMedia,
|
|
152
|
+
disableExtractVariables,
|
|
153
|
+
disableDebugAttr,
|
|
154
|
+
disableExtractFoundComponents,
|
|
155
|
+
includeExtensions = ['.tsx', '.jsx', '.js'],
|
|
156
|
+
extractStyledDefinitions = false,
|
|
157
|
+
prefixLogs,
|
|
158
|
+
excludeProps,
|
|
159
|
+
target,
|
|
160
|
+
...restProps
|
|
161
|
+
} = options
|
|
162
|
+
|
|
163
|
+
let shouldPrintDebug = options.shouldPrintDebug || false
|
|
164
|
+
|
|
165
|
+
if (disable === true || (Array.isArray(disable) && disable.includes(sourcePath))) {
|
|
166
|
+
return null
|
|
167
|
+
}
|
|
168
|
+
if (sourcePath === '') {
|
|
169
|
+
throw new Error(`Must provide a source file name`)
|
|
170
|
+
}
|
|
171
|
+
if (!components) {
|
|
172
|
+
throw new Error(`Must provide components`)
|
|
173
|
+
}
|
|
174
|
+
if (includeExtensions && !includeExtensions.some((ext) => sourcePath.endsWith(ext))) {
|
|
175
|
+
if (shouldPrintDebug) {
|
|
176
|
+
logger.info(
|
|
177
|
+
`Ignoring file due to includeExtensions: ${sourcePath}, includeExtensions: ${includeExtensions.join(
|
|
178
|
+
', '
|
|
179
|
+
)}`
|
|
180
|
+
)
|
|
125
181
|
}
|
|
126
|
-
|
|
127
|
-
|
|
182
|
+
return null
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function isValidStyleKey(name: string, staticConfig: StaticConfigParsed) {
|
|
186
|
+
if (!projectInfo) {
|
|
187
|
+
throw new Error(`Tamagui extractor not loaded yet`)
|
|
128
188
|
}
|
|
129
|
-
if (
|
|
130
|
-
|
|
189
|
+
if (target === 'native' && name[0] === '$' && mediaQueryConfig[name.slice(1)]) {
|
|
190
|
+
return false
|
|
131
191
|
}
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
192
|
+
return !!(
|
|
193
|
+
!!staticConfig.validStyles?.[name] ||
|
|
194
|
+
!!pseudoDescriptors[name] ||
|
|
195
|
+
// dont disable variants or else you lose many things flattening
|
|
196
|
+
staticConfig.variants?.[name] ||
|
|
197
|
+
projectInfo?.tamaguiConfig.shorthands[name] ||
|
|
198
|
+
(name[0] === '$' ? !!mediaQueryConfig[name.slice(1)] : false)
|
|
199
|
+
)
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Step 1: Determine if importing any statically extractable components
|
|
204
|
+
*/
|
|
205
|
+
|
|
206
|
+
const isTargetingHTML = target === 'html'
|
|
207
|
+
const ogDebug = shouldPrintDebug
|
|
208
|
+
const tm = timer()
|
|
209
|
+
const propsWithFileInfo: TamaguiOptionsWithFileInfo = {
|
|
210
|
+
...options,
|
|
211
|
+
sourcePath,
|
|
212
|
+
allLoadedComponents: [...components],
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (!hasLoggedBaseInfo) {
|
|
216
|
+
hasLoggedBaseInfo = true
|
|
217
|
+
if (shouldPrintDebug) {
|
|
218
|
+
logger.info(
|
|
219
|
+
[
|
|
220
|
+
'loaded components:',
|
|
221
|
+
propsWithFileInfo.allLoadedComponents
|
|
222
|
+
.map((comp) => Object.keys(comp.nameToInfo).join(', '))
|
|
223
|
+
.join(', '),
|
|
224
|
+
].join(' ')
|
|
225
|
+
)
|
|
146
226
|
}
|
|
227
|
+
if (process.env.DEBUG?.startsWith('tamagui')) {
|
|
228
|
+
const next = [...propsWithFileInfo.allLoadedComponents].map((info) => {
|
|
229
|
+
const nameToInfo = { ...info.nameToInfo }
|
|
230
|
+
for (const key in nameToInfo) {
|
|
231
|
+
delete nameToInfo[key].staticConfig.validStyles
|
|
232
|
+
}
|
|
233
|
+
return { ...info, nameToInfo }
|
|
234
|
+
})
|
|
235
|
+
logger.info(['loaded:', JSON.stringify(next, null, 2)].join('\n'))
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
tm.mark('load-tamagui', !!shouldPrintDebug)
|
|
240
|
+
|
|
241
|
+
const firstThemeName = Object.keys(tamaguiConfig.themes)[0]
|
|
242
|
+
const firstTheme = tamaguiConfig.themes[firstThemeName]
|
|
243
|
+
|
|
244
|
+
if (!firstTheme || typeof firstTheme !== 'object') {
|
|
245
|
+
console.error(`Missing theme, an error occurred when importing your config`)
|
|
246
|
+
console.log(`Got config:`, tamaguiConfig)
|
|
247
|
+
console.log(`Looking for theme:`, firstThemeName)
|
|
248
|
+
process.exit(0)
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
const proxiedTheme = proxyThemeVariables(firstTheme)
|
|
252
|
+
type AccessListener = (key: string) => void
|
|
253
|
+
const themeAccessListeners = new Set<AccessListener>()
|
|
254
|
+
const defaultTheme = new Proxy(proxiedTheme, {
|
|
255
|
+
get(target, key) {
|
|
256
|
+
if (Reflect.has(target, key)) {
|
|
257
|
+
themeAccessListeners.forEach((cb) => cb(String(key)))
|
|
258
|
+
}
|
|
259
|
+
return Reflect.get(target, key)
|
|
260
|
+
},
|
|
261
|
+
})
|
|
147
262
|
|
|
148
|
-
|
|
263
|
+
// @ts-ignore
|
|
264
|
+
const body = fileOrPath.type === 'Program' ? fileOrPath.get('body') : fileOrPath.program.body
|
|
149
265
|
|
|
150
|
-
|
|
266
|
+
if (Object.keys(components).length === 0) {
|
|
267
|
+
console.warn(`Warning: Tamagui didn't find any valid components (DEBUG=tamagui for more)`)
|
|
268
|
+
if (process.env.DEBUG === 'tamagui') {
|
|
269
|
+
console.log(`components`, Object.keys(components), components)
|
|
270
|
+
}
|
|
271
|
+
}
|
|
151
272
|
|
|
152
|
-
|
|
153
|
-
|
|
273
|
+
if (shouldPrintDebug === 'verbose') {
|
|
274
|
+
logger.info(
|
|
275
|
+
`allLoadedComponent modules ${propsWithFileInfo.allLoadedComponents
|
|
276
|
+
.map((k) => k.moduleName)
|
|
277
|
+
.join(', ')}`
|
|
154
278
|
)
|
|
279
|
+
}
|
|
155
280
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const defaultTheme = new Proxy(proxiedTheme, {
|
|
159
|
-
get(target, key) {
|
|
160
|
-
if (key[0] === '$') {
|
|
161
|
-
themeAccessListeners.forEach((cb) => cb(String(key)))
|
|
162
|
-
}
|
|
163
|
-
return Reflect.get(target, key)
|
|
164
|
-
},
|
|
165
|
-
})
|
|
281
|
+
let doesUseValidImport = false
|
|
282
|
+
let hasImportedTheme = false
|
|
166
283
|
|
|
167
|
-
|
|
284
|
+
const importDeclarations: t.ImportDeclaration[] = []
|
|
168
285
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
return isInsideTamagui(sourcePath) && importStr[0] === '.'
|
|
174
|
-
}
|
|
286
|
+
for (const bodyPath of body) {
|
|
287
|
+
if (bodyPath.type !== 'ImportDeclaration') continue
|
|
288
|
+
const node = ('node' in bodyPath ? bodyPath.node : bodyPath) as t.ImportDeclaration
|
|
289
|
+
const moduleName = node.source.value
|
|
175
290
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
.filter((key) => key[0].toUpperCase() === key[0] && !!components[key]?.staticConfig)
|
|
179
|
-
.reduce((obj, name) => {
|
|
180
|
-
obj[name] = components[name]
|
|
181
|
-
return obj
|
|
182
|
-
}, {})
|
|
291
|
+
// if importing valid module
|
|
292
|
+
const valid = isValidImport(propsWithFileInfo, moduleName)
|
|
183
293
|
|
|
184
|
-
if (
|
|
185
|
-
|
|
294
|
+
if (valid) {
|
|
295
|
+
importDeclarations.push(node)
|
|
186
296
|
}
|
|
187
297
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
for (const bodyPath of body) {
|
|
192
|
-
if (bodyPath.type !== 'ImportDeclaration') continue
|
|
193
|
-
const node = ('node' in bodyPath ? bodyPath.node : bodyPath) as t.ImportDeclaration
|
|
194
|
-
const from = node.source.value
|
|
195
|
-
// if importing styled()
|
|
196
|
-
if (extractStyledDefinitions) {
|
|
197
|
-
if (from === '@tamagui/core' || from === 'tamagui') {
|
|
198
|
-
if (
|
|
199
|
-
node.specifiers.some((specifier) => {
|
|
200
|
-
return specifier.local.name === 'styled'
|
|
201
|
-
})
|
|
202
|
-
) {
|
|
203
|
-
doesUseValidImport = true
|
|
204
|
-
break
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
const isValidImport = props.components.includes(from) || isInternalImport(from)
|
|
209
|
-
if (isValidImport) {
|
|
210
|
-
const isValidComponent = node.specifiers.some((specifier) => {
|
|
211
|
-
const name = specifier.local.name
|
|
212
|
-
return !!(validComponents[name] || validHooks[name])
|
|
213
|
-
})
|
|
214
|
-
if (shouldPrintDebug === 'verbose') {
|
|
215
|
-
console.log('import from', from, { isValidComponent })
|
|
216
|
-
}
|
|
217
|
-
if (isValidComponent) {
|
|
298
|
+
if (extractStyledDefinitions) {
|
|
299
|
+
if (valid) {
|
|
300
|
+
if (node.specifiers.some((specifier) => specifier.local.name === 'styled')) {
|
|
218
301
|
doesUseValidImport = true
|
|
219
302
|
break
|
|
220
303
|
}
|
|
221
304
|
}
|
|
222
305
|
}
|
|
223
306
|
|
|
224
|
-
if (
|
|
225
|
-
|
|
307
|
+
if (valid) {
|
|
308
|
+
const names = node.specifiers.map((specifier) => specifier.local.name)
|
|
309
|
+
const isValidComponent = names.some((name) =>
|
|
310
|
+
Boolean(isValidImport(propsWithFileInfo, moduleName, name) || validHooks[name])
|
|
311
|
+
)
|
|
312
|
+
if (shouldPrintDebug === 'verbose') {
|
|
313
|
+
logger.info(
|
|
314
|
+
`import ${names.join(', ')} from ${moduleName} isValidComponent ${isValidComponent}`
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
if (isValidComponent) {
|
|
318
|
+
doesUseValidImport = true
|
|
319
|
+
break
|
|
320
|
+
}
|
|
226
321
|
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (shouldPrintDebug) {
|
|
325
|
+
logger.info(`file: ${sourcePath} ${JSON.stringify({ doesUseValidImport, hasImportedTheme })}`)
|
|
326
|
+
}
|
|
227
327
|
|
|
228
|
-
|
|
328
|
+
if (!doesUseValidImport) {
|
|
329
|
+
return null
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function getValidImportedComponent(componentName: string) {
|
|
333
|
+
const importDeclaration = importDeclarations.find((dec) =>
|
|
334
|
+
dec.specifiers.some((spec) => spec.local.name === componentName)
|
|
335
|
+
)
|
|
336
|
+
if (!importDeclaration) {
|
|
229
337
|
return null
|
|
230
338
|
}
|
|
339
|
+
return getValidImport(propsWithFileInfo, importDeclaration.source.value, componentName)
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
tm.mark('import-check', !!shouldPrintDebug)
|
|
343
|
+
|
|
344
|
+
let couldntParse = false
|
|
345
|
+
const modifiedComponents = new Set<NodePath<any>>()
|
|
346
|
+
|
|
347
|
+
// only keeping a cache around per-file, reset it if it changes
|
|
348
|
+
const bindingCache: Record<string, string | null> = {}
|
|
349
|
+
|
|
350
|
+
const callTraverse = (a: TraverseOptions<any>) => {
|
|
351
|
+
return fileOrPath.type === 'File' ? traverse(fileOrPath, a) : fileOrPath.traverse(a)
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const shouldDisableExtraction =
|
|
355
|
+
disableExtraction === true ||
|
|
356
|
+
(Array.isArray(disableExtraction) && disableExtraction.includes(sourcePath))
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Step 2: Statically extract from JSX < /> nodes
|
|
360
|
+
*/
|
|
361
|
+
let programPath: NodePath<t.Program> | null = null
|
|
362
|
+
|
|
363
|
+
const res = {
|
|
364
|
+
styled: 0,
|
|
365
|
+
flattened: 0,
|
|
366
|
+
optimized: 0,
|
|
367
|
+
modified: 0,
|
|
368
|
+
found: 0,
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
callTraverse({
|
|
372
|
+
// @ts-ignore
|
|
373
|
+
Program: {
|
|
374
|
+
enter(path) {
|
|
375
|
+
programPath = path
|
|
376
|
+
},
|
|
377
|
+
},
|
|
231
378
|
|
|
232
|
-
|
|
379
|
+
// styled() calls
|
|
380
|
+
CallExpression(path) {
|
|
381
|
+
if (disable || shouldDisableExtraction || extractStyledDefinitions === false) {
|
|
382
|
+
return
|
|
383
|
+
}
|
|
233
384
|
|
|
234
|
-
|
|
235
|
-
|
|
385
|
+
if (!t.isIdentifier(path.node.callee) || path.node.callee.name !== 'styled') {
|
|
386
|
+
return
|
|
387
|
+
}
|
|
236
388
|
|
|
237
|
-
|
|
238
|
-
|
|
389
|
+
const name =
|
|
390
|
+
t.isVariableDeclarator(path.parent) && t.isIdentifier(path.parent.id)
|
|
391
|
+
? path.parent.id.name
|
|
392
|
+
: 'unknown'
|
|
239
393
|
|
|
240
|
-
|
|
241
|
-
return fileOrPath.type === 'File' ? traverse(fileOrPath, a) : fileOrPath.traverse(a)
|
|
242
|
-
}
|
|
394
|
+
const definition = path.node.arguments[1]
|
|
243
395
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
let programPath: NodePath<t.Program>
|
|
248
|
-
|
|
249
|
-
const res = {
|
|
250
|
-
styled: 0,
|
|
251
|
-
flattened: 0,
|
|
252
|
-
optimized: 0,
|
|
253
|
-
modified: 0,
|
|
254
|
-
found: 0,
|
|
255
|
-
}
|
|
396
|
+
if (!name || !definition || !t.isObjectExpression(definition)) {
|
|
397
|
+
return
|
|
398
|
+
}
|
|
256
399
|
|
|
257
|
-
|
|
258
|
-
Program: {
|
|
259
|
-
enter(path) {
|
|
260
|
-
programPath = path
|
|
261
|
-
},
|
|
262
|
-
},
|
|
400
|
+
let Component = getValidImportedComponent(name)
|
|
263
401
|
|
|
264
|
-
|
|
265
|
-
if (
|
|
402
|
+
if (!Component) {
|
|
403
|
+
if (disableExtractFoundComponents === true) {
|
|
266
404
|
return
|
|
267
405
|
}
|
|
268
|
-
|
|
269
|
-
|
|
406
|
+
if (
|
|
407
|
+
Array.isArray(disableExtractFoundComponents) &&
|
|
408
|
+
disableExtractFoundComponents.includes(name)
|
|
409
|
+
) {
|
|
270
410
|
return
|
|
271
411
|
}
|
|
272
412
|
|
|
273
|
-
|
|
274
|
-
t.isVariableDeclarator(path.parent) && t.isIdentifier(path.parent.id)
|
|
275
|
-
? path.parent.id.name
|
|
276
|
-
: 'unknown'
|
|
277
|
-
const definition = path.node.arguments[1]
|
|
278
|
-
|
|
279
|
-
if (!name || !definition || !t.isObjectExpression(definition)) {
|
|
280
|
-
return
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
const Component = validComponents[name] as
|
|
284
|
-
| { staticConfig: StaticConfigParsed }
|
|
285
|
-
| undefined
|
|
286
|
-
|
|
287
|
-
if (!Component) {
|
|
413
|
+
try {
|
|
288
414
|
if (shouldPrintDebug) {
|
|
289
|
-
|
|
290
|
-
`Didn't recognize styled(${name}), ${name} isn't in design system provided to tamagui.config.ts`
|
|
291
|
-
)
|
|
415
|
+
logger.info(`Unknown component ${name}, attempting dynamic load: ${sourcePath}`)
|
|
292
416
|
}
|
|
293
|
-
return
|
|
294
|
-
}
|
|
295
417
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
// for now skip variants, will return to them
|
|
301
|
-
'variants',
|
|
302
|
-
'defaultVariants',
|
|
303
|
-
// skip fontFamily its basically a "variant", important for theme use to be value always
|
|
304
|
-
'fontFamily',
|
|
305
|
-
'name',
|
|
306
|
-
])
|
|
418
|
+
const out = loadTamaguiSync({
|
|
419
|
+
forceExports: true,
|
|
420
|
+
components: [sourcePath],
|
|
421
|
+
})
|
|
307
422
|
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
423
|
+
if (!out?.components) {
|
|
424
|
+
if (shouldPrintDebug) {
|
|
425
|
+
logger.info(`Couldn't load, got ${out}`)
|
|
426
|
+
}
|
|
427
|
+
return
|
|
428
|
+
}
|
|
311
429
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
sourcePath,
|
|
317
|
-
bindingCache,
|
|
318
|
-
shouldPrintDebug
|
|
319
|
-
)
|
|
430
|
+
propsWithFileInfo.allLoadedComponents = [
|
|
431
|
+
...propsWithFileInfo.allLoadedComponents,
|
|
432
|
+
...out.components,
|
|
433
|
+
]
|
|
320
434
|
|
|
321
|
-
|
|
322
|
-
? evaluateAstNode
|
|
323
|
-
: createEvaluator({
|
|
324
|
-
tamaguiConfig,
|
|
325
|
-
staticNamespace,
|
|
326
|
-
sourcePath,
|
|
327
|
-
shouldPrintDebug,
|
|
328
|
-
})
|
|
329
|
-
const attemptEvalSafe = createSafeEvaluator(attemptEval)
|
|
435
|
+
Component = out.components.flatMap((x) => x.nameToInfo[name] ?? [])[0]
|
|
330
436
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
!t.isObjectProperty(property) ||
|
|
334
|
-
!t.isIdentifier(property.key) ||
|
|
335
|
-
!isValidStyleKey(property.key.name, Component.staticConfig) ||
|
|
336
|
-
// skip variants
|
|
337
|
-
Component.staticConfig.variants?.[property.key.name] ||
|
|
338
|
-
componentSkipProps.has(property.key.name)
|
|
339
|
-
) {
|
|
340
|
-
skipped.push(property)
|
|
341
|
-
continue
|
|
437
|
+
if (shouldPrintDebug === 'verbose') {
|
|
438
|
+
logger.info([`Tamagui Loaded`, JSON.stringify(out.components), !!Component].join(' '))
|
|
342
439
|
}
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
440
|
+
} catch (err: any) {
|
|
441
|
+
if (shouldPrintDebug) {
|
|
442
|
+
logger.info(
|
|
443
|
+
`${getPrefixLogs(
|
|
444
|
+
options
|
|
445
|
+
)} skip optimize styled(${name}), unable to pre-process (DEBUG=tamagui for more)`
|
|
446
|
+
)
|
|
447
|
+
}
|
|
448
|
+
if (process.env.DEBUG === 'tamagui') {
|
|
449
|
+
logger.info(
|
|
450
|
+
` Disable this with "disableExtractFoundComponents" in your build-time configuration. \n\n ${err.message} ${err.stack}`
|
|
451
|
+
)
|
|
349
452
|
}
|
|
350
453
|
}
|
|
454
|
+
}
|
|
351
455
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
hover: false,
|
|
356
|
-
mounted: false,
|
|
357
|
-
press: false,
|
|
358
|
-
pressIn: false,
|
|
359
|
-
resolveVariablesAs: 'variable',
|
|
360
|
-
})
|
|
456
|
+
if (!Component) {
|
|
457
|
+
return
|
|
458
|
+
}
|
|
361
459
|
|
|
362
|
-
|
|
363
|
-
|
|
460
|
+
const componentSkipProps = new Set([
|
|
461
|
+
...(Component.staticConfig.inlineWhenUnflattened || []),
|
|
462
|
+
...(Component.staticConfig.inlineProps || []),
|
|
463
|
+
...(Component.staticConfig.deoptProps || []),
|
|
464
|
+
// for now skip variants, will return to them
|
|
465
|
+
'variants',
|
|
466
|
+
'defaultVariants',
|
|
467
|
+
// skip fontFamily its basically a "variant", important for theme use to be value always
|
|
468
|
+
'fontFamily',
|
|
469
|
+
'name',
|
|
470
|
+
])
|
|
471
|
+
|
|
472
|
+
// for now dont parse variants, spreads, etc
|
|
473
|
+
const skipped: (t.ObjectProperty | t.SpreadElement | t.ObjectMethod)[] = []
|
|
474
|
+
const styles = {}
|
|
475
|
+
|
|
476
|
+
// Generate scope object at this level
|
|
477
|
+
const staticNamespace = getStaticBindingsForScope(
|
|
478
|
+
path.scope,
|
|
479
|
+
importsWhitelist,
|
|
480
|
+
sourcePath,
|
|
481
|
+
bindingCache,
|
|
482
|
+
shouldPrintDebug
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
const attemptEval = !evaluateVars
|
|
486
|
+
? evaluateAstNode
|
|
487
|
+
: createEvaluator({
|
|
488
|
+
props: propsWithFileInfo,
|
|
489
|
+
staticNamespace,
|
|
490
|
+
sourcePath,
|
|
491
|
+
shouldPrintDebug,
|
|
492
|
+
})
|
|
493
|
+
const attemptEvalSafe = createSafeEvaluator(attemptEval)
|
|
494
|
+
|
|
495
|
+
for (const property of definition.properties) {
|
|
496
|
+
if (
|
|
497
|
+
!t.isObjectProperty(property) ||
|
|
498
|
+
!t.isIdentifier(property.key) ||
|
|
499
|
+
!isValidStyleKey(property.key.name, Component.staticConfig) ||
|
|
500
|
+
// skip variants
|
|
501
|
+
Component.staticConfig.variants?.[property.key.name] ||
|
|
502
|
+
componentSkipProps.has(property.key.name)
|
|
503
|
+
) {
|
|
504
|
+
skipped.push(property)
|
|
505
|
+
continue
|
|
506
|
+
}
|
|
507
|
+
// attempt eval
|
|
508
|
+
const out = attemptEvalSafe(property.value)
|
|
509
|
+
if (out === FAILED_EVAL) {
|
|
510
|
+
skipped.push(property)
|
|
511
|
+
} else {
|
|
512
|
+
styles[property.key.name] = out
|
|
364
513
|
}
|
|
514
|
+
}
|
|
365
515
|
|
|
366
|
-
|
|
367
|
-
|
|
516
|
+
const out = getSplitStyles(styles, Component.staticConfig, defaultTheme, {
|
|
517
|
+
focus: false,
|
|
518
|
+
hover: false,
|
|
519
|
+
unmounted: true,
|
|
520
|
+
press: false,
|
|
521
|
+
pressIn: false,
|
|
522
|
+
resolveVariablesAs: 'variable',
|
|
523
|
+
noClassNames: false,
|
|
524
|
+
})
|
|
525
|
+
|
|
526
|
+
const classNames = {
|
|
527
|
+
...out.classNames,
|
|
528
|
+
}
|
|
368
529
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
530
|
+
// // add in the style object as classnames
|
|
531
|
+
// const atomics = getStylesAtomic(out.style)
|
|
532
|
+
// for (const atomic of atomics) {
|
|
533
|
+
// out.rulesToInsert = out.rulesToInsert || []
|
|
534
|
+
// out.rulesToInsert.push(atomic)
|
|
535
|
+
// classNames[atomic.property] = atomic.identifier
|
|
536
|
+
// }
|
|
372
537
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
}
|
|
378
|
-
classNames[atomic.property] = atomic.identifier
|
|
379
|
-
}
|
|
538
|
+
if (shouldPrintDebug) {
|
|
539
|
+
// prettier-ignore
|
|
540
|
+
logger.info([`Extracted styled(${name})\n`, JSON.stringify(styles, null, 2), '\n rulesToInsert:', out.rulesToInsert.flatMap((rule) => rule.rules).join('\n')].join(' '))
|
|
541
|
+
}
|
|
380
542
|
|
|
381
|
-
|
|
382
|
-
|
|
543
|
+
// leave only un-parsed props...
|
|
544
|
+
definition.properties = skipped
|
|
383
545
|
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
}
|
|
389
|
-
const val = classNames[cn]
|
|
390
|
-
definition.properties.push(t.objectProperty(t.stringLiteral(cn), t.stringLiteral(val)))
|
|
546
|
+
// ... + key: className
|
|
547
|
+
for (const cn in classNames) {
|
|
548
|
+
if (componentSkipProps.has(cn)) {
|
|
549
|
+
continue
|
|
391
550
|
}
|
|
551
|
+
const val = classNames[cn]
|
|
552
|
+
definition.properties.push(t.objectProperty(t.stringLiteral(cn), t.stringLiteral(val)))
|
|
553
|
+
}
|
|
392
554
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
}
|
|
555
|
+
if (out.rulesToInsert) {
|
|
556
|
+
for (const { identifier, rules } of out.rulesToInsert) {
|
|
557
|
+
onStyleRule?.(identifier, rules)
|
|
397
558
|
}
|
|
559
|
+
}
|
|
398
560
|
|
|
399
|
-
|
|
561
|
+
res.styled++
|
|
400
562
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
563
|
+
if (shouldPrintDebug) {
|
|
564
|
+
logger.info(`Extracted styled(${name})`)
|
|
565
|
+
}
|
|
566
|
+
},
|
|
405
567
|
|
|
406
|
-
|
|
407
|
-
|
|
568
|
+
JSXElement(traversePath) {
|
|
569
|
+
if (shouldDisableExtraction) {
|
|
570
|
+
return
|
|
571
|
+
}
|
|
408
572
|
|
|
409
|
-
|
|
410
|
-
const ogAttributes = node.attributes
|
|
411
|
-
const componentName = findComponentName(traversePath.scope)
|
|
412
|
-
const closingElement = traversePath.node.closingElement
|
|
573
|
+
tm.mark('jsx-element', !!shouldPrintDebug)
|
|
413
574
|
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
575
|
+
const node = traversePath.node.openingElement
|
|
576
|
+
const ogAttributes = node.attributes.map((attr) => ({ ...attr }))
|
|
577
|
+
const componentName = findComponentName(traversePath.scope)
|
|
578
|
+
const closingElement = traversePath.node.closingElement
|
|
418
579
|
|
|
419
|
-
|
|
420
|
-
|
|
580
|
+
// skip non-identifier opening elements (member expressions, etc.)
|
|
581
|
+
if (t.isJSXMemberExpression(closingElement?.name) || !t.isJSXIdentifier(node.name)) {
|
|
582
|
+
return
|
|
583
|
+
}
|
|
421
584
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
585
|
+
// validate its a proper import from tamagui (or internally inside tamagui)
|
|
586
|
+
const binding = traversePath.scope.getBinding(node.name.name)
|
|
587
|
+
let modulePath = ''
|
|
588
|
+
|
|
589
|
+
if (binding) {
|
|
590
|
+
if (!t.isImportDeclaration(binding.path.parent)) {
|
|
591
|
+
if (shouldPrintDebug) {
|
|
592
|
+
logger.info(` - Binding not import declaration, skip`)
|
|
429
593
|
}
|
|
430
|
-
|
|
431
|
-
|
|
594
|
+
return
|
|
595
|
+
}
|
|
596
|
+
modulePath = binding.path.parent.source.value
|
|
597
|
+
if (!isValidImport(propsWithFileInfo, modulePath, binding.identifier.name)) {
|
|
598
|
+
if (shouldPrintDebug) {
|
|
599
|
+
logger.info(` - Binding not internal import or from components ${modulePath}`)
|
|
432
600
|
}
|
|
601
|
+
return
|
|
433
602
|
}
|
|
603
|
+
}
|
|
434
604
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
605
|
+
const component = getValidComponent(propsWithFileInfo, modulePath, node.name.name)
|
|
606
|
+
if (!component || !component.staticConfig) {
|
|
607
|
+
if (shouldPrintDebug) {
|
|
608
|
+
logger.info(` - No Tamagui conf on this: ${node.name.name}`)
|
|
438
609
|
}
|
|
610
|
+
return
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
const originalNodeName = node.name.name
|
|
439
614
|
|
|
440
|
-
|
|
615
|
+
// found a valid tag
|
|
616
|
+
res.found++
|
|
441
617
|
|
|
442
|
-
|
|
443
|
-
|
|
618
|
+
const filePath = `./${relative(process.cwd(), sourcePath)}`
|
|
619
|
+
const lineNumbers = node.loc
|
|
620
|
+
? node.loc.start.line +
|
|
621
|
+
(node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
|
|
622
|
+
: ''
|
|
444
623
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
Boolean
|
|
624
|
+
const codePosition = `${filePath}:${lineNumbers}`
|
|
625
|
+
|
|
626
|
+
// debug just one
|
|
627
|
+
const debugPropValue = node.attributes
|
|
628
|
+
.filter(
|
|
629
|
+
(n) => t.isJSXAttribute(n) && t.isJSXIdentifier(n.name) && n.name.name === 'debug'
|
|
452
630
|
)
|
|
631
|
+
// @ts-ignore
|
|
632
|
+
.map((n: t.JSXAttribute) => {
|
|
633
|
+
if (n.value === null) return true
|
|
634
|
+
if (t.isStringLiteral(n.value)) return n.value.value as 'verbose'
|
|
635
|
+
return false
|
|
636
|
+
})[0] as boolean | 'verbose' | undefined
|
|
637
|
+
|
|
638
|
+
if (debugPropValue) {
|
|
639
|
+
shouldPrintDebug = debugPropValue
|
|
640
|
+
}
|
|
453
641
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
if (t.isStringLiteral(n.value)) return n.value.value as 'verbose'
|
|
463
|
-
return false
|
|
464
|
-
})[0]
|
|
642
|
+
if (shouldPrintDebug) {
|
|
643
|
+
logger.info('\n')
|
|
644
|
+
logger.info(
|
|
645
|
+
`\x1b[33m%s\x1b[0m ` + `${componentName} | ${codePosition} -------------------`
|
|
646
|
+
)
|
|
647
|
+
// prettier-ignore
|
|
648
|
+
logger.info(['\x1b[1m', '\x1b[32m', `<${originalNodeName} />`, disableDebugAttr ? '' : '🐛'].join(' '))
|
|
649
|
+
}
|
|
465
650
|
|
|
466
|
-
|
|
467
|
-
|
|
651
|
+
// add data-* debug attributes
|
|
652
|
+
if (shouldAddDebugProp && !disableDebugAttr) {
|
|
653
|
+
res.modified++
|
|
654
|
+
node.attributes.unshift(
|
|
655
|
+
t.jsxAttribute(t.jsxIdentifier('data-is'), t.stringLiteral(node.name.name))
|
|
656
|
+
)
|
|
657
|
+
if (componentName) {
|
|
658
|
+
node.attributes.unshift(
|
|
659
|
+
t.jsxAttribute(t.jsxIdentifier('data-in'), t.stringLiteral(componentName))
|
|
660
|
+
)
|
|
468
661
|
}
|
|
469
662
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
(
|
|
473
|
-
|
|
474
|
-
t.isJSXIdentifier(n.name) &&
|
|
475
|
-
n.name.name === 'debug' &&
|
|
476
|
-
n.value === null
|
|
663
|
+
node.attributes.unshift(
|
|
664
|
+
t.jsxAttribute(
|
|
665
|
+
t.jsxIdentifier('data-at'),
|
|
666
|
+
t.stringLiteral(`${basename(filePath)}:${lineNumbers}`)
|
|
477
667
|
)
|
|
668
|
+
)
|
|
669
|
+
}
|
|
478
670
|
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
const shouldLog = !hasLogged
|
|
494
|
-
if (shouldLog) {
|
|
495
|
-
console.log(` 1️⃣ Inline optimized 2️⃣ Inline flattened 3️⃣ styled() extracted`)
|
|
496
|
-
const prefix = ' |'
|
|
497
|
-
// prettier-ignore
|
|
498
|
-
console.log(prefixLogs || prefix, ' total · 1️⃣ · 2️⃣ · 3️⃣')
|
|
499
|
-
hasLogged = true
|
|
500
|
-
}
|
|
501
|
-
if (disableExtraction) {
|
|
502
|
-
return
|
|
503
|
-
}
|
|
504
|
-
|
|
505
|
-
const { staticConfig } = component
|
|
506
|
-
const variants = staticConfig.variants || {}
|
|
507
|
-
const isTextView = staticConfig.isText || false
|
|
508
|
-
const validStyles = staticConfig?.validStyles ?? {}
|
|
509
|
-
|
|
510
|
-
// find tag="a" tag="main" etc dom indicators
|
|
511
|
-
let tagName = staticConfig.defaultProps.tag ?? (isTextView ? 'span' : 'div')
|
|
512
|
-
traversePath
|
|
513
|
-
.get('openingElement')
|
|
514
|
-
.get('attributes')
|
|
515
|
-
.forEach((path) => {
|
|
516
|
-
const attr = path.node
|
|
517
|
-
if (t.isJSXSpreadAttribute(attr)) return
|
|
518
|
-
if (attr.name.name !== 'tag') return
|
|
519
|
-
const val = attr.value
|
|
520
|
-
if (!t.isStringLiteral(val)) return
|
|
521
|
-
tagName = val.value
|
|
522
|
-
})
|
|
671
|
+
// disable as it gets messy
|
|
672
|
+
// const shouldLog = !hasLogged
|
|
673
|
+
// if (shouldLog) {
|
|
674
|
+
// logger.info(` 1️⃣ Inline optimized 2️⃣ Inline flattened 3️⃣ styled() extracted`)
|
|
675
|
+
// const prefix = ' |'
|
|
676
|
+
// // prettier-ignore
|
|
677
|
+
// logger.info([prefixLogs || prefix, ' total · 1️⃣ · 2️⃣ · 3️⃣'].join(' '))
|
|
678
|
+
// hasLogged = true
|
|
679
|
+
// }
|
|
680
|
+
|
|
681
|
+
if (disableExtraction) {
|
|
682
|
+
return
|
|
683
|
+
}
|
|
523
684
|
|
|
524
|
-
|
|
685
|
+
try {
|
|
686
|
+
const { staticConfig } = component
|
|
687
|
+
const variants = staticConfig.variants || {}
|
|
688
|
+
const isTextView = staticConfig.isText || false
|
|
689
|
+
const validStyles = staticConfig?.validStyles ?? {}
|
|
690
|
+
|
|
691
|
+
// find tag="a" tag="main" etc dom indicators
|
|
692
|
+
let tagName = staticConfig.defaultProps.tag ?? (isTextView ? 'span' : 'div')
|
|
693
|
+
traversePath
|
|
694
|
+
.get('openingElement')
|
|
695
|
+
.get('attributes')
|
|
696
|
+
.forEach((path) => {
|
|
697
|
+
const attr = path.node
|
|
698
|
+
if (t.isJSXSpreadAttribute(attr)) return
|
|
699
|
+
if (attr.name.name !== 'tag') return
|
|
700
|
+
const val = attr.value
|
|
701
|
+
if (!t.isStringLiteral(val)) return
|
|
702
|
+
tagName = val.value
|
|
703
|
+
})
|
|
525
704
|
|
|
526
|
-
|
|
527
|
-
...(props.inlineProps || []),
|
|
528
|
-
...(staticConfig.inlineProps || []),
|
|
529
|
-
])
|
|
705
|
+
const flatNode = getFlattenedNode?.({ isTextView, tag: tagName })
|
|
530
706
|
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
...(staticConfig.deoptProps || []),
|
|
536
|
-
])
|
|
707
|
+
const inlineProps = new Set([
|
|
708
|
+
...(restProps.inlineProps || []),
|
|
709
|
+
...(staticConfig.inlineProps || []),
|
|
710
|
+
])
|
|
537
711
|
|
|
538
|
-
|
|
712
|
+
const deoptProps = new Set([
|
|
713
|
+
// always de-opt animation
|
|
714
|
+
'animation',
|
|
715
|
+
...(restProps.deoptProps || []),
|
|
716
|
+
...(staticConfig.deoptProps || []),
|
|
717
|
+
])
|
|
539
718
|
|
|
540
|
-
|
|
541
|
-
const staticNamespace = getStaticBindingsForScope(
|
|
542
|
-
traversePath.scope,
|
|
543
|
-
importsWhitelist,
|
|
544
|
-
sourcePath,
|
|
545
|
-
bindingCache,
|
|
546
|
-
shouldPrintDebug
|
|
547
|
-
)
|
|
719
|
+
const inlineWhenUnflattened = new Set([...(staticConfig.inlineWhenUnflattened || [])])
|
|
548
720
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
})
|
|
558
|
-
const attemptEvalSafe = createSafeEvaluator(attemptEval)
|
|
721
|
+
// Generate scope object at this level
|
|
722
|
+
const staticNamespace = getStaticBindingsForScope(
|
|
723
|
+
traversePath.scope,
|
|
724
|
+
importsWhitelist,
|
|
725
|
+
sourcePath,
|
|
726
|
+
bindingCache,
|
|
727
|
+
shouldPrintDebug
|
|
728
|
+
)
|
|
559
729
|
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
730
|
+
const attemptEval = !evaluateVars
|
|
731
|
+
? evaluateAstNode
|
|
732
|
+
: createEvaluator({
|
|
733
|
+
props: propsWithFileInfo,
|
|
734
|
+
staticNamespace,
|
|
735
|
+
sourcePath,
|
|
736
|
+
traversePath,
|
|
737
|
+
shouldPrintDebug,
|
|
738
|
+
})
|
|
739
|
+
const attemptEvalSafe = createSafeEvaluator(attemptEval)
|
|
563
740
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
741
|
+
if (shouldPrintDebug) {
|
|
742
|
+
logger.info(` staticNamespace ${Object.keys(staticNamespace).join(', ')}`)
|
|
743
|
+
}
|
|
567
744
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
745
|
+
//
|
|
746
|
+
// SPREADS SETUP
|
|
747
|
+
//
|
|
748
|
+
|
|
749
|
+
// TODO restore
|
|
750
|
+
// const hasDeopt = (obj: Object) => {
|
|
751
|
+
// return Object.keys(obj).some(isDeoptedProp)
|
|
752
|
+
// }
|
|
753
|
+
|
|
754
|
+
// flatten any easily evaluatable spreads
|
|
755
|
+
const flattenedAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
|
|
756
|
+
traversePath
|
|
757
|
+
.get('openingElement')
|
|
758
|
+
.get('attributes')
|
|
759
|
+
.forEach((path) => {
|
|
760
|
+
const attr = path.node
|
|
761
|
+
if (!t.isJSXSpreadAttribute(attr)) {
|
|
762
|
+
flattenedAttrs.push(attr)
|
|
763
|
+
return
|
|
764
|
+
}
|
|
765
|
+
let arg: any
|
|
766
|
+
try {
|
|
767
|
+
arg = attemptEval(attr.argument)
|
|
768
|
+
} catch (e: any) {
|
|
769
|
+
if (shouldPrintDebug) {
|
|
770
|
+
logger.info([' couldnt parse spread', e.message].join(' '))
|
|
583
771
|
}
|
|
584
|
-
|
|
772
|
+
flattenedAttrs.push(attr)
|
|
773
|
+
return
|
|
774
|
+
}
|
|
775
|
+
if (arg !== undefined) {
|
|
585
776
|
try {
|
|
586
|
-
arg
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
console.log(' non object or null arg', arg)
|
|
777
|
+
if (typeof arg !== 'object' || arg == null) {
|
|
778
|
+
if (shouldPrintDebug) {
|
|
779
|
+
logger.info([' non object or null arg', arg].join(' '))
|
|
780
|
+
}
|
|
781
|
+
flattenedAttrs.push(attr)
|
|
782
|
+
} else {
|
|
783
|
+
for (const k in arg) {
|
|
784
|
+
const value = arg[k]
|
|
785
|
+
// this is a null prop:
|
|
786
|
+
if (!value && typeof value === 'object') {
|
|
787
|
+
logger.error(['Unhandled null prop', k, value, arg].join(' '))
|
|
788
|
+
continue
|
|
599
789
|
}
|
|
600
|
-
flattenedAttrs.push(
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
// this is a null prop:
|
|
605
|
-
if (!value && typeof value === 'object') {
|
|
606
|
-
console.log('shouldnt we handle this?', k, value, arg)
|
|
607
|
-
continue
|
|
608
|
-
}
|
|
609
|
-
flattenedAttrs.push(
|
|
610
|
-
t.jsxAttribute(
|
|
611
|
-
t.jsxIdentifier(k),
|
|
612
|
-
t.jsxExpressionContainer(literalToAst(value))
|
|
613
|
-
)
|
|
790
|
+
flattenedAttrs.push(
|
|
791
|
+
t.jsxAttribute(
|
|
792
|
+
t.jsxIdentifier(k),
|
|
793
|
+
t.jsxExpressionContainer(literalToAst(value))
|
|
614
794
|
)
|
|
615
|
-
|
|
795
|
+
)
|
|
616
796
|
}
|
|
617
|
-
} catch (err) {
|
|
618
|
-
console.warn('cant parse spread, caught err', err)
|
|
619
|
-
couldntParse = true
|
|
620
797
|
}
|
|
798
|
+
} catch (err) {
|
|
799
|
+
logger.warn(`cant parse spread, caught err ${err}`)
|
|
800
|
+
couldntParse = true
|
|
621
801
|
}
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
if (couldntParse) {
|
|
625
|
-
return
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
tm.mark('jsx-element-flattened', shouldPrintDebug === 'verbose')
|
|
629
|
-
|
|
630
|
-
// set flattened
|
|
631
|
-
node.attributes = flattenedAttrs
|
|
632
|
-
|
|
633
|
-
let attrs: ExtractedAttr[] = []
|
|
634
|
-
let shouldDeopt = false
|
|
635
|
-
const inlined = new Map<string, any>()
|
|
636
|
-
const variantValues = new Map<string, any>()
|
|
637
|
-
let hasSetOptimized = false
|
|
638
|
-
const inlineWhenUnflattenedOGVals = {}
|
|
639
|
-
|
|
640
|
-
// RUN first pass
|
|
641
|
-
|
|
642
|
-
// normalize all conditionals so we can evaluate away easier later
|
|
643
|
-
// at the same time lets normalize shorthand media queries into spreads:
|
|
644
|
-
// that way we can parse them with the same logic later on
|
|
645
|
-
//
|
|
646
|
-
// {...media.sm && { color: x ? 'red' : 'blue' }}
|
|
647
|
-
// => {...media.sm && x && { color: 'red' }}
|
|
648
|
-
// => {...media.sm && !x && { color: 'blue' }}
|
|
649
|
-
//
|
|
650
|
-
// $sm={{ color: 'red' }}
|
|
651
|
-
// => {...media.sm && { color: 'red' }}
|
|
652
|
-
//
|
|
653
|
-
// $sm={{ color: x ? 'red' : 'blue' }}
|
|
654
|
-
// => {...media.sm && x && { color: 'red' }}
|
|
655
|
-
// => {...media.sm && !x && { color: 'blue' }}
|
|
656
|
-
|
|
657
|
-
attrs = traversePath
|
|
658
|
-
.get('openingElement')
|
|
659
|
-
.get('attributes')
|
|
660
|
-
.flatMap((path) => {
|
|
661
|
-
try {
|
|
662
|
-
const res = evaluateAttribute(path)
|
|
663
|
-
tm.mark('jsx-element-evaluate-attr', shouldPrintDebug === 'verbose')
|
|
664
|
-
if (!res) {
|
|
665
|
-
path.remove()
|
|
666
|
-
}
|
|
667
|
-
return res
|
|
668
|
-
} catch (err: any) {
|
|
669
|
-
if (shouldPrintDebug) {
|
|
670
|
-
console.log('Error extracting attribute', err.message, err.stack)
|
|
671
|
-
console.log('node', path.node)
|
|
672
|
-
}
|
|
673
|
-
// dont flatten if we run into error
|
|
674
|
-
inlined.set(`${Math.random()}`, 'spread')
|
|
675
|
-
return {
|
|
676
|
-
type: 'attr',
|
|
677
|
-
value: path.node,
|
|
678
|
-
} as const
|
|
679
|
-
}
|
|
680
|
-
})
|
|
681
|
-
.flat(4)
|
|
682
|
-
.filter(isPresent)
|
|
802
|
+
}
|
|
803
|
+
})
|
|
683
804
|
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
805
|
+
if (couldntParse) {
|
|
806
|
+
return
|
|
807
|
+
}
|
|
687
808
|
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
809
|
+
tm.mark('jsx-element-flattened', !!shouldPrintDebug)
|
|
810
|
+
|
|
811
|
+
// set flattened
|
|
812
|
+
node.attributes = flattenedAttrs
|
|
813
|
+
|
|
814
|
+
let attrs: ExtractedAttr[] = []
|
|
815
|
+
let shouldDeopt = false
|
|
816
|
+
const inlined = new Map<string, any>()
|
|
817
|
+
const variantValues = new Map<string, any>()
|
|
818
|
+
let hasSetOptimized = false
|
|
819
|
+
const inlineWhenUnflattenedOGVals = {}
|
|
820
|
+
|
|
821
|
+
// RUN first pass
|
|
822
|
+
|
|
823
|
+
// normalize all conditionals so we can evaluate away easier later
|
|
824
|
+
// at the same time lets normalize shorthand media queries into spreads:
|
|
825
|
+
// that way we can parse them with the same logic later on
|
|
826
|
+
//
|
|
827
|
+
// {...media.sm && { color: x ? 'red' : 'blue' }}
|
|
828
|
+
// => {...media.sm && x && { color: 'red' }}
|
|
829
|
+
// => {...media.sm && !x && { color: 'blue' }}
|
|
830
|
+
//
|
|
831
|
+
// $sm={{ color: 'red' }}
|
|
832
|
+
// => {...media.sm && { color: 'red' }}
|
|
833
|
+
//
|
|
834
|
+
// $sm={{ color: x ? 'red' : 'blue' }}
|
|
835
|
+
// => {...media.sm && x && { color: 'red' }}
|
|
836
|
+
// => {...media.sm && !x && { color: 'blue' }}
|
|
837
|
+
|
|
838
|
+
attrs = traversePath
|
|
839
|
+
.get('openingElement')
|
|
840
|
+
.get('attributes')
|
|
841
|
+
.flatMap((path) => {
|
|
842
|
+
try {
|
|
843
|
+
const res = evaluateAttribute(path)
|
|
844
|
+
tm.mark('jsx-element-evaluate-attr', !!shouldPrintDebug)
|
|
845
|
+
if (!res) {
|
|
846
|
+
path.remove()
|
|
724
847
|
}
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
// directly keep these
|
|
729
|
-
// couldn't evaluate spread, undefined name, or name is not string
|
|
730
|
-
if (
|
|
731
|
-
t.isJSXSpreadAttribute(attribute) ||
|
|
732
|
-
!attribute.name ||
|
|
733
|
-
typeof attribute.name.name !== 'string'
|
|
734
|
-
) {
|
|
848
|
+
return res
|
|
849
|
+
} catch (err: any) {
|
|
735
850
|
if (shouldPrintDebug) {
|
|
736
|
-
|
|
851
|
+
logger.info(
|
|
852
|
+
[
|
|
853
|
+
'Recoverable error extracting attribute',
|
|
854
|
+
err.message,
|
|
855
|
+
shouldPrintDebug === 'verbose' ? err.stack : '',
|
|
856
|
+
].join(' ')
|
|
857
|
+
)
|
|
858
|
+
if (shouldPrintDebug === 'verbose') {
|
|
859
|
+
logger.info(`node ${path.node?.type}`)
|
|
860
|
+
}
|
|
737
861
|
}
|
|
862
|
+
// dont flatten if we run into error
|
|
738
863
|
inlined.set(`${Math.random()}`, 'spread')
|
|
739
|
-
return
|
|
864
|
+
return {
|
|
865
|
+
type: 'attr',
|
|
866
|
+
value: path.node,
|
|
867
|
+
} as const
|
|
740
868
|
}
|
|
869
|
+
})
|
|
870
|
+
.flat(4)
|
|
871
|
+
.filter(isPresent)
|
|
741
872
|
|
|
742
|
-
|
|
873
|
+
if (shouldPrintDebug) {
|
|
874
|
+
logger.info(
|
|
875
|
+
[' - attrs (before):\n', logLines(attrs.map(attrStr).join(', '))].join(' ')
|
|
876
|
+
)
|
|
877
|
+
}
|
|
743
878
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
879
|
+
// START function evaluateAttribute
|
|
880
|
+
function evaluateAttribute(
|
|
881
|
+
path: NodePath<t.JSXAttribute | t.JSXSpreadAttribute>
|
|
882
|
+
): ExtractedAttr | ExtractedAttr[] | null {
|
|
883
|
+
const attribute = path.node
|
|
884
|
+
const attr: ExtractedAttr = { type: 'attr', value: attribute }
|
|
885
|
+
// ...spreads
|
|
886
|
+
if (t.isJSXSpreadAttribute(attribute)) {
|
|
887
|
+
const arg = attribute.argument
|
|
888
|
+
const conditional = t.isConditionalExpression(arg)
|
|
889
|
+
? // <YStack {...isSmall ? { color: 'red } : { color: 'blue }}
|
|
890
|
+
([arg.test, arg.consequent, arg.alternate] as const)
|
|
891
|
+
: t.isLogicalExpression(arg) && arg.operator === '&&'
|
|
892
|
+
? // <YStack {...isSmall && { color: 'red }}
|
|
893
|
+
([arg.left, arg.right, null] as const)
|
|
894
|
+
: null
|
|
895
|
+
|
|
896
|
+
if (conditional) {
|
|
897
|
+
const [test, alt, cons] = conditional
|
|
898
|
+
if (!test) throw new Error(`no test`)
|
|
899
|
+
if ([alt, cons].some((side) => side && !isStaticObject(side))) {
|
|
900
|
+
if (shouldPrintDebug) {
|
|
901
|
+
logger.info(`not extractable ${alt} ${cons}`)
|
|
902
|
+
}
|
|
903
|
+
return attr
|
|
747
904
|
}
|
|
748
|
-
|
|
905
|
+
// split into individual ternaries per object property
|
|
906
|
+
return [
|
|
907
|
+
...(createTernariesFromObjectProperties(test, alt) || []),
|
|
908
|
+
...((cons &&
|
|
909
|
+
createTernariesFromObjectProperties(t.unaryExpression('!', test), cons)) ||
|
|
910
|
+
[]),
|
|
911
|
+
].map((ternary) => ({
|
|
912
|
+
type: 'ternary',
|
|
913
|
+
value: ternary,
|
|
914
|
+
}))
|
|
749
915
|
}
|
|
916
|
+
}
|
|
917
|
+
// END ...spreads
|
|
750
918
|
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
919
|
+
// directly keep these
|
|
920
|
+
// couldn't evaluate spread, undefined name, or name is not string
|
|
921
|
+
if (
|
|
922
|
+
t.isJSXSpreadAttribute(attribute) ||
|
|
923
|
+
!attribute.name ||
|
|
924
|
+
typeof attribute.name.name !== 'string'
|
|
925
|
+
) {
|
|
926
|
+
if (shouldPrintDebug) {
|
|
927
|
+
logger.info(' ! inlining, spread attr')
|
|
757
928
|
}
|
|
929
|
+
inlined.set(`${Math.random()}`, 'spread')
|
|
930
|
+
return attr
|
|
931
|
+
}
|
|
758
932
|
|
|
759
|
-
|
|
760
|
-
if (deoptProps.has(name)) {
|
|
761
|
-
shouldDeopt = true
|
|
762
|
-
inlined.set(name, name)
|
|
763
|
-
if (shouldPrintDebug) {
|
|
764
|
-
console.log(' ! inlining, deopted prop', name)
|
|
765
|
-
}
|
|
766
|
-
return attr
|
|
767
|
-
}
|
|
933
|
+
const name = attribute.name.name
|
|
768
934
|
|
|
769
|
-
|
|
770
|
-
if (
|
|
771
|
-
|
|
935
|
+
if (excludeProps?.has(name)) {
|
|
936
|
+
if (shouldPrintDebug) {
|
|
937
|
+
logger.info([' excluding prop', name].join(' '))
|
|
772
938
|
}
|
|
939
|
+
return null
|
|
940
|
+
}
|
|
773
941
|
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
942
|
+
if (inlineProps.has(name)) {
|
|
943
|
+
inlined.set(name, name)
|
|
944
|
+
if (shouldPrintDebug) {
|
|
945
|
+
logger.info([' ! inlining, inline prop', name].join(' '))
|
|
777
946
|
}
|
|
947
|
+
return attr
|
|
948
|
+
}
|
|
778
949
|
|
|
779
|
-
|
|
780
|
-
|
|
950
|
+
// can still optimize the object... see hoverStyle on native
|
|
951
|
+
if (deoptProps.has(name)) {
|
|
952
|
+
shouldDeopt = true
|
|
953
|
+
inlined.set(name, name)
|
|
954
|
+
if (shouldPrintDebug) {
|
|
955
|
+
logger.info([' ! inlining, deopted prop', name].join(' '))
|
|
781
956
|
}
|
|
957
|
+
return attr
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
// pass className, key, and style props through untouched
|
|
961
|
+
if (UNTOUCHED_PROPS[name]) {
|
|
962
|
+
return attr
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
if (INLINE_EXTRACTABLE[name]) {
|
|
966
|
+
inlined.set(name, INLINE_EXTRACTABLE[name])
|
|
967
|
+
return attr
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
if (name.startsWith('data-')) {
|
|
971
|
+
return attr
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
// shorthand media queries
|
|
975
|
+
if (name[0] === '$' && t.isJSXExpressionContainer(attribute?.value)) {
|
|
976
|
+
const shortname = name.slice(1)
|
|
977
|
+
if (mediaQueryConfig[shortname]) {
|
|
978
|
+
if (target === 'native') {
|
|
979
|
+
shouldDeopt = true
|
|
980
|
+
}
|
|
782
981
|
|
|
783
|
-
// shorthand media queries
|
|
784
|
-
if (name[0] === '$' && t.isJSXExpressionContainer(attribute?.value)) {
|
|
785
982
|
// allow disabling this extraction
|
|
786
983
|
if (disableExtractInlineMedia) {
|
|
787
984
|
return attr
|
|
788
985
|
}
|
|
789
986
|
|
|
790
|
-
const
|
|
791
|
-
if (
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
{
|
|
798
|
-
inlineMediaQuery: shortname,
|
|
799
|
-
}
|
|
800
|
-
)
|
|
801
|
-
if (ternaries) {
|
|
802
|
-
return ternaries.map((value) => ({
|
|
803
|
-
type: 'ternary',
|
|
804
|
-
value,
|
|
805
|
-
}))
|
|
987
|
+
const expression = attribute.value.expression
|
|
988
|
+
if (!t.isJSXEmptyExpression(expression)) {
|
|
989
|
+
const ternaries = createTernariesFromObjectProperties(
|
|
990
|
+
t.stringLiteral(shortname),
|
|
991
|
+
expression,
|
|
992
|
+
{
|
|
993
|
+
inlineMediaQuery: shortname,
|
|
806
994
|
}
|
|
995
|
+
)
|
|
996
|
+
if (ternaries) {
|
|
997
|
+
return ternaries.map((value) => ({
|
|
998
|
+
type: 'ternary',
|
|
999
|
+
value,
|
|
1000
|
+
}))
|
|
807
1001
|
}
|
|
808
1002
|
}
|
|
809
1003
|
}
|
|
1004
|
+
}
|
|
810
1005
|
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
}
|
|
817
|
-
})()
|
|
818
|
-
|
|
819
|
-
const remove = () => {
|
|
820
|
-
Array.isArray(valuePath) ? valuePath.map((p) => p.remove()) : valuePath.remove()
|
|
1006
|
+
const [value, valuePath] = (() => {
|
|
1007
|
+
if (t.isJSXExpressionContainer(attribute?.value)) {
|
|
1008
|
+
return [attribute.value.expression!, path.get('value')!] as const
|
|
1009
|
+
} else {
|
|
1010
|
+
return [attribute.value!, path.get('value')!] as const
|
|
821
1011
|
}
|
|
1012
|
+
})()
|
|
822
1013
|
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
1014
|
+
const remove = () => {
|
|
1015
|
+
Array.isArray(valuePath) ? valuePath.map((p) => p.remove()) : valuePath.remove()
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
if (name === 'ref') {
|
|
1019
|
+
if (shouldPrintDebug) {
|
|
1020
|
+
logger.info([' ! inlining, ref', name].join(' '))
|
|
829
1021
|
}
|
|
1022
|
+
inlined.set('ref', 'ref')
|
|
1023
|
+
return attr
|
|
1024
|
+
}
|
|
830
1025
|
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
}
|
|
1026
|
+
if (name === 'tag') {
|
|
1027
|
+
return {
|
|
1028
|
+
type: 'attr',
|
|
1029
|
+
value: path.node,
|
|
836
1030
|
}
|
|
1031
|
+
}
|
|
837
1032
|
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
return attr
|
|
1033
|
+
// native shouldn't extract variables
|
|
1034
|
+
if (disableExtractVariables === true) {
|
|
1035
|
+
if (value) {
|
|
1036
|
+
if (value.type === 'StringLiteral' && value.value[0] === '$') {
|
|
1037
|
+
if (shouldPrintDebug) {
|
|
1038
|
+
logger.info(
|
|
1039
|
+
[` ! inlining, native disable extract: ${name} =`, value.value].join(' ')
|
|
1040
|
+
)
|
|
847
1041
|
}
|
|
1042
|
+
inlined.set(name, true)
|
|
1043
|
+
return attr
|
|
848
1044
|
}
|
|
849
1045
|
}
|
|
1046
|
+
}
|
|
850
1047
|
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
// if value can be evaluated, extract it and filter it out
|
|
857
|
-
const styleValue = attemptEvalSafe(value)
|
|
858
|
-
|
|
859
|
-
// never flatten if a prop isn't a valid static attribute
|
|
860
|
-
// only post prop-mapping
|
|
861
|
-
if (!variants[name] && !isValidStyleKey(name, staticConfig)) {
|
|
862
|
-
let keys = [name]
|
|
863
|
-
let out: any = null
|
|
864
|
-
|
|
865
|
-
// for now passing empty props {}, a bit odd, need to at least document
|
|
866
|
-
// for now we don't expose custom components so just noting behavior
|
|
867
|
-
out = staticConfig.propMapper(
|
|
868
|
-
name,
|
|
869
|
-
styleValue,
|
|
870
|
-
defaultTheme,
|
|
871
|
-
staticConfig.defaultProps,
|
|
872
|
-
{ resolveVariablesAs: 'auto' },
|
|
873
|
-
undefined,
|
|
874
|
-
shouldPrintDebug
|
|
875
|
-
)
|
|
1048
|
+
if (name === 'theme') {
|
|
1049
|
+
inlined.set('theme', attr.value)
|
|
1050
|
+
return attr
|
|
1051
|
+
}
|
|
876
1052
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
1053
|
+
// if value can be evaluated, extract it and filter it out
|
|
1054
|
+
const styleValue = attemptEvalSafe(value)
|
|
1055
|
+
|
|
1056
|
+
// never flatten if a prop isn't a valid static attribute
|
|
1057
|
+
// only post prop-mapping
|
|
1058
|
+
if (!variants[name] && !isValidStyleKey(name, staticConfig)) {
|
|
1059
|
+
let keys = [name]
|
|
1060
|
+
let out: any = null
|
|
1061
|
+
|
|
1062
|
+
// for now passing empty props {}, a bit odd, need to at least document
|
|
1063
|
+
// for now we don't expose custom components so just noting behavior
|
|
1064
|
+
out = staticConfig.propMapper(
|
|
1065
|
+
name,
|
|
1066
|
+
styleValue,
|
|
1067
|
+
defaultTheme,
|
|
1068
|
+
staticConfig.defaultProps,
|
|
1069
|
+
{ resolveVariablesAs: 'auto' },
|
|
1070
|
+
undefined,
|
|
1071
|
+
undefined,
|
|
1072
|
+
shouldPrintDebug
|
|
1073
|
+
)
|
|
894
1074
|
|
|
1075
|
+
if (out) {
|
|
1076
|
+
if (!Array.isArray(out)) {
|
|
1077
|
+
logger.warn(`Error expected array but got`, out)
|
|
1078
|
+
couldntParse = true
|
|
1079
|
+
shouldDeopt = true
|
|
1080
|
+
} else {
|
|
1081
|
+
out = Object.fromEntries(out)
|
|
895
1082
|
keys = Object.keys(out)
|
|
896
1083
|
}
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
value: { [key]: styleValue },
|
|
905
|
-
name: key,
|
|
906
|
-
attr: path.node,
|
|
907
|
-
} as const
|
|
908
|
-
}
|
|
909
|
-
if (
|
|
910
|
-
validHTMLAttributes[key] ||
|
|
911
|
-
key.startsWith('aria-') ||
|
|
912
|
-
key.startsWith('data-')
|
|
913
|
-
) {
|
|
914
|
-
return attr
|
|
915
|
-
}
|
|
916
|
-
if (shouldPrintDebug) {
|
|
917
|
-
console.log(' ! inlining, non-static', key)
|
|
918
|
-
}
|
|
919
|
-
didInline = true
|
|
920
|
-
inlined.set(key, val)
|
|
921
|
-
return val
|
|
922
|
-
})
|
|
923
|
-
|
|
924
|
-
// weird logic whats going on here
|
|
925
|
-
if (didInline) {
|
|
926
|
-
if (shouldPrintDebug) {
|
|
927
|
-
console.log(' bailing flattening due to attributes', attributes)
|
|
928
|
-
}
|
|
929
|
-
// bail
|
|
930
|
-
return attr
|
|
1084
|
+
}
|
|
1085
|
+
if (out) {
|
|
1086
|
+
if (isTargetingHTML) {
|
|
1087
|
+
// translate to DOM-compat
|
|
1088
|
+
out = createDOMProps(isTextView ? 'span' : 'div', out)
|
|
1089
|
+
// remove className - we dont use rnw styling
|
|
1090
|
+
delete out.className
|
|
931
1091
|
}
|
|
932
1092
|
|
|
933
|
-
|
|
934
|
-
return attributes
|
|
1093
|
+
keys = Object.keys(out)
|
|
935
1094
|
}
|
|
936
1095
|
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
inlineWhenUnflattenedOGVals[name] = { styleValue, attr }
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
if (isValidStyleKey(name, staticConfig)) {
|
|
945
|
-
if (shouldPrintDebug) {
|
|
946
|
-
console.log(` style: ${name} =`, styleValue)
|
|
947
|
-
}
|
|
948
|
-
if (!(name in staticConfig.defaultProps)) {
|
|
949
|
-
if (!hasSetOptimized) {
|
|
950
|
-
res.optimized++
|
|
951
|
-
hasSetOptimized = true
|
|
952
|
-
}
|
|
953
|
-
}
|
|
1096
|
+
let didInline = false
|
|
1097
|
+
const attributes = keys.map((key) => {
|
|
1098
|
+
const val = out[key]
|
|
1099
|
+
if (isValidStyleKey(key, staticConfig)) {
|
|
954
1100
|
return {
|
|
955
1101
|
type: 'style',
|
|
956
|
-
value: { [
|
|
957
|
-
name,
|
|
1102
|
+
value: { [key]: styleValue },
|
|
1103
|
+
name: key,
|
|
958
1104
|
attr: path.node,
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1105
|
+
} as const
|
|
1106
|
+
}
|
|
1107
|
+
if (
|
|
1108
|
+
validHTMLAttributes[key] ||
|
|
1109
|
+
key.startsWith('aria-') ||
|
|
1110
|
+
key.startsWith('data-') ||
|
|
1111
|
+
// this is debug stuff added by vite / new jsx transform
|
|
1112
|
+
key === '__source' ||
|
|
1113
|
+
key === '__self'
|
|
1114
|
+
) {
|
|
965
1115
|
return attr
|
|
966
1116
|
}
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
1117
|
+
if (shouldPrintDebug) {
|
|
1118
|
+
logger.info(' ! inlining, non-static ' + key)
|
|
1119
|
+
}
|
|
1120
|
+
didInline = true
|
|
1121
|
+
inlined.set(key, val)
|
|
1122
|
+
return val
|
|
1123
|
+
})
|
|
970
1124
|
|
|
971
|
-
//
|
|
972
|
-
|
|
973
|
-
// opacity={(conditional ? 0 : 1) * scale}
|
|
974
|
-
if (t.isBinaryExpression(value)) {
|
|
1125
|
+
// weird logic whats going on here
|
|
1126
|
+
if (didInline) {
|
|
975
1127
|
if (shouldPrintDebug) {
|
|
976
|
-
|
|
1128
|
+
logger.info(` bailing flattening due to attributes ${attributes}`)
|
|
977
1129
|
}
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
1130
|
+
// bail
|
|
1131
|
+
return attr
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
// return evaluated attributes
|
|
1135
|
+
return attributes
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
// FAILED = dynamic or ternary, keep going
|
|
1139
|
+
if (styleValue !== FAILED_EVAL) {
|
|
1140
|
+
if (inlineWhenUnflattened.has(name)) {
|
|
1141
|
+
// preserve original value for restoration
|
|
1142
|
+
inlineWhenUnflattenedOGVals[name] = { styleValue, attr }
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
if (isValidStyleKey(name, staticConfig)) {
|
|
982
1146
|
if (shouldPrintDebug) {
|
|
983
|
-
|
|
1147
|
+
logger.info(` style: ${name} = ${styleValue}`)
|
|
984
1148
|
}
|
|
985
|
-
if (
|
|
986
|
-
|
|
987
|
-
|
|
1149
|
+
if (!(name in staticConfig.defaultProps)) {
|
|
1150
|
+
if (!hasSetOptimized) {
|
|
1151
|
+
res.optimized++
|
|
1152
|
+
hasSetOptimized = true
|
|
1153
|
+
}
|
|
988
1154
|
}
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
1155
|
+
return {
|
|
1156
|
+
type: 'style',
|
|
1157
|
+
value: { [name]: styleValue },
|
|
1158
|
+
name,
|
|
1159
|
+
attr: path.node,
|
|
992
1160
|
}
|
|
993
|
-
|
|
994
|
-
|
|
1161
|
+
} else {
|
|
1162
|
+
if (variants[name]) {
|
|
1163
|
+
variantValues.set(name, styleValue)
|
|
995
1164
|
}
|
|
996
1165
|
inlined.set(name, true)
|
|
997
1166
|
return attr
|
|
998
1167
|
}
|
|
1168
|
+
}
|
|
999
1169
|
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1170
|
+
// ternaries!
|
|
1171
|
+
|
|
1172
|
+
// binary ternary, we can eventually make this smarter but step 1
|
|
1173
|
+
// basically for the common use case of:
|
|
1174
|
+
// opacity={(conditional ? 0 : 1) * scale}
|
|
1175
|
+
if (t.isBinaryExpression(value)) {
|
|
1176
|
+
if (shouldPrintDebug) {
|
|
1177
|
+
logger.info(` binary expression ${name} = ${value}`)
|
|
1178
|
+
}
|
|
1179
|
+
const { operator, left, right } = value
|
|
1180
|
+
// if one side is a ternary, and the other side is evaluatable, we can maybe extract
|
|
1181
|
+
const lVal = attemptEvalSafe(left)
|
|
1182
|
+
const rVal = attemptEvalSafe(right)
|
|
1183
|
+
if (shouldPrintDebug) {
|
|
1184
|
+
logger.info(` evalBinaryExpression lVal ${String(lVal)}, rVal ${String(rVal)}`)
|
|
1185
|
+
}
|
|
1186
|
+
if (lVal !== FAILED_EVAL && t.isConditionalExpression(right)) {
|
|
1187
|
+
const ternary = addBinaryConditional(operator, left, right)
|
|
1188
|
+
if (ternary) return ternary
|
|
1189
|
+
}
|
|
1190
|
+
if (rVal !== FAILED_EVAL && t.isConditionalExpression(left)) {
|
|
1191
|
+
const ternary = addBinaryConditional(operator, right, left)
|
|
1192
|
+
if (ternary) return ternary
|
|
1006
1193
|
}
|
|
1194
|
+
if (shouldPrintDebug) {
|
|
1195
|
+
logger.info(` evalBinaryExpression cant extract`)
|
|
1196
|
+
}
|
|
1197
|
+
inlined.set(name, true)
|
|
1198
|
+
return attr
|
|
1199
|
+
}
|
|
1007
1200
|
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
}
|
|
1013
|
-
return { type: 'ternary', value: staticLogical }
|
|
1201
|
+
const staticConditional = getStaticConditional(value)
|
|
1202
|
+
if (staticConditional) {
|
|
1203
|
+
if (shouldPrintDebug === 'verbose') {
|
|
1204
|
+
logger.info(` static conditional ${name} ${value}`)
|
|
1014
1205
|
}
|
|
1206
|
+
return { type: 'ternary', value: staticConditional }
|
|
1207
|
+
}
|
|
1015
1208
|
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
if (shouldPrintDebug) {
|
|
1019
|
-
|
|
1209
|
+
const staticLogical = getStaticLogical(value)
|
|
1210
|
+
if (staticLogical) {
|
|
1211
|
+
if (shouldPrintDebug === 'verbose') {
|
|
1212
|
+
logger.info(` static ternary ${name} = ${value}`)
|
|
1020
1213
|
}
|
|
1214
|
+
return { type: 'ternary', value: staticLogical }
|
|
1215
|
+
}
|
|
1021
1216
|
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1217
|
+
// if we've made it this far, the prop stays inline
|
|
1218
|
+
inlined.set(name, true)
|
|
1219
|
+
if (shouldPrintDebug) {
|
|
1220
|
+
logger.info(` ! inline no match ${name} ${value}`)
|
|
1221
|
+
}
|
|
1026
1222
|
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1223
|
+
//
|
|
1224
|
+
// RETURN ATTR
|
|
1225
|
+
//
|
|
1226
|
+
return attr
|
|
1227
|
+
|
|
1228
|
+
// attr helpers:
|
|
1229
|
+
function addBinaryConditional(
|
|
1230
|
+
operator: any,
|
|
1231
|
+
staticExpr: any,
|
|
1232
|
+
cond: t.ConditionalExpression
|
|
1233
|
+
): ExtractedAttr | null {
|
|
1234
|
+
if (getStaticConditional(cond)) {
|
|
1235
|
+
const alt = attemptEval(t.binaryExpression(operator, staticExpr, cond.alternate))
|
|
1236
|
+
const cons = attemptEval(t.binaryExpression(operator, staticExpr, cond.consequent))
|
|
1237
|
+
if (shouldPrintDebug) {
|
|
1238
|
+
logger.info([' binaryConditional', cond.test, cons, alt].join(' '))
|
|
1239
|
+
}
|
|
1240
|
+
return {
|
|
1241
|
+
type: 'ternary',
|
|
1242
|
+
value: {
|
|
1243
|
+
test: cond.test,
|
|
1244
|
+
remove,
|
|
1245
|
+
alternate: { [name]: alt },
|
|
1246
|
+
consequent: { [name]: cons },
|
|
1247
|
+
},
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
return null
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
function getStaticConditional(value: t.Node): Ternary | null {
|
|
1254
|
+
if (t.isConditionalExpression(value)) {
|
|
1255
|
+
try {
|
|
1256
|
+
const aVal = attemptEval(value.alternate)
|
|
1257
|
+
const cVal = attemptEval(value.consequent)
|
|
1038
1258
|
if (shouldPrintDebug) {
|
|
1039
|
-
|
|
1259
|
+
const type = value.test.type
|
|
1260
|
+
logger.info([' static ternary', type, cVal, aVal].join(' '))
|
|
1040
1261
|
}
|
|
1041
1262
|
return {
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1263
|
+
test: value.test,
|
|
1264
|
+
remove,
|
|
1265
|
+
consequent: { [name]: cVal },
|
|
1266
|
+
alternate: { [name]: aVal },
|
|
1267
|
+
}
|
|
1268
|
+
} catch (err: any) {
|
|
1269
|
+
if (shouldPrintDebug) {
|
|
1270
|
+
logger.info([' cant eval ternary', err.message].join(' '))
|
|
1049
1271
|
}
|
|
1050
1272
|
}
|
|
1051
|
-
return null
|
|
1052
1273
|
}
|
|
1274
|
+
return null
|
|
1275
|
+
}
|
|
1053
1276
|
|
|
1054
|
-
|
|
1055
|
-
|
|
1277
|
+
function getStaticLogical(value: t.Node): Ternary | null {
|
|
1278
|
+
if (t.isLogicalExpression(value)) {
|
|
1279
|
+
if (value.operator === '&&') {
|
|
1056
1280
|
try {
|
|
1057
|
-
const
|
|
1058
|
-
const cVal = attemptEval(value.consequent)
|
|
1281
|
+
const val = attemptEval(value.right)
|
|
1059
1282
|
if (shouldPrintDebug) {
|
|
1060
|
-
|
|
1061
|
-
console.log(' static ternary', type, cVal, aVal)
|
|
1283
|
+
logger.info([' staticLogical', value.left, name, val].join(' '))
|
|
1062
1284
|
}
|
|
1063
1285
|
return {
|
|
1064
|
-
test: value.
|
|
1286
|
+
test: value.left,
|
|
1065
1287
|
remove,
|
|
1066
|
-
consequent: { [name]:
|
|
1067
|
-
alternate:
|
|
1288
|
+
consequent: { [name]: val },
|
|
1289
|
+
alternate: null,
|
|
1068
1290
|
}
|
|
1069
|
-
} catch (err
|
|
1291
|
+
} catch (err) {
|
|
1070
1292
|
if (shouldPrintDebug) {
|
|
1071
|
-
|
|
1293
|
+
logger.info([' cant static eval logical', err].join(' '))
|
|
1072
1294
|
}
|
|
1073
1295
|
}
|
|
1074
1296
|
}
|
|
1075
|
-
return null
|
|
1076
1297
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
remove,
|
|
1089
|
-
consequent: { [name]: val },
|
|
1090
|
-
alternate: null,
|
|
1091
|
-
}
|
|
1092
|
-
} catch (err) {
|
|
1093
|
-
if (shouldPrintDebug) {
|
|
1094
|
-
console.log(' cant static eval logical', err)
|
|
1095
|
-
}
|
|
1096
|
-
}
|
|
1097
|
-
}
|
|
1298
|
+
return null
|
|
1299
|
+
}
|
|
1300
|
+
} // END function evaluateAttribute
|
|
1301
|
+
|
|
1302
|
+
function isStaticObject(obj: t.Node): obj is t.ObjectExpression {
|
|
1303
|
+
return (
|
|
1304
|
+
t.isObjectExpression(obj) &&
|
|
1305
|
+
obj.properties.every((prop) => {
|
|
1306
|
+
if (!t.isObjectProperty(prop)) {
|
|
1307
|
+
logger.info(['not object prop', prop].join(' '))
|
|
1308
|
+
return false
|
|
1098
1309
|
}
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
function isExtractable(obj: t.Node): obj is t.ObjectExpression {
|
|
1104
|
-
return (
|
|
1105
|
-
t.isObjectExpression(obj) &&
|
|
1106
|
-
obj.properties.every((prop) => {
|
|
1107
|
-
if (!t.isObjectProperty(prop)) {
|
|
1108
|
-
console.log('not object prop', prop)
|
|
1109
|
-
return false
|
|
1110
|
-
}
|
|
1111
|
-
const propName = prop.key['name']
|
|
1112
|
-
if (!isValidStyleKey(propName, staticConfig) && propName !== 'tag') {
|
|
1113
|
-
if (shouldPrintDebug) {
|
|
1114
|
-
console.log(' not a valid style prop!', propName)
|
|
1115
|
-
}
|
|
1116
|
-
return false
|
|
1310
|
+
const propName = prop.key['name']
|
|
1311
|
+
if (!isValidStyleKey(propName, staticConfig) && propName !== 'tag') {
|
|
1312
|
+
if (shouldPrintDebug) {
|
|
1313
|
+
logger.info([' not a valid style prop!', propName].join(' '))
|
|
1117
1314
|
}
|
|
1118
|
-
return
|
|
1119
|
-
}
|
|
1120
|
-
|
|
1121
|
-
|
|
1315
|
+
return false
|
|
1316
|
+
}
|
|
1317
|
+
return true
|
|
1318
|
+
})
|
|
1319
|
+
)
|
|
1320
|
+
}
|
|
1122
1321
|
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1322
|
+
// side = {
|
|
1323
|
+
// color: 'red',
|
|
1324
|
+
// background: x ? 'red' : 'green',
|
|
1325
|
+
// $gtSm: { color: 'green' }
|
|
1326
|
+
// }
|
|
1327
|
+
// => Ternary<test, { color: 'red' }, null>
|
|
1328
|
+
// => Ternary<test && x, { background: 'red' }, null>
|
|
1329
|
+
// => Ternary<test && !x, { background: 'green' }, null>
|
|
1330
|
+
// => Ternary<test && '$gtSm', { color: 'green' }, null>
|
|
1331
|
+
function createTernariesFromObjectProperties(
|
|
1332
|
+
test: t.Expression,
|
|
1333
|
+
side: t.Expression | null,
|
|
1334
|
+
ternaryPartial: Partial<Ternary> = {}
|
|
1335
|
+
): null | Ternary[] {
|
|
1336
|
+
if (!side) {
|
|
1337
|
+
return null
|
|
1338
|
+
}
|
|
1339
|
+
if (!isStaticObject(side)) {
|
|
1340
|
+
throw new Error('not extractable')
|
|
1341
|
+
}
|
|
1342
|
+
return side.properties.flatMap((property) => {
|
|
1343
|
+
if (!t.isObjectProperty(property)) {
|
|
1344
|
+
throw new Error('expected object property')
|
|
1142
1345
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
if (
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
t.stringLiteral(mediaQueryKey),
|
|
1156
|
-
property.value,
|
|
1157
|
-
{
|
|
1158
|
-
inlineMediaQuery: mediaQueryKey,
|
|
1159
|
-
}
|
|
1160
|
-
)
|
|
1161
|
-
if (ternaries) {
|
|
1162
|
-
return ternaries.map((value) => ({
|
|
1163
|
-
...ternaryPartial,
|
|
1164
|
-
...value,
|
|
1165
|
-
// ensure media query test stays on left side (see getMediaQueryTernary)
|
|
1166
|
-
test: t.logicalExpression('&&', value.test, test),
|
|
1167
|
-
}))
|
|
1168
|
-
} else {
|
|
1169
|
-
console.log('⚠️ no ternaries?', property)
|
|
1346
|
+
// handle media queries inside spread/conditional objects
|
|
1347
|
+
if (t.isIdentifier(property.key)) {
|
|
1348
|
+
const key = property.key.name
|
|
1349
|
+
const mediaQueryKey = key.slice(1)
|
|
1350
|
+
const isMediaQuery = key[0] === '$' && mediaQueryConfig[mediaQueryKey]
|
|
1351
|
+
if (isMediaQuery) {
|
|
1352
|
+
if (t.isExpression(property.value)) {
|
|
1353
|
+
const ternaries = createTernariesFromObjectProperties(
|
|
1354
|
+
t.stringLiteral(mediaQueryKey),
|
|
1355
|
+
property.value,
|
|
1356
|
+
{
|
|
1357
|
+
inlineMediaQuery: mediaQueryKey,
|
|
1170
1358
|
}
|
|
1359
|
+
)
|
|
1360
|
+
if (ternaries) {
|
|
1361
|
+
return ternaries.map((value) => ({
|
|
1362
|
+
...ternaryPartial,
|
|
1363
|
+
...value,
|
|
1364
|
+
// ensure media query test stays on left side (see getMediaQueryTernary)
|
|
1365
|
+
test: t.logicalExpression('&&', value.test, test),
|
|
1366
|
+
}))
|
|
1171
1367
|
} else {
|
|
1172
|
-
|
|
1368
|
+
logger.info(['⚠️ no ternaries?', property].join(' '))
|
|
1173
1369
|
}
|
|
1370
|
+
} else {
|
|
1371
|
+
logger.info(['⚠️ not expression', property].join(' '))
|
|
1174
1372
|
}
|
|
1175
1373
|
}
|
|
1176
|
-
// this could be a recurse here if we want to get fancy
|
|
1177
|
-
if (t.isConditionalExpression(property.value)) {
|
|
1178
|
-
// merge up into the parent conditional, split into two
|
|
1179
|
-
const [truthy, falsy] = [
|
|
1180
|
-
t.objectExpression([t.objectProperty(property.key, property.value.consequent)]),
|
|
1181
|
-
t.objectExpression([t.objectProperty(property.key, property.value.alternate)]),
|
|
1182
|
-
].map((x) => attemptEval(x))
|
|
1183
|
-
return [
|
|
1184
|
-
createTernary({
|
|
1185
|
-
remove() {},
|
|
1186
|
-
...ternaryPartial,
|
|
1187
|
-
test: t.logicalExpression('&&', test, property.value.test),
|
|
1188
|
-
consequent: truthy,
|
|
1189
|
-
alternate: null,
|
|
1190
|
-
}),
|
|
1191
|
-
createTernary({
|
|
1192
|
-
...ternaryPartial,
|
|
1193
|
-
test: t.logicalExpression(
|
|
1194
|
-
'&&',
|
|
1195
|
-
test,
|
|
1196
|
-
t.unaryExpression('!', property.value.test)
|
|
1197
|
-
),
|
|
1198
|
-
consequent: falsy,
|
|
1199
|
-
alternate: null,
|
|
1200
|
-
remove() {},
|
|
1201
|
-
}),
|
|
1202
|
-
]
|
|
1203
|
-
}
|
|
1204
|
-
const obj = t.objectExpression([t.objectProperty(property.key, property.value)])
|
|
1205
|
-
const consequent = attemptEval(obj)
|
|
1206
|
-
return createTernary({
|
|
1207
|
-
remove() {},
|
|
1208
|
-
...ternaryPartial,
|
|
1209
|
-
test,
|
|
1210
|
-
consequent,
|
|
1211
|
-
alternate: null,
|
|
1212
|
-
})
|
|
1213
|
-
})
|
|
1214
|
-
}
|
|
1215
|
-
|
|
1216
|
-
// now update to new values
|
|
1217
|
-
node.attributes = attrs.filter(isAttr).map((x) => x.value)
|
|
1218
|
-
|
|
1219
|
-
if (couldntParse || shouldDeopt) {
|
|
1220
|
-
if (shouldPrintDebug) {
|
|
1221
|
-
console.log(` avoid optimizing:`, { couldntParse, shouldDeopt })
|
|
1222
1374
|
}
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1375
|
+
// this could be a recurse here if we want to get fancy
|
|
1376
|
+
if (t.isConditionalExpression(property.value)) {
|
|
1377
|
+
// merge up into the parent conditional, split into two
|
|
1378
|
+
const [truthy, falsy] = [
|
|
1379
|
+
t.objectExpression([t.objectProperty(property.key, property.value.consequent)]),
|
|
1380
|
+
t.objectExpression([t.objectProperty(property.key, property.value.alternate)]),
|
|
1381
|
+
].map((x) => attemptEval(x))
|
|
1382
|
+
return [
|
|
1383
|
+
createTernary({
|
|
1384
|
+
remove() {},
|
|
1385
|
+
...ternaryPartial,
|
|
1386
|
+
test: t.logicalExpression('&&', test, property.value.test),
|
|
1387
|
+
consequent: truthy,
|
|
1388
|
+
alternate: null,
|
|
1389
|
+
}),
|
|
1390
|
+
createTernary({
|
|
1391
|
+
...ternaryPartial,
|
|
1392
|
+
test: t.logicalExpression(
|
|
1393
|
+
'&&',
|
|
1394
|
+
test,
|
|
1395
|
+
t.unaryExpression('!', property.value.test)
|
|
1396
|
+
),
|
|
1397
|
+
consequent: falsy,
|
|
1398
|
+
alternate: null,
|
|
1399
|
+
remove() {},
|
|
1400
|
+
}),
|
|
1401
|
+
]
|
|
1402
|
+
}
|
|
1403
|
+
const obj = t.objectExpression([t.objectProperty(property.key, property.value)])
|
|
1404
|
+
const consequent = attemptEval(obj)
|
|
1405
|
+
return createTernary({
|
|
1406
|
+
remove() {},
|
|
1407
|
+
...ternaryPartial,
|
|
1408
|
+
test,
|
|
1409
|
+
consequent,
|
|
1410
|
+
alternate: null,
|
|
1411
|
+
})
|
|
1412
|
+
})
|
|
1413
|
+
}
|
|
1226
1414
|
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
modifiedComponents.add(parentFn)
|
|
1415
|
+
if (couldntParse || shouldDeopt) {
|
|
1416
|
+
if (shouldPrintDebug) {
|
|
1417
|
+
logger.info([` avoid optimizing:`, { couldntParse, shouldDeopt }].join(' '))
|
|
1231
1418
|
}
|
|
1419
|
+
node.attributes = ogAttributes
|
|
1420
|
+
return
|
|
1421
|
+
}
|
|
1232
1422
|
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
)
|
|
1423
|
+
// now update to new values
|
|
1424
|
+
node.attributes = attrs.filter(isAttr).map((x) => x.value)
|
|
1425
|
+
|
|
1426
|
+
// before deopt, can still optimize
|
|
1427
|
+
const parentFn = findTopmostFunction(traversePath)
|
|
1428
|
+
if (parentFn) {
|
|
1429
|
+
modifiedComponents.add(parentFn)
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
// combine ternaries
|
|
1433
|
+
let ternaries: Ternary[] = []
|
|
1434
|
+
attrs = attrs
|
|
1435
|
+
.reduce<(ExtractedAttr | ExtractedAttr[])[]>((out, cur) => {
|
|
1436
|
+
const next = attrs[attrs.indexOf(cur) + 1]
|
|
1437
|
+
if (cur.type === 'ternary') {
|
|
1438
|
+
ternaries.push(cur.value)
|
|
1439
|
+
}
|
|
1440
|
+
if ((!next || next.type !== 'ternary') && ternaries.length) {
|
|
1441
|
+
// finish, process
|
|
1442
|
+
const normalized = normalizeTernaries(ternaries).map(
|
|
1443
|
+
({ alternate, consequent, ...rest }) => {
|
|
1444
|
+
return {
|
|
1445
|
+
type: 'ternary' as const,
|
|
1446
|
+
value: {
|
|
1447
|
+
...rest,
|
|
1448
|
+
alternate: alternate || null,
|
|
1449
|
+
consequent: consequent || null,
|
|
1450
|
+
},
|
|
1262
1451
|
}
|
|
1263
|
-
ternaries = []
|
|
1264
1452
|
}
|
|
1453
|
+
)
|
|
1454
|
+
try {
|
|
1455
|
+
return [...out, ...normalized]
|
|
1456
|
+
} finally {
|
|
1457
|
+
if (shouldPrintDebug) {
|
|
1458
|
+
logger.info(
|
|
1459
|
+
` normalizeTernaries (${ternaries.length} => ${normalized.length})`
|
|
1460
|
+
)
|
|
1461
|
+
}
|
|
1462
|
+
ternaries = []
|
|
1265
1463
|
}
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
}
|
|
1269
|
-
out.push(cur)
|
|
1464
|
+
}
|
|
1465
|
+
if (cur.type === 'ternary') {
|
|
1270
1466
|
return out
|
|
1271
|
-
}
|
|
1272
|
-
.
|
|
1467
|
+
}
|
|
1468
|
+
out.push(cur)
|
|
1469
|
+
return out
|
|
1470
|
+
}, [])
|
|
1471
|
+
.flat()
|
|
1273
1472
|
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1473
|
+
// flatten logic!
|
|
1474
|
+
// fairly simple check to see if all children are text
|
|
1475
|
+
const hasSpread = node.attributes.some((x) => t.isJSXSpreadAttribute(x))
|
|
1277
1476
|
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1477
|
+
const hasOnlyStringChildren =
|
|
1478
|
+
!hasSpread &&
|
|
1479
|
+
(node.selfClosing ||
|
|
1480
|
+
(traversePath.node.children &&
|
|
1481
|
+
traversePath.node.children.every((x) => x.type === 'JSXText')))
|
|
1482
|
+
|
|
1483
|
+
const themeVal = inlined.get('theme')
|
|
1283
1484
|
|
|
1284
|
-
|
|
1485
|
+
// on native we can't flatten when theme prop is set
|
|
1486
|
+
if (target !== 'native') {
|
|
1285
1487
|
inlined.delete('theme')
|
|
1488
|
+
}
|
|
1286
1489
|
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1490
|
+
for (const [key] of [...inlined]) {
|
|
1491
|
+
const isStaticObjectVariant = staticConfig.variants?.[key] && variantValues.has(key)
|
|
1492
|
+
if (INLINE_EXTRACTABLE[key] || isStaticObjectVariant) {
|
|
1493
|
+
inlined.delete(key)
|
|
1291
1494
|
}
|
|
1495
|
+
}
|
|
1292
1496
|
|
|
1293
|
-
|
|
1497
|
+
const canFlattenProps = inlined.size === 0
|
|
1294
1498
|
|
|
1295
|
-
|
|
1499
|
+
let shouldFlatten = Boolean(
|
|
1500
|
+
flatNode &&
|
|
1296
1501
|
!shouldDeopt &&
|
|
1297
1502
|
canFlattenProps &&
|
|
1298
1503
|
!hasSpread &&
|
|
1299
1504
|
staticConfig.neverFlatten !== true &&
|
|
1300
1505
|
(staticConfig.neverFlatten === 'jsx' ? hasOnlyStringChildren : true)
|
|
1506
|
+
)
|
|
1301
1507
|
|
|
1302
|
-
|
|
1508
|
+
const shouldWrapTheme = shouldFlatten && themeVal
|
|
1509
|
+
const usedThemeKeys = new Set<string>()
|
|
1303
1510
|
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1511
|
+
if (disableExtractVariables) {
|
|
1512
|
+
// if it accesses any theme values during evaluation
|
|
1513
|
+
themeAccessListeners.add((key) => {
|
|
1514
|
+
shouldFlatten = false
|
|
1515
|
+
usedThemeKeys.add(key)
|
|
1516
|
+
if (shouldPrintDebug === 'verbose') {
|
|
1517
|
+
logger.info([' ! accessing theme key, avoid flatten', key].join(' '))
|
|
1518
|
+
}
|
|
1519
|
+
})
|
|
1520
|
+
}
|
|
1312
1521
|
|
|
1313
|
-
|
|
1522
|
+
if (shouldPrintDebug) {
|
|
1523
|
+
try {
|
|
1314
1524
|
// prettier-ignore
|
|
1315
|
-
|
|
1525
|
+
logger.info([' flatten?', objToStr({ hasSpread, shouldDeopt, shouldFlatten, canFlattenProps, shouldWrapTheme, hasOnlyStringChildren }), 'inlined', [...inlined]].join(' '))
|
|
1526
|
+
} catch {
|
|
1527
|
+
// ok
|
|
1316
1528
|
}
|
|
1529
|
+
}
|
|
1317
1530
|
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1531
|
+
// wrap theme around children on flatten
|
|
1532
|
+
// TODO move this to bottom and re-check shouldFlatten
|
|
1533
|
+
// account for shouldFlatten could change w the above block "if (disableExtractVariables)"
|
|
1534
|
+
if (shouldFlatten && shouldWrapTheme) {
|
|
1535
|
+
if (!programPath) {
|
|
1536
|
+
console.warn(
|
|
1537
|
+
`No program path found, avoiding importing flattening / importing theme in ${sourcePath}`
|
|
1538
|
+
)
|
|
1539
|
+
} else {
|
|
1322
1540
|
if (shouldPrintDebug) {
|
|
1323
|
-
|
|
1541
|
+
logger.info([' - wrapping theme', themeVal].join(' '))
|
|
1324
1542
|
}
|
|
1325
1543
|
|
|
1326
1544
|
// remove theme attribute from flattened node
|
|
@@ -1351,578 +1569,539 @@ export function createExtractor() {
|
|
|
1351
1569
|
)
|
|
1352
1570
|
)
|
|
1353
1571
|
}
|
|
1572
|
+
}
|
|
1354
1573
|
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
}
|
|
1361
|
-
const value = staticConfig.defaultProps[key]
|
|
1362
|
-
const name = tamaguiConfig.shorthands[key] || key
|
|
1363
|
-
if (value === undefined) {
|
|
1364
|
-
console.warn(
|
|
1365
|
-
`⚠️ Error evaluating default style for component, prop ${key} ${value}`
|
|
1366
|
-
)
|
|
1367
|
-
shouldDeopt = true
|
|
1368
|
-
return
|
|
1369
|
-
}
|
|
1370
|
-
const attr: ExtractedAttrStyle = {
|
|
1371
|
-
type: 'style',
|
|
1372
|
-
name,
|
|
1373
|
-
value: { [name]: value },
|
|
1374
|
-
}
|
|
1375
|
-
return attr
|
|
1376
|
-
}) as ExtractedAttr[]
|
|
1377
|
-
|
|
1378
|
-
if (defaultStyleAttrs.length) {
|
|
1379
|
-
attrs = [...defaultStyleAttrs, ...attrs]
|
|
1574
|
+
// only if we flatten, ensure the default styles are there
|
|
1575
|
+
if (shouldFlatten) {
|
|
1576
|
+
const defaultStyleAttrs = Object.keys(staticConfig.defaultProps).flatMap((key) => {
|
|
1577
|
+
if (!isValidStyleKey(key, staticConfig)) {
|
|
1578
|
+
return []
|
|
1380
1579
|
}
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
// insert overrides - this inserts null props for things that are set in classNames
|
|
1389
|
-
// only when not flattening, so the downstream component can skip applying those styles
|
|
1390
|
-
const ensureOverridden = {}
|
|
1391
|
-
if (!shouldFlatten) {
|
|
1392
|
-
for (const cur of attrs) {
|
|
1393
|
-
if (cur.type === 'style') {
|
|
1394
|
-
// TODO need to loop over initial props not just style props
|
|
1395
|
-
for (const key in cur.value) {
|
|
1396
|
-
const shouldEnsureOverridden = !!staticConfig.ensureOverriddenProp?.[key]
|
|
1397
|
-
const isSetInAttrsAlready = attrs.some(
|
|
1398
|
-
(x) =>
|
|
1399
|
-
x.type === 'attr' &&
|
|
1400
|
-
x.value.type === 'JSXAttribute' &&
|
|
1401
|
-
x.value.name.name === key
|
|
1402
|
-
)
|
|
1403
|
-
|
|
1404
|
-
if (!isSetInAttrsAlready) {
|
|
1405
|
-
const isVariant = !!staticConfig.variants?.[cur.name || '']
|
|
1406
|
-
if (isVariant || shouldEnsureOverridden) {
|
|
1407
|
-
ensureOverridden[key] = true
|
|
1408
|
-
}
|
|
1409
|
-
}
|
|
1410
|
-
}
|
|
1411
|
-
}
|
|
1580
|
+
const value = staticConfig.defaultProps[key]
|
|
1581
|
+
const name = tamaguiConfig.shorthands[key] || key
|
|
1582
|
+
if (value === undefined) {
|
|
1583
|
+
logger.warn(`⚠️ Error evaluating default style for component, prop ${key} ${value}`)
|
|
1584
|
+
shouldDeopt = true
|
|
1585
|
+
return
|
|
1412
1586
|
}
|
|
1587
|
+
const attr: ExtractedAttrStyle = {
|
|
1588
|
+
type: 'style',
|
|
1589
|
+
name,
|
|
1590
|
+
value: { [name]: value },
|
|
1591
|
+
}
|
|
1592
|
+
return attr
|
|
1593
|
+
}) as ExtractedAttr[]
|
|
1594
|
+
|
|
1595
|
+
if (defaultStyleAttrs.length) {
|
|
1596
|
+
attrs = [...defaultStyleAttrs, ...attrs]
|
|
1413
1597
|
}
|
|
1598
|
+
}
|
|
1414
1599
|
|
|
1600
|
+
if (shouldDeopt || !shouldFlatten) {
|
|
1415
1601
|
if (shouldPrintDebug) {
|
|
1416
|
-
|
|
1417
|
-
console.log(' - ensureOverriden:', Object.keys(ensureOverridden).join(', '))
|
|
1602
|
+
logger.info(`Deopting`)
|
|
1418
1603
|
}
|
|
1604
|
+
node.attributes = ogAttributes
|
|
1605
|
+
return
|
|
1606
|
+
}
|
|
1419
1607
|
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
press: false,
|
|
1426
|
-
pressIn: false,
|
|
1427
|
-
}
|
|
1608
|
+
if (shouldPrintDebug) {
|
|
1609
|
+
logger.info(
|
|
1610
|
+
[' - attrs (flattened): \n', logLines(attrs.map(attrStr).join(', '))].join(' ')
|
|
1611
|
+
)
|
|
1612
|
+
}
|
|
1428
1613
|
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1614
|
+
const state = {
|
|
1615
|
+
noClassNames: false,
|
|
1616
|
+
focus: false,
|
|
1617
|
+
hover: false,
|
|
1618
|
+
unmounted: false, // TODO match logic in createComponent
|
|
1619
|
+
press: false,
|
|
1620
|
+
pressIn: false,
|
|
1621
|
+
}
|
|
1622
|
+
|
|
1623
|
+
// evaluates all static attributes into a simple object
|
|
1624
|
+
let foundStaticProps = {}
|
|
1625
|
+
for (const key in attrs) {
|
|
1626
|
+
const cur = attrs[key]
|
|
1627
|
+
if (cur.type === 'style') {
|
|
1628
|
+
// remove variants because they are processed later, and can lead to invalid values here
|
|
1629
|
+
// see <Spacer flex /> where flex looks like a valid style, but is a variant
|
|
1630
|
+
foundStaticProps = {
|
|
1631
|
+
...foundStaticProps,
|
|
1632
|
+
...expandStylesWithoutVariants(cur.value),
|
|
1633
|
+
}
|
|
1634
|
+
continue
|
|
1635
|
+
}
|
|
1636
|
+
if (cur.type === 'attr') {
|
|
1637
|
+
if (t.isJSXSpreadAttribute(cur.value)) {
|
|
1438
1638
|
continue
|
|
1439
1639
|
}
|
|
1440
|
-
if (cur.
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
if (value !== FAILED_EVAL) {
|
|
1451
|
-
foundStaticProps = {
|
|
1452
|
-
...foundStaticProps,
|
|
1453
|
-
[key]: value,
|
|
1454
|
-
}
|
|
1640
|
+
if (!t.isJSXIdentifier(cur.value.name)) {
|
|
1641
|
+
continue
|
|
1642
|
+
}
|
|
1643
|
+
const key = cur.value.name.name
|
|
1644
|
+
// undefined = boolean true
|
|
1645
|
+
const value = attemptEvalSafe(cur.value.value || t.booleanLiteral(true))
|
|
1646
|
+
if (value !== FAILED_EVAL) {
|
|
1647
|
+
foundStaticProps = {
|
|
1648
|
+
...foundStaticProps,
|
|
1649
|
+
[key]: value,
|
|
1455
1650
|
}
|
|
1456
1651
|
}
|
|
1457
1652
|
}
|
|
1653
|
+
}
|
|
1458
1654
|
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
for (const key in foundStaticProps) {
|
|
1467
|
-
completeProps[key] = foundStaticProps[key]
|
|
1655
|
+
// must preserve exact order
|
|
1656
|
+
const completeProps = {}
|
|
1657
|
+
for (const key in staticConfig.defaultProps) {
|
|
1658
|
+
if (!(key in foundStaticProps)) {
|
|
1659
|
+
completeProps[key] = staticConfig.defaultProps[key]
|
|
1468
1660
|
}
|
|
1661
|
+
}
|
|
1662
|
+
for (const key in foundStaticProps) {
|
|
1663
|
+
completeProps[key] = foundStaticProps[key]
|
|
1664
|
+
}
|
|
1469
1665
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1666
|
+
// expand shorthands, de-opt variables
|
|
1667
|
+
attrs = attrs.reduce<ExtractedAttr[]>((acc, cur) => {
|
|
1668
|
+
if (!cur) return acc
|
|
1669
|
+
if (cur.type === 'attr' && !t.isJSXSpreadAttribute(cur.value)) {
|
|
1670
|
+
if (shouldFlatten) {
|
|
1671
|
+
const name = cur.value.name.name
|
|
1672
|
+
if (typeof name === 'string') {
|
|
1673
|
+
if (name === 'tag') {
|
|
1674
|
+
// remove tag=""
|
|
1675
|
+
return acc
|
|
1676
|
+
}
|
|
1481
1677
|
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
)
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
}
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
)
|
|
1525
|
-
|
|
1526
|
-
}
|
|
1678
|
+
// if flattening, expand variants
|
|
1679
|
+
if (variants[name] && variantValues.has(name)) {
|
|
1680
|
+
let out = Object.fromEntries(
|
|
1681
|
+
staticConfig.propMapper(
|
|
1682
|
+
name,
|
|
1683
|
+
variantValues.get(name),
|
|
1684
|
+
defaultTheme,
|
|
1685
|
+
completeProps,
|
|
1686
|
+
{ ...state, resolveVariablesAs: 'auto' },
|
|
1687
|
+
undefined,
|
|
1688
|
+
undefined,
|
|
1689
|
+
shouldPrintDebug
|
|
1690
|
+
) || []
|
|
1691
|
+
)
|
|
1692
|
+
if (out && isTargetingHTML) {
|
|
1693
|
+
const cn = out.className
|
|
1694
|
+
// translate to DOM-compat
|
|
1695
|
+
out = createDOMProps(isTextView ? 'span' : 'div', out)
|
|
1696
|
+
// remove rnw className use ours
|
|
1697
|
+
out.className = cn
|
|
1698
|
+
}
|
|
1699
|
+
if (shouldPrintDebug) {
|
|
1700
|
+
logger.info([' - expanded variant', name, out].join(' '))
|
|
1701
|
+
}
|
|
1702
|
+
for (const key in out) {
|
|
1703
|
+
const value = out[key]
|
|
1704
|
+
if (isValidStyleKey(key, staticConfig)) {
|
|
1705
|
+
acc.push({
|
|
1706
|
+
type: 'style',
|
|
1707
|
+
value: { [key]: value },
|
|
1708
|
+
name: key,
|
|
1709
|
+
attr: cur.value,
|
|
1710
|
+
} as const)
|
|
1711
|
+
} else {
|
|
1712
|
+
acc.push({
|
|
1713
|
+
type: 'attr',
|
|
1714
|
+
value: t.jsxAttribute(
|
|
1715
|
+
t.jsxIdentifier(key),
|
|
1716
|
+
t.jsxExpressionContainer(
|
|
1717
|
+
typeof value === 'string'
|
|
1718
|
+
? t.stringLiteral(value)
|
|
1719
|
+
: literalToAst(value)
|
|
1720
|
+
)
|
|
1721
|
+
),
|
|
1722
|
+
})
|
|
1527
1723
|
}
|
|
1528
1724
|
}
|
|
1529
1725
|
}
|
|
1530
1726
|
}
|
|
1531
1727
|
}
|
|
1728
|
+
}
|
|
1532
1729
|
|
|
1533
|
-
|
|
1534
|
-
acc.push(cur)
|
|
1535
|
-
return acc
|
|
1536
|
-
}
|
|
1537
|
-
|
|
1538
|
-
let key = Object.keys(cur.value)[0]
|
|
1539
|
-
const value = cur.value[key]
|
|
1540
|
-
const fullKey = tamaguiConfig.shorthands[key]
|
|
1541
|
-
// expand shorthands
|
|
1542
|
-
if (fullKey) {
|
|
1543
|
-
cur.value = { [fullKey]: value }
|
|
1544
|
-
key = fullKey
|
|
1545
|
-
}
|
|
1546
|
-
|
|
1547
|
-
// finally we have all styles + expansions, lets see if we need to skip
|
|
1548
|
-
// any and keep them as attrs
|
|
1549
|
-
if (disableExtractVariables) {
|
|
1550
|
-
if (value[0] === '$') {
|
|
1551
|
-
if (shouldPrintDebug) {
|
|
1552
|
-
console.log(` keeping variable inline: ${key} =`, value)
|
|
1553
|
-
}
|
|
1554
|
-
acc.push({
|
|
1555
|
-
type: 'attr',
|
|
1556
|
-
value: t.jsxAttribute(
|
|
1557
|
-
t.jsxIdentifier(key),
|
|
1558
|
-
t.jsxExpressionContainer(t.stringLiteral(value))
|
|
1559
|
-
),
|
|
1560
|
-
})
|
|
1561
|
-
return acc
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1730
|
+
if (cur.type !== 'style') {
|
|
1565
1731
|
acc.push(cur)
|
|
1566
1732
|
return acc
|
|
1567
|
-
}, [])
|
|
1568
|
-
|
|
1569
|
-
tm.mark('jsx-element-expanded', shouldPrintDebug === 'verbose')
|
|
1570
|
-
if (shouldPrintDebug) {
|
|
1571
|
-
console.log(' - attrs (expanded): \n', logLines(attrs.map(attrStr).join(', ')))
|
|
1572
1733
|
}
|
|
1573
1734
|
|
|
1574
|
-
|
|
1575
|
-
|
|
1735
|
+
let key = Object.keys(cur.value)[0]
|
|
1736
|
+
const value = cur.value[key]
|
|
1737
|
+
const fullKey = tamaguiConfig.shorthands[key]
|
|
1738
|
+
// expand shorthands
|
|
1739
|
+
if (fullKey) {
|
|
1740
|
+
cur.value = { [fullKey]: value }
|
|
1741
|
+
key = fullKey
|
|
1742
|
+
}
|
|
1576
1743
|
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
if (
|
|
1582
|
-
|
|
1583
|
-
if (shouldPrintDebug) {
|
|
1584
|
-
if (!next[key] || !prev[key]) {
|
|
1585
|
-
console.log('warn: missing', key, prev, next)
|
|
1586
|
-
}
|
|
1587
|
-
}
|
|
1588
|
-
Object.assign(prev[key], next[key])
|
|
1589
|
-
} else {
|
|
1590
|
-
prev[key] = next[key]
|
|
1744
|
+
// finally we have all styles + expansions, lets see if we need to skip
|
|
1745
|
+
// any and keep them as attrs
|
|
1746
|
+
if (disableExtractVariables) {
|
|
1747
|
+
if (value[0] === '$' && (usedThemeKeys.has(key) || usedThemeKeys.has(fullKey))) {
|
|
1748
|
+
if (shouldPrintDebug) {
|
|
1749
|
+
logger.info([` keeping variable inline: ${key} =`, value].join(' '))
|
|
1591
1750
|
}
|
|
1751
|
+
acc.push({
|
|
1752
|
+
type: 'attr',
|
|
1753
|
+
value: t.jsxAttribute(
|
|
1754
|
+
t.jsxIdentifier(key),
|
|
1755
|
+
t.jsxExpressionContainer(t.stringLiteral(value))
|
|
1756
|
+
),
|
|
1757
|
+
})
|
|
1758
|
+
return acc
|
|
1592
1759
|
}
|
|
1593
1760
|
}
|
|
1594
1761
|
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
const value = cur.value[key]
|
|
1599
|
-
|
|
1600
|
-
const shouldKeepOriginalAttr =
|
|
1601
|
-
// !isStyleAndAttr[key] &&
|
|
1602
|
-
!shouldFlatten &&
|
|
1603
|
-
// de-opt transform styles so it merges properly if not flattened
|
|
1604
|
-
// we handle this later on
|
|
1605
|
-
// (stylePropsTransform[key] ||
|
|
1606
|
-
// de-opt if non-style
|
|
1607
|
-
!validStyles[key] &&
|
|
1608
|
-
!pseudoDescriptors[key] &&
|
|
1609
|
-
!key.startsWith('data-')
|
|
1610
|
-
|
|
1611
|
-
if (shouldKeepOriginalAttr) {
|
|
1612
|
-
if (shouldPrintDebug) {
|
|
1613
|
-
console.log(' - keeping as non-style', key)
|
|
1614
|
-
}
|
|
1615
|
-
prev = cur
|
|
1616
|
-
acc.push({
|
|
1617
|
-
type: 'attr',
|
|
1618
|
-
value: t.jsxAttribute(
|
|
1619
|
-
t.jsxIdentifier(key),
|
|
1620
|
-
t.jsxExpressionContainer(
|
|
1621
|
-
typeof value === 'string' ? t.stringLiteral(value) : literalToAst(value)
|
|
1622
|
-
)
|
|
1623
|
-
),
|
|
1624
|
-
})
|
|
1625
|
-
acc.push(cur)
|
|
1626
|
-
return acc
|
|
1627
|
-
}
|
|
1762
|
+
acc.push(cur)
|
|
1763
|
+
return acc
|
|
1764
|
+
}, [])
|
|
1628
1765
|
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
t.jsxIdentifier(key),
|
|
1636
|
-
t.jsxExpressionContainer(t.nullLiteral())
|
|
1637
|
-
),
|
|
1638
|
-
})
|
|
1639
|
-
}
|
|
1766
|
+
tm.mark('jsx-element-expanded', !!shouldPrintDebug)
|
|
1767
|
+
if (shouldPrintDebug) {
|
|
1768
|
+
logger.info(
|
|
1769
|
+
[' - attrs (expanded): \n', logLines(attrs.map(attrStr).join(', '))].join(' ')
|
|
1770
|
+
)
|
|
1771
|
+
}
|
|
1640
1772
|
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
return acc
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1773
|
+
// merge styles, leave undefined values
|
|
1774
|
+
let prev: ExtractedAttr | null = null
|
|
1646
1775
|
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1776
|
+
function splitVariants(style: any) {
|
|
1777
|
+
const variants = {}
|
|
1778
|
+
const styles = {}
|
|
1779
|
+
for (const key in style) {
|
|
1780
|
+
if (staticConfig.variants?.[key]) {
|
|
1781
|
+
variants[key] = style[key]
|
|
1782
|
+
} else {
|
|
1783
|
+
styles[key] = style[key]
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
return {
|
|
1787
|
+
variants,
|
|
1788
|
+
styles,
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1651
1791
|
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
console.log(' - completeProps: \n', logLines(objToStr(completeProps)))
|
|
1792
|
+
function expandStylesWithoutVariants(style: any) {
|
|
1793
|
+
const { variants, styles } = splitVariants(style)
|
|
1794
|
+
return {
|
|
1795
|
+
...expandStyles(styles),
|
|
1796
|
+
...variants,
|
|
1658
1797
|
}
|
|
1798
|
+
}
|
|
1659
1799
|
|
|
1660
|
-
|
|
1661
|
-
const
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
if (shouldPrintDebug) console.log(' delete excluded', key)
|
|
1670
|
-
delete props[key]
|
|
1800
|
+
function mergeStyles(prev: ViewStyle & PseudoStyles, nextIn: ViewStyle & PseudoStyles) {
|
|
1801
|
+
const next = expandStylesWithoutVariants(nextIn)
|
|
1802
|
+
for (const key in next) {
|
|
1803
|
+
// merge pseudos
|
|
1804
|
+
if (pseudoDescriptors[key]) {
|
|
1805
|
+
prev[key] = prev[key] || {}
|
|
1806
|
+
if (shouldPrintDebug) {
|
|
1807
|
+
if (!next[key] || !prev[key]) {
|
|
1808
|
+
logger.info(['warn: missing', key, prev, next].join(' '))
|
|
1671
1809
|
}
|
|
1672
1810
|
}
|
|
1811
|
+
Object.assign(prev[key], next[key])
|
|
1812
|
+
} else {
|
|
1813
|
+
prev[key] = next[key]
|
|
1673
1814
|
}
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
fallbackProps: completeProps,
|
|
1682
|
-
},
|
|
1683
|
-
undefined,
|
|
1684
|
-
props['debug']
|
|
1685
|
-
)
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
attrs = attrs.reduce<ExtractedAttr[]>((acc, cur) => {
|
|
1819
|
+
if (cur.type === 'style') {
|
|
1820
|
+
const key = Object.keys(cur.value)[0]
|
|
1821
|
+
const value = cur.value[key]
|
|
1686
1822
|
|
|
1687
|
-
|
|
1823
|
+
const shouldKeepOriginalAttr =
|
|
1824
|
+
// !isStyleAndAttr[key] &&
|
|
1825
|
+
!shouldFlatten &&
|
|
1826
|
+
// de-opt if non-style
|
|
1827
|
+
!validStyles[key] &&
|
|
1828
|
+
!pseudoDescriptors[key] &&
|
|
1829
|
+
!key.startsWith('data-')
|
|
1688
1830
|
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1831
|
+
if (shouldKeepOriginalAttr) {
|
|
1832
|
+
if (shouldPrintDebug) {
|
|
1833
|
+
logger.info([' - keeping as non-style', key].join(' '))
|
|
1692
1834
|
}
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
return {}
|
|
1835
|
+
prev = cur
|
|
1836
|
+
acc.push({
|
|
1837
|
+
type: 'attr',
|
|
1838
|
+
value: t.jsxAttribute(
|
|
1839
|
+
t.jsxIdentifier(key),
|
|
1840
|
+
t.jsxExpressionContainer(
|
|
1841
|
+
typeof value === 'string' ? t.stringLiteral(value) : literalToAst(value)
|
|
1842
|
+
)
|
|
1843
|
+
),
|
|
1844
|
+
})
|
|
1845
|
+
acc.push(cur)
|
|
1846
|
+
return acc
|
|
1706
1847
|
}
|
|
1707
|
-
}
|
|
1708
1848
|
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
if (
|
|
1713
|
-
stylePropsTransform[key] ||
|
|
1714
|
-
(!staticConfig.validStyles[key] &&
|
|
1715
|
-
!pseudoDescriptors[key] &&
|
|
1716
|
-
!/(hoverStyle|focusStyle|pressStyle)$/.test(key))
|
|
1717
|
-
) {
|
|
1718
|
-
if (shouldPrintDebug) console.log(' delete invalid style', key)
|
|
1719
|
-
delete style[key]
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1849
|
+
if (prev?.type === 'style') {
|
|
1850
|
+
mergeStyles(prev.value, cur.value)
|
|
1851
|
+
return acc
|
|
1722
1852
|
}
|
|
1723
1853
|
}
|
|
1724
1854
|
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
throw new Error(`Impossible, no styles`)
|
|
1730
|
-
}
|
|
1855
|
+
prev = cur
|
|
1856
|
+
acc.push(cur)
|
|
1857
|
+
return acc
|
|
1858
|
+
}, [])
|
|
1731
1859
|
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1860
|
+
if (shouldPrintDebug) {
|
|
1861
|
+
logger.info(
|
|
1862
|
+
[' - attrs (combined 🔀): \n', logLines(attrs.map(attrStr).join(', '))].join(' ')
|
|
1863
|
+
)
|
|
1864
|
+
logger.info(
|
|
1865
|
+
[' - defaultProps: \n', logLines(objToStr(staticConfig.defaultProps))].join(' ')
|
|
1866
|
+
)
|
|
1867
|
+
// prettier-ignore
|
|
1868
|
+
logger.info([' - foundStaticProps: \n', logLines(objToStr(foundStaticProps))].join(' '))
|
|
1869
|
+
logger.info([' - completeProps: \n', logLines(objToStr(completeProps))].join(' '))
|
|
1870
|
+
}
|
|
1736
1871
|
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
if (shouldPrintDebug)
|
|
1741
|
-
|
|
1872
|
+
// post process
|
|
1873
|
+
const getStyles = (props: Object | null, debugName = '') => {
|
|
1874
|
+
if (!props || !Object.keys(props).length) {
|
|
1875
|
+
if (shouldPrintDebug) logger.info([' getStyles() no props'].join(' '))
|
|
1876
|
+
return {}
|
|
1877
|
+
}
|
|
1878
|
+
if (excludeProps && !!excludeProps.size) {
|
|
1879
|
+
for (const key in props) {
|
|
1880
|
+
if (excludeProps.has(key)) {
|
|
1881
|
+
if (shouldPrintDebug) logger.info([' delete excluded', key].join(' '))
|
|
1882
|
+
delete props[key]
|
|
1883
|
+
}
|
|
1742
1884
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1885
|
+
}
|
|
1886
|
+
try {
|
|
1887
|
+
const out = getSplitStyles(
|
|
1888
|
+
props,
|
|
1889
|
+
staticConfig,
|
|
1890
|
+
defaultTheme,
|
|
1891
|
+
{
|
|
1892
|
+
...state,
|
|
1893
|
+
fallbackProps: completeProps,
|
|
1894
|
+
},
|
|
1895
|
+
undefined,
|
|
1896
|
+
undefined,
|
|
1897
|
+
undefined,
|
|
1898
|
+
debugPropValue
|
|
1899
|
+
)
|
|
1900
|
+
|
|
1901
|
+
const outStyle = {
|
|
1902
|
+
...out.style,
|
|
1903
|
+
...out.pseudos,
|
|
1749
1904
|
}
|
|
1905
|
+
// omitInvalidStyles(outStyle)
|
|
1906
|
+
// if (shouldPrintDebug) {
|
|
1907
|
+
// // prettier-ignore
|
|
1908
|
+
// logger.info(` getStyles ${debugName} (props):\n`, logLines(objToStr(props)))
|
|
1909
|
+
// // prettier-ignore
|
|
1910
|
+
// logger.info(` getStyles ${debugName} (out.viewProps):\n`, logLines(objToStr(out.viewProps)))
|
|
1911
|
+
// // prettier-ignore
|
|
1912
|
+
// logger.info(` getStyles ${debugName} (out.style):\n`, logLines(objToStr(outStyle || {}), true))
|
|
1913
|
+
// }
|
|
1914
|
+
return outStyle
|
|
1915
|
+
} catch (err: any) {
|
|
1916
|
+
logger.info(['error', err.message, err.stack].join(' '))
|
|
1917
|
+
return {}
|
|
1750
1918
|
}
|
|
1919
|
+
}
|
|
1920
|
+
|
|
1921
|
+
// used to ensure we pass the entire prop bundle to getStyles
|
|
1922
|
+
const completeStyles = getStyles(completeProps, 'completeStyles')
|
|
1923
|
+
|
|
1924
|
+
if (!completeStyles) {
|
|
1925
|
+
throw new Error(`Impossible, no styles`)
|
|
1926
|
+
}
|
|
1751
1927
|
|
|
1928
|
+
const isNativeNotFlat = !shouldFlatten && target === 'native'
|
|
1929
|
+
if (isNativeNotFlat) {
|
|
1752
1930
|
if (shouldPrintDebug) {
|
|
1753
|
-
|
|
1754
|
-
if (shouldFlatten) console.log(' -- addInitialStyleKeys', addInitialStyleKeys.join(', '))
|
|
1755
|
-
// prettier-ignore
|
|
1756
|
-
// console.log(' -- completeStyles:\n', logLines(objToStr(completeStyles)))
|
|
1931
|
+
logger.info(`Disabled flattening except for simple cases on native for now`)
|
|
1757
1932
|
}
|
|
1933
|
+
node.attributes = ogAttributes
|
|
1934
|
+
return null
|
|
1935
|
+
}
|
|
1758
1936
|
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1937
|
+
let getStyleError: any = null
|
|
1938
|
+
|
|
1939
|
+
// fix up ternaries, combine final style values
|
|
1940
|
+
for (const attr of attrs) {
|
|
1941
|
+
try {
|
|
1942
|
+
switch (attr.type) {
|
|
1943
|
+
case 'ternary': {
|
|
1944
|
+
const a = getStyles(attr.value.alternate, 'ternary.alternate')
|
|
1945
|
+
const c = getStyles(attr.value.consequent, 'ternary.consequent')
|
|
1946
|
+
if (a) attr.value.alternate = a
|
|
1947
|
+
if (c) attr.value.consequent = c
|
|
1948
|
+
if (shouldPrintDebug) logger.info([' => tern ', attrStr(attr)].join(' '))
|
|
1949
|
+
continue
|
|
1950
|
+
}
|
|
1951
|
+
case 'style': {
|
|
1952
|
+
// expand variants and such
|
|
1953
|
+
const styles = getStyles(attr.value, 'style')
|
|
1954
|
+
if (styles) {
|
|
1955
|
+
attr.value = styles
|
|
1956
|
+
}
|
|
1957
|
+
// prettier-ignore
|
|
1958
|
+
if (shouldPrintDebug) logger.info([' * styles (in)', logLines(objToStr(attr.value))].join(' '))
|
|
1959
|
+
// prettier-ignore
|
|
1960
|
+
if (shouldPrintDebug) logger.info([' * styles (out)', logLines(objToStr(styles))].join(' '))
|
|
1961
|
+
continue
|
|
1783
1962
|
}
|
|
1784
|
-
} catch (err) {
|
|
1785
|
-
// any error de-opt
|
|
1786
|
-
getStyleError = err
|
|
1787
1963
|
}
|
|
1964
|
+
} catch (err) {
|
|
1965
|
+
// any error de-opt
|
|
1966
|
+
getStyleError = err
|
|
1788
1967
|
}
|
|
1968
|
+
}
|
|
1789
1969
|
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
tm.mark('jsx-element-styles', shouldPrintDebug === 'verbose')
|
|
1970
|
+
if (shouldPrintDebug) {
|
|
1971
|
+
// prettier-ignore
|
|
1972
|
+
logger.info([' - attrs (ternaries/combined):\n', logLines(attrs.map(attrStr).join(', '))].join(' '))
|
|
1973
|
+
}
|
|
1796
1974
|
|
|
1797
|
-
|
|
1798
|
-
console.log(' ⚠️ postprocessing error, deopt', getStyleError)
|
|
1799
|
-
node.attributes = ogAttributes
|
|
1800
|
-
return node
|
|
1801
|
-
}
|
|
1975
|
+
tm.mark('jsx-element-styles', !!shouldPrintDebug)
|
|
1802
1976
|
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1977
|
+
if (getStyleError) {
|
|
1978
|
+
logger.info([' ⚠️ postprocessing error, deopt', getStyleError].join(' '))
|
|
1979
|
+
node.attributes = ogAttributes
|
|
1980
|
+
return null
|
|
1981
|
+
}
|
|
1807
1982
|
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
if (t.isJSXIdentifier(attr.value.name)) {
|
|
1813
|
-
const name = attr.value.name.name
|
|
1814
|
-
if (INLINE_EXTRACTABLE[name]) {
|
|
1815
|
-
// map to HTML only name
|
|
1816
|
-
attr.value.name.name = INLINE_EXTRACTABLE[name]
|
|
1817
|
-
}
|
|
1983
|
+
// final lazy extra loop:
|
|
1984
|
+
const existingStyleKeys = new Set()
|
|
1985
|
+
for (let i = attrs.length - 1; i >= 0; i--) {
|
|
1986
|
+
const attr = attrs[i]
|
|
1818
1987
|
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1988
|
+
// if flattening map inline props to proper flattened names
|
|
1989
|
+
if (shouldFlatten) {
|
|
1990
|
+
if (attr.type === 'attr') {
|
|
1991
|
+
if (t.isJSXAttribute(attr.value)) {
|
|
1992
|
+
if (t.isJSXIdentifier(attr.value.name)) {
|
|
1993
|
+
const name = attr.value.name.name
|
|
1994
|
+
if (INLINE_EXTRACTABLE[name]) {
|
|
1995
|
+
// map to HTML only name
|
|
1996
|
+
attr.value.name.name = INLINE_EXTRACTABLE[name]
|
|
1827
1997
|
}
|
|
1828
1998
|
}
|
|
1829
1999
|
}
|
|
1830
2000
|
}
|
|
2001
|
+
}
|
|
1831
2002
|
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
}
|
|
1843
|
-
delete attr.value[key]
|
|
1844
|
-
} else {
|
|
1845
|
-
existingStyleKeys.add(key)
|
|
2003
|
+
// remove duplicate styles
|
|
2004
|
+
// so if you have:
|
|
2005
|
+
// style({ color: 'red' }), ...someProps, style({ color: 'green' })
|
|
2006
|
+
// this will mutate:
|
|
2007
|
+
// style({}), ...someProps, style({ color: 'green' })
|
|
2008
|
+
if (attr.type === 'style') {
|
|
2009
|
+
for (const key in attr.value) {
|
|
2010
|
+
if (existingStyleKeys.has(key)) {
|
|
2011
|
+
if (shouldPrintDebug) {
|
|
2012
|
+
logger.info([` >> delete existing ${key}`].join(' '))
|
|
1846
2013
|
}
|
|
2014
|
+
delete attr.value[key]
|
|
2015
|
+
} else {
|
|
2016
|
+
existingStyleKeys.add(key)
|
|
1847
2017
|
}
|
|
1848
2018
|
}
|
|
1849
2019
|
}
|
|
2020
|
+
}
|
|
1850
2021
|
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2022
|
+
// inlineWhenUnflattened
|
|
2023
|
+
if (!shouldFlatten) {
|
|
2024
|
+
if (inlineWhenUnflattened.size) {
|
|
2025
|
+
for (const [index, attr] of attrs.entries()) {
|
|
2026
|
+
if (attr.type === 'style') {
|
|
2027
|
+
for (const key in attr.value) {
|
|
2028
|
+
if (!inlineWhenUnflattened.has(key)) continue
|
|
2029
|
+
const val = inlineWhenUnflattenedOGVals[key]
|
|
2030
|
+
if (val) {
|
|
2031
|
+
// delete the style
|
|
2032
|
+
delete attr.value[key]
|
|
2033
|
+
|
|
2034
|
+
// and insert it before
|
|
2035
|
+
attrs.splice(index - 1, 0, val.attr)
|
|
2036
|
+
} else {
|
|
2037
|
+
// just delete it, it was added during expansion but should be left inline
|
|
2038
|
+
delete attr.value[key]
|
|
1865
2039
|
}
|
|
1866
2040
|
}
|
|
1867
2041
|
}
|
|
1868
2042
|
}
|
|
1869
2043
|
}
|
|
2044
|
+
}
|
|
1870
2045
|
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
if (shouldPrintDebug) {
|
|
1874
|
-
console.log(' [✅] flattening', originalNodeName, flatNode)
|
|
1875
|
-
}
|
|
1876
|
-
node.name.name = flatNode
|
|
1877
|
-
res.flattened++
|
|
1878
|
-
if (closingElement) {
|
|
1879
|
-
closingElement.name.name = flatNode
|
|
1880
|
-
}
|
|
1881
|
-
}
|
|
1882
|
-
|
|
2046
|
+
if (shouldFlatten) {
|
|
2047
|
+
// DO FLATTEN
|
|
1883
2048
|
if (shouldPrintDebug) {
|
|
1884
|
-
|
|
1885
|
-
console.log(` ❊❊ inline props (${inlined.size}):`, shouldDeopt ? ' deopted' : '', hasSpread ? ' has spread' : '', staticConfig.neverFlatten ? 'neverFlatten' : '')
|
|
1886
|
-
console.log(' - attrs (end):\n', logLines(attrs.map(attrStr).join(', ')))
|
|
2049
|
+
logger.info([' [✅] flattening', originalNodeName, flatNode].join(' '))
|
|
1887
2050
|
}
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
attemptEval,
|
|
1895
|
-
jsxPath: traversePath,
|
|
1896
|
-
originalNodeName,
|
|
1897
|
-
isFlattened: shouldFlatten,
|
|
1898
|
-
programPath,
|
|
1899
|
-
})
|
|
1900
|
-
} finally {
|
|
1901
|
-
if (debugPropValue) {
|
|
1902
|
-
shouldPrintDebug = ogDebug
|
|
2051
|
+
// @ts-ignore
|
|
2052
|
+
node.name.name = flatNode
|
|
2053
|
+
res.flattened++
|
|
2054
|
+
if (closingElement) {
|
|
2055
|
+
// @ts-ignore
|
|
2056
|
+
closingElement.name.name = flatNode
|
|
1903
2057
|
}
|
|
1904
2058
|
}
|
|
1905
|
-
},
|
|
1906
|
-
})
|
|
1907
2059
|
|
|
1908
|
-
|
|
2060
|
+
if (shouldPrintDebug) {
|
|
2061
|
+
// prettier-ignore
|
|
2062
|
+
logger.info([` ❊❊ inline props (${inlined.size}):`, shouldDeopt ? ' deopted' : '', hasSpread ? ' has spread' : '', staticConfig.neverFlatten ? 'neverFlatten' : ''].join(' '))
|
|
2063
|
+
logger.info(` - attrs (end):\n ${logLines(attrs.map(attrStr).join(', '))}`)
|
|
2064
|
+
}
|
|
1909
2065
|
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
2066
|
+
onExtractTag({
|
|
2067
|
+
parserProps: propsWithFileInfo,
|
|
2068
|
+
attrs,
|
|
2069
|
+
node,
|
|
2070
|
+
lineNumbers,
|
|
2071
|
+
filePath,
|
|
2072
|
+
attemptEval,
|
|
2073
|
+
jsxPath: traversePath,
|
|
2074
|
+
originalNodeName,
|
|
2075
|
+
isFlattened: shouldFlatten,
|
|
2076
|
+
programPath: programPath!,
|
|
2077
|
+
completeProps,
|
|
2078
|
+
staticConfig,
|
|
2079
|
+
})
|
|
2080
|
+
} finally {
|
|
2081
|
+
if (debugPropValue) {
|
|
2082
|
+
shouldPrintDebug = ogDebug
|
|
2083
|
+
}
|
|
1920
2084
|
}
|
|
2085
|
+
},
|
|
2086
|
+
})
|
|
2087
|
+
|
|
2088
|
+
tm.mark('jsx-done', !!shouldPrintDebug)
|
|
2089
|
+
|
|
2090
|
+
/**
|
|
2091
|
+
* Step 3: Remove dead code from removed media query / theme hooks
|
|
2092
|
+
*/
|
|
2093
|
+
if (modifiedComponents.size) {
|
|
2094
|
+
const all = Array.from(modifiedComponents)
|
|
2095
|
+
if (shouldPrintDebug) {
|
|
2096
|
+
logger.info(` [🪝] hook check ${all.length}`)
|
|
1921
2097
|
}
|
|
2098
|
+
for (const comp of all) {
|
|
2099
|
+
removeUnusedHooks(comp, shouldPrintDebug)
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
1922
2102
|
|
|
1923
|
-
|
|
2103
|
+
tm.done(shouldPrintDebug === 'verbose')
|
|
1924
2104
|
|
|
1925
|
-
|
|
1926
|
-
},
|
|
2105
|
+
return res
|
|
1927
2106
|
}
|
|
1928
2107
|
}
|