@teleporthq/teleport-plugin-common 0.42.35 → 0.43.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.
Files changed (91) hide show
  1. package/__tests__/node-handlers/node-to-jsx/index.ts +164 -0
  2. package/__tests__/node-handlers/node-to-jsx/url-search-params-expression.ts +59 -0
  3. package/__tests__/node-handlers/node-to-jsx/utils.ts +217 -0
  4. package/__tests__/utils/ast-utils.ts +135 -0
  5. package/__tests__/utils/content-property-sanitiser.ts +156 -0
  6. package/__tests__/utils/url-search-params.ts +48 -0
  7. package/dist/cjs/builders/ast-builders.d.ts +1 -0
  8. package/dist/cjs/builders/ast-builders.d.ts.map +1 -1
  9. package/dist/cjs/builders/ast-builders.js +9 -1
  10. package/dist/cjs/builders/ast-builders.js.map +1 -1
  11. package/dist/cjs/builders/style-builders.d.ts +7 -0
  12. package/dist/cjs/builders/style-builders.d.ts.map +1 -1
  13. package/dist/cjs/builders/style-builders.js +35 -1
  14. package/dist/cjs/builders/style-builders.js.map +1 -1
  15. package/dist/cjs/node-handlers/node-to-html/index.d.ts.map +1 -1
  16. package/dist/cjs/node-handlers/node-to-html/index.js +19 -3
  17. package/dist/cjs/node-handlers/node-to-html/index.js.map +1 -1
  18. package/dist/cjs/node-handlers/node-to-html/utils.d.ts +2 -1
  19. package/dist/cjs/node-handlers/node-to-html/utils.d.ts.map +1 -1
  20. package/dist/cjs/node-handlers/node-to-html/utils.js +94 -11
  21. package/dist/cjs/node-handlers/node-to-html/utils.js.map +1 -1
  22. package/dist/cjs/node-handlers/node-to-jsx/index.d.ts.map +1 -1
  23. package/dist/cjs/node-handlers/node-to-jsx/index.js +701 -42
  24. package/dist/cjs/node-handlers/node-to-jsx/index.js.map +1 -1
  25. package/dist/cjs/node-handlers/node-to-jsx/types.d.ts +40 -2
  26. package/dist/cjs/node-handlers/node-to-jsx/types.d.ts.map +1 -1
  27. package/dist/cjs/node-handlers/node-to-jsx/utils.d.ts +50 -5
  28. package/dist/cjs/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
  29. package/dist/cjs/node-handlers/node-to-jsx/utils.js +492 -35
  30. package/dist/cjs/node-handlers/node-to-jsx/utils.js.map +1 -1
  31. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  32. package/dist/cjs/utils/ast-utils.d.ts +70 -4
  33. package/dist/cjs/utils/ast-utils.d.ts.map +1 -1
  34. package/dist/cjs/utils/ast-utils.js +414 -28
  35. package/dist/cjs/utils/ast-utils.js.map +1 -1
  36. package/dist/cjs/utils/style-utils.d.ts +1 -0
  37. package/dist/cjs/utils/style-utils.d.ts.map +1 -1
  38. package/dist/cjs/utils/style-utils.js +155 -2
  39. package/dist/cjs/utils/style-utils.js.map +1 -1
  40. package/dist/cjs/utils/url-search-params.d.ts +48 -0
  41. package/dist/cjs/utils/url-search-params.d.ts.map +1 -0
  42. package/dist/cjs/utils/url-search-params.js +109 -0
  43. package/dist/cjs/utils/url-search-params.js.map +1 -0
  44. package/dist/esm/builders/ast-builders.d.ts +1 -0
  45. package/dist/esm/builders/ast-builders.d.ts.map +1 -1
  46. package/dist/esm/builders/ast-builders.js +7 -0
  47. package/dist/esm/builders/ast-builders.js.map +1 -1
  48. package/dist/esm/builders/style-builders.d.ts +7 -0
  49. package/dist/esm/builders/style-builders.d.ts.map +1 -1
  50. package/dist/esm/builders/style-builders.js +33 -0
  51. package/dist/esm/builders/style-builders.js.map +1 -1
  52. package/dist/esm/node-handlers/node-to-html/index.d.ts.map +1 -1
  53. package/dist/esm/node-handlers/node-to-html/index.js +20 -4
  54. package/dist/esm/node-handlers/node-to-html/index.js.map +1 -1
  55. package/dist/esm/node-handlers/node-to-html/utils.d.ts +2 -1
  56. package/dist/esm/node-handlers/node-to-html/utils.d.ts.map +1 -1
  57. package/dist/esm/node-handlers/node-to-html/utils.js +93 -11
  58. package/dist/esm/node-handlers/node-to-html/utils.js.map +1 -1
  59. package/dist/esm/node-handlers/node-to-jsx/index.d.ts.map +1 -1
  60. package/dist/esm/node-handlers/node-to-jsx/index.js +703 -44
  61. package/dist/esm/node-handlers/node-to-jsx/index.js.map +1 -1
  62. package/dist/esm/node-handlers/node-to-jsx/types.d.ts +40 -2
  63. package/dist/esm/node-handlers/node-to-jsx/types.d.ts.map +1 -1
  64. package/dist/esm/node-handlers/node-to-jsx/utils.d.ts +50 -5
  65. package/dist/esm/node-handlers/node-to-jsx/utils.d.ts.map +1 -1
  66. package/dist/esm/node-handlers/node-to-jsx/utils.js +486 -33
  67. package/dist/esm/node-handlers/node-to-jsx/utils.js.map +1 -1
  68. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  69. package/dist/esm/utils/ast-utils.d.ts +70 -4
  70. package/dist/esm/utils/ast-utils.d.ts.map +1 -1
  71. package/dist/esm/utils/ast-utils.js +403 -27
  72. package/dist/esm/utils/ast-utils.js.map +1 -1
  73. package/dist/esm/utils/style-utils.d.ts +1 -0
  74. package/dist/esm/utils/style-utils.d.ts.map +1 -1
  75. package/dist/esm/utils/style-utils.js +153 -1
  76. package/dist/esm/utils/style-utils.js.map +1 -1
  77. package/dist/esm/utils/url-search-params.d.ts +48 -0
  78. package/dist/esm/utils/url-search-params.d.ts.map +1 -0
  79. package/dist/esm/utils/url-search-params.js +81 -0
  80. package/dist/esm/utils/url-search-params.js.map +1 -0
  81. package/package.json +4 -4
  82. package/src/builders/ast-builders.ts +26 -0
  83. package/src/builders/style-builders.ts +64 -0
  84. package/src/node-handlers/node-to-html/index.ts +34 -4
  85. package/src/node-handlers/node-to-html/utils.ts +111 -11
  86. package/src/node-handlers/node-to-jsx/index.ts +999 -52
  87. package/src/node-handlers/node-to-jsx/types.ts +48 -3
  88. package/src/node-handlers/node-to-jsx/utils.ts +655 -31
  89. package/src/utils/ast-utils.ts +547 -28
  90. package/src/utils/style-utils.ts +157 -1
  91. package/src/utils/url-search-params.ts +122 -0
@@ -50,6 +50,107 @@ var ast_utils_1 = require("../../utils/ast-utils");
50
50
  var ast_builders_1 = require("../../builders/ast-builders");
51
51
  var constants_1 = require("./constants");
52
52
  var __1 = require("../..");
53
+ // Global references in the UIDL come in two shapes:
54
+ // Shape A: { id: "ecommerce", refPath: ["Cart", "total"] }
55
+ // Shape B: { id: undefined, refPath: ["E-commerce", "Settings", "Delivery", "..."] }
56
+ // This helper normalizes Shape B into Shape A so downstream code can handle
57
+ // both uniformly. The first refPath segment is mapped to a variable name via
58
+ // GLOBAL_REF_ID_MAP (exported from ast-utils so all sites stay in sync).
59
+ // Expression attributes (UIDLExpressionValue) bypass the dynamic-reference
60
+ // tracking in createDynamicValueExpression. When such an expression mentions
61
+ // a known global (currentUser/ecommerce/cart/locale/userIsLoggedIn) we still
62
+ // Plan v15 Layer 4 — junk-name attribute guard.
63
+ // AI fabrication artefacts emit attributes whose KEY is a JS literal
64
+ // (`true="true"`, `false="false"`, `0="x"`, `null="..."`). They survive JSX
65
+ // parsing (treated as string-valued attrs) but break DOM semantics. The
66
+ // upstream Layer 1–3 pipeline should already strip them; this is the final
67
+ // codegen safety net.
68
+ var CODEGEN_JUNK_ATTR_NAMES = new Set(['true', 'false', 'null', 'undefined']);
69
+ function isJunkAttributeName(name) {
70
+ if (typeof name !== 'string' || name.length === 0) {
71
+ return true;
72
+ }
73
+ var lower = name.toLowerCase();
74
+ if (CODEGEN_JUNK_ATTR_NAMES.has(lower)) {
75
+ return true;
76
+ }
77
+ if (/^[0-9]+$/.test(name)) {
78
+ return true;
79
+ }
80
+ return false;
81
+ }
82
+ function hasCorruptBindingMarkers(value) {
83
+ // Entity-escaped `{` / `}` from upstream serialization that should never
84
+ // reach the JSX output verbatim.
85
+ if (/{|}/.test(value)) {
86
+ return true;
87
+ }
88
+ // Unbalanced `{{` (no matching `}}`).
89
+ var opens = (value.match(/\{\{/g) || []).length;
90
+ var closes = (value.match(/\}\}/g) || []).length;
91
+ if (opens > closes) {
92
+ return true;
93
+ }
94
+ return false;
95
+ }
96
+ function truncate(value) {
97
+ if (value.length <= 60) {
98
+ return value;
99
+ }
100
+ return value.slice(0, 57) + '...';
101
+ }
102
+ // need to push it into params.globalReferences so downstream plugins inject
103
+ // the corresponding `useGlobalContext()` destructuring.
104
+ var GLOBAL_EXPRESSION_IDENTIFIERS = [
105
+ { pattern: /\bcurrentUser\b/, id: 'currentUser' },
106
+ { pattern: /\buserIsLoggedIn\b/, id: 'userIsLoggedIn' },
107
+ { pattern: /\becommerce\b/, id: 'ecommerce' },
108
+ { pattern: /\bcart\b/, id: 'cart' },
109
+ { pattern: /\blocales?\b/, id: 'locale' },
110
+ ];
111
+ var trackGlobalRefsInExpression = function (expression, params) {
112
+ if (!expression) {
113
+ return;
114
+ }
115
+ for (var _i = 0, GLOBAL_EXPRESSION_IDENTIFIERS_1 = GLOBAL_EXPRESSION_IDENTIFIERS; _i < GLOBAL_EXPRESSION_IDENTIFIERS_1.length; _i++) {
116
+ var _a = GLOBAL_EXPRESSION_IDENTIFIERS_1[_i], pattern = _a.pattern, id = _a.id;
117
+ if (pattern.test(expression)) {
118
+ params.globalReferences.push(id);
119
+ }
120
+ }
121
+ // Global-state identifiers behave the same way: an expression-shaped UIDL
122
+ // attribute (e.g. cms-mixed-type `itemData`) bypasses the dynamic-ref
123
+ // pipeline that registers `useGlobalState()` destructuring, so we walk the
124
+ // raw expression text and re-attach any state name we recognise. The
125
+ // matched names are added to `globalStateReferences` and the
126
+ // next-global-state component plugin destructures them at codegen time.
127
+ var definitions = params.globalStateDefinitions;
128
+ if (!definitions || Object.keys(definitions).length === 0) {
129
+ return;
130
+ }
131
+ for (var _b = 0, _c = Object.values(definitions); _b < _c.length; _b++) {
132
+ var def = _c[_b];
133
+ var name_1 = def === null || def === void 0 ? void 0 : def.name;
134
+ if (!name_1) {
135
+ continue;
136
+ }
137
+ var escaped = name_1.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
138
+ if (new RegExp("\\b".concat(escaped, "\\b")).test(expression)) {
139
+ params.globalStateReferences.push({ id: def.id, name: name_1 });
140
+ }
141
+ }
142
+ };
143
+ var normalizeGlobalRef = function (node) {
144
+ if (node.content.id || !node.content.refPath || node.content.refPath.length === 0) {
145
+ return node;
146
+ }
147
+ var firstSeg = node.content.refPath[0];
148
+ var mappedId = ast_utils_1.GLOBAL_REF_ID_MAP[firstSeg];
149
+ if (!mappedId) {
150
+ return node;
151
+ }
152
+ return __assign(__assign({}, node), { content: __assign(__assign({}, node.content), { id: mappedId, refPath: node.content.refPath.slice(1) }) });
153
+ };
53
154
  var getElementType = function (node) {
54
155
  if (node.type === 'element' &&
55
156
  node.content &&
@@ -71,6 +172,65 @@ var getClassName = function (node) {
71
172
  }
72
173
  return null;
73
174
  };
175
+ var REACT_CHARTJS2_CHART_TAGS = new Set([
176
+ 'Line',
177
+ 'Bar',
178
+ 'Doughnut',
179
+ 'Pie',
180
+ 'Radar',
181
+ 'Bubble',
182
+ 'PolarArea',
183
+ 'Scatter',
184
+ ]);
185
+ var isReactChartjs2Chart = function (dependency, elementType) {
186
+ if ((dependency === null || dependency === void 0 ? void 0 : dependency.path) !== 'react-chartjs-2') {
187
+ return false;
188
+ }
189
+ return REACT_CHARTJS2_CHART_TAGS.has(elementType);
190
+ };
191
+ /**
192
+ * Chart.js with maintainAspectRatio:false fills the parent; if height is on the chart
193
+ * component via className, react-chartjs-2 may not apply it to the canvas host correctly
194
+ * inside flex layouts, causing unbounded growth. Wrap in a bounded div and move className
195
+ * to the wrapper; the chart fills with height/width 100%.
196
+ */
197
+ var wrapReactChartJs2Element = function (chartElement, _node) {
198
+ var attrs = chartElement.openingElement.attributes;
199
+ var kept = [];
200
+ var classNameAttr = null;
201
+ for (var _i = 0, attrs_1 = attrs; _i < attrs_1.length; _i++) {
202
+ var a = attrs_1[_i];
203
+ if (a.type === 'JSXAttribute' &&
204
+ a.name.type === 'JSXIdentifier' &&
205
+ a.name.name === 'className') {
206
+ classNameAttr = a;
207
+ }
208
+ else {
209
+ kept.push(a);
210
+ }
211
+ }
212
+ chartElement.openingElement.attributes = kept;
213
+ var hasStyleAttr = kept.some(function (a) { return a.type === 'JSXAttribute' && a.name.type === 'JSXIdentifier' && a.name.name === 'style'; });
214
+ if (!hasStyleAttr) {
215
+ chartElement.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('style'), types.jsxExpressionContainer(types.objectExpression([
216
+ types.objectProperty(types.identifier('height'), types.stringLiteral('100%')),
217
+ types.objectProperty(types.identifier('width'), types.stringLiteral('100%')),
218
+ ]))));
219
+ }
220
+ var wrapperStyle = types.objectExpression([
221
+ types.objectProperty(types.identifier('position'), types.stringLiteral('relative')),
222
+ types.objectProperty(types.identifier('minHeight'), types.numericLiteral(0)),
223
+ types.objectProperty(types.identifier('flexShrink'), types.numericLiteral(0)),
224
+ types.objectProperty(types.identifier('overflow'), types.stringLiteral('hidden')),
225
+ ]);
226
+ var wrapperAttrs = [
227
+ types.jsxAttribute(types.jsxIdentifier('style'), types.jsxExpressionContainer(wrapperStyle)),
228
+ ];
229
+ if (classNameAttr) {
230
+ wrapperAttrs.push(classNameAttr);
231
+ }
232
+ return types.jsxElement(types.jsxOpeningElement(types.jsxIdentifier('div'), wrapperAttrs), types.jsxClosingElement(types.jsxIdentifier('div')), [chartElement], false);
233
+ };
74
234
  var reorderChildrenForSearch = function (children) {
75
235
  var searchNodes = [];
76
236
  var dataProviderNodes = [];
@@ -117,6 +277,97 @@ var reorderChildrenForSearch = function (children) {
117
277
  return children;
118
278
  }
119
279
  };
280
+ /**
281
+ * Extracts autocomplete context from a thq-autocomplete node's children.
282
+ * Returns the input's field name and the dropdown's isOpen state name,
283
+ * so child option/clear elements can wire up onClick handlers.
284
+ */
285
+ var extractAutocompleteContext = function (children, formStateName) {
286
+ var _a, _b, _c, _d;
287
+ var fieldName = null;
288
+ var inputHtmlId = null;
289
+ var isOpenStateName = null;
290
+ for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
291
+ var child = children_1[_i];
292
+ if (child.type === 'element') {
293
+ var content = child.content;
294
+ // Check both original elementType and data-thq attr (elementType may have been resolved)
295
+ var dataThq = (_a = content.attrs) === null || _a === void 0 ? void 0 : _a['data-thq'];
296
+ var thqValue = (dataThq === null || dataThq === void 0 ? void 0 : dataThq.type) === 'static' ? String(dataThq.content) : '';
297
+ if (content.elementType === 'thq-autocomplete-input' ||
298
+ thqValue === 'thq-autocomplete-input') {
299
+ var nameAttr = (_b = content.attrs) === null || _b === void 0 ? void 0 : _b.name;
300
+ if ((nameAttr === null || nameAttr === void 0 ? void 0 : nameAttr.type) === 'static' && typeof nameAttr.content === 'string') {
301
+ fieldName = nameAttr.content;
302
+ }
303
+ var idAttr = (_c = content.attrs) === null || _c === void 0 ? void 0 : _c.id;
304
+ if ((idAttr === null || idAttr === void 0 ? void 0 : idAttr.type) === 'static' && typeof idAttr.content === 'string') {
305
+ inputHtmlId = idAttr.content;
306
+ }
307
+ }
308
+ }
309
+ else if (child.type === 'conditional') {
310
+ var condContent = child.content;
311
+ var ref = (_d = condContent.reference) === null || _d === void 0 ? void 0 : _d.content;
312
+ if ((ref === null || ref === void 0 ? void 0 : ref.referenceType) === 'state' && typeof ref.id === 'string') {
313
+ isOpenStateName = ref.id;
314
+ }
315
+ }
316
+ }
317
+ if (fieldName && isOpenStateName) {
318
+ return { fieldName: fieldName, inputHtmlId: inputHtmlId || '', formStateName: formStateName, isOpenStateName: isOpenStateName };
319
+ }
320
+ return undefined;
321
+ };
322
+ var maybeAddFormStoreFieldBinding = function (elementTag, elementName, attrs, params, events) {
323
+ var stateKey = params.formStoreStateName;
324
+ if (!stateKey || !attrs) {
325
+ return;
326
+ }
327
+ var nameAttr = attrs.name;
328
+ if (!nameAttr || nameAttr.type !== 'static' || typeof nameAttr.content !== 'string') {
329
+ return;
330
+ }
331
+ var tag = elementName.toLowerCase();
332
+ var isRichTextEditor = tag === 'richtexteditor';
333
+ if (tag !== 'input' && tag !== 'textarea' && tag !== 'select' && !isRichTextEditor) {
334
+ return;
335
+ }
336
+ // Autocomplete inputs manage their own value through workflows and option onClick handlers.
337
+ // Do NOT bind them to the form store — it causes infinite loops with state-change workflows.
338
+ var dataThq = attrs['data-thq'];
339
+ if ((dataThq === null || dataThq === void 0 ? void 0 : dataThq.type) === 'static' && String(dataThq.content) === 'thq-autocomplete-input') {
340
+ return;
341
+ }
342
+ var fieldName = nameAttr.content;
343
+ var stateId = types.identifier(stateKey);
344
+ var fieldAccess = types.memberExpression(stateId, types.stringLiteral(fieldName), true);
345
+ var typeAttr = attrs.type;
346
+ var isCheckbox = (typeAttr === null || typeAttr === void 0 ? void 0 : typeAttr.type) === 'static' && String(typeAttr.content) === 'checkbox';
347
+ var hasValueInAttrs = Object.prototype.hasOwnProperty.call(attrs, 'value');
348
+ var hasCheckedInAttrs = Object.prototype.hasOwnProperty.call(attrs, 'checked');
349
+ if (isRichTextEditor) {
350
+ var valueForEditor = types.logicalExpression('||', fieldAccess, types.stringLiteral(''));
351
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(valueForEditor)));
352
+ var setterName = "set".concat(stateKey.charAt(0).toUpperCase()).concat(stateKey.slice(1));
353
+ var richHandler = (0, ast_utils_1.parseJSExpressionAsAST)("(html) => { ".concat(setterName, "(prev => ({ ...prev, ['").concat(fieldName, "']: html })); }"));
354
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(richHandler)));
355
+ return;
356
+ }
357
+ if (!hasValueInAttrs && !isCheckbox) {
358
+ var valueExpr = types.logicalExpression('??', fieldAccess, types.stringLiteral(''));
359
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(valueExpr)));
360
+ }
361
+ else if (isCheckbox && !hasCheckedInAttrs) {
362
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('checked'), types.jsxExpressionContainer(fieldAccess)));
363
+ }
364
+ var hasUidlOnChange = events && Object.prototype.hasOwnProperty.call(events, 'onChange');
365
+ if (!hasUidlOnChange) {
366
+ var setterName = "set".concat(stateKey.charAt(0).toUpperCase()).concat(stateKey.slice(1));
367
+ var handler = (0, ast_utils_1.parseJSExpressionAsAST)("(e) => { const t = e.target; if (t.name) { ".concat(setterName, "(prev => ({ ...prev, [t.name]: t.type === 'checkbox' ? t.checked : t.value })); } }"));
368
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(handler)));
369
+ }
370
+ };
120
371
  var generateElementNode = function (node, params, jsxOptions) {
121
372
  var dependencies = params.dependencies, nodesLookup = params.nodesLookup;
122
373
  var options = __assign(__assign({}, constants_1.DEFAULT_JSX_OPTIONS), jsxOptions);
@@ -164,18 +415,86 @@ var generateElementNode = function (node, params, jsxOptions) {
164
415
  : tagName;
165
416
  var elementTag = selfClosing ? (0, ast_builders_1.createSelfClosingJSXTag)(elementName) : (0, ast_builders_1.createJSXTag)(elementName);
166
417
  if (attrs) {
167
- addAttributesToJSXTag(attrs, elementTag, options, params);
418
+ addAttributesToJSXTag(attrs, elementTag, options, params, node.content.semanticType || elementType);
168
419
  }
169
420
  if (events) {
170
421
  Object.keys(events).forEach(function (eventKey) {
171
422
  (0, utils_1.addEventHandlerToTag)(elementTag, eventKey, events[eventKey], params, options);
172
423
  });
173
424
  }
425
+ // Generate onChange handler for form elements with data-store-values-state
426
+ var childParams = params;
427
+ if (attrs === null || attrs === void 0 ? void 0 : attrs['data-store-values-state']) {
428
+ var storeAttr = attrs['data-store-values-state'];
429
+ if (storeAttr.type === 'static' && typeof storeAttr.content === 'string') {
430
+ var stateName = storeAttr.content;
431
+ childParams = __assign(__assign({}, params), { formStoreStateName: stateName });
432
+ var setterName = "set".concat(stateName.charAt(0).toUpperCase()).concat(stateName.slice(1));
433
+ var handler = (0, ast_utils_1.parseJSExpressionAsAST)("(e) => { const t = e.target; if (t.name && t.getAttribute('data-thq') !== 'thq-autocomplete-input') { ".concat(setterName, "(prev => ({ ...prev, [t.name]: t.type === 'checkbox' ? t.checked : t.value })); } }"));
434
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(handler)));
435
+ }
436
+ }
437
+ maybeAddFormStoreFieldBinding(elementTag, elementName, attrs, childParams, events);
438
+ // thq-autocomplete-input: make uncontrolled by converting `value` → `defaultValue`
439
+ // A controlled autocomplete input triggers state-change workflows on every keystroke,
440
+ // which normalizes the typed text and prevents free typing for search/filtering.
441
+ var dataThqAttr = attrs === null || attrs === void 0 ? void 0 : attrs['data-thq'];
442
+ var dataThqValue = (dataThqAttr === null || dataThqAttr === void 0 ? void 0 : dataThqAttr.type) === 'static' ? String(dataThqAttr.content) : '';
443
+ if (dataThqValue === 'thq-autocomplete-input') {
444
+ var jsxAttrs = elementTag.openingElement.attributes;
445
+ var valueIdx = jsxAttrs.findIndex(function (a) { return a.type === 'JSXAttribute' && a.name.type === 'JSXIdentifier' && a.name.name === 'value'; });
446
+ if (valueIdx !== -1) {
447
+ // Convert value → defaultValue so the input is uncontrolled but has initial value
448
+ var valueAttr = jsxAttrs[valueIdx];
449
+ jsxAttrs.splice(valueIdx, 1, types.jsxAttribute(types.jsxIdentifier('defaultValue'), valueAttr.value));
450
+ }
451
+ }
452
+ if (dataThqValue === 'thq-autocomplete' && children) {
453
+ var acCtx = extractAutocompleteContext(children, childParams.formStoreStateName);
454
+ if (acCtx) {
455
+ childParams = __assign(__assign({}, childParams), { autocompleteContext: acCtx });
456
+ }
457
+ }
458
+ // thq-autocomplete-option: add onClick to select the option value
459
+ if (dataThqValue === 'thq-autocomplete-option' && params.autocompleteContext) {
460
+ var _b = params.autocompleteContext, fieldName = _b.fieldName, formStateName = _b.formStateName, isOpenStateName = _b.isOpenStateName, inputHtmlId = _b.inputHtmlId;
461
+ var isOpenSetterName = "set".concat(isOpenStateName.charAt(0).toUpperCase()).concat(isOpenStateName.slice(1));
462
+ var handlerCode
463
+ // The autocomplete input is uncontrolled, so always set the DOM value.
464
+ // If form-store mode, also update the form state for form submission.
465
+ = void 0;
466
+ // The autocomplete input is uncontrolled, so always set the DOM value.
467
+ // If form-store mode, also update the form state for form submission.
468
+ var inputLookup = inputHtmlId
469
+ ? "document.getElementById('".concat(inputHtmlId, "')")
470
+ : "e.currentTarget.closest('[data-thq=\"thq-autocomplete\"]').querySelector('[data-thq=\"thq-autocomplete-input\"]')";
471
+ var formStoreUpdate = formStateName
472
+ ? "var setter = ".concat("set".concat(formStateName.charAt(0).toUpperCase()).concat(formStateName.slice(1)), "; setter(function(prev) { return Object.assign({}, prev, { ['").concat(fieldName, "']: text }); });")
473
+ : '';
474
+ handlerCode = "(e) => { var text = (e.currentTarget.textContent || '').trim(); var input = ".concat(inputLookup, "; if (input) { input.value = text; } ").concat(formStoreUpdate, " ").concat(isOpenSetterName, "(false); }");
475
+ var handler = (0, ast_utils_1.parseJSExpressionAsAST)(handlerCode);
476
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(handler)));
477
+ }
478
+ // thq-autocomplete-clear: add onClick to clear the input value and close dropdown
479
+ if (dataThqValue === 'thq-autocomplete-clear' && params.autocompleteContext) {
480
+ var _c = params.autocompleteContext, fieldName = _c.fieldName, formStateName = _c.formStateName, isOpenStateName = _c.isOpenStateName, inputHtmlId = _c.inputHtmlId;
481
+ var isOpenSetterName = "set".concat(isOpenStateName.charAt(0).toUpperCase()).concat(isOpenStateName.slice(1));
482
+ var handlerCode = void 0;
483
+ var clearInputLookup = inputHtmlId
484
+ ? "document.getElementById('".concat(inputHtmlId, "')")
485
+ : "e.currentTarget.closest('[data-thq=\"thq-autocomplete\"]').querySelector('[data-thq=\"thq-autocomplete-input\"]')";
486
+ var clearFormStoreUpdate = formStateName
487
+ ? "var setter = ".concat("set".concat(formStateName.charAt(0).toUpperCase()).concat(formStateName.slice(1)), "; setter(function(prev) { return Object.assign({}, prev, { ['").concat(fieldName, "']: '' }); });")
488
+ : '';
489
+ handlerCode = "(e) => { var input = ".concat(clearInputLookup, "; if (input) { input.value = ''; } ").concat(clearFormStoreUpdate, " ").concat(isOpenSetterName, "(false); }");
490
+ var handler = (0, ast_utils_1.parseJSExpressionAsAST)(handlerCode);
491
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(handler)));
492
+ }
174
493
  if (!selfClosing && children) {
175
494
  // Reorder children to ensure search nodes appear before DataProvider nodes
176
495
  var reorderedChildren = reorderChildrenForSearch(children);
177
496
  reorderedChildren.forEach(function (child) {
178
- var childTags = generateNode(child, params, options);
497
+ var childTags = generateNode(child, childParams, options);
179
498
  childTags.forEach(function (childTag) {
180
499
  if (typeof childTag === 'string') {
181
500
  (0, ast_utils_1.addChildJSXText)(elementTag, childTag);
@@ -189,23 +508,71 @@ var generateElementNode = function (node, params, jsxOptions) {
189
508
  });
190
509
  });
191
510
  }
511
+ if (dependency && isReactChartjs2Chart(dependency, originalElementName)) {
512
+ var wrapped = wrapReactChartJs2Element(elementTag, node);
513
+ nodesLookup[key] = wrapped;
514
+ return wrapped;
515
+ }
192
516
  nodesLookup[key] = elementTag;
193
517
  return elementTag;
194
518
  };
195
519
  exports.default = generateElementNode;
196
- var addAttributesToJSXTag = function (attrs, elementTag, options, params) {
520
+ var addAttributesToJSXTag = function (attrs, elementTag, options, params, elementName) {
197
521
  Object.keys(attrs !== null && attrs !== void 0 ? attrs : {}).forEach(function (attrKey) {
198
522
  var attributeValue = attrs[attrKey];
199
523
  if (!attributeValue.type) {
200
524
  return;
201
525
  }
526
+ // Skip code-gen directives - handled in generateElementNode
527
+ if (attrKey === 'data-store-values-state') {
528
+ return;
529
+ }
530
+ // Plan v15 Layer 4 — codegen safety net.
531
+ //
532
+ // Drop attributes that look like AI fabrication artefacts even when the
533
+ // upstream pipeline missed them. These never produce valid DOM/JSX:
534
+ // 1. attr names that are pure JS literals (`true`, `false`, bare
535
+ // numbers, `null`, `undefined`) — e.g. the `true="true"` that
536
+ // shipped with the broken Navigation in the 2026-05-24 run.
537
+ // 2. static string values that contain entity-escaped binding markers
538
+ // (`&#123;` / `&#125;`) — emitting them produces broken DOM text.
539
+ // 3. static string values that contain an UNBALANCED `{{` (no
540
+ // matching `}}`) — always garbage, never valid.
541
+ if (isJunkAttributeName(attrKey)) {
542
+ // eslint-disable-next-line no-console
543
+ console.warn("[codegen safety net] dropping junk-name attribute \"".concat(attrKey, "\" on <").concat(elementName !== null && elementName !== void 0 ? elementName : 'element', ">"));
544
+ return;
545
+ }
546
+ if (attributeValue.type === 'static') {
547
+ var staticContent = attributeValue.content;
548
+ if (typeof staticContent === 'string' && hasCorruptBindingMarkers(staticContent)) {
549
+ // eslint-disable-next-line no-console
550
+ console.warn("[codegen safety net] dropping attribute \"".concat(attrKey, "\" on <").concat(elementName !== null && elementName !== void 0 ? elementName : 'element', "> \u2014 value has entity-escaped or truncated binding markers (").concat(truncate(staticContent), ")"));
551
+ return;
552
+ }
553
+ }
202
554
  switch (attributeValue.type) {
203
555
  case 'dynamic':
204
- var referenceType = attributeValue.content.referenceType;
556
+ var dynamicRef = attributeValue;
557
+ var referenceType = dynamicRef.content.referenceType;
558
+ if (referenceType === 'global') {
559
+ var normRef = normalizeGlobalRef(dynamicRef);
560
+ params.globalReferences.push(normRef.content.id);
561
+ // Use the normalized ref to generate the attribute expression
562
+ var globalExpr = (0, utils_1.createDynamicValueExpression)(normRef, options);
563
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier((0, ast_utils_1.convertToReactAttributeName)(attrKey)), types.jsxExpressionContainer(globalExpr)));
564
+ break;
565
+ }
566
+ if (referenceType === 'globalState') {
567
+ var gsName = (0, utils_1.resolveGlobalStateName)(dynamicRef.content.id, params.globalStateDefinitions);
568
+ params.globalStateReferences.push({ id: dynamicRef.content.id, name: gsName });
569
+ var expr = (0, utils_1.createGlobalStateExpression)(dynamicRef, params.globalStateDefinitions);
570
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier((0, ast_utils_1.convertToReactAttributeName)(attrKey)), types.jsxExpressionContainer(expr)));
571
+ break;
572
+ }
205
573
  switch (referenceType) {
206
574
  default:
207
- var prefix = options.dynamicReferencePrefixMap[referenceType];
208
- var dynamicRef = attributeValue;
575
+ var prefix = options.dynamicReferencePrefixMap[referenceType] || '';
209
576
  var idWithRefPath = teleport_shared_1.UIDLUtils.generateIdWithRefPath(dynamicRef.content.id, dynamicRef.content.refPath);
210
577
  (0, ast_utils_1.addDynamicAttributeToJSXTag)(elementTag, attrKey, idWithRefPath, prefix);
211
578
  break;
@@ -214,15 +581,50 @@ var addAttributesToJSXTag = function (attrs, elementTag, options, params) {
214
581
  case 'import':
215
582
  (0, ast_utils_1.addDynamicAttributeToJSXTag)(elementTag, attrKey, attributeValue.content.id);
216
583
  break;
217
- case 'raw':
584
+ case 'raw': {
585
+ var rawValue = attributeValue;
586
+ if (elementName === 'markdown-node') {
587
+ if (rawValue.dynamic) {
588
+ applyDynamicMarkdownInjection(elementTag, rawValue, params, options);
589
+ }
590
+ else {
591
+ applyStaticMarkdownInjection(elementTag, rawValue, params);
592
+ }
593
+ break;
594
+ }
595
+ if (elementName === 'rich-text-editor-node') {
596
+ applyRichTextEditorRawAttribute(elementTag, attrKey, rawValue, params, options);
597
+ break;
598
+ }
599
+ if (rawValue.dynamic) {
600
+ applyDynamicHtmlInjection(elementTag, rawValue, params, options);
601
+ break;
602
+ }
218
603
  (0, ast_utils_1.addRawAttributeToJSXTag)(elementTag, attrKey, attributeValue);
219
604
  break;
605
+ }
220
606
  case 'comp-style':
221
- case 'static':
222
607
  (0, ast_utils_1.addAttributeToJSXTag)(elementTag, attrKey, attributeValue.content);
223
608
  break;
609
+ case 'static':
610
+ if (typeof attributeValue.content === 'object' &&
611
+ attributeValue.content !== null &&
612
+ !Array.isArray(attributeValue.content)) {
613
+ var constName = "__staticProp".concat(params.hoistedConstants.length);
614
+ var expression = (0, ast_utils_1.objectToObjectExpression)(attributeValue.content);
615
+ params.hoistedConstants.push({ name: constName, expression: expression });
616
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier((0, ast_utils_1.convertToReactAttributeName)(attrKey)), types.jsxExpressionContainer(types.identifier(constName))));
617
+ }
618
+ else {
619
+ (0, ast_utils_1.addAttributeToJSXTag)(elementTag, attrKey, attributeValue.content);
620
+ }
621
+ break;
224
622
  case 'expr':
225
623
  (0, ast_utils_1.addDynamicExpressionAttributeToJSXTag)(elementTag, attributeValue, attrKey);
624
+ // Scan the *sanitized* content so any globals introduced by the
625
+ // repair (e.g. `/profile/${}` → `/profile/${currentUser?.id}`) still
626
+ // trigger the downstream useGlobalContext() wiring.
627
+ trackGlobalRefsInExpression((0, ast_utils_1.sanitizeExprContent)(String(attributeValue.content), attrKey), params);
226
628
  break;
227
629
  case 'element':
228
630
  (0, ast_utils_1.addAttributeToJSXTag)(elementTag, attrKey, generateElementNode(attributeValue, params, options));
@@ -241,23 +643,65 @@ var addAttributesToJSXTag = function (attrs, elementTag, options, params) {
241
643
  }
242
644
  });
243
645
  };
646
+ /**
647
+ * Converts text containing {{ expr }} templates into a mix of JSX text and expression containers.
648
+ * e.g. "x{{ (state.score / 10) || '0' }}" → ["x", JSXExpressionContainer((score / 10) || '0')]
649
+ *
650
+ * Uses parseStringWithTemplateExpressions to parse the template into a TemplateLiteral AST,
651
+ * then converts its quasis (text parts) and expressions into JSX children.
652
+ */
653
+ var convertTextTemplateToJSX = function (text) {
654
+ try {
655
+ var templateLiteral = (0, ast_utils_1.parseStringWithTemplateExpressions)(text);
656
+ var result = [];
657
+ for (var i = 0; i < templateLiteral.quasis.length; i++) {
658
+ var quasi = templateLiteral.quasis[i];
659
+ var textPart = quasi.value.cooked || quasi.value.raw;
660
+ if (textPart) {
661
+ result.push(teleport_shared_1.StringUtils.encode(textPart));
662
+ }
663
+ if (i < templateLiteral.expressions.length) {
664
+ result.push(types.jsxExpressionContainer(templateLiteral.expressions[i]));
665
+ }
666
+ }
667
+ return result.length > 0 ? result : [teleport_shared_1.StringUtils.encode(text)];
668
+ }
669
+ catch (_a) {
670
+ // If parsing fails, fall back to encoded text
671
+ return [teleport_shared_1.StringUtils.encode(text)];
672
+ }
673
+ };
244
674
  var generateNode = function (node, params, options) {
675
+ var _a;
245
676
  switch (node.type) {
246
677
  case 'expr':
247
678
  return [generateExpressionNode(node, params, options)];
248
- case 'raw':
679
+ case 'raw': {
680
+ var rawNode = node;
681
+ if (rawNode.dynamic) {
682
+ var dynamicExpr = resolveDynamicReferenceExpression(rawNode.dynamic, params, options);
683
+ var fallback = rawNode.fallback || rawNode.content;
684
+ return [__1.ASTBuilders.createDynamicDOMInjectionNode(dynamicExpr, fallback)];
685
+ }
249
686
  return [
250
687
  options.domHTMLInjection
251
688
  ? options.domHTMLInjection(node.content.toString())
252
689
  : node.content.toString(),
253
690
  ];
691
+ }
254
692
  case 'inject':
255
693
  if (node === null || node === void 0 ? void 0 : node.dependency) {
256
694
  params.dependencies.Script = node.dependency;
257
695
  }
258
696
  return [node.content.toString()];
259
- case 'static':
260
- return [teleport_shared_1.StringUtils.encode(node.content.toString())];
697
+ case 'static': {
698
+ var textContent = node.content.toString();
699
+ // Check if the text contains {{ }} template expressions
700
+ if (/\{\{/.test(textContent)) {
701
+ return convertTextTemplateToJSX(textContent);
702
+ }
703
+ return [teleport_shared_1.StringUtils.encode(textContent)];
704
+ }
261
705
  case 'dynamic':
262
706
  switch (node.content.referenceType) {
263
707
  case 'prop': {
@@ -296,10 +740,18 @@ var generateNode = function (node, params, options) {
296
740
  return [jsxTag];
297
741
  }
298
742
  case 'global': {
299
- params.globalReferences.push(node.content.id);
300
- return [(0, utils_1.createDynamicValueExpression)(node, options)];
743
+ var globalNode = normalizeGlobalRef(node);
744
+ params.globalReferences.push(globalNode.content.id);
745
+ return [(0, utils_1.createDynamicValueExpression)(globalNode, options)];
301
746
  }
302
747
  default:
748
+ if (node.content.referenceType === 'globalState') {
749
+ var gsName = (0, utils_1.resolveGlobalStateName)(node.content.id, params.globalStateDefinitions);
750
+ params.globalStateReferences.push({ id: node.content.id, name: gsName });
751
+ return [
752
+ (0, utils_1.createGlobalStateExpression)(node, params.globalStateDefinitions),
753
+ ];
754
+ }
303
755
  return [(0, utils_1.createDynamicValueExpression)(node, options)];
304
756
  }
305
757
  case 'cms-item':
@@ -312,7 +764,7 @@ var generateNode = function (node, params, options) {
312
764
  case 'data-source-item':
313
765
  case 'data-source-list':
314
766
  return generateDataSourceNode(node, params, options);
315
- case 'element':
767
+ case 'element': {
316
768
  // Check if this element node is wrapping a data-source node
317
769
  if (node.content &&
318
770
  typeof node.content === 'object' &&
@@ -322,7 +774,15 @@ var generateNode = function (node, params, options) {
322
774
  // tslint:disable-next-line:no-any
323
775
  return generateDataSourceNode(node.content, params, options);
324
776
  }
325
- return [generateElementNode(node, params, options)];
777
+ var elementTag = generateElementNode(node, params, options);
778
+ var renderingConditions = (_a = node.content) === null || _a === void 0 ? void 0 : _a.renderingConditions;
779
+ if (renderingConditions) {
780
+ return [
781
+ wrapWithConditional(elementTag, renderingConditions.reference, renderingConditions.condition, params, options),
782
+ ];
783
+ }
784
+ return [elementTag];
785
+ }
326
786
  case 'repeat':
327
787
  return generateRepeatNode(node, params, options);
328
788
  case 'conditional':
@@ -383,7 +843,7 @@ var generateCMSNode = function (node, params, options) {
383
843
  }
384
844
  var cmsNode = __1.ASTBuilders.createJSXTag(jsxTag, [], true);
385
845
  if (node.type === 'cms-item') {
386
- cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('renderSuccess'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier(renderPropIdentifier)], generateNode(success, params, options)[0]))));
846
+ cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('renderSuccess'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier(renderPropIdentifier)], generateNode(success, params, __assign(__assign({}, options), { localIdentifier: renderPropIdentifier }))[0]))));
387
847
  }
388
848
  if (node.type === 'cms-list') {
389
849
  cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('renderSuccess'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier('params')], generateNode(success, params, options)[0]))));
@@ -397,18 +857,24 @@ var generateCMSNode = function (node, params, options) {
397
857
  if (error) {
398
858
  cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('renderError'), types.jsxExpressionContainer(types.arrowFunctionExpression([], generateNode(error, params, options)[0]))));
399
859
  }
400
- if (initialData && initialData.content.referenceType === 'prop') {
401
- cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.memberExpression(types.identifier(options.dynamicReferencePrefixMap[initialData.content.referenceType]), types.identifier(initialData.content.id)))));
860
+ if (initialData && initialData.content.referenceType) {
861
+ var refType = initialData.content.referenceType;
862
+ var initialDataExpr = refType === 'prop'
863
+ ? types.memberExpression(types.identifier(options.dynamicReferencePrefixMap[refType]), types.identifier(initialData.content.id))
864
+ : types.identifier(initialData.content.id);
865
+ cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(initialDataExpr)));
402
866
  cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
403
- var keyValue = 'props?.pagination?.page';
404
- if (node.type === 'cms-item') {
405
- var entityKeyProperty = node.content.entityKeyProperty;
406
- var entityName = initialData.content.id;
407
- keyValue = entityKeyProperty
408
- ? "props?.".concat(entityName, "?.").concat(entityKeyProperty)
409
- : "props?.".concat(entityName, "?.id");
867
+ if (refType === 'prop') {
868
+ var keyValue = 'props?.pagination?.page';
869
+ if (node.type === 'cms-item') {
870
+ var entityKeyProperty = node.content.entityKeyProperty;
871
+ var entityName = initialData.content.id;
872
+ keyValue = entityKeyProperty
873
+ ? "props?.".concat(entityName, "?.").concat(entityKeyProperty)
874
+ : "props?.".concat(entityName, "?.id");
875
+ }
876
+ cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.identifier(keyValue))));
410
877
  }
411
- cmsNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.identifier(keyValue))));
412
878
  }
413
879
  if (Object.keys(resourceParams || {}).length > 0) {
414
880
  var nodeParams = Object.keys(resourceParams).reduce(function (acc, attrKey) {
@@ -433,8 +899,8 @@ var generateCMSNode = function (node, params, options) {
433
899
  return [cmsNode];
434
900
  };
435
901
  var generateDataSourceNode = function (node, params, options) {
436
- var _a, _b, _c, _d;
437
- var _e = node.content, renderPropIdentifier = _e.renderPropIdentifier, elementType = _e.elementType, dependency = _e.dependency, resourceDefinition = _e.resourceDefinition;
902
+ var _a, _b, _c, _d, _e;
903
+ var _f = node.content, renderPropIdentifier = _f.renderPropIdentifier, elementType = _f.elementType, dependency = _f.dependency, resourceDefinition = _f.resourceDefinition;
438
904
  var key = node.content.key || "ds-".concat(resourceDefinition.dataSourceId, "-").concat(Date.now());
439
905
  var name = node.content.name || renderPropIdentifier;
440
906
  // tslint:disable-next-line:no-any
@@ -456,7 +922,10 @@ var generateDataSourceNode = function (node, params, options) {
456
922
  ]))));
457
923
  dataSourceNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('name'), types.jsxExpressionContainer(types.stringLiteral(name))));
458
924
  if (children && children.length > 0) {
459
- var childrenNodes = children.flatMap(function (child) { return generateNode(child, params, options); });
925
+ // Pass the render prop identifier as the 'ctx' prefix for data source context references
926
+ // and as the localIdentifier so conditional nodes resolve local refs correctly
927
+ var childOptions_1 = __assign(__assign({}, options), { localIdentifier: renderPropIdentifier, dynamicReferencePrefixMap: __assign(__assign({}, options.dynamicReferencePrefixMap), { ctx: renderPropIdentifier }) });
928
+ var childrenNodes = children.flatMap(function (child) { return generateNode(child, params, childOptions_1); });
460
929
  var renderFunction = types.arrowFunctionExpression([types.identifier(renderPropIdentifier)], types.jsxFragment(types.jsxOpeningFragment(), types.jsxClosingFragment(), childrenNodes));
461
930
  dataSourceNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('renderSuccess'), types.jsxExpressionContainer(renderFunction)));
462
931
  }
@@ -509,6 +978,17 @@ var generateDataSourceNode = function (node, params, options) {
509
978
  }, []);
510
979
  dataSourceNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.objectExpression(nodeParams))));
511
980
  }
981
+ // Add initialData if the UIDL node has it (similar to CMS nodes)
982
+ // tslint:disable-next-line:no-any
983
+ var nodeInitialData = node.content.initialData;
984
+ if (nodeInitialData && ((_e = nodeInitialData.content) === null || _e === void 0 ? void 0 : _e.referenceType)) {
985
+ var refType = nodeInitialData.content.referenceType;
986
+ var initialDataExpr = refType === 'prop'
987
+ ? types.memberExpression(types.identifier(options.dynamicReferencePrefixMap[refType]), types.identifier(nodeInitialData.content.id))
988
+ : types.identifier(nodeInitialData.content.id);
989
+ dataSourceNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(initialDataExpr)));
990
+ dataSourceNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
991
+ }
512
992
  params.nodesLookup[key] = dataSourceNode;
513
993
  return [dataSourceNode];
514
994
  };
@@ -531,30 +1011,86 @@ var generateRepeatNode = function (node, params, options) {
531
1011
  ]));
532
1012
  });
533
1013
  };
534
- var generateConditionalNode = function (node, params, options) {
535
- var _a = node.content, reference = _a.reference, value = _a.value;
536
- var subTrees = generateNode(node.content.node, params, options);
537
- // Track global references used in conditionals
1014
+ // Shared between UIDLConditionalNode (wraps a child subtree) and the inline
1015
+ // `renderingConditions` property on UIDLElement content. Tracks global and
1016
+ // globalState references on params, resolves the condition identifier, and
1017
+ // builds the `condition && <content/>` logical expression.
1018
+ var wrapWithConditional = function (subTree, reference, condition, params, options) {
538
1019
  if (reference.type === 'dynamic' &&
539
1020
  'referenceType' in reference.content &&
540
1021
  reference.content.referenceType === 'global') {
541
- params.globalReferences.push(reference.content.id);
1022
+ var normCondRef = normalizeGlobalRef(reference);
1023
+ params.globalReferences.push(normCondRef.content.id);
542
1024
  }
1025
+ if (reference.type === 'dynamic' &&
1026
+ 'referenceType' in reference.content &&
1027
+ reference.content.referenceType === 'globalState') {
1028
+ var gsName = (0, utils_1.resolveGlobalStateName)(reference.content.id, params.globalStateDefinitions);
1029
+ params.globalStateReferences.push({ id: reference.content.id, name: gsName });
1030
+ }
1031
+ var effectiveRef = reference.type === 'dynamic' &&
1032
+ 'referenceType' in reference.content &&
1033
+ reference.content.referenceType === 'global'
1034
+ ? normalizeGlobalRef(reference)
1035
+ : reference;
1036
+ var conditionIdentifier = (0, utils_1.createConditionIdentifier)(effectiveRef, params, options);
1037
+ return (0, utils_1.createConditionalJSXExpression)(subTree, condition, conditionIdentifier, {
1038
+ localIdentifier: options.localIdentifier,
1039
+ detailsPageExposeAsName: options.detailsPageExposeAsName || params.detailsPageExposeAsName,
1040
+ });
1041
+ };
1042
+ var generateConditionalNode = function (node, params, options) {
1043
+ var _a = node.content, reference = _a.reference, value = _a.value;
1044
+ var subTrees = generateNode(node.content.node, params, options);
543
1045
  var condition = value !== undefined && value !== null
544
1046
  ? { conditions: [{ operand: value, operation: '===' }] }
545
1047
  : node.content.condition;
546
- var conditionIdentifier = (0, utils_1.createConditionIdentifier)(reference, params, options);
547
- var conditionalExpressions = subTrees.map(function (subTree) {
548
- return (0, utils_1.createConditionalJSXExpression)(subTree, condition, conditionIdentifier);
1048
+ return subTrees.map(function (subTree) {
1049
+ return wrapWithConditional(subTree, reference, condition, params, options);
549
1050
  });
550
- return conditionalExpressions;
551
1051
  };
552
1052
  var generateCMSListRepeaterNode = function (node, params, options) {
553
- var _a, _b;
1053
+ var _a, _b, _c;
554
1054
  var jsxTag = teleport_shared_1.StringUtils.dashCaseToUpperCamelCase(node.content.elementType);
555
1055
  var repeaterNode = __1.ASTBuilders.createJSXTag(jsxTag, [], true);
556
- repeaterNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('items'), types.jsxExpressionContainer(types.identifier((_a = node.content.source) !== null && _a !== void 0 ? _a : 'params'))));
557
- var listElement = generateNode(node.content.nodes.list, params, __assign(__assign({}, options), { localIdentifier: node.content.renderPropIdentifier }))[0];
1056
+ var dataNodeIdAttr = (_a = node.content.attrs) === null || _a === void 0 ? void 0 : _a.dataNodeId;
1057
+ if (dataNodeIdAttr === null || dataNodeIdAttr === void 0 ? void 0 : dataNodeIdAttr.content) {
1058
+ (0, ast_utils_1.addAttributeToJSXTag)(repeaterNode, 'dataNodeId', dataNodeIdAttr.content);
1059
+ }
1060
+ // When the repeater source is a global context like "ecommerce", resolve to
1061
+ // the appropriate array from the ecommerce context based on what the repeater
1062
+ // iterates over (determined by renderPropIdentifier).
1063
+ var repeaterItemsExpr;
1064
+ var source = (_b = node.content.source) !== null && _b !== void 0 ? _b : 'params';
1065
+ if (source === 'ecommerce') {
1066
+ var rpId = node.content.renderPropIdentifier || '';
1067
+ // Map renderPropIdentifier to the correct ecommerce context path
1068
+ var ecommercePathMap = {
1069
+ paymentProvider: ['paymentProviders'],
1070
+ storeLocation: ['storeLocations'],
1071
+ };
1072
+ // Default: cart items for orderItem, cartItem, or any unrecognized identifier
1073
+ var path = ecommercePathMap[rpId] || ['Cart', 'items'];
1074
+ var expr = types.identifier('ecommerce');
1075
+ for (var _i = 0, path_1 = path; _i < path_1.length; _i++) {
1076
+ var seg = path_1[_i];
1077
+ expr = types.optionalMemberExpression(expr, types.identifier(seg), false, true);
1078
+ }
1079
+ repeaterItemsExpr = types.logicalExpression('||', expr, types.arrayExpression([]));
1080
+ params.globalReferences.push('ecommerce');
1081
+ }
1082
+ else {
1083
+ // Resolve any global-state reference encoded in `source` and register it
1084
+ // so the `next-global-state` component plugin destructures the matching
1085
+ // identifier from `useGlobalState()`. Without this, sources emitted as
1086
+ // either `<globalStateName> || []` (modern) or `globalState_<defId>`
1087
+ // (legacy) compile to a `ReferenceError` at render time because the
1088
+ // identifier never enters scope.
1089
+ var resolvedSource = (0, utils_1.resolveAndRegisterGlobalStateSource)(source, params);
1090
+ repeaterItemsExpr = types.identifier(resolvedSource);
1091
+ }
1092
+ repeaterNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('items'), types.jsxExpressionContainer(repeaterItemsExpr)));
1093
+ var listElement = generateNode(node.content.nodes.list, params, __assign(__assign({}, options), { localIdentifier: node.content.renderPropIdentifier, dynamicReferencePrefixMap: __assign(__assign({}, options.dynamicReferencePrefixMap), { ctx: node.content.renderPropIdentifier }) }))[0];
558
1094
  // Create key as template literal: `${item?.id}${index}`
559
1095
  var keyAttribute = types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
560
1096
  types.templateElement({ raw: '', cooked: '' }, false),
@@ -572,7 +1108,7 @@ var generateCMSListRepeaterNode = function (node, params, options) {
572
1108
  if ('loading' in node.content.nodes) {
573
1109
  generateNode(node.content.nodes.loading, params, options);
574
1110
  }
575
- if (((_b = node.content) === null || _b === void 0 ? void 0 : _b.dependency) && options.dependencyHandling === 'import') {
1111
+ if (((_c = node.content) === null || _c === void 0 ? void 0 : _c.dependency) && options.dependencyHandling === 'import') {
576
1112
  params.dependencies[jsxTag] = node.content.dependency;
577
1113
  }
578
1114
  return [repeaterNode];
@@ -622,4 +1158,127 @@ var generateNativeSlotNode = function (node, params, options) {
622
1158
  }
623
1159
  return slotNode;
624
1160
  };
1161
+ var resolveDynamicReferenceExpression = function (dynamicRef, params, options) {
1162
+ var referenceType = dynamicRef.content.referenceType;
1163
+ if (referenceType === 'global') {
1164
+ var normDynRef = normalizeGlobalRef(dynamicRef);
1165
+ params.globalReferences.push(normDynRef.content.id);
1166
+ return (0, utils_1.createDynamicValueExpression)(normDynRef, options);
1167
+ }
1168
+ if (referenceType === 'globalState') {
1169
+ var gsName = (0, utils_1.resolveGlobalStateName)(dynamicRef.content.id, params.globalStateDefinitions);
1170
+ params.globalStateReferences.push({ id: dynamicRef.content.id, name: gsName });
1171
+ return (0, utils_1.createGlobalStateExpression)(dynamicRef, params.globalStateDefinitions);
1172
+ }
1173
+ return (0, utils_1.createDynamicValueExpression)(dynamicRef, options);
1174
+ };
1175
+ var applyDynamicHtmlInjection = function (elementTag, rawValue, params, options) {
1176
+ var dynamicExpr = resolveDynamicReferenceExpression(rawValue.dynamic, params, options);
1177
+ var fallbackContent = rawValue.fallback || rawValue.content;
1178
+ var fallbackExpr = types.stringLiteral(fallbackContent);
1179
+ var valueExpr = types.logicalExpression('||', dynamicExpr, fallbackExpr);
1180
+ elementTag.openingElement.name.name = 'span';
1181
+ if (elementTag.closingElement) {
1182
+ ;
1183
+ elementTag.closingElement.name.name = 'span';
1184
+ }
1185
+ elementTag.openingElement.selfClosing = true;
1186
+ elementTag.closingElement = null;
1187
+ elementTag.children = [];
1188
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('dangerouslySetInnerHTML'), types.jsxExpressionContainer(types.objectExpression([types.objectProperty(types.identifier('__html'), valueExpr)]))));
1189
+ Object.keys(params.dependencies).forEach(function (key) {
1190
+ var _a, _b;
1191
+ if ((_b = (_a = params.dependencies[key]) === null || _a === void 0 ? void 0 : _a.path) === null || _b === void 0 ? void 0 : _b.includes('dangerous-html')) {
1192
+ delete params.dependencies[key];
1193
+ }
1194
+ });
1195
+ };
1196
+ var applyStaticMarkdownInjection = function (elementTag, rawValue, params) {
1197
+ var content = rawValue.content || '';
1198
+ elementTag.openingElement.name.name = 'div';
1199
+ elementTag.openingElement.selfClosing = true;
1200
+ elementTag.closingElement = null;
1201
+ elementTag.children = [];
1202
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('dangerouslySetInnerHTML'), types.jsxExpressionContainer(types.objectExpression([
1203
+ types.objectProperty(types.identifier('__html'), types.stringLiteral(content)),
1204
+ ]))));
1205
+ cleanupMarkdownMappingDependencies(params);
1206
+ };
1207
+ var applyDynamicMarkdownInjection = function (elementTag, rawValue, params, options) {
1208
+ var dynamicExpr = resolveDynamicReferenceExpression(rawValue.dynamic, params, options);
1209
+ var fallbackContent = rawValue.fallback || rawValue.content;
1210
+ var reactMarkdownTag = (0, ast_builders_1.createJSXTag)('ReactMarkdown');
1211
+ (0, ast_utils_1.addChildJSXTag)(reactMarkdownTag, types.jsxExpressionContainer(types.cloneNode(dynamicExpr)));
1212
+ var fallbackTag = __1.ASTBuilders.createDOMInjectionNode(fallbackContent);
1213
+ var conditionalExpr = types.conditionalExpression(dynamicExpr, reactMarkdownTag, fallbackTag);
1214
+ elementTag.openingElement.name.name = 'div';
1215
+ elementTag.openingElement.selfClosing = false;
1216
+ if (!elementTag.closingElement) {
1217
+ elementTag.closingElement = types.jsxClosingElement(types.jsxIdentifier('div'));
1218
+ }
1219
+ else {
1220
+ ;
1221
+ elementTag.closingElement.name.name = 'div';
1222
+ }
1223
+ elementTag.children = [types.jsxExpressionContainer(conditionalExpr)];
1224
+ cleanupMarkdownMappingDependencies(params);
1225
+ params.dependencies.ReactMarkdown = {
1226
+ type: 'package',
1227
+ path: 'react-markdown',
1228
+ version: '^8.0.7',
1229
+ };
1230
+ };
1231
+ var cleanupMarkdownMappingDependencies = function (params) {
1232
+ Object.keys(params.dependencies).forEach(function (key) {
1233
+ var _a, _b;
1234
+ if ((_b = (_a = params.dependencies[key]) === null || _a === void 0 ? void 0 : _a.path) === null || _b === void 0 ? void 0 : _b.includes('markdown-to-jsx')) {
1235
+ delete params.dependencies[key];
1236
+ }
1237
+ });
1238
+ };
1239
+ /**
1240
+ * Handles raw attributes on a rich-text-editor-node element.
1241
+ *
1242
+ * - `html` attribute → becomes a `value` prop (static string or dynamic expression with fallback)
1243
+ * - `quillFormats` attribute → parsed from JSON string into a JS array expression
1244
+ */
1245
+ var applyRichTextEditorRawAttribute = function (elementTag, attrKey, rawValue, params, options) {
1246
+ if (attrKey === 'html' && params.formStoreStateName) {
1247
+ return;
1248
+ }
1249
+ if (attrKey === 'html') {
1250
+ if (rawValue.dynamic) {
1251
+ var dynamicExpr = resolveDynamicReferenceExpression(rawValue.dynamic, params, options);
1252
+ var fallbackContent = rawValue.fallback || rawValue.content || '';
1253
+ var valueExpr = types.logicalExpression('||', dynamicExpr, types.stringLiteral(fallbackContent));
1254
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(valueExpr)));
1255
+ }
1256
+ else {
1257
+ var content = rawValue.content || '';
1258
+ (0, ast_utils_1.addAttributeToJSXTag)(elementTag, 'value', content);
1259
+ }
1260
+ return;
1261
+ }
1262
+ if (attrKey === 'quillFormats') {
1263
+ var formats = null;
1264
+ try {
1265
+ var parsed = JSON.parse(rawValue.content);
1266
+ if (Array.isArray(parsed)) {
1267
+ formats = parsed;
1268
+ }
1269
+ }
1270
+ catch (_a) {
1271
+ // Parsing failed → don't add the attribute; component will use all formats
1272
+ }
1273
+ if (formats === null) {
1274
+ // Parse failure or not an array → omit attribute so component uses all formats
1275
+ return;
1276
+ }
1277
+ var arrayExpr = types.arrayExpression(formats.map(function (f) { return types.stringLiteral(f); }));
1278
+ elementTag.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('quillFormats'), types.jsxExpressionContainer(arrayExpr)));
1279
+ return;
1280
+ }
1281
+ // Any other raw attribute on rich-text-editor-node: fall through to default handling
1282
+ (0, ast_utils_1.addRawAttributeToJSXTag)(elementTag, attrKey, rawValue);
1283
+ };
625
1284
  //# sourceMappingURL=index.js.map