@teleporthq/teleport-plugin-html-base-component 0.38.0-alpha.0 → 0.38.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.
- package/__tests__/index.ts +26 -20
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +40 -17
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/node-handlers.d.ts +5 -4
- package/dist/cjs/node-handlers.d.ts.map +1 -1
- package/dist/cjs/node-handlers.js +390 -144
- package/dist/cjs/node-handlers.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +41 -18
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node-handlers.d.ts +5 -4
- package/dist/esm/node-handlers.d.ts.map +1 -1
- package/dist/esm/node-handlers.js +390 -144
- package/dist/esm/node-handlers.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +7 -7
- package/src/index.ts +55 -21
- package/src/node-handlers.ts +566 -166
package/src/node-handlers.ts
CHANGED
|
@@ -19,37 +19,79 @@ import {
|
|
|
19
19
|
UIDLRouteDefinitions,
|
|
20
20
|
ComponentPlugin,
|
|
21
21
|
ComponentStructure,
|
|
22
|
+
UIDLComponentOutputOptions,
|
|
23
|
+
UIDLElement,
|
|
24
|
+
ElementsLookup,
|
|
25
|
+
UIDLConditionalNode,
|
|
26
|
+
PropDefaultValueTypes,
|
|
22
27
|
} from '@teleporthq/teleport-types'
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
28
|
+
import { join, relative } from 'path'
|
|
29
|
+
import { HASTBuilders, HASTUtils, ASTUtils } from '@teleporthq/teleport-plugin-common'
|
|
30
|
+
import { GenericUtils, StringUtils, UIDLUtils } from '@teleporthq/teleport-shared'
|
|
25
31
|
import { staticNode } from '@teleporthq/teleport-uidl-builders'
|
|
26
32
|
import { createCSSPlugin } from '@teleporthq/teleport-plugin-css'
|
|
33
|
+
import { generateUniqueKeys, createNodesLookup } from '@teleporthq/teleport-uidl-resolver'
|
|
27
34
|
import { DEFAULT_COMPONENT_CHUNK_NAME } from './constants'
|
|
28
35
|
|
|
36
|
+
const isValidURL = (url: string) => {
|
|
37
|
+
try {
|
|
38
|
+
/* tslint:disable:no-unused-expression */
|
|
39
|
+
new URL(url)
|
|
40
|
+
return true
|
|
41
|
+
} catch (error) {
|
|
42
|
+
return false
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const addNodeToLookup = (
|
|
47
|
+
key: string,
|
|
48
|
+
node: UIDLElementNode,
|
|
49
|
+
tag: HastNode | HastText,
|
|
50
|
+
nodesLoookup: Record<string, HastNode | HastText>,
|
|
51
|
+
hierarchy: string[] = []
|
|
52
|
+
) => {
|
|
53
|
+
// In html code-generation we combine the nodes of the component that is being consumed with the current component.
|
|
54
|
+
// As html can't load the component at runtime like react or any other frameworks. So, we merge the component as a standalone
|
|
55
|
+
// component in the current component.
|
|
56
|
+
if (nodesLoookup[key]) {
|
|
57
|
+
throw new HTMLComponentGeneratorError(
|
|
58
|
+
`\n${hierarchy.join(' -> ')} \n
|
|
59
|
+
Duplicate key found in nodesLookup: ${node.content.key} \n
|
|
60
|
+
|
|
61
|
+
A node with the same key already exists\n
|
|
62
|
+
Received \n\n ${JSON.stringify(tag)}\n ${JSON.stringify(node)}
|
|
63
|
+
Existing \n\n ${JSON.stringify(nodesLoookup[key])} \n\n`
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
nodesLoookup[key] = tag
|
|
68
|
+
}
|
|
69
|
+
|
|
29
70
|
type NodeToHTML<NodeType, ReturnType> = (
|
|
30
71
|
node: NodeType,
|
|
31
|
-
|
|
72
|
+
componentName: string,
|
|
73
|
+
nodesLookup: Record<string, HastNode | HastText>,
|
|
32
74
|
propDefinitions: Record<string, UIDLPropDefinition>,
|
|
33
75
|
stateDefinitions: Record<string, UIDLStateDefinition>,
|
|
34
76
|
subComponentOptions: {
|
|
35
77
|
externals: Record<string, ComponentUIDL>
|
|
36
78
|
plugins: ComponentPlugin[]
|
|
37
79
|
},
|
|
38
|
-
routeDefinitions: UIDLRouteDefinitions,
|
|
39
80
|
structure: {
|
|
40
81
|
chunks: ChunkDefinition[]
|
|
41
82
|
dependencies: Record<string, UIDLDependency>
|
|
42
83
|
options: GeneratorOptions
|
|
84
|
+
outputOptions: UIDLComponentOutputOptions
|
|
43
85
|
}
|
|
44
86
|
) => ReturnType
|
|
45
87
|
|
|
46
|
-
export const
|
|
88
|
+
export const generateHtmlSyntax: NodeToHTML<UIDLNode, Promise<HastNode | HastText>> = async (
|
|
47
89
|
node,
|
|
48
|
-
|
|
90
|
+
compName,
|
|
91
|
+
nodesLookup,
|
|
49
92
|
propDefinitions,
|
|
50
93
|
stateDefinitions,
|
|
51
94
|
subComponentOptions,
|
|
52
|
-
routeDefinitions,
|
|
53
95
|
structure
|
|
54
96
|
) => {
|
|
55
97
|
switch (node.type) {
|
|
@@ -64,26 +106,103 @@ export const generateHtmlSynatx: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
|
|
|
64
106
|
return HASTBuilders.createHTMLNode(node.type)
|
|
65
107
|
|
|
66
108
|
case 'element':
|
|
67
|
-
|
|
109
|
+
const elementNode = await generateElementNode(
|
|
68
110
|
node,
|
|
69
|
-
|
|
111
|
+
compName,
|
|
112
|
+
nodesLookup,
|
|
70
113
|
propDefinitions,
|
|
71
114
|
stateDefinitions,
|
|
72
115
|
subComponentOptions,
|
|
73
|
-
routeDefinitions,
|
|
74
116
|
structure
|
|
75
117
|
)
|
|
118
|
+
return elementNode
|
|
76
119
|
|
|
77
120
|
case 'dynamic':
|
|
78
|
-
|
|
121
|
+
const dynamicNode = await generateDynamicNode(
|
|
79
122
|
node,
|
|
80
|
-
|
|
123
|
+
compName,
|
|
124
|
+
nodesLookup,
|
|
81
125
|
propDefinitions,
|
|
82
126
|
stateDefinitions,
|
|
83
127
|
subComponentOptions,
|
|
84
|
-
routeDefinitions,
|
|
85
128
|
structure
|
|
86
129
|
)
|
|
130
|
+
return dynamicNode
|
|
131
|
+
|
|
132
|
+
case 'conditional':
|
|
133
|
+
const conditionalNodeComment = HASTBuilders.createComment(
|
|
134
|
+
'Conditional nodes are not supported in HTML'
|
|
135
|
+
)
|
|
136
|
+
const {
|
|
137
|
+
value: staticValue,
|
|
138
|
+
reference,
|
|
139
|
+
condition: { conditions, matchingCriteria },
|
|
140
|
+
} = node.content
|
|
141
|
+
|
|
142
|
+
if (reference.type !== 'dynamic') {
|
|
143
|
+
return conditionalNodeComment
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const {
|
|
147
|
+
content: { referenceType, id, refPath },
|
|
148
|
+
} = reference
|
|
149
|
+
|
|
150
|
+
switch (referenceType) {
|
|
151
|
+
case 'prop': {
|
|
152
|
+
const usedProp = propDefinitions[id]
|
|
153
|
+
if (usedProp === undefined || usedProp.defaultValue === undefined) {
|
|
154
|
+
return conditionalNodeComment
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
let defaultValue = usedProp.defaultValue
|
|
158
|
+
for (const path of refPath) {
|
|
159
|
+
defaultValue = (defaultValue as Record<string, unknown[]>)?.[path]
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
// Safety measure in case no value is found
|
|
163
|
+
if (!defaultValue) {
|
|
164
|
+
defaultValue = usedProp.defaultValue
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Since we know the operand and the default value from the prop.
|
|
168
|
+
// We can try building the condition and check if the condition is true or false.
|
|
169
|
+
// @todo: You can only use a 'value' in UIDL or 'conditions' but not both.
|
|
170
|
+
// UIDL validations need to be improved on this aspect.
|
|
171
|
+
const dynamicConditions = createConditionalStatement(
|
|
172
|
+
staticValue !== undefined ? [{ operand: staticValue, operation: '===' }] : conditions,
|
|
173
|
+
defaultValue
|
|
174
|
+
)
|
|
175
|
+
const matchCondition = matchingCriteria && matchingCriteria === 'all' ? '&&' : '||'
|
|
176
|
+
const conditionString = dynamicConditions.join(` ${matchCondition} `)
|
|
177
|
+
|
|
178
|
+
try {
|
|
179
|
+
// tslint:disable-next-line function-constructor
|
|
180
|
+
const isConditionPassing = new Function(`return ${conditionString}`)()
|
|
181
|
+
if (isConditionPassing) {
|
|
182
|
+
return generateHtmlSyntax(
|
|
183
|
+
node.content.node,
|
|
184
|
+
compName,
|
|
185
|
+
nodesLookup,
|
|
186
|
+
propDefinitions,
|
|
187
|
+
stateDefinitions,
|
|
188
|
+
subComponentOptions,
|
|
189
|
+
structure
|
|
190
|
+
)
|
|
191
|
+
}
|
|
192
|
+
} catch (error) {
|
|
193
|
+
return conditionalNodeComment
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return conditionalNodeComment
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
case 'state':
|
|
200
|
+
default:
|
|
201
|
+
return conditionalNodeComment
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
case 'expr':
|
|
205
|
+
return HASTBuilders.createComment('Expressions are not supported in HTML')
|
|
87
206
|
|
|
88
207
|
default:
|
|
89
208
|
throw new HTMLComponentGeneratorError(
|
|
@@ -96,13 +215,47 @@ export const generateHtmlSynatx: NodeToHTML<UIDLNode, Promise<HastNode | HastTex
|
|
|
96
215
|
}
|
|
97
216
|
}
|
|
98
217
|
|
|
99
|
-
const
|
|
218
|
+
const createConditionalStatement = (
|
|
219
|
+
conditions: UIDLConditionalNode['content']['condition']['conditions'],
|
|
220
|
+
leftOperand: UIDLPropDefinition['defaultValue']
|
|
221
|
+
) => {
|
|
222
|
+
return conditions.map((condition) => {
|
|
223
|
+
const { operation, operand } = condition
|
|
224
|
+
|
|
225
|
+
if (operand === undefined) {
|
|
226
|
+
return `${ASTUtils.convertToUnaryOperator(operation)}${getValueType(operand)}`
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return `${getValueType(leftOperand)} ${ASTUtils.convertToBinaryOperator(
|
|
230
|
+
operation
|
|
231
|
+
)} ${getValueType(operand)}`
|
|
232
|
+
})
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const getValueType = (value: UIDLPropDefinition['defaultValue']) => {
|
|
236
|
+
const valueType = typeof value
|
|
237
|
+
switch (valueType) {
|
|
238
|
+
case 'string':
|
|
239
|
+
return `"${value}"`
|
|
240
|
+
case 'number':
|
|
241
|
+
return value
|
|
242
|
+
case 'boolean':
|
|
243
|
+
return value
|
|
244
|
+
default:
|
|
245
|
+
throw new HTMLComponentGeneratorError(
|
|
246
|
+
`Conditional node received an operand of type ${valueType} \n
|
|
247
|
+
Received ${JSON.stringify(value)}`
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const generateElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastText>> = async (
|
|
100
253
|
node,
|
|
101
|
-
|
|
254
|
+
compName,
|
|
255
|
+
nodesLookup,
|
|
102
256
|
propDefinitions,
|
|
103
257
|
stateDefinitions,
|
|
104
258
|
subComponentOptions,
|
|
105
|
-
routeDefinitions,
|
|
106
259
|
structure
|
|
107
260
|
) => {
|
|
108
261
|
const {
|
|
@@ -112,45 +265,44 @@ const generatElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTex
|
|
|
112
265
|
style = {},
|
|
113
266
|
referencedStyles = {},
|
|
114
267
|
dependency,
|
|
115
|
-
key,
|
|
116
268
|
} = node.content
|
|
117
|
-
|
|
118
|
-
const elementNode = HASTBuilders.createHTMLNode(elementType)
|
|
119
|
-
templatesLookUp[key] = elementNode
|
|
120
|
-
|
|
121
269
|
const { dependencies } = structure
|
|
122
|
-
if (dependency && (dependency as UIDLDependency)?.type !== 'local') {
|
|
123
|
-
dependencies[dependency.path] = dependency
|
|
124
|
-
}
|
|
125
|
-
|
|
126
270
|
if (dependency && (dependency as UIDLDependency)?.type === 'local') {
|
|
127
271
|
const compTag = await generateComponentContent(
|
|
128
272
|
node,
|
|
273
|
+
compName,
|
|
274
|
+
nodesLookup,
|
|
129
275
|
propDefinitions,
|
|
130
276
|
stateDefinitions,
|
|
131
277
|
subComponentOptions,
|
|
132
|
-
routeDefinitions,
|
|
133
278
|
structure
|
|
134
279
|
)
|
|
280
|
+
|
|
281
|
+
if ('tagName' in compTag) {
|
|
282
|
+
compTag.children.unshift(HASTBuilders.createComment(`${node.content.semanticType} component`))
|
|
283
|
+
}
|
|
284
|
+
|
|
135
285
|
return compTag
|
|
136
286
|
}
|
|
137
287
|
|
|
288
|
+
if (dependency && (dependency as UIDLDependency)?.type !== 'local') {
|
|
289
|
+
dependencies[dependency.path] = dependency
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const elementNode = HASTBuilders.createHTMLNode(elementType)
|
|
293
|
+
|
|
138
294
|
if (children) {
|
|
139
295
|
for (const child of children) {
|
|
140
|
-
const childTag = await
|
|
296
|
+
const childTag = await generateHtmlSyntax(
|
|
141
297
|
child,
|
|
142
|
-
|
|
298
|
+
compName,
|
|
299
|
+
nodesLookup,
|
|
143
300
|
propDefinitions,
|
|
144
301
|
stateDefinitions,
|
|
145
302
|
subComponentOptions,
|
|
146
|
-
routeDefinitions,
|
|
147
303
|
structure
|
|
148
304
|
)
|
|
149
305
|
|
|
150
|
-
if (!childTag) {
|
|
151
|
-
return
|
|
152
|
-
}
|
|
153
|
-
|
|
154
306
|
if (typeof childTag === 'string') {
|
|
155
307
|
HASTUtils.addTextNode(elementNode, childTag)
|
|
156
308
|
} else {
|
|
@@ -164,7 +316,6 @@ const generatElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTex
|
|
|
164
316
|
const refStyle = referencedStyles[styleRef]
|
|
165
317
|
if (refStyle.content.mapType === 'inlined') {
|
|
166
318
|
handleStyles(node, refStyle.content.styles, propDefinitions, stateDefinitions)
|
|
167
|
-
return
|
|
168
319
|
}
|
|
169
320
|
})
|
|
170
321
|
}
|
|
@@ -173,43 +324,66 @@ const generatElementNode: NodeToHTML<UIDLElementNode, Promise<HastNode | HastTex
|
|
|
173
324
|
handleStyles(node, style, propDefinitions, stateDefinitions)
|
|
174
325
|
}
|
|
175
326
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
327
|
+
handleAttributes(
|
|
328
|
+
elementType,
|
|
329
|
+
elementNode,
|
|
330
|
+
attrs,
|
|
331
|
+
propDefinitions,
|
|
332
|
+
stateDefinitions,
|
|
333
|
+
structure.options.projectRouteDefinition,
|
|
334
|
+
structure.outputOptions
|
|
335
|
+
)
|
|
179
336
|
|
|
337
|
+
addNodeToLookup(node.content.key, node, elementNode, nodesLookup, [compName])
|
|
180
338
|
return elementNode
|
|
181
339
|
}
|
|
182
340
|
|
|
341
|
+
const createLookupTable = (
|
|
342
|
+
component: ComponentUIDL,
|
|
343
|
+
nodesLookup: Record<string, HastNode | HastText>
|
|
344
|
+
): ElementsLookup => {
|
|
345
|
+
const lookup: ElementsLookup = {}
|
|
346
|
+
for (const node of Object.keys(nodesLookup)) {
|
|
347
|
+
lookup[node] = {
|
|
348
|
+
count: 1,
|
|
349
|
+
nextKey: '1',
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
createNodesLookup(component, lookup)
|
|
353
|
+
return lookup
|
|
354
|
+
}
|
|
355
|
+
|
|
183
356
|
const generateComponentContent = async (
|
|
184
357
|
node: UIDLElementNode,
|
|
358
|
+
compName: string,
|
|
359
|
+
nodesLookup: Record<string, HastNode | HastText>,
|
|
185
360
|
propDefinitions: Record<string, UIDLPropDefinition>,
|
|
186
361
|
stateDefinitions: Record<string, UIDLStateDefinition>,
|
|
187
362
|
subComponentOptions: {
|
|
188
363
|
externals: Record<string, ComponentUIDL>
|
|
189
364
|
plugins: ComponentPlugin[]
|
|
190
365
|
},
|
|
191
|
-
routeDefinitions: UIDLRouteDefinitions,
|
|
192
366
|
structure: {
|
|
193
367
|
chunks: ChunkDefinition[]
|
|
194
368
|
dependencies: Record<string, UIDLDependency>
|
|
195
369
|
options: GeneratorOptions
|
|
370
|
+
outputOptions: UIDLComponentOutputOptions
|
|
196
371
|
}
|
|
197
372
|
) => {
|
|
198
373
|
const { externals, plugins } = subComponentOptions
|
|
199
|
-
const { elementType, attrs = {},
|
|
374
|
+
const { elementType, attrs = {}, children = [] } = node.content
|
|
200
375
|
const { dependencies, chunks = [], options } = structure
|
|
201
|
-
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
throw new HTMLComponentGeneratorError(`${elementType} is not found from the externals. \n
|
|
207
|
-
Received ${JSON.stringify(Object.keys(externals), null, 2)}`)
|
|
376
|
+
// "Component" will not exist when generating a component because the resolver checks for illegal class names
|
|
377
|
+
const componentName = elementType === 'Component' ? 'AppComponent' : elementType
|
|
378
|
+
const component = externals[componentName]
|
|
379
|
+
if (component === undefined) {
|
|
380
|
+
throw new HTMLComponentGeneratorError(`${componentName} is missing from externals object`)
|
|
208
381
|
}
|
|
209
382
|
|
|
383
|
+
const componentClone = UIDLUtils.cloneObject<ComponentUIDL>(component)
|
|
384
|
+
|
|
210
385
|
if (children.length) {
|
|
211
|
-
|
|
212
|
-
UIDLUtils.traverseNodes(comp.node, (childNode, parentNode) => {
|
|
386
|
+
UIDLUtils.traverseNodes(componentClone.node, (childNode, parentNode) => {
|
|
213
387
|
if (childNode.type === 'slot' && parentNode.type === 'element') {
|
|
214
388
|
const nonSlotNodes = parentNode.content?.children?.filter((n) => n.type !== 'slot')
|
|
215
389
|
parentNode.content.children = [
|
|
@@ -219,6 +393,7 @@ const generateComponentContent = async (
|
|
|
219
393
|
content: {
|
|
220
394
|
key: 'custom-slot',
|
|
221
395
|
elementType: 'slot',
|
|
396
|
+
name: componentClone.name + 'slot',
|
|
222
397
|
style: {
|
|
223
398
|
display: {
|
|
224
399
|
type: 'static',
|
|
@@ -238,31 +413,49 @@ const generateComponentContent = async (
|
|
|
238
413
|
node.content.children = []
|
|
239
414
|
}
|
|
240
415
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
416
|
+
// In UIDL, we define only the link between a component and a page.
|
|
417
|
+
// We define this link using the UIDLLocalDependency approach.
|
|
418
|
+
// So, during the page resolution step, where we ideally generate the unique keys for the components.
|
|
419
|
+
// We can't generate the unique keys for the components because we don't have the full UIDL of the component.
|
|
420
|
+
// When we are using components in a page, the `addExternalComponents` step of the
|
|
421
|
+
// html-component-generator will add the full UIDL of the component to the externals object after resolving them.
|
|
422
|
+
// But when a component is used multiple number of times, we are basically using the same nodes again and again.
|
|
423
|
+
// Which indivates duplication. So, we create a lookup table of all the nodes present with us in the page
|
|
424
|
+
// And then pass it to the component to avoid any coilissions.
|
|
425
|
+
const lookupTableForCurrentPage = createLookupTable(componentClone, nodesLookup)
|
|
426
|
+
generateUniqueKeys(componentClone, lookupTableForCurrentPage)
|
|
427
|
+
|
|
428
|
+
// We are combining props of the current component
|
|
429
|
+
// with props of the component that we need to generate.
|
|
430
|
+
// Refer to line 309, for element props. We either pick from the attr of the current instance of component
|
|
431
|
+
// or from the propDefinitions of the component that we are generating.
|
|
432
|
+
// We don't need to keep passing the props of the current component to the child component and so on
|
|
433
|
+
// for the case of element nodes in attributes or propDefinitions.
|
|
434
|
+
const combinedProps: Record<string, UIDLPropDefinition> = {
|
|
435
|
+
...Object.keys(propDefinitions).reduce<Record<string, UIDLPropDefinition>>(
|
|
436
|
+
(acc: Record<string, UIDLPropDefinition>, propKey) => {
|
|
437
|
+
if (propDefinitions[propKey]?.type === 'element') {
|
|
438
|
+
return acc
|
|
249
439
|
}
|
|
250
|
-
|
|
251
|
-
acc
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
},
|
|
256
|
-
|
|
257
|
-
)
|
|
258
|
-
|
|
259
|
-
const combinedStates = { ...stateDefinitions, ...(comp?.stateDefinitions || {}) }
|
|
440
|
+
acc[propKey] = propDefinitions[propKey]
|
|
441
|
+
return acc
|
|
442
|
+
},
|
|
443
|
+
{}
|
|
444
|
+
),
|
|
445
|
+
...(componentClone?.propDefinitions || {}),
|
|
446
|
+
}
|
|
447
|
+
const combinedStates = { ...stateDefinitions, ...(componentClone?.stateDefinitions || {}) }
|
|
260
448
|
const statesForInstance = Object.keys(combinedStates).reduce(
|
|
261
449
|
(acc: Record<string, UIDLStateDefinition>, propKey) => {
|
|
262
|
-
|
|
450
|
+
const attr = attrs[propKey]
|
|
451
|
+
if (attr.type === 'object') {
|
|
452
|
+
throw new Error(`Object attributes are not supported in html exports`)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
if (attr) {
|
|
263
456
|
acc[propKey] = {
|
|
264
457
|
...combinedStates[propKey],
|
|
265
|
-
defaultValue:
|
|
458
|
+
defaultValue: attr?.content || combinedStates[propKey]?.defaultValue,
|
|
266
459
|
}
|
|
267
460
|
} else {
|
|
268
461
|
acc[propKey] = combinedStates[propKey]
|
|
@@ -273,43 +466,127 @@ const generateComponentContent = async (
|
|
|
273
466
|
{}
|
|
274
467
|
)
|
|
275
468
|
|
|
276
|
-
const
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
469
|
+
const propsForInstance: Record<string, UIDLPropDefinition> = {}
|
|
470
|
+
// this is where we check if the component we are conusming is actually passing any props to the instance.
|
|
471
|
+
// We check if we are passing any props and pick the value from the atrrs, if not we pick the value from the propDefinitions of
|
|
472
|
+
// the component instance that we are using here.
|
|
473
|
+
for (const propKey of Object.keys(combinedProps)) {
|
|
474
|
+
const attribute = attrs[propKey]
|
|
475
|
+
|
|
476
|
+
if (attribute?.type === 'element') {
|
|
477
|
+
propsForInstance[propKey] = {
|
|
478
|
+
...combinedProps[propKey],
|
|
479
|
+
defaultValue: attrs[propKey],
|
|
480
|
+
}
|
|
481
|
+
await generateHtmlSyntax(
|
|
482
|
+
attrs[propKey] as UIDLElementNode,
|
|
483
|
+
component.name,
|
|
484
|
+
nodesLookup,
|
|
485
|
+
propDefinitions,
|
|
486
|
+
stateDefinitions,
|
|
487
|
+
subComponentOptions,
|
|
488
|
+
structure
|
|
489
|
+
)
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
if (attribute?.type === 'dynamic') {
|
|
493
|
+
// When we are using a component instance in a component and the attribute
|
|
494
|
+
// that is passed to the component is of dynamic reference.
|
|
495
|
+
// If means, the component is redirecting the prop that is received to the prop of the component that it is consuming.
|
|
496
|
+
// In this case, we need to pass the value of the prop that is received to the prop of the component that it is consuming.
|
|
497
|
+
// And similary we do the same for the states.
|
|
498
|
+
switch (attribute.content.referenceType) {
|
|
499
|
+
case 'prop':
|
|
500
|
+
propsForInstance[propKey] = combinedProps[propKey]
|
|
501
|
+
break
|
|
502
|
+
case 'state':
|
|
503
|
+
propsForInstance[propKey] = combinedStates[propKey]
|
|
504
|
+
break
|
|
505
|
+
default:
|
|
506
|
+
throw new Error(
|
|
507
|
+
`ReferenceType ${attribute.content.referenceType} is not supported in HTML Export.`
|
|
508
|
+
)
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (attribute?.type === 'object') {
|
|
513
|
+
propsForInstance[propKey] = {
|
|
514
|
+
...combinedProps[propKey],
|
|
515
|
+
defaultValue: (attribute?.content as object) || combinedProps[propKey]?.defaultValue,
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
if (
|
|
520
|
+
attribute?.type !== 'dynamic' &&
|
|
521
|
+
attribute?.type !== 'element' &&
|
|
522
|
+
attribute?.type !== 'object'
|
|
523
|
+
) {
|
|
524
|
+
propsForInstance[propKey] = {
|
|
525
|
+
...combinedProps[propKey],
|
|
526
|
+
defaultValue: attribute?.content || combinedProps[propKey]?.defaultValue,
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
if (attribute === undefined) {
|
|
531
|
+
const propFromCurrentComponent = combinedProps[propKey]
|
|
532
|
+
if (propFromCurrentComponent.type === 'element' && propFromCurrentComponent.defaultValue) {
|
|
533
|
+
await generateHtmlSyntax(
|
|
534
|
+
propFromCurrentComponent.defaultValue as UIDLElementNode,
|
|
535
|
+
component.name,
|
|
536
|
+
nodesLookup,
|
|
537
|
+
propDefinitions,
|
|
538
|
+
stateDefinitions,
|
|
539
|
+
subComponentOptions,
|
|
540
|
+
structure
|
|
541
|
+
)
|
|
542
|
+
}
|
|
543
|
+
propsForInstance[propKey] = propFromCurrentComponent
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
let componentWrapper = StringUtils.camelCaseToDashCase(`${componentName}-wrapper`)
|
|
548
|
+
const isExistingNode = nodesLookup[componentWrapper]
|
|
549
|
+
if (isExistingNode !== undefined) {
|
|
550
|
+
componentWrapper = `${componentWrapper}-${StringUtils.generateRandomString()}`
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
const componentInstanceToGenerate: UIDLElementNode = {
|
|
554
|
+
type: 'element',
|
|
555
|
+
content: {
|
|
556
|
+
elementType: componentWrapper,
|
|
557
|
+
key: componentWrapper,
|
|
558
|
+
children: [componentClone.node],
|
|
559
|
+
style: {
|
|
560
|
+
display: {
|
|
561
|
+
type: 'static',
|
|
562
|
+
content: 'contents',
|
|
290
563
|
},
|
|
291
564
|
},
|
|
292
565
|
},
|
|
293
|
-
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const compTag = await generateHtmlSyntax(
|
|
569
|
+
componentInstanceToGenerate,
|
|
570
|
+
component.name,
|
|
571
|
+
nodesLookup,
|
|
294
572
|
propsForInstance,
|
|
295
573
|
statesForInstance,
|
|
296
574
|
subComponentOptions,
|
|
297
|
-
routeDefinitions,
|
|
298
575
|
structure
|
|
299
|
-
)
|
|
576
|
+
)
|
|
300
577
|
|
|
301
578
|
const cssPlugin = createCSSPlugin({
|
|
302
579
|
templateStyle: 'html',
|
|
303
580
|
templateChunkName: DEFAULT_COMPONENT_CHUNK_NAME,
|
|
304
581
|
declareDependency: 'import',
|
|
305
|
-
|
|
306
|
-
chunkName: comp.name,
|
|
582
|
+
chunkName: componentClone.name,
|
|
307
583
|
staticPropReferences: true,
|
|
308
584
|
})
|
|
309
585
|
|
|
310
586
|
const initialStructure: ComponentStructure = {
|
|
311
587
|
uidl: {
|
|
312
|
-
...
|
|
588
|
+
...componentClone,
|
|
589
|
+
node: componentInstanceToGenerate,
|
|
313
590
|
propDefinitions: propsForInstance,
|
|
314
591
|
stateDefinitions: statesForInstance,
|
|
315
592
|
},
|
|
@@ -321,7 +598,7 @@ const generateComponentContent = async (
|
|
|
321
598
|
linkAfter: [],
|
|
322
599
|
content: compTag,
|
|
323
600
|
meta: {
|
|
324
|
-
nodesLookup
|
|
601
|
+
nodesLookup,
|
|
325
602
|
},
|
|
326
603
|
},
|
|
327
604
|
],
|
|
@@ -337,41 +614,81 @@ const generateComponentContent = async (
|
|
|
337
614
|
Promise.resolve(initialStructure)
|
|
338
615
|
)
|
|
339
616
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
chunks.push(chunk)
|
|
344
|
-
}
|
|
345
|
-
})
|
|
346
|
-
} else {
|
|
347
|
-
const chunk = chunks.find((item) => item.name === comp.name)
|
|
348
|
-
if (!chunk) {
|
|
349
|
-
const styleChunk = result.chunks.find(
|
|
350
|
-
(item: ChunkDefinition) => item.fileType === FileType.CSS
|
|
351
|
-
)
|
|
352
|
-
if (!styleChunk) {
|
|
353
|
-
return
|
|
354
|
-
}
|
|
355
|
-
chunks.push(styleChunk)
|
|
617
|
+
result.chunks.forEach((chunk) => {
|
|
618
|
+
if (chunk.fileType === FileType.CSS) {
|
|
619
|
+
chunks.push(chunk)
|
|
356
620
|
}
|
|
357
|
-
}
|
|
621
|
+
})
|
|
358
622
|
|
|
623
|
+
addNodeToLookup(node.content.key, node, compTag, nodesLookup, [compName, component.name])
|
|
359
624
|
return compTag
|
|
360
625
|
}
|
|
361
626
|
|
|
362
|
-
const generateDynamicNode: NodeToHTML<UIDLDynamicReference, HastNode
|
|
627
|
+
const generateDynamicNode: NodeToHTML<UIDLDynamicReference, Promise<HastNode | HastText>> = async (
|
|
363
628
|
node,
|
|
364
|
-
|
|
629
|
+
compName,
|
|
630
|
+
nodesLookup,
|
|
365
631
|
propDefinitions,
|
|
366
|
-
stateDefinitions
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
632
|
+
stateDefinitions,
|
|
633
|
+
subComponentOptions,
|
|
634
|
+
structure
|
|
635
|
+
): Promise<HastNode | HastText> => {
|
|
636
|
+
if (node.content.referenceType === 'locale') {
|
|
637
|
+
const localeTag = HASTBuilders.createHTMLNode('span')
|
|
638
|
+
const commentNode = HASTBuilders.createComment(`Content for locale ${node.content.id}`)
|
|
639
|
+
HASTUtils.addChildNode(localeTag, commentNode)
|
|
640
|
+
return localeTag
|
|
641
|
+
}
|
|
373
642
|
|
|
374
|
-
|
|
643
|
+
const usedReferenceValue = getValueFromReference(
|
|
644
|
+
node.content.id,
|
|
645
|
+
node.content.referenceType === 'prop' ? propDefinitions : stateDefinitions
|
|
646
|
+
)
|
|
647
|
+
|
|
648
|
+
if (
|
|
649
|
+
(usedReferenceValue.type === 'object' || usedReferenceValue.type === 'array') &&
|
|
650
|
+
usedReferenceValue.defaultValue
|
|
651
|
+
) {
|
|
652
|
+
// Let's say users are biding the prop to a node using something like this "fields.Title"
|
|
653
|
+
// But the fields in the object is the value where the object is defined either in propDefinitions
|
|
654
|
+
// or on the attrs. So, we just need to parsed the rest of the object path and get the value from the object.
|
|
655
|
+
return HASTBuilders.createTextNode(
|
|
656
|
+
String(
|
|
657
|
+
extractDefaultValueFromRefPath(
|
|
658
|
+
usedReferenceValue.defaultValue as Record<string, UIDLPropDefinition>,
|
|
659
|
+
node.content.refPath
|
|
660
|
+
)
|
|
661
|
+
)
|
|
662
|
+
)
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
if (usedReferenceValue.type === 'element') {
|
|
666
|
+
const elementNode = usedReferenceValue.defaultValue as UIDLElementNode
|
|
667
|
+
if (elementNode) {
|
|
668
|
+
if (elementNode.content.key in nodesLookup) {
|
|
669
|
+
return nodesLookup[elementNode.content.key]
|
|
670
|
+
} else {
|
|
671
|
+
const elementTag = await generateHtmlSyntax(
|
|
672
|
+
elementNode,
|
|
673
|
+
compName,
|
|
674
|
+
nodesLookup,
|
|
675
|
+
propDefinitions,
|
|
676
|
+
stateDefinitions,
|
|
677
|
+
subComponentOptions,
|
|
678
|
+
structure
|
|
679
|
+
)
|
|
680
|
+
return elementTag
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
const spanTagWrapper = HASTBuilders.createHTMLNode('span')
|
|
685
|
+
const commentNode = HASTBuilders.createComment(`Content for slot ${node.content.id}`)
|
|
686
|
+
HASTUtils.addChildNode(spanTagWrapper, commentNode)
|
|
687
|
+
return spanTagWrapper
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
const spanTag = HASTBuilders.createHTMLNode('span')
|
|
691
|
+
HASTUtils.addTextNode(spanTag, String(usedReferenceValue.defaultValue))
|
|
375
692
|
return spanTag
|
|
376
693
|
}
|
|
377
694
|
|
|
@@ -384,10 +701,14 @@ const handleStyles = (
|
|
|
384
701
|
Object.keys(styles).forEach((styleKey) => {
|
|
385
702
|
let style: string | UIDLStyleValue = styles[styleKey]
|
|
386
703
|
if (style.type === 'dynamic' && style.content?.referenceType !== 'token') {
|
|
387
|
-
|
|
388
|
-
style
|
|
389
|
-
|
|
390
|
-
|
|
704
|
+
const referencedValue = getValueFromReference(
|
|
705
|
+
style.content.id,
|
|
706
|
+
style.content.referenceType === 'prop' ? propDefinitions : stateDefinitions
|
|
707
|
+
)
|
|
708
|
+
if (referencedValue.type === 'string' || referencedValue.type === 'number') {
|
|
709
|
+
style = String(
|
|
710
|
+
extractDefaultValueFromRefPath(referencedValue.defaultValue, style?.content?.refPath)
|
|
711
|
+
)
|
|
391
712
|
}
|
|
392
713
|
node.content.style[styleKey] = typeof style === 'string' ? staticNode(style) : style
|
|
393
714
|
}
|
|
@@ -395,62 +716,125 @@ const handleStyles = (
|
|
|
395
716
|
}
|
|
396
717
|
|
|
397
718
|
const handleAttributes = (
|
|
719
|
+
elementType: UIDLElement['elementType'],
|
|
398
720
|
htmlNode: HastNode,
|
|
399
721
|
attrs: Record<string, UIDLAttributeValue>,
|
|
400
722
|
propDefinitions: Record<string, UIDLPropDefinition>,
|
|
401
723
|
stateDefinitions: Record<string, UIDLStateDefinition>,
|
|
402
|
-
routeDefinitions: UIDLRouteDefinitions
|
|
724
|
+
routeDefinitions: UIDLRouteDefinitions,
|
|
725
|
+
outputOptions: UIDLComponentOutputOptions
|
|
403
726
|
) => {
|
|
404
|
-
Object.keys(attrs)
|
|
405
|
-
|
|
727
|
+
for (const attrKey of Object.keys(attrs)) {
|
|
728
|
+
const attrValue = attrs[attrKey]
|
|
729
|
+
const { type, content } = attrValue
|
|
730
|
+
|
|
731
|
+
switch (type) {
|
|
732
|
+
case 'static': {
|
|
733
|
+
if (attrKey === 'href' && typeof content === 'string' && content.startsWith('/')) {
|
|
734
|
+
let targetLink
|
|
735
|
+
|
|
736
|
+
const targetRoute = (routeDefinitions?.values || []).find(
|
|
737
|
+
(route) => route.pageOptions.navLink === content
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
if (targetRoute) {
|
|
741
|
+
targetLink = targetRoute.pageOptions.navLink
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
if (!targetRoute && content === '/home') {
|
|
745
|
+
targetLink = '/'
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
if (!targetLink && !targetRoute) {
|
|
749
|
+
targetLink = content
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
const currentPageRoute = join(...(outputOptions?.folderPath || []), './')
|
|
753
|
+
const localPrefix = relative(
|
|
754
|
+
`/${currentPageRoute}`,
|
|
755
|
+
`/${targetLink === '/' ? 'index' : targetLink}`
|
|
756
|
+
)
|
|
757
|
+
|
|
758
|
+
HASTUtils.addAttributeToNode(htmlNode, attrKey, `${localPrefix}.html`)
|
|
759
|
+
break
|
|
760
|
+
}
|
|
406
761
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
762
|
+
if (typeof content === 'boolean') {
|
|
763
|
+
htmlNode.properties[attrKey] = content === true ? 'true' : 'false'
|
|
764
|
+
} else if (typeof content === 'string' || typeof attrValue.content === 'number') {
|
|
765
|
+
let value = StringUtils.encode(String(attrValue.content))
|
|
766
|
+
|
|
767
|
+
/*
|
|
768
|
+
elementType of image is always mapped to img.
|
|
769
|
+
For reference, check `html-mapping` file.
|
|
770
|
+
*/
|
|
771
|
+
if (elementType === 'img' && attrKey === 'src' && !isValidURL(value)) {
|
|
772
|
+
/*
|
|
773
|
+
By default we just prefix all the asset paths with just the
|
|
774
|
+
assetPrefix that is configured in the project. But for `html` generators
|
|
775
|
+
we need to prefix that with the current file location.
|
|
776
|
+
|
|
777
|
+
Because, all the other frameworks have a build setup. which serves all the
|
|
778
|
+
assets from the `public` folder. But in the case of `html` here is how it works
|
|
779
|
+
|
|
780
|
+
We load a file from `index.html` the request for the image goes from
|
|
781
|
+
'...url.../public/...image...'
|
|
782
|
+
If it's a nested url, then the request goes from
|
|
783
|
+
'...url/nested/public/...image..'
|
|
784
|
+
|
|
785
|
+
But the nested folder is available only on the root. With this
|
|
786
|
+
The url changes prefixes to
|
|
787
|
+
|
|
788
|
+
../public/playground_assets/..image.. etc depending on the dept the file is in.
|
|
789
|
+
*/
|
|
790
|
+
value = join(relative(join(...outputOptions.folderPath), './'), value)
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
HASTUtils.addAttributeToNode(htmlNode, attrKey, value)
|
|
794
|
+
}
|
|
424
795
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
attrValue.content.referenceType === 'prop'
|
|
428
|
-
? getValueFromReference(attrValue.content.id, propDefinitions)
|
|
429
|
-
: getValueFromReference(attrValue.content.id, stateDefinitions)
|
|
430
|
-
HASTUtils.addAttributeToNode(htmlNode, attrKey, String(value))
|
|
431
|
-
return
|
|
432
|
-
}
|
|
796
|
+
break
|
|
797
|
+
}
|
|
433
798
|
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
799
|
+
case 'dynamic': {
|
|
800
|
+
const value = getValueFromReference(
|
|
801
|
+
content.id,
|
|
802
|
+
content.referenceType === 'prop' ? propDefinitions : stateDefinitions
|
|
803
|
+
)
|
|
804
|
+
|
|
805
|
+
HASTUtils.addAttributeToNode(
|
|
806
|
+
htmlNode,
|
|
807
|
+
attrKey,
|
|
808
|
+
String(extractDefaultValueFromRefPath(value.defaultValue, content.refPath))
|
|
809
|
+
)
|
|
810
|
+
break
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
case 'raw': {
|
|
814
|
+
HASTUtils.addAttributeToNode(htmlNode, attrKey, content)
|
|
815
|
+
break
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
case 'element':
|
|
819
|
+
case 'import':
|
|
820
|
+
case 'expr':
|
|
821
|
+
case 'object':
|
|
822
|
+
break
|
|
438
823
|
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
return
|
|
824
|
+
default: {
|
|
825
|
+
throw new HTMLComponentGeneratorError(
|
|
826
|
+
`Received ${JSON.stringify(attrValue, null, 2)} \n in handleAttributes for html`
|
|
827
|
+
)
|
|
828
|
+
}
|
|
445
829
|
}
|
|
446
|
-
}
|
|
830
|
+
}
|
|
447
831
|
}
|
|
448
832
|
|
|
449
833
|
const getValueFromReference = (
|
|
450
834
|
key: string,
|
|
451
835
|
definitions: Record<string, UIDLPropDefinition>
|
|
452
|
-
):
|
|
453
|
-
const usedReferenceValue = definitions[key.includes('
|
|
836
|
+
): UIDLPropDefinition | undefined => {
|
|
837
|
+
const usedReferenceValue = definitions[key.includes('?.') ? key.split('?.')[0] : key]
|
|
454
838
|
|
|
455
839
|
if (!usedReferenceValue) {
|
|
456
840
|
throw new HTMLComponentGeneratorError(
|
|
@@ -458,9 +842,11 @@ const getValueFromReference = (
|
|
|
458
842
|
)
|
|
459
843
|
}
|
|
460
844
|
|
|
461
|
-
if (
|
|
845
|
+
if (
|
|
846
|
+
['string', 'number', 'object', 'element', 'array'].includes(usedReferenceValue?.type) === false
|
|
847
|
+
) {
|
|
462
848
|
throw new HTMLComponentGeneratorError(
|
|
463
|
-
`
|
|
849
|
+
`Attribute is using dynamic value, but received of type ${JSON.stringify(
|
|
464
850
|
usedReferenceValue,
|
|
465
851
|
null,
|
|
466
852
|
2
|
|
@@ -468,9 +854,12 @@ const getValueFromReference = (
|
|
|
468
854
|
)
|
|
469
855
|
}
|
|
470
856
|
|
|
471
|
-
if (
|
|
857
|
+
if (
|
|
858
|
+
usedReferenceValue.type !== 'element' &&
|
|
859
|
+
usedReferenceValue.hasOwnProperty('defaultValue') === false
|
|
860
|
+
) {
|
|
472
861
|
throw new HTMLComponentGeneratorError(
|
|
473
|
-
`
|
|
862
|
+
`Default value is missing from dynamic reference - ${JSON.stringify(
|
|
474
863
|
usedReferenceValue,
|
|
475
864
|
null,
|
|
476
865
|
2
|
|
@@ -478,5 +867,16 @@ const getValueFromReference = (
|
|
|
478
867
|
)
|
|
479
868
|
}
|
|
480
869
|
|
|
481
|
-
return
|
|
870
|
+
return usedReferenceValue
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
const extractDefaultValueFromRefPath = (
|
|
874
|
+
propDefaultValue: PropDefaultValueTypes,
|
|
875
|
+
refPath?: string[]
|
|
876
|
+
) => {
|
|
877
|
+
if (typeof propDefaultValue !== 'object' || !refPath?.length) {
|
|
878
|
+
return propDefaultValue
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
return GenericUtils.getValueFromPath(refPath.join('.'), propDefaultValue) as PropDefaultValueTypes
|
|
482
882
|
}
|