@teleporthq/teleport-plugin-html-base-component 0.38.5 → 0.38.9
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/node-handlers.d.ts +9 -2
- package/dist/cjs/node-handlers.d.ts.map +1 -1
- package/dist/cjs/node-handlers.js +156 -28
- package/dist/cjs/node-handlers.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/node-handlers.d.ts +9 -2
- package/dist/esm/node-handlers.d.ts.map +1 -1
- package/dist/esm/node-handlers.js +156 -28
- package/dist/esm/node-handlers.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/src/node-handlers.ts +205 -32
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teleporthq/teleport-plugin-html-base-component",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.9",
|
|
4
4
|
"description": "A plugin for handling the skeleton/baseline of a base html component",
|
|
5
5
|
"author": "teleportHQ",
|
|
6
6
|
"license": "MIT",
|
|
@@ -24,11 +24,11 @@
|
|
|
24
24
|
"build": "tsc -p tsconfig.json && tsc -p tsconfig.json --module commonjs --outDir dist/cjs"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@teleporthq/teleport-plugin-common": "^0.38.
|
|
28
|
-
"@teleporthq/teleport-plugin-css": "^0.38.
|
|
27
|
+
"@teleporthq/teleport-plugin-common": "^0.38.9",
|
|
28
|
+
"@teleporthq/teleport-plugin-css": "^0.38.9",
|
|
29
29
|
"@teleporthq/teleport-shared": "^0.38.3",
|
|
30
30
|
"@teleporthq/teleport-types": "^0.38.3",
|
|
31
31
|
"@teleporthq/teleport-uidl-builders": "^0.38.3"
|
|
32
32
|
},
|
|
33
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "a0c0698b2c4f14e9e3c4cbe62f9e57d231a6c2e4"
|
|
34
34
|
}
|
package/src/node-handlers.ts
CHANGED
|
@@ -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'
|
|
@@ -45,23 +46,21 @@ const isValidURL = (url: string) => {
|
|
|
45
46
|
|
|
46
47
|
const addNodeToLookup = (
|
|
47
48
|
key: string,
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
nodesLoookup: Record<string, HastNode | HastText>,
|
|
51
|
-
hierarchy: string[] = []
|
|
49
|
+
tag: HastNode | HastText | Array<HastNode | HastText>,
|
|
50
|
+
nodesLoookup: Record<string, HastNode | HastText | Array<HastNode | HastText>>
|
|
52
51
|
) => {
|
|
53
52
|
// In html code-generation we combine the nodes of the component that is being consumed with the current component.
|
|
54
53
|
// As html can't load the component at runtime like react or any other frameworks. So, we merge the component as a standalone
|
|
55
54
|
// component in the current component.
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
const currentLookup = nodesLoookup[key]
|
|
56
|
+
if (currentLookup) {
|
|
57
|
+
if (Array.isArray(currentLookup)) {
|
|
58
|
+
Array.isArray(tag) ? currentLookup.push(...tag) : currentLookup.push(tag)
|
|
59
|
+
} else {
|
|
60
|
+
nodesLoookup[key] = Array.isArray(tag) ? [currentLookup, ...tag] : [currentLookup, tag]
|
|
61
|
+
}
|
|
60
62
|
|
|
61
|
-
|
|
62
|
-
Received \n\n ${JSON.stringify(tag)}\n ${JSON.stringify(node)}
|
|
63
|
-
Existing \n\n ${JSON.stringify(nodesLoookup[key])} \n\n`
|
|
64
|
-
)
|
|
63
|
+
return
|
|
65
64
|
}
|
|
66
65
|
|
|
67
66
|
nodesLoookup[key] = tag
|
|
@@ -70,7 +69,7 @@ Existing \n\n ${JSON.stringify(nodesLoookup[key])} \n\n`
|
|
|
70
69
|
type NodeToHTML<NodeType, ReturnType> = (
|
|
71
70
|
node: NodeType,
|
|
72
71
|
componentName: string,
|
|
73
|
-
nodesLookup: Record<string, HastNode | HastText
|
|
72
|
+
nodesLookup: Record<string, HastNode | HastText | Array<HastNode | HastText>>,
|
|
74
73
|
propDefinitions: Record<string, UIDLPropDefinition>,
|
|
75
74
|
stateDefinitions: Record<string, UIDLStateDefinition>,
|
|
76
75
|
subComponentOptions: {
|
|
@@ -82,17 +81,28 @@ type NodeToHTML<NodeType, ReturnType> = (
|
|
|
82
81
|
dependencies: Record<string, UIDLDependency>
|
|
83
82
|
options: GeneratorOptions
|
|
84
83
|
outputOptions: UIDLComponentOutputOptions
|
|
84
|
+
},
|
|
85
|
+
/**
|
|
86
|
+
* This param is just to be able to handle CMS array mappers/Repeater nodes. A bit hacky, better support should be implemented
|
|
87
|
+
*/
|
|
88
|
+
resolvedExpressions?: {
|
|
89
|
+
expressions: Record<string, UIDLPropDefinition>
|
|
90
|
+
currentIndex: number
|
|
85
91
|
}
|
|
86
92
|
) => ReturnType
|
|
87
93
|
|
|
88
|
-
export const generateHtmlSyntax: NodeToHTML<
|
|
94
|
+
export const generateHtmlSyntax: NodeToHTML<
|
|
95
|
+
UIDLNode,
|
|
96
|
+
Promise<HastNode | HastText | Array<HastNode | HastText>>
|
|
97
|
+
> = async (
|
|
89
98
|
node,
|
|
90
99
|
compName,
|
|
91
100
|
nodesLookup,
|
|
92
101
|
propDefinitions,
|
|
93
102
|
stateDefinitions,
|
|
94
103
|
subComponentOptions,
|
|
95
|
-
structure
|
|
104
|
+
structure,
|
|
105
|
+
resolvedExpressions
|
|
96
106
|
) => {
|
|
97
107
|
switch (node.type) {
|
|
98
108
|
case 'inject':
|
|
@@ -113,7 +123,8 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
|
|
|
113
123
|
propDefinitions,
|
|
114
124
|
stateDefinitions,
|
|
115
125
|
subComponentOptions,
|
|
116
|
-
structure
|
|
126
|
+
structure,
|
|
127
|
+
resolvedExpressions
|
|
117
128
|
)
|
|
118
129
|
return elementNode
|
|
119
130
|
|
|
@@ -186,7 +197,8 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
|
|
|
186
197
|
propDefinitions,
|
|
187
198
|
stateDefinitions,
|
|
188
199
|
subComponentOptions,
|
|
189
|
-
structure
|
|
200
|
+
structure,
|
|
201
|
+
resolvedExpressions
|
|
190
202
|
)
|
|
191
203
|
}
|
|
192
204
|
} catch (error) {
|
|
@@ -202,9 +214,40 @@ export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
|
|
|
202
214
|
}
|
|
203
215
|
|
|
204
216
|
case 'expr':
|
|
217
|
+
const content = node.content.split('?.')
|
|
218
|
+
|
|
219
|
+
if (resolvedExpressions && resolvedExpressions.expressions?.[content[0] || '']) {
|
|
220
|
+
const uidlDynamicRef: UIDLDynamicReference = {
|
|
221
|
+
type: 'dynamic',
|
|
222
|
+
content: {
|
|
223
|
+
referenceType: 'prop',
|
|
224
|
+
refPath: [resolvedExpressions.currentIndex.toString(), ...content.slice(1)],
|
|
225
|
+
id: content[0],
|
|
226
|
+
},
|
|
227
|
+
}
|
|
228
|
+
const generatedNode = await generateDynamicNode(
|
|
229
|
+
uidlDynamicRef,
|
|
230
|
+
compName,
|
|
231
|
+
nodesLookup,
|
|
232
|
+
resolvedExpressions.expressions,
|
|
233
|
+
stateDefinitions,
|
|
234
|
+
subComponentOptions,
|
|
235
|
+
structure
|
|
236
|
+
)
|
|
237
|
+
return generatedNode
|
|
238
|
+
}
|
|
239
|
+
|
|
205
240
|
return HASTBuilders.createComment('Expressions are not supported in HTML')
|
|
206
241
|
case 'cms-list-repeater':
|
|
207
|
-
return
|
|
242
|
+
return generateRepeaterNode(
|
|
243
|
+
node,
|
|
244
|
+
compName,
|
|
245
|
+
nodesLookup,
|
|
246
|
+
propDefinitions,
|
|
247
|
+
stateDefinitions,
|
|
248
|
+
subComponentOptions,
|
|
249
|
+
structure
|
|
250
|
+
)
|
|
208
251
|
default:
|
|
209
252
|
throw new HTMLComponentGeneratorError(
|
|
210
253
|
`generateHtmlSyntax encountered a node of unsupported type: ${JSON.stringify(
|
|
@@ -250,7 +293,10 @@ const getValueType = (value: UIDLPropDefinition['defaultValue']) => {
|
|
|
250
293
|
}
|
|
251
294
|
}
|
|
252
295
|
|
|
253
|
-
const
|
|
296
|
+
const generateRepeaterNode: NodeToHTML<
|
|
297
|
+
UIDLCMSListRepeaterNode,
|
|
298
|
+
Promise<HastNode | HastText>
|
|
299
|
+
> = async (
|
|
254
300
|
node,
|
|
255
301
|
compName,
|
|
256
302
|
nodesLookup,
|
|
@@ -258,6 +304,110 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
|
|
|
258
304
|
stateDefinitions,
|
|
259
305
|
subComponentOptions,
|
|
260
306
|
structure
|
|
307
|
+
) => {
|
|
308
|
+
const { nodes } = node.content
|
|
309
|
+
|
|
310
|
+
const contextId = node.content.renderPropIdentifier
|
|
311
|
+
const sourceValue = node.content.source
|
|
312
|
+
let propDef =
|
|
313
|
+
propDefinitions[
|
|
314
|
+
Object.keys(propDefinitions).find((propKey) => sourceValue.includes(propKey)) || ''
|
|
315
|
+
]
|
|
316
|
+
|
|
317
|
+
if (!propDef || !Array.isArray(propDef.defaultValue)) {
|
|
318
|
+
// If no prop is found we might have a static source value
|
|
319
|
+
try {
|
|
320
|
+
const parsedSource = JSON.parse(sourceValue)
|
|
321
|
+
propDef = {
|
|
322
|
+
defaultValue: parsedSource,
|
|
323
|
+
id: contextId,
|
|
324
|
+
type: 'array',
|
|
325
|
+
}
|
|
326
|
+
} catch {
|
|
327
|
+
// Silent fail
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
// We do the check again to keep typescript happy, otherwise this could be in catch
|
|
332
|
+
if (!propDef || !Array.isArray(propDef.defaultValue)) {
|
|
333
|
+
return HASTBuilders.createComment(
|
|
334
|
+
'CMS Array Mapper/Repeater not supported in HTML without a prop source'
|
|
335
|
+
)
|
|
336
|
+
}
|
|
337
|
+
propDefinitions[contextId] = propDef
|
|
338
|
+
|
|
339
|
+
const elementNode = HASTBuilders.createHTMLNode('div')
|
|
340
|
+
node.content.nodes.list.content.style = { display: { type: 'static', content: 'contents' } }
|
|
341
|
+
if (node.content.nodes.empty) {
|
|
342
|
+
node.content.nodes.empty.content.style = { display: { type: 'static', content: 'contents' } }
|
|
343
|
+
}
|
|
344
|
+
// Empty case
|
|
345
|
+
if (propDef.defaultValue.length === 0) {
|
|
346
|
+
const emptyChildren = nodes.empty.content.children
|
|
347
|
+
if (emptyChildren) {
|
|
348
|
+
for (const child of emptyChildren) {
|
|
349
|
+
const childTag = await generateHtmlSyntax(
|
|
350
|
+
child,
|
|
351
|
+
compName,
|
|
352
|
+
nodesLookup,
|
|
353
|
+
propDefinitions,
|
|
354
|
+
stateDefinitions,
|
|
355
|
+
subComponentOptions,
|
|
356
|
+
structure
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
if (typeof childTag === 'string') {
|
|
360
|
+
HASTUtils.addTextNode(elementNode, childTag)
|
|
361
|
+
} else {
|
|
362
|
+
HASTUtils.addChildNode(elementNode, childTag as HastNode)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
addNodeToLookup(`${node.content.nodes.empty.content.key}`, elementNode, nodesLookup)
|
|
368
|
+
return elementNode
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
const listChildren = nodes.list.content.children
|
|
372
|
+
if (listChildren) {
|
|
373
|
+
for (let index = 0; index < propDef.defaultValue.length; index++) {
|
|
374
|
+
for (const child of listChildren) {
|
|
375
|
+
const childTag = await generateHtmlSyntax(
|
|
376
|
+
child,
|
|
377
|
+
compName,
|
|
378
|
+
nodesLookup,
|
|
379
|
+
propDefinitions,
|
|
380
|
+
stateDefinitions,
|
|
381
|
+
subComponentOptions,
|
|
382
|
+
structure,
|
|
383
|
+
{ currentIndex: index, expressions: { [contextId]: propDef } }
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
if (typeof childTag === 'string') {
|
|
387
|
+
HASTUtils.addTextNode(elementNode, childTag)
|
|
388
|
+
} else {
|
|
389
|
+
HASTUtils.addChildNode(elementNode, childTag as HastNode)
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
addNodeToLookup(`${node.content.nodes.list.content.key}`, elementNode, nodesLookup)
|
|
396
|
+
return elementNode
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const generateElementNode: NodeToHTML<
|
|
400
|
+
UIDLElementNode,
|
|
401
|
+
Promise<HastNode | HastText | Array<HastNode | HastText>>
|
|
402
|
+
> = async (
|
|
403
|
+
node,
|
|
404
|
+
compName,
|
|
405
|
+
nodesLookup,
|
|
406
|
+
propDefinitions,
|
|
407
|
+
stateDefinitions,
|
|
408
|
+
subComponentOptions,
|
|
409
|
+
structure,
|
|
410
|
+
resolvedExpressions
|
|
261
411
|
) => {
|
|
262
412
|
const {
|
|
263
413
|
elementType,
|
|
@@ -271,7 +421,6 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
|
|
|
271
421
|
if (dependency && (dependency as UIDLDependency)?.type === 'local') {
|
|
272
422
|
const compTag = await generateComponentContent(
|
|
273
423
|
node,
|
|
274
|
-
compName,
|
|
275
424
|
nodesLookup,
|
|
276
425
|
propDefinitions,
|
|
277
426
|
stateDefinitions,
|
|
@@ -301,7 +450,8 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
|
|
|
301
450
|
propDefinitions,
|
|
302
451
|
stateDefinitions,
|
|
303
452
|
subComponentOptions,
|
|
304
|
-
structure
|
|
453
|
+
structure,
|
|
454
|
+
resolvedExpressions
|
|
305
455
|
)
|
|
306
456
|
|
|
307
457
|
if (typeof childTag === 'string') {
|
|
@@ -332,16 +482,17 @@ const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTe
|
|
|
332
482
|
propDefinitions,
|
|
333
483
|
stateDefinitions,
|
|
334
484
|
structure.options.projectRouteDefinition,
|
|
335
|
-
structure.outputOptions
|
|
485
|
+
structure.outputOptions,
|
|
486
|
+
resolvedExpressions?.currentIndex
|
|
336
487
|
)
|
|
337
488
|
|
|
338
|
-
addNodeToLookup(node.content.key,
|
|
489
|
+
addNodeToLookup(node.content.key, elementNode, nodesLookup)
|
|
339
490
|
return elementNode
|
|
340
491
|
}
|
|
341
492
|
|
|
342
493
|
const createLookupTable = (
|
|
343
494
|
component: ComponentUIDL,
|
|
344
|
-
nodesLookup: Record<string, HastNode | HastText
|
|
495
|
+
nodesLookup: Record<string, HastNode | HastText | Array<HastNode | HastText>>
|
|
345
496
|
): ElementsLookup => {
|
|
346
497
|
const lookup: ElementsLookup = {}
|
|
347
498
|
for (const node of Object.keys(nodesLookup)) {
|
|
@@ -356,8 +507,7 @@ const createLookupTable = (
|
|
|
356
507
|
|
|
357
508
|
const generateComponentContent = async (
|
|
358
509
|
node: UIDLElementNode,
|
|
359
|
-
|
|
360
|
-
nodesLookup: Record<string, HastNode | HastText>,
|
|
510
|
+
nodesLookup: Record<string, HastNode | HastText | Array<HastNode | HastText>>,
|
|
361
511
|
propDefinitions: Record<string, UIDLPropDefinition>,
|
|
362
512
|
stateDefinitions: Record<string, UIDLStateDefinition>,
|
|
363
513
|
subComponentOptions: {
|
|
@@ -505,7 +655,7 @@ const generateComponentContent = async (
|
|
|
505
655
|
propsForInstance[propKey] = combinedStates[propKey]
|
|
506
656
|
break
|
|
507
657
|
case 'expr':
|
|
508
|
-
// Ignore expr type attributes in html for the time being.
|
|
658
|
+
// Ignore expr type attributes in html comp instances for the time being.
|
|
509
659
|
break
|
|
510
660
|
default:
|
|
511
661
|
throw new Error(
|
|
@@ -625,11 +775,14 @@ const generateComponentContent = async (
|
|
|
625
775
|
}
|
|
626
776
|
})
|
|
627
777
|
|
|
628
|
-
addNodeToLookup(node.content.key,
|
|
778
|
+
addNodeToLookup(node.content.key, compTag, nodesLookup)
|
|
629
779
|
return compTag
|
|
630
780
|
}
|
|
631
781
|
|
|
632
|
-
const generateDynamicNode: NodeToHTML<
|
|
782
|
+
const generateDynamicNode: NodeToHTML<
|
|
783
|
+
UIDLDynamicReference,
|
|
784
|
+
Promise<HastNode | HastText | Array<HastNode | HastText>>
|
|
785
|
+
> = async (
|
|
633
786
|
node,
|
|
634
787
|
compName,
|
|
635
788
|
nodesLookup,
|
|
@@ -637,7 +790,7 @@ const generateDynamicNode: NodeToHTML<UIDLDynamicReference, Promise<HastNode | H
|
|
|
637
790
|
stateDefinitions,
|
|
638
791
|
subComponentOptions,
|
|
639
792
|
structure
|
|
640
|
-
): Promise<HastNode | HastText
|
|
793
|
+
): Promise<HastNode | HastText | Array<HastNode | HastText>> => {
|
|
641
794
|
if (node.content.referenceType === 'locale') {
|
|
642
795
|
const localeTag = HASTBuilders.createHTMLNode('span')
|
|
643
796
|
const commentNode = HASTBuilders.createComment(`Content for locale ${node.content.id}`)
|
|
@@ -727,7 +880,8 @@ const handleAttributes = (
|
|
|
727
880
|
propDefinitions: Record<string, UIDLPropDefinition>,
|
|
728
881
|
stateDefinitions: Record<string, UIDLStateDefinition>,
|
|
729
882
|
routeDefinitions: UIDLRouteDefinitions,
|
|
730
|
-
outputOptions: UIDLComponentOutputOptions
|
|
883
|
+
outputOptions: UIDLComponentOutputOptions,
|
|
884
|
+
currentIndex?: number
|
|
731
885
|
) => {
|
|
732
886
|
for (const attrKey of Object.keys(attrs)) {
|
|
733
887
|
const attrValue = attrs[attrKey]
|
|
@@ -820,9 +974,28 @@ const handleAttributes = (
|
|
|
820
974
|
break
|
|
821
975
|
}
|
|
822
976
|
|
|
977
|
+
case 'expr': {
|
|
978
|
+
const fullPath = content.split('?.')
|
|
979
|
+
const prop = propDefinitions[fullPath?.[0] || '']
|
|
980
|
+
|
|
981
|
+
if (!prop) {
|
|
982
|
+
break
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
const path =
|
|
986
|
+
typeof currentIndex === 'number'
|
|
987
|
+
? [currentIndex.toString(), ...fullPath.slice(1)]
|
|
988
|
+
: fullPath.slice(1)
|
|
989
|
+
const value = extractDefaultValueFromRefPath(prop.defaultValue, path)
|
|
990
|
+
if (!value) {
|
|
991
|
+
break
|
|
992
|
+
}
|
|
993
|
+
HASTUtils.addAttributeToNode(htmlNode, attrKey, String(value))
|
|
994
|
+
break
|
|
995
|
+
}
|
|
996
|
+
|
|
823
997
|
case 'element':
|
|
824
998
|
case 'import':
|
|
825
|
-
case 'expr':
|
|
826
999
|
case 'object':
|
|
827
1000
|
break
|
|
828
1001
|
|