@tamagui/static 1.0.0-alpha.5 → 1.0.0-alpha.9
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/extractor/createExtractor.js +74 -51
- package/dist/extractor/createExtractor.js.map +2 -2
- package/dist/extractor/extractToClassNames.js +11 -21
- package/dist/extractor/extractToClassNames.js.map +2 -2
- package/dist/extractor/logLines.js +17 -0
- package/dist/extractor/logLines.js.map +7 -0
- package/dist/index.cjs +118 -77
- package/dist/index.cjs.map +3 -3
- package/dist/patchReactNativeWeb.js +18 -3
- package/dist/patchReactNativeWeb.js.map +2 -2
- package/package.json +8 -7
- package/src/extractor/createExtractor.ts +94 -72
- package/src/extractor/extractToClassNames.ts +7 -21
- package/src/extractor/logLines.ts +11 -0
- package/src/patchReactNativeWeb.ts +21 -5
- package/src/types.ts +12 -3
- package/types.d.ts +12 -3
|
@@ -4,8 +4,24 @@ import * as fs from "fs";
|
|
|
4
4
|
import path from "path";
|
|
5
5
|
function patchReactNativeWeb() {
|
|
6
6
|
const rootDir = require.resolve("react-native-web").replace(/\/dist.*/, "");
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const modulePath = path.join(rootDir, "dist", "tamagui-exports.js");
|
|
8
|
+
const cjsPath = path.join(rootDir, "dist", "cjs", "tamagui-exports.js");
|
|
9
|
+
const isEqual = (() => {
|
|
10
|
+
let res = false;
|
|
11
|
+
try {
|
|
12
|
+
res = fs.readFileSync(modulePath, "utf-8") === moduleExports && fs.readFileSync(cjsPath, "utf-8") == cjsExports;
|
|
13
|
+
} catch {
|
|
14
|
+
res = false;
|
|
15
|
+
}
|
|
16
|
+
return res;
|
|
17
|
+
})();
|
|
18
|
+
if (!isEqual) {
|
|
19
|
+
console.log("\u{1F95A} Tamagui patching react-native-web to share atomic styling primitives");
|
|
20
|
+
console.log(" > adding", modulePath);
|
|
21
|
+
console.log(" > adding", cjsPath);
|
|
22
|
+
fs.writeFileSync(modulePath, moduleExports);
|
|
23
|
+
fs.writeFileSync(cjsPath, cjsExports);
|
|
24
|
+
}
|
|
9
25
|
const moduleEntry = path.join(rootDir, "dist", "index.js");
|
|
10
26
|
const moduleEntrySrc = fs.readFileSync(moduleEntry, "utf-8");
|
|
11
27
|
if (!moduleEntrySrc.includes("// tamagui-patch-v4")) {
|
|
@@ -26,7 +42,6 @@ export const TamaguiExports = TExports
|
|
|
26
42
|
exports.TamaguiExports = _interopRequireDefault(require("./tamagui-exports"));
|
|
27
43
|
// tamagui-patch-end
|
|
28
44
|
`);
|
|
29
|
-
console.log(`Tamagui patched react-native-web`);
|
|
30
45
|
}
|
|
31
46
|
}
|
|
32
47
|
__name(patchReactNativeWeb, "patchReactNativeWeb");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/patchReactNativeWeb.ts"],
|
|
4
|
-
"sourcesContent": ["import * as fs from 'fs'\nimport path from 'path'\n\n// were patching react-native-web so we can use some internal methods\n// we do it this way because we need to rely on webpack or bundler config to determine cjs vs esm\n// so we can't just require it all directly\n// would be nice in the future to be able to eject from react-native-web entirely optionally\n\n// keep it sync\nexport function patchReactNativeWeb() {\n const rootDir = require.resolve('react-native-web').replace(/\\/dist.*/, '')\n
|
|
5
|
-
"mappings": ";;AAAA;AACA;AAQO,+BAA+B;AACpC,QAAM,UAAU,AAAgB,oCAAoB,QAAQ,YAAY;
|
|
4
|
+
"sourcesContent": ["import * as fs from 'fs'\nimport path from 'path'\n\n// were patching react-native-web so we can use some internal methods\n// we do it this way because we need to rely on webpack or bundler config to determine cjs vs esm\n// so we can't just require it all directly\n// would be nice in the future to be able to eject from react-native-web entirely optionally\n\n// keep it sync\nexport function patchReactNativeWeb() {\n const rootDir = require.resolve('react-native-web').replace(/\\/dist.*/, '')\n const modulePath = path.join(rootDir, 'dist', 'tamagui-exports.js')\n const cjsPath = path.join(rootDir, 'dist', 'cjs', 'tamagui-exports.js')\n\n const isEqual = (() => {\n let res = false\n try {\n res =\n fs.readFileSync(modulePath, 'utf-8') === moduleExports &&\n fs.readFileSync(cjsPath, 'utf-8') == cjsExports\n } catch {\n res = false\n }\n return res\n })()\n\n if (!isEqual) {\n console.log('\uD83E\uDD5A Tamagui patching react-native-web to share atomic styling primitives')\n console.log(' > adding', modulePath)\n console.log(' > adding', cjsPath)\n fs.writeFileSync(modulePath, moduleExports)\n fs.writeFileSync(cjsPath, cjsExports)\n }\n\n // if entry files not patched, patch them:\n const moduleEntry = path.join(rootDir, 'dist', 'index.js')\n const moduleEntrySrc = fs.readFileSync(moduleEntry, 'utf-8')\n if (!moduleEntrySrc.includes('// tamagui-patch-v4')) {\n fs.writeFileSync(\n moduleEntry,\n `${removePatch(moduleEntrySrc)}\n\n// tamagui-patch-v4\nimport * as TExports from './tamagui-exports'\nexport const TamaguiExports = TExports\n// tamagui-patch-end\n`\n )\n }\n const cjsEntry = path.join(rootDir, 'dist', 'cjs', 'index.js')\n const cjsEntrySrc = fs.readFileSync(cjsEntry, 'utf-8')\n if (!cjsEntrySrc.includes('// tamagui-patch-v4')) {\n fs.writeFileSync(\n cjsEntry,\n `${removePatch(cjsEntrySrc)}\n\n// tamagui-patch-v4\nexports.TamaguiExports = _interopRequireDefault(require(\"./tamagui-exports\"));\n// tamagui-patch-end\n`\n )\n }\n}\n\nfunction removePatch(source: string) {\n return source.replace(/\\/\\/ tamagui-patch([.\\s\\S]*)/g, '')\n}\n\n// view exports/View.ts\nconst forwardedPropsObj = `{\n ...fwdProps.defaultProps,\n ...fwdProps.accessibilityProps,\n ...fwdProps.clickProps,\n ...fwdProps.focusProps,\n ...fwdProps.keyboardProps,\n ...fwdProps.mouseProps,\n ...fwdProps.touchProps,\n ...fwdProps.styleProps,\n href: true,\n lang: true,\n onScroll: true,\n onWheel: true,\n pointerEvents: true\n}\n`\n\nconst moduleExports = `\nexport { atomic } from './exports/StyleSheet/compile'\nexport { default as createCompileableStyle } from './exports/StyleSheet/createCompileableStyle'\nexport { default as createReactDOMStyle } from './exports/StyleSheet/createReactDOMStyle'\nexport { default as i18Style } from './exports/StyleSheet/i18nStyle'\nexport { default as createDOMProps } from './modules/createDOMProps'\nexport { default as AccessibilityUtil } from './modules/AccessibilityUtil'\nexport { default as createElement } from './exports/createElement'\nexport { default as css } from './exports/StyleSheet/css'\nexport { default as TextAncestorContext } from './exports/Text/TextAncestorContext'\nexport { default as pick } from './modules/pick'\nexport { default as useElementLayout } from './modules/useElementLayout'\nexport { default as useMergeRefs } from './modules/useMergeRefs'\nexport { default as usePlatformMethods } from './modules/usePlatformMethods'\nexport { default as useResponderEvents } from './modules/useResponderEvents'\nimport * as fwdProps from './modules/forwardedProps'\nexport const forwardedProps = ${forwardedPropsObj}\n`\n\nconst cjsExports = `\nexports.atomic = require('./exports/StyleSheet/compile').atomic\nexports.createCompileableStyle = require('./exports/StyleSheet/createCompileableStyle')\nexports.createReactDOMStyle = require('./exports/StyleSheet/createReactDOMStyle')\nexports.i18Style = require('./exports/StyleSheet/i18nStyle')\nexports.createDOMProps = require('./modules/createDOMProps')\nexports.AccessibilityUtil = require('./modules/AccessibilityUtil')\nexports.createElement = require('./exports/createElement')\nexports.css = require('./exports/StyleSheet/css')\nexports.TextAncestorContext = require('./exports/Text/TextAncestorContext')\nexports.pick = require('./modules/pick')\nexports.useElementLayout = require('./modules/useElementLayout')\nexports.useMergeRefs = require('./modules/useMergeRefs')\nexports.usePlatformMethods = require('./modules/usePlatformMethods')\nexports.useResponderEvents = require('./modules/useResponderEvents')\nconst fwdProps = require('./modules/forwardedProps')\nexports.forwardedProps = ${forwardedPropsObj}\n`\n"],
|
|
5
|
+
"mappings": ";;AAAA;AACA;AAQO,+BAA+B;AACpC,QAAM,UAAU,AAAgB,oCAAoB,QAAQ,YAAY;AACxE,QAAM,aAAa,KAAK,KAAK,SAAS,QAAQ;AAC9C,QAAM,UAAU,KAAK,KAAK,SAAS,QAAQ,OAAO;AAElD,QAAM,UAAW,OAAM;AACrB,QAAI,MAAM;AACV,QAAI;AACF,YACE,GAAG,aAAa,YAAY,aAAa,iBACzC,GAAG,aAAa,SAAS,YAAY;AAAA,YACvC;AACA,YAAM;AAAA;AAER,WAAO;AAAA;AAGT,MAAI,CAAC,SAAS;AACZ,YAAQ,IAAI;AACZ,YAAQ,IAAI,eAAe;AAC3B,YAAQ,IAAI,eAAe;AAC3B,OAAG,cAAc,YAAY;AAC7B,OAAG,cAAc,SAAS;AAAA;AAI5B,QAAM,cAAc,KAAK,KAAK,SAAS,QAAQ;AAC/C,QAAM,iBAAiB,GAAG,aAAa,aAAa;AACpD,MAAI,CAAC,eAAe,SAAS,wBAAwB;AACnD,OAAG,cACD,aACA,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AASnB,QAAM,WAAW,KAAK,KAAK,SAAS,QAAQ,OAAO;AACnD,QAAM,cAAc,GAAG,aAAa,UAAU;AAC9C,MAAI,CAAC,YAAY,SAAS,wBAAwB;AAChD,OAAG,cACD,UACA,GAAG,YAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA7CL;AAuDhB,qBAAqB,QAAgB;AACnC,SAAO,OAAO,QAAQ,iCAAiC;AAAA;AADhD;AAKT,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiB1B,MAAM,gBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gCAgBU;AAAA;AAGhC,MAAM,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2BAgBQ;AAAA;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tamagui/static",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.9",
|
|
4
4
|
"source": "src/index.ts",
|
|
5
5
|
"main": "dist/index.cjs",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"@types/webpack": "^4.41.26",
|
|
36
36
|
"babel-loader": "^8.2.2",
|
|
37
37
|
"css-loader": "^5.2.4",
|
|
38
|
+
"esbuild-loader": "^2.16.0",
|
|
38
39
|
"jest": "^27.3.1",
|
|
39
40
|
"loader-utils": "^2.0.0",
|
|
40
41
|
"react": "*",
|
|
@@ -52,11 +53,11 @@
|
|
|
52
53
|
"@babel/traverse": "^7.15.4",
|
|
53
54
|
"@dish/babel-preset": "^0.0.6",
|
|
54
55
|
"@expo/match-media": "^0.1.0",
|
|
55
|
-
"@tamagui/build": "^1.0.0-alpha.
|
|
56
|
-
"@tamagui/core": "^1.0.0-alpha.
|
|
57
|
-
"@tamagui/core-node": "^1.0.0-alpha.
|
|
56
|
+
"@tamagui/build": "^1.0.0-alpha.8",
|
|
57
|
+
"@tamagui/core": "^1.0.0-alpha.9",
|
|
58
|
+
"@tamagui/core-node": "^1.0.0-alpha.8",
|
|
58
59
|
"@tamagui/fake-react-native": "^1.0.0-alpha.2",
|
|
59
|
-
"@tamagui/helpers": "^1.0.0-alpha.
|
|
60
|
+
"@tamagui/helpers": "^1.0.0-alpha.8",
|
|
60
61
|
"babel-literal-to-ast": "^2.1.0",
|
|
61
62
|
"esbuild": "^0.13.12",
|
|
62
63
|
"esbuild-register": "^3.1.2",
|
|
@@ -64,10 +65,10 @@
|
|
|
64
65
|
"fs-extra": "^9.0.0",
|
|
65
66
|
"invariant": "^2.2.4",
|
|
66
67
|
"lodash": "^4.17.20",
|
|
67
|
-
"tamagui": "^1.0.0-alpha.
|
|
68
|
+
"tamagui": "^1.0.0-alpha.9"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
71
|
"react-native-web": "*"
|
|
71
72
|
},
|
|
72
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "48ab0be0ca0b8d7e9a1470ee18d46348bc316cdd"
|
|
73
74
|
}
|
|
@@ -13,6 +13,7 @@ import { findTopmostFunction } from './findTopmostFunction'
|
|
|
13
13
|
import { getStaticBindingsForScope } from './getStaticBindingsForScope'
|
|
14
14
|
import { literalToAst } from './literalToAst'
|
|
15
15
|
import { loadTamagui } from './loadTamagui'
|
|
16
|
+
import { logLines } from './logLines'
|
|
16
17
|
import { normalizeTernaries } from './normalizeTernaries'
|
|
17
18
|
import { removeUnusedHooks } from './removeUnusedHooks'
|
|
18
19
|
|
|
@@ -51,9 +52,10 @@ export function createExtractor() {
|
|
|
51
52
|
})
|
|
52
53
|
|
|
53
54
|
let loadedTamaguiConfig: TamaguiInternalConfig
|
|
55
|
+
let hasLogged = false
|
|
54
56
|
|
|
55
57
|
return {
|
|
56
|
-
|
|
58
|
+
getTamagui() {
|
|
57
59
|
return loadedTamaguiConfig
|
|
58
60
|
},
|
|
59
61
|
parse: (
|
|
@@ -66,7 +68,9 @@ export function createExtractor() {
|
|
|
66
68
|
sourcePath = '',
|
|
67
69
|
onExtractTag,
|
|
68
70
|
getFlattenedNode,
|
|
69
|
-
|
|
71
|
+
disableExtraction,
|
|
72
|
+
disableExtractInlineMedia,
|
|
73
|
+
disableDebugAttr,
|
|
70
74
|
...props
|
|
71
75
|
}: ExtractorParseProps
|
|
72
76
|
) => {
|
|
@@ -87,27 +91,25 @@ export function createExtractor() {
|
|
|
87
91
|
loadedTamaguiConfig = tamaguiConfig
|
|
88
92
|
|
|
89
93
|
const defaultTheme = tamaguiConfig.themes[Object.keys(tamaguiConfig.themes)[0]]
|
|
90
|
-
|
|
91
|
-
// TODO this can be passed in / set based on if source changed
|
|
92
|
-
// const shouldReCheckTheme = false //Date.now() - hasParsedFileLast > 600
|
|
93
|
-
// hasParsedFileLast = Date.now()
|
|
94
|
-
|
|
95
|
-
let doesUseValidImport = false
|
|
96
94
|
const body = fileOrPath.type === 'Program' ? fileOrPath.get('body') : fileOrPath.program.body
|
|
97
95
|
|
|
98
96
|
/**
|
|
99
97
|
* Step 1: Determine if importing any statically extractable components
|
|
100
98
|
*/
|
|
101
|
-
const isInternalImport = (importStr: string) =>
|
|
102
|
-
isInsideTamagui(sourcePath) && importStr[0] === '.'
|
|
99
|
+
const isInternalImport = (importStr: string) => {
|
|
100
|
+
return isInsideTamagui(sourcePath) && importStr[0] === '.'
|
|
101
|
+
}
|
|
103
102
|
|
|
104
103
|
const validComponents: { [key: string]: any } = Object.keys(components)
|
|
105
|
-
|
|
104
|
+
// check if uppercase to avoid hitting media query proxy before init
|
|
105
|
+
.filter((key) => key[0].toUpperCase() === key[0] && !!components[key]?.staticConfig)
|
|
106
106
|
.reduce((obj, name) => {
|
|
107
107
|
obj[name] = components[name]
|
|
108
108
|
return obj
|
|
109
109
|
}, {})
|
|
110
110
|
|
|
111
|
+
let doesUseValidImport = false
|
|
112
|
+
|
|
111
113
|
for (const bodyPath of body) {
|
|
112
114
|
if (bodyPath.type !== 'ImportDeclaration') continue
|
|
113
115
|
const node = ('node' in bodyPath ? bodyPath.node : bodyPath) as any
|
|
@@ -148,6 +150,12 @@ export function createExtractor() {
|
|
|
148
150
|
*/
|
|
149
151
|
let programPath: NodePath<t.Program>
|
|
150
152
|
|
|
153
|
+
const res = {
|
|
154
|
+
flattened: 0,
|
|
155
|
+
optimized: 0,
|
|
156
|
+
modified: 0,
|
|
157
|
+
}
|
|
158
|
+
|
|
151
159
|
callTraverse({
|
|
152
160
|
Program: {
|
|
153
161
|
enter(path) {
|
|
@@ -186,8 +194,41 @@ export function createExtractor() {
|
|
|
186
194
|
return
|
|
187
195
|
}
|
|
188
196
|
|
|
189
|
-
const { staticConfig } = component
|
|
190
197
|
const originalNodeName = node.name.name
|
|
198
|
+
|
|
199
|
+
if (shouldPrintDebug) {
|
|
200
|
+
console.log(`\n<${originalNodeName} />`)
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const filePath = sourcePath.replace(process.cwd(), '.')
|
|
204
|
+
const lineNumbers = node.loc
|
|
205
|
+
? node.loc.start.line +
|
|
206
|
+
(node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
|
|
207
|
+
: ''
|
|
208
|
+
|
|
209
|
+
// add data-is
|
|
210
|
+
if (shouldAddDebugProp && !disableDebugAttr) {
|
|
211
|
+
const preName = componentName ? `${componentName}:` : ''
|
|
212
|
+
res.modified++
|
|
213
|
+
node.attributes.unshift(
|
|
214
|
+
t.jsxAttribute(
|
|
215
|
+
t.jsxIdentifier('data-is'),
|
|
216
|
+
t.stringLiteral(
|
|
217
|
+
` ${preName}${node.name.name} ${filePath.replace('./', '')}:${lineNumbers} `
|
|
218
|
+
)
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (disableExtraction) {
|
|
224
|
+
if (!hasLogged) {
|
|
225
|
+
console.log('🥚 Tamagui disableExtraction set: no CSS or optimizations will be run')
|
|
226
|
+
hasLogged = true
|
|
227
|
+
}
|
|
228
|
+
return
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const { staticConfig } = component
|
|
191
232
|
const isTextView = staticConfig.isText || false
|
|
192
233
|
const validStyles = staticConfig?.validStyles ?? {}
|
|
193
234
|
|
|
@@ -224,10 +265,6 @@ export function createExtractor() {
|
|
|
224
265
|
return res
|
|
225
266
|
}
|
|
226
267
|
|
|
227
|
-
if (shouldPrintDebug) {
|
|
228
|
-
console.log(`\n<${originalNodeName} />`)
|
|
229
|
-
}
|
|
230
|
-
|
|
231
268
|
// Generate scope object at this level
|
|
232
269
|
const staticNamespace = getStaticBindingsForScope(
|
|
233
270
|
traversePath.scope,
|
|
@@ -542,6 +579,11 @@ export function createExtractor() {
|
|
|
542
579
|
|
|
543
580
|
// shorthand media queries
|
|
544
581
|
if (name[0] === '$' && t.isJSXExpressionContainer(attribute?.value)) {
|
|
582
|
+
// allow disabling this extraction
|
|
583
|
+
if (disableExtractInlineMedia) {
|
|
584
|
+
return attr
|
|
585
|
+
}
|
|
586
|
+
|
|
545
587
|
const shortname = name.slice(1)
|
|
546
588
|
if (mediaQueryConfig[shortname]) {
|
|
547
589
|
const expression = attribute.value.expression
|
|
@@ -593,8 +635,8 @@ export function createExtractor() {
|
|
|
593
635
|
// if value can be evaluated, extract it and filter it out
|
|
594
636
|
const styleValue = attemptEvalSafe(value)
|
|
595
637
|
|
|
596
|
-
//
|
|
597
|
-
//
|
|
638
|
+
// never flatten if a prop isn't a valid static attribute
|
|
639
|
+
// only post prop-mapping
|
|
598
640
|
if (!isStaticAttributeName(name)) {
|
|
599
641
|
let keys = [name]
|
|
600
642
|
if (staticConfig.propMapper) {
|
|
@@ -624,6 +666,8 @@ export function createExtractor() {
|
|
|
624
666
|
return {
|
|
625
667
|
type: 'style',
|
|
626
668
|
value: { [name]: styleValue },
|
|
669
|
+
name,
|
|
670
|
+
attr: path.node,
|
|
627
671
|
}
|
|
628
672
|
}
|
|
629
673
|
|
|
@@ -755,7 +799,7 @@ export function createExtractor() {
|
|
|
755
799
|
|
|
756
800
|
// see if we can filter them
|
|
757
801
|
if (shouldPrintDebug) {
|
|
758
|
-
console.log(' - attrs (before)
|
|
802
|
+
console.log(' - attrs (before):\n', logLines(attrs.map(attrStr).join(', ')))
|
|
759
803
|
}
|
|
760
804
|
|
|
761
805
|
// now update to new values
|
|
@@ -775,12 +819,6 @@ export function createExtractor() {
|
|
|
775
819
|
modifiedComponents.add(parentFn)
|
|
776
820
|
}
|
|
777
821
|
|
|
778
|
-
const filePath = sourcePath.replace(process.cwd(), '.')
|
|
779
|
-
const lineNumbers = node.loc
|
|
780
|
-
? node.loc.start.line +
|
|
781
|
-
(node.loc.start.line !== node.loc.end.line ? `-${node.loc.end.line}` : '')
|
|
782
|
-
: ''
|
|
783
|
-
|
|
784
822
|
// combine ternaries
|
|
785
823
|
let ternaries: Ternary[] = []
|
|
786
824
|
attrs = attrs
|
|
@@ -870,29 +908,27 @@ export function createExtractor() {
|
|
|
870
908
|
if (cur.type === 'style') {
|
|
871
909
|
// TODO need to loop over initial props not just style props
|
|
872
910
|
for (const key in cur.value) {
|
|
873
|
-
const
|
|
874
|
-
!!(
|
|
875
|
-
staticConfig.ensureOverriddenProp?.[key] // || staticConfig.defaultProps?.[key]
|
|
876
|
-
)
|
|
911
|
+
const shouldEnsureOverridden = !!staticConfig.ensureOverriddenProp?.[key]
|
|
877
912
|
const isSetInAttrsAlready = attrs.some(
|
|
878
913
|
(x) =>
|
|
879
914
|
x.type === 'attr' &&
|
|
880
915
|
x.value.type === 'JSXAttribute' &&
|
|
881
916
|
x.value.name.name === key
|
|
882
917
|
)
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
918
|
+
|
|
919
|
+
if (!isSetInAttrsAlready) {
|
|
920
|
+
const isVariant = !!staticConfig.variants?.[cur.name || '']
|
|
921
|
+
if (isVariant || shouldEnsureOverridden) {
|
|
922
|
+
acc.push({
|
|
923
|
+
type: 'attr',
|
|
924
|
+
value:
|
|
925
|
+
cur.attr ||
|
|
926
|
+
t.jsxAttribute(
|
|
927
|
+
t.jsxIdentifier(key),
|
|
928
|
+
t.jsxExpressionContainer(t.nullLiteral())
|
|
929
|
+
),
|
|
930
|
+
})
|
|
931
|
+
}
|
|
896
932
|
}
|
|
897
933
|
}
|
|
898
934
|
}
|
|
@@ -902,7 +938,7 @@ export function createExtractor() {
|
|
|
902
938
|
}
|
|
903
939
|
|
|
904
940
|
if (shouldPrintDebug) {
|
|
905
|
-
console.log(' - attrs (flattened):
|
|
941
|
+
console.log(' - attrs (flattened): \n', logLines(attrs.map(attrStr).join(', ')))
|
|
906
942
|
}
|
|
907
943
|
|
|
908
944
|
// evaluate away purely style props
|
|
@@ -928,7 +964,7 @@ export function createExtractor() {
|
|
|
928
964
|
}, [])
|
|
929
965
|
|
|
930
966
|
if (shouldPrintDebug) {
|
|
931
|
-
console.log(' - attrs (evaluated styles):
|
|
967
|
+
console.log(' - attrs (evaluated styles): \n', logLines(attrs.map(attrStr).join(', ')))
|
|
932
968
|
}
|
|
933
969
|
|
|
934
970
|
// combine styles, leave undefined values
|
|
@@ -946,7 +982,7 @@ export function createExtractor() {
|
|
|
946
982
|
}, [])
|
|
947
983
|
|
|
948
984
|
if (shouldPrintDebug) {
|
|
949
|
-
console.log(' - attrs (combined 🔀):
|
|
985
|
+
console.log(' - attrs (combined 🔀): \n', logLines(attrs.map(attrStr).join(', ')))
|
|
950
986
|
}
|
|
951
987
|
|
|
952
988
|
// post process
|
|
@@ -961,9 +997,10 @@ export function createExtractor() {
|
|
|
961
997
|
const out = postProcessStyles(props, staticConfig, defaultTheme)
|
|
962
998
|
const next = out?.style ?? props
|
|
963
999
|
if (shouldPrintDebug) {
|
|
964
|
-
console.log('
|
|
965
|
-
console.log('
|
|
966
|
-
console.log('
|
|
1000
|
+
console.log(' getStyles props >>\n', logLines(objToStr(props)))
|
|
1001
|
+
console.log(' getStyles next >>\n', logLines(objToStr(next)))
|
|
1002
|
+
console.log(' getStyles style >>\n', logLines(objToStr(out.style)))
|
|
1003
|
+
console.log(' getStyles viewp >>\n', logLines(objToStr(out.viewProps)))
|
|
967
1004
|
}
|
|
968
1005
|
if (staticConfig.validStyles) {
|
|
969
1006
|
for (const key in next) {
|
|
@@ -975,10 +1012,6 @@ export function createExtractor() {
|
|
|
975
1012
|
return next
|
|
976
1013
|
}
|
|
977
1014
|
|
|
978
|
-
if (shouldPrintDebug) {
|
|
979
|
-
console.log(' staticConfig.defaultProps', staticConfig.defaultProps)
|
|
980
|
-
}
|
|
981
|
-
|
|
982
1015
|
// used to ensure we pass the entire prop bundle to getStyles
|
|
983
1016
|
const completeStylesProcessed = getStyles({
|
|
984
1017
|
...staticConfig.defaultProps,
|
|
@@ -1007,9 +1040,9 @@ export function createExtractor() {
|
|
|
1007
1040
|
|
|
1008
1041
|
if (shouldPrintDebug) {
|
|
1009
1042
|
// prettier-ignore
|
|
1010
|
-
console.log('
|
|
1043
|
+
console.log(' completeStaticProps\n', logLines(objToStr(completeStaticProps)))
|
|
1011
1044
|
// prettier-ignore
|
|
1012
|
-
console.log('
|
|
1045
|
+
console.log(' completeStylesProcessed\n', logLines(objToStr(completeStylesProcessed)))
|
|
1013
1046
|
}
|
|
1014
1047
|
|
|
1015
1048
|
for (const attr of attrs) {
|
|
@@ -1048,22 +1081,7 @@ export function createExtractor() {
|
|
|
1048
1081
|
}
|
|
1049
1082
|
|
|
1050
1083
|
if (shouldPrintDebug) {
|
|
1051
|
-
console.log(' - attrs (after)
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
// add data-is
|
|
1055
|
-
if (shouldAddDebugProp) {
|
|
1056
|
-
const preName = componentName ? `${componentName}:` : ''
|
|
1057
|
-
// unshift so spreads/nesting overwrite
|
|
1058
|
-
attrs.unshift({
|
|
1059
|
-
type: 'attr',
|
|
1060
|
-
value: t.jsxAttribute(
|
|
1061
|
-
t.jsxIdentifier('data-is'),
|
|
1062
|
-
t.stringLiteral(
|
|
1063
|
-
` ${preName}${node.name.name} ${filePath.replace('./', '')}:${lineNumbers} `
|
|
1064
|
-
)
|
|
1065
|
-
),
|
|
1066
|
-
})
|
|
1084
|
+
console.log(' - attrs (after):\n', logLines(attrs.map(attrStr).join(', ')))
|
|
1067
1085
|
}
|
|
1068
1086
|
|
|
1069
1087
|
if (shouldFlatten) {
|
|
@@ -1073,7 +1091,7 @@ export function createExtractor() {
|
|
|
1073
1091
|
}
|
|
1074
1092
|
isFlattened = true
|
|
1075
1093
|
node.name.name = flatNode
|
|
1076
|
-
|
|
1094
|
+
res.flattened++
|
|
1077
1095
|
if (closingElement) {
|
|
1078
1096
|
closingElement.name.name = flatNode
|
|
1079
1097
|
}
|
|
@@ -1082,9 +1100,11 @@ export function createExtractor() {
|
|
|
1082
1100
|
if (shouldPrintDebug) {
|
|
1083
1101
|
// prettier-ignore
|
|
1084
1102
|
console.log(' [❊] inline props ', inlinePropCount, shouldDeopt ? ' deopted' : '', hasSpread ? ' spread' : '', '!flatten', staticConfig.neverFlatten)
|
|
1085
|
-
console.log(' - attrs (end)
|
|
1103
|
+
console.log(' - attrs (end):\n', logLines(attrs.map(attrStr).join(', ')))
|
|
1086
1104
|
}
|
|
1087
1105
|
|
|
1106
|
+
res.optimized++
|
|
1107
|
+
|
|
1088
1108
|
onExtractTag({
|
|
1089
1109
|
attrs,
|
|
1090
1110
|
node,
|
|
@@ -1111,6 +1131,8 @@ export function createExtractor() {
|
|
|
1111
1131
|
removeUnusedHooks(comp, shouldPrintDebug)
|
|
1112
1132
|
}
|
|
1113
1133
|
}
|
|
1134
|
+
|
|
1135
|
+
return res
|
|
1114
1136
|
},
|
|
1115
1137
|
}
|
|
1116
1138
|
}
|
|
@@ -18,6 +18,7 @@ import { ensureImportingConcat } from './ensureImportingConcat'
|
|
|
18
18
|
import { isSimpleSpread } from './extractHelpers'
|
|
19
19
|
import { extractMediaStyle } from './extractMediaStyle'
|
|
20
20
|
import { hoistClassNames } from './hoistClassNames'
|
|
21
|
+
import { logLines } from './logLines'
|
|
21
22
|
|
|
22
23
|
export const CONCAT_CLASSNAME_IMPORT = 'concatClassName'
|
|
23
24
|
|
|
@@ -79,17 +80,11 @@ export function extractToClassNames({
|
|
|
79
80
|
const cssMap = new Map<string, { css: string; commentTexts: string[] }>()
|
|
80
81
|
const existingHoists: { [key: string]: t.Identifier } = {}
|
|
81
82
|
|
|
82
|
-
|
|
83
|
-
let optimized = 0
|
|
84
|
-
|
|
85
|
-
extractor.parse(ast, {
|
|
83
|
+
const res = extractor.parse(ast, {
|
|
86
84
|
sourcePath,
|
|
87
85
|
shouldPrintDebug,
|
|
88
86
|
...options,
|
|
89
87
|
getFlattenedNode: ({ tag }) => tag,
|
|
90
|
-
onDidFlatten() {
|
|
91
|
-
flattened++
|
|
92
|
-
},
|
|
93
88
|
onExtractTag: ({
|
|
94
89
|
attrs,
|
|
95
90
|
node,
|
|
@@ -100,8 +95,6 @@ export function extractToClassNames({
|
|
|
100
95
|
lineNumbers,
|
|
101
96
|
programPath,
|
|
102
97
|
}) => {
|
|
103
|
-
optimized++
|
|
104
|
-
|
|
105
98
|
let finalClassNames: ClassNameObject[] = []
|
|
106
99
|
let finalAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
|
|
107
100
|
let finalStyles: StyleObject[] = []
|
|
@@ -144,10 +137,6 @@ export function extractToClassNames({
|
|
|
144
137
|
case 'style':
|
|
145
138
|
const styles = addStyles(attr.value)
|
|
146
139
|
const newClassNames = concatClassName(styles.map((x) => x.identifier).join(' '))
|
|
147
|
-
if (shouldPrintDebug) {
|
|
148
|
-
// console.log(' style', attr.value)
|
|
149
|
-
console.log(' classnames', newClassNames, finalClassNames)
|
|
150
|
-
}
|
|
151
140
|
// prettier-ignore
|
|
152
141
|
const existing = finalClassNames.find((x) => x.type == 'StringLiteral') as t.StringLiteral | null
|
|
153
142
|
if (existing) {
|
|
@@ -157,7 +146,7 @@ export function extractToClassNames({
|
|
|
157
146
|
}
|
|
158
147
|
if (shouldPrintDebug) {
|
|
159
148
|
// prettier-ignore
|
|
160
|
-
console.log(' classnames (after)', finalClassNames.map(x => x['value']).join(' '))
|
|
149
|
+
console.log(' classnames (after)\n', logLines(finalClassNames.map(x => x['value']).join(' ')))
|
|
161
150
|
}
|
|
162
151
|
break
|
|
163
152
|
case 'attr':
|
|
@@ -190,7 +179,7 @@ export function extractToClassNames({
|
|
|
190
179
|
const mediaExtraction = extractMediaStyle(
|
|
191
180
|
attr.value,
|
|
192
181
|
jsxPath,
|
|
193
|
-
extractor.
|
|
182
|
+
extractor.getTamagui(),
|
|
194
183
|
sourcePath,
|
|
195
184
|
lastMediaImportance,
|
|
196
185
|
shouldPrintDebug
|
|
@@ -276,15 +265,12 @@ export function extractToClassNames({
|
|
|
276
265
|
},
|
|
277
266
|
})
|
|
278
267
|
|
|
279
|
-
if (!
|
|
268
|
+
if (!res || !res.modified) {
|
|
280
269
|
return null
|
|
281
270
|
}
|
|
282
271
|
|
|
283
272
|
const styles = Array.from(cssMap.values())
|
|
284
|
-
.map((x) =>
|
|
285
|
-
// remove comments
|
|
286
|
-
return x.css //shouldInternalDedupe ? x.css : `${x.commentTexts.join('\n')}\n${x.css}`
|
|
287
|
-
})
|
|
273
|
+
.map((x) => x.css)
|
|
288
274
|
.join('\n')
|
|
289
275
|
.trim()
|
|
290
276
|
|
|
@@ -325,7 +311,7 @@ export function extractToClassNames({
|
|
|
325
311
|
const memUsed =
|
|
326
312
|
Math.round(((process.memoryUsage().heapUsed - mem.heapUsed) / 1024 / 1204) * 10) / 10
|
|
327
313
|
// prettier-ignore
|
|
328
|
-
console.log(` 🥚 ${basename(sourcePath).padStart(40)} ${`${Date.now() - start}`.padStart(3)}ms ׁ· ${`${optimized}`.padStart(4)} optimized · ${flattened} flattened ${memUsed > 10 ? `used ${memUsed}MB` : ''}`)
|
|
314
|
+
console.log(` 🥚 ${basename(sourcePath).padStart(40)} ${`${Date.now() - start}`.padStart(3)}ms ׁ· ${`${res.optimized}`.padStart(4)} optimized · ${res.flattened} flattened ${memUsed > 10 ? `used ${memUsed}MB` : ''}`)
|
|
329
315
|
}
|
|
330
316
|
|
|
331
317
|
return {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const logLines = (str: string) => {
|
|
2
|
+
let lines: string[] = ['']
|
|
3
|
+
const items = str.split(' ')
|
|
4
|
+
for (const item of items) {
|
|
5
|
+
if (item.length + lines[lines.length - 1].length > 100) {
|
|
6
|
+
lines.push('')
|
|
7
|
+
}
|
|
8
|
+
lines[lines.length - 1] += item + ' '
|
|
9
|
+
}
|
|
10
|
+
return lines.map((line, i) => ' ' + (i == 0 ? '' : ' ') + line.trim()).join('\n')
|
|
11
|
+
}
|
|
@@ -9,10 +9,28 @@ import path from 'path'
|
|
|
9
9
|
// keep it sync
|
|
10
10
|
export function patchReactNativeWeb() {
|
|
11
11
|
const rootDir = require.resolve('react-native-web').replace(/\/dist.*/, '')
|
|
12
|
+
const modulePath = path.join(rootDir, 'dist', 'tamagui-exports.js')
|
|
13
|
+
const cjsPath = path.join(rootDir, 'dist', 'cjs', 'tamagui-exports.js')
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
15
|
+
const isEqual = (() => {
|
|
16
|
+
let res = false
|
|
17
|
+
try {
|
|
18
|
+
res =
|
|
19
|
+
fs.readFileSync(modulePath, 'utf-8') === moduleExports &&
|
|
20
|
+
fs.readFileSync(cjsPath, 'utf-8') == cjsExports
|
|
21
|
+
} catch {
|
|
22
|
+
res = false
|
|
23
|
+
}
|
|
24
|
+
return res
|
|
25
|
+
})()
|
|
26
|
+
|
|
27
|
+
if (!isEqual) {
|
|
28
|
+
console.log('🥚 Tamagui patching react-native-web to share atomic styling primitives')
|
|
29
|
+
console.log(' > adding', modulePath)
|
|
30
|
+
console.log(' > adding', cjsPath)
|
|
31
|
+
fs.writeFileSync(modulePath, moduleExports)
|
|
32
|
+
fs.writeFileSync(cjsPath, cjsExports)
|
|
33
|
+
}
|
|
16
34
|
|
|
17
35
|
// if entry files not patched, patch them:
|
|
18
36
|
const moduleEntry = path.join(rootDir, 'dist', 'index.js')
|
|
@@ -41,8 +59,6 @@ exports.TamaguiExports = _interopRequireDefault(require("./tamagui-exports"));
|
|
|
41
59
|
// tamagui-patch-end
|
|
42
60
|
`
|
|
43
61
|
)
|
|
44
|
-
|
|
45
|
-
console.log(`Tamagui patched react-native-web`)
|
|
46
62
|
}
|
|
47
63
|
}
|
|
48
64
|
|
package/src/types.ts
CHANGED
|
@@ -15,6 +15,8 @@ export interface TamaguiOptions {
|
|
|
15
15
|
evaluateVars?: boolean
|
|
16
16
|
importsWhitelist?: string[]
|
|
17
17
|
disableExtraction?: boolean
|
|
18
|
+
disableDebugAttr?: boolean
|
|
19
|
+
disableExtractInlineMedia?: boolean
|
|
18
20
|
exclude?: RegExp
|
|
19
21
|
logTimings?: boolean
|
|
20
22
|
|
|
@@ -30,9 +32,17 @@ export type ExtractedAttrAttr = {
|
|
|
30
32
|
value: t.JSXAttribute | t.JSXSpreadAttribute
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
export type ExtractedAttrStyle = {
|
|
35
|
+
export type ExtractedAttrStyle = {
|
|
36
|
+
type: 'style'
|
|
37
|
+
value: Object
|
|
38
|
+
attr?: t.JSXAttribute | t.JSXSpreadAttribute
|
|
39
|
+
name?: string
|
|
40
|
+
}
|
|
34
41
|
|
|
35
|
-
export type ExtractedAttr =
|
|
42
|
+
export type ExtractedAttr =
|
|
43
|
+
| ExtractedAttrAttr
|
|
44
|
+
| { type: 'ternary'; value: Ternary }
|
|
45
|
+
| ExtractedAttrStyle
|
|
36
46
|
|
|
37
47
|
export type ExtractTagProps = {
|
|
38
48
|
attrs: ExtractedAttr[]
|
|
@@ -51,7 +61,6 @@ export type ExtractorParseProps = TamaguiOptions & {
|
|
|
51
61
|
shouldPrintDebug?: boolean
|
|
52
62
|
onExtractTag: (props: ExtractTagProps) => void
|
|
53
63
|
getFlattenedNode: (props: { isTextView: boolean; tag: string }) => string
|
|
54
|
-
onDidFlatten?: () => void
|
|
55
64
|
}
|
|
56
65
|
|
|
57
66
|
export interface Ternary {
|