@teleporthq/teleport-plugin-html-base-component 0.38.5 → 0.38.7

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.
@@ -24,6 +24,7 @@ import {
24
24
  ElementsLookup,
25
25
  UIDLConditionalNode,
26
26
  PropDefaultValueTypes,
27
+ UIDLCMSListRepeaterNode,
27
28
  } from '@teleporthq/teleport-types'
28
29
  import { join, relative } from 'path'
29
30
  import { HASTBuilders, HASTUtils, ASTUtils } from '@teleporthq/teleport-plugin-common'
@@ -82,6 +83,13 @@ type NodeToHTML<NodeType, ReturnType> = (
82
83
  dependencies: Record<string, UIDLDependency>
83
84
  options: GeneratorOptions
84
85
  outputOptions: UIDLComponentOutputOptions
86
+ },
87
+ /**
88
+ * This param is just to be able to handle CMS array mappers/Repeater nodes. A bit hacky, better support should be implemented
89
+ */
90
+ resolvedExpressions?: {
91
+ expressions: Record<string, UIDLPropDefinition>
92
+ currentIndex: number
85
93
  }
86
94
  ) => ReturnType
87
95
 
@@ -92,7 +100,8 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
92
100
  propDefinitions,
93
101
  stateDefinitions,
94
102
  subComponentOptions,
95
- structure
103
+ structure,
104
+ resolvedExpressions
96
105
  ) => {
97
106
  switch (node.type) {
98
107
  case 'inject':
@@ -113,7 +122,8 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
113
122
  propDefinitions,
114
123
  stateDefinitions,
115
124
  subComponentOptions,
116
- structure
125
+ structure,
126
+ resolvedExpressions
117
127
  )
118
128
  return elementNode
119
129
 
@@ -186,7 +196,8 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
186
196
  propDefinitions,
187
197
  stateDefinitions,
188
198
  subComponentOptions,
189
- structure
199
+ structure,
200
+ resolvedExpressions
190
201
  )
191
202
  }
192
203
  } catch (error) {
@@ -202,9 +213,40 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
202
213
  }
203
214
 
204
215
  case 'expr':
216
+ const content = node.content.split('?.')
217
+
218
+ if (resolvedExpressions && resolvedExpressions.expressions?.[content[0] || '']) {
219
+ const uidlDynamicRef: UIDLDynamicReference = {
220
+ type: 'dynamic',
221
+ content: {
222
+ referenceType: 'prop',
223
+ refPath: [resolvedExpressions.currentIndex.toString(), ...content.slice(1)],
224
+ id: content[0],
225
+ },
226
+ }
227
+ const generatedNode = await generateDynamicNode(
228
+ uidlDynamicRef,
229
+ compName,
230
+ nodesLookup,
231
+ resolvedExpressions.expressions,
232
+ stateDefinitions,
233
+ subComponentOptions,
234
+ structure
235
+ )
236
+ return generatedNode
237
+ }
238
+
205
239
  return HASTBuilders.createComment('Expressions are not supported in HTML')
206
240
  case 'cms-list-repeater':
207
- return HASTBuilders.createComment('CMS Repeater/Array Mapper nodes are not supported in HTML')
241
+ return generateRepeaterNode(
242
+ node,
243
+ compName,
244
+ nodesLookup,
245
+ propDefinitions,
246
+ stateDefinitions,
247
+ subComponentOptions,
248
+ structure
249
+ )
208
250
  default:
209
251
  throw new HTMLComponentGeneratorError(
210
252
  `generateHtmlSyntax encountered a node of unsupported type: ${JSON.stringify(
@@ -250,7 +292,10 @@ const getValueType = (value: UIDLPropDefinition['defaultValue']) => {
250
292
  }
251
293
  }
252
294
 
253
- const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastText>> = async (
295
+ const generateRepeaterNode: NodeToHTML<
296
+ UIDLCMSListRepeaterNode,
297
+ Promise<HastNode | HastText>
298
+ > = async (
254
299
  node,
255
300
  compName,
256
301
  nodesLookup,
@@ -258,6 +303,94 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
258
303
  stateDefinitions,
259
304
  subComponentOptions,
260
305
  structure
306
+ ) => {
307
+ const { nodes } = node.content
308
+
309
+ const contextId = node.content.renderPropIdentifier
310
+ const sourceProp = node.content.source
311
+ const propDef =
312
+ propDefinitions[
313
+ Object.keys(propDefinitions).find((propKey) => sourceProp.includes(propKey)) || ''
314
+ ]
315
+
316
+ propDefinitions[contextId] = propDef
317
+
318
+ if (!propDef || !Array.isArray(propDef.defaultValue)) {
319
+ return HASTBuilders.createComment(
320
+ 'CMS Array Mapper/Repeater not supported in HTML without a prop source'
321
+ )
322
+ }
323
+
324
+ const elementNode = HASTBuilders.createHTMLNode('div')
325
+ node.content.nodes.list.content.style = { display: { type: 'static', content: 'contents' } }
326
+ // Empty case
327
+ if (propDef.defaultValue.length === 0) {
328
+ const emptyChildren = nodes.empty.content.children
329
+ if (emptyChildren) {
330
+ for (const child of emptyChildren) {
331
+ const childTag = await generateHtmlSyntax(
332
+ child,
333
+ compName,
334
+ nodesLookup,
335
+ propDefinitions,
336
+ stateDefinitions,
337
+ subComponentOptions,
338
+ structure
339
+ )
340
+
341
+ if (typeof childTag === 'string') {
342
+ HASTUtils.addTextNode(elementNode, childTag)
343
+ } else {
344
+ HASTUtils.addChildNode(elementNode, childTag as HastNode)
345
+ }
346
+ }
347
+ }
348
+ return elementNode
349
+ }
350
+
351
+ const listChildren = nodes.list.content.children
352
+ if (listChildren) {
353
+ for (let index = 0; index < propDef.defaultValue.length; index++) {
354
+ for (const child of listChildren) {
355
+ const childTag = await generateHtmlSyntax(
356
+ child,
357
+ compName,
358
+ nodesLookup,
359
+ propDefinitions,
360
+ stateDefinitions,
361
+ subComponentOptions,
362
+ structure,
363
+ { currentIndex: index, expressions: { [contextId]: propDef } }
364
+ )
365
+
366
+ if (typeof childTag === 'string') {
367
+ HASTUtils.addTextNode(elementNode, childTag)
368
+ } else {
369
+ HASTUtils.addChildNode(elementNode, childTag as HastNode)
370
+ }
371
+ }
372
+ }
373
+ }
374
+
375
+ addNodeToLookup(
376
+ `${node.content.nodes.list.content.key}`,
377
+ node.content.nodes.list,
378
+ elementNode,
379
+ nodesLookup,
380
+ [compName]
381
+ )
382
+ return elementNode
383
+ }
384
+
385
+ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastText>> = async (
386
+ node,
387
+ compName,
388
+ nodesLookup,
389
+ propDefinitions,
390
+ stateDefinitions,
391
+ subComponentOptions,
392
+ structure,
393
+ resolvedExpressions
261
394
  ) => {
262
395
  const {
263
396
  elementType,
@@ -301,7 +434,8 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
301
434
  propDefinitions,
302
435
  stateDefinitions,
303
436
  subComponentOptions,
304
- structure
437
+ structure,
438
+ resolvedExpressions
305
439
  )
306
440
 
307
441
  if (typeof childTag === 'string') {
@@ -332,10 +466,19 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
332
466
  propDefinitions,
333
467
  stateDefinitions,
334
468
  structure.options.projectRouteDefinition,
335
- structure.outputOptions
469
+ structure.outputOptions,
470
+ resolvedExpressions?.currentIndex
336
471
  )
337
472
 
338
- addNodeToLookup(node.content.key, node, elementNode, nodesLookup, [compName])
473
+ addNodeToLookup(
474
+ resolvedExpressions
475
+ ? `${node.content.key}-repeat${resolvedExpressions.currentIndex}`
476
+ : node.content.key,
477
+ node,
478
+ elementNode,
479
+ nodesLookup,
480
+ [compName]
481
+ )
339
482
  return elementNode
340
483
  }
341
484
 
@@ -505,7 +648,7 @@ const generateComponentContent = async (
505
648
  propsForInstance[propKey] = combinedStates[propKey]
506
649
  break
507
650
  case 'expr':
508
- // Ignore expr type attributes in html for the time being.
651
+ // Ignore expr type attributes in html comp instances for the time being.
509
652
  break
510
653
  default:
511
654
  throw new Error(
@@ -727,7 +870,8 @@ const handleAttributes = (
727
870
  propDefinitions: Record<string, UIDLPropDefinition>,
728
871
  stateDefinitions: Record<string, UIDLStateDefinition>,
729
872
  routeDefinitions: UIDLRouteDefinitions,
730
- outputOptions: UIDLComponentOutputOptions
873
+ outputOptions: UIDLComponentOutputOptions,
874
+ currentIndex?: number
731
875
  ) => {
732
876
  for (const attrKey of Object.keys(attrs)) {
733
877
  const attrValue = attrs[attrKey]
@@ -820,9 +964,28 @@ const handleAttributes = (
820
964
  break
821
965
  }
822
966
 
967
+ case 'expr': {
968
+ const fullPath = content.split('?.')
969
+ const prop = propDefinitions[fullPath?.[0] || '']
970
+
971
+ if (!prop) {
972
+ break
973
+ }
974
+
975
+ const path =
976
+ typeof currentIndex === 'number'
977
+ ? [currentIndex.toString(), ...fullPath.slice(1)]
978
+ : fullPath.slice(1)
979
+ const value = extractDefaultValueFromRefPath(prop.defaultValue, path)
980
+ if (!value) {
981
+ break
982
+ }
983
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, String(value))
984
+ break
985
+ }
986
+
823
987
  case 'element':
824
988
  case 'import':
825
- case 'expr':
826
989
  case 'object':
827
990
  break
828
991