@tamagui/static 1.100.6 → 1.101.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/extractor/extractToNative.js +319 -0
- package/dist/cjs/extractor/extractToNative.js.map +6 -0
- package/dist/cjs/extractor/extractToNative.native.js +353 -0
- package/dist/cjs/extractor/extractToNative.native.js.map +6 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/index.native.js +2 -0
- package/dist/cjs/index.native.js.map +1 -1
- package/dist/esm/extractor/extractToNative.js +309 -0
- package/dist/esm/extractor/extractToNative.js.map +6 -0
- package/dist/esm/extractor/extractToNative.mjs +232 -0
- package/dist/esm/extractor/extractToNative.native.js +329 -0
- package/dist/esm/extractor/extractToNative.native.js.map +6 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/index.native.js +1 -0
- package/dist/esm/index.native.js.map +1 -1
- package/package.json +15 -14
- package/src/extractor/extractToNative.ts +504 -0
- package/src/index.ts +1 -0
- package/types/extractor/extractToNative.d.ts +13 -0
- package/types/extractor/extractToNative.d.ts.map +1 -0
- package/types/index.d.ts +1 -0
- package/types/index.d.ts.map +1 -1
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { basename } from 'node:path'
|
|
2
|
+
|
|
3
|
+
import { type BabelFileResult, transformFromAstSync } from '@babel/core'
|
|
4
|
+
import generator from '@babel/generator'
|
|
5
|
+
import { declare } from '@babel/helper-plugin-utils'
|
|
6
|
+
import { parse } from '@babel/parser'
|
|
7
|
+
import template from '@babel/template'
|
|
8
|
+
import * as t from '@babel/types'
|
|
9
|
+
import type { TamaguiOptions } from '@tamagui/static'
|
|
10
|
+
import {
|
|
11
|
+
createExtractor,
|
|
12
|
+
createLogger,
|
|
13
|
+
getPragmaOptions,
|
|
14
|
+
isSimpleSpread,
|
|
15
|
+
literalToAst,
|
|
16
|
+
loadTamaguiBuildConfigSync,
|
|
17
|
+
} from '@tamagui/static'
|
|
18
|
+
|
|
19
|
+
const importNativeView = template(`
|
|
20
|
+
const __ReactNativeView = require('react-native').View;
|
|
21
|
+
const __ReactNativeText = require('react-native').Text;
|
|
22
|
+
`)
|
|
23
|
+
|
|
24
|
+
const importStyleSheet = template(`
|
|
25
|
+
const __ReactNativeStyleSheet = require('react-native').StyleSheet;
|
|
26
|
+
`)
|
|
27
|
+
|
|
28
|
+
const importWithStyle = template(`
|
|
29
|
+
const __withStableStyle = require('@tamagui/core')._withStableStyle;
|
|
30
|
+
`)
|
|
31
|
+
|
|
32
|
+
const extractor = createExtractor({ platform: 'native' })
|
|
33
|
+
|
|
34
|
+
let tamaguiBuildOptionsLoaded: TamaguiOptions | null
|
|
35
|
+
|
|
36
|
+
export function extractToNative(
|
|
37
|
+
sourceFileName: string,
|
|
38
|
+
sourceCode: string,
|
|
39
|
+
options: TamaguiOptions
|
|
40
|
+
): BabelFileResult {
|
|
41
|
+
const ast = parse(sourceCode, {
|
|
42
|
+
sourceType: 'module',
|
|
43
|
+
plugins: ['jsx', 'typescript'],
|
|
44
|
+
})
|
|
45
|
+
|
|
46
|
+
const babelPlugin = getBabelPlugin()
|
|
47
|
+
|
|
48
|
+
const out = transformFromAstSync(ast, sourceCode, {
|
|
49
|
+
plugins: [[babelPlugin, options]],
|
|
50
|
+
configFile: false,
|
|
51
|
+
sourceFileName,
|
|
52
|
+
filename: sourceFileName,
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
if (!out) {
|
|
56
|
+
throw new Error(`No output returned`)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return out
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function getBabelPlugin() {
|
|
63
|
+
return declare((api, options: TamaguiOptions) => {
|
|
64
|
+
api.assertVersion(7)
|
|
65
|
+
return getBabelParseDefinition(options)
|
|
66
|
+
})
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function getBabelParseDefinition(options: TamaguiOptions) {
|
|
70
|
+
return {
|
|
71
|
+
name: 'tamagui',
|
|
72
|
+
|
|
73
|
+
visitor: {
|
|
74
|
+
Program: {
|
|
75
|
+
enter(this: any, root) {
|
|
76
|
+
let sourcePath = this.file.opts.filename
|
|
77
|
+
if (sourcePath?.includes('node_modules')) {
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
// by default only pick up .jsx / .tsx
|
|
81
|
+
if (!sourcePath?.endsWith('.jsx') && !sourcePath?.endsWith('.tsx')) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// this filename comes back incorrect in react-native, it adds /ios/ for some reason
|
|
86
|
+
// adding a fix here, but it's a bit tentative...
|
|
87
|
+
if (process.env.SOURCE_ROOT?.endsWith('ios')) {
|
|
88
|
+
sourcePath = sourcePath.replace('/ios', '')
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
let hasImportedView = false
|
|
92
|
+
let hasImportedViewWrapper = false
|
|
93
|
+
const sheetStyles = {}
|
|
94
|
+
const sheetIdentifier = root.scope.generateUidIdentifier('sheet')
|
|
95
|
+
|
|
96
|
+
// babel doesnt append the `//` so we need to
|
|
97
|
+
const firstCommentContents = // join because you can join together multiple pragmas
|
|
98
|
+
root.node.body[0]?.leadingComments
|
|
99
|
+
?.map((comment) => comment?.value || ' ')
|
|
100
|
+
.join(' ') ?? ''
|
|
101
|
+
const firstComment = firstCommentContents ? `//${firstCommentContents}` : ''
|
|
102
|
+
|
|
103
|
+
const { shouldPrintDebug, shouldDisable } = getPragmaOptions({
|
|
104
|
+
source: firstComment,
|
|
105
|
+
path: sourcePath,
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
if (shouldDisable) {
|
|
109
|
+
return
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (!options.config && !options.components) {
|
|
113
|
+
// if no config/components given try and load from the tamagui.build.ts file
|
|
114
|
+
tamaguiBuildOptionsLoaded ||= loadTamaguiBuildConfigSync({})
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const finalOptions = {
|
|
118
|
+
// @ts-ignore just in case they leave it out
|
|
119
|
+
platform: 'native',
|
|
120
|
+
...tamaguiBuildOptionsLoaded,
|
|
121
|
+
...options,
|
|
122
|
+
} satisfies TamaguiOptions
|
|
123
|
+
|
|
124
|
+
const printLog = createLogger(sourcePath, finalOptions)
|
|
125
|
+
|
|
126
|
+
function addSheetStyle(style: any, node: t.JSXOpeningElement) {
|
|
127
|
+
const styleIndex = `${Object.keys(sheetStyles).length}`
|
|
128
|
+
let key = `${styleIndex}`
|
|
129
|
+
if (process.env.NODE_ENV === 'development') {
|
|
130
|
+
const lineNumbers = node.loc
|
|
131
|
+
? node.loc.start.line +
|
|
132
|
+
(node.loc.start.line !== node.loc.end.line
|
|
133
|
+
? `-${node.loc.end.line}`
|
|
134
|
+
: '')
|
|
135
|
+
: ''
|
|
136
|
+
key += `:${basename(sourcePath)}:${lineNumbers}`
|
|
137
|
+
}
|
|
138
|
+
sheetStyles[key] = style
|
|
139
|
+
return readStyleExpr(key)
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function readStyleExpr(key: string) {
|
|
143
|
+
return template(`SHEET['KEY']`)({
|
|
144
|
+
SHEET: sheetIdentifier.name,
|
|
145
|
+
KEY: key,
|
|
146
|
+
})['expression'] as t.MemberExpression
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
let res
|
|
150
|
+
|
|
151
|
+
try {
|
|
152
|
+
res = extractor.parseSync(root, {
|
|
153
|
+
importsWhitelist: ['constants.js', 'colors.js'],
|
|
154
|
+
extractStyledDefinitions: options.forceExtractStyleDefinitions,
|
|
155
|
+
excludeProps: new Set([
|
|
156
|
+
'className',
|
|
157
|
+
'userSelect',
|
|
158
|
+
'whiteSpace',
|
|
159
|
+
'textOverflow',
|
|
160
|
+
'cursor',
|
|
161
|
+
'contain',
|
|
162
|
+
]),
|
|
163
|
+
shouldPrintDebug,
|
|
164
|
+
...finalOptions,
|
|
165
|
+
// disable this extraction for now at least, need to figure out merging theme vs non-theme
|
|
166
|
+
// because theme need to stay in render(), whereas non-theme can be extracted
|
|
167
|
+
// for now just turn it off entirely at a small perf loss
|
|
168
|
+
disableExtractInlineMedia: true,
|
|
169
|
+
// disable extracting variables as no native concept of them (only theme values)
|
|
170
|
+
disableExtractVariables: options.experimentalFlattenThemesOnNative
|
|
171
|
+
? false
|
|
172
|
+
: 'theme',
|
|
173
|
+
sourcePath,
|
|
174
|
+
|
|
175
|
+
// disabling flattening for now
|
|
176
|
+
// it's flattening a plain <Paragraph>hello</Paragraph> which breaks things because themes
|
|
177
|
+
// thinking it's not really worth the effort to do much compilation on native
|
|
178
|
+
// for now just disable flatten as it can only run in narrow places on native
|
|
179
|
+
// disableFlattening: 'styled',
|
|
180
|
+
|
|
181
|
+
getFlattenedNode({ isTextView }) {
|
|
182
|
+
if (!hasImportedView) {
|
|
183
|
+
hasImportedView = true
|
|
184
|
+
root.unshiftContainer('body', importNativeView())
|
|
185
|
+
}
|
|
186
|
+
return isTextView ? '__ReactNativeText' : '__ReactNativeView'
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
onExtractTag(props) {
|
|
190
|
+
const { isFlattened } = props
|
|
191
|
+
|
|
192
|
+
if (!isFlattened) {
|
|
193
|
+
// we aren't optimizing at all if not flattened anymore
|
|
194
|
+
return
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
assertValidTag(props.node)
|
|
198
|
+
const stylesExpr = t.arrayExpression([])
|
|
199
|
+
const hocStylesExpr = t.arrayExpression([])
|
|
200
|
+
const expressions: t.Expression[] = []
|
|
201
|
+
const finalAttrs: (t.JSXAttribute | t.JSXSpreadAttribute)[] = []
|
|
202
|
+
const themeKeysUsed = new Set<string>()
|
|
203
|
+
|
|
204
|
+
function getStyleExpression(style: Object | null) {
|
|
205
|
+
if (!style) return
|
|
206
|
+
|
|
207
|
+
// split theme properties and leave them as props since RN has no concept of theme
|
|
208
|
+
const { plain, themed } = splitThemeStyles(style)
|
|
209
|
+
|
|
210
|
+
// TODO: themed is not a good name, because it's not just theme it also includes tokens
|
|
211
|
+
let themeExpr: t.ObjectExpression | null = null
|
|
212
|
+
if (themed && options.experimentalFlattenThemesOnNative) {
|
|
213
|
+
for (const key in themed) {
|
|
214
|
+
themeKeysUsed.add(themed[key].split('$')[1])
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// make a sub-array
|
|
218
|
+
themeExpr = getThemedStyleExpression(themed)
|
|
219
|
+
}
|
|
220
|
+
const ident = addSheetStyle(plain, props.node)
|
|
221
|
+
if (themeExpr) {
|
|
222
|
+
addStyleExpression(ident)
|
|
223
|
+
addStyleExpression(ident, true)
|
|
224
|
+
return themeExpr
|
|
225
|
+
}
|
|
226
|
+
// since we only do flattened disabling this path
|
|
227
|
+
return ident
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function addStyleExpression(expr: any, HOC = false) {
|
|
231
|
+
if (Array.isArray(expr)) {
|
|
232
|
+
;(HOC ? hocStylesExpr : stylesExpr).elements.push(...expr)
|
|
233
|
+
} else {
|
|
234
|
+
;(HOC ? hocStylesExpr : stylesExpr).elements.push(expr)
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function getThemedStyleExpression(styles: Object) {
|
|
239
|
+
const themedStylesAst = literalToAst(styles) as t.ObjectExpression
|
|
240
|
+
themedStylesAst.properties.forEach((_) => {
|
|
241
|
+
const prop = _ as t.ObjectProperty
|
|
242
|
+
if (prop.value.type === 'StringLiteral') {
|
|
243
|
+
prop.value = t.memberExpression(
|
|
244
|
+
t.identifier('theme'),
|
|
245
|
+
t.identifier(prop.value.value.slice(1) + '.get()')
|
|
246
|
+
)
|
|
247
|
+
}
|
|
248
|
+
})
|
|
249
|
+
return themedStylesAst
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
let hasDynamicStyle = false
|
|
253
|
+
|
|
254
|
+
for (const attr of props.attrs) {
|
|
255
|
+
switch (attr.type) {
|
|
256
|
+
case 'style': {
|
|
257
|
+
let styleExpr = getStyleExpression(attr.value)
|
|
258
|
+
addStyleExpression(styleExpr)
|
|
259
|
+
if (options.experimentalFlattenThemesOnNative) {
|
|
260
|
+
addStyleExpression(styleExpr, true)
|
|
261
|
+
}
|
|
262
|
+
break
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
case 'ternary': {
|
|
266
|
+
const { consequent, alternate } = attr.value
|
|
267
|
+
const consExpr = getStyleExpression(consequent)
|
|
268
|
+
const altExpr = getStyleExpression(alternate)
|
|
269
|
+
|
|
270
|
+
if (options.experimentalFlattenThemesOnNative) {
|
|
271
|
+
expressions.push(attr.value.test)
|
|
272
|
+
addStyleExpression(
|
|
273
|
+
t.conditionalExpression(
|
|
274
|
+
t.identifier(`_expressions[${expressions.length - 1}]`),
|
|
275
|
+
consExpr || t.nullLiteral(),
|
|
276
|
+
altExpr || t.nullLiteral()
|
|
277
|
+
),
|
|
278
|
+
true
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
const styleExpr = t.conditionalExpression(
|
|
283
|
+
attr.value.test,
|
|
284
|
+
consExpr || t.nullLiteral(),
|
|
285
|
+
altExpr || t.nullLiteral()
|
|
286
|
+
)
|
|
287
|
+
addStyleExpression(
|
|
288
|
+
styleExpr
|
|
289
|
+
// TODO: what is this for ?
|
|
290
|
+
// isFlattened ? simpleHash(JSON.stringify({ consequent, alternate })) : undefined
|
|
291
|
+
)
|
|
292
|
+
break
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
case 'dynamic-style': {
|
|
296
|
+
hasDynamicStyle = true
|
|
297
|
+
expressions.push(attr.value as t.Expression)
|
|
298
|
+
if (options.experimentalFlattenDynamicValues) {
|
|
299
|
+
addStyleExpression(
|
|
300
|
+
t.objectExpression([
|
|
301
|
+
t.objectProperty(
|
|
302
|
+
t.identifier(attr.name as string),
|
|
303
|
+
t.identifier(`_expressions[${expressions.length - 1}]`)
|
|
304
|
+
),
|
|
305
|
+
]),
|
|
306
|
+
true
|
|
307
|
+
)
|
|
308
|
+
} else {
|
|
309
|
+
addStyleExpression(
|
|
310
|
+
t.objectExpression([
|
|
311
|
+
t.objectProperty(
|
|
312
|
+
t.identifier(attr.name as string),
|
|
313
|
+
attr.value as t.Expression
|
|
314
|
+
),
|
|
315
|
+
])
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
break
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
case 'attr': {
|
|
322
|
+
if (t.isJSXSpreadAttribute(attr.value)) {
|
|
323
|
+
if (isSimpleSpread(attr.value)) {
|
|
324
|
+
stylesExpr.elements.push(
|
|
325
|
+
t.memberExpression(attr.value.argument, t.identifier('style'))
|
|
326
|
+
)
|
|
327
|
+
if (options.experimentalFlattenThemesOnNative) {
|
|
328
|
+
hocStylesExpr.elements.push(
|
|
329
|
+
t.memberExpression(
|
|
330
|
+
attr.value.argument,
|
|
331
|
+
t.identifier('style')
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
finalAttrs.push(attr.value)
|
|
338
|
+
break
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
props.node.attributes = finalAttrs
|
|
344
|
+
|
|
345
|
+
if (props.isFlattened) {
|
|
346
|
+
if (
|
|
347
|
+
options.experimentalFlattenThemesOnNative &&
|
|
348
|
+
(themeKeysUsed.size ||
|
|
349
|
+
hocStylesExpr.elements.length > 1 ||
|
|
350
|
+
hasDynamicStyle)
|
|
351
|
+
) {
|
|
352
|
+
if (!hasImportedViewWrapper) {
|
|
353
|
+
root.unshiftContainer('body', importWithStyle())
|
|
354
|
+
hasImportedViewWrapper = true
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
const name = props.node.name['name']
|
|
358
|
+
const WrapperIdentifier = root.scope.generateUidIdentifier(
|
|
359
|
+
name + 'Wrapper'
|
|
360
|
+
)
|
|
361
|
+
|
|
362
|
+
root.pushContainer(
|
|
363
|
+
'body',
|
|
364
|
+
t.variableDeclaration('const', [
|
|
365
|
+
t.variableDeclarator(
|
|
366
|
+
WrapperIdentifier,
|
|
367
|
+
t.callExpression(t.identifier('__withStableStyle'), [
|
|
368
|
+
t.identifier(name),
|
|
369
|
+
t.arrowFunctionExpression(
|
|
370
|
+
[t.identifier('theme'), t.identifier('_expressions')],
|
|
371
|
+
t.blockStatement([
|
|
372
|
+
t.returnStatement(
|
|
373
|
+
t.callExpression(
|
|
374
|
+
t.memberExpression(
|
|
375
|
+
t.identifier('React'),
|
|
376
|
+
t.identifier('useMemo')
|
|
377
|
+
),
|
|
378
|
+
[
|
|
379
|
+
t.arrowFunctionExpression(
|
|
380
|
+
[],
|
|
381
|
+
t.blockStatement([
|
|
382
|
+
t.returnStatement(
|
|
383
|
+
t.arrayExpression([...hocStylesExpr.elements])
|
|
384
|
+
),
|
|
385
|
+
])
|
|
386
|
+
),
|
|
387
|
+
t.arrayExpression([
|
|
388
|
+
t.spreadElement(t.identifier('_expressions')),
|
|
389
|
+
]),
|
|
390
|
+
]
|
|
391
|
+
)
|
|
392
|
+
),
|
|
393
|
+
])
|
|
394
|
+
),
|
|
395
|
+
])
|
|
396
|
+
),
|
|
397
|
+
])
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
// @ts-ignore
|
|
401
|
+
props.node.name = WrapperIdentifier
|
|
402
|
+
if (props.jsxPath.node.closingElement) {
|
|
403
|
+
// @ts-ignore
|
|
404
|
+
props.jsxPath.node.closingElement.name = WrapperIdentifier
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (expressions.length) {
|
|
408
|
+
props.node.attributes.push(
|
|
409
|
+
t.jsxAttribute(
|
|
410
|
+
t.jsxIdentifier('expressions'),
|
|
411
|
+
t.jsxExpressionContainer(t.arrayExpression(expressions))
|
|
412
|
+
)
|
|
413
|
+
)
|
|
414
|
+
}
|
|
415
|
+
} else {
|
|
416
|
+
props.node.attributes.push(
|
|
417
|
+
t.jsxAttribute(
|
|
418
|
+
t.jsxIdentifier('style'),
|
|
419
|
+
t.jsxExpressionContainer(
|
|
420
|
+
stylesExpr.elements.length === 1
|
|
421
|
+
? (stylesExpr.elements[0] as any)
|
|
422
|
+
: stylesExpr
|
|
423
|
+
)
|
|
424
|
+
)
|
|
425
|
+
)
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
})
|
|
430
|
+
} catch (err) {
|
|
431
|
+
if (err instanceof Error) {
|
|
432
|
+
// metro doesn't show stack so we can
|
|
433
|
+
let message = `${shouldPrintDebug === 'verbose' ? err : err.message}`
|
|
434
|
+
if (message.includes('Unexpected return value from visitor method')) {
|
|
435
|
+
message = 'Unexpected return value from visitor method'
|
|
436
|
+
}
|
|
437
|
+
console.warn('Error in Tamagui parse, skipping', message, err.stack)
|
|
438
|
+
return
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
if (!Object.keys(sheetStyles).length) {
|
|
443
|
+
if (shouldPrintDebug) {
|
|
444
|
+
console.info('END no styles')
|
|
445
|
+
}
|
|
446
|
+
if (res) printLog(res)
|
|
447
|
+
return
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
const sheetObject = literalToAst(sheetStyles)
|
|
451
|
+
const sheetOuter = template(
|
|
452
|
+
'const SHEET = __ReactNativeStyleSheet.create(null)'
|
|
453
|
+
)({
|
|
454
|
+
SHEET: sheetIdentifier.name,
|
|
455
|
+
}) as any
|
|
456
|
+
|
|
457
|
+
// replace the null with our object
|
|
458
|
+
sheetOuter.declarations[0].init.arguments[0] = sheetObject
|
|
459
|
+
root.unshiftContainer('body', sheetOuter)
|
|
460
|
+
// add import
|
|
461
|
+
root.unshiftContainer('body', importStyleSheet())
|
|
462
|
+
|
|
463
|
+
if (shouldPrintDebug) {
|
|
464
|
+
console.info('\n -------- output code ------- \n')
|
|
465
|
+
console.info(
|
|
466
|
+
generator(root.parent)
|
|
467
|
+
.code.split('\n')
|
|
468
|
+
.filter((x) => !x.startsWith('//'))
|
|
469
|
+
.join('\n')
|
|
470
|
+
)
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
if (res) printLog(res)
|
|
474
|
+
},
|
|
475
|
+
},
|
|
476
|
+
},
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
function assertValidTag(node: t.JSXOpeningElement) {
|
|
481
|
+
if (node.attributes.find((x) => x.type === 'JSXAttribute' && x.name.name === 'style')) {
|
|
482
|
+
// we can just deopt here instead and log warning
|
|
483
|
+
// need to make onExtractTag have a special catch error or similar
|
|
484
|
+
if (process.env.DEBUG?.startsWith('tamagui')) {
|
|
485
|
+
console.warn('⚠️ Cannot pass style attribute to extracted style')
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
function splitThemeStyles(style: Object) {
|
|
491
|
+
const themed: Object = {}
|
|
492
|
+
const plain: Object = {}
|
|
493
|
+
let noTheme = true
|
|
494
|
+
for (const key in style) {
|
|
495
|
+
const val = style[key]
|
|
496
|
+
if (val && val[0] === '$') {
|
|
497
|
+
themed[key] = val
|
|
498
|
+
noTheme = false
|
|
499
|
+
} else {
|
|
500
|
+
plain[key] = val
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
return { themed: noTheme ? null : themed, plain }
|
|
504
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { createExtractor } from './extractor/createExtractor'
|
|
|
6
6
|
export { literalToAst } from './extractor/literalToAst'
|
|
7
7
|
export * from './constants'
|
|
8
8
|
export * from './extractor/extractToClassNames'
|
|
9
|
+
export * from './extractor/extractToNative'
|
|
9
10
|
export * from './extractor/extractHelpers'
|
|
10
11
|
export * from './extractor/loadTamagui'
|
|
11
12
|
export * from './extractor/watchTamaguiConfig'
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type BabelFileResult } from '@babel/core';
|
|
2
|
+
import type { TamaguiOptions } from '@tamagui/static';
|
|
3
|
+
export declare function extractToNative(sourceFileName: string, sourceCode: string, options: TamaguiOptions): BabelFileResult;
|
|
4
|
+
export declare function getBabelPlugin(): any;
|
|
5
|
+
export declare function getBabelParseDefinition(options: TamaguiOptions): {
|
|
6
|
+
name: string;
|
|
7
|
+
visitor: {
|
|
8
|
+
Program: {
|
|
9
|
+
enter(this: any, root: any): void;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=extractToNative.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractToNative.d.ts","sourceRoot":"","sources":["../../src/extractor/extractToNative.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,eAAe,EAAwB,MAAM,aAAa,CAAA;AAMxE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AA2BrD,wBAAgB,eAAe,CAC7B,cAAc,EAAE,MAAM,EACtB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,cAAc,GACtB,eAAe,CAoBjB;AAED,wBAAgB,cAAc,QAK7B;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc;;;;wBAM3C,GAAG;;;EAmZtB"}
|
package/types/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { createExtractor } from './extractor/createExtractor';
|
|
|
6
6
|
export { literalToAst } from './extractor/literalToAst';
|
|
7
7
|
export * from './constants';
|
|
8
8
|
export * from './extractor/extractToClassNames';
|
|
9
|
+
export * from './extractor/extractToNative';
|
|
9
10
|
export * from './extractor/extractHelpers';
|
|
10
11
|
export * from './extractor/loadTamagui';
|
|
11
12
|
export * from './extractor/watchTamaguiConfig';
|
package/types/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,CAAA;AAChB,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,cAAc,aAAa,CAAA;AAC3B,cAAc,iCAAiC,CAAA;AAC/C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,CAAA;AAChB,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,SAAS,CAAA;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAA;AACvD,cAAc,aAAa,CAAA;AAC3B,cAAc,iCAAiC,CAAA;AAC/C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,0BAA0B,CAAA;AACxC,cAAc,mBAAmB,CAAA;AACjC,cAAc,oBAAoB,CAAA"}
|