@useinsider/guido 3.17.0-beta.58179dc → 3.17.0-beta.dc7f4d2

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 (79) hide show
  1. package/dist/components/Guido.vue.js +8 -8
  2. package/dist/components/Guido.vue2.js +78 -76
  3. package/dist/components/organisms/AutoSaveController.vue2.js +9 -8
  4. package/dist/components/organisms/header/EditorActions.vue.js +2 -2
  5. package/dist/components/organisms/header/EditorActions.vue2.js +74 -43
  6. package/dist/components/organisms/header/LeftSlot.vue.js +5 -5
  7. package/dist/components/organisms/header/LeftSlot.vue2.js +46 -23
  8. package/dist/components/organisms/validation/ValidationErrorDrawer.vue.js +20 -0
  9. package/dist/components/organisms/validation/ValidationErrorDrawer.vue2.js +48 -0
  10. package/dist/components/wrappers/WpDrawer.vue.js +9 -7
  11. package/dist/components/wrappers/WpDrawer.vue2.js +1 -1
  12. package/dist/composables/useHtmlCompiler.js +37 -26
  13. package/dist/composables/useHtmlValidator.js +2 -0
  14. package/dist/composables/useSave.js +84 -41
  15. package/dist/composables/useSaveValidation.js +279 -0
  16. package/dist/composables/useSaveValidationRollout.js +9 -0
  17. package/dist/composables/validators/useCouponBlockValidator.js +24 -21
  18. package/dist/composables/validators/useUnsubscribeBlockValidator.js +34 -27
  19. package/dist/config/migrator/index.js +8 -9
  20. package/dist/config/migrator/recommendation/compositionMapper.js +20 -20
  21. package/dist/config/migrator/recommendation/extractors.js +24 -29
  22. package/dist/config/migrator/recommendation/htmlBuilder.js +130 -116
  23. package/dist/config/migrator/recommendationMigrator.js +15 -18
  24. package/dist/enums/save-validation.js +4 -0
  25. package/dist/extensions/Blocks/Recommendation/block.js +20 -49
  26. package/dist/extensions/Blocks/Recommendation/constants/blockIds.js +1 -1
  27. package/dist/extensions/Blocks/Recommendation/constants/controlIds.js +1 -1
  28. package/dist/extensions/Blocks/Recommendation/constants/defaultConfig.js +22 -23
  29. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +28 -34
  30. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +238 -306
  31. package/dist/extensions/Blocks/Recommendation/controls/main/index.js +8 -9
  32. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +0 -1
  33. package/dist/extensions/Blocks/Recommendation/extension.js +29 -31
  34. package/dist/extensions/Blocks/Recommendation/settingsPanel.js +4 -23
  35. package/dist/extensions/Blocks/Recommendation/store/recommendation.js +33 -26
  36. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +3 -3
  37. package/dist/extensions/Blocks/Recommendation/templates/utils.js +107 -85
  38. package/dist/guido.css +1 -1
  39. package/dist/src/@types/save-validation.d.ts +19 -0
  40. package/dist/src/components/Guido.vue.d.ts +17 -1
  41. package/dist/src/components/organisms/header/EditorActions.vue.d.ts +17 -1
  42. package/dist/src/components/organisms/header/HeaderWrapper.vue.d.ts +17 -1
  43. package/dist/src/components/organisms/header/RightSlot.vue.d.ts +17 -1
  44. package/dist/src/components/organisms/validation/ValidationErrorDrawer.vue.d.ts +2 -0
  45. package/dist/src/components/wrappers/WpDrawer.vue.d.ts +4 -3
  46. package/dist/src/composables/useHtmlValidator.d.ts +21 -0
  47. package/dist/src/composables/useSave.d.ts +6 -1
  48. package/dist/src/composables/useSaveValidation.d.ts +6 -0
  49. package/dist/src/composables/useSaveValidationRollout.d.ts +3 -0
  50. package/dist/src/composables/validators/useCouponBlockValidator.d.ts +3 -0
  51. package/dist/src/composables/validators/useUnsubscribeBlockValidator.d.ts +10 -0
  52. package/dist/src/config/migrator/recommendation/extractors.d.ts +0 -8
  53. package/dist/src/enums/save-validation.d.ts +27 -0
  54. package/dist/src/extensions/Blocks/Recommendation/block.d.ts +0 -15
  55. package/dist/src/extensions/Blocks/Recommendation/constants/blockIds.d.ts +1 -2
  56. package/dist/src/extensions/Blocks/Recommendation/constants/controlIds.d.ts +0 -7
  57. package/dist/src/extensions/Blocks/Recommendation/constants/defaultConfig.d.ts +0 -1
  58. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  59. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +0 -10
  60. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +0 -10
  61. package/dist/src/extensions/Blocks/Recommendation/controls/index.d.ts +0 -1
  62. package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +0 -1
  63. package/dist/src/extensions/Blocks/Recommendation/store/recommendation.d.ts +5 -0
  64. package/dist/src/stores/config.d.ts +5 -0
  65. package/dist/src/stores/save-validation.d.ts +22 -0
  66. package/dist/src/utils/templatePreparation.d.ts +30 -0
  67. package/dist/static/styles/customEditorStyle.css.js +1 -3
  68. package/dist/stores/config.js +13 -6
  69. package/dist/stores/save-validation.js +30 -0
  70. package/dist/utils/templatePreparation.js +28 -25
  71. package/package.json +1 -1
  72. package/dist/config/migrator/recommendationTitleMigrator.js +0 -119
  73. package/dist/extensions/Blocks/Recommendation/controls/title/index.js +0 -44
  74. package/dist/extensions/Blocks/Recommendation/templates/titleRows.js +0 -33
  75. package/dist/extensions/Blocks/Recommendation/utils/legacyTitle.js +0 -20
  76. package/dist/src/config/migrator/recommendationTitleMigrator.d.ts +0 -5
  77. package/dist/src/extensions/Blocks/Recommendation/controls/title/index.d.ts +0 -86
  78. package/dist/src/extensions/Blocks/Recommendation/templates/titleRows.d.ts +0 -13
  79. package/dist/src/extensions/Blocks/Recommendation/utils/legacyTitle.d.ts +0 -20
@@ -1,9 +1,8 @@
1
- import { ATTR_PRODUCT_PRICE as l, ATTR_PRODUCT_OLD_PRICE as a, ATTR_CUSTOM_PREFIX as T, ATTR_PRODUCT_IMAGE as b, ATTR_PRODUCT_NAME as _, ATTR_PRODUCT_OMNIBUS_PRICE as C, ATTR_PRODUCT_OMNIBUS_DISCOUNT as A, ATTR_PRODUCT_BUTTON as p, PRODUCT_ATTRIBUTE_PREFIX as I } from "../constants/selectors.js";
1
+ import { ATTR_PRODUCT_PRICE as l, ATTR_PRODUCT_OLD_PRICE as a, ATTR_CUSTOM_PREFIX as T, ATTR_PRODUCT_IMAGE as m, ATTR_PRODUCT_NAME as C, ATTR_PRODUCT_OMNIBUS_PRICE as _, ATTR_PRODUCT_OMNIBUS_DISCOUNT as p, ATTR_PRODUCT_BUTTON as y, PRODUCT_ATTRIBUTE_PREFIX as I } from "../constants/selectors.js";
2
2
  import { useRecommendationExtensionStore as L } from "../store/recommendation.js";
3
- import { compositionKeyToProductAttr as y, isDefaultProductAttr as f, bareAttributeName as S, findFilterByBareName as $, productAttrToCompositionKey as P } from "../utils/compositionKeys.js";
3
+ import { compositionKeyToProductAttr as A, isDefaultProductAttr as b, bareAttributeName as S, findFilterByBareName as $, productAttrToCompositionKey as h } from "../utils/compositionKeys.js";
4
4
  import { formatPrice as B } from "../utils/priceFormatter.js";
5
- import { buildTitleRows as k } from "./titleRows.js";
6
- function x() {
5
+ function k() {
7
6
  const t = L(), { currencySettings: e } = t.recommendationConfigs;
8
7
  return {
9
8
  code: e.value,
@@ -14,17 +13,17 @@ function x() {
14
13
  thousandSeparator: e.thousandSeparator
15
14
  };
16
15
  }
17
- function m(t, e = "price") {
18
- const o = x(), n = t[e], c = (n == null ? void 0 : n[o.code]) ?? Object.values(n ?? {})[0] ?? 0;
16
+ function f(t, e = "price") {
17
+ const o = k(), n = t[e], c = (n == null ? void 0 : n[o.code]) ?? Object.values(n ?? {})[0] ?? 0;
19
18
  return B({
20
19
  price: c,
21
20
  currency: o
22
21
  });
23
22
  }
24
23
  function q(t) {
25
- return m(t, "price") === m(t, "original_price");
24
+ return f(t, "price") === f(t, "original_price");
26
25
  }
27
- function N(t) {
26
+ function x(t) {
28
27
  return t.replace(/_/g, " ").replace(/\b\w/g, (e) => e.toUpperCase());
29
28
  }
30
29
  function J(t) {
@@ -35,114 +34,115 @@ function J(t) {
35
34
  skip: n ? l : a
36
35
  };
37
36
  }
38
- function F(t) {
37
+ function N(t) {
39
38
  const e = Array.isArray(t) ? t[t.length - 1] : t;
40
39
  if (typeof e == "string")
41
40
  return e;
42
41
  if (typeof e == "number")
43
42
  return String(e);
44
43
  }
45
- function v(t, e) {
44
+ function w(t, e) {
46
45
  var o;
47
46
  return ((o = $(t, e)) == null ? void 0 : o.type) === "defaultAttribute";
48
47
  }
49
- function w(t, e) {
50
- return v(t, e) ? t : `${I}${t}`;
48
+ function F(t, e) {
49
+ return w(t, e) ? t : `${I}${t}`;
51
50
  }
52
51
  function Q(t) {
53
- return P(t);
52
+ return h(t);
54
53
  }
55
- const M = Symbol("customCellHtml");
54
+ const v = Symbol("customCellHtml");
56
55
  function Z(t, e, o = {}) {
57
- const n = t[M];
56
+ const n = t[v];
58
57
  if (!n)
59
58
  return { ...t };
60
59
  const c = { ...t };
61
- return e.filter((i) => i.startsWith(T) && !c[i]).forEach((i) => {
62
- const s = y(i), r = f(s) ? w(s, o) : s, u = S(r), h = N(u), D = f(r);
63
- c[i] = (d, U) => {
60
+ return e.filter((s) => s.startsWith(T) && !c[s]).forEach((s) => {
61
+ const i = A(s), r = b(i) ? F(i, o) : i, u = S(r), R = x(u), D = b(r);
62
+ c[s] = (d, U) => {
64
63
  var g;
65
- const O = D ? d[u] : (g = d.product_attributes) == null ? void 0 : g[u], E = F(O) ?? h;
66
- return n(r, E, U);
64
+ const E = D ? d[u] : (g = d.product_attributes) == null ? void 0 : g[u], O = N(E) ?? R;
65
+ return n(r, O, U);
67
66
  };
68
67
  }), c;
69
68
  }
70
69
  function tt(t, e, o = []) {
71
- const n = t.startsWith(T) ? P(S(y(t))) : t, i = n !== t && !o.includes(n) ? n : t, s = (r) => (r == null ? void 0 : r[t]) ?? (r == null ? void 0 : r[i]);
70
+ const n = t.startsWith(T) ? h(S(A(t))) : t, s = n !== t && !o.includes(n) ? n : t, i = (r) => (r == null ? void 0 : r[t]) ?? (r == null ? void 0 : r[s]);
72
71
  return {
73
72
  cellPadding: e.cellPadding,
74
73
  cardBackgroundColor: e.cardBackgroundColor,
75
- cellBackgroundColor: s(e.cellBackgroundColors),
76
- cellAlignment: s(e.cellAlignments),
77
- cellClasses: s(e.cellClasses),
78
- omnibusText: s(e.omnibusTexts),
79
- styleTemplate: s(e.styleTemplates)
74
+ cellBackgroundColor: i(e.cellBackgroundColors),
75
+ cellAlignment: i(e.cellAlignments),
76
+ cellClasses: i(e.cellClasses),
77
+ omnibusText: i(e.omnibusTexts),
78
+ styleTemplate: i(e.styleTemplates)
80
79
  };
81
80
  }
82
81
  const et = {
83
82
  TITLE: "You May Also Like!"
84
83
  }, ot = [
85
- b,
86
- _,
84
+ m,
85
+ C,
87
86
  a,
88
87
  l,
89
- C,
90
- A,
91
- p
88
+ _,
89
+ p,
90
+ y
92
91
  ], nt = {
93
- [b]: !0,
94
- [_]: !0,
92
+ [m]: !0,
93
+ [C]: !0,
95
94
  [l]: !0,
96
95
  [a]: !0,
97
- [C]: !1,
98
- [A]: !1,
99
- [p]: !0
100
- }, W = 10;
101
- function rt(t = W) {
96
+ [_]: !1,
97
+ [p]: !1,
98
+ [y]: !0
99
+ }, M = 10;
100
+ function W(t = M) {
102
101
  return `
103
102
  <tr>
104
103
  <td class="spacer" style="height: ${t}px;"></td>
105
104
  </tr>
106
105
  `;
107
106
  }
108
- function H(t, e) {
107
+ const H = W();
108
+ function V(t, e) {
109
109
  return e ? e.pStyle ?? "" : t;
110
110
  }
111
- function it(t, e, o) {
112
- const n = H(e.pStyle, o), c = o ? o.openTags ?? "" : e.openTags, i = o ? o.closeTags ?? "" : e.closeTags;
113
- return `<p contenteditable="false" style="${n}">${c}${t}${i}</p>`;
111
+ function rt(t, e, o) {
112
+ const n = V(e.pStyle, o), c = o ? o.openTags ?? "" : e.openTags, s = o ? o.closeTags ?? "" : e.closeTags;
113
+ return `<p contenteditable="false" style="${n}">${c}${t}${s}</p>`;
114
114
  }
115
115
  function st(t, e) {
116
116
  const o = [];
117
117
  return t && o.push(t), e && o.push(`background-color: ${e};`), o.join(" ");
118
118
  }
119
- function V(t) {
119
+ function Y(t) {
120
120
  return t ? ` background-color: ${t};` : "";
121
121
  }
122
- function ct(t) {
123
- const e = V(t);
122
+ function it(t) {
123
+ const e = Y(t);
124
124
  return e ? ` style="${e.trim()}"` : "";
125
125
  }
126
- function lt(t, e = "") {
126
+ function ct(t, e = "") {
127
127
  return {
128
128
  before: (t == null ? void 0 : t.before) ?? e,
129
129
  after: (t == null ? void 0 : t.after) ?? ""
130
130
  };
131
131
  }
132
- function at(t, e) {
132
+ function lt(t, e) {
133
133
  return `${(e == null ? void 0 : e.openTags) ?? ""}${t}${(e == null ? void 0 : e.closeTags) ?? ""}`;
134
134
  }
135
- function ut(t) {
135
+ function at(t) {
136
136
  return t != null && t.buttonFitToContainer ? "es-button-border es-fw" : "es-button-border";
137
137
  }
138
- const dt = "display: block; max-width: 100%; height: auto;", gt = "border-width: 1px; background: rgb(217, 234, 211); border-color: rgb(106, 168, 79);", ft = "color: rgb(56, 118, 29); background: rgb(217, 234, 211); font-family: arial, 'helvetica neue', helvetica, sans-serif; font-size: 16px; font-weight: normal; line-height: 120%; mso-border-alt: 10px solid rgb(217, 234, 211); mso-padding-alt: 0;", R = "https://email-static.useinsider.com/stripo/modules/email-recommendation-v3/assets/images/image-placeholder.png";
139
- function mt(t) {
140
- return !t || typeof t != "string" || t.trim() === "" ? R : t.startsWith("http://") ? t.replace("http://", "https://") : t;
138
+ const ut = "display: block; max-width: 100%; height: auto;", dt = "border-width: 1px; background: rgb(217, 234, 211); border-color: rgb(106, 168, 79);", gt = "color: rgb(56, 118, 29); background: rgb(217, 234, 211); font-family: arial, 'helvetica neue', helvetica, sans-serif; font-size: 16px; font-weight: normal; line-height: 120%; mso-border-alt: 10px solid rgb(217, 234, 211); mso-padding-alt: 0;", P = "https://email-static.useinsider.com/stripo/modules/email-recommendation-v3/assets/images/image-placeholder.png";
139
+ function bt(t) {
140
+ return !t || typeof t != "string" || t.trim() === "" ? P : t.startsWith("http://") ? t.replace("http://", "https://") : t;
141
141
  }
142
- function Y(t) {
142
+ function G(t) {
143
143
  return {
144
144
  name: "Product Name",
145
- image_url: R,
145
+ image_url: P,
146
146
  price: { USD: 18 },
147
147
  original_price: { USD: 20 },
148
148
  discount: { USD: 2 },
@@ -154,20 +154,19 @@ function Y(t) {
154
154
  category: []
155
155
  };
156
156
  }
157
- function Tt(t = 6) {
157
+ function ft(t = 6) {
158
158
  return Array.from(
159
159
  { length: t },
160
- (e, o) => Y(String(o + 1))
160
+ (e, o) => G(String(o + 1))
161
161
  );
162
162
  }
163
- function bt(t = "grid", e) {
163
+ function Tt(t = "grid", e) {
164
164
  const o = t === "list" ? `
165
- data-layout="list"` : "", n = e ? ` ${e}` : "", i = `recommendation-block-v2 esd-block-recommendation-v3-block es-p20${t === "list" ? " es-m-p0 ins-recommendation-list-layout" : ""}${n}`, s = t === "list" ? "" : `
166
- {-{-MOBILE_PRODUCT_ROWS-}-}`, r = t === "list" ? ' style="display: none;"' : "";
165
+ data-layout="list"` : "", n = e ? ` ${e}` : "";
167
166
  return `
168
167
  <td
169
168
  align="left"
170
- class="${i}"${o}>
169
+ class="${`recommendation-block-v2 esd-block-recommendation-v3-block es-p20${t === "list" ? " es-m-p0 ins-recommendation-list-layout" : ""}${n}`}"${o}>
171
170
  <table width="100%" cellpadding="0" cellspacing="0" border="0">
172
171
  <tr>
173
172
  <td align="center">
@@ -178,7 +177,28 @@ function bt(t = "grid", e) {
178
177
  cellspacing="0"
179
178
  border="0">
180
179
  <tbody>
181
- ${k()}
180
+ <tr>
181
+ <td>
182
+ <table
183
+ width="100%"
184
+ cellpadding="0"
185
+ cellspacing="0"
186
+ border="0">
187
+ <tbody>
188
+ <tr>
189
+ <td
190
+ class="esd-block-text es-p10t es-p10b es-p20l es-p20r"
191
+ align="center">
192
+ <p style="font-size: 28px; color: #333333;">
193
+ <strong>{-{-TITLE-}-}</strong>
194
+ </p>
195
+ </td>
196
+ </tr>
197
+ </tbody>
198
+ </table>
199
+ </td>
200
+ </tr>
201
+ ${H}
182
202
  <tr>
183
203
  <td>
184
204
  <table
@@ -193,7 +213,7 @@ function bt(t = "grid", e) {
193
213
  </table>
194
214
  </td>
195
215
  </tr>
196
- <tr class="ins-recommendation-mobile-row"${r}>
216
+ <tr class="ins-recommendation-mobile-row"${t === "list" ? ' style="display: none;"' : ""}>
197
217
  <td>
198
218
  <table
199
219
  class="ins-recommendation-product-container
@@ -203,7 +223,8 @@ function bt(t = "grid", e) {
203
223
  cellspacing="0"
204
224
  border="0"
205
225
  style="display: none;"
206
- >${s}
226
+ >${t === "list" ? "" : `
227
+ {-{-MOBILE_PRODUCT_ROWS-}-}`}
207
228
  </table>
208
229
  </td>
209
230
  </tr>
@@ -216,36 +237,37 @@ function bt(t = "grid", e) {
216
237
  `;
217
238
  }
218
239
  export {
219
- M as CUSTOM_CELL_HTML,
240
+ v as CUSTOM_CELL_HTML,
220
241
  et as DEFAULTS,
221
- ft as DEFAULT_BUTTON_ANCHOR_STYLE,
222
- gt as DEFAULT_BUTTON_BORDER_STYLE,
242
+ gt as DEFAULT_BUTTON_ANCHOR_STYLE,
243
+ dt as DEFAULT_BUTTON_BORDER_STYLE,
223
244
  ot as DEFAULT_CARD_COMPOSITION,
224
245
  nt as DEFAULT_CARD_VISIBILITY,
225
- dt as DEFAULT_IMG_STYLE,
226
- W as DEFAULT_ROW_SPACING_PX,
227
- R as PLACEHOLDER_IMAGE,
228
- V as bgColorFragment,
246
+ ut as DEFAULT_IMG_STYLE,
247
+ M as DEFAULT_ROW_SPACING_PX,
248
+ P as PLACEHOLDER_IMAGE,
249
+ Y as bgColorFragment,
229
250
  tt as buildCellOptions,
230
251
  Z as buildElementRenderer,
231
- rt as buildSpacer,
232
- ct as cellBgStyleAttr,
233
- bt as createBlockTemplate,
234
- m as formatProductPrice,
235
- x as getCurrentCurrencyConfig,
236
- Tt as getDefaultProducts,
237
- v as isDefaultAttribute,
252
+ W as buildSpacer,
253
+ it as cellBgStyleAttr,
254
+ Tt as createBlockTemplate,
255
+ f as formatProductPrice,
256
+ k as getCurrentCurrencyConfig,
257
+ ft as getDefaultProducts,
258
+ w as isDefaultAttribute,
238
259
  q as isSamePrice,
239
- at as renderButtonLabel,
240
- it as renderStyledParagraph,
241
- ut as resolveButtonBorderClass,
260
+ lt as renderButtonLabel,
261
+ rt as renderStyledParagraph,
262
+ at as resolveButtonBorderClass,
242
263
  J as resolveInlinePriceOrder,
243
- lt as resolveOmnibusText,
244
- H as resolvePStyle,
245
- w as resolveProductAttrValue,
264
+ ct as resolveOmnibusText,
265
+ V as resolvePStyle,
266
+ F as resolveProductAttrValue,
246
267
  st as resolveSegmentBgStyle,
247
- mt as sanitizeImageUrl,
268
+ bt as sanitizeImageUrl,
269
+ H as spacer,
248
270
  Q as toCustomCompositionKey,
249
- N as toDisplayName,
250
- F as toDisplayableAttributeValue
271
+ x as toDisplayName,
272
+ N as toDisplayableAttributeValue
251
273
  };
package/dist/guido.css CHANGED
@@ -1 +1 @@
1
- .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-73199fa4] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-6e711fd7]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.guido-editor__wrapper[data-v-b0d3b445]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-b0d3b445]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-b0d3b445]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
1
+ .gap-16[data-v-5553d071],.gap-16[data-v-0e1b0c54]{gap:16px}[data-v-74d455fc] .in-button-v2__wrapper{line-height:0}[data-v-22226124] .in-segments-wrapper__button_selected,[data-v-22226124] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb;color:#0010ac;border-color:#0010ac}[data-v-2cb418af] .in-progress-wrapper__progress p span:last-child{display:none!important}[data-v-2cb418af] .in-progress-description-status{display:none!important}.view-options-wrapper[data-v-87033101]{position:relative;display:inline-block}.new-tag[data-v-87033101]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-87033101] .guido__view-option-selection-desktop svg,[data-v-87033101] .guido__view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-87033101] .in-segments-wrapper__button_selected,[data-v-87033101] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-87033101] .in-tooltip-wrapper-v2__icon{cursor:pointer}.editor-toolbar[data-v-173c3a40]{gap:4px}.version-history-item[data-v-ee4b9c3f]{flex-basis:200px}.version-history[data-v-fad98586]{gap:8px}.version-history__toolbar[data-v-fad98586]{gap:4px}.view-options-wrapper[data-v-6ebabfe4]{position:relative;display:inline-block}.new-tag[data-v-6ebabfe4]{position:absolute;top:-8px;right:-16px;z-index:10}[data-v-6ebabfe4] .guido__verion-history-view-option-selection-desktop svg,[data-v-6ebabfe4] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-6ebabfe4] .in-segments-wrapper__button_selected,[data-v-6ebabfe4] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}[data-v-6ebabfe4] .in-tooltip-wrapper-v2__icon{cursor:pointer}.auto-save-toggle[data-v-2c964af4]{position:relative}.auto-save-toggle__info-box[data-v-2c964af4]{position:absolute;top:100%;left:0;z-index:10;width:280px}.editor-actions[data-v-44d8e7c8]{gap:4px}.header-wrapper[data-v-d11dd577]{min-width:1000px}.guido-loading__wrapper[data-v-07c4b2d8]{height:100%;top:75px!important;bottom:0!important}.validation-error-list[data-v-856367aa]{gap:16px}.validation-error-row[data-v-856367aa]{gap:8px;padding:24px;border:1px solid #E1E1E1;border-radius:8px}.validation-error-row__icon[data-v-856367aa]{flex-shrink:0;font-size:24px;line-height:0}.validation-error-row__text[data-v-856367aa]{font-size:13px;line-height:16px;color:#292929;word-break:break-word}.guido-editor__wrapper[data-v-f02fdde0]{--ribbon-offset: 0px;position:relative;width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__container[data-v-f02fdde0]{width:100%;height:calc(100vh - 128px - var(--ribbon-offset))}.guido-editor__no-header[data-v-f02fdde0]{height:calc(100vh - 75px - var(--ribbon-offset))}[data-v-293f1c47] .in-breadcrumb-wrapper__links{cursor:pointer}.templates-wrapper[data-v-91a26acd]{gap:16px;grid-template-columns:repeat(3,1fr)}.templates-wrapper .template-wrapper[data-v-91a26acd]{cursor:pointer}.templates-wrapper .template-wrapper .template-container[data-v-91a26acd]{height:274px;padding:2px;transition:none}.templates-wrapper .template-wrapper .template-container.selected[data-v-91a26acd]{padding:1px}.templates-wrapper .template-wrapper .template-container .thumbnail[data-v-91a26acd]{object-fit:cover;transform:scale(1)}[data-v-b9a93c6e] .guido__verion-history-view-option-selection-desktop svg,[data-v-b9a93c6e] .guido__verion-history-view-option-selection-mobile svg{margin:0 0 0 2px}[data-v-b9a93c6e] .in-segments-wrapper__button_selected,[data-v-b9a93c6e] .in-segments-wrapper__button_selected:hover{background-color:#dae1fb}.error-list[data-v-c3fd5d4b]{gap:16px}.desktop-browser-header[data-v-d86c5af5]{height:79px;min-height:79px}.desktop-browser-header__left[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:378px}.desktop-browser-header__center[data-v-d86c5af5]{height:79px;background-repeat:repeat-x;background-size:auto 100%;background-position:left top}.desktop-browser-header__right[data-v-d86c5af5]{-webkit-user-drag:none;height:79px;width:112px}.desktop-preview[data-v-cf946232]{min-width:602px;height:70vh;min-height:583px;border-radius:10px}.desktop-preview iframe[data-v-cf946232]{min-height:504px}.iframe-wrapper[data-v-f255b2bb]{width:258px}.iframe-scaled[data-v-f255b2bb]{width:320px;height:124.0310077519%;transform:scale(.80625);transform-origin:top left}.cropped-text[data-v-eb3d05d7]{width:220px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.mobile-preview-wrapper__phone[data-v-3f472f96]{width:282px}.mobile-preview-wrapper__phone img[data-v-3f472f96]{object-fit:cover;border-radius:44px}.mobile-preview-wrapper__content[data-v-3f472f96]{width:258px;height:450px;left:12px}[data-v-6bcaca8a] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-f16f20f8] .vueperslides__bullets{pointer-events:none!important}[data-v-f16f20f8] .vueperslides__parallax-wrapper{padding-bottom:110px!important}[data-v-bb3cca55] .vueperslides__bullets{pointer-events:none!important}[data-v-bb3cca55] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-b09e80c4] .vueperslides__bullets{pointer-events:none!important}[data-v-b09e80c4] .vueperslides__parallax-wrapper{height:110px!important;padding-bottom:110px!important}[data-v-9bdef600] .vueperslides__parallax-wrapper{padding-bottom:110px!important}
@@ -0,0 +1,19 @@
1
+ import type { SaveValidationRule } from '@@/Enums/save-validation';
2
+ import type { ToasterTypeOptions } from '@@/Enums/toaster';
3
+ /** Which action triggered the validation run. Drives telemetry only in v1. */
4
+ export type SaveValidationIntent = 'save' | 'back' | 'test';
5
+ /**
6
+ * A single validation failure instance, one per drawer row. Names avoid the
7
+ * public `ValidationError` (config validation) collision — NOT exported from
8
+ * library.ts.
9
+ */
10
+ export interface SaveValidationError {
11
+ /** Stable discriminator for tests and de-duplication. */
12
+ rule: SaveValidationRule;
13
+ /** Final translated string — trans() is applied at collect time. */
14
+ message: string;
15
+ /** Raw user content (field name / tag / src) — not i18n. */
16
+ detail?: string;
17
+ /** Mirrors the legacy toaster severity. Kept for the discriminator/tests; the drawer renders a uniform icon and never reads it. */
18
+ type: ToasterTypeOptions;
19
+ }
@@ -15,7 +15,23 @@ declare const _default: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_T
15
15
  close: () => void;
16
16
  };
17
17
  hasChanges: import("vue").ComputedRef<boolean>;
18
- saveSilent: () => Promise<Omit<SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
18
+ saveSilent: () => Promise<{
19
+ dynamicContentList: import("@@/Types/generic").DynamicContent[];
20
+ compiledHtml: string;
21
+ rawHtml: string;
22
+ css: string;
23
+ ampHtml: string;
24
+ ampErrors: string[];
25
+ modules: number[];
26
+ recommendation: {
27
+ campaignUrls: Record<string, string>;
28
+ configs: Record<string, string>;
29
+ };
30
+ unsubscribe: {
31
+ status: boolean;
32
+ config: number[];
33
+ };
34
+ } | undefined> | undefined;
19
35
  setLoading: (value: boolean) => void;
20
36
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {
21
37
  "dynamic-content:open": (detail: {
@@ -1,4 +1,20 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
- handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
2
+ handleSave: (isSilent: boolean) => Promise<{
3
+ dynamicContentList: import("../../../@types/generic.js").DynamicContent[];
4
+ compiledHtml: string;
5
+ rawHtml: string;
6
+ css: string;
7
+ ampHtml: string;
8
+ ampErrors: string[];
9
+ modules: number[];
10
+ recommendation: {
11
+ campaignUrls: Record<string, string>;
12
+ configs: Record<string, string>;
13
+ };
14
+ unsubscribe: {
15
+ status: boolean;
16
+ config: number[];
17
+ };
18
+ } | undefined> | undefined;
3
19
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
4
20
  export default _default;
@@ -1,4 +1,20 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
- handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
2
+ handleSave: (isSilent: boolean) => Promise<{
3
+ dynamicContentList: import("../../../@types/generic.js").DynamicContent[];
4
+ compiledHtml: string;
5
+ rawHtml: string;
6
+ css: string;
7
+ ampHtml: string;
8
+ ampErrors: string[];
9
+ modules: number[];
10
+ recommendation: {
11
+ campaignUrls: Record<string, string>;
12
+ configs: Record<string, string>;
13
+ };
14
+ unsubscribe: {
15
+ status: boolean;
16
+ config: number[];
17
+ };
18
+ } | undefined> | undefined;
3
19
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
4
20
  export default _default;
@@ -1,4 +1,20 @@
1
1
  declare const _default: import("vue").DefineComponent<{}, {
2
- handleSave: (isSilent: boolean) => Promise<Omit<import("../../../@types/stripo.js").SavedTemplateDetails, "metadata" | "silent"> | undefined> | undefined;
2
+ handleSave: (isSilent: boolean) => Promise<{
3
+ dynamicContentList: import("../../../@types/generic.js").DynamicContent[];
4
+ compiledHtml: string;
5
+ rawHtml: string;
6
+ css: string;
7
+ ampHtml: string;
8
+ ampErrors: string[];
9
+ modules: number[];
10
+ recommendation: {
11
+ campaignUrls: Record<string, string>;
12
+ configs: Record<string, string>;
13
+ };
14
+ unsubscribe: {
15
+ status: boolean;
16
+ config: number[];
17
+ };
18
+ } | undefined> | undefined;
3
19
  }, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
4
20
  export default _default;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue/types/v3-component-options.js").ComponentOptionsMixin, import("vue/types/v3-component-options.js").ComponentOptionsMixin, {}, string, Readonly<import("vue").ExtractPropTypes<{}>>, {}>;
2
+ export default _default;
@@ -10,11 +10,11 @@ interface Props {
10
10
  status: boolean;
11
11
  titleText: string;
12
12
  }
13
- declare var __VLS_12: {}, __VLS_14: {};
13
+ declare var __VLS_13: {}, __VLS_15: {};
14
14
  type __VLS_Slots = {} & {
15
- headerBottomSlot?: (props: typeof __VLS_12) => any;
15
+ headerBottomSlot?: (props: typeof __VLS_13) => any;
16
16
  } & {
17
- default?: (props: typeof __VLS_14) => any;
17
+ default?: (props: typeof __VLS_15) => any;
18
18
  };
19
19
  declare const __VLS_component: import("vue").DefineComponent<__VLS_WithDefaults<__VLS_TypePropsToOption<Props>, {
20
20
  className: string;
@@ -26,6 +26,7 @@ declare const __VLS_component: import("vue").DefineComponent<__VLS_WithDefaults<
26
26
  cancelOrBackButtonEvent: () => void;
27
27
  onCloseEvent: () => void;
28
28
  primaryButtonEvent: () => void;
29
+ secondaryButtonEvent: () => void;
29
30
  }, string, Readonly<import("vue").ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToOption<Props>, {
30
31
  className: string;
31
32
  size: string;
@@ -1,5 +1,12 @@
1
1
  import type { DynamicContent } from '@@/Types/generic';
2
2
  import type { FiltersResponse } from '@@/Types/recommendation';
3
+ /**
4
+ * Extracts recommendation block IDs directly from the HTML by parsing
5
+ * the recommendation-id attribute on block elements.
6
+ * This avoids depending on store state which may not be populated
7
+ * when the settings panel hasn't been opened yet (e.g., saved templates).
8
+ */
9
+ export declare function getRecommendationBlockIds(html: string): string[];
3
10
  /**
4
11
  * Parses a `{{recoId_index_attributeName}}` variable (already stripped of the
5
12
  * braces/whitespace) into its recommendation id and attribute name. Returns
@@ -27,6 +34,20 @@ export declare function buildPartnerAttributeNameSet(filterList: FiltersResponse
27
34
  * before, so flagging it would false-positive on merge tags like `{{user.name}}`.
28
35
  */
29
36
  export declare function findInvalidCustomFields(html: string, validCustomFields: string[], recommendationBlockIds: string[], ignoredIds: Set<string>, ignoredAttributeNames: Set<string> | null): string[];
37
+ /**
38
+ * Returns the invalid `{{ ... }}` dynamic-content tags found in the HTML.
39
+ *
40
+ * A tag's variable name is the part before the first `|` (everything after it is the fallback).
41
+ * Surrounding whitespace is always allowed (trimmed). A tag is valid only when the variable name
42
+ * is an allowed system token, or it is a clean identifier (`[A-Za-z0-9_.]`) and — when a `|` is
43
+ * present — the fallback after it is not empty. Otherwise the tag is invalid (e.g.
44
+ * `{{Api Response: OA1 Main Item Url}}` — spaces/`:` — or `{{bounce|}}` — empty fallback).
45
+ *
46
+ * `data-*` block-config attribute values are excluded from the scan: blocks such as Items/cart
47
+ * store product merge tags (`data-product_button_link="{{Abandoned Cart Item (1) Url}}"`) that the
48
+ * backend resolves through its own pipeline, so they must not be treated as user-authored tags.
49
+ */
50
+ export declare function getInvalidDynamicContentTags(html: string): string[];
30
51
  export declare const useHtmlValidator: () => {
31
52
  validateHtml: (html: string, customFields: DynamicContent[], isOnSaveValidation?: boolean) => Promise<boolean>;
32
53
  };
@@ -1,4 +1,9 @@
1
1
  import type { SavedTemplateDetails } from '@@/Types/stripo';
2
+ type SaveDetails = Omit<SavedTemplateDetails, 'metadata' | 'silent'>;
3
+ type SaveResult = SaveDetails | undefined;
2
4
  export declare const useSave: () => {
3
- save: (suppressEmit?: boolean, silent?: boolean) => Promise<Omit<SavedTemplateDetails, "metadata" | "silent"> | undefined>;
5
+ save: (suppressEmit?: boolean, silent?: boolean) => Promise<SaveResult>;
6
+ saveWithErrors: () => Promise<SaveResult>;
7
+ saveRawOnly: () => Promise<SaveResult>;
4
8
  };
9
+ export {};
@@ -0,0 +1,6 @@
1
+ import type { DynamicContent } from '@@/Types/generic';
2
+ import type { SaveValidationError } from '@@/Types/save-validation';
3
+ export declare const useSaveValidation: () => {
4
+ collectSaveValidationErrors: (compiledHtml: string, dynamicContentList: DynamicContent[]) => Promise<SaveValidationError[]>;
5
+ validateCurrentTemplate: () => Promise<SaveValidationError[]>;
6
+ };
@@ -0,0 +1,3 @@
1
+ export declare const useSaveValidationRollout: () => {
2
+ isEnabled: import("vue").ComputedRef<boolean>;
3
+ };
@@ -1,3 +1,6 @@
1
+ export declare const COUPON_TAG_MODIFIED_KEY = "newsletter.coupon-tag-modified";
2
+ /** Pure core: the tag text of every coupon block whose code was modified. */
3
+ export declare function findInvalidCouponBlocks(html: string): string[];
1
4
  export declare const useCouponBlockValidator: () => {
2
5
  validateCouponBlockTags: (html: string) => boolean;
3
6
  };
@@ -1,4 +1,14 @@
1
+ declare const SINGLETON_BLOCK_RULES: {
2
+ pageType: number;
3
+ messageKey: string;
4
+ }[];
5
+ export declare const EMPTY_BLOCK_KEY = "unsubscription-preference.select-page-to-continue";
6
+ /** Pure core: the singleton rules whose page type appears more than once. */
7
+ export declare function findDuplicateUnsubPageTypes(html: string): typeof SINGLETON_BLOCK_RULES;
8
+ /** Pure core: count of unsubscribe blocks with no page type or page list chosen. */
9
+ export declare function countUnsubBlocksWithoutPage(html: string): number;
1
10
  export declare const useUnsubscribeBlockValidator: () => {
2
11
  validateUnsubscribeBlockUniqueness: (html: string) => boolean;
3
12
  validateUnsubscribeBlockHasTemplate: (html: string) => boolean;
4
13
  };
14
+ export {};
@@ -1,12 +1,4 @@
1
1
  export declare function extractTitleText(block: Element): string;
2
- /**
3
- * Fallback for legacy configs that carry no `p_recommendation_title` variable:
4
- * the rendered HTML decides. A missing or `display: none` title container means
5
- * the user never saw a title, so the migrated block keeps it toggled off.
6
- * @param block - The legacy recommendation block element
7
- * @returns True when the legacy block renders a visible title
8
- */
9
- export declare function hasVisibleTitle(block: Element): boolean;
10
2
  /**
11
3
  * Card background lives on either the block (`bgcolor`/`style`) or per-card
12
4
  * cells (`.product-card`). Returns empty string when no background is set —
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Stable discriminators for each save-validation rule site — one per rule that
3
+ * can produce a drawer row, kept in sync with the collector + legacy validator chains.
4
+ */
5
+ export declare enum SaveValidationRule {
6
+ CouponTagModified = "coupon-tag-modified",
7
+ DuplicateUnsubBlock = "duplicate-unsub-block",
8
+ UnsubBlockMissingTemplate = "unsub-block-missing-template",
9
+ LiquidSyntax = "liquid-syntax",
10
+ InvalidLinks = "invalid-links",
11
+ LinkCheckInProgress = "link-check-in-progress",
12
+ CustomFieldScript = "custom-field-script",
13
+ EmptyHtml = "empty-html",
14
+ MismatchedBraces = "mismatched-braces",
15
+ InvalidDynamicTag = "invalid-dynamic-tag",
16
+ InvalidCustomField = "invalid-custom-field",
17
+ ConditionsSyntax = "conditions-syntax",
18
+ WrongEqualityOperator = "wrong-equality-operator",
19
+ MissingIfEndif = "missing-if-endif",
20
+ ConditionTagSpacing = "condition-tag-spacing",
21
+ BracesInsideIfTag = "braces-inside-if-tag",
22
+ RecommendationRequiredFields = "recommendation-required-fields",
23
+ RecommendationFilters = "recommendation-filters",
24
+ InvalidImageType = "invalid-image-type",
25
+ CheckboxUnsubGroup = "checkbox-unsub-group",
26
+ RadioButtonUnsubGroup = "radio-button-unsub-group"
27
+ }
@@ -48,21 +48,6 @@ export declare class RecommendationBlock extends Block {
48
48
  * @param node - The block node that may need migration
49
49
  */
50
50
  onDocumentChanged(node: ImmutableHtmlNode): void;
51
- /**
52
- * Adopts the plain text cell a pre-SD-147795 block used as its title.
53
- *
54
- * `recommendationTitleMigrator` tags that cell before the document is handed
55
- * to Stripo, but Stripo serves a template it already holds in its own storage
56
- * (`forceRecreate: false`) and drops the HTML we pass, so for an already-saved
57
- * campaign the tagging only ever lands here. Without it the title is an
58
- * ordinary text block: Card Composition reads the toggle as off while the
59
- * title is on screen, switching it on prepends a second title, and the cell
60
- * keeps the generic delete/duplicate node actions the CSS hides by class.
61
- *
62
- * Partner-managed blocks are left alone, the same exclusion the migrator makes.
63
- * @param node - The block node that may still carry an untagged title
64
- */
65
- private _healLegacyTitle;
66
51
  /**
67
52
  * Called when a block is deleted from the template
68
53
  *