@teleporthq/teleport-plugin-html-base-component 0.40.0-alpha.0 → 0.40.1

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