@teleporthq/teleport-plugin-html-base-component 0.38.3 → 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
 
@@ -144,7 +154,7 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
144
154
  }
145
155
 
146
156
  const {
147
- content: { referenceType, id, refPath },
157
+ content: { referenceType, id, refPath = [] },
148
158
  } = reference
149
159
 
150
160
  switch (referenceType) {
@@ -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,8 +213,40 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
202
213
  }
203
214
 
204
215
  case 'expr':
205
- return HASTBuilders.createComment('Expressions are not supported in HTML')
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
+ }
206
238
 
239
+ return HASTBuilders.createComment('Expressions are not supported in HTML')
240
+ case 'cms-list-repeater':
241
+ return generateRepeaterNode(
242
+ node,
243
+ compName,
244
+ nodesLookup,
245
+ propDefinitions,
246
+ stateDefinitions,
247
+ subComponentOptions,
248
+ structure
249
+ )
207
250
  default:
208
251
  throw new HTMLComponentGeneratorError(
209
252
  `generateHtmlSyntax encountered a node of unsupported type: ${JSON.stringify(
@@ -249,7 +292,10 @@ const getValueType = (value: UIDLPropDefinition['defaultValue']) => {
249
292
  }
250
293
  }
251
294
 
252
- const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastText>> = async (
295
+ const generateRepeaterNode: NodeToHTML<
296
+ UIDLCMSListRepeaterNode,
297
+ Promise<HastNode | HastText>
298
+ > = async (
253
299
  node,
254
300
  compName,
255
301
  nodesLookup,
@@ -257,6 +303,94 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
257
303
  stateDefinitions,
258
304
  subComponentOptions,
259
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
260
394
  ) => {
261
395
  const {
262
396
  elementType,
@@ -300,7 +434,8 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
300
434
  propDefinitions,
301
435
  stateDefinitions,
302
436
  subComponentOptions,
303
- structure
437
+ structure,
438
+ resolvedExpressions
304
439
  )
305
440
 
306
441
  if (typeof childTag === 'string') {
@@ -331,10 +466,19 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
331
466
  propDefinitions,
332
467
  stateDefinitions,
333
468
  structure.options.projectRouteDefinition,
334
- structure.outputOptions
469
+ structure.outputOptions,
470
+ resolvedExpressions?.currentIndex
335
471
  )
336
472
 
337
- 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
+ )
338
482
  return elementNode
339
483
  }
340
484
 
@@ -448,7 +592,8 @@ const generateComponentContent = async (
448
592
  const statesForInstance = Object.keys(combinedStates).reduce(
449
593
  (acc: Record<string, UIDLStateDefinition>, propKey) => {
450
594
  const attr = attrs[propKey]
451
- if (attr.type === 'object') {
595
+
596
+ if (attr?.type === 'object') {
452
597
  throw new Error(`Object attributes are not supported in html exports`)
453
598
  }
454
599
 
@@ -502,6 +647,9 @@ const generateComponentContent = async (
502
647
  case 'state':
503
648
  propsForInstance[propKey] = combinedStates[propKey]
504
649
  break
650
+ case 'expr':
651
+ // Ignore expr type attributes in html comp instances for the time being.
652
+ break
505
653
  default:
506
654
  throw new Error(
507
655
  `ReferenceType ${attribute.content.referenceType} is not supported in HTML Export.`
@@ -722,7 +870,8 @@ const handleAttributes = (
722
870
  propDefinitions: Record<string, UIDLPropDefinition>,
723
871
  stateDefinitions: Record<string, UIDLStateDefinition>,
724
872
  routeDefinitions: UIDLRouteDefinitions,
725
- outputOptions: UIDLComponentOutputOptions
873
+ outputOptions: UIDLComponentOutputOptions,
874
+ currentIndex?: number
726
875
  ) => {
727
876
  for (const attrKey of Object.keys(attrs)) {
728
877
  const attrValue = attrs[attrKey]
@@ -815,9 +964,28 @@ const handleAttributes = (
815
964
  break
816
965
  }
817
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
+
818
987
  case 'element':
819
988
  case 'import':
820
- case 'expr':
821
989
  case 'object':
822
990
  break
823
991