@teleporthq/teleport-plugin-html-base-component 0.40.3 → 0.40.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.
@@ -136,7 +136,8 @@ export const generateHtmlSyntax: NodeToHTML<
136
136
  propDefinitions,
137
137
  stateDefinitions,
138
138
  subComponentOptions,
139
- structure
139
+ structure,
140
+ resolvedExpressions
140
141
  )
141
142
  return dynamicNode
142
143
 
@@ -232,6 +233,56 @@ export const generateHtmlSyntax: NodeToHTML<
232
233
  return generatedNode
233
234
  }
234
235
 
236
+ // Repeater alias fallback: if inside repeater but key doesn't match, try the single available context
237
+ if (
238
+ resolvedExpressions &&
239
+ resolvedExpressions.expressions &&
240
+ Object.keys(resolvedExpressions.expressions).length === 1
241
+ ) {
242
+ const onlyKey = Object.keys(resolvedExpressions.expressions)[0]
243
+ const uidlDynamicRef: UIDLDynamicReference = {
244
+ type: 'dynamic',
245
+ content: {
246
+ referenceType: 'prop',
247
+ refPath: [resolvedExpressions.currentIndex.toString(), ...content.slice(1)],
248
+ id: onlyKey,
249
+ },
250
+ }
251
+ const generatedNode = await generateDynamicNode(
252
+ uidlDynamicRef,
253
+ compName,
254
+ nodesLookup,
255
+ resolvedExpressions.expressions,
256
+ stateDefinitions,
257
+ subComponentOptions,
258
+ structure
259
+ )
260
+ return generatedNode
261
+ }
262
+
263
+ // Fallback: support simple prop/state expressions outside of repeater context
264
+ if (content[0] && (propDefinitions?.[content[0]] || stateDefinitions?.[content[0]])) {
265
+ const isProp = Boolean(propDefinitions?.[content[0]])
266
+ const uidlDynamicRef: UIDLDynamicReference = {
267
+ type: 'dynamic',
268
+ content: {
269
+ referenceType: isProp ? 'prop' : 'state',
270
+ refPath: content.slice(1),
271
+ id: content[0],
272
+ },
273
+ }
274
+ const generatedNode = await generateDynamicNode(
275
+ uidlDynamicRef,
276
+ compName,
277
+ nodesLookup,
278
+ isProp ? propDefinitions : stateDefinitions,
279
+ stateDefinitions,
280
+ subComponentOptions,
281
+ structure
282
+ )
283
+ return generatedNode
284
+ }
285
+
235
286
  return HASTBuilders.createComment('Expressions are not supported in HTML')
236
287
  case 'cms-list-repeater':
237
288
  return generateRepeaterNode(
@@ -664,18 +715,27 @@ const generateComponentContent = async (
664
715
  const propKeyFromAttr = Object.keys(combinedProps).find((key) => key === ctxId)
665
716
 
666
717
  const resolvedValue = combinedProps[propKeyFromAttr]
667
- propsForInstance[propKey] = Array.isArray(resolvedValue)
668
- ? resolvedValue
669
- : {
670
- ...resolvedValue,
671
- defaultValue:
672
- refPath.length > 0 && resolvedValue?.defaultValue
673
- ? extractDefaultValueFromRefPath(resolvedValue.defaultValue, [
674
- resolvedExpressions.currentIndex.toString(),
675
- ...refPath,
676
- ])
677
- : null,
678
- }
718
+ const hasRefPath = refPath.length > 0
719
+ // Build the path using repeater index when available
720
+ const fullRefPath =
721
+ typeof resolvedExpressions?.currentIndex === 'number' && hasRefPath
722
+ ? [resolvedExpressions.currentIndex.toString(), ...refPath]
723
+ : refPath
724
+
725
+ if (Array.isArray(resolvedValue)) {
726
+ // If the resolved value itself is an array definition, pass it through
727
+ propsForInstance[propKey] = resolvedValue
728
+ } else {
729
+ const defaultVal = resolvedValue?.defaultValue
730
+ const extracted =
731
+ hasRefPath && defaultVal !== undefined
732
+ ? extractDefaultValueFromRefPath(defaultVal, fullRefPath)
733
+ : defaultVal ?? null
734
+ propsForInstance[propKey] = {
735
+ ...resolvedValue,
736
+ defaultValue: extracted,
737
+ }
738
+ }
679
739
  }
680
740
 
681
741
  if (
@@ -724,7 +784,8 @@ const generateComponentContent = async (
724
784
  propsForInstance,
725
785
  statesForInstance,
726
786
  subComponentOptions,
727
- structure
787
+ structure,
788
+ resolvedExpressions
728
789
  )
729
790
 
730
791
  const cssPlugin = createCSSPlugin({
@@ -786,7 +847,8 @@ const generateDynamicNode: NodeToHTML<
786
847
  propDefinitions,
787
848
  stateDefinitions,
788
849
  subComponentOptions,
789
- structure
850
+ structure,
851
+ resolvedExpressions?
790
852
  ): Promise<HastNode | HastText | Array<HastNode | HastText>> => {
791
853
  if (node.content.referenceType === 'locale') {
792
854
  const localeTag = HASTBuilders.createHTMLNode('span')
@@ -807,33 +869,53 @@ const generateDynamicNode: NodeToHTML<
807
869
  // Let's say users are biding the prop to a node using something like this "fields.Title"
808
870
  // But the fields in the object is the value where the object is defined either in propDefinitions
809
871
  // or on the attrs. So, we just need to parsed the rest of the object path and get the value from the object.
810
- return HASTBuilders.createTextNode(
811
- String(
812
- extractDefaultValueFromRefPath(
813
- usedReferenceValue.defaultValue as Record<string, UIDLPropDefinition>,
814
- node.content.refPath
815
- )
816
- )
872
+ const extracted = extractDefaultValueFromRefPath(
873
+ usedReferenceValue.defaultValue as Record<string, UIDLPropDefinition>,
874
+ node.content.refPath
817
875
  )
876
+ if (extracted === undefined || extracted === null) {
877
+ return HASTBuilders.createTextNode('')
878
+ }
879
+ return HASTBuilders.createTextNode(String(extracted))
818
880
  }
819
881
 
820
882
  if (usedReferenceValue.type === 'element') {
821
883
  const elementNode = usedReferenceValue.defaultValue as UIDLElementNode
822
884
  if (elementNode) {
823
- if (elementNode.content.key in nodesLookup) {
824
- return nodesLookup[elementNode.content.key]
825
- } else {
826
- const elementTag = await generateHtmlSyntax(
827
- elementNode,
885
+ // In repeater context, avoid reusing cached nodes; uniquify key per iteration
886
+ if (resolvedExpressions && typeof resolvedExpressions.currentIndex === 'number') {
887
+ const elementClone = UIDLUtils.cloneObject<UIDLElementNode>(elementNode)
888
+ if (elementClone?.content?.key) {
889
+ elementClone.content.key = `${elementClone.content.key}-${resolvedExpressions.currentIndex}`
890
+ }
891
+ const iterElementTag = await generateHtmlSyntax(
892
+ elementClone,
828
893
  compName,
829
894
  nodesLookup,
830
895
  propDefinitions,
831
896
  stateDefinitions,
832
897
  subComponentOptions,
833
- structure
898
+ structure,
899
+ resolvedExpressions
834
900
  )
835
- return elementTag
901
+ return iterElementTag
902
+ }
903
+
904
+ if (elementNode.content.key in nodesLookup) {
905
+ return nodesLookup[elementNode.content.key]
836
906
  }
907
+
908
+ const generatedElementTag = await generateHtmlSyntax(
909
+ elementNode,
910
+ compName,
911
+ nodesLookup,
912
+ propDefinitions,
913
+ stateDefinitions,
914
+ subComponentOptions,
915
+ structure,
916
+ resolvedExpressions
917
+ )
918
+ return generatedElementTag
837
919
  }
838
920
 
839
921
  const spanTagWrapper = HASTBuilders.createHTMLNode('span')
@@ -958,13 +1040,15 @@ const handleAttributes = (
958
1040
  content.referenceType === 'prop' ? propDefinitions : stateDefinitions
959
1041
  )
960
1042
 
961
- const extractedValue = String(
962
- extractDefaultValueFromRefPath(value.defaultValue, content.refPath)
963
- )
1043
+ const extracted = extractDefaultValueFromRefPath(value.defaultValue, content.refPath)
1044
+ const extractedValue = String(extracted)
964
1045
 
965
- if ((elementType === 'img' || elementType === 'video') && attrKey === 'src') {
1046
+ if (
1047
+ (elementType === 'img' || elementType === 'video') &&
1048
+ attrKey === 'src' &&
1049
+ !extractedValue.startsWith('http')
1050
+ ) {
966
1051
  const path = join(relative(join(...outputOptions.folderPath), './'), extractedValue)
967
-
968
1052
  HASTUtils.addAttributeToNode(htmlNode, attrKey, path)
969
1053
  break
970
1054
  }
@@ -1057,8 +1141,25 @@ const getValueFromReference = (
1057
1141
  const extractDefaultValueFromRefPath = (
1058
1142
  propDefaultValue: PropDefaultValueTypes,
1059
1143
  refPath?: string[]
1060
- ) => {
1061
- if (typeof propDefaultValue !== 'object' || !refPath?.length) {
1144
+ ): PropDefaultValueTypes => {
1145
+ if (!refPath || refPath.length === 0) {
1146
+ return propDefaultValue
1147
+ }
1148
+
1149
+ // Directly handle array indexing for the first segment when applicable
1150
+ if (Array.isArray(propDefaultValue)) {
1151
+ const [first, ...rest] = refPath
1152
+ const idx = Number(first)
1153
+ if (!Number.isNaN(idx) && idx >= 0 && idx < propDefaultValue.length) {
1154
+ const nextVal = propDefaultValue[idx] as PropDefaultValueTypes
1155
+ if (rest.length === 0) {
1156
+ return nextVal
1157
+ }
1158
+ return extractDefaultValueFromRefPath(nextVal, rest)
1159
+ }
1160
+ }
1161
+
1162
+ if (typeof propDefaultValue !== 'object') {
1062
1163
  return propDefaultValue
1063
1164
  }
1064
1165