@useinsider/guido 3.20.0-beta.11a0bde → 3.20.0-beta.12889e0
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/config/compiler/utils/recommendationCompilerUtils.js +72 -57
- package/dist/extensions/Blocks/Recommendation/block.js +63 -41
- package/dist/extensions/Blocks/Recommendation/controls/mobileLayout/cssRules.js +15 -11
- package/dist/extensions/Blocks/Recommendation/templates/utils.js +16 -16
- package/dist/extensions/Blocks/Recommendation/utils/captureStyleTemplates.js +91 -87
- package/dist/extensions/Blocks/Recommendation/utils/legacyStrategyMigration.js +9 -9
- package/dist/extensions/Blocks/Recommendation/utils/productIds.js +3 -5
- package/dist/src/extensions/Blocks/Recommendation/block.d.ts +1 -0
- package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +5 -2
- package/dist/src/extensions/Blocks/Recommendation/utils/productIds.d.ts +0 -2
- package/dist/src/utils/fluidImageStyle.d.ts +7 -0
- package/dist/utils/fluidImageStyle.js +26 -0
- package/package.json +1 -1
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { useConfig as
|
|
2
|
-
import { useRecommendation as
|
|
3
|
-
import { MOBILE_ROW_SELECTOR as
|
|
4
|
-
import { useRecommendationExtensionStore as
|
|
5
|
-
import {
|
|
6
|
-
|
|
1
|
+
import { useConfig as O } from "../../../composables/useConfig.js";
|
|
2
|
+
import { useRecommendation as q } from "../../../composables/useRecommendation.js";
|
|
3
|
+
import { MOBILE_ROW_SELECTOR as L, MOBILE_CONTAINER_SELECTOR as M, CSS_CLASS_RECO_BUTTON as P } from "../../../extensions/Blocks/Recommendation/constants/selectors.js";
|
|
4
|
+
import { useRecommendationExtensionStore as R } from "../../../extensions/Blocks/Recommendation/store/recommendation.js";
|
|
5
|
+
import { FLUID_IMAGE_MOBILE_RULE as T, getFluidImageStyleChanges as B } from "../../../utils/fluidImageStyle.js";
|
|
6
|
+
import { isIgnoredRecommendationBlock as N } from "./recommendationIgnoreUtils.js";
|
|
7
|
+
function D(t, r, e, o, c = "") {
|
|
7
8
|
const i = `{{${c}${t}_${r}_${e}}}`, n = `{{${c}${t}_${r}_currency}}`;
|
|
8
9
|
return o === "before" ? `${n} ${i}` : `${i} ${n}`;
|
|
9
10
|
}
|
|
@@ -13,13 +14,13 @@ function _(t) {
|
|
|
13
14
|
[r] = r.children;
|
|
14
15
|
return r;
|
|
15
16
|
}
|
|
16
|
-
function
|
|
17
|
+
function E(t, r, e, o, c, i) {
|
|
17
18
|
switch (r) {
|
|
18
19
|
case "productImage": {
|
|
19
20
|
const n = t.querySelector("img");
|
|
20
21
|
n && (n.setAttribute("src", `{{${i}${e}_${o}_image_url}}`), n.setAttribute("alt", `{{${i}${e}_${o}_name}}`));
|
|
21
22
|
const s = t.querySelector("a");
|
|
22
|
-
s && (s.setAttribute("href", `{{${i}${e}_${o}_url}}`), s.classList.add(
|
|
23
|
+
s && (s.setAttribute("href", `{{${i}${e}_${o}_url}}`), s.classList.add(P));
|
|
23
24
|
break;
|
|
24
25
|
}
|
|
25
26
|
case "productName": {
|
|
@@ -33,7 +34,7 @@ function A(t, r, e, o, c, i) {
|
|
|
33
34
|
case "productPrice":
|
|
34
35
|
case "productOldPrice": {
|
|
35
36
|
const n = (l, d) => {
|
|
36
|
-
l && (_(l).textContent =
|
|
37
|
+
l && (_(l).textContent = D(
|
|
37
38
|
e,
|
|
38
39
|
o,
|
|
39
40
|
d,
|
|
@@ -77,24 +78,24 @@ function A(t, r, e, o, c, i) {
|
|
|
77
78
|
}
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
|
-
const
|
|
81
|
+
const w = "name";
|
|
81
82
|
function b(t, r, e, o) {
|
|
82
|
-
const c = `${o}${r}_${e}_${
|
|
83
|
+
const c = `${o}${r}_${e}_${w}`;
|
|
83
84
|
return {
|
|
84
85
|
open: t.createComment(`{% if ${c} and ${c} != "" %}`),
|
|
85
86
|
close: t.createComment("{% endif %}")
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
|
-
function
|
|
89
|
+
function F(t, r, e) {
|
|
89
90
|
return b(t, r, 0, e);
|
|
90
91
|
}
|
|
91
|
-
function
|
|
92
|
+
function v(t, r, e, o) {
|
|
92
93
|
if (!t.innerHTML.includes("{{"))
|
|
93
94
|
return;
|
|
94
95
|
const { open: c, close: i } = b(t.ownerDocument, r, e, o);
|
|
95
96
|
t.insertBefore(c, t.firstChild), t.appendChild(i);
|
|
96
97
|
}
|
|
97
|
-
function
|
|
98
|
+
function H(t, r, e, o) {
|
|
98
99
|
var n, s;
|
|
99
100
|
if (!t.innerHTML.includes("{{"))
|
|
100
101
|
return;
|
|
@@ -106,36 +107,36 @@ function W(t, r, e, o) {
|
|
|
106
107
|
i.querySelectorAll("[data-attribute-type]").forEach((a) => {
|
|
107
108
|
const u = a.getAttribute("data-attribute-type") || "", l = a.querySelectorAll(".attribute-cell");
|
|
108
109
|
l.length > 0 ? l.forEach((d) => {
|
|
109
|
-
|
|
110
|
-
}) :
|
|
111
|
-
}),
|
|
110
|
+
E(d, u, r, n, e, o);
|
|
111
|
+
}) : E(a, u, r, n, e, o);
|
|
112
|
+
}), H(i, r, n, o);
|
|
112
113
|
});
|
|
113
114
|
}
|
|
114
|
-
function
|
|
115
|
+
function G(t, r, e, o) {
|
|
115
116
|
const c = t.querySelectorAll(".recommendation-product-row");
|
|
116
117
|
if (!c.length)
|
|
117
118
|
return;
|
|
118
119
|
const [i] = c, n = i.querySelector("[data-attribute-type]"), s = n ? n.querySelectorAll(".attribute-cell").length : 1;
|
|
119
120
|
c.forEach((a, u) => {
|
|
120
121
|
a.querySelectorAll("[data-attribute-type]").forEach((d) => {
|
|
121
|
-
const
|
|
122
|
-
d.querySelectorAll(".attribute-cell").forEach((
|
|
123
|
-
const
|
|
124
|
-
|
|
122
|
+
const f = d.getAttribute("data-attribute-type") || "";
|
|
123
|
+
d.querySelectorAll(".attribute-cell").forEach((p, m) => {
|
|
124
|
+
const y = u * s + m;
|
|
125
|
+
E(p, f, r, y, e, o), v(p, r, y, o);
|
|
125
126
|
});
|
|
126
127
|
});
|
|
127
128
|
});
|
|
128
129
|
}
|
|
129
|
-
function
|
|
130
|
+
function U(t, r, e, o) {
|
|
130
131
|
t.querySelectorAll(".ins-recommendation-product-container").forEach((i) => {
|
|
131
|
-
|
|
132
|
+
G(i, r, e, o);
|
|
132
133
|
});
|
|
133
134
|
}
|
|
134
|
-
function
|
|
135
|
+
function I(t, r, e) {
|
|
135
136
|
const o = t.getAttribute("data-layout") || "grid", c = t.getAttribute("currency-alignment") || "after";
|
|
136
|
-
o === "list" ? W(t, r, c, e) :
|
|
137
|
+
o === "list" ? W(t, r, c, e) : U(t, r, c, e);
|
|
137
138
|
}
|
|
138
|
-
function
|
|
139
|
+
function S(t, r, e) {
|
|
139
140
|
const o = new RegExp(`${r}\\s*:\\s*(\\d+)\\s*px`, "i"), c = t.match(o);
|
|
140
141
|
return c ? parseInt(c[1]) : e;
|
|
141
142
|
}
|
|
@@ -150,7 +151,7 @@ function C(t) {
|
|
|
150
151
|
const e = (t.getAttribute("style") || "").match(/(?:^|[;\s])width\s*:\s*(\d+(?:\.\d+)?(?:px|%))/i);
|
|
151
152
|
return e && $(e[1]) ? e[1] : null;
|
|
152
153
|
}
|
|
153
|
-
function
|
|
154
|
+
function V(t, r) {
|
|
154
155
|
let e = t.parentElement;
|
|
155
156
|
for (; e && e !== r; ) {
|
|
156
157
|
if (e.tagName === "TD" && C(e))
|
|
@@ -159,60 +160,74 @@ function G(t, r) {
|
|
|
159
160
|
}
|
|
160
161
|
return null;
|
|
161
162
|
}
|
|
162
|
-
function
|
|
163
|
-
const r =
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
function A(t) {
|
|
164
|
+
const r = B(
|
|
165
|
+
(e) => t.style.getPropertyValue(e),
|
|
166
|
+
t.getAttribute("width")
|
|
167
|
+
);
|
|
168
|
+
Object.entries(r).forEach(([e, o]) => t.style.setProperty(e, o));
|
|
169
|
+
}
|
|
170
|
+
function X(t) {
|
|
171
|
+
const r = t.getAttribute("style") || "", e = S(r, "width", 600), o = S(r, "padding", 0) * 2, c = Math.max(0, e - o);
|
|
172
|
+
t.querySelectorAll("img.adapt-img").forEach((i) => {
|
|
173
|
+
if (i.hasAttribute("width") || c === 0) {
|
|
174
|
+
A(i);
|
|
166
175
|
return;
|
|
167
|
-
|
|
168
|
-
|
|
176
|
+
}
|
|
177
|
+
const n = V(i, t);
|
|
178
|
+
if (!n) {
|
|
179
|
+
A(i);
|
|
169
180
|
return;
|
|
170
|
-
const s = C(n), a = y(n.getAttribute("style") || "", "padding", 0) * 2, u = s.endsWith("%") ? Math.floor(c * parseFloat(s) / 100) : parseInt(s), l = Math.max(1, u - a);
|
|
171
|
-
i.setAttribute("width", String(l));
|
|
172
|
-
const d = i.getAttribute("style") || "";
|
|
173
|
-
if (!/\bwidth\s*:\s*\d/i.test(d)) {
|
|
174
|
-
const p = d && !d.trim().endsWith(";") ? "; " : "";
|
|
175
|
-
i.setAttribute("style", `${d}${p}width: ${l}px`);
|
|
176
181
|
}
|
|
182
|
+
const s = C(n), a = S(n.getAttribute("style") || "", "padding", 0) * 2, u = s.endsWith("%") ? Math.floor(c * parseFloat(s) / 100) : parseInt(s), l = Math.max(1, u - a);
|
|
183
|
+
i.setAttribute("width", String(l)), A(i);
|
|
177
184
|
});
|
|
178
185
|
}
|
|
179
|
-
const
|
|
180
|
-
function
|
|
181
|
-
t.querySelectorAll(
|
|
186
|
+
const j = /\.recommendation-block-v2\s+\.adapt-img/;
|
|
187
|
+
function x(t, r) {
|
|
188
|
+
const e = r.some((i) => i.querySelector("img.adapt-img")), o = Array.from(t.querySelectorAll("style")).some((i) => j.test(i.textContent ?? ""));
|
|
189
|
+
if (!e || o || !t.head)
|
|
190
|
+
return;
|
|
191
|
+
const c = t.createElement("style");
|
|
192
|
+
c.setAttribute("type", "text/css"), c.textContent = T, t.head.appendChild(c);
|
|
193
|
+
}
|
|
194
|
+
const g = "MSO_MOBILE_HIDE_START", Y = "MSO_MOBILE_HIDE_END";
|
|
195
|
+
function k(t, r) {
|
|
196
|
+
t.querySelectorAll(L).forEach((e) => {
|
|
182
197
|
var i, n;
|
|
183
198
|
const o = e.querySelector(M);
|
|
184
199
|
if (!o || o.children.length === 0)
|
|
185
200
|
return;
|
|
186
201
|
const c = e.previousSibling;
|
|
187
|
-
(c == null ? void 0 : c.nodeType) === Node.COMMENT_NODE && c.data ===
|
|
202
|
+
(c == null ? void 0 : c.nodeType) === Node.COMMENT_NODE && c.data === g || ((i = e.parentNode) == null || i.insertBefore(r.createComment(g), e), (n = e.parentNode) == null || n.insertBefore(r.createComment(Y), e.nextSibling));
|
|
188
203
|
});
|
|
189
204
|
}
|
|
190
|
-
function
|
|
205
|
+
function z(t, r) {
|
|
191
206
|
const e = t.match(/<!DOCTYPE[^>]*>/i);
|
|
192
207
|
return (e ? `${e[0]}
|
|
193
208
|
` : "") + r.documentElement.outerHTML;
|
|
194
209
|
}
|
|
195
|
-
function
|
|
210
|
+
function rt(t) {
|
|
196
211
|
const r = t.replaceAll("{%", "<!--{%").replaceAll("%}", "%}-->"), e = new DOMParser().parseFromString(r, "text/html"), o = e.querySelectorAll(".recommendation-block-v2");
|
|
197
212
|
if (!o.length)
|
|
198
213
|
return t;
|
|
199
|
-
const { buildCampaignUrl: c } =
|
|
214
|
+
const { buildCampaignUrl: c } = q(), i = R();
|
|
200
215
|
i.recommendationCampaignUrls = {};
|
|
201
|
-
const { isFeatureEnabled: n } =
|
|
216
|
+
const { isFeatureEnabled: n } = O(), s = n("liquidSyntax") ? "reco_" : "";
|
|
202
217
|
return o.forEach((u) => {
|
|
203
|
-
var d,
|
|
218
|
+
var d, f, h, p;
|
|
204
219
|
const l = u.getAttribute("recommendation-id");
|
|
205
220
|
if (l) {
|
|
206
|
-
if ((d = u.parentNode) == null || d.insertBefore(e.createComment("REC_START"), u), (
|
|
207
|
-
|
|
208
|
-
const { open: m, close:
|
|
209
|
-
(
|
|
221
|
+
if ((d = u.parentNode) == null || d.insertBefore(e.createComment("REC_START"), u), (f = u.parentNode) == null || f.insertBefore(e.createComment("REC_END"), u.nextSibling), u.querySelectorAll('[data-visibility="0"]').forEach((m) => m.remove()), c(l), k(u, e), !N(u)) {
|
|
222
|
+
I(u, l, s);
|
|
223
|
+
const { open: m, close: y } = F(e, l, s);
|
|
224
|
+
(h = u.parentNode) == null || h.insertBefore(m, u), (p = u.parentNode) == null || p.insertBefore(y, u.nextSibling);
|
|
210
225
|
}
|
|
211
|
-
|
|
226
|
+
X(u);
|
|
212
227
|
}
|
|
213
|
-
}),
|
|
228
|
+
}), x(e, Array.from(o)), z(r, e).replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}").replaceAll("<!--{%", "{%").replaceAll("%}-->", "%}");
|
|
214
229
|
}
|
|
215
230
|
export {
|
|
216
|
-
|
|
217
|
-
|
|
231
|
+
D as formatPriceVariable,
|
|
232
|
+
rt as prepareRecommendationBlocks
|
|
218
233
|
};
|
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
1
|
+
var A = Object.defineProperty;
|
|
2
|
+
var B = (a, c, t) => c in a ? A(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
4
|
import { useConfig as d } from "../../../composables/useConfig.js";
|
|
5
5
|
import { BlockId as D } from "../../../enums/block.js";
|
|
6
|
+
import { getFluidImageStyleChanges as E } from "../../../utils/fluidImageStyle.js";
|
|
6
7
|
import { getMigrationBannerHtml as C } from "../../../utils/migrationBannerHtml.js";
|
|
7
|
-
import { Block as
|
|
8
|
-
import { CURRENT_CONFIG_VERSION as
|
|
8
|
+
import { Block as S, BlockCompositionType as N, ModificationDescription as h } from "../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
9
|
+
import { CURRENT_CONFIG_VERSION as M, PRE_RRS_CONFIG_VERSION as O } from "./constants/defaultConfig.js";
|
|
9
10
|
import { RECOMMENDATION_ID_ATTR as m } from "./constants/selectors.js";
|
|
10
|
-
import { regenerateMobileProductRows as
|
|
11
|
-
import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as
|
|
12
|
-
import { RecommendationConfigService as
|
|
13
|
-
import { useRecommendationExtensionStore as
|
|
11
|
+
import { regenerateMobileProductRows as w } from "./controls/main/utils.js";
|
|
12
|
+
import { ensureMobileCssRulesExist as I, setMobileLayoutOptOut as k, hasMobileLayoutOptOut as H } from "./controls/mobileLayout/cssRules.js";
|
|
13
|
+
import { RecommendationConfigService as l } from "./services/configService.js";
|
|
14
|
+
import { useRecommendationExtensionStore as f } from "./store/recommendation.js";
|
|
14
15
|
import { getDefaultTemplate as T } from "./templates/grid/template.js";
|
|
15
16
|
import { useRecommendationBlockWarning as v } from "./useRecommendationBlockWarning.js";
|
|
16
|
-
const
|
|
17
|
+
const R = D.Recommendation, u = "recommendation-block-v2", y = "hide-price";
|
|
17
18
|
let b = !1;
|
|
18
|
-
class
|
|
19
|
+
class Q extends S {
|
|
19
20
|
constructor() {
|
|
20
21
|
super();
|
|
21
22
|
/**
|
|
22
23
|
* Stores the ID generated in getTemplate() so onCreated() can reuse it.
|
|
23
24
|
* This avoids generating a new (different) ID in onCreated().
|
|
24
25
|
*/
|
|
25
|
-
|
|
26
|
+
p(this, "_pendingBlockId", null);
|
|
26
27
|
/** Ids already reset under their new name, so the deferred pass skips their stale snapshot. */
|
|
27
|
-
|
|
28
|
+
p(this, "_resetSourceIds", /* @__PURE__ */ new Set());
|
|
28
29
|
}
|
|
29
30
|
getId() {
|
|
30
|
-
return
|
|
31
|
+
return R;
|
|
31
32
|
}
|
|
32
33
|
getIcon() {
|
|
33
34
|
return "recommendation-icon";
|
|
34
35
|
}
|
|
35
36
|
getBlockCompositionType() {
|
|
36
|
-
return
|
|
37
|
+
return N.CONTAINER;
|
|
37
38
|
}
|
|
38
39
|
getName() {
|
|
39
40
|
return this.api.translate("Recommendation Block");
|
|
@@ -45,7 +46,7 @@ class j extends E {
|
|
|
45
46
|
}
|
|
46
47
|
getSettingsPanelTitleHtml() {
|
|
47
48
|
return C(
|
|
48
|
-
|
|
49
|
+
R,
|
|
49
50
|
this.api.translate("Recommendation Block"),
|
|
50
51
|
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.")
|
|
51
52
|
);
|
|
@@ -91,28 +92,28 @@ class j extends E {
|
|
|
91
92
|
}
|
|
92
93
|
const i = this._pendingBlockId ?? this._generateNextId();
|
|
93
94
|
this._pendingBlockId = null, this._assignRecommendationId(t, i);
|
|
94
|
-
const n = d().isFeatureEnabled("reusableRecommendationStrategy"), o = n && !
|
|
95
|
+
const n = d().isFeatureEnabled("reusableRecommendationStrategy"), o = n && !l.hasConfig(t), { config: r, wasFreshDrop: s } = l.initializeConfig(
|
|
95
96
|
this.api,
|
|
96
97
|
t,
|
|
97
98
|
{
|
|
98
99
|
recommendationId: i,
|
|
99
|
-
configVersion: n ?
|
|
100
|
+
configVersion: n ? M : O,
|
|
100
101
|
...o ? { partnerName: d().partnerName.value } : {},
|
|
101
102
|
// An RRS block picks a strategy, not an algorithm, and its algorithm control is
|
|
102
103
|
// hidden. Keeping the `mostPopular` default would bake a most-popular feed URL
|
|
103
104
|
// at save for a block the user never configured.
|
|
104
105
|
...o ? { strategy: "" } : {}
|
|
105
106
|
}
|
|
106
|
-
),
|
|
107
|
-
if (
|
|
107
|
+
), g = f();
|
|
108
|
+
if (g.setCurrentBlock(i), this._stampHidePrice(t, r.priceHideIfSameAsDiscounted), s) {
|
|
108
109
|
I(this.api);
|
|
109
110
|
const _ = this._getBlockElement(t);
|
|
110
|
-
_ && (
|
|
111
|
+
_ && (k(this.api, _, !0), w({
|
|
111
112
|
currentNode: t,
|
|
112
113
|
documentModifier: this.api.getDocumentModifier()
|
|
113
114
|
}));
|
|
114
115
|
}
|
|
115
|
-
|
|
116
|
+
g.patchCurrentBlockConfig({ language: r.language }, { triggerRefetch: !1 }), this._warnIfMultipleBlocks();
|
|
116
117
|
}
|
|
117
118
|
/**
|
|
118
119
|
* Called when the document changes or template is loaded
|
|
@@ -125,20 +126,24 @@ class j extends E {
|
|
|
125
126
|
if (!(!t || !("getNodeConfig" in t))) {
|
|
126
127
|
if (!this._getRecommendationId(t)) {
|
|
127
128
|
const e = this._generateNextId();
|
|
128
|
-
this._assignRecommendationId(t, e),
|
|
129
|
+
this._assignRecommendationId(t, e), l.hasConfig(t) && l.updateConfig(
|
|
129
130
|
this.api,
|
|
130
131
|
t,
|
|
131
132
|
{ recommendationId: e },
|
|
132
133
|
"Assign recommendation ID to legacy block"
|
|
133
134
|
);
|
|
134
135
|
}
|
|
135
|
-
this._healLingeringDuplicate(t),
|
|
136
|
+
this._healLingeringDuplicate(t), l.needsMigration(t) && this._migrateFromLegacy(t), this._healHidePriceAttr(t);
|
|
137
|
+
try {
|
|
138
|
+
this._healFluidImages(t);
|
|
139
|
+
} catch {
|
|
140
|
+
}
|
|
136
141
|
try {
|
|
137
142
|
b || (I(this.api), b = !0);
|
|
138
|
-
const e =
|
|
143
|
+
const e = l.getConfig(t), i = this._getBlockElement(t);
|
|
139
144
|
if (i) {
|
|
140
145
|
const n = !e.mobileLayoutEnabled;
|
|
141
|
-
|
|
146
|
+
H(i) !== n && k(this.api, i, n);
|
|
142
147
|
}
|
|
143
148
|
} catch {
|
|
144
149
|
}
|
|
@@ -152,7 +157,7 @@ class j extends E {
|
|
|
152
157
|
*/
|
|
153
158
|
onDelete(t) {
|
|
154
159
|
const e = this._getRecommendationId(t);
|
|
155
|
-
e &&
|
|
160
|
+
e && f().removeBlockState(e);
|
|
156
161
|
}
|
|
157
162
|
/**
|
|
158
163
|
* Warns (dark advisory toaster) when the design holds more than one live
|
|
@@ -200,7 +205,7 @@ class j extends E {
|
|
|
200
205
|
_scheduleArrivalReset(t) {
|
|
201
206
|
d().isFeatureEnabled("reusableRecommendationStrategy") && setTimeout(() => {
|
|
202
207
|
const e = this._getRecommendationId(t);
|
|
203
|
-
e !== null && e > 0 && !this._resetSourceIds.delete(e) &&
|
|
208
|
+
e !== null && e > 0 && !this._resetSourceIds.delete(e) && f().resetArrivedBlock(e);
|
|
204
209
|
}, 0);
|
|
205
210
|
}
|
|
206
211
|
/**
|
|
@@ -231,9 +236,9 @@ class j extends E {
|
|
|
231
236
|
if (!o)
|
|
232
237
|
return;
|
|
233
238
|
let r = -1;
|
|
234
|
-
for (let
|
|
235
|
-
if (n[
|
|
236
|
-
r =
|
|
239
|
+
for (let s = 0; s < n.length; s++)
|
|
240
|
+
if (n[s] === o) {
|
|
241
|
+
r = s;
|
|
237
242
|
break;
|
|
238
243
|
}
|
|
239
244
|
if (r <= 0)
|
|
@@ -256,7 +261,7 @@ class j extends E {
|
|
|
256
261
|
}
|
|
257
262
|
/** Assigns a fresh id to a duplicated block and syncs DOM, node config and store. */
|
|
258
263
|
_handleDuplicate(t, e) {
|
|
259
|
-
const i = this._reassignDuplicateId(t, e), n =
|
|
264
|
+
const i = this._reassignDuplicateId(t, e), n = f();
|
|
260
265
|
n.cloneBlockState(e, i), n.setCurrentBlock(i), d().isFeatureEnabled("reusableRecommendationStrategy") && (this._resetSourceIds.add(e), n.resetArrivedBlock(i)), this._warnIfMultipleBlocks();
|
|
261
266
|
}
|
|
262
267
|
/**
|
|
@@ -272,7 +277,7 @@ class j extends E {
|
|
|
272
277
|
*/
|
|
273
278
|
_reassignDuplicateId(t, e) {
|
|
274
279
|
const i = this._generateNextId(), n = this._getBlockElement(t);
|
|
275
|
-
return this._assignRecommendationId(t, i), n && this._reassignInstanceClass(n, e, i),
|
|
280
|
+
return this._assignRecommendationId(t, i), n && this._reassignInstanceClass(n, e, i), l.hasConfig(t) && l.updateConfig(
|
|
276
281
|
this.api,
|
|
277
282
|
t,
|
|
278
283
|
{ recommendationId: i },
|
|
@@ -290,7 +295,7 @@ class j extends E {
|
|
|
290
295
|
if (!("getAttribute" in t))
|
|
291
296
|
return;
|
|
292
297
|
const n = `ins-recommendation-v3-block-${e}`, o = `ins-recommendation-v3-block-${i}`, r = this.api.getDocumentModifier();
|
|
293
|
-
r.modifyHtml(t).removeClass(n).setClass(o), r.apply(new
|
|
298
|
+
r.modifyHtml(t).removeClass(n).setClass(o), r.apply(new h(
|
|
294
299
|
`Reassign recommendation instance class ${n} -> ${o}`
|
|
295
300
|
));
|
|
296
301
|
}
|
|
@@ -305,7 +310,7 @@ class j extends E {
|
|
|
305
310
|
if (!i)
|
|
306
311
|
return;
|
|
307
312
|
const n = this.api.getDocumentModifier();
|
|
308
|
-
n.modifyHtml(i).setAttribute(m, e.toString()), n.apply(new
|
|
313
|
+
n.modifyHtml(i).setAttribute(m, e.toString()), n.apply(new h(`Assign recommendation ID ${e}`));
|
|
309
314
|
}
|
|
310
315
|
/**
|
|
311
316
|
* Stamps the `hide-price` attribute (read by email-service at send time) on
|
|
@@ -313,7 +318,7 @@ class j extends E {
|
|
|
313
318
|
*/
|
|
314
319
|
_stampHidePrice(t, e) {
|
|
315
320
|
const i = this._getBlockElement(t);
|
|
316
|
-
i && this.api.getDocumentModifier().modifyHtml(i).setAttribute(
|
|
321
|
+
i && this.api.getDocumentModifier().modifyHtml(i).setAttribute(y, String(e)).apply(new h("Stamp hide-price"));
|
|
317
322
|
}
|
|
318
323
|
/**
|
|
319
324
|
* Stamps `hide-price` from config only when the block lacks the attribute —
|
|
@@ -321,11 +326,28 @@ class j extends E {
|
|
|
321
326
|
*/
|
|
322
327
|
_healHidePriceAttr(t) {
|
|
323
328
|
const e = this._getBlockElement(t);
|
|
324
|
-
if (!e || !("getAttribute" in e) || e.getAttribute(
|
|
329
|
+
if (!e || !("getAttribute" in e) || e.getAttribute(y) !== null)
|
|
325
330
|
return;
|
|
326
|
-
const { priceHideIfSameAsDiscounted: i } =
|
|
331
|
+
const { priceHideIfSameAsDiscounted: i } = l.getConfig(t);
|
|
327
332
|
this._stampHidePrice(t, i);
|
|
328
333
|
}
|
|
334
|
+
// Writes into the stored template too, which email-service compiles again.
|
|
335
|
+
// Applies only on a real change: an empty apply re-fires onDocumentChanged.
|
|
336
|
+
_healFluidImages(t) {
|
|
337
|
+
const e = this._getBlockElement(t);
|
|
338
|
+
if (!e || !("querySelectorAll" in e))
|
|
339
|
+
return;
|
|
340
|
+
const i = this.api.getDocumentModifier();
|
|
341
|
+
let n = !1;
|
|
342
|
+
e.querySelectorAll("img.adapt-img").forEach((o) => {
|
|
343
|
+
if (!("getStyle" in o) || !("getAttribute" in o))
|
|
344
|
+
return;
|
|
345
|
+
const r = E((s) => o.getStyle(s), o.getAttribute("width"));
|
|
346
|
+
Object.entries(r).forEach(([s, g]) => {
|
|
347
|
+
i.modifyHtml(o).setStyle(s, g), n = !0;
|
|
348
|
+
});
|
|
349
|
+
}), n && i.apply(new h("Make product images fluid"));
|
|
350
|
+
}
|
|
329
351
|
/**
|
|
330
352
|
* Gets the recommendation-id from a block node
|
|
331
353
|
*/
|
|
@@ -354,10 +376,10 @@ class j extends E {
|
|
|
354
376
|
* Migrate configuration from legacy format
|
|
355
377
|
*/
|
|
356
378
|
_migrateFromLegacy(t) {
|
|
357
|
-
|
|
379
|
+
l.migrateFromDataAttributes(this.api, t);
|
|
358
380
|
}
|
|
359
381
|
}
|
|
360
382
|
export {
|
|
361
|
-
|
|
362
|
-
|
|
383
|
+
R as BLOCK_ID,
|
|
384
|
+
Q as RecommendationBlock
|
|
363
385
|
};
|
|
@@ -1,26 +1,30 @@
|
|
|
1
|
+
import { FLUID_IMAGE_MOBILE_RULE as u, FLUID_IMAGE_CLASS as m, FLUID_IMAGE_SELECTOR as p } from "../../../../../utils/fluidImageStyle.js";
|
|
1
2
|
import { ModificationDescription as a } from "../../../../../node_modules/@stripoinc/ui-editor-extensions/dist/esm/index.js";
|
|
2
|
-
const r = "ins-recommendation-desktop-container", l = "ins-recommendation-mobile-container", i = "ins-recommendation-list-layout", s = "ins-recommendation-no-mobile-layout",
|
|
3
|
-
function
|
|
3
|
+
const r = "ins-recommendation-desktop-container", l = "ins-recommendation-mobile-container", i = "ins-recommendation-list-layout", s = "ins-recommendation-no-mobile-layout", d = `.${l} { display: none; }`, c = `@media only screen and (max-width: 480px) { .${r} { display: none !important; } .${l} { display: table !important; } .${i} .${r} { display: table !important; } .${i} .${l}, .${i} .ins-recommendation-mobile-row { display: none !important; } .${i} .product-image-cell { width: 80px !important; } .${i} .product-image-cell img { max-width: 80px !important; } .${i} .button-cell { width: 80px !important; } .${i} .product-info-cell { padding: 5px 8px !important; } }`, f = `@media only screen and (max-width: 480px) { .${s} .${r} { display: table !important; } .${s} .${l}, .${s} .ins-recommendation-mobile-row { display: none !important; } }`, _ = `.${l}`;
|
|
4
|
+
function S(t, e) {
|
|
4
5
|
return !!t.querySelector(e);
|
|
5
6
|
}
|
|
6
|
-
function
|
|
7
|
+
function y(t) {
|
|
7
8
|
return t.querySelectorAll(`*${r}`).length > 0;
|
|
8
9
|
}
|
|
9
|
-
function
|
|
10
|
+
function C(t) {
|
|
10
11
|
return t.querySelectorAll(`*${s}`).length > 0;
|
|
11
12
|
}
|
|
12
|
-
function
|
|
13
|
+
function E(t) {
|
|
14
|
+
return t.querySelectorAll(`*${m}`).some((e) => "getSelector" in e && typeof e.getSelector == "function" && e.getSelector() === p);
|
|
15
|
+
}
|
|
16
|
+
function I(t) {
|
|
13
17
|
const e = t.getDocumentRootCssNode();
|
|
14
18
|
if (!e)
|
|
15
19
|
return;
|
|
16
20
|
const o = t.getDocumentModifier();
|
|
17
21
|
let n = !1;
|
|
18
|
-
|
|
22
|
+
S(e, _) || (o.modifyCss(e).appendRule(d), n = !0), y(e) || (o.modifyCss(e).appendRule(c), n = !0), C(e) || (o.modifyCss(e).appendRule(f), n = !0), E(e) || (o.modifyCss(e).appendRule(u), n = !0), n && o.apply(new a("Add mobile layout CSS rules"));
|
|
19
23
|
}
|
|
20
|
-
function
|
|
24
|
+
function R(t) {
|
|
21
25
|
return "hasClass" in t ? t.hasClass(s) : !1;
|
|
22
26
|
}
|
|
23
|
-
function
|
|
27
|
+
function $(t, e, o) {
|
|
24
28
|
const n = t.getDocumentModifier();
|
|
25
29
|
o ? n.modifyHtml(e).setClass(s) : n.modifyHtml(e).removeClass(s), n.apply(
|
|
26
30
|
new a(
|
|
@@ -32,7 +36,7 @@ export {
|
|
|
32
36
|
r as CSS_CLASS_DESKTOP_CONTAINER,
|
|
33
37
|
l as CSS_CLASS_MOBILE_CONTAINER,
|
|
34
38
|
s as CSS_CLASS_NO_MOBILE_LAYOUT,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
I as ensureMobileCssRulesExist,
|
|
40
|
+
R as hasMobileLayoutOptOut,
|
|
41
|
+
$ as setMobileLayoutOptOut
|
|
38
42
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
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";
|
|
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
|
|
3
|
+
import { compositionKeyToProductAttr as y, isDefaultProductAttr as f, bareAttributeName as S, findFilterByBareName as $, productAttrToCompositionKey as h } from "../utils/compositionKeys.js";
|
|
4
4
|
import { formatPrice as B } from "../utils/priceFormatter.js";
|
|
5
5
|
import { buildTitleRows as k } from "./titleRows.js";
|
|
6
6
|
function x() {
|
|
@@ -35,22 +35,22 @@ function J(t) {
|
|
|
35
35
|
skip: n ? l : a
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
|
-
function
|
|
38
|
+
function w(t) {
|
|
39
39
|
const e = Array.isArray(t) ? t[t.length - 1] : t;
|
|
40
40
|
if (typeof e == "string")
|
|
41
41
|
return e;
|
|
42
42
|
if (typeof e == "number")
|
|
43
43
|
return String(e);
|
|
44
44
|
}
|
|
45
|
-
function
|
|
45
|
+
function F(t, e) {
|
|
46
46
|
var o;
|
|
47
47
|
return ((o = $(t, e)) == null ? void 0 : o.type) === "defaultAttribute";
|
|
48
48
|
}
|
|
49
|
-
function
|
|
50
|
-
return
|
|
49
|
+
function v(t, e) {
|
|
50
|
+
return F(t, e) ? t : `${I}${t}`;
|
|
51
51
|
}
|
|
52
52
|
function Q(t) {
|
|
53
|
-
return
|
|
53
|
+
return h(t);
|
|
54
54
|
}
|
|
55
55
|
const M = Symbol("customCellHtml");
|
|
56
56
|
function Z(t, e, o = {}) {
|
|
@@ -59,16 +59,16 @@ function Z(t, e, o = {}) {
|
|
|
59
59
|
return { ...t };
|
|
60
60
|
const c = { ...t };
|
|
61
61
|
return e.filter((i) => i.startsWith(T) && !c[i]).forEach((i) => {
|
|
62
|
-
const s = y(i), r = f(s) ?
|
|
62
|
+
const s = y(i), r = f(s) ? v(s, o) : s, u = S(r), R = N(u), D = f(r);
|
|
63
63
|
c[i] = (d, U) => {
|
|
64
64
|
var g;
|
|
65
|
-
const O = D ? d[u] : (g = d.product_attributes) == null ? void 0 : g[u], E =
|
|
65
|
+
const O = D ? d[u] : (g = d.product_attributes) == null ? void 0 : g[u], E = w(O) ?? R;
|
|
66
66
|
return n(r, E, U);
|
|
67
67
|
};
|
|
68
68
|
}), c;
|
|
69
69
|
}
|
|
70
70
|
function tt(t, e, o = []) {
|
|
71
|
-
const n = t.startsWith(T) ?
|
|
71
|
+
const n = t.startsWith(T) ? h(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]);
|
|
72
72
|
return {
|
|
73
73
|
cellPadding: e.cellPadding,
|
|
74
74
|
cardBackgroundColor: e.cardBackgroundColor,
|
|
@@ -135,14 +135,14 @@ function at(t, e) {
|
|
|
135
135
|
function ut(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;",
|
|
138
|
+
const dt = "display: block; width: 100%; 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;", P = "https://email-static.useinsider.com/stripo/modules/email-recommendation-v3/assets/images/image-placeholder.png";
|
|
139
139
|
function mt(t) {
|
|
140
|
-
return !t || typeof t != "string" || t.trim() === "" ?
|
|
140
|
+
return !t || typeof t != "string" || t.trim() === "" ? P : t.startsWith("http://") ? t.replace("http://", "https://") : t;
|
|
141
141
|
}
|
|
142
142
|
function Y(t) {
|
|
143
143
|
return {
|
|
144
144
|
name: "Product Name",
|
|
145
|
-
image_url:
|
|
145
|
+
image_url: P,
|
|
146
146
|
price: { USD: 18 },
|
|
147
147
|
original_price: { USD: 20 },
|
|
148
148
|
discount: { USD: 2 },
|
|
@@ -224,7 +224,7 @@ export {
|
|
|
224
224
|
nt as DEFAULT_CARD_VISIBILITY,
|
|
225
225
|
dt as DEFAULT_IMG_STYLE,
|
|
226
226
|
W as DEFAULT_ROW_SPACING_PX,
|
|
227
|
-
|
|
227
|
+
P as PLACEHOLDER_IMAGE,
|
|
228
228
|
V as bgColorFragment,
|
|
229
229
|
tt as buildCellOptions,
|
|
230
230
|
Z as buildElementRenderer,
|
|
@@ -234,7 +234,7 @@ export {
|
|
|
234
234
|
m as formatProductPrice,
|
|
235
235
|
x as getCurrentCurrencyConfig,
|
|
236
236
|
Tt as getDefaultProducts,
|
|
237
|
-
|
|
237
|
+
F as isDefaultAttribute,
|
|
238
238
|
q as isSamePrice,
|
|
239
239
|
at as renderButtonLabel,
|
|
240
240
|
it as renderStyledParagraph,
|
|
@@ -242,10 +242,10 @@ export {
|
|
|
242
242
|
J as resolveInlinePriceOrder,
|
|
243
243
|
lt as resolveOmnibusText,
|
|
244
244
|
H as resolvePStyle,
|
|
245
|
-
|
|
245
|
+
v as resolveProductAttrValue,
|
|
246
246
|
st as resolveSegmentBgStyle,
|
|
247
247
|
mt as sanitizeImageUrl,
|
|
248
248
|
Q as toCustomCompositionKey,
|
|
249
249
|
N as toDisplayName,
|
|
250
|
-
|
|
250
|
+
w as toDisplayableAttributeValue
|
|
251
251
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getFluidImageStyleChanges as E } from "../../../../utils/fluidImageStyle.js";
|
|
2
|
+
import { extractWrapperTags as A } from "../../../../utils/preserveTextStyles.js";
|
|
2
3
|
import { RecommendationBlockId as c } from "../constants/blockIds.js";
|
|
3
|
-
import { DESKTOP_CONTAINER_SELECTOR as
|
|
4
|
-
import { CSS_CLASS_TEXT_TRIM as
|
|
5
|
-
import { toCustomCompositionKey as
|
|
6
|
-
import { resolveRowCompositionKey as
|
|
7
|
-
import { hasQuerySelectorAll as
|
|
8
|
-
const
|
|
4
|
+
import { DESKTOP_CONTAINER_SELECTOR as g, ATTR_PRODUCT_NAME as P, ATTR_PRODUCT_PRICE as b, ATTR_PRODUCT_OLD_PRICE as p, ATTR_PRODUCT_OMNIBUS_PRICE as R, ATTR_PRODUCT_OMNIBUS_DISCOUNT as _, ATTR_PRODUCT_BUTTON as q, ATTR_PRODUCT_IMAGE as x, ATTR_PRODUCT_ATTR as v } from "../constants/selectors.js";
|
|
5
|
+
import { CSS_CLASS_TEXT_TRIM as B } from "../controls/shared/textTrimCssRules.js";
|
|
6
|
+
import { toCustomCompositionKey as U } from "../templates/utils.js";
|
|
7
|
+
import { resolveRowCompositionKey as M } from "./compositionKeys.js";
|
|
8
|
+
import { hasQuerySelectorAll as I, hasGetAttribute as a, hasGetStyle as O, hasGetComputedStyle as N } from "./tagName.js";
|
|
9
|
+
const l = [
|
|
9
10
|
"font-size",
|
|
10
11
|
"font-family",
|
|
11
12
|
"font-weight",
|
|
@@ -14,15 +15,15 @@ const s = [
|
|
|
14
15
|
"text-align",
|
|
15
16
|
"line-height",
|
|
16
17
|
"text-decoration"
|
|
17
|
-
],
|
|
18
|
+
], D = [
|
|
18
19
|
"background",
|
|
19
20
|
"background-color",
|
|
20
21
|
"border-width",
|
|
21
22
|
"border-color",
|
|
22
23
|
"border-style",
|
|
23
24
|
"border-radius"
|
|
24
|
-
],
|
|
25
|
-
...
|
|
25
|
+
], w = [
|
|
26
|
+
...l,
|
|
26
27
|
"background",
|
|
27
28
|
"background-color",
|
|
28
29
|
// Stripo's Border Radius control writes the radius to the anchor too, not just the
|
|
@@ -39,48 +40,48 @@ const s = [
|
|
|
39
40
|
"max-width",
|
|
40
41
|
"border-radius",
|
|
41
42
|
"margin"
|
|
42
|
-
],
|
|
43
|
-
{ attrKey:
|
|
44
|
-
{ attrKey:
|
|
45
|
-
{ attrKey:
|
|
46
|
-
{ attrKey:
|
|
47
|
-
{ attrKey:
|
|
48
|
-
{ attrKey:
|
|
49
|
-
{ attrKey:
|
|
43
|
+
], S = /* @__PURE__ */ new Set(["transparent", "rgba(0, 0, 0, 0)"]), L = [
|
|
44
|
+
{ attrKey: P, blockId: c.NAME, kind: "text" },
|
|
45
|
+
{ attrKey: b, blockId: c.PRICE, kind: "text" },
|
|
46
|
+
{ attrKey: p, blockId: c.OLD_PRICE, kind: "text" },
|
|
47
|
+
{ attrKey: R, blockId: c.OMNIBUS_PRICE, kind: "text" },
|
|
48
|
+
{ attrKey: _, blockId: c.OMNIBUS_DISCOUNT, kind: "text" },
|
|
49
|
+
{ attrKey: q, blockId: c.BUTTON, kind: "button" },
|
|
50
|
+
{ attrKey: x, blockId: c.IMAGE, kind: "image" }
|
|
50
51
|
];
|
|
51
|
-
function
|
|
52
|
+
function h(t) {
|
|
52
53
|
return t && "getInnerHTML" in t && typeof t.getInnerHTML == "function" ? t.getInnerHTML().trim() : "";
|
|
53
54
|
}
|
|
54
|
-
function
|
|
55
|
+
function K(t) {
|
|
55
56
|
return t && "getInnerText" in t && typeof t.getInnerText == "function" ? t.getInnerText().trim() : "";
|
|
56
57
|
}
|
|
57
|
-
function
|
|
58
|
-
!e || !
|
|
58
|
+
function s(t, e, r) {
|
|
59
|
+
!e || !O(e) || r.forEach((n) => {
|
|
59
60
|
const o = e.getStyle(n);
|
|
60
61
|
o && o !== "inherit" && o !== "initial" && (t[n] = o);
|
|
61
62
|
});
|
|
62
63
|
}
|
|
63
|
-
function
|
|
64
|
+
function y(t) {
|
|
64
65
|
return Object.entries(t).map(([e, r]) => `${e}: ${r};`).join(" ");
|
|
65
66
|
}
|
|
66
67
|
function k(t) {
|
|
67
|
-
if (!t || !
|
|
68
|
+
if (!t || !O(t))
|
|
68
69
|
return;
|
|
69
70
|
const e = t.getStyle("background-color") || t.getStyle("background");
|
|
70
|
-
return e && !
|
|
71
|
+
return e && !S.has(e) ? e : void 0;
|
|
71
72
|
}
|
|
72
|
-
function
|
|
73
|
+
function C(t, e) {
|
|
73
74
|
const r = {};
|
|
74
|
-
return
|
|
75
|
+
return s(r, t, e), y(r);
|
|
75
76
|
}
|
|
76
|
-
function
|
|
77
|
+
function $(t) {
|
|
77
78
|
const e = t.querySelector("p"), r = {};
|
|
78
|
-
|
|
79
|
-
const n =
|
|
79
|
+
s(r, t, l), s(r, e, l), s(r, t.querySelector("strong"), l), s(r, t.querySelector("em"), l), s(r, t.querySelector("s"), l);
|
|
80
|
+
const n = y(r), { openTags: o, closeTags: i } = A(h(e));
|
|
80
81
|
return !n && !o ? null : { pStyle: n || void 0, openTags: o, closeTags: i };
|
|
81
82
|
}
|
|
82
|
-
function
|
|
83
|
-
const e = t.querySelector(".es-button-border"), r = t.querySelector("a.es-button") ?? t.querySelector("a"), n =
|
|
83
|
+
function j(t) {
|
|
84
|
+
const e = t.querySelector(".es-button-border"), r = t.querySelector("a.es-button") ?? t.querySelector("a"), n = C(e, D), o = C(r, w), i = e && "getAttribute" in e ? e.getAttribute("class") ?? "" : "", u = /\bes-fw\b/.test(i), { openTags: T, closeTags: d } = A(h(r)), m = K(r);
|
|
84
85
|
return !n && !o && !u && !T && !m ? null : {
|
|
85
86
|
buttonBorderStyle: n || void 0,
|
|
86
87
|
buttonAnchorStyle: o || void 0,
|
|
@@ -90,137 +91,140 @@ function $(t) {
|
|
|
90
91
|
closeTags: d
|
|
91
92
|
};
|
|
92
93
|
}
|
|
93
|
-
function
|
|
94
|
-
const e =
|
|
95
|
-
|
|
94
|
+
function F(t) {
|
|
95
|
+
const e = t.querySelector("img"), r = {};
|
|
96
|
+
if (s(r, e, G), !Object.keys(r).length)
|
|
97
|
+
return null;
|
|
98
|
+
const n = a(e) ? e.getAttribute("width") : null;
|
|
99
|
+
return Object.assign(r, E((o) => r[o], n)), { imgStyle: y(r) };
|
|
96
100
|
}
|
|
97
|
-
function
|
|
98
|
-
return e === "button" ?
|
|
101
|
+
function H(t, e) {
|
|
102
|
+
return e === "button" ? j(t) : e === "image" ? F(t) : $(t);
|
|
99
103
|
}
|
|
100
104
|
function f(t, e) {
|
|
101
105
|
if (!t || !("querySelector" in t))
|
|
102
106
|
return;
|
|
103
|
-
const r = t.querySelector(
|
|
107
|
+
const r = t.querySelector(g) ?? t;
|
|
104
108
|
if (L.forEach(({ attrKey: i, blockId: u, kind: T }) => {
|
|
105
109
|
const d = r.querySelector(`[esd-extension-block-id="${u}"]`);
|
|
106
110
|
d && e(d, i, T);
|
|
107
|
-
}), !
|
|
111
|
+
}), !I(r))
|
|
108
112
|
return;
|
|
109
113
|
const n = /* @__PURE__ */ new Set();
|
|
110
114
|
r.querySelectorAll(
|
|
111
115
|
`[esd-extension-block-id="${c.CUSTOM_ATTRIBUTE}"]`
|
|
112
116
|
).forEach((i) => {
|
|
113
|
-
const u =
|
|
114
|
-
!u || n.has(u) || (n.add(u), e(i,
|
|
117
|
+
const u = a(i) ? i.getAttribute(v) : null;
|
|
118
|
+
!u || n.has(u) || (n.add(u), e(i, U(u), "text"));
|
|
115
119
|
});
|
|
116
120
|
}
|
|
117
|
-
function
|
|
121
|
+
function X(t) {
|
|
118
122
|
const e = {};
|
|
119
123
|
return f(t, (r, n, o) => {
|
|
120
124
|
if (!("querySelector" in r))
|
|
121
125
|
return;
|
|
122
|
-
const i =
|
|
126
|
+
const i = H(r, o);
|
|
123
127
|
i && (e[n] = i);
|
|
124
128
|
}), e;
|
|
125
129
|
}
|
|
126
|
-
function
|
|
130
|
+
function z(t) {
|
|
127
131
|
if (!t || !("querySelector" in t))
|
|
128
132
|
return;
|
|
129
|
-
const e = t.querySelector(
|
|
133
|
+
const e = t.querySelector(g) ?? t, r = e.querySelector(".product-card-segment") ?? e.querySelector(".product-card-wrapper");
|
|
130
134
|
return k(r);
|
|
131
135
|
}
|
|
132
|
-
function
|
|
136
|
+
function Q(t) {
|
|
133
137
|
if (!t)
|
|
134
138
|
return;
|
|
135
|
-
const e =
|
|
136
|
-
if (e && !
|
|
139
|
+
const e = a(t) ? t.getAttribute("bgcolor") : null;
|
|
140
|
+
if (e && !S.has(e))
|
|
137
141
|
return e;
|
|
138
142
|
const r = k(t);
|
|
139
143
|
if (r)
|
|
140
144
|
return r;
|
|
141
145
|
const n = N(t) ? t.getComputedStyle("background-color") : void 0;
|
|
142
|
-
return n && !
|
|
146
|
+
return n && !S.has(n) ? n : void 0;
|
|
143
147
|
}
|
|
144
|
-
function
|
|
148
|
+
function V(t) {
|
|
145
149
|
const e = {};
|
|
146
150
|
return f(t, (r, n, o) => {
|
|
147
151
|
if (o !== "text")
|
|
148
152
|
return;
|
|
149
|
-
const i =
|
|
153
|
+
const i = Q(r);
|
|
150
154
|
i && (e[n] = i);
|
|
151
155
|
}), e;
|
|
152
156
|
}
|
|
153
|
-
function
|
|
157
|
+
function W(t) {
|
|
154
158
|
const e = {};
|
|
155
159
|
return f(t, (r, n, o) => {
|
|
156
160
|
if (o === "image")
|
|
157
161
|
return;
|
|
158
|
-
const i =
|
|
162
|
+
const i = a(r) ? r.getAttribute("align") : null;
|
|
159
163
|
i && (e[n] = i);
|
|
160
164
|
}), e;
|
|
161
165
|
}
|
|
162
|
-
const
|
|
163
|
-
function
|
|
164
|
-
const e =
|
|
166
|
+
const Y = /^es-[pm]\d+[trbl]?$/;
|
|
167
|
+
function J(t) {
|
|
168
|
+
const e = a(t) ? t.getAttribute("class") : null;
|
|
165
169
|
if (!e)
|
|
166
170
|
return;
|
|
167
|
-
const r = e.split(/\s+/).filter((n) =>
|
|
171
|
+
const r = e.split(/\s+/).filter((n) => Y.test(n) || n === B);
|
|
168
172
|
return r.length ? r.join(" ") : void 0;
|
|
169
173
|
}
|
|
170
|
-
function
|
|
174
|
+
function Z(t) {
|
|
171
175
|
if (!t || !("querySelector" in t))
|
|
172
176
|
return !1;
|
|
173
|
-
const e = t.querySelector(
|
|
174
|
-
return r(e.querySelector(`[data-attribute-type="${
|
|
177
|
+
const e = t.querySelector(g) ?? t, r = (n) => !!(n && "querySelector" in n && n.querySelector(".product-price") && n.querySelector(".product-old-price"));
|
|
178
|
+
return r(e.querySelector(`[data-attribute-type="${b}"]`)) || r(e.querySelector(`[data-attribute-type="${p}"]`));
|
|
175
179
|
}
|
|
176
|
-
function
|
|
177
|
-
const e = {}, r =
|
|
180
|
+
function tt(t) {
|
|
181
|
+
const e = {}, r = Z(t);
|
|
178
182
|
return f(t, (n, o, i) => {
|
|
179
|
-
if (i === "image" || r && (o ===
|
|
183
|
+
if (i === "image" || r && (o === b || o === p))
|
|
180
184
|
return;
|
|
181
|
-
const u =
|
|
185
|
+
const u = J(n);
|
|
182
186
|
u && (e[o] = u);
|
|
183
187
|
}), e;
|
|
184
188
|
}
|
|
185
|
-
function
|
|
189
|
+
function et(t) {
|
|
186
190
|
const e = {};
|
|
187
191
|
return f(t, (r, n) => {
|
|
188
|
-
if (n !==
|
|
192
|
+
if (n !== R && n !== _ || !a(r))
|
|
189
193
|
return;
|
|
190
194
|
const o = r.getAttribute("data-text-before"), i = r.getAttribute("data-text-after");
|
|
191
195
|
(o != null || i != null) && (e[n] = { before: o ?? void 0, after: i ?? void 0 });
|
|
192
196
|
}), e;
|
|
193
197
|
}
|
|
194
|
-
function
|
|
198
|
+
function rt(t) {
|
|
195
199
|
const e = {};
|
|
196
200
|
if (!t || !("querySelector" in t))
|
|
197
201
|
return e;
|
|
198
|
-
const r = t.querySelector(
|
|
199
|
-
return
|
|
200
|
-
if (!
|
|
202
|
+
const r = t.querySelector(g) ?? t;
|
|
203
|
+
return I(r) && r.querySelectorAll(".recommendation-attribute-row").forEach((n) => {
|
|
204
|
+
if (!a(n))
|
|
201
205
|
return;
|
|
202
|
-
const o =
|
|
206
|
+
const o = M(n), i = n.getAttribute("data-visibility");
|
|
203
207
|
o && i != null && (e[o] = i !== "0");
|
|
204
208
|
}), e;
|
|
205
209
|
}
|
|
206
|
-
function
|
|
210
|
+
function ft(t) {
|
|
207
211
|
return {
|
|
208
|
-
styleTemplates:
|
|
209
|
-
cardBackgroundColor:
|
|
210
|
-
cellBackgroundColors:
|
|
211
|
-
cellAlignments:
|
|
212
|
-
cellClasses:
|
|
213
|
-
omnibusTexts:
|
|
214
|
-
visibility:
|
|
212
|
+
styleTemplates: X(t),
|
|
213
|
+
cardBackgroundColor: z(t),
|
|
214
|
+
cellBackgroundColors: V(t),
|
|
215
|
+
cellAlignments: W(t),
|
|
216
|
+
cellClasses: tt(t),
|
|
217
|
+
omnibusTexts: et(t),
|
|
218
|
+
visibility: rt(t)
|
|
215
219
|
};
|
|
216
220
|
}
|
|
217
221
|
export {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
222
|
+
X as captureAttributeStyleTemplates,
|
|
223
|
+
z as captureCardBackgroundColor,
|
|
224
|
+
W as captureCellAlignments,
|
|
225
|
+
V as captureCellBackgroundColors,
|
|
226
|
+
tt as captureCellClasses,
|
|
227
|
+
et as captureOmnibusTexts,
|
|
228
|
+
ft as captureStyles,
|
|
229
|
+
rt as captureVisibility
|
|
226
230
|
};
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
import "../constants/selectors.js";
|
|
2
2
|
import { RRS_CONFIG_VERSION as m } from "../constants/defaultConfig.js";
|
|
3
|
-
import { sanitizeProductIds as p
|
|
4
|
-
const
|
|
5
|
-
function
|
|
3
|
+
import { sanitizeProductIds as p } from "./productIds.js";
|
|
4
|
+
const d = "manualMerchandising";
|
|
5
|
+
function N({ strategyId: e, nodeConfigVersion: t }) {
|
|
6
6
|
return !e && t < m;
|
|
7
7
|
}
|
|
8
8
|
const o = (e) => {
|
|
9
9
|
const t = String(e ?? "").trim();
|
|
10
10
|
return /^[1-9]\d*$/.test(t) ? t : null;
|
|
11
11
|
};
|
|
12
|
-
function
|
|
12
|
+
function f({ campaignId: e, templateLibraryId: t }) {
|
|
13
13
|
if (o(e))
|
|
14
14
|
return { scope: "campaign" };
|
|
15
15
|
const n = o(t);
|
|
16
16
|
return n ? { scope: "template", templateId: n } : { scope: "campaign" };
|
|
17
17
|
}
|
|
18
|
-
function
|
|
18
|
+
function y({
|
|
19
19
|
blockId: e,
|
|
20
20
|
url: t,
|
|
21
21
|
campaignId: n,
|
|
@@ -24,7 +24,7 @@ function S({
|
|
|
24
24
|
productIds: s,
|
|
25
25
|
target: r
|
|
26
26
|
}) {
|
|
27
|
-
const i = c ===
|
|
27
|
+
const i = c === d ? p(s).split(",").filter(Boolean) : [];
|
|
28
28
|
return {
|
|
29
29
|
...r.scope === "template" ? { templateId: Number.parseInt(r.templateId) } : {
|
|
30
30
|
campaignId: Number.parseInt(n) || 0,
|
|
@@ -36,7 +36,7 @@ function S({
|
|
|
36
36
|
};
|
|
37
37
|
}
|
|
38
38
|
export {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
y as buildLegacyMigrationPayload,
|
|
40
|
+
N as isLegacyStrategyConfig,
|
|
41
|
+
f as resolveMigrationTarget
|
|
42
42
|
};
|
|
@@ -1,8 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return t.map((n) => String(n ?? "").trim()).filter(Boolean).join(",");
|
|
1
|
+
function n(t) {
|
|
2
|
+
return t.map((i) => String(i ?? "").trim()).filter(Boolean).join(",");
|
|
4
3
|
}
|
|
5
4
|
export {
|
|
6
|
-
|
|
7
|
-
o as sanitizeProductIds
|
|
5
|
+
n as sanitizeProductIds
|
|
8
6
|
};
|
|
@@ -137,6 +137,7 @@ export declare class RecommendationBlock extends Block {
|
|
|
137
137
|
* heals templates saved before this feature without dirtying current ones.
|
|
138
138
|
*/
|
|
139
139
|
private _healHidePriceAttr;
|
|
140
|
+
private _healFluidImages;
|
|
140
141
|
/**
|
|
141
142
|
* Gets the recommendation-id from a block node
|
|
142
143
|
*/
|
|
@@ -292,8 +292,11 @@ export declare function renderButtonLabel(label: string, template?: AttributeSty
|
|
|
292
292
|
* class, not inline width, so we preserve the class across regeneration.
|
|
293
293
|
*/
|
|
294
294
|
export declare function resolveButtonBorderClass(template?: AttributeStyleTemplate): string;
|
|
295
|
-
/**
|
|
296
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Default inline style for the product image `<img>` (used when nothing is captured).
|
|
297
|
+
* `width: 100%` is inline so the image shrinks even where the `.adapt-img` media rule is dropped.
|
|
298
|
+
*/
|
|
299
|
+
export declare const DEFAULT_IMG_STYLE = "display: block; width: 100%; max-width: 100%; height: auto;";
|
|
297
300
|
/** Default inline style for the button `<span class="es-button-border">`. */
|
|
298
301
|
export declare const DEFAULT_BUTTON_BORDER_STYLE: string;
|
|
299
302
|
/**
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
/** Separator between product ids in the `sanitizeProductIds` output */
|
|
2
|
-
export declare const PRODUCT_ID_SEPARATOR = ",";
|
|
3
1
|
/**
|
|
4
2
|
* Builds the request/URL `productId` value from raw product ID segments.
|
|
5
3
|
* Trimming happens here — NOT on input change — so the user's in-progress
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Reads one inline style property (Stripo `getStyle` or CSSOM `getPropertyValue`). */
|
|
2
|
+
export type StyleReader = (property: string) => string | null | undefined;
|
|
3
|
+
export type FluidImageStyleChanges = Partial<Record<'width' | 'max-width' | 'height', string>>;
|
|
4
|
+
export declare function getFluidImageStyleChanges(readStyle: StyleReader, widthAttr?: string | null): FluidImageStyleChanges;
|
|
5
|
+
export declare const FLUID_IMAGE_CLASS = "recommendation-block-v2";
|
|
6
|
+
export declare const FLUID_IMAGE_SELECTOR = ".recommendation-block-v2 .adapt-img";
|
|
7
|
+
export declare const FLUID_IMAGE_MOBILE_RULE: string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const c = /^(\d+(?:\.\d+)?)px$/i;
|
|
2
|
+
function o(t) {
|
|
3
|
+
return (t ?? "").trim().toLowerCase();
|
|
4
|
+
}
|
|
5
|
+
function e(t) {
|
|
6
|
+
const n = o(t).match(c);
|
|
7
|
+
return n && parseFloat(n[1]) > 0 ? `${n[1]}px` : null;
|
|
8
|
+
}
|
|
9
|
+
function h(t) {
|
|
10
|
+
const n = (t ?? "").trim();
|
|
11
|
+
return /^\d+$/.test(n) && parseInt(n) > 0 ? `${parseInt(n)}px` : null;
|
|
12
|
+
}
|
|
13
|
+
function r(t, n) {
|
|
14
|
+
return e(t("width")) ?? e(t("max-width")) ?? h(n) ?? "100%";
|
|
15
|
+
}
|
|
16
|
+
function d(t, n) {
|
|
17
|
+
const i = {}, a = r(t, n);
|
|
18
|
+
return o(t("width")) !== "100%" && (i.width = "100%"), o(t("max-width")) !== a && (i["max-width"] = a), o(t("height")) || (i.height = "auto"), i;
|
|
19
|
+
}
|
|
20
|
+
const s = "recommendation-block-v2", m = `.${s} .adapt-img`, u = `@media only screen and (max-width: 600px) { ${m} { max-width: 100% !important; } }`;
|
|
21
|
+
export {
|
|
22
|
+
s as FLUID_IMAGE_CLASS,
|
|
23
|
+
u as FLUID_IMAGE_MOBILE_RULE,
|
|
24
|
+
m as FLUID_IMAGE_SELECTOR,
|
|
25
|
+
d as getFluidImageStyleChanges
|
|
26
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@useinsider/guido",
|
|
3
|
-
"version": "3.20.0-beta.
|
|
3
|
+
"version": "3.20.0-beta.12889e0",
|
|
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",
|