@teleporthq/teleport-plugin-common 0.31.6 → 0.32.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.
Files changed (48) hide show
  1. package/__tests__/builders/style-builders.ts +12 -1
  2. package/__tests__/node-handlers/node-to-jsx/index.ts +3 -2
  3. package/dist/cjs/builders/style-builders.d.ts +3 -3
  4. package/dist/cjs/builders/style-builders.d.ts.map +1 -1
  5. package/dist/cjs/builders/style-builders.js +16 -9
  6. package/dist/cjs/builders/style-builders.js.map +1 -1
  7. package/dist/cjs/node-handlers/node-to-html/utils.d.ts.map +1 -1
  8. package/dist/cjs/node-handlers/node-to-html/utils.js.map +1 -1
  9. package/dist/cjs/node-handlers/node-to-jsx/index.d.ts.map +1 -1
  10. package/dist/cjs/node-handlers/node-to-jsx/index.js +208 -69
  11. package/dist/cjs/node-handlers/node-to-jsx/index.js.map +1 -1
  12. package/dist/cjs/node-handlers/node-to-jsx/types.d.ts +2 -1
  13. package/dist/cjs/node-handlers/node-to-jsx/types.d.ts.map +1 -1
  14. package/dist/cjs/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
  15. package/dist/cjs/node-handlers/node-to-jsx/utils.js +18 -7
  16. package/dist/cjs/node-handlers/node-to-jsx/utils.js.map +1 -1
  17. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  18. package/dist/cjs/utils/ast-utils.d.ts +15 -2
  19. package/dist/cjs/utils/ast-utils.d.ts.map +1 -1
  20. package/dist/cjs/utils/ast-utils.js +322 -11
  21. package/dist/cjs/utils/ast-utils.js.map +1 -1
  22. package/dist/esm/builders/style-builders.d.ts +3 -3
  23. package/dist/esm/builders/style-builders.d.ts.map +1 -1
  24. package/dist/esm/builders/style-builders.js +16 -9
  25. package/dist/esm/builders/style-builders.js.map +1 -1
  26. package/dist/esm/node-handlers/node-to-html/utils.d.ts.map +1 -1
  27. package/dist/esm/node-handlers/node-to-html/utils.js.map +1 -1
  28. package/dist/esm/node-handlers/node-to-jsx/index.d.ts.map +1 -1
  29. package/dist/esm/node-handlers/node-to-jsx/index.js +209 -70
  30. package/dist/esm/node-handlers/node-to-jsx/index.js.map +1 -1
  31. package/dist/esm/node-handlers/node-to-jsx/types.d.ts +2 -1
  32. package/dist/esm/node-handlers/node-to-jsx/types.d.ts.map +1 -1
  33. package/dist/esm/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
  34. package/dist/esm/node-handlers/node-to-jsx/utils.js +18 -7
  35. package/dist/esm/node-handlers/node-to-jsx/utils.js.map +1 -1
  36. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  37. package/dist/esm/utils/ast-utils.d.ts +15 -2
  38. package/dist/esm/utils/ast-utils.d.ts.map +1 -1
  39. package/dist/esm/utils/ast-utils.js +314 -10
  40. package/dist/esm/utils/ast-utils.js.map +1 -1
  41. package/package.json +7 -5
  42. package/src/builders/style-builders.ts +33 -10
  43. package/src/node-handlers/node-to-html/utils.ts +0 -1
  44. package/src/node-handlers/node-to-jsx/index.ts +443 -85
  45. package/src/node-handlers/node-to-jsx/types.ts +7 -1
  46. package/src/node-handlers/node-to-jsx/utils.ts +21 -7
  47. package/src/types.d.ts +2 -0
  48. package/src/utils/ast-utils.ts +562 -18
@@ -7,9 +7,15 @@ import {
7
7
  UIDLDynamicReference,
8
8
  UIDLSlotNode,
9
9
  UIDLNode,
10
+ UIDLCMSListNode,
11
+ UIDLCMSItemNode,
12
+ UIDLExpressionValue,
13
+ UIDLCMSListRepeaterNode,
14
+ UIDLCMSMixedTypeNode,
15
+ UIDLElement,
10
16
  } from '@teleporthq/teleport-types'
11
17
  import { UIDLUtils, StringUtils } from '@teleporthq/teleport-shared'
12
- import { JSXASTReturnType, NodeToJSX } from './types'
18
+ import { JSXASTReturnType, JSXGenerationOptions, NodeToJSX } from './types'
13
19
 
14
20
  import {
15
21
  addEventHandlerToTag,
@@ -25,17 +31,20 @@ import {
25
31
  addDynamicAttributeToJSXTag,
26
32
  addRawAttributeToJSXTag,
27
33
  generateDynamicWindowImport,
34
+ addDynamicExpressionAttributeToJSXTag,
35
+ resolveObjectValue,
28
36
  } from '../../utils/ast-utils'
29
37
  import { createJSXTag, createSelfClosingJSXTag } from '../../builders/ast-builders'
30
38
  import { DEFAULT_JSX_OPTIONS } from './constants'
39
+ import { ASTBuilders, ASTUtils } from '../..'
31
40
 
32
41
  const generateElementNode: NodeToJSX<UIDLElementNode, types.JSXElement> = (
33
42
  node,
34
43
  params,
35
44
  jsxOptions
36
45
  ) => {
37
- const options = { ...DEFAULT_JSX_OPTIONS, ...jsxOptions }
38
- const { dependencies, nodesLookup } = params
46
+ const { dependencies, nodesLookup, projectResources = {} } = params
47
+ const options = { ...DEFAULT_JSX_OPTIONS, ...jsxOptions, projectResources }
39
48
  const { elementType, selfClosing, children, key, attrs, dependency, events } = node.content
40
49
 
41
50
  const originalElementName = elementType || 'component'
@@ -77,37 +86,7 @@ const generateElementNode: NodeToJSX<UIDLElementNode, types.JSXElement> = (
77
86
  const elementTag = selfClosing ? createSelfClosingJSXTag(elementName) : createJSXTag(elementName)
78
87
 
79
88
  if (attrs) {
80
- Object.keys(attrs).forEach((attrKey) => {
81
- const attributeValue = attrs[attrKey]
82
-
83
- switch (attributeValue.type) {
84
- case 'dynamic':
85
- const {
86
- content: { id, referenceType },
87
- } = attributeValue
88
- const prefix =
89
- options.dynamicReferencePrefixMap[referenceType as 'prop' | 'state' | 'local']
90
- addDynamicAttributeToJSXTag(elementTag, attrKey, id, prefix)
91
- break
92
- case 'import':
93
- addDynamicAttributeToJSXTag(elementTag, attrKey, attributeValue.content.id)
94
- break
95
- case 'raw':
96
- addRawAttributeToJSXTag(elementTag, attrKey, attributeValue)
97
- break
98
- case 'comp-style':
99
- case 'static':
100
- const { content } = attributeValue
101
- addAttributeToJSXTag(elementTag, attrKey, content)
102
- break
103
- default:
104
- throw new Error(
105
- `generateElementNode could not generate code for attribute of type ${JSON.stringify(
106
- attributeValue
107
- )}`
108
- )
109
- }
110
- })
89
+ addAttributesToJSXTag(attrs, elementTag, options)
111
90
  }
112
91
 
113
92
  if (events) {
@@ -118,15 +97,16 @@ const generateElementNode: NodeToJSX<UIDLElementNode, types.JSXElement> = (
118
97
 
119
98
  if (!selfClosing && children) {
120
99
  children.forEach((child) => {
121
- const childTag = generateNode(child, params, options)
122
-
123
- if (typeof childTag === 'string') {
124
- addChildJSXText(elementTag, childTag)
125
- } else if (childTag.type === 'JSXExpressionContainer' || childTag.type === 'JSXElement') {
126
- addChildJSXTag(elementTag, childTag)
127
- } else {
128
- addChildJSXTag(elementTag, types.jsxExpressionContainer(childTag))
129
- }
100
+ const childTags = generateNode(child, params, options)
101
+ childTags.forEach((childTag) => {
102
+ if (typeof childTag === 'string') {
103
+ addChildJSXText(elementTag, childTag)
104
+ } else if (childTag.type === 'JSXExpressionContainer' || childTag.type === 'JSXElement') {
105
+ addChildJSXTag(elementTag, childTag)
106
+ } else {
107
+ addChildJSXTag(elementTag, types.jsxExpressionContainer(childTag))
108
+ }
109
+ })
130
110
  })
131
111
  }
132
112
 
@@ -136,28 +116,94 @@ const generateElementNode: NodeToJSX<UIDLElementNode, types.JSXElement> = (
136
116
 
137
117
  export default generateElementNode
138
118
 
139
- const generateNode: NodeToJSX<UIDLNode, JSXASTReturnType> = (node, params, options) => {
119
+ const addAttributesToJSXTag = (
120
+ attrs: UIDLElement['attrs'],
121
+ elementTag: types.JSXElement,
122
+ options: JSXGenerationOptions
123
+ ) => {
124
+ Object.keys(attrs).forEach((attrKey) => {
125
+ const attributeValue = attrs[attrKey]
126
+
127
+ switch (attributeValue.type) {
128
+ case 'dynamic':
129
+ const {
130
+ content: { referenceType },
131
+ } = attributeValue
132
+
133
+ switch (referenceType) {
134
+ default:
135
+ const prefix =
136
+ options.dynamicReferencePrefixMap[referenceType as 'prop' | 'state' | 'local']
137
+ addDynamicAttributeToJSXTag(
138
+ elementTag,
139
+ attrKey,
140
+ (attributeValue as UIDLDynamicReference).content.id,
141
+ prefix
142
+ )
143
+
144
+ break
145
+ }
146
+ break
147
+ case 'import':
148
+ addDynamicAttributeToJSXTag(elementTag, attrKey, attributeValue.content.id)
149
+ break
150
+ case 'raw':
151
+ addRawAttributeToJSXTag(elementTag, attrKey, attributeValue)
152
+ break
153
+ case 'comp-style':
154
+ case 'static':
155
+ addAttributeToJSXTag(elementTag, attrKey, attributeValue.content)
156
+ break
157
+ case 'expr':
158
+ addDynamicExpressionAttributeToJSXTag(elementTag, attributeValue, attrKey)
159
+ break
160
+ default:
161
+ throw new Error(
162
+ `generateElementNode could not generate code for attribute of type ${JSON.stringify(
163
+ attributeValue
164
+ )}`
165
+ )
166
+ }
167
+ })
168
+ }
169
+
170
+ const generateNode: NodeToJSX<UIDLNode, JSXASTReturnType[]> = (node, params, options) => {
140
171
  switch (node.type) {
172
+ case 'expr':
173
+ return [generateExpressionNode(node, params, options)]
174
+
175
+ case 'raw':
176
+ return [
177
+ options.domHTMLInjection
178
+ ? options.domHTMLInjection(node.content.toString())
179
+ : node.content.toString(),
180
+ ]
181
+
141
182
  case 'inject':
142
183
  if (node?.dependency) {
143
184
  /* tslint:disable:no-string-literal */
144
185
  params.dependencies['Script'] = node.dependency
145
186
  }
146
- return node.content.toString()
147
-
148
- case 'raw':
149
- return options.domHTMLInjection
150
- ? options.domHTMLInjection(node.content.toString())
151
- : node.content.toString()
187
+ return [node.content.toString()]
152
188
 
153
189
  case 'static':
154
- return StringUtils.encode(node.content.toString())
190
+ return [StringUtils.encode(node.content.toString())]
155
191
 
156
192
  case 'dynamic':
157
- return createDynamicValueExpression(node, options)
193
+ return [createDynamicValueExpression(node, options, undefined)]
194
+
195
+ case 'cms-item':
196
+ case 'cms-list':
197
+ return generateCMSNode(node, params, options)
198
+
199
+ case 'cms-list-repeater':
200
+ return generateCMSListRepeaterNode(node, params, options)
201
+
202
+ case 'cms-mixed-type':
203
+ return generateCMSMixedTypeNode(node, params, options)
158
204
 
159
205
  case 'element':
160
- return generateElementNode(node, params, options)
206
+ return [generateElementNode(node, params, options)]
161
207
 
162
208
  case 'repeat':
163
209
  return generateRepeatNode(node, params, options)
@@ -167,7 +213,7 @@ const generateNode: NodeToJSX<UIDLNode, JSXASTReturnType> = (node, params, optio
167
213
 
168
214
  case 'slot':
169
215
  if (options.slotHandling === 'native') {
170
- return generateNativeSlotNode(node, params, options)
216
+ return [generateNativeSlotNode(node, params, options)]
171
217
  } else {
172
218
  return generatePropsSlotNode(node, params, options)
173
219
  }
@@ -183,19 +229,273 @@ const generateNode: NodeToJSX<UIDLNode, JSXASTReturnType> = (node, params, optio
183
229
  }
184
230
  }
185
231
 
186
- const generateRepeatNode: NodeToJSX<UIDLRepeatNode, types.JSXExpressionContainer> = (
232
+ const generateExpressionNode: NodeToJSX<UIDLExpressionValue, types.JSXExpressionContainer> = (
233
+ node
234
+ ) => {
235
+ const expression = ASTUtils.getExpressionFromUIDLExpressionNode(node)
236
+ return types.jsxExpressionContainer(expression)
237
+ }
238
+
239
+ const generateCMSMixedTypeNode: NodeToJSX<UIDLCMSMixedTypeNode, types.JSXElement[]> = (
187
240
  node,
188
241
  params,
189
242
  options
190
243
  ) => {
191
- const { node: repeatContent, dataSource, meta } = node.content
244
+ const {
245
+ nodes: { error, fallback },
246
+ elementType,
247
+ renderPropIdentifier,
248
+ mappings = {},
249
+ attrs,
250
+ dependency,
251
+ } = node.content
252
+ const jsxTag = StringUtils.dashCaseToUpperCamelCase(elementType)
253
+ const cmsMixedNode = ASTBuilders.createJSXTag(jsxTag, [], true)
254
+ const mappingsObject: types.ObjectProperty[] = []
255
+
256
+ if (attrs) {
257
+ addAttributesToJSXTag(attrs, cmsMixedNode, options)
258
+ }
259
+
260
+ if (dependency) {
261
+ params.dependencies[elementType] = dependency
262
+ }
263
+
264
+ Object.keys(mappings).forEach((key) => {
265
+ const element = generateElementNode(mappings[key], params, options)
266
+ mappingsObject.push(
267
+ types.objectProperty(
268
+ types.identifier(key),
269
+ types.arrowFunctionExpression([types.identifier(renderPropIdentifier)], element)
270
+ )
271
+ )
272
+ })
273
+
274
+ cmsMixedNode.openingElement.attributes.push(
275
+ types.jsxAttribute(
276
+ types.jsxIdentifier('mappingConfiguration'),
277
+ types.jsxExpressionContainer(types.objectExpression(mappingsObject))
278
+ )
279
+ )
280
+
281
+ if (fallback) {
282
+ cmsMixedNode.openingElement.attributes.push(
283
+ types.jSXAttribute(
284
+ types.jsxIdentifier('renderDefault'),
285
+ types.jsxExpressionContainer(
286
+ types.arrowFunctionExpression(
287
+ [types.identifier(renderPropIdentifier)],
288
+ generateElementNode(fallback, params, options)
289
+ )
290
+ )
291
+ )
292
+ )
293
+ }
294
+
295
+ if (error) {
296
+ cmsMixedNode.openingElement.attributes.push(
297
+ types.jSXAttribute(
298
+ types.jsxIdentifier('renderError'),
299
+ types.jsxExpressionContainer(
300
+ types.arrowFunctionExpression(
301
+ [types.identifier(renderPropIdentifier)],
302
+ generateElementNode(error, params, options)
303
+ )
304
+ )
305
+ )
306
+ )
307
+ }
308
+
309
+ return [cmsMixedNode]
310
+ }
311
+
312
+ const generateCMSNode: NodeToJSX<UIDLCMSListNode | UIDLCMSItemNode, types.JSXElement[]> = (
313
+ node,
314
+ params,
315
+ options
316
+ ) => {
317
+ const {
318
+ initialData,
319
+ key,
320
+ renderPropIdentifier,
321
+ resource: { params: resourceParams } = {},
322
+ router,
323
+ elementType,
324
+ dependency,
325
+ } = node.content
326
+ const { loading, error, success } = node.content.nodes
327
+ const jsxTag = StringUtils.dashCaseToUpperCamelCase(elementType)
328
+
329
+ if (router && options?.dependencyHandling === 'import') {
330
+ params.dependencies.useRouter = router
331
+ }
332
+
333
+ if (!success) {
334
+ return []
335
+ }
336
+
337
+ if (dependency && options.dependencyHandling === 'import') {
338
+ params.dependencies[elementType] = dependency
339
+ }
340
+
341
+ const cmsNode = ASTBuilders.createJSXTag(jsxTag, [], true)
342
+
343
+ if (node.type === 'cms-item') {
344
+ cmsNode.openingElement.attributes.push(
345
+ types.jsxAttribute(
346
+ types.jsxIdentifier('renderSuccess'),
347
+ types.jsxExpressionContainer(
348
+ types.arrowFunctionExpression(
349
+ [types.identifier(renderPropIdentifier)],
350
+ generateNode(success, params, options)[0] as types.JSXElement
351
+ )
352
+ )
353
+ )
354
+ )
355
+ }
356
+
357
+ if (node.type === 'cms-list') {
358
+ cmsNode.openingElement.attributes.push(
359
+ types.jsxAttribute(
360
+ types.jsxIdentifier('renderSuccess'),
361
+ types.jsxExpressionContainer(
362
+ types.arrowFunctionExpression(
363
+ [types.identifier('params')],
364
+ generateNode(success, params, options)[0] as types.JSXElement
365
+ )
366
+ )
367
+ )
368
+ )
369
+ }
370
+ if (dependency && options.dependencyHandling === 'import') {
371
+ params.dependencies.Repeater = dependency
372
+ }
373
+ if (loading) {
374
+ cmsNode.openingElement.attributes.push(
375
+ types.jsxAttribute(
376
+ types.jsxIdentifier('renderLoading'),
377
+ types.jsxExpressionContainer(
378
+ types.arrowFunctionExpression(
379
+ [],
380
+ generateNode(loading, params, options)[0] as types.JSXElement
381
+ )
382
+ )
383
+ )
384
+ )
385
+ }
386
+
387
+ if (error) {
388
+ cmsNode.openingElement.attributes.push(
389
+ types.jsxAttribute(
390
+ types.jsxIdentifier('renderError'),
391
+ types.jsxExpressionContainer(
392
+ types.arrowFunctionExpression(
393
+ [],
394
+ generateNode(error, params, options)[0] as types.JSXElement
395
+ )
396
+ )
397
+ )
398
+ )
399
+ }
400
+
401
+ if (initialData && initialData.content.referenceType === 'prop') {
402
+ cmsNode.openingElement.attributes.push(
403
+ types.jsxAttribute(
404
+ types.jsxIdentifier('initialData'),
405
+ types.jsxExpressionContainer(
406
+ types.memberExpression(
407
+ types.identifier(options.dynamicReferencePrefixMap[initialData.content.referenceType]),
408
+ types.identifier(initialData.content.id)
409
+ )
410
+ )
411
+ )
412
+ )
192
413
 
193
- const contentAST = generateElementNode(repeatContent, params, options)
414
+ cmsNode.openingElement.attributes.push(
415
+ types.jsxAttribute(
416
+ types.jsxIdentifier('persistDataDuringLoading'),
417
+ types.jsxExpressionContainer(types.booleanLiteral(true))
418
+ )
419
+ )
420
+
421
+ let keyValue = 'props?.pagination?.page'
422
+
423
+ if (node.type === 'cms-item') {
424
+ const { entityKeyProperty } = node.content
425
+ const entityName = initialData.content.id
426
+ keyValue = entityKeyProperty
427
+ ? `props?.${entityName}?.${entityKeyProperty}`
428
+ : `props?.${entityName}?.id`
429
+ }
430
+
431
+ cmsNode.openingElement.attributes.push(
432
+ types.jsxAttribute(
433
+ types.jsxIdentifier('key'),
434
+ types.jsxExpressionContainer(types.identifier(keyValue))
435
+ )
436
+ )
437
+ }
438
+
439
+ if (Object.keys(resourceParams || {}).length > 0) {
440
+ const nodeParams: types.ObjectProperty[] = Object.keys(resourceParams).reduce(
441
+ (acc: types.ObjectProperty[], attrKey) => {
442
+ const property = resourceParams[attrKey]
443
+
444
+ if (property.type === 'static') {
445
+ acc.push(types.objectProperty(types.stringLiteral(attrKey), resolveObjectValue(property)))
446
+ }
447
+
448
+ if (property.type === 'expr') {
449
+ const expression = ASTUtils.getExpressionFromUIDLExpressionNode(property)
450
+ acc.push(types.objectProperty(types.stringLiteral(attrKey), expression))
451
+ }
452
+
453
+ if (property.type === 'dynamic') {
454
+ acc.push(
455
+ types.objectProperty(
456
+ types.stringLiteral(attrKey),
457
+ property.content.referenceType === 'prop'
458
+ ? types.memberExpression(
459
+ types.identifier(
460
+ options.dynamicReferencePrefixMap[property.content.referenceType]
461
+ ),
462
+ types.identifier(property.content.id)
463
+ )
464
+ : types.identifier(property.content.id)
465
+ )
466
+ )
467
+ }
468
+
469
+ return acc
470
+ },
471
+ []
472
+ )
473
+ cmsNode.openingElement.attributes.push(
474
+ types.jsxAttribute(
475
+ types.jsxIdentifier('params'),
476
+ types.jsxExpressionContainer(types.objectExpression(nodeParams))
477
+ )
478
+ )
479
+ }
480
+
481
+ params.nodesLookup[key] = cmsNode
482
+ return [cmsNode]
483
+ }
484
+
485
+ const generateRepeatNode: NodeToJSX<UIDLRepeatNode, types.JSXExpressionContainer[]> = (
486
+ node,
487
+ params,
488
+ options
489
+ ) => {
490
+ const { node: repeatContent, dataSource, meta } = node.content
491
+ const contentASTs = generateNode(repeatContent, params, options) as types.JSXElement[]
194
492
 
195
493
  const { iteratorName, iteratorKey } = UIDLUtils.getRepeatIteratorNameAndKey(meta)
196
494
 
197
495
  const localIteratorPrefix = options.dynamicReferencePrefixMap.local
198
- addDynamicAttributeToJSXTag(contentAST, 'key', iteratorKey, localIteratorPrefix)
496
+ contentASTs.forEach((contentAST) => {
497
+ addDynamicAttributeToJSXTag(contentAST, 'key', iteratorKey, localIteratorPrefix)
498
+ })
199
499
 
200
500
  const source = getRepeatSourceIdentifier(dataSource, options)
201
501
 
@@ -204,14 +504,16 @@ const generateRepeatNode: NodeToJSX<UIDLRepeatNode, types.JSXExpressionContainer
204
504
  arrowFunctionArguments.push(types.identifier('index'))
205
505
  }
206
506
 
207
- return types.jsxExpressionContainer(
208
- types.callExpression(types.memberExpression(source, types.identifier('map')), [
209
- types.arrowFunctionExpression(arrowFunctionArguments, contentAST),
210
- ])
507
+ return contentASTs.map((contentAST) =>
508
+ types.jsxExpressionContainer(
509
+ types.callExpression(types.memberExpression(source, types.identifier('map')), [
510
+ types.arrowFunctionExpression(arrowFunctionArguments, contentAST),
511
+ ])
512
+ )
211
513
  )
212
514
  }
213
515
 
214
- const generateConditionalNode: NodeToJSX<UIDLConditionalNode, types.LogicalExpression> = (
516
+ const generateConditionalNode: NodeToJSX<UIDLConditionalNode, types.LogicalExpression[]> = (
215
517
  node,
216
518
  params,
217
519
  options
@@ -219,17 +521,67 @@ const generateConditionalNode: NodeToJSX<UIDLConditionalNode, types.LogicalExpre
219
521
  const { reference, value } = node.content
220
522
  const conditionIdentifier = createConditionIdentifier(reference, params, options)
221
523
 
222
- const subTree = generateNode(node.content.node, params, options)
524
+ const subTrees = generateNode(node.content.node, params, options)
223
525
 
224
526
  const condition: UIDLConditionalExpression =
225
527
  value !== undefined && value !== null
226
528
  ? { conditions: [{ operand: value, operation: '===' }] }
227
529
  : node.content.condition
228
530
 
229
- return createConditionalJSXExpression(subTree, condition, conditionIdentifier)
531
+ return subTrees.map((subTree) =>
532
+ createConditionalJSXExpression(subTree, condition, conditionIdentifier)
533
+ )
534
+ }
535
+
536
+ const generateCMSListRepeaterNode: NodeToJSX<UIDLCMSListRepeaterNode, types.JSXElement[]> = (
537
+ node,
538
+ params,
539
+ options
540
+ ) => {
541
+ const jsxTag = StringUtils.dashCaseToUpperCamelCase(node.content.elementType)
542
+ const repeaterNode = ASTBuilders.createJSXTag(jsxTag, [], true)
543
+
544
+ repeaterNode.openingElement.attributes.push(
545
+ types.jsxAttribute(
546
+ types.jsxIdentifier('items'),
547
+ types.jsxExpressionContainer(types.identifier(node.content.source ?? 'params'))
548
+ )
549
+ )
550
+
551
+ repeaterNode.openingElement.attributes.push(
552
+ types.jsxAttribute(
553
+ types.jSXIdentifier('renderItem'),
554
+ types.jsxExpressionContainer(
555
+ types.arrowFunctionExpression(
556
+ [types.identifier(node.content.renderPropIdentifier)],
557
+ generateNode(node.content.nodes.list, params, options)[0] as types.JSXElement
558
+ )
559
+ )
560
+ )
561
+ )
562
+
563
+ if ('empty' in node.content.nodes) {
564
+ repeaterNode.openingElement.attributes.push(
565
+ types.jsxAttribute(
566
+ types.jsxIdentifier('renderEmpty'),
567
+ types.jsxExpressionContainer(
568
+ types.arrowFunctionExpression(
569
+ [],
570
+ generateNode(node.content.nodes.empty, params, options)[0] as types.JSXElement
571
+ )
572
+ )
573
+ )
574
+ )
575
+ }
576
+
577
+ if (node.content?.dependency && options.dependencyHandling === 'import') {
578
+ params.dependencies[jsxTag] = node.content.dependency
579
+ }
580
+
581
+ return [repeaterNode]
230
582
  }
231
583
 
232
- const generatePropsSlotNode: NodeToJSX<UIDLSlotNode, types.JSXExpressionContainer> = (
584
+ const generatePropsSlotNode: NodeToJSX<UIDLSlotNode, types.JSXExpressionContainer[]> = (
233
585
  node: UIDLSlotNode,
234
586
  params,
235
587
  options
@@ -247,20 +599,23 @@ const generatePropsSlotNode: NodeToJSX<UIDLSlotNode, types.JSXExpressionContaine
247
599
  const childrenExpression = createDynamicValueExpression(childrenProp, options)
248
600
 
249
601
  if (node.content.fallback) {
250
- const fallbackContent = generateNode(node.content.fallback, params, options)
602
+ const fallbackContents = generateNode(node.content.fallback, params, options)
251
603
  // only static dynamic or element are allowed here
252
- const fallbackNode =
253
- typeof fallbackContent === 'string'
254
- ? types.stringLiteral(fallbackContent)
255
- : (fallbackContent as types.JSXElement | types.MemberExpression)
256
-
257
- // props.children with fallback
258
- return types.jsxExpressionContainer(
259
- types.logicalExpression('||', childrenExpression, fallbackNode)
260
- )
604
+
605
+ return fallbackContents.map((fallbackContent) => {
606
+ const fallbackNode =
607
+ typeof fallbackContent === 'string'
608
+ ? types.stringLiteral(fallbackContent)
609
+ : (fallbackContent as types.JSXElement | types.MemberExpression)
610
+
611
+ // props.children with fallback
612
+ return types.jsxExpressionContainer(
613
+ types.logicalExpression('||', childrenExpression, fallbackNode)
614
+ )
615
+ })
261
616
  }
262
617
 
263
- return types.jsxExpressionContainer(childrenExpression)
618
+ return [types.jsxExpressionContainer(childrenExpression)]
264
619
  }
265
620
 
266
621
  const generateNativeSlotNode: NodeToJSX<UIDLSlotNode, types.JSXElement> = (
@@ -275,14 +630,17 @@ const generateNativeSlotNode: NodeToJSX<UIDLSlotNode, types.JSXElement> = (
275
630
  }
276
631
 
277
632
  if (node.content.fallback) {
278
- const fallbackContent = generateNode(node.content.fallback, params, options)
279
- if (typeof fallbackContent === 'string') {
280
- addChildJSXText(slotNode, fallbackContent)
281
- } else if (fallbackContent.type === 'MemberExpression') {
282
- addChildJSXTag(slotNode, types.jsxExpressionContainer(fallbackContent))
283
- } else {
284
- addChildJSXTag(slotNode, fallbackContent as types.JSXElement)
285
- }
633
+ const fallbackContents = generateNode(node.content.fallback, params, options)
634
+
635
+ fallbackContents.forEach((fallbackContent) => {
636
+ if (typeof fallbackContent === 'string') {
637
+ addChildJSXText(slotNode, fallbackContent)
638
+ } else if (fallbackContent.type === 'MemberExpression') {
639
+ addChildJSXTag(slotNode, types.jsxExpressionContainer(fallbackContent))
640
+ } else {
641
+ addChildJSXTag(slotNode, fallbackContent as types.JSXElement)
642
+ }
643
+ })
286
644
  }
287
645
 
288
646
  return slotNode
@@ -1,6 +1,11 @@
1
1
  import * as types from '@babel/types'
2
2
 
3
- import { UIDLPropDefinition, UIDLDependency, UIDLStateDefinition } from '@teleporthq/teleport-types'
3
+ import {
4
+ UIDLPropDefinition,
5
+ UIDLDependency,
6
+ UIDLStateDefinition,
7
+ ProjectResource,
8
+ } from '@teleporthq/teleport-types'
4
9
 
5
10
  export interface JSXGenerationParams {
6
11
  propDefinitions: Record<string, UIDLPropDefinition>
@@ -8,6 +13,7 @@ export interface JSXGenerationParams {
8
13
  nodesLookup: Record<string, types.JSXElement>
9
14
  dependencies: Record<string, UIDLDependency>
10
15
  windowImports: Record<string, types.ExpressionStatement>
16
+ projectResources?: Record<string, ProjectResource>
11
17
  }
12
18
 
13
19
  export interface JSXGenerationOptions {