@useinsider/guido 3.18.1-beta.d0bc5f3 → 3.18.1-beta.d82285c

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.
@@ -1,7 +1,7 @@
1
1
  import { useConfig as V } from "./useConfig.js";
2
2
  import { getIgnoredRecommendationBlockIds as M } from "../config/compiler/utils/recommendationIgnoreUtils.js";
3
3
  import { TemplateTypes as W } from "../enums/defaults.js";
4
- import { DISPLAY_CONDITIONS_REGEX as G, DISPLAY_CONDITIONS_EXCEPTIONS_REGEX as H, CampaignCouldNotBeSavedKey as P, CanNotMakeAnyChangesForRunningKey as X, DATA_ATTRIBUTE_REGEX as $, DYNAMIC_CONTENT_TAG_REGEX as K, ALLOWED_DYNAMIC_SYSTEM_TOKENS as Y, VALID_DYNAMIC_VARIABLE_REGEX as U } from "../enums/html-validator.js";
4
+ import { DISPLAY_CONDITIONS_REGEX as G, DISPLAY_CONDITIONS_EXCEPTIONS_REGEX as H, CampaignCouldNotBeSavedKey as K, CanNotMakeAnyChangesForRunningKey as P, DATA_ATTRIBUTE_REGEX as X, DYNAMIC_CONTENT_TAG_REGEX as Y, ALLOWED_DYNAMIC_SYSTEM_TOKENS as $, VALID_DYNAMIC_VARIABLE_REGEX as U } from "../enums/html-validator.js";
5
5
  import { ToasterTypeOptions as c } from "../enums/toaster.js";
6
6
  import { BLOCK_ROOT_SELECTOR as j } from "../extensions/Blocks/Checkbox/constants/selectors.js";
7
7
  import { itemsBlockDynamicVariables as q } from "../extensions/Blocks/Items/enums/productEnums.js";
@@ -9,58 +9,58 @@ import { BLOCK_ROOT_SELECTOR as z } from "../extensions/Blocks/RadioButton/const
9
9
  import { RECOMMENDATION_VARIABLE_BUILTIN_ATTRIBUTES as Z } from "../extensions/Blocks/Recommendation/constants/selectors.js";
10
10
  import { useRecommendationExtensionStore as J } from "../extensions/Blocks/Recommendation/store/recommendation.js";
11
11
  import { filterToProductAttrValue as Q } from "../extensions/Blocks/Recommendation/utils/compositionKeys.js";
12
- import { RecommendationRequiredFieldsKey as ee } from "../extensions/Blocks/Recommendation/validation/requiredFields.js";
13
- import { useRecommendationStore as te } from "../stores/recommendation.js";
14
- import { base64EncodeWithSpecialChars as ne } from "../utils/base64.js";
15
- import { computed as se } from "vue";
16
- import { useHttp as re } from "./useHttp.js";
17
- import { useToaster as oe } from "./useToaster.js";
18
- import { useTranslations as ie } from "./useTranslations.js";
19
- const ae = /recommendation-id="(\d+)"/g;
20
- function ce(s) {
21
- return [...s.matchAll(ae)].map((l) => l[1]);
12
+ import { STRATEGY_FIELD_KEY as ee, RecommendationAssignStrategyKey as te, RecommendationRequiredFieldsKey as ne } from "../extensions/Blocks/Recommendation/validation/requiredFields.js";
13
+ import { useRecommendationStore as se } from "../stores/recommendation.js";
14
+ import { base64EncodeWithSpecialChars as re } from "../utils/base64.js";
15
+ import { computed as oe } from "vue";
16
+ import { useHttp as ie } from "./useHttp.js";
17
+ import { useToaster as ae } from "./useToaster.js";
18
+ import { useTranslations as ce } from "./useTranslations.js";
19
+ const le = /recommendation-id="(\d+)"/g;
20
+ function me(s) {
21
+ return [...s.matchAll(le)].map((m) => m[1]);
22
22
  }
23
- function me(s, l) {
24
- return l.some((f) => s.startsWith(`${f}_`));
23
+ function ue(s, m) {
24
+ return m.some((f) => s.startsWith(`${f}_`));
25
25
  }
26
- const le = /^(\d+)_\d+_(.+)$/;
27
- function ue(s) {
28
- const l = s.match(le);
29
- return l ? { recoId: l[1], attribute: l[2] } : null;
26
+ const de = /^(\d+)_\d+_(.+)$/;
27
+ function fe(s) {
28
+ const m = s.match(de);
29
+ return m ? { recoId: m[1], attribute: m[2] } : null;
30
30
  }
31
- function de(s) {
32
- const l = new Set(Z);
31
+ function ge(s) {
32
+ const m = new Set(Z);
33
33
  return Object.values(s).forEach((f) => {
34
- l.add(Q(f).toLowerCase());
35
- }), l;
34
+ m.add(Q(f).toLowerCase());
35
+ }), m;
36
36
  }
37
- function fe(s, l, f, o, d) {
37
+ function pe(s, m, f, o, d) {
38
38
  const u = s.match(/{{([a-zA-Z0-9_.\s]*)}}/gm);
39
39
  if (!u)
40
40
  return [];
41
- const g = new Set(l.map((C) => C.toLowerCase())), E = [];
41
+ const p = new Set(m.map((C) => C.toLowerCase())), E = [];
42
42
  return u.forEach((C) => {
43
- const p = C.slice(2, -2).trim().toLowerCase();
44
- if (p !== "" && g.has(p))
43
+ const g = C.slice(2, -2).trim().toLowerCase();
44
+ if (g !== "" && p.has(g))
45
45
  return;
46
- const h = ue(p);
47
- if (h && o.has(h.recoId)) {
48
- if (!d || d.has(h.attribute))
46
+ const y = fe(g);
47
+ if (y && o.has(y.recoId)) {
48
+ if (!d || d.has(y.attribute))
49
49
  return;
50
- E.push(p);
50
+ E.push(g);
51
51
  return;
52
52
  }
53
- me(p, f) || p.includes(".") || E.push(p);
53
+ ue(g, f) || g.includes(".") || E.push(g);
54
54
  }), E;
55
55
  }
56
- function pe(s) {
57
- return (s.replace($, "$1").match(K) ?? []).filter((o) => {
58
- const d = o.slice(2, -2), u = d.indexOf("|"), g = (u === -1 ? d : d.slice(0, u)).trim();
59
- return Y.includes(g) ? !1 : U.test(g) ? u !== -1 && d.slice(u + 1).trim() === "" : !0;
56
+ function Ee(s) {
57
+ return (s.replace(X, "$1").match(Y) ?? []).filter((o) => {
58
+ const d = o.slice(2, -2), u = d.indexOf("|"), p = (u === -1 ? d : d.slice(0, u)).trim();
59
+ return $.includes(p) ? !1 : U.test(p) ? u !== -1 && d.slice(u + 1).trim() === "" : !0;
60
60
  });
61
61
  }
62
- const De = () => {
63
- const { showToaster: s } = oe(), { post: l } = re(), { config: f } = V(), o = ie(), d = te(), u = J(), g = se(
62
+ const ke = () => {
63
+ const { showToaster: s } = ae(), { post: m } = ie(), { config: f } = V(), o = ce(), d = se(), u = J(), p = oe(
64
64
  () => {
65
65
  var e, t;
66
66
  return ((t = (e = f.value) == null ? void 0 : e.partner) == null ? void 0 : t.messageType) === W.transactional;
@@ -73,27 +73,27 @@ const De = () => {
73
73
  } catch {
74
74
  return null;
75
75
  }
76
- return de(u.filterList);
76
+ return ge(u.filterList);
77
77
  }, C = async (e) => {
78
- const n = await l(
78
+ const n = await m(
79
79
  "/newsletter/template-library/check-template-html-body",
80
- { html: ne(e) }
80
+ { html: re(e) }
81
81
  ), { status: r, message: a } = n.data;
82
82
  return r || s({
83
83
  type: c.Error,
84
84
  message: r === void 0 ? a : o("newsletter.invalid-url-link-for-toaster")
85
- }), o(P), a === o(X) && s({
85
+ }), o(K), a === o(P) && s({
86
86
  type: c.Error,
87
87
  message: o("newsletter.already-in-progress")
88
88
  }), r;
89
- }, p = (e) => !["if", "endif", "else", "elif", "now"].includes(e.toLowerCase()), h = (e) => ["if", "endif"].includes(e.toLowerCase()), T = (e, t) => {
89
+ }, g = (e) => !["if", "endif", "else", "elif", "now"].includes(e.toLowerCase()), y = (e) => ["if", "endif"].includes(e.toLowerCase()), I = (e, t) => {
90
90
  const n = e.match(/({%(.*?)%})/g);
91
91
  let r = !0;
92
- return n !== null && !g.value && n.forEach((a) => {
92
+ return n !== null && !p.value && n.forEach((a) => {
93
93
  const i = a.slice(2, -2).trim().match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);
94
94
  if (i && i.length > 0) {
95
- const [m] = i;
96
- p(m) && !t.includes(m) && (s({
95
+ const [l] = i;
96
+ g(l) && !t.includes(l) && (s({
97
97
  type: c.Warning,
98
98
  message: o("custom-fields.invalid-custom-fields")
99
99
  }), r = !1);
@@ -101,11 +101,11 @@ const De = () => {
101
101
  }), r;
102
102
  }, R = async (e, t, n) => {
103
103
  const r = n ? await C(e) : !0;
104
- return T(e, t) && r;
105
- }, b = (e) => e.length > 0 ? !0 : (s({
104
+ return I(e, t) && r;
105
+ }, A = (e) => e.length > 0 ? !0 : (s({
106
106
  type: c.Warning,
107
107
  message: o("newsletter.html-content-is-empty")
108
- }), !1), A = (e) => {
108
+ }), !1), _ = (e) => {
109
109
  const t = (e.match(/{/gm) || []).length, n = (e.match(/}/gm) || []).length;
110
110
  return t > n && s({
111
111
  type: c.Warning,
@@ -114,26 +114,26 @@ const De = () => {
114
114
  type: c.Warning,
115
115
  message: o("custom-fields.missing-opening-braces")
116
116
  }), t === n;
117
- }, _ = (e) => {
118
- const t = pe(e).length === 0;
117
+ }, b = (e) => {
118
+ const t = Ee(e).length === 0;
119
119
  return t || s({
120
120
  type: c.Warning,
121
121
  message: o("custom-fields.invalid-custom-fields")
122
122
  }), t;
123
123
  }, O = (e, t, n, r) => {
124
- if (g.value)
124
+ if (p.value)
125
125
  return !0;
126
- const a = fe(
126
+ const a = pe(
127
127
  e,
128
128
  t,
129
- ce(e),
129
+ me(e),
130
130
  n,
131
131
  r
132
132
  );
133
133
  if (a.length > 0) {
134
134
  const i = `
135
135
  <ul>
136
- ${a.map((m) => `<li>${m}</li>`).join("")}
136
+ ${a.map((l) => `<li>${l}</li>`).join("")}
137
137
  </ul>
138
138
  `;
139
139
  return s({
@@ -146,22 +146,22 @@ const De = () => {
146
146
  const t = e.match(/{%(.*?)%}/g), n = [];
147
147
  let r = !0;
148
148
  if (t && t.forEach((a) => {
149
- const i = a.match(G), m = a.match(H), v = (i == null ? void 0 : i.join("")) || "";
150
- (!i || a !== v) && !m && (s({
149
+ const i = a.match(G), l = a.match(H), v = (i == null ? void 0 : i.join("")) || "";
150
+ (!i || a !== v) && !l && (s({
151
151
  type: c.Error,
152
152
  message: o("newsletter.display-conditions-invalid-syntax")
153
- }), r = !1), i && i.forEach((y) => {
154
- y.trim() === "=" && (s({
153
+ }), r = !1), i && i.forEach((h) => {
154
+ h.trim() === "=" && (s({
155
155
  type: c.Error,
156
156
  message: o("custom-conditions.wrong-equality-operators")
157
157
  }), r = !1);
158
- const I = y.match(/^[a-zA-Z]*$/g);
159
- I && I.forEach((S) => {
160
- h(S) && n.push(S);
158
+ const S = h.match(/^[a-zA-Z]*$/g);
159
+ S && S.forEach((T) => {
160
+ y(T) && n.push(T);
161
161
  });
162
162
  });
163
163
  }), n.length) {
164
- const a = n.filter((m) => m === "if"), i = n.filter((m) => m === "endif");
164
+ const a = n.filter((l) => l === "if"), i = n.filter((l) => l === "endif");
165
165
  a.length !== i.length && (s({
166
166
  type: c.Error,
167
167
  message: o("custom-conditions.missing-if-endif-tag")
@@ -177,23 +177,28 @@ const De = () => {
177
177
  }, N = (e) => (e.match(/({%(.*?)%})/g) || []).filter((n) => n.includes("if")).map((n) => (n.match(/{{.*}}/gm) || []).length).reduce((n, r) => n + r, 0) > 0 ? (s({
178
178
  type: c.Warning,
179
179
  message: o("custom-conditions.no-braces-inside-if-tag")
180
- }), !1) : !0, B = () => u.hasInvalidBlock() ? (s({
181
- type: c.Error,
182
- message: o(ee)
183
- }), !1) : !0, x = () => d.recommendationConfigs && Object.values(d.recommendationConfigs).find((t) => t.filters.find((n) => n.value === "")) !== void 0 ? (s({
180
+ }), !1) : !0, B = () => {
181
+ if (!u.hasInvalidBlock())
182
+ return !0;
183
+ const e = u.invalidBlockFields().includes(ee);
184
+ return s({
185
+ type: e ? c.Warning : c.Error,
186
+ message: o(e ? te : ne)
187
+ }), !1;
188
+ }, x = () => d.recommendationConfigs && Object.values(d.recommendationConfigs).find((t) => t.filters.find((n) => n.value === "")) !== void 0 ? (s({
184
189
  type: c.Error,
185
190
  message: o("newsletter.fill-all-necessary-fields")
186
- }), !1) : !0, D = (e) => {
191
+ }), !1) : !0, F = (e) => {
187
192
  const t = /src="[^"]*\.(svg|pst)"/gm;
188
193
  return e.match(t) === null ? !0 : (s({
189
194
  type: c.Error,
190
195
  message: o("newsletter.invalid-image-type")
191
196
  }), !1);
192
- }, F = (e) => {
197
+ }, D = (e) => {
193
198
  const r = new DOMParser().parseFromString(e, "text/html").querySelectorAll(j);
194
199
  return Array.from(r).find((i) => {
195
- var m;
196
- return !((m = i.id) != null && m.trim());
200
+ var l;
201
+ return !((l = i.id) != null && l.trim());
197
202
  }) ? (s({
198
203
  type: c.Error,
199
204
  message: o("unsubscribe-templates.select-checkbox-groups")
@@ -201,26 +206,26 @@ const De = () => {
201
206
  }, k = (e) => {
202
207
  const r = new DOMParser().parseFromString(e, "text/html").querySelectorAll(z);
203
208
  return Array.from(r).find((i) => {
204
- var m;
205
- return !((m = i.id) != null && m.trim());
209
+ var l;
210
+ return !((l = i.id) != null && l.trim());
206
211
  }) ? (s({
207
212
  type: c.Error,
208
213
  message: o("unsubscribe-templates.select-radio-button-groups")
209
214
  }), !1) : !0;
210
215
  };
211
216
  return { validateHtml: async (e, t, n = !1) => {
212
- var v, y;
217
+ var v, h;
213
218
  const r = [
214
- ...t.map((I) => I.value),
219
+ ...t.map((S) => S.value),
215
220
  ...q,
216
- ...((y = (v = f.value) == null ? void 0 : v.template) == null ? void 0 : y.customFieldAttributes) ?? []
221
+ ...((h = (v = f.value) == null ? void 0 : v.template) == null ? void 0 : h.customFieldAttributes) ?? []
217
222
  ], a = M(e), i = await E(a);
218
- return await R(e, r, n) && b(e) && A(e) && _(e) && O(e, r, a, i) && w(e) && L(e) && N(e) && B() && x() && D(e) && F(e) && k(e);
223
+ return await R(e, r, n) && A(e) && _(e) && b(e) && O(e, r, a, i) && w(e) && L(e) && N(e) && B() && x() && F(e) && D(e) && k(e);
219
224
  } };
220
225
  };
221
226
  export {
222
- de as buildPartnerAttributeNameSet,
223
- fe as findInvalidCustomFields,
224
- ue as parseRecommendationVariable,
225
- De as useHtmlValidator
227
+ ge as buildPartnerAttributeNameSet,
228
+ pe as findInvalidCustomFields,
229
+ fe as parseRecommendationVariable,
230
+ ke as useHtmlValidator
226
231
  };
@@ -1,22 +1,22 @@
1
1
  import { getRecommendationFeedSourceMaps as y, URLS as I } from "../enums/extensions/recommendationBlock.js";
2
2
  import { MinDeviceViewport as C, DefaultPadding as R } from "../enums/recommendation.js";
3
- import { useRecommendationExtensionStore as l } from "../extensions/Blocks/Recommendation/store/recommendation.js";
3
+ import { useRecommendationExtensionStore as f } from "../extensions/Blocks/Recommendation/store/recommendation.js";
4
4
  import { generateCompleteFilterQuery as b } from "../extensions/Blocks/Recommendation/utils/filterUtil.js";
5
5
  import { getPartnerRecommendationParams as h } from "../extensions/Blocks/Recommendation/utils/partnerCustomizations.js";
6
6
  import { sanitizeProductIds as x } from "../extensions/Blocks/Recommendation/utils/productIds.js";
7
7
  import { useConfigStore as P } from "../stores/config.js";
8
8
  const B = () => ({
9
9
  calculateCardWidth: ({
10
- mobileLeftPadding: i,
10
+ mobileLeftPadding: a,
11
11
  mobileRightPadding: c,
12
- cardsInRow: s,
12
+ cardsInRow: i,
13
13
  unresponsive: n
14
14
  }) => {
15
- const o = n ? s : 1, e = i + c + (o - 1) * R;
15
+ const o = n ? i : 1, e = a + c + (o - 1) * R;
16
16
  return (C - e) / o;
17
17
  },
18
- getRecommendationCampaignData: (i) => {
19
- const c = l(), s = Number(i), n = c.blockStates[s];
18
+ getRecommendationCampaignData: (a) => {
19
+ const c = f(), i = Number(a), n = c.blockStates[i];
20
20
  if (!n)
21
21
  return {
22
22
  textTrimming: !1,
@@ -44,17 +44,17 @@ const B = () => ({
44
44
  discountAfterTextValue: ""
45
45
  };
46
46
  },
47
- buildCampaignUrl: (i, c) => {
48
- var m;
49
- const s = l(), n = P(), o = Number(i);
47
+ buildCampaignUrl: (a, c) => {
48
+ var l;
49
+ const i = f(), n = P(), o = Number(a);
50
50
  let e;
51
51
  if (c)
52
52
  e = c;
53
53
  else {
54
- const a = s.blockStates[o];
55
- if (!a)
54
+ const s = i.blockStates[o];
55
+ if (!s)
56
56
  return "";
57
- const { recommendationConfigs: r } = a;
57
+ const { recommendationConfigs: r } = s;
58
58
  e = {
59
59
  strategy: r.strategy,
60
60
  strategyId: r.strategyId,
@@ -67,17 +67,20 @@ const B = () => ({
67
67
  };
68
68
  }
69
69
  if (e.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy"))
70
- return s.recommendationCampaignUrls[i] = {
70
+ return i.recommendationCampaignUrls[a] = {
71
71
  strategyId: e.strategyId,
72
72
  locale: e.language,
73
73
  currency: e.currencyCode
74
74
  }, "";
75
- const g = ((m = y().find((a) => a.key === e.strategy)) == null ? void 0 : m.path) || "", t = new URLSearchParams();
75
+ const d = ((l = y().find((s) => s.key === e.strategy)) == null ? void 0 : l.path) || "";
76
+ if (!d)
77
+ return delete i.recommendationCampaignUrls[a], "";
78
+ const t = new URLSearchParams();
76
79
  t.set("locale", e.language), t.set("currency", e.currencyCode), t.set("partnerName", n.partnerName), t.set("size", e.size), t.set("details", "true"), t.set("campaignId", n.variationId), e.strategy === "manualMerchandising" ? t.set("productId", x(e.productIds)) : e.strategy === "similarViewed" && t.set("productId", "{itemId}"), e.strategy === "userBased" && t.set("userId", "{user_id}");
77
- const f = e.filters.filter((a) => a.isValid), d = b(f);
78
- d && t.set("filter", d), e.shuffleProducts && t.set("shuffle", "true"), Object.entries(h(n.partnerName, e.strategy)).forEach(([a, r]) => t.set(a, r));
79
- const p = decodeURIComponent(t.toString()), u = `${I.RECOMMENDATION_API_URL}/v2/${g}?${p}`;
80
- return s.recommendationCampaignUrls[i] = u, u;
80
+ const g = e.filters.filter((s) => s.isValid), u = b(g);
81
+ u && t.set("filter", u), e.shuffleProducts && t.set("shuffle", "true"), Object.entries(h(n.partnerName, e.strategy)).forEach(([s, r]) => t.set(s, r));
82
+ const p = decodeURIComponent(t.toString()), m = `${I.RECOMMENDATION_API_URL}/v2/${d}?${p}`;
83
+ return i.recommendationCampaignUrls[a] = m, m;
81
84
  }
82
85
  });
83
86
  export {
@@ -1,37 +1,37 @@
1
- var R = Object.defineProperty;
2
- var B = (a, c, t) => c in a ? R(a, c, { enumerable: !0, configurable: !0, writable: !0, value: t }) : a[c] = t;
3
- var p = (a, c, t) => B(a, typeof c != "symbol" ? c + "" : c, t);
4
- import { useConfig as D } from "../../../composables/useConfig.js";
5
- import { BlockId as y } from "../../../enums/block.js";
6
- import { getMigrationBannerHtml as C } from "../../../utils/migrationBannerHtml.js";
7
- import { Block as b, BlockCompositionType as A, ModificationDescription as g } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
- import { CURRENT_CONFIG_VERSION as E, PRE_RRS_CONFIG_VERSION as S } from "./constants/defaultConfig.js";
1
+ var D = Object.defineProperty;
2
+ var y = (l, c, t) => c in l ? D(l, c, { enumerable: !0, configurable: !0, writable: !0, value: t }) : l[c] = t;
3
+ var f = (l, c, t) => y(l, typeof c != "symbol" ? c + "" : c, t);
4
+ import { useConfig as C } from "../../../composables/useConfig.js";
5
+ import { BlockId as b } from "../../../enums/block.js";
6
+ import { getMigrationBannerHtml as A } from "../../../utils/migrationBannerHtml.js";
7
+ import { Block as E, BlockCompositionType as S, ModificationDescription as g } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
8
+ import { CURRENT_CONFIG_VERSION as N, PRE_RRS_CONFIG_VERSION as O } from "./constants/defaultConfig.js";
9
9
  import { RECOMMENDATION_ID_ATTR as m } from "./constants/selectors.js";
10
- import { regenerateMobileProductRows as N } from "./controls/main/utils.js";
11
- import { ensureMobileCssRulesExist as h, setMobileLayoutOptOut as f, hasMobileLayoutOptOut as O } from "./controls/mobileLayout/cssRules.js";
10
+ import { regenerateMobileProductRows as M } from "./controls/main/utils.js";
11
+ import { ensureMobileCssRulesExist as _, setMobileLayoutOptOut as I, hasMobileLayoutOptOut as w } from "./controls/mobileLayout/cssRules.js";
12
12
  import { RecommendationConfigService as s } from "./services/configService.js";
13
13
  import { useRecommendationExtensionStore as d } from "./store/recommendation.js";
14
- import { getDefaultTemplate as M } from "./templates/grid/template.js";
15
- import { useRecommendationBlockWarning as w } from "./useRecommendationBlockWarning.js";
16
- const _ = y.Recommendation, u = "recommendation-block-v2", I = "hide-price";
17
- let k = !1;
18
- class W extends b {
14
+ import { getDefaultTemplate as x } from "./templates/grid/template.js";
15
+ import { useRecommendationBlockWarning as H } from "./useRecommendationBlockWarning.js";
16
+ const k = b.Recommendation, u = "recommendation-block-v2", R = "hide-price";
17
+ let B = !1;
18
+ class j extends E {
19
19
  constructor() {
20
20
  super();
21
21
  /**
22
22
  * Stores the ID generated in getTemplate() so onCreated() can reuse it.
23
23
  * This avoids generating a new (different) ID in onCreated().
24
24
  */
25
- p(this, "_pendingBlockId", null);
25
+ f(this, "_pendingBlockId", null);
26
26
  }
27
27
  getId() {
28
- return _;
28
+ return k;
29
29
  }
30
30
  getIcon() {
31
31
  return "recommendation-icon";
32
32
  }
33
33
  getBlockCompositionType() {
34
- return A.CONTAINER;
34
+ return S.CONTAINER;
35
35
  }
36
36
  getName() {
37
37
  return this.api.translate("Recommendation Block");
@@ -42,8 +42,8 @@ class W extends b {
42
42
  );
43
43
  }
44
44
  getSettingsPanelTitleHtml() {
45
- return C(
46
- _,
45
+ return A(
46
+ k,
47
47
  this.api.translate("Recommendation Block"),
48
48
  this.api.translate("This block is switched from the Old Version to the New Version. We recommend you check the Recommendation block and test your message to ensure it works properly.")
49
49
  );
@@ -66,7 +66,7 @@ class W extends b {
66
66
  */
67
67
  getTemplate() {
68
68
  const t = this._generateNextId();
69
- return this._pendingBlockId = t, M(t);
69
+ return this._pendingBlockId = t, x(t);
70
70
  }
71
71
  /**
72
72
  * Called when a new block is dropped into the template
@@ -89,23 +89,27 @@ class W extends b {
89
89
  }
90
90
  const i = this._pendingBlockId ?? this._generateNextId();
91
91
  this._pendingBlockId = null, this._assignRecommendationId(t, i);
92
- const { config: n, wasFreshDrop: o } = s.initializeConfig(
92
+ const n = C().isFeatureEnabled("reusableRecommendationStrategy"), o = n && !s.hasConfig(t), { config: r, wasFreshDrop: a } = s.initializeConfig(
93
93
  this.api,
94
94
  t,
95
95
  {
96
96
  recommendationId: i,
97
- configVersion: D().isFeatureEnabled("reusableRecommendationStrategy") ? E : S
97
+ configVersion: n ? N : O,
98
+ // An RRS block picks a strategy, not an algorithm, and its algorithm control is
99
+ // hidden. Keeping the `mostPopular` default would bake a most-popular feed URL
100
+ // at save for a block the user never configured.
101
+ ...o ? { strategy: "" } : {}
98
102
  }
99
- ), r = d();
100
- if (r.setCurrentBlock(i), this._stampHidePrice(t, n.priceHideIfSameAsDiscounted), o) {
101
- h(this.api);
102
- const l = this._getBlockElement(t);
103
- l && (f(this.api, l, !0), N({
103
+ ), p = d();
104
+ if (p.setCurrentBlock(i), this._stampHidePrice(t, r.priceHideIfSameAsDiscounted), a) {
105
+ _(this.api);
106
+ const h = this._getBlockElement(t);
107
+ h && (I(this.api, h, !0), M({
104
108
  currentNode: t,
105
109
  documentModifier: this.api.getDocumentModifier()
106
110
  }));
107
111
  }
108
- r.patchCurrentBlockConfig({ language: n.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
112
+ p.patchCurrentBlockConfig({ language: r.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
109
113
  }
110
114
  /**
111
115
  * Called when the document changes or template is loaded
@@ -127,11 +131,11 @@ class W extends b {
127
131
  }
128
132
  this._healLingeringDuplicate(t), s.needsMigration(t) && this._migrateFromLegacy(t), this._healHidePriceAttr(t);
129
133
  try {
130
- k || (h(this.api), k = !0);
134
+ B || (_(this.api), B = !0);
131
135
  const e = s.getConfig(t), i = this._getBlockElement(t);
132
136
  if (i) {
133
137
  const n = !e.mobileLayoutEnabled;
134
- O(i) !== n && f(this.api, i, n);
138
+ w(i) !== n && I(this.api, i, n);
135
139
  }
136
140
  } catch {
137
141
  }
@@ -161,7 +165,7 @@ class W extends b {
161
165
  */
162
166
  _warnIfMultipleBlocks() {
163
167
  try {
164
- w().warnIfMultipleBlocks(this.api.getDocumentRootHtmlNode());
168
+ H().warnIfMultipleBlocks(this.api.getDocumentRootHtmlNode());
165
169
  } catch {
166
170
  }
167
171
  }
@@ -211,9 +215,9 @@ class W extends b {
211
215
  if (!o)
212
216
  return;
213
217
  let r = -1;
214
- for (let l = 0; l < n.length; l++)
215
- if (n[l] === o) {
216
- r = l;
218
+ for (let a = 0; a < n.length; a++)
219
+ if (n[a] === o) {
220
+ r = a;
217
221
  break;
218
222
  }
219
223
  if (r <= 0)
@@ -293,7 +297,7 @@ class W extends b {
293
297
  */
294
298
  _stampHidePrice(t, e) {
295
299
  const i = this._getBlockElement(t);
296
- i && this.api.getDocumentModifier().modifyHtml(i).setAttribute(I, String(e)).apply(new g("Stamp hide-price"));
300
+ i && this.api.getDocumentModifier().modifyHtml(i).setAttribute(R, String(e)).apply(new g("Stamp hide-price"));
297
301
  }
298
302
  /**
299
303
  * Stamps `hide-price` from config only when the block lacks the attribute —
@@ -301,7 +305,7 @@ class W extends b {
301
305
  */
302
306
  _healHidePriceAttr(t) {
303
307
  const e = this._getBlockElement(t);
304
- if (!e || !("getAttribute" in e) || e.getAttribute(I) !== null)
308
+ if (!e || !("getAttribute" in e) || e.getAttribute(R) !== null)
305
309
  return;
306
310
  const { priceHideIfSameAsDiscounted: i } = s.getConfig(t);
307
311
  this._stampHidePrice(t, i);
@@ -338,6 +342,6 @@ class W extends b {
338
342
  }
339
343
  }
340
344
  export {
341
- _ as BLOCK_ID,
342
- W as RecommendationBlock
345
+ k as BLOCK_ID,
346
+ j as RecommendationBlock
343
347
  };
@@ -1,23 +1,23 @@
1
- import { getRecommendationFeedSourceMaps as k, strategyEditPath as G, URLS as F, getOperatorOptions as D, PriceAttributes as _ } from "../../../../enums/extensions/recommendationBlock.js";
2
- import { useRecommendationApi as L } from "../../../../services/recommendationApi.js";
3
- import { useConfigStore as N } from "../../../../stores/config.js";
4
- import { defineStore as U } from "pinia";
1
+ import { getRecommendationFeedSourceMaps as k, strategyEditPath as G, URLS as D, getOperatorOptions as _, PriceAttributes as L } from "../../../../enums/extensions/recommendationBlock.js";
2
+ import { useRecommendationApi as E } from "../../../../services/recommendationApi.js";
3
+ import { useConfigStore as P } from "../../../../stores/config.js";
4
+ import { defineStore as N } from "pinia";
5
5
  import "../constants/selectors.js";
6
- import { DEFAULT_MOBILE_CARDS_IN_ROW as A, DEFAULT_CARDS_IN_ROW as E } from "../constants/layout.js";
7
- import { DEFAULT_NODE_CONFIG as x, EXCLUDED_ALGORITHM_IDS as M } from "../constants/defaultConfig.js";
6
+ import { DEFAULT_MOBILE_CARDS_IN_ROW as U, DEFAULT_CARDS_IN_ROW as A } from "../constants/layout.js";
7
+ import { DEFAULT_NODE_CONFIG as x, EXCLUDED_ALGORITHM_IDS as B } from "../constants/defaultConfig.js";
8
8
  import { getDefaultProducts as C } from "../templates/utils.js";
9
9
  import { generateCompleteFilterQuery as v } from "../utils/filterUtil.js";
10
- import { getPartnerRecommendationParams as B } from "../utils/partnerCustomizations.js";
10
+ import { getPartnerRecommendationParams as M } from "../utils/partnerCustomizations.js";
11
11
  import { sanitizeProductIds as O } from "../utils/productIds.js";
12
12
  import { isFilterValid as T } from "../validation/filterSchema.js";
13
- import { isConfigValid as z } from "../validation/requiredFields.js";
14
- const d = L();
13
+ import { getInvalidFields as z, isConfigValid as V } from "../validation/requiredFields.js";
14
+ const d = E();
15
15
  let h = null, g = null, S = null, p = null, y = 0;
16
- const I = /* @__PURE__ */ new Map();
17
- let m = null;
18
- function P() {
16
+ const b = /* @__PURE__ */ new Map();
17
+ let u = null;
18
+ function F() {
19
19
  return {
20
- cardsInRow: E,
20
+ cardsInRow: A,
21
21
  currencySettings: {
22
22
  name: "USD",
23
23
  value: "USD",
@@ -31,13 +31,17 @@ function P() {
31
31
  productIds: [],
32
32
  id: 1,
33
33
  language: "en_US",
34
- mobileCardsInRow: A,
34
+ mobileCardsInRow: U,
35
35
  mobileLayoutEnabled: !1,
36
36
  orientation: "grid",
37
37
  recommendedProducts: [],
38
38
  sendProductRequestFlag: !1,
39
39
  shuffleProducts: !1,
40
- strategy: "mostPopular",
40
+ // With RRS on, a block that has not been synced yet must not claim an algorithm:
41
+ // that default is what reached buildCampaignUrl and baked a most-popular feed URL
42
+ // for a block the user never configured (SD-149916). Legacy blocks still get their real
43
+ // algorithm from the node-config sync or the save-time seed.
44
+ strategy: P().isFeatureEnabled("reusableRecommendationStrategy") ? "" : "mostPopular",
41
45
  strategyId: "",
42
46
  textTrimming: !0,
43
47
  unresponsive: !1,
@@ -49,7 +53,7 @@ function P() {
49
53
  }
50
54
  function w() {
51
55
  return {
52
- recommendationConfigs: P(),
56
+ recommendationConfigs: F(),
53
57
  recommendationProducts: [],
54
58
  filterStatus: !1,
55
59
  filterSelectionDrawerStatus: !1,
@@ -60,7 +64,7 @@ function w() {
60
64
  filterSnapshot: null
61
65
  };
62
66
  }
63
- const V = () => ({
67
+ const j = () => ({
64
68
  recommendationCampaignUrls: {},
65
69
  activePredictiveAlgorithms: [],
66
70
  languages: {},
@@ -73,8 +77,8 @@ const V = () => ({
73
77
  blockStates: {},
74
78
  currentRecommendationId: null,
75
79
  configVersion: 0
76
- }), rt = U("guidoRecommendationExtension", {
77
- state: () => V(),
80
+ }), nt = N("guidoRecommendationExtension", {
81
+ state: () => j(),
78
82
  getters: {
79
83
  // ====================================================================
80
84
  // Proxy Getters — Backward Compatible Access to Current Block State
@@ -84,7 +88,7 @@ const V = () => ({
84
88
  * This allows all existing code that reads `store.recommendationConfigs` to work unchanged.
85
89
  */
86
90
  recommendationConfigs(t) {
87
- return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : P();
91
+ return t.currentRecommendationId !== null && t.blockStates[t.currentRecommendationId] ? t.blockStates[t.currentRecommendationId].recommendationConfigs : F();
88
92
  },
89
93
  /**
90
94
  * Proxy getter: delegates to blockStates[currentRecommendationId].recommendationProducts
@@ -140,7 +144,7 @@ const V = () => ({
140
144
  },
141
145
  getActivePredictiveAlgorithms: (t) => {
142
146
  const e = k(), r = [];
143
- return t.activePredictiveAlgorithms.filter((n) => !M.includes(n)).forEach((n) => {
147
+ return t.activePredictiveAlgorithms.filter((n) => !B.includes(n)).forEach((n) => {
144
148
  r.push(...e.filter((s) => s.id === n));
145
149
  }), r.map((n) => ({
146
150
  text: n.name,
@@ -158,7 +162,7 @@ const V = () => ({
158
162
  getFilterList() {
159
163
  return Object.values(this.filterList).filter((t) => t.isFilterable !== 0 && t.isFilterable !== !1).map((t) => {
160
164
  let e;
161
- return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : _.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
165
+ return t.type === "productAttribute" ? e = `product_attributes.${t.attributeName}` : L.includes(t.attributeName) ? e = `${t.attributeName}.${this.recommendationConfigs.currencySettings.value}` : e = t.attributeName, {
162
166
  text: t.displayName,
163
167
  value: e,
164
168
  type: t.attributeType
@@ -287,7 +291,7 @@ const V = () => ({
287
291
  * Creates a filter with the first available attribute and operator pre-selected.
288
292
  */
289
293
  createDefaultFilter(t, e) {
290
- const [r] = this.getFilterList, [n] = D(r == null ? void 0 : r.type);
294
+ const [r] = this.getFilterList, [n] = _(r == null ? void 0 : r.type);
291
295
  return {
292
296
  type: "standardFilter",
293
297
  attribute: (r == null ? void 0 : r.value) ?? "",
@@ -381,7 +385,7 @@ const V = () => ({
381
385
  * page, so anyone who never does pays nothing.
382
386
  */
383
387
  _armStrategyPageReturn(t) {
384
- window.open(t, "_blank", "noopener"), m == null || m();
388
+ window.open(t, "_blank", "noopener"), u == null || u();
385
389
  let e = !1;
386
390
  const r = () => {
387
391
  document.hidden || e || (e = !0, this.invalidateStrategies(), this.fetchStrategies().then(() => this._refreshAssignedStrategyProducts()).catch(() => {
@@ -389,8 +393,8 @@ const V = () => ({
389
393
  e = !1;
390
394
  }));
391
395
  };
392
- document.addEventListener("visibilitychange", r), window.addEventListener("focus", r), m = () => {
393
- document.removeEventListener("visibilitychange", r), window.removeEventListener("focus", r), m = null;
396
+ document.addEventListener("visibilitychange", r), window.addEventListener("focus", r), u = () => {
397
+ document.removeEventListener("visibilitychange", r), window.removeEventListener("focus", r), u = null;
394
398
  };
395
399
  },
396
400
  /**
@@ -407,14 +411,14 @@ const V = () => ({
407
411
  },
408
412
  /** Lets the editor tear the return listeners down when it unmounts. */
409
413
  disposeStrategyPageReturn() {
410
- m == null || m();
414
+ u == null || u();
411
415
  },
412
416
  /**
413
417
  * Opens Smart Recommender's strategy creation page. Every return refreshes the list so the
414
418
  * new strategy is offered; the user picks it themselves.
415
419
  */
416
420
  openStrategyCreation() {
417
- this._armStrategyPageReturn(F.RECOMMENDATION_STRATEGY_CREATE_PATH);
421
+ this._armStrategyPageReturn(D.RECOMMENDATION_STRATEGY_CREATE_PATH);
418
422
  },
419
423
  /**
420
424
  * Opens the strategy's edit page. Every return refreshes the list so the block reflects the
@@ -558,7 +562,14 @@ const V = () => ({
558
562
  * every block's recommendationConfigs across user edits.
559
563
  */
560
564
  hasInvalidBlock() {
561
- return Object.values(this.blockStates).some((t) => !z(t.recommendationConfigs, this));
565
+ return Object.values(this.blockStates).some((t) => !V(t.recommendationConfigs, this));
566
+ },
567
+ /**
568
+ * Which required fields are missing across the design's blocks, so the save
569
+ * toaster can name the cause instead of always showing the generic message.
570
+ */
571
+ invalidBlockFields() {
572
+ return Object.values(this.blockStates).flatMap((t) => z(t.recommendationConfigs, this));
562
573
  },
563
574
  // ====================================================================
564
575
  // Per-Block Product Fetching
@@ -579,12 +590,17 @@ const V = () => ({
579
590
  },
580
591
  async _doFetchProducts() {
581
592
  var f;
582
- const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = N();
593
+ const t = this.currentRecommendationId, e = this.blockStates[t], { recommendationConfigs: r } = e, n = P();
583
594
  if (r.strategyId && n.isFeatureEnabled("reusableRecommendationStrategy")) {
584
595
  await this._doFetchStrategyProducts(t);
585
596
  return;
586
597
  }
587
- const s = r.filters.filter((u) => u.isValid), i = v(s), o = ((f = k().find((u) => u.key === r.strategy)) == null ? void 0 : f.path) || "", c = parseInt(r.size) || 6, a = {
598
+ const s = parseInt(r.size) || 6;
599
+ if (!r.strategy) {
600
+ this._setBlockProducts(t, [], s);
601
+ return;
602
+ }
603
+ const i = r.filters.filter((m) => m.isValid), o = v(i), c = ((f = k().find((m) => m.key === r.strategy)) == null ? void 0 : f.path) || "", a = {
588
604
  locale: r.language,
589
605
  currency: r.currencySettings.value,
590
606
  partnerName: n.partnerName,
@@ -592,21 +608,21 @@ const V = () => ({
592
608
  details: !0,
593
609
  campaignId: n.variationId
594
610
  };
595
- r.strategy === "manualMerchandising" ? a.productId = O(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), i && (a.filter = i), r.shuffleProducts && (a.shuffle = !0), Object.assign(
611
+ r.strategy === "manualMerchandising" ? a.productId = O(r.productIds) : r.strategy === "similarViewed" && (a.productId = "{itemId}"), r.strategy === "userBased" && (a.userId = "{user_id}"), o && (a.filter = o), r.shuffleProducts && (a.shuffle = !0), Object.assign(
596
612
  a,
597
- B(n.partnerName, r.strategy)
613
+ M(n.partnerName, r.strategy)
598
614
  );
599
615
  let l;
600
616
  try {
601
- l = await d.fetchRecommendationProducts(o, a);
617
+ l = await d.fetchRecommendationProducts(c, a);
602
618
  } catch {
603
619
  l = [];
604
620
  }
605
- this._setBlockProducts(t, l, c);
621
+ this._setBlockProducts(t, l, s);
606
622
  },
607
623
  async _doFetchStrategyProducts(t) {
608
- const e = (I.get(t) ?? 0) + 1;
609
- I.set(t, e);
624
+ const e = (b.get(t) ?? 0) + 1;
625
+ b.set(t, e);
610
626
  const { recommendationConfigs: r } = this.blockStates[t];
611
627
  let n = [], s = parseInt(r.size) || 6;
612
628
  try {
@@ -616,13 +632,13 @@ const V = () => ({
616
632
  );
617
633
  if (i) {
618
634
  s = parseInt(String(i.size ?? "")) || s;
619
- const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), f = l === -1 ? a : a.slice(0, l), u = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((R) => R && !R.startsWith("user_id=")), b = u.length ? `${f}?${u.join("&")}` : f;
620
- b && (n = await d.fetchRecommendationProductsByUrl(b));
635
+ const o = r.currencySettings.value, a = (await this.resolveStrategyUrlTemplate(i, o)).replaceAll("{locale}", r.language).replaceAll("{currency}", o), l = a.indexOf("?"), f = l === -1 ? a : a.slice(0, l), m = (l === -1 ? "" : a.slice(l + 1)).split("&").filter((R) => R && !R.startsWith("user_id=")), I = m.length ? `${f}?${m.join("&")}` : f;
636
+ I && (n = await d.fetchRecommendationProductsByUrl(I));
621
637
  }
622
638
  } catch {
623
639
  n = [];
624
640
  }
625
- I.get(t) === e && this._setBlockProducts(t, n, s);
641
+ b.get(t) === e && this._setBlockProducts(t, n, s);
626
642
  },
627
643
  _setBlockProducts(t, e, r) {
628
644
  if (!this.blockStates[t])
@@ -636,5 +652,5 @@ const V = () => ({
636
652
  }
637
653
  });
638
654
  export {
639
- rt as useRecommendationExtensionStore
655
+ nt as useRecommendationExtensionStore
640
656
  };
@@ -1,34 +1,43 @@
1
- const l = [
1
+ const o = "strategy", u = [
2
2
  {
3
3
  key: "locale",
4
4
  getValue: (e) => e.language,
5
5
  getAvailableOptions: (e) => Object.keys(e.languages)
6
6
  },
7
+ {
8
+ // A block feeds from either an assigned strategy (RRS) or an algorithm (legacy).
9
+ // Only a fresh RRS block has neither, and its feed URL would otherwise be built
10
+ // from an empty algorithm path.
11
+ key: o,
12
+ getValue: (e) => e.strategyId || e.strategy
13
+ },
7
14
  {
8
15
  key: "currency",
9
16
  getValue: (e) => e.currencySettings.value,
10
17
  getAvailableOptions: (e) => e.currencyList.map((n) => n.text),
11
18
  canBeEmpty: !0
12
19
  }
13
- ], o = "newsletter.recommendation-fill-required-fields";
14
- function c(e, n, i = l) {
20
+ ], l = "newsletter.recommendation-fill-required-fields", g = "newsletter.recommendation-assign-strategy";
21
+ function c(e, n, i = u) {
15
22
  return i.filter((t) => {
16
- var u;
23
+ var s;
17
24
  if (t.condition && !t.condition(e))
18
25
  return !1;
19
- const r = (u = t.getAvailableOptions) == null ? void 0 : u.call(t, n);
20
- if (t.canBeEmpty && (r == null ? void 0 : r.length) === 0)
26
+ const a = (s = t.getAvailableOptions) == null ? void 0 : s.call(t, n);
27
+ if (t.canBeEmpty && (a == null ? void 0 : a.length) === 0)
21
28
  return !1;
22
- const a = t.getValue(e);
23
- return a ? r !== void 0 && !r.includes(a) : !0;
29
+ const r = t.getValue(e);
30
+ return r ? a !== void 0 && !a.includes(r) : !0;
24
31
  }).map((t) => t.key);
25
32
  }
26
- function s(e, n) {
33
+ function y(e, n) {
27
34
  return c(e, n).length === 0;
28
35
  }
29
36
  export {
30
- l as REQUIRED_RECOMMENDATION_FIELDS,
31
- o as RecommendationRequiredFieldsKey,
37
+ u as REQUIRED_RECOMMENDATION_FIELDS,
38
+ g as RecommendationAssignStrategyKey,
39
+ l as RecommendationRequiredFieldsKey,
40
+ o as STRATEGY_FIELD_KEY,
32
41
  c as getInvalidFields,
33
- s as isConfigValid
42
+ y as isConfigValid
34
43
  };
@@ -494,6 +494,11 @@ export declare const useRecommendationExtensionStore: import("pinia").StoreDefin
494
494
  * every block's recommendationConfigs across user edits.
495
495
  */
496
496
  hasInvalidBlock(): boolean;
497
+ /**
498
+ * Which required fields are missing across the design's blocks, so the save
499
+ * toaster can name the cause instead of always showing the generic message.
500
+ */
501
+ invalidBlockFields(): string[];
497
502
  fetchRecommendationProducts(): Promise<void>;
498
503
  _doFetchProducts(): Promise<void>;
499
504
  _doFetchStrategyProducts(blockId: number): Promise<void>;
@@ -15,7 +15,11 @@ export interface RequiredField {
15
15
  getAvailableOptions?: (store: ExtensionStoreSlice) => string[];
16
16
  condition?: (config: PerBlockConfigs) => boolean;
17
17
  }
18
+ /** Field key of the strategy/algorithm descriptor, used to pick the toaster message. */
19
+ export declare const STRATEGY_FIELD_KEY = "strategy";
18
20
  export declare const REQUIRED_RECOMMENDATION_FIELDS: RequiredField[];
19
21
  export declare const RecommendationRequiredFieldsKey = "newsletter.recommendation-fill-required-fields";
22
+ /** Shown instead of the generic message when the only thing missing is the strategy. */
23
+ export declare const RecommendationAssignStrategyKey = "newsletter.recommendation-assign-strategy";
20
24
  export declare function getInvalidFields(config: PerBlockConfigs, store: ExtensionStoreSlice, fields?: RequiredField[]): string[];
21
25
  export declare function isConfigValid(config: PerBlockConfigs, store: ExtensionStoreSlice): boolean;
@@ -1,31 +1,31 @@
1
- import { useActionsApi as k } from "../composables/useActionsApi.js";
2
- import { useConfig as U } from "../composables/useConfig.js";
3
- import { useHtmlCompiler as x } from "../composables/useHtmlCompiler.js";
4
- import { DEFAULT_CURRENCY as d, DEFAULT_NODE_CONFIG as a } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
5
- import { useRecommendationExtensionStore as C } from "../extensions/Blocks/Recommendation/store/recommendation.js";
6
- import { mapLegacyStrategy as L } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMap.js";
1
+ import { useActionsApi as R } from "../composables/useActionsApi.js";
2
+ import { useConfig as k } from "../composables/useConfig.js";
3
+ import { useHtmlCompiler as N } from "../composables/useHtmlCompiler.js";
4
+ import { CURRENT_CONFIG_VERSION as U, DEFAULT_CURRENCY as d, DEFAULT_NODE_CONFIG as a } from "../extensions/Blocks/Recommendation/constants/defaultConfig.js";
5
+ import { useRecommendationExtensionStore as T } from "../extensions/Blocks/Recommendation/store/recommendation.js";
6
+ import { mapLegacyStrategy as x } from "../extensions/Blocks/Recommendation/utils/legacyStrategyMap.js";
7
7
  import { DATA_ATTRIBUTES as A } from "../extensions/Blocks/Unsubscribe/utils/constants.js";
8
- import { parsePageList as R } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
9
- import { useDynamicContentStore as N } from "../stores/dynamic-content.js";
10
- import { useEditorStore as z } from "../stores/editor.js";
11
- import { useUnsubscribeStore as _ } from "../stores/unsubscribe.js";
8
+ import { parsePageList as L } from "../extensions/Blocks/Unsubscribe/utils/utils.js";
9
+ import { useDynamicContentStore as z } from "../stores/dynamic-content.js";
10
+ import { useEditorStore as _ } from "../stores/editor.js";
11
+ import { useUnsubscribeStore as O } from "../stores/unsubscribe.js";
12
12
  import { assignTrackingIds as v } from "./linkTrackingIds.js";
13
- function O(m) {
13
+ function B(m) {
14
14
  const i = new DOMParser().parseFromString(m, "text/html").querySelectorAll(`[${A.PAGE_LIST}]`), t = [];
15
15
  return i.forEach((s) => {
16
- const o = s.getAttribute(A.PAGE_LIST);
17
- o && t.push(...R(o));
16
+ const r = s.getAttribute(A.PAGE_LIST);
17
+ r && t.push(...L(r));
18
18
  }), [...new Set(t)];
19
19
  }
20
- async function M(m) {
20
+ async function G(m) {
21
21
  const n = new DOMParser().parseFromString(m, "text/html").querySelectorAll(".recommendation-block-v2");
22
22
  if (n.length === 0)
23
23
  return;
24
- const i = C();
24
+ const i = T();
25
25
  n.forEach((t) => {
26
- var r, l, g, f, c;
27
- const s = t.getAttribute("recommendation-id"), o = s ? Number(s) : NaN;
28
- if (!Number.isFinite(o))
26
+ var l, g, f, c, y;
27
+ const s = t.getAttribute("recommendation-id"), r = s ? Number(s) : NaN;
28
+ if (!Number.isFinite(r))
29
29
  return;
30
30
  const p = t.getAttribute("esd-ext-config");
31
31
  if (!p)
@@ -38,11 +38,11 @@ async function M(m) {
38
38
  }
39
39
  if (!e || typeof e != "object" || Array.isArray(e))
40
40
  return;
41
- const h = {
41
+ const b = !!e.strategyId || (e.configVersion ?? 0) >= U, o = {
42
42
  // Normalize legacy strategy keys (e.g. `mostViewed` → `mostPopular`) so
43
43
  // already-saved blocks that never re-run the migrator don't emit a
44
44
  // strategy-less campaign URL. `||` also catches '' / undefined (SD-144882).
45
- strategy: L(e.strategy) || a.strategy,
45
+ strategy: x(e.strategy) || (b ? "" : a.strategy),
46
46
  strategyId: e.strategyId ?? a.strategyId,
47
47
  language: e.language ?? a.language,
48
48
  size: e.size ?? a.size,
@@ -51,13 +51,13 @@ async function M(m) {
51
51
  productIds: e.productIds ?? [...a.productIds],
52
52
  filters: e.filters ?? [...a.filters],
53
53
  shuffleProducts: e.shuffleProducts ?? a.shuffleProducts,
54
- currencyCode: ((r = e.currency) == null ? void 0 : r.code) ?? d.code,
55
- currencyAlignment: ((l = e.currency) == null ? void 0 : l.alignment) ?? d.alignment,
56
- currencyDecimalCount: ((g = e.currency) == null ? void 0 : g.decimalCount) ?? d.decimalCount,
57
- currencyDecimalSeparator: ((f = e.currency) == null ? void 0 : f.decimalSeparator) ?? d.decimalSeparator,
58
- currencyThousandSeparator: ((c = e.currency) == null ? void 0 : c.thousandSeparator) ?? d.thousandSeparator
54
+ currencyCode: ((l = e.currency) == null ? void 0 : l.code) ?? d.code,
55
+ currencyAlignment: ((g = e.currency) == null ? void 0 : g.alignment) ?? d.alignment,
56
+ currencyDecimalCount: ((f = e.currency) == null ? void 0 : f.decimalCount) ?? d.decimalCount,
57
+ currencyDecimalSeparator: ((c = e.currency) == null ? void 0 : c.decimalSeparator) ?? d.decimalSeparator,
58
+ currencyThousandSeparator: ((y = e.currency) == null ? void 0 : y.thousandSeparator) ?? d.thousandSeparator
59
59
  };
60
- i.seedBlockUrlConfig(o, h);
60
+ i.seedBlockUrlConfig(r, o);
61
61
  });
62
62
  try {
63
63
  await i.fetchRecommendationCreateData();
@@ -68,51 +68,51 @@ async function M(m) {
68
68
  );
69
69
  }
70
70
  }
71
- const Z = () => {
72
- const m = N(), u = z(), n = _(), { getCompiledEmail: i, getTemplateData: t, updateHtmlAndCss: s } = k(), { compileHtml: o, compileAmpHtml: p } = x(), { isFeatureEnabled: e } = U();
71
+ const ee = () => {
72
+ const m = z(), u = _(), n = O(), { getCompiledEmail: i, getTemplateData: t, updateHtmlAndCss: s } = R(), { compileHtml: r, compileAmpHtml: p } = N(), { isFeatureEnabled: e } = k();
73
73
  return {
74
74
  prepareTemplateDetails: async () => {
75
- let { html: r, css: l, syncModulesIds: g = [] } = await t();
75
+ let { html: o, css: l, syncModulesIds: g = [] } = await t();
76
76
  if (e("linkTrackingIds"))
77
77
  try {
78
- const { html: S, changed: F, nextSeq: H } = v(r, u.trackIdSessionFloor);
79
- u.trackIdSessionFloor = H, F && (r = S, await s(S, l));
80
- } catch (S) {
81
- console.error("Tracking-id step failed, saving anyway:", S);
78
+ const { html: h, changed: P, nextSeq: H } = v(o, u.trackIdSessionFloor);
79
+ u.trackIdSessionFloor = H, P && (o = h, await s(h, l));
80
+ } catch (h) {
81
+ console.error("Tracking-id step failed, saving anyway:", h);
82
82
  }
83
- const { html: f, ampHtml: c = "", ampErrors: T = [] } = await i({
83
+ const { html: f, ampHtml: c = "", ampErrors: y = [] } = await i({
84
84
  minimize: !0,
85
85
  resetDataSavedFlag: !1
86
86
  });
87
- n.selectedUnsubscribePages.length && await n.fetchTemplates(), await M(r);
88
- const { compiledHtml: I, stats: y, appliedRules: w } = o(f), D = c && p(c).compiledHtml, E = m.getSelectedDynamicContentList, P = C(), b = O(r);
87
+ n.selectedUnsubscribePages.length && await n.fetchTemplates(), await G(o);
88
+ const { compiledHtml: I, stats: S, appliedRules: E } = r(f), w = c && p(c).compiledHtml, D = m.getSelectedDynamicContentList, F = T(), C = B(o);
89
89
  return console.debug("HTML Compilation Stats:", {
90
- originalSize: y.originalSize,
91
- compiledSize: y.compiledSize,
92
- reduction: `${y.reductionPercentage.toFixed(2)}%`,
93
- appliedRules: w,
94
- executionTime: `${y.executionTime.toFixed(2)}ms`
90
+ originalSize: S.originalSize,
91
+ compiledSize: S.compiledSize,
92
+ reduction: `${S.reductionPercentage.toFixed(2)}%`,
93
+ appliedRules: E,
94
+ executionTime: `${S.executionTime.toFixed(2)}ms`
95
95
  }), {
96
- dynamicContentList: E,
96
+ dynamicContentList: D,
97
97
  compiledHtml: I,
98
- rawHtml: r,
98
+ rawHtml: o,
99
99
  css: l,
100
- ampHtml: D,
101
- ampErrors: T,
100
+ ampHtml: w,
101
+ ampErrors: y,
102
102
  modules: g.map(Number),
103
103
  recommendation: {
104
- campaignUrls: P.recommendationCampaignUrls,
104
+ campaignUrls: F.recommendationCampaignUrls,
105
105
  configs: {}
106
106
  },
107
107
  unsubscribe: {
108
- status: b.length > 0,
109
- config: b
108
+ status: C.length > 0,
109
+ config: C
110
110
  }
111
111
  };
112
112
  }
113
113
  };
114
114
  };
115
115
  export {
116
- O as getHtmlReferencedUnsubscribePages,
117
- Z as useTemplatePreparation
116
+ B as getHtmlReferencedUnsubscribePages,
117
+ ee as useTemplatePreparation
118
118
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@useinsider/guido",
3
- "version": "3.18.1-beta.d0bc5f3",
3
+ "version": "3.18.1-beta.d82285c",
4
4
  "description": "Guido is a Vue + TypeScript wrapper for Email Plugin. Easily embed the email editor in your Vue applications.",
5
5
  "main": "./dist/guido.umd.cjs",
6
6
  "module": "./dist/library.js",