@teleporthq/teleport-plugin-html-base-component 0.42.0-alpha.0 → 0.42.2

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.
@@ -56,68 +56,346 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
56
56
  };
57
57
  import { HTMLComponentGeneratorError, ChunkType, FileType, } from '@teleporthq/teleport-types';
58
58
  import { join, relative } from 'path';
59
- import { HASTBuilders, HASTUtils } from '@teleporthq/teleport-plugin-common';
60
- import { StringUtils, UIDLUtils } from '@teleporthq/teleport-shared';
59
+ import { HASTBuilders, HASTUtils, ASTUtils } from '@teleporthq/teleport-plugin-common';
60
+ import { GenericUtils, StringUtils, UIDLUtils } from '@teleporthq/teleport-shared';
61
61
  import { staticNode } from '@teleporthq/teleport-uidl-builders';
62
62
  import { createCSSPlugin } from '@teleporthq/teleport-plugin-css';
63
+ import { generateUniqueKeys, createNodesLookup } from '@teleporthq/teleport-uidl-resolver';
63
64
  import { DEFAULT_COMPONENT_CHUNK_NAME } from './constants';
64
- export var generateHtmlSynatx = function (node, templatesLookUp, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
65
- return __generator(this, function (_a) {
66
- switch (node.type) {
67
- case 'inject':
68
- case 'raw':
69
- return [2 /*return*/, HASTBuilders.createTextNode(node.content.toString())];
70
- case 'static':
71
- return [2 /*return*/, HASTBuilders.createTextNode(StringUtils.encode(node.content.toString()))];
72
- case 'slot':
73
- return [2 /*return*/, HASTBuilders.createHTMLNode(node.type)];
74
- case 'element':
75
- return [2 /*return*/, generatElementNode(node, templatesLookUp, propDefinitions, stateDefinitions, subComponentOptions, structure)];
76
- case 'dynamic':
77
- return [2 /*return*/, generateDynamicNode(node, templatesLookUp, propDefinitions, stateDefinitions, subComponentOptions, structure)];
78
- default:
79
- throw new HTMLComponentGeneratorError("generateHtmlSyntax encountered a node of unsupported type: ".concat(JSON.stringify(node, null, 2), " "));
65
+ var isValidURL = function (url) {
66
+ try {
67
+ /* tslint:disable:no-unused-expression */
68
+ new URL(url);
69
+ return true;
70
+ }
71
+ catch (error) {
72
+ return false;
73
+ }
74
+ };
75
+ var addNodeToLookup = function (key, tag, nodesLoookup) {
76
+ // In html code-generation we combine the nodes of the component that is being consumed with the current component.
77
+ // As html can't load the component at runtime like react or any other frameworks. So, we merge the component as a standalone
78
+ // component in the current component.
79
+ var currentLookup = nodesLoookup[key];
80
+ if (currentLookup) {
81
+ if (Array.isArray(currentLookup)) {
82
+ Array.isArray(tag) ? currentLookup.push.apply(currentLookup, tag) : currentLookup.push(tag);
83
+ }
84
+ else {
85
+ nodesLoookup[key] = Array.isArray(tag) ? __spreadArray([currentLookup], tag, true) : [currentLookup, tag];
86
+ }
87
+ return;
88
+ }
89
+ nodesLoookup[key] = tag;
90
+ };
91
+ export var generateHtmlSyntax = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions) { return __awaiter(void 0, void 0, void 0, function () {
92
+ var _a, elementNode, dynamicNode, conditionalNodeComment, _b, staticValue, reference, _c, conditions, matchingCriteria, _d, referenceType, id, _e, refPath, usedProp, defaultValue, _i, refPath_1, path, dynamicConditions, matchCondition, conditionString, isConditionPassing, content, uidlDynamicRef, generatedNode, isProp, uidlDynamicRef, generatedNode, successNode;
93
+ var _f, _g;
94
+ return __generator(this, function (_h) {
95
+ switch (_h.label) {
96
+ case 0:
97
+ _a = node.type;
98
+ switch (_a) {
99
+ case 'inject': return [3 /*break*/, 1];
100
+ case 'raw': return [3 /*break*/, 1];
101
+ case 'static': return [3 /*break*/, 2];
102
+ case 'slot': return [3 /*break*/, 3];
103
+ case 'element': return [3 /*break*/, 4];
104
+ case 'dynamic': return [3 /*break*/, 6];
105
+ case 'conditional': return [3 /*break*/, 8];
106
+ case 'expr': return [3 /*break*/, 9];
107
+ case 'cms-list-repeater': return [3 /*break*/, 14];
108
+ case 'cms-item': return [3 /*break*/, 15];
109
+ case 'cms-list': return [3 /*break*/, 15];
110
+ case 'data-source-item': return [3 /*break*/, 15];
111
+ case 'data-source-list': return [3 /*break*/, 15];
112
+ }
113
+ return [3 /*break*/, 16];
114
+ case 1: return [2 /*return*/, HASTBuilders.createTextNode(node.content.toString())];
115
+ case 2: return [2 /*return*/, HASTBuilders.createTextNode(StringUtils.encode(node.content.toString()))];
116
+ case 3: return [2 /*return*/, HASTBuilders.createHTMLNode(node.type)];
117
+ case 4: return [4 /*yield*/, generateElementNode(node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
118
+ case 5:
119
+ elementNode = _h.sent();
120
+ return [2 /*return*/, elementNode];
121
+ case 6: return [4 /*yield*/, generateDynamicNode(node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
122
+ case 7:
123
+ dynamicNode = _h.sent();
124
+ return [2 /*return*/, dynamicNode];
125
+ case 8:
126
+ conditionalNodeComment = HASTBuilders.createTextNode('');
127
+ _b = node.content, staticValue = _b.value, reference = _b.reference, _c = _b.condition, conditions = _c.conditions, matchingCriteria = _c.matchingCriteria;
128
+ if (reference.type !== 'dynamic') {
129
+ return [2 /*return*/, conditionalNodeComment];
130
+ }
131
+ _d = reference.content, referenceType = _d.referenceType, id = _d.id, _e = _d.refPath, refPath = _e === void 0 ? [] : _e;
132
+ switch (referenceType) {
133
+ case 'prop': {
134
+ usedProp = propDefinitions[id];
135
+ if (usedProp === undefined || usedProp.defaultValue === undefined) {
136
+ return [2 /*return*/, conditionalNodeComment];
137
+ }
138
+ defaultValue = usedProp.defaultValue;
139
+ for (_i = 0, refPath_1 = refPath; _i < refPath_1.length; _i++) {
140
+ path = refPath_1[_i];
141
+ defaultValue = defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue[path];
142
+ }
143
+ // If defaultValue is undefined or null after path traversal, use original default
144
+ defaultValue = defaultValue !== null && defaultValue !== void 0 ? defaultValue : usedProp.defaultValue;
145
+ dynamicConditions = createConditionalStatement(staticValue !== undefined ? [{ operand: staticValue, operation: '===' }] : conditions, defaultValue);
146
+ matchCondition = matchingCriteria && matchingCriteria === 'all' ? '&&' : '||';
147
+ conditionString = dynamicConditions.join(" ".concat(matchCondition, " "));
148
+ try {
149
+ isConditionPassing = new Function("return ".concat(conditionString))();
150
+ if (isConditionPassing) {
151
+ return [2 /*return*/, generateHtmlSyntax(node.content.node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
152
+ }
153
+ }
154
+ catch (error) {
155
+ return [2 /*return*/, conditionalNodeComment];
156
+ }
157
+ return [2 /*return*/, conditionalNodeComment];
158
+ }
159
+ case 'state':
160
+ default:
161
+ return [2 /*return*/, conditionalNodeComment];
162
+ }
163
+ _h.label = 9;
164
+ case 9:
165
+ content = node.content.split('?.');
166
+ if (!(resolvedExpressions && ((_f = resolvedExpressions.expressions) === null || _f === void 0 ? void 0 : _f[content[0] || '']))) return [3 /*break*/, 11];
167
+ uidlDynamicRef = {
168
+ type: 'dynamic',
169
+ content: {
170
+ referenceType: 'prop',
171
+ refPath: __spreadArray([resolvedExpressions.currentIndex.toString()], content.slice(1), true),
172
+ id: content[0],
173
+ },
174
+ };
175
+ return [4 /*yield*/, generateDynamicNode(uidlDynamicRef, compName, nodesLookup, resolvedExpressions.expressions, stateDefinitions, subComponentOptions, structure)];
176
+ case 10:
177
+ generatedNode = _h.sent();
178
+ return [2 /*return*/, generatedNode];
179
+ case 11:
180
+ if (!(content[0] && ((propDefinitions === null || propDefinitions === void 0 ? void 0 : propDefinitions[content[0]]) || (stateDefinitions === null || stateDefinitions === void 0 ? void 0 : stateDefinitions[content[0]])))) return [3 /*break*/, 13];
181
+ isProp = Boolean(propDefinitions === null || propDefinitions === void 0 ? void 0 : propDefinitions[content[0]]);
182
+ uidlDynamicRef = {
183
+ type: 'dynamic',
184
+ content: {
185
+ referenceType: isProp ? 'prop' : 'state',
186
+ refPath: content.slice(1),
187
+ id: content[0],
188
+ },
189
+ };
190
+ return [4 /*yield*/, generateDynamicNode(uidlDynamicRef, compName, nodesLookup, isProp ? propDefinitions : stateDefinitions, stateDefinitions, subComponentOptions, structure)];
191
+ case 12:
192
+ generatedNode = _h.sent();
193
+ return [2 /*return*/, generatedNode];
194
+ case 13: return [2 /*return*/, HASTBuilders.createComment('Expressions are not supported in HTML')];
195
+ case 14: return [2 /*return*/, generateRepeaterNode(node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
196
+ case 15:
197
+ successNode = (_g = node.content.nodes) === null || _g === void 0 ? void 0 : _g.success;
198
+ if (successNode) {
199
+ return [2 /*return*/, generateHtmlSyntax(successNode, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
200
+ }
201
+ // If no success node, return empty div
202
+ return [2 /*return*/, HASTBuilders.createHTMLNode('div')];
203
+ case 16: throw new HTMLComponentGeneratorError("generateHtmlSyntax encountered a node of unsupported type: ".concat(JSON.stringify(node, null, 2), " "));
80
204
  }
81
- return [2 /*return*/];
82
205
  });
83
206
  }); };
84
- var generatElementNode = function (node, templatesLookUp, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
85
- var _a, elementType, children, _b, attrs, _c, style, _d, referencedStyles, dependency, key, elementNode, dependencies, compTag, _i, children_1, child, childTag;
86
- return __generator(this, function (_e) {
87
- switch (_e.label) {
207
+ var createConditionalStatement = function (conditions, leftOperand) {
208
+ return conditions.map(function (condition) {
209
+ var operation = condition.operation, operand = condition.operand;
210
+ if (operand === undefined) {
211
+ return "".concat(ASTUtils.convertToUnaryOperator(operation)).concat(getValueType(operand));
212
+ }
213
+ return "".concat(getValueType(leftOperand), " ").concat(ASTUtils.convertToBinaryOperator(operation), " ").concat(getValueType(operand));
214
+ });
215
+ };
216
+ var getValueType = function (value) {
217
+ var valueType = typeof value;
218
+ switch (valueType) {
219
+ case 'string':
220
+ return "\"".concat(value, "\"");
221
+ case 'number':
222
+ return value;
223
+ case 'boolean':
224
+ return value;
225
+ case 'object':
226
+ // Handle dynamic references (local, prop, state)
227
+ if (value && typeof value === 'object' && 'type' in value) {
228
+ var dynamicValue = value;
229
+ if (dynamicValue.type === 'dynamic' && dynamicValue.content) {
230
+ var _a = dynamicValue.content, referenceType = _a.referenceType, id = _a.id, refPath = _a.refPath;
231
+ if (referenceType === 'local' && id) {
232
+ // Local reference from repeater context
233
+ if (refPath && refPath.length > 0) {
234
+ return "".concat(id, ".").concat(refPath.join('.'));
235
+ }
236
+ return id;
237
+ }
238
+ else if (referenceType === 'prop' || referenceType === 'state') {
239
+ // Prop or state reference
240
+ var key = refPath && refPath.length > 0 ? refPath.join('.') : id;
241
+ return key;
242
+ }
243
+ }
244
+ }
245
+ throw new HTMLComponentGeneratorError("Conditional node received an operand of type ".concat(valueType, " \n\n Received ").concat(JSON.stringify(value)));
246
+ default:
247
+ throw new HTMLComponentGeneratorError("Conditional node received an operand of type ".concat(valueType, " \n\n Received ").concat(JSON.stringify(value)));
248
+ }
249
+ };
250
+ var generateRepeaterNode = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
251
+ var nodes, contextId, sourceValue, propDef, parsedSource, elementNode, emptyChildren, _i, emptyChildren_1, child, childTag, listChildren, index, _a, listChildren_1, child, childTag;
252
+ var _b;
253
+ var _c;
254
+ return __generator(this, function (_d) {
255
+ switch (_d.label) {
88
256
  case 0:
89
- _a = node.content, elementType = _a.elementType, children = _a.children, _b = _a.attrs, attrs = _b === void 0 ? {} : _b, _c = _a.style, style = _c === void 0 ? {} : _c, _d = _a.referencedStyles, referencedStyles = _d === void 0 ? {} : _d, dependency = _a.dependency, key = _a.key;
90
- elementNode = HASTBuilders.createHTMLNode(elementType);
91
- templatesLookUp[key] = elementNode;
92
- dependencies = structure.dependencies;
93
- if (dependency && (dependency === null || dependency === void 0 ? void 0 : dependency.type) !== 'local') {
94
- dependencies[dependency.path] = dependency;
257
+ nodes = node.content.nodes;
258
+ contextId = node.content.renderPropIdentifier;
259
+ sourceValue = node.content.source;
260
+ propDef = sourceValue && typeof sourceValue === 'string'
261
+ ? propDefinitions[Object.keys(propDefinitions).find(function (propKey) { return sourceValue.includes(propKey); }) || '']
262
+ : undefined;
263
+ if (!propDef || !Array.isArray(propDef.defaultValue)) {
264
+ // If no prop is found we might have a static source value
265
+ try {
266
+ parsedSource = JSON.parse(sourceValue);
267
+ propDef = {
268
+ defaultValue: parsedSource,
269
+ id: contextId,
270
+ type: 'array',
271
+ };
272
+ }
273
+ catch (_e) {
274
+ // Silent fail
275
+ }
276
+ }
277
+ // We do the check again to keep typescript happy, otherwise this could be in catch
278
+ if (!propDef || !Array.isArray(propDef.defaultValue)) {
279
+ return [2 /*return*/, HASTBuilders.createComment('CMS Array Mapper/Repeater not supported in HTML without a prop source')];
95
280
  }
281
+ propDefinitions[contextId] = propDef;
282
+ elementNode = HASTBuilders.createHTMLNode('div');
283
+ node.content.nodes.list.content.style = { display: { type: 'static', content: 'contents' } };
284
+ if (node.content.nodes.empty) {
285
+ node.content.nodes.empty.content.style = { display: { type: 'static', content: 'contents' } };
286
+ }
287
+ if (node.content.nodes.loading) {
288
+ node.content.nodes.loading.content.style = { display: { type: 'static', content: 'contents' } };
289
+ }
290
+ if (!(propDef.defaultValue.length === 0)) return [3 /*break*/, 5];
291
+ emptyChildren = (_c = nodes.empty) === null || _c === void 0 ? void 0 : _c.content.children;
292
+ if (!emptyChildren) return [3 /*break*/, 4];
293
+ _i = 0, emptyChildren_1 = emptyChildren;
294
+ _d.label = 1;
295
+ case 1:
296
+ if (!(_i < emptyChildren_1.length)) return [3 /*break*/, 4];
297
+ child = emptyChildren_1[_i];
298
+ return [4 /*yield*/, generateHtmlSyntax(child, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
299
+ case 2:
300
+ childTag = _d.sent();
301
+ if (typeof childTag === 'string') {
302
+ HASTUtils.addTextNode(elementNode, childTag);
303
+ }
304
+ else {
305
+ HASTUtils.addChildNode(elementNode, childTag);
306
+ }
307
+ _d.label = 3;
308
+ case 3:
309
+ _i++;
310
+ return [3 /*break*/, 1];
311
+ case 4:
312
+ if (nodes.empty) {
313
+ addNodeToLookup("".concat(node.content.nodes.empty.content.key), elementNode, nodesLookup);
314
+ }
315
+ return [2 /*return*/, elementNode];
316
+ case 5:
317
+ listChildren = nodes.list.content.children;
318
+ if (!listChildren) return [3 /*break*/, 11];
319
+ index = 0;
320
+ _d.label = 6;
321
+ case 6:
322
+ if (!(index < propDef.defaultValue.length)) return [3 /*break*/, 11];
323
+ _a = 0, listChildren_1 = listChildren;
324
+ _d.label = 7;
325
+ case 7:
326
+ if (!(_a < listChildren_1.length)) return [3 /*break*/, 10];
327
+ child = listChildren_1[_a];
328
+ return [4 /*yield*/, generateHtmlSyntax(child, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, { currentIndex: index, expressions: (_b = {}, _b[contextId] = propDef, _b) })];
329
+ case 8:
330
+ childTag = _d.sent();
331
+ if (typeof childTag === 'string') {
332
+ HASTUtils.addTextNode(elementNode, childTag);
333
+ }
334
+ else {
335
+ HASTUtils.addChildNode(elementNode, childTag);
336
+ }
337
+ _d.label = 9;
338
+ case 9:
339
+ _a++;
340
+ return [3 /*break*/, 7];
341
+ case 10:
342
+ index++;
343
+ return [3 /*break*/, 6];
344
+ case 11:
345
+ addNodeToLookup("".concat(node.content.nodes.list.content.key), elementNode, nodesLookup);
346
+ return [2 /*return*/, elementNode];
347
+ }
348
+ });
349
+ }); };
350
+ var generateElementNode = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions) { return __awaiter(void 0, void 0, void 0, function () {
351
+ var successNode, _a, elementType, children, _b, attrs, _c, style, _d, referencedStyles, dependency, dependencies, compTag, elementNode, _i, children_1, child, childTag;
352
+ var _e;
353
+ return __generator(this, function (_f) {
354
+ switch (_f.label) {
355
+ case 0:
356
+ // Check if this is a wrapped data-source node
357
+ if (node.content &&
358
+ typeof node.content === 'object' &&
359
+ 'type' in node.content &&
360
+ (node.content.type === 'data-source-item' || node.content.type === 'data-source-list')) {
361
+ successNode = (_e = node.content.nodes) === null || _e === void 0 ? void 0 : _e.success;
362
+ if (successNode) {
363
+ return [2 /*return*/, generateHtmlSyntax(successNode, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
364
+ }
365
+ // If no success node, return empty div
366
+ return [2 /*return*/, HASTBuilders.createHTMLNode('div')];
367
+ }
368
+ _a = node.content, elementType = _a.elementType, children = _a.children, _b = _a.attrs, attrs = _b === void 0 ? {} : _b, _c = _a.style, style = _c === void 0 ? {} : _c, _d = _a.referencedStyles, referencedStyles = _d === void 0 ? {} : _d, dependency = _a.dependency;
369
+ dependencies = structure.dependencies;
96
370
  if (!(dependency && (dependency === null || dependency === void 0 ? void 0 : dependency.type) === 'local')) return [3 /*break*/, 2];
97
- return [4 /*yield*/, generateComponentContent(node, propDefinitions, stateDefinitions, subComponentOptions, structure)];
371
+ return [4 /*yield*/, generateComponentContent(node, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
98
372
  case 1:
99
- compTag = _e.sent();
373
+ compTag = _f.sent();
374
+ if ('tagName' in compTag) {
375
+ compTag.children.unshift(HASTBuilders.createComment("".concat(node.content.semanticType, " component")));
376
+ }
100
377
  return [2 /*return*/, compTag];
101
378
  case 2:
379
+ if (dependency && (dependency === null || dependency === void 0 ? void 0 : dependency.type) !== 'local') {
380
+ dependencies[dependency.path] = dependency;
381
+ }
382
+ elementNode = HASTBuilders.createHTMLNode(elementType);
102
383
  if (!children) return [3 /*break*/, 6];
103
384
  _i = 0, children_1 = children;
104
- _e.label = 3;
385
+ _f.label = 3;
105
386
  case 3:
106
387
  if (!(_i < children_1.length)) return [3 /*break*/, 6];
107
388
  child = children_1[_i];
108
- return [4 /*yield*/, generateHtmlSynatx(child, templatesLookUp, propDefinitions, stateDefinitions, subComponentOptions, structure)];
389
+ return [4 /*yield*/, generateHtmlSyntax(child, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
109
390
  case 4:
110
- childTag = _e.sent();
111
- if (!childTag) {
112
- return [2 /*return*/];
113
- }
391
+ childTag = _f.sent();
114
392
  if (typeof childTag === 'string') {
115
393
  HASTUtils.addTextNode(elementNode, childTag);
116
394
  }
117
395
  else {
118
396
  HASTUtils.addChildNode(elementNode, childTag);
119
397
  }
120
- _e.label = 5;
398
+ _f.label = 5;
121
399
  case 5:
122
400
  _i++;
123
401
  return [3 /*break*/, 3];
@@ -127,38 +405,47 @@ var generatElementNode = function (node, templatesLookUp, propDefinitions, state
127
405
  var refStyle = referencedStyles[styleRef];
128
406
  if (refStyle.content.mapType === 'inlined') {
129
407
  handleStyles(node, refStyle.content.styles, propDefinitions, stateDefinitions);
130
- return;
131
408
  }
132
409
  });
133
410
  }
134
411
  if (Object.keys(style).length > 0) {
135
412
  handleStyles(node, style, propDefinitions, stateDefinitions);
136
413
  }
137
- if (Object.keys(attrs).length > 0) {
138
- handleAttributes(elementType, elementNode, attrs, propDefinitions, stateDefinitions, structure.options.projectRouteDefinition, structure.outputOptions);
139
- }
414
+ handleAttributes(elementType, elementNode, attrs, propDefinitions, stateDefinitions, structure.options.projectRouteDefinition, structure.outputOptions, resolvedExpressions === null || resolvedExpressions === void 0 ? void 0 : resolvedExpressions.currentIndex);
415
+ addNodeToLookup(node.content.key, elementNode, nodesLookup);
140
416
  return [2 /*return*/, elementNode];
141
417
  }
142
418
  });
143
419
  }); };
144
- var generateComponentContent = function (node, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
145
- var externals, plugins, _a, elementType, _b, attrs, key, _c, children, dependencies, _d, chunks, options, comp, lookUpTemplates, compHasSlots, combinedProps, propsForInstance, combinedStates, statesForInstance, elementNode, compTag, cssPlugin, initialStructure, result, chunk, styleChunk;
146
- var _e;
147
- return __generator(this, function (_f) {
148
- switch (_f.label) {
420
+ var createLookupTable = function (component, nodesLookup) {
421
+ var lookup = {};
422
+ for (var _i = 0, _a = Object.keys(nodesLookup); _i < _a.length; _i++) {
423
+ var node = _a[_i];
424
+ lookup[node] = {
425
+ count: 1,
426
+ nextKey: '1',
427
+ };
428
+ }
429
+ createNodesLookup(component, lookup);
430
+ return lookup;
431
+ };
432
+ var generateComponentContent = function (node, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions) { return __awaiter(void 0, void 0, void 0, function () {
433
+ var externals, plugins, _a, elementType, _b, attrs, _c, children, dependencies, _d, chunks, options, componentName, component, componentClone, lookupTableForCurrentPage, combinedProps, combinedStates, statesForInstance, propsForInstance, _loop_1, _i, _e, propKey, componentWrapper, isExistingNode, wrapperAttrs, componentInstanceToGenerate, compTag, cssPlugin, initialStructure, result;
434
+ var _f, _g, _h;
435
+ return __generator(this, function (_j) {
436
+ switch (_j.label) {
149
437
  case 0:
150
438
  externals = subComponentOptions.externals, plugins = subComponentOptions.plugins;
151
- _a = node.content, elementType = _a.elementType, _b = _a.attrs, attrs = _b === void 0 ? {} : _b, key = _a.key, _c = _a.children, children = _c === void 0 ? [] : _c;
439
+ _a = node.content, elementType = _a.elementType, _b = _a.attrs, attrs = _b === void 0 ? {} : _b, _c = _a.children, children = _c === void 0 ? [] : _c;
152
440
  dependencies = structure.dependencies, _d = structure.chunks, chunks = _d === void 0 ? [] : _d, options = structure.options;
153
- comp = UIDLUtils.cloneObject(externals[elementType] || {});
154
- lookUpTemplates = {};
155
- compHasSlots = false;
156
- if (!comp || !(comp === null || comp === void 0 ? void 0 : comp.node)) {
157
- throw new HTMLComponentGeneratorError("".concat(elementType, " is not found from the externals. \n\n Received ").concat(JSON.stringify(Object.keys(externals), null, 2)));
441
+ componentName = elementType === 'Component' ? 'AppComponent' : elementType;
442
+ component = externals[componentName];
443
+ if (component === undefined) {
444
+ throw new HTMLComponentGeneratorError("".concat(componentName, " is missing from externals object"));
158
445
  }
446
+ componentClone = UIDLUtils.cloneObject(component);
159
447
  if (children.length) {
160
- compHasSlots = true;
161
- UIDLUtils.traverseNodes(comp.node, function (childNode, parentNode) {
448
+ UIDLUtils.traverseNodes(componentClone.node, function (childNode, parentNode) {
162
449
  var _a, _b;
163
450
  if (childNode.type === 'slot' && parentNode.type === 'element') {
164
451
  var nonSlotNodes = (_b = (_a = parentNode.content) === null || _a === void 0 ? void 0 : _a.children) === null || _b === void 0 ? void 0 : _b.filter(function (n) { return n.type !== 'slot'; });
@@ -168,6 +455,7 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
168
455
  content: {
169
456
  key: 'custom-slot',
170
457
  elementType: 'slot',
458
+ name: componentClone.name + 'slot',
171
459
  style: {
172
460
  display: {
173
461
  type: 'static',
@@ -186,46 +474,132 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
186
474
  */
187
475
  node.content.children = [];
188
476
  }
189
- combinedProps = __assign(__assign({}, propDefinitions), ((comp === null || comp === void 0 ? void 0 : comp.propDefinitions) || {}));
190
- propsForInstance = Object.keys(combinedProps).reduce(function (acc, propKey) {
191
- var _a, _b;
192
- if (attrs[propKey]) {
193
- acc[propKey] = __assign(__assign({}, combinedProps[propKey]), { defaultValue: ((_a = attrs[propKey]) === null || _a === void 0 ? void 0 : _a.content) || ((_b = combinedProps[propKey]) === null || _b === void 0 ? void 0 : _b.defaultValue) });
194
- }
195
- else {
196
- acc[propKey] = combinedProps[propKey];
197
- }
477
+ lookupTableForCurrentPage = createLookupTable(componentClone, nodesLookup);
478
+ generateUniqueKeys(componentClone, lookupTableForCurrentPage);
479
+ combinedProps = __assign(__assign({}, Object.keys(propDefinitions).reduce(function (acc, propKey) {
480
+ acc[propKey] = propDefinitions[propKey];
198
481
  return acc;
199
- }, {});
200
- combinedStates = __assign(__assign({}, stateDefinitions), ((comp === null || comp === void 0 ? void 0 : comp.stateDefinitions) || {}));
482
+ }, {})), ((componentClone === null || componentClone === void 0 ? void 0 : componentClone.propDefinitions) || {}));
483
+ combinedStates = __assign(__assign({}, stateDefinitions), ((componentClone === null || componentClone === void 0 ? void 0 : componentClone.stateDefinitions) || {}));
201
484
  statesForInstance = Object.keys(combinedStates).reduce(function (acc, propKey) {
202
485
  var _a, _b;
203
- if (attrs[propKey]) {
204
- acc[propKey] = __assign(__assign({}, combinedStates[propKey]), { defaultValue: ((_a = attrs[propKey]) === null || _a === void 0 ? void 0 : _a.content) || ((_b = combinedStates[propKey]) === null || _b === void 0 ? void 0 : _b.defaultValue) });
486
+ var attr = attrs[propKey];
487
+ if ((attr === null || attr === void 0 ? void 0 : attr.type) === 'object') {
488
+ throw new Error("Object attributes are not supported in html exports");
489
+ }
490
+ if (attr) {
491
+ acc[propKey] = __assign(__assign({}, combinedStates[propKey]), { defaultValue: (_a = attr === null || attr === void 0 ? void 0 : attr.content) !== null && _a !== void 0 ? _a : (_b = combinedStates[propKey]) === null || _b === void 0 ? void 0 : _b.defaultValue });
205
492
  }
206
493
  else {
207
494
  acc[propKey] = combinedStates[propKey];
208
495
  }
209
496
  return acc;
210
497
  }, {});
211
- elementNode = HASTBuilders.createHTMLNode(StringUtils.camelCaseToDashCase(elementType));
212
- lookUpTemplates[key] = elementNode;
213
- return [4 /*yield*/, generateHtmlSynatx(__assign(__assign({}, comp.node), { content: __assign(__assign({}, comp.node.content), { style: __assign(__assign({}, (((_e = comp.node.content) === null || _e === void 0 ? void 0 : _e.style) || {})), { display: {
214
- type: 'static',
215
- content: 'contents',
216
- } }) }) }), lookUpTemplates, propsForInstance, statesForInstance, subComponentOptions, structure)];
498
+ propsForInstance = {};
499
+ _loop_1 = function (propKey) {
500
+ var attribute = attrs[propKey];
501
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'element') {
502
+ propsForInstance[propKey] = __assign(__assign({}, combinedProps[propKey]), { defaultValue: attrs[propKey] });
503
+ }
504
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'dynamic') {
505
+ // When we are using a component instance in a component and the attribute
506
+ // that is passed to the component is of dynamic reference.
507
+ // If means, the component is redirecting the prop that is received to the prop of the component that it is consuming.
508
+ // 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.
509
+ // And similary we do the same for the states.
510
+ switch (attribute.content.referenceType) {
511
+ case 'prop':
512
+ propsForInstance[propKey] = combinedProps[attribute.content.id];
513
+ break;
514
+ case 'state':
515
+ propsForInstance[propKey] = combinedStates[attribute.content.id];
516
+ break;
517
+ case 'expr':
518
+ // Ignore expr type attributes in html comp instances for the time being.
519
+ break;
520
+ default:
521
+ throw new Error("ReferenceType ".concat(attribute.content.referenceType, " is not supported in HTML Export."));
522
+ }
523
+ }
524
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'object') {
525
+ propsForInstance[propKey] = __assign(__assign({}, combinedProps[propKey]), { defaultValue: (attribute === null || attribute === void 0 ? void 0 : attribute.content) || ((_f = combinedProps[propKey]) === null || _f === void 0 ? void 0 : _f.defaultValue) });
526
+ }
527
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'expr') {
528
+ var _k = attribute.content.split('?.'), ctxId_1 = _k[0], refPath = _k.slice(1);
529
+ var propKeyFromAttr = Object.keys(combinedProps).find(function (key) { return key === ctxId_1; });
530
+ var resolvedValue = combinedProps[propKeyFromAttr];
531
+ var hasRefPath = refPath.length > 0;
532
+ // Build the path using repeater index when available
533
+ var fullRefPath = typeof (resolvedExpressions === null || resolvedExpressions === void 0 ? void 0 : resolvedExpressions.currentIndex) === 'number' && hasRefPath
534
+ ? __spreadArray([resolvedExpressions.currentIndex.toString()], refPath, true) : refPath;
535
+ if (Array.isArray(resolvedValue)) {
536
+ // If the resolved value itself is an array definition, pass it through
537
+ propsForInstance[propKey] = resolvedValue;
538
+ }
539
+ else {
540
+ var defaultVal = resolvedValue === null || resolvedValue === void 0 ? void 0 : resolvedValue.defaultValue;
541
+ var extracted = hasRefPath && defaultVal !== undefined
542
+ ? extractDefaultValueFromRefPath(defaultVal, fullRefPath)
543
+ : defaultVal !== null && defaultVal !== void 0 ? defaultVal : null;
544
+ propsForInstance[propKey] = __assign(__assign({}, resolvedValue), { defaultValue: extracted });
545
+ }
546
+ }
547
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'dynamic' &&
548
+ (attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'element' &&
549
+ (attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'object' &&
550
+ (attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'expr') {
551
+ propsForInstance[propKey] = __assign(__assign({}, combinedProps[propKey]), { defaultValue: (_g = attribute === null || attribute === void 0 ? void 0 : attribute.content) !== null && _g !== void 0 ? _g : (_h = combinedProps[propKey]) === null || _h === void 0 ? void 0 : _h.defaultValue });
552
+ }
553
+ if (attribute === undefined) {
554
+ var propFromCurrentComponent = combinedProps[propKey];
555
+ propsForInstance[propKey] = propFromCurrentComponent;
556
+ }
557
+ };
558
+ // this is where we check if the component we are conusming is actually passing any props to the instance.
559
+ // 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
560
+ // the component instance that we are using here.
561
+ for (_i = 0, _e = Object.keys(combinedProps); _i < _e.length; _i++) {
562
+ propKey = _e[_i];
563
+ _loop_1(propKey);
564
+ }
565
+ componentWrapper = StringUtils.camelCaseToDashCase("".concat(componentName, "-wrapper"));
566
+ isExistingNode = nodesLookup[componentWrapper];
567
+ if (isExistingNode !== undefined) {
568
+ componentWrapper = "".concat(componentWrapper, "-").concat(StringUtils.generateRandomString());
569
+ }
570
+ wrapperAttrs = {};
571
+ Object.keys(attrs).forEach(function (attrKey) {
572
+ if (attrKey.startsWith('dataNode') || attrKey.startsWith('data-node')) {
573
+ wrapperAttrs[attrKey] = attrs[attrKey];
574
+ }
575
+ });
576
+ componentInstanceToGenerate = {
577
+ type: 'element',
578
+ content: {
579
+ elementType: componentWrapper,
580
+ key: componentWrapper,
581
+ children: [componentClone.node],
582
+ attrs: wrapperAttrs,
583
+ style: {
584
+ display: {
585
+ type: 'static',
586
+ content: 'contents',
587
+ },
588
+ },
589
+ },
590
+ };
591
+ return [4 /*yield*/, generateHtmlSyntax(componentInstanceToGenerate, component.name, nodesLookup, propsForInstance, statesForInstance, subComponentOptions, structure, resolvedExpressions)];
217
592
  case 1:
218
- compTag = (_f.sent());
593
+ compTag = _j.sent();
219
594
  cssPlugin = createCSSPlugin({
220
595
  templateStyle: 'html',
221
596
  templateChunkName: DEFAULT_COMPONENT_CHUNK_NAME,
222
597
  declareDependency: 'import',
223
- forceScoping: true,
224
- chunkName: comp.name,
598
+ chunkName: componentClone.name,
225
599
  staticPropReferences: true,
226
600
  });
227
601
  initialStructure = {
228
- uidl: __assign(__assign({}, comp), { propDefinitions: propsForInstance, stateDefinitions: statesForInstance }),
602
+ uidl: __assign(__assign({}, componentClone), { node: componentInstanceToGenerate, propDefinitions: propsForInstance, stateDefinitions: statesForInstance }),
229
603
  chunks: [
230
604
  {
231
605
  type: ChunkType.HAST,
@@ -234,7 +608,7 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
234
608
  linkAfter: [],
235
609
  content: compTag,
236
610
  meta: {
237
- nodesLookup: lookUpTemplates,
611
+ nodesLookup: nodesLookup,
238
612
  },
239
613
  },
240
614
  ],
@@ -253,132 +627,220 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
253
627
  });
254
628
  }); }, Promise.resolve(initialStructure))];
255
629
  case 2:
256
- result = _f.sent();
257
- if (compHasSlots) {
258
- result.chunks.forEach(function (chunk) {
259
- if (chunk.fileType === FileType.CSS) {
260
- chunks.push(chunk);
261
- }
262
- });
630
+ result = _j.sent();
631
+ result.chunks.forEach(function (chunk) {
632
+ if (chunk.fileType === FileType.CSS) {
633
+ chunks.push(chunk);
634
+ }
635
+ });
636
+ addNodeToLookup(node.content.key, compTag, nodesLookup);
637
+ return [2 /*return*/, compTag];
638
+ }
639
+ });
640
+ }); };
641
+ var generateDynamicNode = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions) { return __awaiter(void 0, void 0, void 0, function () {
642
+ var localeTag, commentNode, usedReferenceValue, extracted, elementNode, elementClone, iterElementTag, generatedElementTag, spanTagWrapper, commentNode, spanTag;
643
+ var _a;
644
+ return __generator(this, function (_b) {
645
+ switch (_b.label) {
646
+ case 0:
647
+ if (node.content.referenceType === 'locale') {
648
+ localeTag = HASTBuilders.createHTMLNode('span');
649
+ commentNode = HASTBuilders.createComment("Content for locale ".concat(node.content.id));
650
+ HASTUtils.addChildNode(localeTag, commentNode);
651
+ return [2 /*return*/, localeTag];
263
652
  }
264
- else {
265
- chunk = chunks.find(function (item) { return item.name === comp.name; });
266
- if (!chunk) {
267
- styleChunk = result.chunks.find(function (item) { return item.fileType === FileType.CSS; });
268
- if (!styleChunk) {
269
- return [2 /*return*/];
270
- }
271
- chunks.push(styleChunk);
653
+ usedReferenceValue = getValueFromReference(node.content.id, node.content.referenceType === 'prop' ? propDefinitions : stateDefinitions);
654
+ if ((usedReferenceValue.type === 'object' || usedReferenceValue.type === 'array') &&
655
+ usedReferenceValue.defaultValue) {
656
+ extracted = extractDefaultValueFromRefPath(usedReferenceValue.defaultValue, node.content.refPath);
657
+ if (extracted === undefined || extracted === null) {
658
+ return [2 /*return*/, HASTBuilders.createTextNode('')];
272
659
  }
660
+ return [2 /*return*/, HASTBuilders.createTextNode(String(extracted))];
273
661
  }
274
- return [2 /*return*/, compTag];
662
+ if (!(usedReferenceValue.type === 'element')) return [3 /*break*/, 5];
663
+ elementNode = usedReferenceValue.defaultValue;
664
+ if (!elementNode) return [3 /*break*/, 4];
665
+ if (!(resolvedExpressions && typeof resolvedExpressions.currentIndex === 'number')) return [3 /*break*/, 2];
666
+ elementClone = UIDLUtils.cloneObject(elementNode);
667
+ if ((_a = elementClone === null || elementClone === void 0 ? void 0 : elementClone.content) === null || _a === void 0 ? void 0 : _a.key) {
668
+ elementClone.content.key = "".concat(elementClone.content.key, "-").concat(resolvedExpressions.currentIndex);
669
+ }
670
+ return [4 /*yield*/, generateHtmlSyntax(elementClone, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
671
+ case 1:
672
+ iterElementTag = _b.sent();
673
+ return [2 /*return*/, iterElementTag];
674
+ case 2:
675
+ if (elementNode.content.key in nodesLookup) {
676
+ return [2 /*return*/, nodesLookup[elementNode.content.key]];
677
+ }
678
+ return [4 /*yield*/, generateHtmlSyntax(elementNode, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure, resolvedExpressions)];
679
+ case 3:
680
+ generatedElementTag = _b.sent();
681
+ return [2 /*return*/, generatedElementTag];
682
+ case 4:
683
+ spanTagWrapper = HASTBuilders.createHTMLNode('span');
684
+ commentNode = HASTBuilders.createComment("Content for slot ".concat(node.content.id));
685
+ HASTUtils.addChildNode(spanTagWrapper, commentNode);
686
+ return [2 /*return*/, spanTagWrapper];
687
+ case 5:
688
+ spanTag = HASTBuilders.createHTMLNode('span');
689
+ HASTUtils.addTextNode(spanTag, String(usedReferenceValue.defaultValue));
690
+ return [2 /*return*/, spanTag];
275
691
  }
276
692
  });
277
693
  }); };
278
- var generateDynamicNode = function (node, _, propDefinitions, stateDefinitions) {
279
- var spanTag = HASTBuilders.createHTMLNode('span');
280
- var usedReferenceValue = node.content.referenceType === 'prop'
281
- ? getValueFromReference(node.content.id, propDefinitions)
282
- : getValueFromReference(node.content.id, stateDefinitions);
283
- HASTUtils.addTextNode(spanTag, String(usedReferenceValue));
284
- return spanTag;
285
- };
286
694
  var handleStyles = function (node, styles, propDefinitions, stateDefinitions) {
287
695
  Object.keys(styles).forEach(function (styleKey) {
288
- var _a;
696
+ var _a, _b;
289
697
  var style = styles[styleKey];
290
698
  if (style.type === 'dynamic' && ((_a = style.content) === null || _a === void 0 ? void 0 : _a.referenceType) !== 'token') {
291
- if (style.content.referenceType === 'prop') {
292
- style = getValueFromReference(style.content.id, propDefinitions);
293
- }
294
- else if (style.content.referenceType === 'state') {
295
- style = getValueFromReference(style.content.id, stateDefinitions);
699
+ var referencedValue = getValueFromReference(style.content.id, style.content.referenceType === 'prop' ? propDefinitions : stateDefinitions);
700
+ if (referencedValue.type === 'string' || referencedValue.type === 'number') {
701
+ style = String(extractDefaultValueFromRefPath(referencedValue.defaultValue, (_b = style === null || style === void 0 ? void 0 : style.content) === null || _b === void 0 ? void 0 : _b.refPath));
296
702
  }
297
703
  node.content.style[styleKey] = typeof style === 'string' ? staticNode(style) : style;
298
704
  }
299
705
  });
300
706
  };
301
- var handleAttributes = function (elementType, htmlNode, attrs, propDefinitions, stateDefinitions, routeDefinitions, outputOptions) {
302
- Object.keys(attrs).forEach(function (attrKey) {
707
+ var handleAttributes = function (elementType, htmlNode, attrs, propDefinitions, stateDefinitions, routeDefinitions, outputOptions, currentIndex) {
708
+ var _loop_2 = function (attrKey) {
303
709
  var attrValue = attrs[attrKey];
304
- if (attrKey === 'href' &&
305
- attrValue.type === 'static' &&
306
- typeof attrValue.content === 'string' &&
307
- attrValue.content.startsWith('/')) {
308
- var targetLink = void 0;
309
- var targetRoute = ((routeDefinitions === null || routeDefinitions === void 0 ? void 0 : routeDefinitions.values) || []).find(function (route) { return route.pageOptions.navLink === attrValue.content; });
310
- if (targetRoute) {
311
- targetLink = targetRoute.pageOptions.navLink;
710
+ var type = attrValue.type, content = attrValue.content;
711
+ switch (type) {
712
+ case 'static': {
713
+ if (attrKey === 'href' && typeof content === 'string' && content.startsWith('/')) {
714
+ var targetLink = void 0;
715
+ var targetRoute = ((routeDefinitions === null || routeDefinitions === void 0 ? void 0 : routeDefinitions.values) || []).find(function (route) { return route.pageOptions.navLink === content; });
716
+ if (targetRoute) {
717
+ targetLink = targetRoute.pageOptions.navLink;
718
+ }
719
+ if (!targetRoute && content === '/home') {
720
+ targetLink = '/';
721
+ }
722
+ if (!targetLink && !targetRoute) {
723
+ targetLink = content;
724
+ }
725
+ var currentPageRoute = join.apply(void 0, __spreadArray(__spreadArray([], ((outputOptions === null || outputOptions === void 0 ? void 0 : outputOptions.folderPath) || []), false), ['./'], false));
726
+ var localPrefix = relative("/".concat(currentPageRoute), "/".concat(targetLink === '/' ? 'index' : targetLink));
727
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, "".concat(localPrefix, ".html"));
728
+ break;
729
+ }
730
+ if (typeof content === 'boolean') {
731
+ htmlNode.properties[attrKey] = content === true ? 'true' : 'false';
732
+ }
733
+ else if (typeof content === 'string' || typeof attrValue.content === 'number') {
734
+ var value = StringUtils.encode(String(attrValue.content));
735
+ /*
736
+ elementType of image is always mapped to img.
737
+ For reference, check `html-mapping` file.
738
+ */
739
+ if (elementType === 'img' && attrKey === 'src' && !isValidURL(value)) {
740
+ /*
741
+ By default we just prefix all the asset paths with just the
742
+ assetPrefix that is configured in the project. But for `html` generators
743
+ we need to prefix that with the current file location.
744
+
745
+ Because, all the other frameworks have a build setup. which serves all the
746
+ assets from the `public` folder. But in the case of `html` here is how it works
747
+
748
+ We load a file from `index.html` the request for the image goes from
749
+ '...url.../public/...image...'
750
+ If it's a nested url, then the request goes from
751
+ '...url/nested/public/...image..'
752
+
753
+ But the nested folder is available only on the root. With this
754
+ The url changes prefixes to
755
+
756
+ ../public/playground_assets/..image.. etc depending on the dept the file is in.
757
+ */
758
+ value = join(relative(join.apply(void 0, outputOptions.folderPath), './'), value);
759
+ }
760
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, value);
761
+ }
762
+ break;
312
763
  }
313
- if (!targetRoute && attrValue.content === '/home') {
314
- targetLink = '/';
764
+ case 'dynamic': {
765
+ var value = getValueFromReference(content.id, content.referenceType === 'prop' ? propDefinitions : stateDefinitions);
766
+ var extracted = extractDefaultValueFromRefPath(value.defaultValue, content.refPath);
767
+ var extractedValue = String(extracted);
768
+ if ((elementType === 'img' || elementType === 'video') &&
769
+ attrKey === 'src' &&
770
+ !extractedValue.startsWith('http')) {
771
+ var path = join(relative(join.apply(void 0, outputOptions.folderPath), './'), extractedValue);
772
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, path);
773
+ break;
774
+ }
775
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, extractedValue);
776
+ break;
315
777
  }
316
- if (!targetLink && !targetRoute) {
317
- targetLink = attrValue.content;
778
+ case 'raw': {
779
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, content);
780
+ break;
318
781
  }
319
- var currentPageRoute = join.apply(void 0, __spreadArray(__spreadArray([], ((outputOptions === null || outputOptions === void 0 ? void 0 : outputOptions.folderPath) || []), false), ['./'], false));
320
- var localPrefix = relative("/".concat(currentPageRoute), "/".concat(targetLink === '/' ? 'index' : targetLink));
321
- HASTUtils.addAttributeToNode(htmlNode, attrKey, "".concat(localPrefix, ".html"));
322
- return;
323
- }
324
- if (attrValue.type === 'dynamic') {
325
- var value = attrValue.content.referenceType === 'prop'
326
- ? getValueFromReference(attrValue.content.id, propDefinitions)
327
- : getValueFromReference(attrValue.content.id, stateDefinitions);
328
- HASTUtils.addAttributeToNode(htmlNode, attrKey, String(value));
329
- return;
330
- }
331
- if (attrValue.type === 'raw') {
332
- HASTUtils.addAttributeToNode(htmlNode, attrKey, attrValue.content);
333
- return;
334
- }
335
- if (typeof attrValue.content === 'boolean') {
336
- HASTUtils.addBooleanAttributeToNode(htmlNode, attrKey);
337
- return;
338
- }
339
- else if (typeof attrValue.content === 'string' || typeof attrValue.content === 'number') {
340
- var value = StringUtils.encode(String(attrValue.content));
341
- /*
342
- elementType of image is always mapped to img.
343
- For reference, check `html-mapping` file.
344
- */
345
- if (elementType === 'img' && attrKey === 'src') {
346
- /*
347
- By default we just prefix all the asset paths with just the
348
- assetPrefix that is configured in the project. But for `html` generators
349
- we need to prefix that with the current file location.
350
-
351
- Because, all the other frameworks have a build setup. which serves all the
352
- assets from the `public` folder. But in the case of `html` here is how it works
353
-
354
- We load a file from `index.html` the request for the image goes from
355
- '...url.../public/...image...'
356
- If it's a nested url, then the request goes from
357
- '...url/nested/public/...image..'
358
-
359
- But the nested folder is available only on the root. With this
360
- The url changes prefixes to
361
-
362
- ../public/playground_assets/..image.. etc depending on the dept the file is in.
363
- */
364
- value = join(relative(join.apply(void 0, outputOptions.folderPath), './'), value);
782
+ case 'expr': {
783
+ var fullPath = content.split('?.');
784
+ var prop = propDefinitions[(fullPath === null || fullPath === void 0 ? void 0 : fullPath[0]) || ''];
785
+ if (!prop) {
786
+ break;
787
+ }
788
+ var path = typeof currentIndex === 'number'
789
+ ? __spreadArray([currentIndex.toString()], fullPath.slice(1), true) : fullPath.slice(1);
790
+ var value = extractDefaultValueFromRefPath(prop.defaultValue, path);
791
+ if (!value) {
792
+ break;
793
+ }
794
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, String(value));
795
+ break;
796
+ }
797
+ case 'element':
798
+ case 'import':
799
+ case 'object':
800
+ break;
801
+ default: {
802
+ throw new HTMLComponentGeneratorError("Received ".concat(JSON.stringify(attrValue, null, 2), " \n in handleAttributes for html"));
365
803
  }
366
- HASTUtils.addAttributeToNode(htmlNode, attrKey, value);
367
- return;
368
804
  }
369
- });
805
+ };
806
+ for (var _i = 0, _a = Object.keys(attrs); _i < _a.length; _i++) {
807
+ var attrKey = _a[_i];
808
+ _loop_2(attrKey);
809
+ }
370
810
  };
371
811
  var getValueFromReference = function (key, definitions) {
372
- var usedReferenceValue = definitions[key.includes('.') ? key.split('.')[0] : key];
812
+ var usedReferenceValue = definitions[key.includes('?.') ? key.split('?.')[0] : key];
373
813
  if (!usedReferenceValue) {
374
814
  throw new HTMLComponentGeneratorError("Definition for ".concat(key, " is missing from ").concat(JSON.stringify(definitions, null, 2)));
375
815
  }
376
- if (!usedReferenceValue.hasOwnProperty('defaultValue')) {
816
+ if (['string', 'number', 'object', 'element', 'array', 'boolean'].includes(usedReferenceValue === null || usedReferenceValue === void 0 ? void 0 : usedReferenceValue.type) === false) {
817
+ throw new HTMLComponentGeneratorError("Attribute is using dynamic value, but received of type ".concat(JSON.stringify(usedReferenceValue, null, 2)));
818
+ }
819
+ if (usedReferenceValue.type !== 'element' &&
820
+ usedReferenceValue.hasOwnProperty('defaultValue') === false) {
377
821
  throw new HTMLComponentGeneratorError("Default value is missing from dynamic reference - ".concat(JSON.stringify(usedReferenceValue, null, 2)));
378
822
  }
379
- if (!['string', 'number', 'object'].includes(usedReferenceValue === null || usedReferenceValue === void 0 ? void 0 : usedReferenceValue.type)) {
380
- throw new HTMLComponentGeneratorError("Attribute is using dynamic value, but received of type ".concat(JSON.stringify(usedReferenceValue, null, 2)));
823
+ return usedReferenceValue;
824
+ };
825
+ var extractDefaultValueFromRefPath = function (propDefaultValue, refPath) {
826
+ if (!refPath || refPath.length === 0) {
827
+ return propDefaultValue;
828
+ }
829
+ // Directly handle array indexing for the first segment when applicable
830
+ if (Array.isArray(propDefaultValue)) {
831
+ var first = refPath[0], rest = refPath.slice(1);
832
+ var idx = Number(first);
833
+ if (!Number.isNaN(idx) && idx >= 0 && idx < propDefaultValue.length) {
834
+ var nextVal = propDefaultValue[idx];
835
+ if (rest.length === 0) {
836
+ return nextVal;
837
+ }
838
+ return extractDefaultValueFromRefPath(nextVal, rest);
839
+ }
840
+ }
841
+ if (typeof propDefaultValue !== 'object') {
842
+ return propDefaultValue;
381
843
  }
382
- return String(usedReferenceValue.defaultValue);
844
+ return GenericUtils.getValueFromPath(refPath.join('.'), propDefaultValue);
383
845
  };
384
846
  //# sourceMappingURL=node-handlers.js.map