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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -55,61 +55,158 @@ 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, node, tag, nodesLoookup, hierarchy) {
76
+ if (hierarchy === void 0) { hierarchy = []; }
77
+ // In html code-generation we combine the nodes of the component that is being consumed with the current component.
78
+ // As html can't load the component at runtime like react or any other frameworks. So, we merge the component as a standalone
79
+ // component in the current component.
80
+ if (nodesLoookup[key]) {
81
+ throw new HTMLComponentGeneratorError("\n".concat(hierarchy.join(' -> '), " \n\nDuplicate key found in nodesLookup: ").concat(node.content.key, " \n\n\nA node with the same key already exists\n\nReceived \n\n ").concat(JSON.stringify(tag), "\n ").concat(JSON.stringify(node), "\nExisting \n\n ").concat(JSON.stringify(nodesLoookup[key]), " \n\n"));
82
+ }
83
+ nodesLoookup[key] = tag;
84
+ };
85
+ export var generateHtmlSyntax = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
86
+ var _a, elementNode, dynamicNode, conditionalNodeComment, _b, staticValue, reference, _c, conditions, matchingCriteria, _d, referenceType, id, refPath, usedProp, defaultValue, _i, refPath_1, path, dynamicConditions, matchCondition, conditionString, isConditionPassing;
87
+ return __generator(this, function (_e) {
88
+ switch (_e.label) {
89
+ case 0:
90
+ _a = node.type;
91
+ switch (_a) {
92
+ case 'inject': return [3 /*break*/, 1];
93
+ case 'raw': return [3 /*break*/, 1];
94
+ case 'static': return [3 /*break*/, 2];
95
+ case 'slot': return [3 /*break*/, 3];
96
+ case 'element': return [3 /*break*/, 4];
97
+ case 'dynamic': return [3 /*break*/, 6];
98
+ case 'conditional': return [3 /*break*/, 8];
99
+ case 'expr': return [3 /*break*/, 9];
100
+ }
101
+ return [3 /*break*/, 10];
102
+ case 1: return [2 /*return*/, HASTBuilders.createTextNode(node.content.toString())];
103
+ case 2: return [2 /*return*/, HASTBuilders.createTextNode(StringUtils.encode(node.content.toString()))];
104
+ case 3: return [2 /*return*/, HASTBuilders.createHTMLNode(node.type)];
105
+ case 4: return [4 /*yield*/, generateElementNode(node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
106
+ case 5:
107
+ elementNode = _e.sent();
108
+ return [2 /*return*/, elementNode];
109
+ case 6: return [4 /*yield*/, generateDynamicNode(node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
110
+ case 7:
111
+ dynamicNode = _e.sent();
112
+ return [2 /*return*/, dynamicNode];
113
+ case 8:
114
+ conditionalNodeComment = HASTBuilders.createComment('Conditional nodes are not supported in HTML');
115
+ _b = node.content, staticValue = _b.value, reference = _b.reference, _c = _b.condition, conditions = _c.conditions, matchingCriteria = _c.matchingCriteria;
116
+ if (reference.type !== 'dynamic') {
117
+ return [2 /*return*/, conditionalNodeComment];
118
+ }
119
+ _d = reference.content, referenceType = _d.referenceType, id = _d.id, refPath = _d.refPath;
120
+ switch (referenceType) {
121
+ case 'prop': {
122
+ usedProp = propDefinitions[id];
123
+ if (usedProp === undefined || usedProp.defaultValue === undefined) {
124
+ return [2 /*return*/, conditionalNodeComment];
125
+ }
126
+ defaultValue = usedProp.defaultValue;
127
+ for (_i = 0, refPath_1 = refPath; _i < refPath_1.length; _i++) {
128
+ path = refPath_1[_i];
129
+ defaultValue = defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue[path];
130
+ }
131
+ // Safety measure in case no value is found
132
+ if (!defaultValue) {
133
+ defaultValue = usedProp.defaultValue;
134
+ }
135
+ dynamicConditions = createConditionalStatement(staticValue !== undefined ? [{ operand: staticValue, operation: '===' }] : conditions, defaultValue);
136
+ matchCondition = matchingCriteria && matchingCriteria === 'all' ? '&&' : '||';
137
+ conditionString = dynamicConditions.join(" ".concat(matchCondition, " "));
138
+ try {
139
+ isConditionPassing = new Function("return ".concat(conditionString))();
140
+ if (isConditionPassing) {
141
+ return [2 /*return*/, generateHtmlSyntax(node.content.node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
142
+ }
143
+ }
144
+ catch (error) {
145
+ return [2 /*return*/, conditionalNodeComment];
146
+ }
147
+ return [2 /*return*/, conditionalNodeComment];
148
+ }
149
+ case 'state':
150
+ default:
151
+ return [2 /*return*/, conditionalNodeComment];
152
+ }
153
+ _e.label = 9;
154
+ case 9: return [2 /*return*/, HASTBuilders.createComment('Expressions are not supported in HTML')];
155
+ case 10: throw new HTMLComponentGeneratorError("generateHtmlSyntax encountered a node of unsupported type: ".concat(JSON.stringify(node, null, 2), " "));
79
156
  }
80
- return [2 /*return*/];
81
157
  });
82
158
  }); };
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;
159
+ var createConditionalStatement = function (conditions, leftOperand) {
160
+ return conditions.map(function (condition) {
161
+ var operation = condition.operation, operand = condition.operand;
162
+ if (operand === undefined) {
163
+ return "".concat(ASTUtils.convertToUnaryOperator(operation)).concat(getValueType(operand));
164
+ }
165
+ return "".concat(getValueType(leftOperand), " ").concat(ASTUtils.convertToBinaryOperator(operation), " ").concat(getValueType(operand));
166
+ });
167
+ };
168
+ var getValueType = function (value) {
169
+ var valueType = typeof value;
170
+ switch (valueType) {
171
+ case 'string':
172
+ return "\"".concat(value, "\"");
173
+ case 'number':
174
+ return value;
175
+ case 'boolean':
176
+ return value;
177
+ default:
178
+ throw new HTMLComponentGeneratorError("Conditional node received an operand of type ".concat(valueType, " \n\n Received ").concat(JSON.stringify(value)));
179
+ }
180
+ };
181
+ var generateElementNode = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
182
+ var _a, elementType, children, _b, attrs, _c, style, _d, referencedStyles, dependency, dependencies, compTag, elementNode, _i, children_1, child, childTag;
85
183
  return __generator(this, function (_e) {
86
184
  switch (_e.label) {
87
185
  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;
186
+ _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
187
  dependencies = structure.dependencies;
92
- if (dependency && (dependency === null || dependency === void 0 ? void 0 : dependency.type) !== 'local') {
93
- dependencies[dependency.path] = dependency;
94
- }
95
188
  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)];
189
+ return [4 /*yield*/, generateComponentContent(node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
97
190
  case 1:
98
191
  compTag = _e.sent();
192
+ if ('tagName' in compTag) {
193
+ compTag.children.unshift(HASTBuilders.createComment("".concat(node.content.semanticType, " component")));
194
+ }
99
195
  return [2 /*return*/, compTag];
100
196
  case 2:
197
+ if (dependency && (dependency === null || dependency === void 0 ? void 0 : dependency.type) !== 'local') {
198
+ dependencies[dependency.path] = dependency;
199
+ }
200
+ elementNode = HASTBuilders.createHTMLNode(elementType);
101
201
  if (!children) return [3 /*break*/, 6];
102
202
  _i = 0, children_1 = children;
103
203
  _e.label = 3;
104
204
  case 3:
105
205
  if (!(_i < children_1.length)) return [3 /*break*/, 6];
106
206
  child = children_1[_i];
107
- return [4 /*yield*/, generateHtmlSynatx(child, templatesLookUp, propDefinitions, stateDefinitions, subComponentOptions, routeDefinitions, structure)];
207
+ return [4 /*yield*/, generateHtmlSyntax(child, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
108
208
  case 4:
109
209
  childTag = _e.sent();
110
- if (!childTag) {
111
- return [2 /*return*/];
112
- }
113
210
  if (typeof childTag === 'string') {
114
211
  HASTUtils.addTextNode(elementNode, childTag);
115
212
  }
@@ -126,38 +223,47 @@ var generatElementNode = function (node, templatesLookUp, propDefinitions, state
126
223
  var refStyle = referencedStyles[styleRef];
127
224
  if (refStyle.content.mapType === 'inlined') {
128
225
  handleStyles(node, refStyle.content.styles, propDefinitions, stateDefinitions);
129
- return;
130
226
  }
131
227
  });
132
228
  }
133
229
  if (Object.keys(style).length > 0) {
134
230
  handleStyles(node, style, propDefinitions, stateDefinitions);
135
231
  }
136
- if (Object.keys(attrs).length > 0) {
137
- handleAttributes(elementNode, attrs, propDefinitions, stateDefinitions, routeDefinitions);
138
- }
232
+ handleAttributes(elementType, elementNode, attrs, propDefinitions, stateDefinitions, structure.options.projectRouteDefinition, structure.outputOptions);
233
+ addNodeToLookup(node.content.key, node, elementNode, nodesLookup, [compName]);
139
234
  return [2 /*return*/, elementNode];
140
235
  }
141
236
  });
142
237
  }); };
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) {
238
+ var createLookupTable = function (component, nodesLookup) {
239
+ var lookup = {};
240
+ for (var _i = 0, _a = Object.keys(nodesLookup); _i < _a.length; _i++) {
241
+ var node = _a[_i];
242
+ lookup[node] = {
243
+ count: 1,
244
+ nextKey: '1',
245
+ };
246
+ }
247
+ createNodesLookup(component, lookup);
248
+ return lookup;
249
+ };
250
+ var generateComponentContent = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
251
+ var externals, plugins, _a, elementType, _b, attrs, _c, children, dependencies, _d, chunks, options, componentName, component, componentClone, lookupTableForCurrentPage, combinedProps, combinedStates, statesForInstance, propsForInstance, _i, _e, propKey, attribute, propFromCurrentComponent, componentWrapper, isExistingNode, componentInstanceToGenerate, compTag, cssPlugin, initialStructure, result;
252
+ var _f, _g;
253
+ return __generator(this, function (_h) {
254
+ switch (_h.label) {
148
255
  case 0:
149
256
  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;
257
+ _a = node.content, elementType = _a.elementType, _b = _a.attrs, attrs = _b === void 0 ? {} : _b, _c = _a.children, children = _c === void 0 ? [] : _c;
151
258
  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)));
259
+ componentName = elementType === 'Component' ? 'AppComponent' : elementType;
260
+ component = externals[componentName];
261
+ if (component === undefined) {
262
+ throw new HTMLComponentGeneratorError("".concat(componentName, " is missing from externals object"));
157
263
  }
264
+ componentClone = UIDLUtils.cloneObject(component);
158
265
  if (children.length) {
159
- compHasSlots = true;
160
- UIDLUtils.traverseNodes(comp.node, function (childNode, parentNode) {
266
+ UIDLUtils.traverseNodes(componentClone.node, function (childNode, parentNode) {
161
267
  var _a, _b;
162
268
  if (childNode.type === 'slot' && parentNode.type === 'element') {
163
269
  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 +273,7 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
167
273
  content: {
168
274
  key: 'custom-slot',
169
275
  elementType: 'slot',
276
+ name: componentClone.name + 'slot',
170
277
  style: {
171
278
  display: {
172
279
  type: 'static',
@@ -185,46 +292,115 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
185
292
  */
186
293
  node.content.children = [];
187
294
  }
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];
295
+ lookupTableForCurrentPage = createLookupTable(componentClone, nodesLookup);
296
+ generateUniqueKeys(componentClone, lookupTableForCurrentPage);
297
+ combinedProps = __assign(__assign({}, Object.keys(propDefinitions).reduce(function (acc, propKey) {
298
+ var _a;
299
+ if (((_a = propDefinitions[propKey]) === null || _a === void 0 ? void 0 : _a.type) === 'element') {
300
+ return acc;
196
301
  }
302
+ acc[propKey] = propDefinitions[propKey];
197
303
  return acc;
198
- }, {});
199
- combinedStates = __assign(__assign({}, stateDefinitions), ((comp === null || comp === void 0 ? void 0 : comp.stateDefinitions) || {}));
304
+ }, {})), ((componentClone === null || componentClone === void 0 ? void 0 : componentClone.propDefinitions) || {}));
305
+ combinedStates = __assign(__assign({}, stateDefinitions), ((componentClone === null || componentClone === void 0 ? void 0 : componentClone.stateDefinitions) || {}));
200
306
  statesForInstance = Object.keys(combinedStates).reduce(function (acc, propKey) {
201
- 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) });
307
+ var _a;
308
+ var attr = attrs[propKey];
309
+ if (attr.type === 'object') {
310
+ throw new Error("Object attributes are not supported in html exports");
311
+ }
312
+ if (attr) {
313
+ acc[propKey] = __assign(__assign({}, combinedStates[propKey]), { defaultValue: (attr === null || attr === void 0 ? void 0 : attr.content) || ((_a = combinedStates[propKey]) === null || _a === void 0 ? void 0 : _a.defaultValue) });
204
314
  }
205
315
  else {
206
316
  acc[propKey] = combinedStates[propKey];
207
317
  }
208
318
  return acc;
209
319
  }, {});
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)];
320
+ propsForInstance = {};
321
+ _i = 0, _e = Object.keys(combinedProps);
322
+ _h.label = 1;
216
323
  case 1:
217
- compTag = (_f.sent());
324
+ if (!(_i < _e.length)) return [3 /*break*/, 7];
325
+ propKey = _e[_i];
326
+ attribute = attrs[propKey];
327
+ if (!((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'element')) return [3 /*break*/, 3];
328
+ propsForInstance[propKey] = __assign(__assign({}, combinedProps[propKey]), { defaultValue: attrs[propKey] });
329
+ return [4 /*yield*/, generateHtmlSyntax(attrs[propKey], component.name, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
330
+ case 2:
331
+ _h.sent();
332
+ _h.label = 3;
333
+ case 3:
334
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'dynamic') {
335
+ // When we are using a component instance in a component and the attribute
336
+ // that is passed to the component is of dynamic reference.
337
+ // If means, the component is redirecting the prop that is received to the prop of the component that it is consuming.
338
+ // 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.
339
+ // And similary we do the same for the states.
340
+ switch (attribute.content.referenceType) {
341
+ case 'prop':
342
+ propsForInstance[propKey] = combinedProps[propKey];
343
+ break;
344
+ case 'state':
345
+ propsForInstance[propKey] = combinedStates[propKey];
346
+ break;
347
+ default:
348
+ throw new Error("ReferenceType ".concat(attribute.content.referenceType, " is not supported in HTML Export."));
349
+ }
350
+ }
351
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) === 'object') {
352
+ 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) });
353
+ }
354
+ if ((attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'dynamic' &&
355
+ (attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'element' &&
356
+ (attribute === null || attribute === void 0 ? void 0 : attribute.type) !== 'object') {
357
+ propsForInstance[propKey] = __assign(__assign({}, combinedProps[propKey]), { defaultValue: (attribute === null || attribute === void 0 ? void 0 : attribute.content) || ((_g = combinedProps[propKey]) === null || _g === void 0 ? void 0 : _g.defaultValue) });
358
+ }
359
+ if (!(attribute === undefined)) return [3 /*break*/, 6];
360
+ propFromCurrentComponent = combinedProps[propKey];
361
+ if (!(propFromCurrentComponent.type === 'element' && propFromCurrentComponent.defaultValue)) return [3 /*break*/, 5];
362
+ return [4 /*yield*/, generateHtmlSyntax(propFromCurrentComponent.defaultValue, component.name, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
363
+ case 4:
364
+ _h.sent();
365
+ _h.label = 5;
366
+ case 5:
367
+ propsForInstance[propKey] = propFromCurrentComponent;
368
+ _h.label = 6;
369
+ case 6:
370
+ _i++;
371
+ return [3 /*break*/, 1];
372
+ case 7:
373
+ componentWrapper = StringUtils.camelCaseToDashCase("".concat(componentName, "-wrapper"));
374
+ isExistingNode = nodesLookup[componentWrapper];
375
+ if (isExistingNode !== undefined) {
376
+ componentWrapper = "".concat(componentWrapper, "-").concat(StringUtils.generateRandomString());
377
+ }
378
+ componentInstanceToGenerate = {
379
+ type: 'element',
380
+ content: {
381
+ elementType: componentWrapper,
382
+ key: componentWrapper,
383
+ children: [componentClone.node],
384
+ style: {
385
+ display: {
386
+ type: 'static',
387
+ content: 'contents',
388
+ },
389
+ },
390
+ },
391
+ };
392
+ return [4 /*yield*/, generateHtmlSyntax(componentInstanceToGenerate, component.name, nodesLookup, propsForInstance, statesForInstance, subComponentOptions, structure)];
393
+ case 8:
394
+ compTag = _h.sent();
218
395
  cssPlugin = createCSSPlugin({
219
396
  templateStyle: 'html',
220
397
  templateChunkName: DEFAULT_COMPONENT_CHUNK_NAME,
221
398
  declareDependency: 'import',
222
- forceScoping: true,
223
- chunkName: comp.name,
399
+ chunkName: componentClone.name,
224
400
  staticPropReferences: true,
225
401
  });
226
402
  initialStructure = {
227
- uidl: __assign(__assign({}, comp), { propDefinitions: propsForInstance, stateDefinitions: statesForInstance }),
403
+ uidl: __assign(__assign({}, componentClone), { node: componentInstanceToGenerate, propDefinitions: propsForInstance, stateDefinitions: statesForInstance }),
228
404
  chunks: [
229
405
  {
230
406
  type: ChunkType.HAST,
@@ -233,7 +409,7 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
233
409
  linkAfter: [],
234
410
  content: compTag,
235
411
  meta: {
236
- nodesLookup: lookUpTemplates,
412
+ nodesLookup: nodesLookup,
237
413
  },
238
414
  },
239
415
  ],
@@ -251,100 +427,170 @@ var generateComponentContent = function (node, propDefinitions, stateDefinitions
251
427
  }
252
428
  });
253
429
  }); }, Promise.resolve(initialStructure))];
254
- 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);
430
+ case 9:
431
+ result = _h.sent();
432
+ result.chunks.forEach(function (chunk) {
433
+ if (chunk.fileType === FileType.CSS) {
434
+ chunks.push(chunk);
271
435
  }
272
- }
436
+ });
437
+ addNodeToLookup(node.content.key, node, compTag, nodesLookup, [compName, component.name]);
273
438
  return [2 /*return*/, compTag];
274
439
  }
275
440
  });
276
441
  }); };
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
- };
442
+ var generateDynamicNode = function (node, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure) { return __awaiter(void 0, void 0, void 0, function () {
443
+ var localeTag, commentNode, usedReferenceValue, elementNode, elementTag, spanTagWrapper, commentNode, spanTag;
444
+ return __generator(this, function (_a) {
445
+ switch (_a.label) {
446
+ case 0:
447
+ if (node.content.referenceType === 'locale') {
448
+ localeTag = HASTBuilders.createHTMLNode('span');
449
+ commentNode = HASTBuilders.createComment("Content for locale ".concat(node.content.id));
450
+ HASTUtils.addChildNode(localeTag, commentNode);
451
+ return [2 /*return*/, localeTag];
452
+ }
453
+ usedReferenceValue = getValueFromReference(node.content.id, node.content.referenceType === 'prop' ? propDefinitions : stateDefinitions);
454
+ if ((usedReferenceValue.type === 'object' || usedReferenceValue.type === 'array') &&
455
+ usedReferenceValue.defaultValue) {
456
+ // Let's say users are biding the prop to a node using something like this "fields.Title"
457
+ // But the fields in the object is the value where the object is defined either in propDefinitions
458
+ // or on the attrs. So, we just need to parsed the rest of the object path and get the value from the object.
459
+ return [2 /*return*/, HASTBuilders.createTextNode(String(extractDefaultValueFromRefPath(usedReferenceValue.defaultValue, node.content.refPath)))];
460
+ }
461
+ if (!(usedReferenceValue.type === 'element')) return [3 /*break*/, 4];
462
+ elementNode = usedReferenceValue.defaultValue;
463
+ if (!elementNode) return [3 /*break*/, 3];
464
+ if (!(elementNode.content.key in nodesLookup)) return [3 /*break*/, 1];
465
+ return [2 /*return*/, nodesLookup[elementNode.content.key]];
466
+ case 1: return [4 /*yield*/, generateHtmlSyntax(elementNode, compName, nodesLookup, propDefinitions, stateDefinitions, subComponentOptions, structure)];
467
+ case 2:
468
+ elementTag = _a.sent();
469
+ return [2 /*return*/, elementTag];
470
+ case 3:
471
+ spanTagWrapper = HASTBuilders.createHTMLNode('span');
472
+ commentNode = HASTBuilders.createComment("Content for slot ".concat(node.content.id));
473
+ HASTUtils.addChildNode(spanTagWrapper, commentNode);
474
+ return [2 /*return*/, spanTagWrapper];
475
+ case 4:
476
+ spanTag = HASTBuilders.createHTMLNode('span');
477
+ HASTUtils.addTextNode(spanTag, String(usedReferenceValue.defaultValue));
478
+ return [2 /*return*/, spanTag];
479
+ }
480
+ });
481
+ }); };
285
482
  var handleStyles = function (node, styles, propDefinitions, stateDefinitions) {
286
483
  Object.keys(styles).forEach(function (styleKey) {
287
- var _a;
484
+ var _a, _b;
288
485
  var style = styles[styleKey];
289
486
  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);
487
+ var referencedValue = getValueFromReference(style.content.id, style.content.referenceType === 'prop' ? propDefinitions : stateDefinitions);
488
+ if (referencedValue.type === 'string' || referencedValue.type === 'number') {
489
+ style = String(extractDefaultValueFromRefPath(referencedValue.defaultValue, (_b = style === null || style === void 0 ? void 0 : style.content) === null || _b === void 0 ? void 0 : _b.refPath));
295
490
  }
296
491
  node.content.style[styleKey] = typeof style === 'string' ? staticNode(style) : style;
297
492
  }
298
493
  });
299
494
  };
300
- var handleAttributes = function (htmlNode, attrs, propDefinitions, stateDefinitions, routeDefinitions) {
301
- Object.keys(attrs).forEach(function (attrKey) {
495
+ var handleAttributes = function (elementType, htmlNode, attrs, propDefinitions, stateDefinitions, routeDefinitions, outputOptions) {
496
+ var _loop_1 = function (attrKey) {
302
497
  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;
498
+ var type = attrValue.type, content = attrValue.content;
499
+ switch (type) {
500
+ case 'static': {
501
+ if (attrKey === 'href' && typeof content === 'string' && content.startsWith('/')) {
502
+ var targetLink = void 0;
503
+ var targetRoute = ((routeDefinitions === null || routeDefinitions === void 0 ? void 0 : routeDefinitions.values) || []).find(function (route) { return route.pageOptions.navLink === content; });
504
+ if (targetRoute) {
505
+ targetLink = targetRoute.pageOptions.navLink;
506
+ }
507
+ if (!targetRoute && content === '/home') {
508
+ targetLink = '/';
509
+ }
510
+ if (!targetLink && !targetRoute) {
511
+ targetLink = content;
512
+ }
513
+ var currentPageRoute = join.apply(void 0, __spreadArray(__spreadArray([], ((outputOptions === null || outputOptions === void 0 ? void 0 : outputOptions.folderPath) || []), false), ['./'], false));
514
+ var localPrefix = relative("/".concat(currentPageRoute), "/".concat(targetLink === '/' ? 'index' : targetLink));
515
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, "".concat(localPrefix, ".html"));
516
+ break;
517
+ }
518
+ if (typeof content === 'boolean') {
519
+ htmlNode.properties[attrKey] = content === true ? 'true' : 'false';
520
+ }
521
+ else if (typeof content === 'string' || typeof attrValue.content === 'number') {
522
+ var value = StringUtils.encode(String(attrValue.content));
523
+ /*
524
+ elementType of image is always mapped to img.
525
+ For reference, check `html-mapping` file.
526
+ */
527
+ if (elementType === 'img' && attrKey === 'src' && !isValidURL(value)) {
528
+ /*
529
+ By default we just prefix all the asset paths with just the
530
+ assetPrefix that is configured in the project. But for `html` generators
531
+ we need to prefix that with the current file location.
532
+
533
+ Because, all the other frameworks have a build setup. which serves all the
534
+ assets from the `public` folder. But in the case of `html` here is how it works
535
+
536
+ We load a file from `index.html` the request for the image goes from
537
+ '...url.../public/...image...'
538
+ If it's a nested url, then the request goes from
539
+ '...url/nested/public/...image..'
540
+
541
+ But the nested folder is available only on the root. With this
542
+ The url changes prefixes to
543
+
544
+ ../public/playground_assets/..image.. etc depending on the dept the file is in.
545
+ */
546
+ value = join(relative(join.apply(void 0, outputOptions.folderPath), './'), value);
547
+ }
548
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, value);
549
+ }
550
+ break;
551
+ }
552
+ case 'dynamic': {
553
+ var value = getValueFromReference(content.id, content.referenceType === 'prop' ? propDefinitions : stateDefinitions);
554
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, String(extractDefaultValueFromRefPath(value.defaultValue, content.refPath)));
555
+ break;
556
+ }
557
+ case 'raw': {
558
+ HASTUtils.addAttributeToNode(htmlNode, attrKey, content);
559
+ break;
560
+ }
561
+ case 'element':
562
+ case 'import':
563
+ case 'expr':
564
+ case 'object':
565
+ break;
566
+ default: {
567
+ throw new HTMLComponentGeneratorError("Received ".concat(JSON.stringify(attrValue, null, 2), " \n in handleAttributes for html"));
568
+ }
334
569
  }
335
- });
570
+ };
571
+ for (var _i = 0, _a = Object.keys(attrs); _i < _a.length; _i++) {
572
+ var attrKey = _a[_i];
573
+ _loop_1(attrKey);
574
+ }
336
575
  };
337
576
  var getValueFromReference = function (key, definitions) {
338
- var usedReferenceValue = definitions[key.includes('.') ? key.split('.')[0] : key];
577
+ var usedReferenceValue = definitions[key.includes('?.') ? key.split('?.')[0] : key];
339
578
  if (!usedReferenceValue) {
340
579
  throw new HTMLComponentGeneratorError("Definition for ".concat(key, " is missing from ").concat(JSON.stringify(definitions, null, 2)));
341
580
  }
342
- if (!usedReferenceValue.hasOwnProperty('defaultValue')) {
581
+ if (['string', 'number', 'object', 'element', 'array'].includes(usedReferenceValue === null || usedReferenceValue === void 0 ? void 0 : usedReferenceValue.type) === false) {
582
+ throw new HTMLComponentGeneratorError("Attribute is using dynamic value, but received of type ".concat(JSON.stringify(usedReferenceValue, null, 2)));
583
+ }
584
+ if (usedReferenceValue.type !== 'element' &&
585
+ usedReferenceValue.hasOwnProperty('defaultValue') === false) {
343
586
  throw new HTMLComponentGeneratorError("Default value is missing from dynamic reference - ".concat(JSON.stringify(usedReferenceValue, null, 2)));
344
587
  }
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)));
588
+ return usedReferenceValue;
589
+ };
590
+ var extractDefaultValueFromRefPath = function (propDefaultValue, refPath) {
591
+ if (typeof propDefaultValue !== 'object' || !(refPath === null || refPath === void 0 ? void 0 : refPath.length)) {
592
+ return propDefaultValue;
347
593
  }
348
- return String(usedReferenceValue.defaultValue);
594
+ return GenericUtils.getValueFromPath(refPath.join('.'), propDefaultValue);
349
595
  };
350
596
  //# sourceMappingURL=node-handlers.js.map