@useinsider/guido 3.8.1 → 3.9.0-beta.7791f66
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.
- package/dist/composables/useHtmlValidator.js +180 -133
- package/dist/config/compiler/utils/recommendationCompilerUtils.js +58 -57
- package/dist/config/compiler/utils/recommendationIgnoreUtils.js +15 -0
- package/dist/config/migrator/recommendation/extractors.js +44 -22
- package/dist/config/migrator/recommendation/htmlBuilder.js +175 -169
- package/dist/config/migrator/recommendationMigrator.js +30 -31
- package/dist/extensions/Blocks/Recommendation/constants/selectors.js +26 -20
- package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +55 -41
- package/dist/extensions/Blocks/Recommendation/controls/main/index.js +58 -57
- package/dist/extensions/Blocks/Recommendation/controls/main/layoutOrientation.js +43 -31
- package/dist/extensions/Blocks/Recommendation/controls/main/productCount.js +3 -2
- package/dist/extensions/Blocks/Recommendation/controls/main/productLayout.js +55 -45
- package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +63 -56
- package/dist/extensions/Blocks/Recommendation/controls/syncInfoMessage.js +7 -6
- package/dist/extensions/Blocks/Recommendation/extension.js +3 -2
- package/dist/extensions/Blocks/Recommendation/settingsPanel.js +3 -2
- package/dist/extensions/Blocks/Recommendation/store/recommendation.js +3 -2
- package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +13 -12
- package/dist/extensions/Blocks/Recommendation/templates/index.js +7 -6
- package/dist/extensions/Blocks/Recommendation/templates/utils.js +1 -1
- package/dist/src/composables/useHtmlValidator.d.ts +27 -0
- package/dist/src/composables/useHtmlValidator.test.d.ts +1 -0
- package/dist/src/config/compiler/utils/recommendationIgnoreUtils.d.ts +17 -0
- package/dist/src/config/compiler/utils/recommendationIgnoreUtils.test.d.ts +1 -0
- package/dist/src/config/migrator/recommendation/extractors.d.ts +15 -0
- package/dist/src/config/migrator/recommendation/htmlBuilder.d.ts +8 -0
- package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
- package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +21 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +7 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/layoutOrientation.d.ts +5 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/productLayout.d.ts +6 -0
- package/dist/src/extensions/Blocks/Recommendation/controls/main/utils.d.ts +9 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ModificationDescription as g } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
2
|
import { RecommendationBlockId as m } from "../../constants/blockIds.js";
|
|
3
|
-
import { CURRENCY_ATTR as
|
|
3
|
+
import { CURRENCY_ATTR as y, CSS_CLASS_SKIP_COMPILE as F, MOBILE_CONTAINER_SELECTOR as O, DESKTOP_CONTAINER_SELECTOR as w, CONTAINER_SELECTOR as G, MOBILE_ROW_SELECTOR as N, ATTR_PRODUCT_ATTR as K, PRODUCT_ATTRIBUTE_PREFIX as R } from "../../constants/selectors.js";
|
|
4
4
|
import { RecommendationConfigService as S } from "../../services/configService.js";
|
|
5
5
|
import { useRecommendationExtensionStore as P } from "../../store/recommendation.js";
|
|
6
6
|
import { prepareProductRows as _ } from "../../templates/index.js";
|
|
@@ -8,7 +8,7 @@ import { captureStyles as k } from "../../utils/captureStyleTemplates.js";
|
|
|
8
8
|
import { formatPrice as V } from "../../utils/priceFormatter.js";
|
|
9
9
|
import { getDefaultProducts as L, DEFAULT_CARD_COMPOSITION as T, sanitizeImageUrl as W, toDisplayableAttributeValue as Y } from "../../templates/utils.js";
|
|
10
10
|
const M = "recommendation-block-v2";
|
|
11
|
-
function
|
|
11
|
+
function A(e) {
|
|
12
12
|
if (!e)
|
|
13
13
|
return null;
|
|
14
14
|
if ("getAttribute" in e) {
|
|
@@ -18,15 +18,19 @@ function q(e) {
|
|
|
18
18
|
}
|
|
19
19
|
return "querySelector" in e ? e.querySelector(`.${M}`) ?? null : null;
|
|
20
20
|
}
|
|
21
|
+
function X(e) {
|
|
22
|
+
const t = A(e);
|
|
23
|
+
return !t || !("getAttribute" in t) ? !1 : (t.getAttribute("class") ?? "").split(/\s+/).includes(F);
|
|
24
|
+
}
|
|
21
25
|
function C(e) {
|
|
22
|
-
const t =
|
|
26
|
+
const t = A(e);
|
|
23
27
|
if (!t || !("getAttribute" in t))
|
|
24
28
|
return "grid";
|
|
25
29
|
const n = t.getAttribute("data-layout");
|
|
26
30
|
return n === "list" || n === "horizontal" ? "list" : "grid";
|
|
27
31
|
}
|
|
28
32
|
function x(e) {
|
|
29
|
-
const t =
|
|
33
|
+
const t = A(e);
|
|
30
34
|
if (!t || !("getAttribute" in t))
|
|
31
35
|
return T;
|
|
32
36
|
const n = t.getAttribute("data-card-composition");
|
|
@@ -51,25 +55,25 @@ function U(e) {
|
|
|
51
55
|
if (typeof e == "number")
|
|
52
56
|
return `0 ${e / 2}px`;
|
|
53
57
|
}
|
|
54
|
-
function
|
|
58
|
+
function z(e) {
|
|
55
59
|
const { currentNode: t, documentModifier: n } = e;
|
|
56
60
|
if (!t || !("querySelector" in t))
|
|
57
61
|
return !1;
|
|
58
62
|
const o = t.querySelector(N);
|
|
59
63
|
return o ? (n.modifyHtml(o).setInnerHtml(""), !0) : !1;
|
|
60
64
|
}
|
|
61
|
-
function
|
|
65
|
+
function J(e) {
|
|
62
66
|
return "getOuterHTML" in e && typeof e.getOuterHTML == "function" ? e.getOuterHTML() : "";
|
|
63
67
|
}
|
|
64
|
-
function
|
|
68
|
+
function Q(e) {
|
|
65
69
|
const t = e.querySelector(".container");
|
|
66
70
|
return !t || !("childNodes" in t) ? null : t.childNodes().find((o) => "getTagName" in o && o.getTagName() === "tbody") ?? t.querySelector("tbody") ?? null;
|
|
67
71
|
}
|
|
68
|
-
function
|
|
69
|
-
const o =
|
|
72
|
+
function Z(e, t, n) {
|
|
73
|
+
const o = Q(e);
|
|
70
74
|
if (!o || !("childNodes" in o))
|
|
71
75
|
return;
|
|
72
|
-
const r = o.childNodes().map(
|
|
76
|
+
const r = o.childNodes().map(J).join(""), s = `<tr class="ins-recommendation-mobile-row">${n}</tr>`;
|
|
73
77
|
t.modifyHtml(o).setInnerHtml(r + s), t.apply(new g("Added mobile product row"));
|
|
74
78
|
}
|
|
75
79
|
function $(e, t = {}) {
|
|
@@ -84,8 +88,8 @@ function $(e, t = {}) {
|
|
|
84
88
|
return !1;
|
|
85
89
|
const u = s ?? C(n), c = S.getConfig(n);
|
|
86
90
|
if (u === "list" || !c.mobileLayoutEnabled)
|
|
87
|
-
return
|
|
88
|
-
const l = P(), a = H(r, l.recommendationProducts), d = i ?? x(n),
|
|
91
|
+
return z({ currentNode: n, documentModifier: o });
|
|
92
|
+
const l = P(), a = H(r, l.recommendationProducts), d = i ?? x(n), p = `<td><table class="ins-recommendation-product-container ins-recommendation-mobile-container" width="100%" cellpadding="0" cellspacing="0" border="0">${_(a, u, {
|
|
89
93
|
productsPerRow: c.mobileCardsInRow,
|
|
90
94
|
composition: d,
|
|
91
95
|
filterList: l.filterList,
|
|
@@ -94,12 +98,12 @@ function $(e, t = {}) {
|
|
|
94
98
|
rowSpacingPx: c.mobileRowSpacing,
|
|
95
99
|
...t
|
|
96
100
|
})}</table></td>`, E = n.querySelector(N);
|
|
97
|
-
return E ? (o.modifyHtml(E).setInnerHtml(
|
|
101
|
+
return E ? (o.modifyHtml(E).setInnerHtml(p), !0) : (Z(n, o, p), !1);
|
|
98
102
|
}
|
|
99
|
-
function
|
|
103
|
+
function pe(e) {
|
|
100
104
|
$(e, k(e.currentNode)) && e.documentModifier.apply(new g("Updated mobile product rows"));
|
|
101
105
|
}
|
|
102
|
-
function
|
|
106
|
+
function ee(e, t = {}) {
|
|
103
107
|
const {
|
|
104
108
|
currentNode: n,
|
|
105
109
|
documentModifier: o,
|
|
@@ -109,21 +113,21 @@ function Q(e, t = {}) {
|
|
|
109
113
|
} = e;
|
|
110
114
|
if (!n || !("querySelector" in n))
|
|
111
115
|
return !1;
|
|
112
|
-
const u = n.querySelector(w) ?? n.querySelector(
|
|
116
|
+
const u = n.querySelector(w) ?? n.querySelector(G);
|
|
113
117
|
if (!u)
|
|
114
118
|
return !1;
|
|
115
|
-
const c = P(), l = H(r, c.recommendationProducts), { cardsInRow: a } = S.getConfig(n), d = i ?? x(n), f = s ?? C(n),
|
|
119
|
+
const c = P(), l = H(r, c.recommendationProducts), { cardsInRow: a } = S.getConfig(n), d = i ?? x(n), f = s ?? C(n), p = S.getConfig(n), E = _(l, f, {
|
|
116
120
|
productsPerRow: a,
|
|
117
121
|
composition: d,
|
|
118
122
|
filterList: c.filterList,
|
|
119
123
|
// One product per row has no gutter — suppress padding without clobbering the stored value.
|
|
120
|
-
cellPadding: a === 1 ? "0" : U(
|
|
121
|
-
rowSpacingPx:
|
|
124
|
+
cellPadding: a === 1 ? "0" : U(p.columnSpacing),
|
|
125
|
+
rowSpacingPx: p.rowSpacing,
|
|
122
126
|
...t
|
|
123
127
|
});
|
|
124
128
|
return o.modifyHtml(u).setInnerHtml(E), !0;
|
|
125
129
|
}
|
|
126
|
-
function
|
|
130
|
+
function ye(e) {
|
|
127
131
|
const {
|
|
128
132
|
currentNode: t,
|
|
129
133
|
documentModifier: n,
|
|
@@ -142,10 +146,10 @@ function me(e) {
|
|
|
142
146
|
layout: s,
|
|
143
147
|
composition: i
|
|
144
148
|
};
|
|
145
|
-
let a =
|
|
149
|
+
let a = ee(l, c);
|
|
146
150
|
a = $(l, c) || a, a && n.apply(new g("Regenerate products with styles")), o == null || o();
|
|
147
151
|
}
|
|
148
|
-
function
|
|
152
|
+
function be(e, t) {
|
|
149
153
|
return e.length === t ? e : e.length > t ? e.slice(0, t) : [...e, ...L(t - e.length)];
|
|
150
154
|
}
|
|
151
155
|
function B() {
|
|
@@ -159,14 +163,14 @@ function B() {
|
|
|
159
163
|
thousandSeparator: t.thousandSeparator
|
|
160
164
|
};
|
|
161
165
|
}
|
|
162
|
-
function
|
|
166
|
+
function q(e, t = "price") {
|
|
163
167
|
const n = B(), o = e[t], r = (o == null ? void 0 : o[n.code]) ?? Object.values(o ?? {})[0] ?? 0;
|
|
164
168
|
return V({
|
|
165
169
|
price: r,
|
|
166
170
|
currency: n
|
|
167
171
|
});
|
|
168
172
|
}
|
|
169
|
-
function
|
|
173
|
+
function te(e) {
|
|
170
174
|
var s, i;
|
|
171
175
|
const t = B(), n = ((s = e.original_price) == null ? void 0 : s[t.code]) ?? Object.values(e.original_price ?? {})[0] ?? 0, o = ((i = e.price) == null ? void 0 : i[t.code]) ?? Object.values(e.price ?? {})[0] ?? 0, r = n > 0 ? Math.round((n - o) / n * 100) : 0;
|
|
172
176
|
return r > 0 ? `-${r}%` : "0%";
|
|
@@ -175,24 +179,24 @@ function v(e) {
|
|
|
175
179
|
const { documentModifier: t, product: n, priceEl: o, oldPriceEl: r, omnibusPriceEl: s, omnibusDiscountEl: i } = e;
|
|
176
180
|
let u = !1;
|
|
177
181
|
if (o && "querySelector" in o) {
|
|
178
|
-
const c = o.querySelector("strong") ?? o.querySelector("p"), l =
|
|
182
|
+
const c = o.querySelector("strong") ?? o.querySelector("p"), l = q(n, "price");
|
|
179
183
|
b(t, c ?? null, l) && (u = !0);
|
|
180
184
|
}
|
|
181
185
|
if (r && "querySelector" in r) {
|
|
182
|
-
const c = r.querySelector("strong") ?? r.querySelector("p"), l =
|
|
186
|
+
const c = r.querySelector("strong") ?? r.querySelector("p"), l = q(n, "original_price");
|
|
183
187
|
b(t, c ?? null, l) && (u = !0);
|
|
184
188
|
}
|
|
185
189
|
if (s && "querySelector" in s) {
|
|
186
|
-
const c = s.querySelector(".omnibus-price-value") ?? null, l =
|
|
190
|
+
const c = s.querySelector(".omnibus-price-value") ?? null, l = q(n, "original_price");
|
|
187
191
|
b(t, c, l) && (u = !0);
|
|
188
192
|
}
|
|
189
193
|
if (i && "querySelector" in i) {
|
|
190
|
-
const c = i.querySelector(".omnibus-discount-value") ?? null, l =
|
|
194
|
+
const c = i.querySelector(".omnibus-discount-value") ?? null, l = te(n);
|
|
191
195
|
b(t, c, l) && (u = !0);
|
|
192
196
|
}
|
|
193
197
|
return u;
|
|
194
198
|
}
|
|
195
|
-
function
|
|
199
|
+
function ne(e) {
|
|
196
200
|
const {
|
|
197
201
|
documentModifier: t,
|
|
198
202
|
product: n,
|
|
@@ -231,7 +235,7 @@ function ee(e) {
|
|
|
231
235
|
function j(e) {
|
|
232
236
|
return "querySelector" in e ? e.querySelector(w) ?? e : e;
|
|
233
237
|
}
|
|
234
|
-
function
|
|
238
|
+
function oe(e, t) {
|
|
235
239
|
var o;
|
|
236
240
|
let n;
|
|
237
241
|
if (e.startsWith(R)) {
|
|
@@ -241,7 +245,7 @@ function te(e, t) {
|
|
|
241
245
|
n = t[e];
|
|
242
246
|
return Y(n) || null;
|
|
243
247
|
}
|
|
244
|
-
function
|
|
248
|
+
function re(e, t, n) {
|
|
245
249
|
if (!("querySelectorAll" in e))
|
|
246
250
|
return !1;
|
|
247
251
|
const o = e.querySelectorAll(
|
|
@@ -253,7 +257,7 @@ function ne(e, t, n) {
|
|
|
253
257
|
o.forEach((i) => {
|
|
254
258
|
if (!("getAttribute" in i))
|
|
255
259
|
return;
|
|
256
|
-
const u = i.getAttribute(
|
|
260
|
+
const u = i.getAttribute(K);
|
|
257
261
|
if (!u)
|
|
258
262
|
return;
|
|
259
263
|
const c = r.get(u) ?? [];
|
|
@@ -265,7 +269,7 @@ function ne(e, t, n) {
|
|
|
265
269
|
i.slice(0, c).forEach((l, a) => {
|
|
266
270
|
if (!("querySelector" in l))
|
|
267
271
|
return;
|
|
268
|
-
const d =
|
|
272
|
+
const d = oe(u, n[a]);
|
|
269
273
|
if (d === null)
|
|
270
274
|
return;
|
|
271
275
|
const f = l.querySelector("p") ?? null;
|
|
@@ -273,7 +277,7 @@ function ne(e, t, n) {
|
|
|
273
277
|
});
|
|
274
278
|
}), s;
|
|
275
279
|
}
|
|
276
|
-
function
|
|
280
|
+
function I(e, t, n) {
|
|
277
281
|
if (!("querySelectorAll" in e))
|
|
278
282
|
return !1;
|
|
279
283
|
const o = e.querySelectorAll(
|
|
@@ -293,7 +297,7 @@ function h(e, t, n) {
|
|
|
293
297
|
), a = Math.min(o.length, n.length);
|
|
294
298
|
let d = !1;
|
|
295
299
|
for (let f = 0; f < a; f++) {
|
|
296
|
-
const
|
|
300
|
+
const p = ne({
|
|
297
301
|
documentModifier: t,
|
|
298
302
|
product: n[f],
|
|
299
303
|
imageEl: o[f] ?? null,
|
|
@@ -304,11 +308,11 @@ function h(e, t, n) {
|
|
|
304
308
|
omnibusDiscountEl: c[f] ?? null,
|
|
305
309
|
buttonEl: l[f] ?? null
|
|
306
310
|
});
|
|
307
|
-
d = d ||
|
|
311
|
+
d = d || p;
|
|
308
312
|
}
|
|
309
|
-
return
|
|
313
|
+
return re(e, t, n) && (d = !0), d;
|
|
310
314
|
}
|
|
311
|
-
function
|
|
315
|
+
function ge(e) {
|
|
312
316
|
const { currentNode: t, documentModifier: n, products: o } = e;
|
|
313
317
|
if (!t || !("querySelectorAll" in t))
|
|
314
318
|
return !1;
|
|
@@ -317,12 +321,12 @@ function pe(e) {
|
|
|
317
321
|
`[esd-extension-block-id="${m.IMAGE}"]`
|
|
318
322
|
).length !== o.length)
|
|
319
323
|
return !1;
|
|
320
|
-
let i =
|
|
324
|
+
let i = I(r, n, o);
|
|
321
325
|
const u = C(t), c = S.getConfig(t);
|
|
322
326
|
if (u !== "list" && c.mobileLayoutEnabled && "querySelector" in t) {
|
|
323
327
|
const l = t.querySelector(O);
|
|
324
328
|
if (l) {
|
|
325
|
-
const a =
|
|
329
|
+
const a = I(
|
|
326
330
|
l,
|
|
327
331
|
n,
|
|
328
332
|
o
|
|
@@ -332,7 +336,7 @@ function pe(e) {
|
|
|
332
336
|
}
|
|
333
337
|
return i && n.apply(new g("Updated product content in-place")), !0;
|
|
334
338
|
}
|
|
335
|
-
function
|
|
339
|
+
function h(e, t, n) {
|
|
336
340
|
if (!("querySelectorAll" in e))
|
|
337
341
|
return !1;
|
|
338
342
|
const o = e.querySelectorAll(
|
|
@@ -356,44 +360,47 @@ function I(e, t, n) {
|
|
|
356
360
|
}) && (c = !0);
|
|
357
361
|
return c;
|
|
358
362
|
}
|
|
359
|
-
function
|
|
363
|
+
function Se(e) {
|
|
360
364
|
const { currentNode: t, documentModifier: n } = e;
|
|
361
365
|
if (!t || !("querySelectorAll" in t))
|
|
362
366
|
return !1;
|
|
367
|
+
if (X(t))
|
|
368
|
+
return !0;
|
|
363
369
|
const r = P().recommendationProducts;
|
|
364
370
|
if (r.length === 0)
|
|
365
371
|
return !1;
|
|
366
372
|
const s = j(t);
|
|
367
|
-
let i =
|
|
373
|
+
let i = h(s, n, r);
|
|
368
374
|
const u = C(t), c = S.getConfig(t);
|
|
369
375
|
if (u !== "list" && c.mobileLayoutEnabled && "querySelector" in t) {
|
|
370
376
|
const l = t.querySelector(O);
|
|
371
377
|
if (l) {
|
|
372
|
-
const a =
|
|
378
|
+
const a = h(l, n, r);
|
|
373
379
|
i = i || a;
|
|
374
380
|
}
|
|
375
381
|
}
|
|
376
382
|
return i && n.apply(new g("Updated price formatting in-place")), i;
|
|
377
383
|
}
|
|
378
|
-
function
|
|
379
|
-
const { currentNode: t, documentModifier: n, currency: o } = e, r =
|
|
384
|
+
function Ee(e) {
|
|
385
|
+
const { currentNode: t, documentModifier: n, currency: o } = e, r = A(t);
|
|
380
386
|
if (!r)
|
|
381
387
|
return;
|
|
382
388
|
const s = o.alignment === "before" ? "0" : "1", i = (u, c) => {
|
|
383
389
|
n.modifyHtml(r).setAttribute(u, c);
|
|
384
390
|
};
|
|
385
|
-
i(
|
|
391
|
+
i(y.CURRENCY, o.code), i(y.SYMBOL, o.symbol), i(y.ALIGNMENT, s), i(y.THOUSAND_SEPARATOR, o.thousandSeparator), i(y.DECIMAL_SEPARATOR, o.decimalSeparator), i(y.DECIMAL_COUNT, o.decimalCount.toString()), n.apply(new g("Update currency attributes"));
|
|
386
392
|
}
|
|
387
393
|
export {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
394
|
+
be as adjustProductsToSize,
|
|
395
|
+
q as formatProductPrice,
|
|
396
|
+
A as getBlockElement,
|
|
391
397
|
x as getCardComposition,
|
|
392
398
|
C as getCurrentLayout,
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
+
X as isPartnerManagedBlock,
|
|
400
|
+
pe as regenerateMobileProductRows,
|
|
401
|
+
ye as regenerateProductRowsWithStyles,
|
|
402
|
+
Ee as setCurrencyAttributes,
|
|
403
|
+
Se as updatePricesInPlace,
|
|
404
|
+
ge as updateProductContentInPlace,
|
|
405
|
+
ne as updateSingleProductContent
|
|
399
406
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
var m = Object.defineProperty;
|
|
2
|
-
var
|
|
3
|
-
var a = (o, e, t) =>
|
|
4
|
-
import { UIElementType as c, UEAttr as
|
|
2
|
+
var p = (o, e, t) => e in o ? m(o, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : o[e] = t;
|
|
3
|
+
var a = (o, e, t) => p(o, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
import { UIElementType as c, UEAttr as _ } from "../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
5
5
|
import { CommonControl as d } from "../../common-control.js";
|
|
6
6
|
import { RecommendationControlId as C } from "../constants/controlIds.js";
|
|
7
|
+
import "../constants/selectors.js";
|
|
7
8
|
const S = C.SYNC_INFO_MESSAGE, r = "sync-info-message", u = "Note that changes will be applied to all product cards in your recommendation block.";
|
|
8
|
-
class
|
|
9
|
+
class O extends d {
|
|
9
10
|
constructor() {
|
|
10
11
|
super(...arguments);
|
|
11
12
|
a(this, "_repositionedElement", null);
|
|
@@ -17,7 +18,7 @@ class h extends d {
|
|
|
17
18
|
return `
|
|
18
19
|
<div class="${r}">
|
|
19
20
|
<${c.ICON}
|
|
20
|
-
${
|
|
21
|
+
${_.ICON.src}="migration-info-icon"
|
|
21
22
|
class="${r}__icon">
|
|
22
23
|
</${c.ICON}>
|
|
23
24
|
<p class="${r}__text">
|
|
@@ -61,5 +62,5 @@ class h extends d {
|
|
|
61
62
|
}
|
|
62
63
|
export {
|
|
63
64
|
S as SYNC_INFO_MESSAGE_CONTROL_ID,
|
|
64
|
-
|
|
65
|
+
O as SyncInfoMessageControl
|
|
65
66
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ExtensionBuilder as r } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
2
|
import { RecommendationBlock as m } from "./block.js";
|
|
3
3
|
import { RecommendationBlockControl as n } from "./controls/main/index.js";
|
|
4
|
+
import "./constants/selectors.js";
|
|
4
5
|
import "./store/recommendation.js";
|
|
5
6
|
import "./utils/captureStyleTemplates.js";
|
|
6
7
|
import { NameControls as i } from "./controls/name/index.js";
|
|
@@ -36,10 +37,10 @@ const b = [
|
|
|
36
37
|
], S = [
|
|
37
38
|
...P,
|
|
38
39
|
...b.flatMap((o) => Object.values(o))
|
|
39
|
-
],
|
|
40
|
+
], Q = S.reduce(
|
|
40
41
|
(o, t) => o.addControl(t),
|
|
41
42
|
new r().addBlock(m).withSettingsPanelRegistry(B)
|
|
42
43
|
).addStyles(y).withIconsRegistry(R).build();
|
|
43
44
|
export {
|
|
44
|
-
|
|
45
|
+
Q as default
|
|
45
46
|
};
|
|
@@ -2,6 +2,7 @@ import { SettingsPanelRegistry as E, SettingsPanelTab as _, SettingsTab as O, Co
|
|
|
2
2
|
import { BLOCK_ID as U } from "./block.js";
|
|
3
3
|
import { RecommendationBlockId as S } from "./constants/blockIds.js";
|
|
4
4
|
import { RecommendationControlId as T } from "./constants/controlIds.js";
|
|
5
|
+
import "./constants/selectors.js";
|
|
5
6
|
import { CONTROL_BLOCK_ID as A } from "./controls/main/index.js";
|
|
6
7
|
import "./store/recommendation.js";
|
|
7
8
|
import "./utils/captureStyleTemplates.js";
|
|
@@ -16,7 +17,7 @@ import { SPACING_CONTROL_ID as L } from "./controls/spacing/index.js";
|
|
|
16
17
|
import { CARD_BACKGROUND_COLOR_CONTROL_ID as D } from "./controls/cardBackground/index.js";
|
|
17
18
|
import { COMPOSITION_CONTROL_BLOCK_ID as B } from "./controls/cardComposition/index.js";
|
|
18
19
|
import { SYNC_INFO_MESSAGE_CONTROL_ID as N } from "./controls/syncInfoMessage.js";
|
|
19
|
-
class
|
|
20
|
+
class d extends E {
|
|
20
21
|
registerBlockControls(I) {
|
|
21
22
|
I[U] = [
|
|
22
23
|
new _(
|
|
@@ -195,5 +196,5 @@ class a extends E {
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
export {
|
|
198
|
-
|
|
199
|
+
d as SettingsPanel
|
|
199
200
|
};
|
|
@@ -2,6 +2,7 @@ import { getRecommendationFeedSourceMaps as g, getOperatorOptions as R, PriceAtt
|
|
|
2
2
|
import { useRecommendationApi as y } from "../../../../services/recommendationApi.js";
|
|
3
3
|
import { useConfigStore as G } from "../../../../stores/config.js";
|
|
4
4
|
import { defineStore as F } from "pinia";
|
|
5
|
+
import "../constants/selectors.js";
|
|
5
6
|
import { DEFAULT_MOBILE_CARDS_IN_ROW as P, DEFAULT_CARDS_IN_ROW as D } from "../constants/layout.js";
|
|
6
7
|
import { EXCLUDED_ALGORITHM_IDS as w } from "../constants/defaultConfig.js";
|
|
7
8
|
import { getDefaultProducts as S } from "../templates/utils.js";
|
|
@@ -60,7 +61,7 @@ const L = () => ({
|
|
|
60
61
|
blockStates: {},
|
|
61
62
|
currentRecommendationId: null,
|
|
62
63
|
configVersion: 0
|
|
63
|
-
}),
|
|
64
|
+
}), $ = F("guidoRecommendationExtension", {
|
|
64
65
|
state: () => L(),
|
|
65
66
|
getters: {
|
|
66
67
|
// ====================================================================
|
|
@@ -476,5 +477,5 @@ const L = () => ({
|
|
|
476
477
|
}
|
|
477
478
|
});
|
|
478
479
|
export {
|
|
479
|
-
|
|
480
|
+
$ as useRecommendationExtensionStore
|
|
480
481
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import "../../constants/selectors.js";
|
|
1
2
|
import { DEFAULT_PRODUCTS_PER_ROW as f } from "../../constants/layout.js";
|
|
2
3
|
import { getDefaultProducts as A, DEFAULTS as C, createBlockTemplate as g, buildSpacer as P, DEFAULT_CARD_COMPOSITION as O, buildElementRenderer as U, DEFAULT_CARD_VISIBILITY as Y } from "../utils.js";
|
|
3
4
|
import { DEFAULT_CELL_PADDING as h, buildFillerCell as B, gridElementRenderer as F } from "./elementRenderer.js";
|
|
@@ -29,34 +30,34 @@ const W = `
|
|
|
29
30
|
`;
|
|
30
31
|
function H(e, r, c, o = O, n = {}, p = {}) {
|
|
31
32
|
const {
|
|
32
|
-
cellPadding:
|
|
33
|
+
cellPadding: a = h,
|
|
33
34
|
styleTemplates: s,
|
|
34
35
|
cardBackgroundColor: T,
|
|
35
36
|
cellBackgroundColors: l,
|
|
36
37
|
cellAlignments: d,
|
|
37
38
|
cellClasses: u,
|
|
38
|
-
omnibusTexts:
|
|
39
|
+
omnibusTexts: i,
|
|
39
40
|
visibility: R
|
|
40
|
-
} = p, m = (100 / r).toFixed(2), I = r - e.length, S = I > 0 ? B(m,
|
|
41
|
+
} = p, m = (100 / r).toFixed(2), I = r - e.length, S = I > 0 ? B(m, a).repeat(I) : "", L = U(c, o, n);
|
|
41
42
|
return o.filter((t) => L[t]).map((t) => {
|
|
42
43
|
const E = (R == null ? void 0 : R[t]) ?? Y[t] ?? !0, b = E ? "" : 'style="display: none;"', _ = {
|
|
43
|
-
cellPadding:
|
|
44
|
+
cellPadding: a,
|
|
44
45
|
cardBackgroundColor: T,
|
|
45
46
|
cellBackgroundColor: l == null ? void 0 : l[t],
|
|
46
47
|
cellAlignment: d == null ? void 0 : d[t],
|
|
47
48
|
cellClasses: u == null ? void 0 : u[t],
|
|
48
|
-
omnibusText:
|
|
49
|
+
omnibusText: i == null ? void 0 : i[t],
|
|
49
50
|
styleTemplate: s == null ? void 0 : s[t]
|
|
50
51
|
}, w = e.map((D) => L[t](D, _).replace("<td", `<td width="${m}%"`)).join("");
|
|
51
52
|
return k.replace("{-{-ATTR_TYPE-}-}", t).replace("{-{-VISIBILITY-}-}", E ? "1" : "0").replace("{-{-DISPLAY_STYLE-}-}", b).replace("{-{-CELLS-}-}", w + S);
|
|
52
53
|
}).join("");
|
|
53
54
|
}
|
|
54
55
|
function x(e, r, c, o, n = {}, p = {}) {
|
|
55
|
-
const
|
|
56
|
+
const a = [];
|
|
56
57
|
for (let l = 0; l < e.length; l += r)
|
|
57
|
-
|
|
58
|
+
a.push(e.slice(l, l + r));
|
|
58
59
|
const s = P(p.rowSpacingPx);
|
|
59
|
-
return
|
|
60
|
+
return a.map((l, d) => {
|
|
60
61
|
const u = H(
|
|
61
62
|
l,
|
|
62
63
|
r,
|
|
@@ -64,8 +65,8 @@ function x(e, r, c, o, n = {}, p = {}) {
|
|
|
64
65
|
o,
|
|
65
66
|
n,
|
|
66
67
|
p
|
|
67
|
-
),
|
|
68
|
-
return d > 0 ? s +
|
|
68
|
+
), i = W.replace("{-{-ATTRIBUTE_ROWS-}-}", u);
|
|
69
|
+
return d > 0 ? s + i : i;
|
|
69
70
|
}).join("");
|
|
70
71
|
}
|
|
71
72
|
function V(e, r, c, o = {}, n = {}) {
|
|
@@ -78,12 +79,12 @@ function V(e, r, c, o = {}, n = {}) {
|
|
|
78
79
|
n
|
|
79
80
|
);
|
|
80
81
|
}
|
|
81
|
-
function
|
|
82
|
+
function y(e) {
|
|
82
83
|
const r = e ? `ins-recommendation-v3-block-${e}` : void 0, c = g("grid", r), o = A(), n = V(o, f);
|
|
83
84
|
return c.replace("{-{-TITLE-}-}", C.TITLE).replace("{-{-PRODUCT_ROWS-}-}", n).replace("{-{-MOBILE_PRODUCT_ROWS-}-}", "");
|
|
84
85
|
}
|
|
85
86
|
export {
|
|
86
|
-
|
|
87
|
+
y as getDefaultTemplate,
|
|
87
88
|
H as prepareGridAttributeRows,
|
|
88
89
|
x as prepareGridProductRows,
|
|
89
90
|
V as prepareProductRows
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import "../constants/selectors.js";
|
|
1
2
|
import { DEFAULT_PRODUCTS_PER_ROW as f } from "../constants/layout.js";
|
|
2
3
|
import { prepareProductRows as w } from "./grid/template.js";
|
|
3
4
|
import { prepareProductRows as g } from "./list/template.js";
|
|
4
|
-
function
|
|
5
|
+
function O(o, t, r = {}) {
|
|
5
6
|
const {
|
|
6
7
|
cellPadding: s,
|
|
7
8
|
rowSpacingPx: i,
|
|
@@ -10,8 +11,8 @@ function L(o, t, r = {}) {
|
|
|
10
11
|
cellBackgroundColors: p,
|
|
11
12
|
cellAlignments: n,
|
|
12
13
|
cellClasses: a,
|
|
13
|
-
omnibusTexts:
|
|
14
|
-
visibility:
|
|
14
|
+
omnibusTexts: m,
|
|
15
|
+
visibility: d
|
|
15
16
|
} = r, e = {
|
|
16
17
|
cellPadding: s,
|
|
17
18
|
rowSpacingPx: i,
|
|
@@ -20,8 +21,8 @@ function L(o, t, r = {}) {
|
|
|
20
21
|
cellBackgroundColors: p,
|
|
21
22
|
cellAlignments: n,
|
|
22
23
|
cellClasses: a,
|
|
23
|
-
omnibusTexts:
|
|
24
|
-
visibility:
|
|
24
|
+
omnibusTexts: m,
|
|
25
|
+
visibility: d
|
|
25
26
|
};
|
|
26
27
|
if (t === "list")
|
|
27
28
|
return g(o, r.composition, r.filterList, e);
|
|
@@ -29,5 +30,5 @@ function L(o, t, r = {}) {
|
|
|
29
30
|
return w(o, u, P, R, e);
|
|
30
31
|
}
|
|
31
32
|
export {
|
|
32
|
-
|
|
33
|
+
O as prepareProductRows
|
|
33
34
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ATTR_CUSTOM_PREFIX as c, ATTR_PRODUCT_IMAGE as b, ATTR_PRODUCT_NAME as T, ATTR_PRODUCT_OLD_PRICE as g, ATTR_PRODUCT_PRICE as _, ATTR_PRODUCT_OMNIBUS_PRICE as f, ATTR_PRODUCT_OMNIBUS_DISCOUNT as p, ATTR_PRODUCT_BUTTON as m
|
|
1
|
+
import { ATTR_CUSTOM_PREFIX as c, PRODUCT_ATTRIBUTE_PREFIX as l, ATTR_PRODUCT_IMAGE as b, ATTR_PRODUCT_NAME as T, ATTR_PRODUCT_OLD_PRICE as g, ATTR_PRODUCT_PRICE as _, ATTR_PRODUCT_OMNIBUS_PRICE as f, ATTR_PRODUCT_OMNIBUS_DISCOUNT as p, ATTR_PRODUCT_BUTTON as m } from "../constants/selectors.js";
|
|
2
2
|
function U(t) {
|
|
3
3
|
return t.replace(/_/g, " ").replace(/\b\w/g, (n) => n.toUpperCase());
|
|
4
4
|
}
|
|
@@ -1,4 +1,31 @@
|
|
|
1
1
|
import type { DynamicContent } from '@@/Types/generic';
|
|
2
|
+
import type { FiltersResponse } from '@@/Types/recommendation';
|
|
3
|
+
/**
|
|
4
|
+
* Parses a `{{recoId_index_attributeName}}` variable (already stripped of the
|
|
5
|
+
* braces/whitespace) into its recommendation id and attribute name. Returns
|
|
6
|
+
* null for anything that isn't a well-formed recommendation variable.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseRecommendationVariable(field: string): {
|
|
9
|
+
recoId: string;
|
|
10
|
+
attribute: string;
|
|
11
|
+
} | null;
|
|
12
|
+
/**
|
|
13
|
+
* Builds the set of attribute forms valid inside partner-authored
|
|
14
|
+
* `{{recoId_index_attribute}}` variables: the built-in compiler attributes plus
|
|
15
|
+
* each account attribute in its canonical token form — bare for
|
|
16
|
+
* `defaultAttribute`, `product_attribute.<name>` for `productAttribute`. Using
|
|
17
|
+
* `resolveProductAttrValue` (the same producer the block builder uses) keeps the
|
|
18
|
+
* validator's notion of "valid form" identical to what is actually emitted.
|
|
19
|
+
*/
|
|
20
|
+
export declare function buildPartnerAttributeNameSet(filterList: FiltersResponse): Set<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Returns the `{{...}}` custom fields in the HTML that are invalid. Partner
|
|
23
|
+
* attributes in `ins-skip-compile` blocks (recoId ∈ ignoredIds) are checked
|
|
24
|
+
* against `ignoredAttributeNames`; Guido-generated reco variables and known merge
|
|
25
|
+
* tags pass. An unrecognized dotted token is ignored: it was never captured
|
|
26
|
+
* before, so flagging it would false-positive on merge tags like `{{user.name}}`.
|
|
27
|
+
*/
|
|
28
|
+
export declare function findInvalidCustomFields(html: string, validCustomFields: string[], recommendationBlockIds: string[], ignoredIds: Set<string>, ignoredAttributeNames: Set<string> | null): string[];
|
|
2
29
|
export declare const useHtmlValidator: () => {
|
|
3
30
|
validateHtml: (html: string, customFields: DynamicContent[], isOnSaveValidation?: boolean) => Promise<boolean>;
|
|
4
31
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns true when a recommendation block has opted out of Guido's
|
|
3
|
+
* product-data → template-variable substitution. Partners signal opt-out by
|
|
4
|
+
* adding the `ins-skip-compile` class on the `.recommendation-block-v2`
|
|
5
|
+
* element. Only the variable substitution is skipped — campaign URL building,
|
|
6
|
+
* hidden-row removal, Outlook image widths, discount conditions, text-trim CSS
|
|
7
|
+
* and general HTML optimizations still apply. See `CSS_CLASS_SKIP_COMPILE` for
|
|
8
|
+
* the full scope.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isIgnoredRecommendationBlock(block: Element): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* DOM-parses the HTML once and returns the set of `recommendation-id`
|
|
13
|
+
* values that belong to ignored blocks. Use this in regex/string-based
|
|
14
|
+
* compiler rules where the rule processes flat matches and only has the
|
|
15
|
+
* extracted block ID rather than a DOM Element reference.
|
|
16
|
+
*/
|
|
17
|
+
export declare function getIgnoredRecommendationBlockIds(html: string): Set<string>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -5,3 +5,18 @@ export declare function extractTitleText(block: Element): string;
|
|
|
5
5
|
* the caller treats that as "no segment background".
|
|
6
6
|
*/
|
|
7
7
|
export declare function extractCardBgColor(block: Element): string;
|
|
8
|
+
/**
|
|
9
|
+
* Reads the legacy block's own `currency-*` attributes into a
|
|
10
|
+
* `currencySettings`-shaped object that `mapCurrency` understands. Used as a
|
|
11
|
+
* fallback when the external recommendationConfigs map has no entry for this
|
|
12
|
+
* block, so the migrated block keeps its real currency instead of defaulting.
|
|
13
|
+
* Returns undefined when the block carries no `currency` attribute.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractCurrencyFromBlock(block: Element): Record<string, string> | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* True when a PM has manually opted the legacy block out of content
|
|
18
|
+
* regeneration by adding the `ins-skip-compile` class. Detected before rebuild
|
|
19
|
+
* so the migrator preserves the partner's markup verbatim (keeping their
|
|
20
|
+
* hand-authored variables) instead of regenerating the block.
|
|
21
|
+
*/
|
|
22
|
+
export declare function isPartnerManagedBlock(block: Element): boolean;
|
|
@@ -8,4 +8,12 @@ export declare function buildBlockHtml(params: {
|
|
|
8
8
|
extraClasses?: string;
|
|
9
9
|
legacyId?: string;
|
|
10
10
|
legacyBgColor?: string;
|
|
11
|
+
/**
|
|
12
|
+
* When set, the block's existing inner HTML is preserved verbatim instead
|
|
13
|
+
* of regenerating product rows — used for partner-customized blocks so
|
|
14
|
+
* their hand-authored `{{...}}` variables survive migration.
|
|
15
|
+
*/
|
|
16
|
+
preserveInnerHtml?: string;
|
|
17
|
+
/** Adds the `ins-skip-compile` opt-out class to the migrated block. */
|
|
18
|
+
skipCompile?: boolean;
|
|
11
19
|
}): string;
|
|
@@ -8,6 +8,6 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { RecommendationBlockId } from './blockIds';
|
|
10
10
|
export { RecommendationControlId } from './controlIds';
|
|
11
|
-
export { BLOCK_ROOT_SELECTOR, CONTAINER_SELECTOR, DESKTOP_CONTAINER_SELECTOR, MOBILE_CONTAINER_SELECTOR, MOBILE_ROW_SELECTOR, CSS_CLASS_RECO_BUTTON, CURRENCY_ATTR, ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON, ATTR_CUSTOM_PREFIX, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, PRODUCT_ATTRIBUTE_PREFIX, BUILT_IN_DEFAULT_ATTRIBUTES, } from './selectors';
|
|
11
|
+
export { BLOCK_ROOT_SELECTOR, CONTAINER_SELECTOR, DESKTOP_CONTAINER_SELECTOR, MOBILE_CONTAINER_SELECTOR, MOBILE_ROW_SELECTOR, CSS_CLASS_RECO_BUTTON, CSS_CLASS_SKIP_COMPILE, RECOMMENDATION_VARIABLE_BUILTIN_ATTRIBUTES, CURRENCY_ATTR, ATTR_PRODUCT_IMAGE, ATTR_PRODUCT_NAME, ATTR_PRODUCT_PRICE, ATTR_PRODUCT_OLD_PRICE, ATTR_PRODUCT_OMNIBUS_PRICE, ATTR_PRODUCT_OMNIBUS_DISCOUNT, ATTR_PRODUCT_BUTTON, ATTR_CUSTOM_PREFIX, ATTR_DATA_CUSTOM_ATTRIBUTES, ATTR_PRODUCT_ATTR, PRODUCT_ATTRIBUTE_PREFIX, BUILT_IN_DEFAULT_ATTRIBUTES, } from './selectors';
|
|
12
12
|
export { LAYOUT_VALUES, LAYOUT_OPTIONS, DEFAULT_PRODUCTS_PER_ROW, DEFAULT_CARDS_IN_ROW, DEFAULT_MOBILE_CARDS_IN_ROW, MAX_PRODUCT_COUNT, MIN_PRODUCT_COUNT, MAX_PRODUCTS_PER_ROW, MIN_PRODUCTS_PER_ROW, MAX_MOBILE_PRODUCTS_PER_ROW, MIN_MOBILE_PRODUCTS_PER_ROW, DEFAULT_COLUMN_SPACING, DEFAULT_ROW_SPACING, DEFAULT_MOBILE_COLUMN_SPACING, DEFAULT_MOBILE_ROW_SPACING, MIN_SPACING, MAX_SPACING, SPACING_STEP, } from './layout';
|
|
13
13
|
export { DEFAULT_NODE_CONFIG, DEFAULT_CURRENCY, DEFAULT_COMPOSITION, DEFAULT_VISIBILITY, CURRENT_CONFIG_VERSION, EXCLUDED_ALGORITHM_IDS, } from './defaultConfig';
|