@useinsider/guido 3.1.1 → 3.2.0-beta.4aabac5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/@types/config/schemas.js +66 -54
  2. package/dist/components/Guido.vue.js +4 -4
  3. package/dist/components/Guido.vue2.js +91 -81
  4. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue.js +7 -7
  5. package/dist/components/organisms/email-preview/desktop-preview/EmailSizeIndicator.vue2.js +12 -20
  6. package/dist/composables/useHtmlCompiler.js +20 -20
  7. package/dist/composables/useHtmlValidator.js +40 -38
  8. package/dist/composables/usePreviewMode.js +20 -16
  9. package/dist/composables/useSave.js +15 -13
  10. package/dist/config/compiler/recommendationCompilerRules.js +158 -44
  11. package/dist/config/compiler/unsubscribeCompilerRules.js +37 -37
  12. package/dist/config/compiler/utils/recommendationCompilerUtils.js +49 -46
  13. package/dist/config/i18n/en/tooltips.json.js +2 -1
  14. package/dist/config/migrator/checkboxMigrator.js +5 -3
  15. package/dist/config/migrator/radioButtonMigrator.js +14 -12
  16. package/dist/enums/extensions/recommendationBlock.js +14 -11
  17. package/dist/enums/recommendation.js +2 -2
  18. package/dist/extensions/Blocks/Recommendation/block.js +1 -1
  19. package/dist/extensions/Blocks/Recommendation/constants/selectors.js +27 -11
  20. package/dist/extensions/Blocks/Recommendation/controls/cardComposition/index.js +185 -172
  21. package/dist/extensions/Blocks/Recommendation/controls/main/utils.js +95 -93
  22. package/dist/extensions/Blocks/Recommendation/controls/spacing/index.js +75 -73
  23. package/dist/extensions/Blocks/Recommendation/templates/grid/elementRenderer.js +7 -5
  24. package/dist/extensions/Blocks/Recommendation/templates/grid/template.js +30 -29
  25. package/dist/extensions/Blocks/Recommendation/templates/index.js +7 -7
  26. package/dist/extensions/Blocks/Recommendation/templates/list/elementRenderer.js +3 -1
  27. package/dist/extensions/Blocks/Recommendation/templates/list/template.js +20 -20
  28. package/dist/extensions/Blocks/Recommendation/templates/utils.js +57 -50
  29. package/dist/extensions/Blocks/Recommendation/utils/tagName.js +6 -6
  30. package/dist/extensions/Blocks/Unsubscribe/settingsPanel.js +16 -17
  31. package/dist/guido.css +1 -1
  32. package/dist/services/recommendationApi.js +15 -15
  33. package/dist/src/@types/config/index.d.ts +1 -1
  34. package/dist/src/@types/config/schemas.d.ts +28 -0
  35. package/dist/src/@types/config/types.d.ts +3 -1
  36. package/dist/src/@types/generic.d.ts +0 -1
  37. package/dist/src/composables/useConfig.d.ts +12 -0
  38. package/dist/src/config/compiler/utils/recommendationCompilerUtils.d.ts +1 -1
  39. package/dist/src/enums/extensions/recommendationBlock.d.ts +3 -0
  40. package/dist/src/extensions/Blocks/Recommendation/constants/index.d.ts +1 -1
  41. package/dist/src/extensions/Blocks/Recommendation/constants/selectors.d.ts +5 -0
  42. package/dist/src/extensions/Blocks/Recommendation/controls/cardComposition/index.d.ts +5 -0
  43. package/dist/src/extensions/Blocks/Recommendation/templates/grid/template.d.ts +4 -4
  44. package/dist/src/extensions/Blocks/Recommendation/templates/list/template.d.ts +3 -3
  45. package/dist/src/extensions/Blocks/Recommendation/templates/utils.d.ts +20 -3
  46. package/dist/src/stores/config.d.ts +108 -0
  47. package/dist/src/stores/preview.d.ts +3 -0
  48. package/dist/src/utils/htmlCompiler.d.ts +2 -1
  49. package/dist/static/styles/base.css.js +7 -2
  50. package/dist/stores/preview.js +4 -3
  51. package/dist/utils/htmlCompiler.js +48 -41
  52. package/dist/utils/templatePreparation.js +36 -25
  53. package/dist/utils/tooltipUtils.js +4 -5
  54. package/package.json +2 -2
@@ -9,76 +9,76 @@ import { useHttp as j } from "./useHttp.js";
9
9
  import { useToaster as q } from "./useToaster.js";
10
10
  import { useTranslations as z } from "./useTranslations.js";
11
11
  const K = /recommendation-id="(\d+)"/g;
12
- function U(i) {
13
- return [...i.matchAll(K)].map((u) => u[1]);
12
+ function U(a) {
13
+ return [...a.matchAll(K)].map((u) => u[1]);
14
14
  }
15
- function Y(i, u) {
16
- return u.some((d) => i.startsWith(`${d}_`));
15
+ function Y(a, u) {
16
+ return u.some((d) => a.startsWith(`${d}_`));
17
17
  }
18
18
  const ce = () => {
19
19
  var y, h;
20
- const { showToaster: i } = q(), { post: u } = j(), { config: d } = L(), r = z(), g = $(), p = ((h = (y = d.value) == null ? void 0 : y.partner) == null ? void 0 : h.messageType) === V.transactional, w = async (e) => {
20
+ const { showToaster: a } = q(), { post: u } = j(), { config: d } = L(), r = z(), g = $(), p = ((h = (y = d.value) == null ? void 0 : y.partner) == null ? void 0 : h.messageType) === V.transactional, b = async (e) => {
21
21
  const t = await u(
22
22
  "/newsletter/template-library/check-template-html-body",
23
23
  { html: X(e) }
24
24
  ), { status: n, message: l } = t.data;
25
- return n || i({
25
+ return n || a({
26
26
  type: c.Alert,
27
27
  message: n === void 0 ? l : r("newsletter.invalid-url-link-for-toaster")
28
- }), r(P), l === r(G) && i({
28
+ }), r(P), l === r(G) && a({
29
29
  type: c.Alert,
30
30
  message: r("newsletter.already-in-progress")
31
31
  }), n;
32
- }, b = (e) => !["if", "endif", "else", "elif", "now"].includes(e.toLowerCase()), S = (e) => ["if", "endif"].includes(e.toLowerCase()), E = (e, s) => {
32
+ }, w = (e) => !["if", "endif", "else", "elif", "now"].includes(e.toLowerCase()), S = (e) => ["if", "endif"].includes(e.toLowerCase()), E = (e, s) => {
33
33
  const t = e.match(/({%(.*?)%})/g);
34
34
  let n = !0;
35
35
  return t !== null && !p && t.forEach((l) => {
36
36
  const o = l.slice(2, -2).trim().match(/(".*?"|[^"\s]+)(?=\s*|\s*$)/g);
37
37
  if (o && o.length > 0) {
38
- const [a] = o;
39
- b(a) && !s.includes(a) && (i({
38
+ const [i] = o;
39
+ w(i) && !s.includes(i) && (a({
40
40
  type: c.Warning,
41
41
  message: r("custom-fields.invalid-custom-fields")
42
42
  }), n = !1);
43
43
  }
44
44
  }), n;
45
45
  }, A = async (e, s, t) => {
46
- const n = t ? await w(e) : !0;
46
+ const n = t ? await b(e) : !0;
47
47
  return E(e, s) && n;
48
- }, I = (e) => e.length > 0 ? !0 : (i({
48
+ }, I = (e) => e.length > 0 ? !0 : (a({
49
49
  type: c.Warning,
50
50
  message: r("newsletter.html-content-is-empty")
51
51
  }), !1), k = (e) => {
52
52
  const s = (e.match(/{/gm) || []).length, t = (e.match(/}/gm) || []).length;
53
- return s > t && i({
53
+ return s > t && a({
54
54
  type: c.Warning,
55
55
  message: r("custom-fields.missing-closing-braces")
56
- }), s < t && i({
56
+ }), s < t && a({
57
57
  type: c.Warning,
58
58
  message: r("custom-fields.missing-opening-braces")
59
59
  }), s === t;
60
60
  }, x = (e) => {
61
61
  const s = e.match(/{{\s*(\w+\s+((\w+\|\w+)|(\w+)))\s*}}/gm) === null;
62
- return s || i({
62
+ return s || a({
63
63
  type: c.Warning,
64
64
  message: r("custom-fields.invalid-custom-fields")
65
65
  }), s;
66
66
  }, T = (e, s) => {
67
67
  const t = e.match(/{{([a-zA-Z0-9_\s]*)}}/gm);
68
68
  if (t && !p) {
69
- const n = new Set(s.map((a) => a.toLowerCase())), l = U(e), o = [];
70
- if (t.forEach((a) => {
71
- const m = a.slice(2, -2).trim().toLowerCase();
69
+ const n = new Set(s.map((i) => i.toLowerCase())), l = U(e), o = [];
70
+ if (t.forEach((i) => {
71
+ const m = i.slice(2, -2).trim().toLowerCase();
72
72
  (!n.has(m) || m === "") && !Y(m, l) && o.push(m);
73
73
  }), o.length > 0) {
74
- const a = `
74
+ const i = `
75
75
  <ul>
76
76
  ${o.map((m) => `<li>${m}</li>`).join("")}
77
77
  </ul>
78
78
  `;
79
- return i({
79
+ return a({
80
80
  type: c.Alert,
81
- message: r("custom-fields.invalid-custom-fields") + a
81
+ message: r("custom-fields.invalid-custom-fields") + i
82
82
  }), !1;
83
83
  }
84
84
  }
@@ -87,12 +87,12 @@ const ce = () => {
87
87
  const s = e.match(/{%(.*?)%}/g), t = [];
88
88
  let n = !0;
89
89
  if (s && s.forEach((l) => {
90
- const o = l.match(_), a = l.match(H), m = (o == null ? void 0 : o.join("")) || "";
91
- (!o || l !== m) && !a && (i({
90
+ const o = l.match(_), i = l.match(H), m = (o == null ? void 0 : o.join("")) || "";
91
+ (!o || l !== m) && !i && (a({
92
92
  type: c.Alert,
93
93
  message: r("newsletter.display-conditions-invalid-syntax")
94
94
  }), n = !1), o && o.forEach((f) => {
95
- f.trim() === "=" && (i({
95
+ f.trim() === "=" && (a({
96
96
  type: c.Alert,
97
97
  message: r("custom-conditions.wrong-equality-operators")
98
98
  }), n = !1);
@@ -102,8 +102,8 @@ const ce = () => {
102
102
  });
103
103
  });
104
104
  }), t.length) {
105
- const l = t.filter((a) => a === "if"), o = t.filter((a) => a === "endif");
106
- l.length !== o.length && (i({
105
+ const l = t.filter((i) => i === "if"), o = t.filter((i) => i === "endif");
106
+ l.length !== o.length && (a({
107
107
  type: c.Alert,
108
108
  message: r("custom-conditions.missing-if-endif-tag")
109
109
  }), n = !1);
@@ -111,45 +111,47 @@ const ce = () => {
111
111
  return n;
112
112
  }, W = (e) => {
113
113
  const s = (e.match(/{% /gm) || []).length, t = (e.match(/ %}/gm) || []).length, n = s === t;
114
- return n || i({
114
+ return n || a({
115
115
  type: c.Warning,
116
116
  message: r("custom-conditions.no-space-after-braces")
117
117
  }), n;
118
- }, N = (e) => (e.match(/({%(.*?)%})/g) || []).filter((t) => t.includes("if")).map((t) => (t.match(/{{.*}}/gm) || []).length).reduce((t, n) => t + n, 0) > 0 ? (i({
118
+ }, N = (e) => (e.match(/({%(.*?)%})/g) || []).filter((t) => t.includes("if")).map((t) => (t.match(/{{.*}}/gm) || []).length).reduce((t, n) => t + n, 0) > 0 ? (a({
119
119
  type: c.Warning,
120
120
  message: r("custom-conditions.no-braces-inside-if-tag")
121
- }), !1) : !0, O = () => g.recommendationConfigs && Object.values(g.recommendationConfigs).find((s) => s.filters.find((t) => t.value === "")) !== void 0 ? (i({
121
+ }), !1) : !0, O = () => g.recommendationConfigs && Object.values(g.recommendationConfigs).find((s) => s.filters.find((t) => t.value === "")) !== void 0 ? (a({
122
122
  type: c.Alert,
123
123
  message: r("newsletter.fill-all-necessary-fields")
124
124
  }), !1) : !0, B = (e) => {
125
125
  const s = /src="[^"]*\.(svg|pst)"/gm;
126
- return e.match(s) === null ? !0 : (i({
126
+ return e.match(s) === null ? !0 : (a({
127
127
  type: c.Alert,
128
128
  message: r("newsletter.invalid-image-type")
129
129
  }), !1);
130
130
  }, R = (e) => {
131
131
  const n = new DOMParser().parseFromString(e, "text/html").querySelectorAll(".checkbox-block-v2");
132
132
  return Array.from(n).find((o) => {
133
- var a;
134
- return !((a = o.id) != null && a.trim());
135
- }) ? (i({
133
+ var i;
134
+ return !((i = o.id) != null && i.trim());
135
+ }) ? (a({
136
136
  type: c.Alert,
137
137
  message: r("unsubscribe-templates.select-checkbox-groups")
138
138
  }), !1) : !0;
139
139
  }, D = (e) => {
140
140
  const n = new DOMParser().parseFromString(e, "text/html").querySelectorAll(".radio-button-v2");
141
141
  return Array.from(n).find((o) => {
142
- var a;
143
- return !((a = o.id) != null && a.trim());
144
- }) ? (i({
142
+ var i;
143
+ return !((i = o.id) != null && i.trim());
144
+ }) ? (a({
145
145
  type: c.Alert,
146
146
  message: r("unsubscribe-templates.select-radio-button-groups")
147
147
  }), !1) : !0;
148
148
  };
149
149
  return { validateHtml: async (e, s, t = !1) => {
150
+ var o, i;
150
151
  const n = [
151
- ...s.map((o) => o.value),
152
- ...M
152
+ ...s.map((m) => m.value),
153
+ ...M,
154
+ ...((i = (o = d.value) == null ? void 0 : o.template) == null ? void 0 : i.customFieldAttributes) ?? []
153
155
  ];
154
156
  return await A(e, n, t) && I(e) && k(e) && x(e) && T(e, n) && F(e) && W(e) && N(e) && O() && B(e) && R(e) && D(e);
155
157
  } };
@@ -1,31 +1,35 @@
1
- import { useEditorStore as n } from "../stores/editor.js";
2
- import { usePreviewStore as l } from "../stores/preview.js";
3
- import { useActionsApi as m } from "./useActionsApi.js";
4
- import { useCodeEditorApi as p } from "./useCodeEditorApi.js";
5
- const E = () => {
6
- const o = n(), e = l(), { closeCodeEditor: a } = p(), { getPreviewData: s } = m(), r = () => {
7
- o.isPreviewModeOpen = !1, e.$reset();
1
+ import { useEditorStore as d } from "../stores/editor.js";
2
+ import { usePreviewStore as n } from "../stores/preview.js";
3
+ import { useActionsApi as p } from "./useActionsApi.js";
4
+ import { useCodeEditorApi as c } from "./useCodeEditorApi.js";
5
+ import { useHtmlCompiler as u } from "./useHtmlCompiler.js";
6
+ const g = () => {
7
+ const t = d(), e = n(), { closeCodeEditor: i } = c(), { getPreviewData: a, getCompiledEmail: s } = p(), { compileHtml: m } = u(), r = () => {
8
+ t.isPreviewModeOpen = !1, e.$reset();
8
9
  };
9
10
  return {
10
11
  closePreviewMode: r,
11
12
  openPreviewMode: () => {
12
- o.isCodeEditorOpen && a(), o.isPreviewModeOpen = !0;
13
+ t.isCodeEditorOpen && i(), t.isPreviewModeOpen = !0;
13
14
  },
14
15
  loadPreviewData: async () => {
15
- if (!(o.loadingStatus || e.isLoaded)) {
16
- o.loadingStatus = !0;
16
+ if (!(t.loadingStatus || e.isLoaded)) {
17
+ t.loadingStatus = !0;
17
18
  try {
18
- const { html: t, ampHtml: i, ampErrors: d } = await s();
19
- e.templateHtml = t || "", e.ampHtml = i || "", e.ampErrors = d || [], e.setEmailFormat(i ? "AMP" : "html"), e.isLoaded = !0;
20
- } catch (t) {
21
- console.error("Failed to load preview data:", t), r();
19
+ const [o, l] = await Promise.all([
20
+ a(),
21
+ s({ minimize: !0, resetDataSavedFlag: !1 })
22
+ ]);
23
+ e.templateHtml = o.html || "", e.ampHtml = o.ampHtml || "", e.ampErrors = o.ampErrors || [], e.setEmailFormat(o.ampHtml ? "AMP" : "html"), e.emailSizeKB = m(l.html).estimatedSizeKB, e.isLoaded = !0;
24
+ } catch (o) {
25
+ console.error("Failed to load preview data:", o), r();
22
26
  } finally {
23
- o.loadingStatus = !1;
27
+ t.loadingStatus = !1;
24
28
  }
25
29
  }
26
30
  }
27
31
  };
28
32
  };
29
33
  export {
30
- E as usePreviewMode
34
+ g as usePreviewMode
31
35
  };
@@ -1,21 +1,23 @@
1
- import { useConfig as d } from "./useConfig.js";
2
- import { useSaveStart as p, useSaveComplete as f } from "./useGuidoActions.js";
3
- import { useSyncModuleExtractor as v } from "./useSyncModuleExtractor.js";
4
- import { useStripoApi as S } from "../services/stripoApi.js";
5
- import { useTemplatePreparation as x } from "../utils/templatePreparation.js";
6
- import { useHtmlValidator as V } from "./useHtmlValidator.js";
7
- const g = () => {
8
- const o = p(), s = f(), { validateHtml: i } = V(), { callbacks: a } = d(), { extractSyncModuleData: r } = v(), { setSyncModuleUnsubscriptionPages: n } = S();
9
- return { save: async (l = !1) => {
1
+ import { useActionsApi as d } from "./useActionsApi.js";
2
+ import { useConfig as f } from "./useConfig.js";
3
+ import { useSaveStart as v, useSaveComplete as S } from "./useGuidoActions.js";
4
+ import { useSyncModuleExtractor as x } from "./useSyncModuleExtractor.js";
5
+ import { useStripoApi as V } from "../services/stripoApi.js";
6
+ import { useTemplatePreparation as y } from "../utils/templatePreparation.js";
7
+ import { useHtmlValidator as w } from "./useHtmlValidator.js";
8
+ const k = () => {
9
+ const o = v(), s = S(), { validateHtml: i } = w(), { callbacks: a } = f(), { extractSyncModuleData: r } = x(), { setSyncModuleUnsubscriptionPages: n } = V(), { editorSave: l } = d();
10
+ return { save: async (c = !1) => {
10
11
  var e;
11
12
  o();
12
- const { prepareTemplateDetails: c } = x(), t = await c();
13
+ const { prepareTemplateDetails: m } = y(), t = await m();
13
14
  if (!await i(t.compiledHtml, t.dynamicContentList, !0) || (e = a.value) != null && e.externalValidation && !await a.value.externalValidation(t))
14
15
  return;
15
- const { unsubscribePayload: m, stripoModules: u } = r(t.rawHtml);
16
- return await n(m), t.modules = u, l || s(t), t;
16
+ l();
17
+ const { unsubscribePayload: u, stripoModules: p } = r(t.rawHtml);
18
+ return await n(u), t.modules = p, c || s(t), t;
17
19
  } };
18
20
  };
19
21
  export {
20
- g as useSave
22
+ k as useSave
21
23
  };
@@ -1,18 +1,18 @@
1
- import { useRecommendation as f } from "../../composables/useRecommendation.js";
2
- import { DUMMY_IMAGE_MAPPINGS as P, REGEX as m, VerticalOrientation as g, CSS as e, ATTRIBUTES as a, CONDITIONS as A, HTML as h } from "../../enums/recommendation.js";
3
- import { prepareRecommendationBlocks as D } from "./utils/recommendationCompilerUtils.js";
4
- const G = [
1
+ import { useRecommendation as N } from "../../composables/useRecommendation.js";
2
+ import { DUMMY_IMAGE_MAPPINGS as C, REGEX as T, VerticalOrientation as M, CSS as E, ATTRIBUTES as R, CONDITIONS as $, HTML as h } from "../../enums/recommendation.js";
3
+ import { prepareRecommendationBlocks as x } from "./utils/recommendationCompilerUtils.js";
4
+ const w = [
5
5
  {
6
6
  id: "replace-images-with-variable-names",
7
7
  description: "Replacing dummy images with variable names in recommendation module",
8
8
  type: "custom",
9
- processor: (s) => {
10
- let t = s;
11
- return Object.entries(P).forEach(([, l]) => {
12
- Object.entries(l).forEach(([n, o]) => {
13
- t = t.replaceAll(o, `{{${n}}}`);
9
+ processor: (i) => {
10
+ let e = i;
11
+ return Object.entries(C).forEach(([, p]) => {
12
+ Object.entries(p).forEach(([c, n]) => {
13
+ e = e.replaceAll(n, `{{${c}}}`);
14
14
  });
15
- }), t;
15
+ }), e;
16
16
  },
17
17
  priority: 50
18
18
  },
@@ -29,21 +29,21 @@ const G = [
29
29
  id: "add-recommendation-unresponsive-css",
30
30
  description: "Adding recommendation unresponsive css",
31
31
  type: "custom",
32
- processor: (s) => {
33
- const { calculateCardWidth: t, getRecommendationCampaignData: l } = f();
34
- let n = s;
35
- const o = n.match(m.ID);
36
- if (o) {
37
- const d = [];
38
- if (o.forEach((c) => {
39
- const E = /recommendation-id="(.*?)"/i.exec(c), I = E ? E[1].trim() : "", p = l(I);
40
- p.textTrimming && p.orientation === g && d.push(t(p));
41
- }), d.length) {
42
- const c = `width:${Math.min(...d)}px!important;`;
43
- n = n.replace(e.REGULAR_NAME_HEIGHT, `${e.TRIMMED_NAME_HEIGHT} ${c} ${e.ELLIPSIS}`).replace(e.REGULAR_NAME_CONTAINER_HEIGHT, e.TRIMMED_NAME_CONTAINER_CSS).replace(e.RESPONSIVE_NAME_SIZE, `${e.RESPONSIVE_NAME_HEIGHT} ${c} ${e.ELLIPSIS}`).replace(e.RESPONSIVE_NAME_CONTAINER_HEIGHT, e.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
32
+ processor: (i) => {
33
+ const { calculateCardWidth: e, getRecommendationCampaignData: p } = N();
34
+ let c = i;
35
+ const n = c.match(T.ID);
36
+ if (n) {
37
+ const a = [];
38
+ if (n.forEach((s) => {
39
+ const d = /recommendation-id="(.*?)"/i.exec(s), _ = d ? d[1].trim() : "", A = p(_);
40
+ A.textTrimming && A.orientation === M && a.push(e(A));
41
+ }), a.length) {
42
+ const s = `width:${Math.min(...a)}px!important;`;
43
+ c = c.replace(E.REGULAR_NAME_HEIGHT, `${E.TRIMMED_NAME_HEIGHT} ${s} ${E.ELLIPSIS}`).replace(E.REGULAR_NAME_CONTAINER_HEIGHT, E.TRIMMED_NAME_CONTAINER_CSS).replace(E.RESPONSIVE_NAME_SIZE, `${E.RESPONSIVE_NAME_HEIGHT} ${s} ${E.ELLIPSIS}`).replace(E.RESPONSIVE_NAME_CONTAINER_HEIGHT, E.TRIMMED_RESPONSIVE_NAME_CONTAINER_CSS);
44
44
  }
45
45
  }
46
- return n;
46
+ return c;
47
47
  },
48
48
  priority: 52
49
49
  },
@@ -51,39 +51,153 @@ const G = [
51
51
  id: "prepare-recommendations",
52
52
  description: "Replacing product data with template variables in recommendation blocks",
53
53
  type: "custom",
54
- processor: (s) => D(s),
54
+ processor: (i) => x(i),
55
55
  priority: 48
56
56
  },
57
57
  {
58
58
  id: "add-discount-conditions",
59
59
  description: "Adding discount conditions to the recommendation block",
60
60
  type: "custom",
61
- processor: (s) => {
62
- let t = s;
63
- const l = t.match(m.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: n } = f();
64
- return l !== null && l.forEach((o) => {
65
- const d = o.match(m.CUSTOM_FIELD);
66
- if (!d)
61
+ processor: (i) => {
62
+ let e = i;
63
+ const p = e.match(T.ATTRIBUTE_PARAGRAPH), { getRecommendationCampaignData: c } = N();
64
+ return p !== null && p.forEach((n) => {
65
+ const a = n.match(T.CUSTOM_FIELD);
66
+ if (!a)
67
67
  return;
68
- const [c] = d, E = c.match(m.CUSTOM_FIELD_INDEXES_PART), I = c.match(m.CUSTOM_FIELD_NAME_PART), p = o.match(m.ATTRIBUTE_PARAGRAPH_START_TAG);
69
- if (!E || !I || !p)
68
+ const [s] = a, d = s.match(T.CUSTOM_FIELD_INDEXES_PART), _ = s.match(T.CUSTOM_FIELD_NAME_PART), A = n.match(T.ATTRIBUTE_PARAGRAPH_START_TAG);
69
+ if (!d || !_ || !A)
70
70
  return;
71
- const [u] = E, [R] = I, [_] = p, T = R.substring(1, R.length - 2), S = _.match(m.COMPOSITION) !== null;
72
- let i = c;
73
- if (S) {
74
- const $ = u.substring(2, u.length - 3), r = n($);
75
- T === a.OMNIBUS_PRICE && (r.priceBeforeTextValue && (i = `${r.priceBeforeTextValue}${i}`), r.priceAfterTextValue && (i = `${i}${r.priceAfterTextValue}`)), T === a.OMNIBUS_DISCOUNT && (r.discountBeforeTextValue && (i = `${r.discountBeforeTextValue}${i}`), r.discountAfterTextValue && (i = `${i}${r.discountAfterTextValue}`));
71
+ const [I] = d, [S] = _, [m] = A, o = S.substring(1, S.length - 2), r = m.match(T.COMPOSITION) !== null;
72
+ let t = s;
73
+ if (r) {
74
+ const b = I.substring(2, I.length - 3), l = c(b);
75
+ o === R.OMNIBUS_PRICE && (l.priceBeforeTextValue && (t = `${l.priceBeforeTextValue}${t}`), l.priceAfterTextValue && (t = `${t}${l.priceAfterTextValue}`)), o === R.OMNIBUS_DISCOUNT && (l.discountBeforeTextValue && (t = `${l.discountBeforeTextValue}${t}`), l.discountAfterTextValue && (t = `${t}${l.discountAfterTextValue}`));
76
76
  }
77
- const N = u.substring(2);
78
- let M = "";
79
- T in A.IF && (M = A.IF[T].replaceAll(`{${a.DISCOUNT}}`, `${N}${a.DISCOUNT}`).replaceAll(`{${a.OMNIBUS_DISCOUNT}}`, `${N}${a.OMNIBUS_DISCOUNT}`).replaceAll(`{${a.OMNIBUS_PRICE}}`, `${N}${a.OMNIBUS_PRICE}`));
80
- const O = `${_}${i}${h.PARAGRAPH_END_TAG}`, C = `${M}${S ? O : o}${A.ELSE}${_}${h.PARAGRAPH_END_TAG}${A.END_IF}`;
81
- t = t.replace(o, C);
82
- }), t;
77
+ const u = I.substring(2);
78
+ let f = "";
79
+ o in $.IF && (f = $.IF[o].replaceAll(`{${R.DISCOUNT}}`, `${u}${R.DISCOUNT}`).replaceAll(`{${R.OMNIBUS_DISCOUNT}}`, `${u}${R.OMNIBUS_DISCOUNT}`).replaceAll(`{${R.OMNIBUS_PRICE}}`, `${u}${R.OMNIBUS_PRICE}`));
80
+ const g = `${m}${t}${h.PARAGRAPH_END_TAG}`, y = `${f}${r ? g : n}${$.ELSE}${m}${h.PARAGRAPH_END_TAG}${$.END_IF}`;
81
+ e = e.replace(n, y);
82
+ }), e;
83
83
  },
84
84
  priority: 53
85
+ },
86
+ {
87
+ id: "strip-empty-omnibus-spans",
88
+ description: "Remove empty omnibus text-before and text-after span elements",
89
+ type: "regex",
90
+ pattern: '<span class="omnibus-text-(?:before|after)">\\s*</span>',
91
+ replacement: "",
92
+ flags: "g",
93
+ priority: 54
94
+ },
95
+ {
96
+ id: "strip-recommendation-editor-attributes",
97
+ description: "Strip editor-only attributes from compiled recommendation output",
98
+ type: "regex",
99
+ // eslint-disable-next-line @stylistic/max-len
100
+ pattern: '\\s+(?:esd-extension-block-id|data-attribute-type|data-visibility|data-text-before|data-text-after|product-attr|composition)="[^"]*"',
101
+ replacement: "",
102
+ flags: "g",
103
+ priority: 55
104
+ },
105
+ {
106
+ id: "strip-unused-recommendation-classes",
107
+ description: "Remove CSS classes not referenced by any style rule from recommendation elements",
108
+ type: "custom",
109
+ processor: (i) => {
110
+ let e = i.replace(
111
+ / class="(?:product-card-segment|attribute-cell|recommendation-attribute-row|product-image|product-name|product-price|product-old-price|product-omnibus-price|product-omnibus-discount|product-button|recommendation-product-row|product-card-wrapper)"/g,
112
+ ""
113
+ );
114
+ return e = e.replaceAll("es-button buy-button", "es-button"), e = e.replaceAll("ins-recommendation-product-container ", ""), e;
115
+ },
116
+ priority: 56
117
+ },
118
+ {
119
+ id: "remove-empty-mobile-layout-artifacts",
120
+ description: "Remove empty mobile container rows and unused mobile layout CSS",
121
+ type: "custom",
122
+ processor: (i) => {
123
+ let e = i;
124
+ return e = e.replace(
125
+ /<tr[^>]*class="ins-recommendation-mobile-row"[^>]*><\/tr>/g,
126
+ ""
127
+ ), /class="[^"]*ins-recommendation-mobile-container/.test(e) || (e = e.replace(
128
+ /\.ins-recommendation-mobile-container\s*\{\s*display\s*:\s*none\s*;?\s*\}/g,
129
+ ""
130
+ ), e = e.replace(
131
+ /@media[^{]*max-width\s*:\s*480px[^{]*\{((?:[^{}]*\{[^{}]*\})*[^{}]*)\}/g,
132
+ (p, c) => {
133
+ const n = c.match(/[^{}]+\{[^{}]*\}/g) || [], a = /ins-recommendation|product-image-cell|button-cell|product-info-cell/;
134
+ return n.every((d) => a.test(d)) ? "" : p;
135
+ }
136
+ )), e;
137
+ },
138
+ priority: 57
139
+ },
140
+ {
141
+ id: "deduplicate-inline-styles",
142
+ description: "Replace repeated inline styles with CSS class references within recommendation blocks",
143
+ type: "custom",
144
+ processor: (i) => {
145
+ const e = i.replace(
146
+ /<a\b[^>]*\bes-button\b[^>]*>/g,
147
+ (o) => o.replace(
148
+ /([;"]color:)([^;"]+)/g,
149
+ (r, t, u) => u.includes("!important") ? r : `${t}${u} !important`
150
+ )
151
+ ), p = /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g, c = / style="([^"]*)"/g, n = /* @__PURE__ */ new Map();
152
+ let a = p.exec(e);
153
+ for (; a !== null; ) {
154
+ let o = c.exec(a[1]);
155
+ for (; o !== null; ) {
156
+ const [, r] = o;
157
+ n.set(r, (n.get(r) || 0) + 1), o = c.exec(a[1]);
158
+ }
159
+ c.lastIndex = 0, a = p.exec(e);
160
+ }
161
+ const s = /* @__PURE__ */ new Map(), d = [];
162
+ let _ = 0;
163
+ if (n.forEach((o, r) => {
164
+ if (o >= 6) {
165
+ const t = `rc${_++}`;
166
+ s.set(r, t), d.push(`.${t}{${r}}`);
167
+ }
168
+ }), s.size === 0) {
169
+ let o = e;
170
+ return o = o.replaceAll("<!--REC_START-->", ""), o = o.replaceAll("<!--REC_END-->", ""), o;
171
+ }
172
+ const A = (o) => o.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), I = (o, r) => `${o.slice(0, -1)} ${r}"`, S = /* @__PURE__ */ new Map();
173
+ s.forEach((o, r) => {
174
+ const t = A(r);
175
+ S.set(r, {
176
+ caseA: new RegExp(`(class="[^"]*")((?:[^>]*?)) style="${t}"`, "g"),
177
+ caseB: new RegExp(` style="${t}"((?:[^>]*?))(class="[^"]*")`, "g")
178
+ });
179
+ });
180
+ let m = e.replace("</style>", `${d.join("")}</style>`);
181
+ return m = m.replace(
182
+ /<!--REC_START-->([\s\S]*?)<!--REC_END-->/g,
183
+ (o, r) => {
184
+ let t = r;
185
+ return s.forEach((u, f) => {
186
+ const g = S.get(f);
187
+ t = t.replace(
188
+ g.caseA,
189
+ (y, b, l) => I(b, u) + l
190
+ ), t = t.replace(
191
+ g.caseB,
192
+ (y, b, l) => b + I(l, u)
193
+ ), t = t.replaceAll(` style="${f}"`, ` class="${u}"`);
194
+ }), t;
195
+ }
196
+ ), m = m.replaceAll("<!--REC_START-->", ""), m = m.replaceAll("<!--REC_END-->", ""), m;
197
+ },
198
+ priority: 58
85
199
  }
86
200
  ];
87
201
  export {
88
- G as recommendationCompilerRules
202
+ w as recommendationCompilerRules
89
203
  };
@@ -1,41 +1,41 @@
1
- import { usePartner as N } from "../../composables/usePartner.js";
2
- import { LINK_REGEXES as l, LINK_TYPES as S, INSIDER_ID as R, URLS as _ } from "../../enums/unsubscribe.js";
3
- import { parsePageList as U } from "../../extensions/Blocks/Unsubscribe/utils/utils.js";
4
- import { useConfigStore as B } from "../../stores/config.js";
5
- import { useDynamicContentStore as y } from "../../stores/dynamic-content.js";
6
- import { useUnsubscribeStore as L } from "../../stores/unsubscribe.js";
7
- const D = [
1
+ import { usePartner as y } from "../../composables/usePartner.js";
2
+ import { LINK_REGEXES as p, LINK_TYPES as S, INSIDER_ID as m, URLS as R } from "../../enums/unsubscribe.js";
3
+ import { parsePageList as I } from "../../extensions/Blocks/Unsubscribe/utils/utils.js";
4
+ import { useConfigStore as N } from "../../stores/config.js";
5
+ import { useDynamicContentStore as U } from "../../stores/dynamic-content.js";
6
+ import { useUnsubscribeStore as C } from "../../stores/unsubscribe.js";
7
+ const G = [
8
8
  {
9
9
  id: "add-unsubscribe-link-values",
10
10
  description: "Adding unsubscribe link values",
11
11
  type: "custom",
12
12
  processor: (t) => {
13
- const { getPartnerName: i } = N(), c = B(), n = y(), u = L(), a = c.variationId;
13
+ const { getPartnerName: i } = y(), o = N(), s = U(), d = C(), a = o.variationId;
14
14
  if (!a)
15
15
  return t;
16
16
  let e = t;
17
- const r = `/${i()}/email/${a}?user={{iid}}`;
18
- return new DOMParser().parseFromString(e, "text/html").querySelectorAll(".unsubscribe-block-v2[data-unsubscribe-page-list]").forEach((p) => {
19
- var g;
20
- const m = p.getAttribute("data-unsubscribe-page-list");
21
- if (!m)
17
+ const r = `/${i()}/email/${a}?user={{iid}}`, E = new DOMParser().parseFromString(e, "text/html").querySelectorAll(".unsubscribe-block-v2[data-unsubscribe-page-list]");
18
+ let c = !1, l = !1;
19
+ return E.forEach((f) => {
20
+ var b;
21
+ const u = f.getAttribute("data-unsubscribe-page-list");
22
+ if (!u)
22
23
  return;
23
- const I = U(m), d = ((g = u.templates) == null ? void 0 : g.filter(
24
- (o) => I.includes(o.id)
25
- )) ?? [], E = d.some((o) => o.type === S.UNSUBSCRIBE_LINK_TYPE), b = d.some((o) => o.type === S.PREFERENCES_LINK_TYPE), f = p.outerHTML;
26
- let s = f;
27
- (E || b) && n.selectedDynamicContentList.push({
28
- text: R,
29
- value: R,
30
- fallback: ""
31
- }), E && (s = s.replace(
32
- l.GLOBAL_UNSUBSCRIBE_LINK_REGEX,
33
- _.UNSUBSCRIBE_URL + r
34
- )), b && (s = s.replace(
35
- l.PREFERENCES_UNSUBSCRIBE_LINK_REGEX,
36
- _.PREFERENCES_URL + r
37
- )), s = s.replace(l.UNSUBSCRIBE_LINK_REGEX, ""), e = e.replace(f, s);
38
- }), e;
24
+ const _ = I(u), g = ((b = d.templates) == null ? void 0 : b.filter(
25
+ (n) => _.includes(n.id)
26
+ )) ?? [];
27
+ c = c || g.some((n) => n.type === S.UNSUBSCRIBE_LINK_TYPE), l = l || g.some((n) => n.type === S.PREFERENCES_LINK_TYPE);
28
+ }), (c || l) && (s.selectedDynamicContentList.some((u) => u.value === m) || s.selectedDynamicContentList.push({
29
+ text: m,
30
+ value: m,
31
+ fallback: ""
32
+ })), c && (e = e.replace(
33
+ p.GLOBAL_UNSUBSCRIBE_LINK_REGEX,
34
+ R.UNSUBSCRIBE_URL + r
35
+ )), l && (e = e.replace(
36
+ p.PREFERENCES_UNSUBSCRIBE_LINK_REGEX,
37
+ R.PREFERENCES_URL + r
38
+ )), E.length && (e = e.replace(p.UNSUBSCRIBE_LINK_REGEX, "")), e;
39
39
  },
40
40
  priority: 60
41
41
  },
@@ -43,7 +43,7 @@ const D = [
43
43
  id: "remove-data-ogsb-button-styles",
44
44
  description: "Removing styles like [data-ogsb] .es-button.es-button-123 { background: red; }",
45
45
  type: "regex",
46
- pattern: l.DATA_OGSB_BUTTON_CSS_REGEX,
46
+ pattern: p.DATA_OGSB_BUTTON_CSS_REGEX,
47
47
  replacement: "",
48
48
  flags: "g",
49
49
  priority: 61
@@ -61,16 +61,16 @@ const D = [
61
61
  type: "custom",
62
62
  processor: (t) => {
63
63
  let i = t;
64
- const c = i.match(/<a[^>]+>(.*?)<\/a>/gm);
65
- return c && c.forEach((n) => {
66
- if (n.includes("insEmail=1"))
64
+ const o = i.match(/<a[^>]+>(.*?)<\/a>/gm);
65
+ return o && o.forEach((s) => {
66
+ if (s.includes("insEmail=1"))
67
67
  return;
68
- if (n.match(/<a\s+(?:[^>]*?\s+)?href=(["'`”])(.*?)\1\s+(?:[^>]*?\s+)?universal=(["'`”])true\3/gm)) {
69
- const a = n.replace(/href=(["'`”])(.*?)\1/gm, (e) => {
68
+ if (s.match(/<a\s+(?:[^>]*?\s+)?href=(["'`”])(.*?)\1\s+(?:[^>]*?\s+)?universal=(["'`”])true\3/gm)) {
69
+ const a = s.replace(/href=(["'`”])(.*?)\1/gm, (e) => {
70
70
  const r = e.slice(6, e.length - 1).trim();
71
71
  return e.includes("?") || e.includes("#") ? r.slice(-1) === "&" ? e.replace(r, `${r}insEmail=1`) : e.replace(r, `${r}&insEmail=1`) : e.replace(r, `${r}?insEmail=1`);
72
72
  });
73
- i = i.replace(n, a);
73
+ i = i.replace(s, a);
74
74
  }
75
75
  }), i;
76
76
  },
@@ -78,5 +78,5 @@ const D = [
78
78
  }
79
79
  ];
80
80
  export {
81
- D as unsubscribeCompilerRules
81
+ G as unsubscribeCompilerRules
82
82
  };